refactor: new structure

This commit is contained in:
Oleg Proskurin 2026-04-21 19:49:08 +07:00
parent 99bc387244
commit ba676c2924
45 changed files with 12097 additions and 807 deletions

6
.gitignore vendored
View File

@ -2,3 +2,9 @@ node_modules/
output/
.env
!.claude/settings.local.json
# Generated output HTML (template + data → output)
tasks/*/docs/*.output.html
# Editor temp files (diffs, transient data)
tasks/*/temp/

344
CLAUDE.md
View File

@ -1,15 +1,13 @@
# Math Tasks Generator
Printable math worksheet generator (A4 PDF) for children aged 79. Claude Code-driven workflow: user describes a task idea → Claude generates JSON config → creates HTML pages with Tailwind CSS → converts to PDF via Puppeteer.
**No template engine.** Claude Code generates fresh HTML pages directly from JSON task configs each time.
Printable math worksheet generator (A4 PDF) for children aged 79. Claude Code is the central orchestrator: user describes a task idea → Claude creates/edits HTML templates → optional visual editor fine-tuning → PDF via Puppeteer.
## Commands
```bash
pnpm build:css # Build Tailwind CSS (minified)
pnpm build:css:watch # Watch mode for CSS
pnpm preview # Serve HTML at localhost:3000 with live-reload
pnpm preview # Serve at localhost:3300 with live-reload
pnpm dev # CSS watch + preview server (concurrent)
pnpm pdf -- <file> # Convert HTML file to PDF
pnpm remove-bg -- <file|dir> # Remove white background from PNG icons
@ -20,230 +18,202 @@ Generate images via `/gen-image` skill (uses Banatie API, reads `BANATIE_KEY` fr
## Directory Structure
```
tasks/
index.html — document index (Claude updates manually)
{task-type}/ — one folder per task type
CLAUDE.md — type-specific rules and conventions
editor.html — visual editor for this task type
scripts/ — type-specific scripts (validation, generation)
docs/ — document instances
{docId}.md — task description, problem patterns, notes (Claude reads/writes)
{docId}.template.html — near-final HTML maintained by Claude
{docId}.data.json — editor data layer (positions, values — may not exist)
{docId}.output.html — generated from template+data (gitignored)
temp/ — diffs and transient data (gitignored)
src/
styles/main.css — Tailwind source with A4/print styles
templates/space-base.html — Base template (layout/styling reference)
examples/space-worksheet2.html — Finished 3-page example (output reference)
editor/editor-core.js — shared editor framework
scripts/
generate-pdf.mjs — HTML → PDF via Puppeteer
remove-bg.mjs — Remove white background from PNGs (flood fill)
tasks/ — JSON task definition files
assets/
hero-images/ — spaceship1-6.jpeg (header hero images)
footers/ — planet1-6.jpeg (footer panorama images)
icons/pack1/ — minerals1-6 + plants1-6, 16 variants each ({name}-{row}-{col}.png)
backgrounds/ — large background images per theme (~1200x1700px)
output/
html/ — generated HTML (gitignored)
pdf/ — generated PDFs (gitignored)
css/ — built Tailwind CSS (gitignored)
generate-pdf.mjs — HTML → PDF via Puppeteer (all types)
remove-bg.mjs — Remove white background from PNGs
split-sprites.mjs — Split sprite sheets into icons
generate-problems.mjs — Problem generation utility
styles/main.css — Tailwind source with A4/print styles
templates/space-base.html — Shared base template reference
assets/ — images (hero, footer, icons, items, backgrounds)
output/pdf/ — generated PDFs (gitignored)
```
## JSON Task Format
## Task Types
Each task is a JSON file in `tasks/` defining a multi-page document. See `tasks/space-exploration-1.json` for a real example.
Each task type lives in `tasks/{type-name}/` with its own CLAUDE.md, scripts, editor, and document instances. Current types:
```json
{
"id": "space-exploration-1",
"title": "Исследуй Планету",
"description": "3-page space worksheet: addition ±, multiply by 5 ±, multiplication table ±",
"labels": {
"title": "Исследуй Планету",
"subtitle": "Собери ресурсы, решая примеры!",
"footerBubble": "Итого собрано на планете:"
},
"theme": {
"style": "space",
"template": "space-base",
"icons": "assets/icons/pack1/"
},
"layout": {
"columns": 2,
"problemsPerPage": 20
},
"pages": [
{
"task": "A + B ± C, где A от 8 до 16, B от 4 до 8, C от 1 до 3. Знак ± выбирается случайно",
"problemCount": 20,
"heroImage": "assets/hero-images/spaceship2.jpeg",
"footerImage": "assets/footers/planet3.jpeg",
"heroDirection": "row-reverse"
}
]
}
- **space-exploration** — math problem worksheets with hero images and icon-decorated cards
- **collecting-asteroids** — match asteroids to cargo ships by weight sum
- **space-route** — navigate hex graph routes with difficulty constraints
**Type-specific rules** (layout details, asset conventions, generation algorithms) live in each type's own CLAUDE.md — NOT in this file. Read `tasks/{type}/CLAUDE.md` before working on any task of that type.
## Document File Set
Each document instance consists of up to 4 files in `tasks/{type}/docs/`:
| File | Purpose | Owner |
|------|---------|-------|
| `{docId}.md` | Task description, problem patterns, page notes | Claude writes, user reviews |
| `{docId}.template.html` | Near-final static HTML, maintained by Claude | Claude |
| `{docId}.data.json` | Editor data layer (positions, values) | Editor UI via save endpoint |
| `{docId}.output.html` | Final HTML = template + data applied | generate.mjs (gitignored) |
**Key:** `.data.json` may not exist — and that's fine. When it doesn't exist, `.template.html` IS the final output.
**The `.md` file does NOT directly drive HTML generation.** It's context for Claude — problem patterns, non-obvious details (e.g., hero orientation per page), things Claude needs to know when editing the template. It does NOT contain titles, footers, or asset paths that are already in the HTML.
## Creating New Task Types
1. Create folder `tasks/{type-name}/`
2. Create `CLAUDE.md` with type-specific rules
3. Create `scripts/generate.mjs` — template + data → output pipeline
4. Create `editor.html` importing `src/editor/editor-core.js` + type-specific logic
5. Create `scripts/` for any validation/generation utilities
6. Add section to `tasks/index.html`
## Creating New Documents
When the user asks to create a new document of an existing type:
1. Copy the previous document's files with incremented number:
- `{type}-N.template.html``{type}-(N+1).template.html`
- `{type}-N.md``{type}-(N+1).md`
2. Update the `.md` file with new problem patterns / page descriptions
3. Edit `.template.html` as needed (new problems, different assets, etc.)
4. Add card to `tasks/index.html`
**No script for this — Claude does it manually.** `.data.json` starts empty (created only when the editor is used).
## Adding Pages to Existing Documents
1. Read the `.md` file to understand existing patterns
2. Edit `.template.html` directly — add new page markup
3. Update `.md` if new patterns were added
## Generation Pipeline
```
.template.html + .data.json (if exists) → scripts/generate.mjs → .output.html
```
### Fields
- Same pipeline for both Claude-initiated regeneration and editor-save flow
- If no `.data.json` exists → template.html copied as-is to output.html
- `generate.mjs` is a per-task-type script, not a global one
- **pages[]** — array of pages, each with its own task and images
- **pages[].task** — free-text description of problems to generate (Claude reads this and creates concrete expressions)
- **pages[].problemCount** — how many problems on this page
- **pages[].heroImage** — path to hero image for this page
- **pages[].footerImage** — path to footer panorama for this page
- **pages[].heroDirection**`row` (hero left) or `row-reverse` (hero right)
- **layout.columns** — 1 or 2 column layout
- **layout.problemsPerPage** — max problems per A4 page
- **labels** — all visible text (no hardcoded language)
- **theme.style** — visual theme name (e.g. "space")
- **theme.template** — which base template to use (e.g. "space-base")
- **theme.icons** — path to icon directory for problem cards
## Editor System
## Space Base Template
Each task type has its own `editor.html` in its folder. All editors share `src/editor/editor-core.js` for common functionality (drag, selection, keyboard, toolbar, save, toast).
Base template: `src/templates/space-base.html`
Finished example: `src/examples/space-worksheet2.html` (3-page output matching `tasks/space-worksheet2.json`)
**Opening in editor:**
```
http://localhost:3300/tasks/{type}/editor.html?file={docId}
```
The base template defines the visual design for all space-themed worksheets. The example shows a complete generated document. When generating a new worksheet, **read both files first**, then produce a new HTML with these variations:
**Save flow:**
1. User clicks Save in editor
2. Editor POST `/api/save-edits` with `{ taskType, docId, data }`
3. Server writes `docs/{docId}.data.json`
4. Server computes diff → writes `temp/{docId}.diff.json`
5. Server runs `generate.mjs` to regenerate output.html
### What to vary per worksheet
**Claude reviewing editor changes:**
```bash
cat tasks/{type}/temp/{docId}.diff.json
```
1. **Hero image** — pick one from `assets/hero-images/spaceship{1-6}.jpeg`
2. **Footer image** — pick one from `assets/footers/planet{1-6}.jpeg`
3. **Hero position** — use `flex-row-reverse` class (hero right) or default flex direction (hero left) on the header div
4. **Problem icons** — pick from `assets/icons/pack1/` (minerals and plants, any variant `{name}-{row}-{col}.png`). **Every icon must be unique across the entire document** (no repeats across pages). Shuffle minerals and plants together randomly — do not sort by type
5. **Problem alignment** — for each problem card, randomly assign `justify-start`, `justify-center`, or `justify-end` within its grid column. No repeating patterns — should look chaotic/scattered
6. **Title, subtitle, footer text** — set from the task description
7. **Problems** — generate directly from the `task` text in JSON config. Claude reads the free-text description and creates concrete math expressions
## Index Page
### Layout structure (do not change)
`tasks/index.html` — Claude updates manually when creating new documents. Each document has View and Edit links. Different task types can have different card styles.
- Page: `w-[210mm] h-[297mm]` white container
- Footer: absolute bottom, `h-[80mm]`, with white-to-transparent fade on top. **No `overflow-hidden`** on footer container (causes 1px hairline artifact in PDF)
- Footer bubble: absolute `bottom-[12mm]`, pill-shaped with semi-transparent white bg
- Content area: `px-[12mm] pt-[4mm] pb-[65mm]` flex column
- Header: hero image `w-[48%]` + title block centered, use `flex-row-reverse` for hero-right
- Footer gradient: `linear-gradient(to bottom, white 0%, rgba(255,255,255,0.6) 25%, transparent 50%)` with `h-full`
- Problems: `grid grid-cols-2 gap-x-3 gap-y-[3px]` — 20 problems total
- Each problem: 58px icon outside pill + `text-[1.2rem]` expression + `w-16` answer underline inside pill
- Font: Nunito via Google Fonts
- Uses Tailwind CDN (`<script src="https://cdn.tailwindcss.com">`)
**Preview:** `http://localhost:3300/tasks/index.html`
### Color palette (do not change)
## Script Principles (Orchestrator Pattern)
| Element | Hex |
|---------|-----|
| Title text | `text-indigo-950` (#1e1b4b) |
| Subtitle | `text-indigo-400` (#6366f1) |
| Card border | `border-indigo-100` (#e0e7ff) |
| Answer underline | `border-indigo-300` (#a5b4fc) |
| Card bg gradient | `from-white to-indigo-50/40` |
| Footer bubble border | `border-indigo-200` |
Claude Code is the central orchestrator. Scripts are tools for Claude, not autonomous actors.
**Rules:**
- Scripts read input → compute → output to stdout (JSON) or write a single specific output file
- Scripts NEVER chain together
- Scripts NEVER auto-modify documents or make decisions
- Claude runs a script, reads its output, decides what to do next
**Allowed write exceptions:**
- `generate.mjs` — writes `.output.html` (template+data→output, deterministic)
- `generate-pdf.mjs` — writes PDF (final artifact)
- `/api/save-edits` — writes `.data.json` + `.diff.json` + runs `generate.mjs` (user-initiated from editor UI)
**Example of correct flow:**
```
Claude: node tasks/collecting-asteroids/scripts/verify.mjs --ships 10,10,14 --asteroids 3,2,1,4,5
Script → stdout: { "valid": false, "errors": ["ship 2 overflow by 3"] }
Claude: *reads output, decides how to fix, edits template*
```
## Proactive Rule Saving
During sessions, when the user gives feedback or instructions specific to a task type, **proactively suggest saving it as a rule**:
> "Сохранить это как правило для {type}?"
If confirmed → write to `tasks/{type}/CLAUDE.md`.
General rules that apply to all types → root CLAUDE.md (this file).
## HTML Generation Guidelines
When generating HTML worksheets:
- **OUTPUT MUST BE STATIC HTML.** Generated HTML files in `output/html/` must contain only static markup — no embedded `<script>` that computes, generates, or modifies content at runtime. If you need algorithms or calculations (graph generation, random placement, etc.), run them in a separate Node.js script in `src/scripts/`, then write the computed results as static HTML to `output/html/`. The user works with the final HTML directly and expects it to be stable across page reloads.
- **Always read** `src/templates/space-base.html` (structure) and `src/examples/space-worksheet.html` (finished output) before generating
- **OUTPUT MUST BE STATIC HTML.** Template files must contain only static markup — no embedded `<script>` that computes, generates, or modifies content at runtime. Tailwind CDN `<script>` tag is the only exception.
- **Page size:** A4 = 210mm × 297mm
- **CSS:** Uses Tailwind CDN in the HTML `<script>` tag (not the compiled CSS file) — this is the only allowed script
- **Page breaks:** Use `break-after: page` between pages
- **Icons:** 58×58px inline images from `assets/icons/` next to each problem (outside the pill card)
- **Page breaks:** `break-after: page` between pages
- **Fonts:** Nunito from Google Fonts via `<link>`
- **Images in PDF:** Use local file paths (not URLs). Puppeteer resolves `file://` protocol
- **Embed images** as base64 data URIs when possible for reliable PDF rendering
- **Images in PDF:** Use local file paths. Puppeteer resolves `file://` protocol. Embed as base64 data URIs when possible for reliable rendering.
## Image Generation
Use the `/gen-image` skill to generate images via the Banatie API. The skill has its own script and full API documentation in `.claude/skills/gen-image/`. Auth via `BANATIE_KEY` in `.env`. Rate limit: 100 requests/hour.
Use the `/gen-image` skill to generate images via the Banatie API. Auth via `BANATIE_KEY` in `.env`. Rate limit: 100 requests/hour.
### Reference Policy for This Project
### Reference Policy
When generating new assets for `assets/items/`, use existing images from the same subfolder as `--ref` to maintain visual consistency across the set. For example, when creating `asteroid2.png`, reference `asteroid1.png` from the same folder. The gen-image skill's default policy is to ask before using refs — this project overrides that: use refs automatically for items in the same asset group.
When generating new assets for `assets/items/`, use existing images from the same subfolder as `--ref` to maintain visual consistency. The gen-image skill's default policy is to ask before using refs — this project overrides that: use refs automatically for items in the same asset group.
Style reference chain for themed assets:
- `assets/items/asteroids/` — use any existing asteroid as ref for new ones
- `assets/items/crystals/` — use any existing crystal as ref for new ones
- `assets/icons/` — generate independently (icons have their own pipeline via icon packs)
- `assets/hero-images/`, `assets/footers/`, `assets/backgrounds/` — generate independently, no refs needed
Style reference chain:
- `assets/items/asteroids/` — use any existing asteroid as ref
- `assets/items/crystals/` — use any existing crystal as ref
- `assets/icons/` — generate independently (icon packs have their own pipeline)
- `assets/hero-images/`, `assets/footers/`, `assets/backgrounds/` — generate independently
## Background Removal
Script `src/scripts/remove-bg.mjs` removes white backgrounds from PNG icons using flood-fill from edges (like magic wand in Photoshop). Uses sharp. White areas inside objects are preserved.
`src/scripts/remove-bg.mjs` — flood-fill white background removal from PNGs (like magic wand). Uses sharp.
```bash
node src/scripts/remove-bg.mjs <file|dir> [--threshold N] [--fuzz N]
```
- `--threshold` — whiteness threshold for R,G,B (default: 230, lower = more aggressive)
- `--fuzz` — anti-alias radius in pixels at the boundary (default: 0)
- Default input: `assets/icons/pack2/`
This is optional — not all icons need it. After generating/splitting new icons, ask the user if they want background removal on specific files.
Optional — not all icons need it. Ask user after generating/splitting new icons.
## PDF Generation
Puppeteer settings for A4 worksheets:
- Format: A4
- `printBackground: true` (required for background images)
- Margins: zero (CSS handles margins)
- `preferCSSPageSize: true`
## Space Route Task Type
Generator script: `src/scripts/generate-space-route.mjs`
Output: `output/html/space-route-{N}.html`
### Generation rules
- **Grid:** 7×9 hex grid with jitter, nodes evenly distributed across map area
- **Start nodes:** Enemy = top-left corner, Player = bottom-left corner. Start nodes trimmed to exactly 2 edges
- **No asteroids on route nodes** — decorative objects must not be placed on any node belonging to enemy or player routes, nor on neighbors of start nodes
- **Routes use waypoints** — route goes toward an offset waypoint for ~40% of steps, then changes direction toward the final target. This prevents obvious straight-line paths
- **Route length:** 7-9 steps for enemy, player gets 10 empty cells
- **Ship orientation:** check each ship image and set `flipEnemy`/`flipPlayer` flags so all ships face right
- **Difficulty via diffRange:** `[minNodeValue, maxSpread]` — first number = minimum node value, second = max |difference| between connected neighbors
## Visual Position Editor
`output/html/editor.html` — a standalone drag-and-drop editor for repositioning elements (asteroids, icons, etc.) in generated worksheets.
### Usage
```
http://localhost:3300/html/editor.html?file=collecting-asteroids-1.html
```bash
node src/scripts/generate-pdf.mjs tasks/{type}/docs/{docId}.output.html
```
- **Mouse drag** — move elements freely
- **Arrow keys** — nudge 1mm (Shift+Arrow = 5mm)
- **Copy All JSON** — export all positions to clipboard
- **Copy Changes** — export only moved elements
- **`window.getConfig()`** — same via console
Puppeteer: A4, `printBackground: true`, zero margins, `preferCSSPageSize: true`.
### How it works
## Workflow Summary
The editor `fetch()`es the worksheet HTML and injects it into its own DOM, adding drag-and-drop behavior. The worksheet HTML stays clean — no editor code touches it. The editor identifies draggable elements via CSS selector (e.g., `img[src*="pack3-asteroids"]` for asteroids).
### Applying positions from editor
User copies JSON from editor, gives it to Claude. Claude applies positions via a Node.js one-liner:
```js
// Pattern: regex-replace positions in order per page
html.replace(
/(<div class="absolute" style="left: )-?\d+mm; top: -?\d+mm(;"><div class="relative w-\[88px\]...pack3-asteroids)/g,
(match, prefix, suffix) => { /* replace with new left/top from JSON */ }
);
```
### When to use this pattern
Use the visual editor approach whenever a worksheet requires **manual fine-tuning of element positions** — any time automated placement can't fully replace human judgment (e.g., avoiding overlaps with irregular ship shapes, achieving visual balance). The workflow is:
1. Claude generates initial positions algorithmically
2. User opens editor, adjusts positions visually
3. User exports JSON → Claude applies to HTML
4. Generate PDF
This pattern can be extended to other element types by adding new CSS selectors to the editor's identification logic.
## Workflow
1. User describes the math task idea (or runs `/new-doc`)
2. Claude creates/updates a JSON config in `tasks/` with `pages[].task` descriptions
3. Claude reads `src/templates/space-base.html` + `src/examples/space-worksheet.html` as references
4. Claude generates HTML file in `output/html/` — creates concrete problems from `task` text, assigns unique shuffled icons, builds all pages
5. **(Optional)** User fine-tunes element positions via visual editor at `editor.html?file=<name>.html`, exports JSON, Claude applies
6. Add a link to the new document in `output/index.html` (card with title and path)
7. Run `node src/scripts/generate-pdf.mjs output/html/<file>.html` to create PDF
8. Preview with `pnpm preview` at localhost:3300
1. User describes the task idea (or runs `/new-doc`)
2. Claude creates/updates `.md` file with patterns and notes
3. Claude creates/edits `.template.html` (reading type CLAUDE.md and base references)
4. Run `generate.mjs` to create `.output.html`
5. **(Optional)** User opens editor → fine-tunes positions → Save → data.json + output.html updated
6. Claude reviews diff if asked: `cat tasks/{type}/temp/{docId}.diff.json`
7. Add card to `tasks/index.html`
8. Generate PDF: `node src/scripts/generate-pdf.mjs tasks/{type}/docs/{docId}.output.html`
9. Preview at `http://localhost:3300/tasks/index.html`

View File

@ -3,14 +3,13 @@ const path = require('path');
module.exports = {
server: {
baseDir: "output",
routes: {
"/assets": "assets"
}
baseDir: "."
},
files: [
"output/index.html",
"output/html/**/*.html",
"tasks/index.html",
"tasks/*/docs/*.template.html",
"tasks/*/docs/*.output.html",
"tasks/*/editor.html",
"assets/**/*"
],
port: 3300,
@ -19,21 +18,46 @@ module.exports = {
ui: false,
middleware: [
{
route: "/api/save-editor",
route: "/api/save-edits",
handle: function (req, res, next) {
if (req.method !== 'POST') return next();
let body = '';
req.on('data', chunk => body += chunk);
req.on('end', () => {
try {
const data = JSON.parse(body);
const name = path.basename(data.file || 'unknown', '.html');
const dir = path.join(__dirname, 'output', 'editor-saves');
fs.mkdirSync(dir, { recursive: true });
const savePath = path.join(dir, name + '.json');
fs.writeFileSync(savePath, JSON.stringify(data, null, 2));
const payload = JSON.parse(body);
const { taskType, docId, data } = payload;
if (!taskType || !docId || !data) {
res.writeHead(400, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: 'Missing taskType, docId, or data' }));
return;
}
const docsDir = path.join(__dirname, 'tasks', taskType, 'docs');
const tempDir = path.join(__dirname, 'tasks', taskType, 'temp');
fs.mkdirSync(tempDir, { recursive: true });
const dataPath = path.join(docsDir, docId + '.data.json');
const diffPath = path.join(tempDir, docId + '.diff.json');
// Read old data for diff
let oldData = null;
try {
oldData = JSON.parse(fs.readFileSync(dataPath, 'utf-8'));
} catch (e) {
// No previous data — first save
}
// Write new data
fs.writeFileSync(dataPath, JSON.stringify(data, null, 2));
// Compute and write diff
const diff = computeDiff(oldData, data, docId);
fs.writeFileSync(diffPath, JSON.stringify(diff, null, 2));
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ ok: true, path: savePath }));
res.end(JSON.stringify({ ok: true, path: dataPath }));
} catch (e) {
res.writeHead(400, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: e.message }));
@ -43,3 +67,38 @@ module.exports = {
}
]
};
function computeDiff(oldData, newData, docId) {
const changes = [];
const timestamp = new Date().toISOString();
if (!oldData) {
return { timestamp, docId, firstSave: true, changes: [] };
}
const oldPages = oldData.pages || [];
const newPages = newData.pages || [];
for (let i = 0; i < Math.max(oldPages.length, newPages.length); i++) {
const oldPage = oldPages[i] || {};
const newPage = newPages[i] || {};
const pageNum = (newPage.page || oldPage.page || i + 1);
// Compare all element arrays in the page
for (const key of new Set([...Object.keys(oldPage), ...Object.keys(newPage)])) {
if (key === 'page') continue;
const oldVal = JSON.stringify(oldPage[key]);
const newVal = JSON.stringify(newPage[key]);
if (oldVal !== newVal) {
changes.push({
page: pageNum,
field: key,
from: oldPage[key],
to: newPage[key]
});
}
}
}
return { timestamp, docId, changes };
}

233
src/editor/editor-core.js Normal file
View File

@ -0,0 +1,233 @@
/**
* EditorCore shared framework for all task-type visual editors.
*
* Handles: worksheet loading, page management, toolbar wiring,
* toast/tooltip, save endpoint, copy/export.
*
* Task-specific logic (selectors, drag, keyboard, serialization)
* stays in each editor.html.
*
* Usage:
* const core = EditorCore.init({
* taskType: 'collecting-asteroids',
* onReady: (pages, mmToPx) => { ... setup draggables, keyboard, etc. }
* });
*/
window.EditorCore = (function () {
let _pages = [];
let _currentPage = 0;
let _mmToPx = 1;
let _config = {};
let _serializeFn = null;
/**
* Initialize the editor core.
* @param {Object} opts
* @param {string} opts.taskType - e.g. 'collecting-asteroids'
* @param {Function} opts.onReady - called after worksheet loaded: (pages, mmToPx) => void
* @param {Function} [opts.serialize] - fn(changesOnly) => config object
* @param {Function} [opts.onReset] - fn(pageNum) => void
*/
function init(opts) {
const params = new URLSearchParams(location.search);
const fileParam = params.get('file');
if (!fileParam) {
document.getElementById('worksheet-container').innerHTML =
'<p style="padding:80px 20px;color:#f38ba8;">No file specified. Use ?file=&lt;docId&gt;</p>';
return null;
}
_config = {
taskType: opts.taskType || '',
fileParam: fileParam,
docId: fileParam,
filePath: 'docs/' + fileParam + '.template.html',
};
if (opts.serialize) _serializeFn = opts.serialize;
// Wire standard toolbar buttons
_wireButton('btn-prev', () => scrollToPage(_currentPage - 1));
_wireButton('btn-next', () => scrollToPage(_currentPage + 1));
_wireButton('btn-copy', () => _copyConfig(false));
_wireButton('btn-copy-changes', () => _copyConfig(true));
_wireButton('btn-save', _saveToServer);
if (opts.onReset) {
_wireButton('btn-reset', () => opts.onReset(_currentPage + 1));
}
// Load worksheet
_loadWorksheet(_config.filePath, opts.onReady);
return {
get pages() { return _pages; },
get currentPage() { return _currentPage; },
get mmToPx() { return _mmToPx; },
get docId() { return _config.docId; },
scrollToPage,
showToast,
showTooltip,
hideTooltip,
setSerializer: (fn) => { _serializeFn = fn; },
};
}
// ---- Worksheet Loading ----
function _loadWorksheet(filePath, onReady) {
fetch(filePath)
.then(r => { if (!r.ok) throw new Error(r.status); return r.text(); })
.then(html => {
const parser = new DOMParser();
const doc = parser.parseFromString(html, 'text/html');
const container = document.getElementById('worksheet-container');
// Tailwind CDN
const tw = document.createElement('script');
tw.src = 'https://cdn.tailwindcss.com';
document.head.appendChild(tw);
// Copy head elements
doc.querySelectorAll('head script:not([src])').forEach(s => {
const ns = document.createElement('script');
ns.textContent = s.textContent;
document.head.appendChild(ns);
});
doc.querySelectorAll('head style').forEach(s => {
const ns = document.createElement('style');
ns.textContent = s.textContent;
document.head.appendChild(ns);
});
doc.querySelectorAll('head link').forEach(l => {
document.head.appendChild(l.cloneNode(true));
});
container.innerHTML = doc.body.innerHTML;
// Wait for Tailwind, then init pages and call onReady
setTimeout(() => {
_initPages();
if (onReady) onReady(_pages, _mmToPx);
}, 350);
})
.catch(err => {
document.getElementById('worksheet-container').innerHTML =
`<p style="padding:80px 20px;color:#f38ba8;">Failed to load ${filePath}: ${err.message}</p>`;
});
}
// ---- Pages ----
function _initPages() {
_pages = Array.from(document.querySelectorAll('.w-\\[210mm\\]'));
_pages.forEach((p, i) => {
p.dataset.page = i + 1;
p.style.position = 'relative';
const label = document.createElement('div');
label.className = 'page-label';
label.textContent = `Page ${i + 1}`;
p.appendChild(label);
});
document.getElementById('page-indicator').textContent = `Page 1 / ${_pages.length}`;
if (_pages.length > 0) {
_mmToPx = _pages[0].getBoundingClientRect().width / 210;
}
// Scroll tracking
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting && entry.intersectionRatio > 0.3) {
_currentPage = parseInt(entry.target.dataset.page) - 1;
document.getElementById('page-indicator').textContent =
`Page ${_currentPage + 1} / ${_pages.length}`;
}
});
}, { threshold: [0.3] });
_pages.forEach(p => observer.observe(p));
// Resize handler
window.addEventListener('resize', () => {
if (_pages.length > 0) _mmToPx = _pages[0].getBoundingClientRect().width / 210;
});
}
function scrollToPage(index) {
if (index < 0 || index >= _pages.length) return;
_pages[index].scrollIntoView({ behavior: 'smooth', block: 'start' });
}
// ---- Toast ----
function showToast(msg) {
const toast = document.getElementById('toast');
if (!toast) return;
toast.textContent = msg;
toast.classList.add('show');
setTimeout(() => toast.classList.remove('show'), 1500);
}
// ---- Tooltip ----
function showTooltip(e, text) {
const tooltip = document.getElementById('coord-tooltip');
if (!tooltip) return;
tooltip.style.display = 'block';
tooltip.textContent = text;
tooltip.style.left = (e.clientX + 15) + 'px';
tooltip.style.top = (e.clientY - 10) + 'px';
}
function hideTooltip() {
const tooltip = document.getElementById('coord-tooltip');
if (tooltip) tooltip.style.display = 'none';
}
// ---- Save / Copy ----
async function _saveToServer() {
if (!_serializeFn) { showToast('No serializer'); return; }
const data = _serializeFn(false);
try {
const resp = await fetch('/api/save-edits', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
taskType: _config.taskType,
docId: _config.docId,
data: data
})
});
const result = await resp.json();
showToast(result.ok ? 'Saved!' : 'Error: ' + result.error);
} catch (e) {
showToast('Save failed: ' + e.message);
}
}
function _copyConfig(changesOnly) {
if (!_serializeFn) { showToast('No serializer'); return; }
const data = _serializeFn(changesOnly);
const json = JSON.stringify(data, null, 2);
navigator.clipboard.writeText(json).then(() => {
showToast(changesOnly ? 'Changes copied!' : 'Config copied!');
}).catch(() => {
console.log(json);
showToast('Copied to console (clipboard blocked)');
});
}
// ---- Helpers ----
function _wireButton(id, handler) {
const btn = document.getElementById(id);
if (btn) btn.addEventListener('click', handler);
}
return { init };
})();

View File

@ -1,131 +0,0 @@
{
"id": "collecting-asteroids-1",
"title": "Собери Астероиды",
"description": "9-page asteroid-matching worksheet: match asteroids to cargo ships by weight sum, increasing difficulty",
"labels": {
"title": "Собери Астероиды",
"subtitle": "Загрузи трюмы кораблей!",
"footerBubble": "Итого загружено:"
},
"theme": {
"style": "space-asteroids",
"template": "space-base",
"asteroids": "assets/icons/pack3-asteroids/"
},
"layout": {
"type": "asteroid-matching",
"shipsPerPage": 3,
"asteroidTypesPerPage": 2,
"asteroidTypeRatio": "70:30"
},
"pages": [
{
"ships": [
{ "capacity": 5, "fillCount": 2 },
{ "capacity": 5, "fillCount": 2 },
{ "capacity": 7, "fillCount": 3 }
],
"heroImage": "assets/hero-images/splitters/splitter1.png",
"footerImage": "assets/footers/cabin1.jpeg",
"heroDirection": "row-reverse",
"cargoBays": ["cargo-bay1", "cargo-bay2", "cargo-bay3"],
"asteroidTypes": ["asteroid1", "asteroid6"]
},
{
"ships": [
{ "capacity": 7, "fillCount": 3 },
{ "capacity": 7, "fillCount": 3 },
{ "capacity": 10, "fillCount": 4 }
],
"heroImage": "assets/hero-images/splitters/splitter2.png",
"footerImage": "assets/footers/cabin2.jpeg",
"heroDirection": "row",
"cargoBays": ["cargo-bay4", "cargo-bay5", "cargo-bay6"],
"asteroidTypes": ["asteroid3", "asteroid9"]
},
{
"ships": [
{ "capacity": 5, "fillCount": 2 },
{ "capacity": 5, "fillCount": 3 },
{ "capacity": 6, "fillCount": 3 }
],
"heroImage": "assets/hero-images/splitters/splitter3.png",
"footerImage": "assets/footers/cabin3.jpeg",
"heroDirection": "row-reverse",
"cargoBays": ["cargo-bay7", "cargo-bay8", "cargo-bay9"],
"asteroidTypes": ["asteroid5", "asteroid11"]
},
{
"ships": [
{ "capacity": 8, "fillCount": 2 },
{ "capacity": 8, "fillCount": 3 },
{ "capacity": 6, "fillCount": 2 }
],
"heroImage": "assets/hero-images/splitters/splitter4.png",
"footerImage": "assets/footers/cabin4.jpeg",
"heroDirection": "row",
"cargoBays": ["cargo-bay1", "cargo-bay2", "cargo-bay3"],
"asteroidTypes": ["asteroid2", "asteroid8"]
},
{
"ships": [
{ "capacity": 4, "fillCount": 1 },
{ "capacity": 4, "fillCount": 2 },
{ "capacity": 4, "fillCount": 3 }
],
"heroImage": "assets/hero-images/splitters/splitter5.png",
"footerImage": "assets/footers/cabin5.jpeg",
"heroDirection": "row-reverse",
"cargoBays": ["cargo-bay4", "cargo-bay5", "cargo-bay6"],
"asteroidTypes": ["asteroid4", "asteroid10"]
},
{
"ships": [
{ "capacity": 10, "fillCount": 4 },
{ "capacity": 10, "fillCount": 3 },
{ "capacity": 8, "fillCount": 3 }
],
"heroImage": "assets/hero-images/splitters/splitter6.png",
"footerImage": "assets/footers/cabin6.jpeg",
"heroDirection": "row",
"cargoBays": ["cargo-bay7", "cargo-bay8", "cargo-bay9"],
"asteroidTypes": ["asteroid7", "asteroid13"]
},
{
"ships": [
{ "capacity": 6, "fillCount": 2 },
{ "capacity": 9, "fillCount": 3 },
{ "capacity": 12, "fillCount": 4 }
],
"heroImage": "assets/hero-images/splitters/splitter7.png",
"footerImage": "assets/footers/cabin7.jpeg",
"heroDirection": "row-reverse",
"cargoBays": ["cargo-bay1", "cargo-bay2", "cargo-bay3"],
"asteroidTypes": ["asteroid12", "asteroid16"]
},
{
"ships": [
{ "capacity": 14, "fillCount": 3 },
{ "capacity": 10, "fillCount": 2 },
{ "capacity": 16, "fillCount": 4 }
],
"heroImage": "assets/hero-images/splitters/splitter8.png",
"footerImage": "assets/footers/cabin8.jpeg",
"heroDirection": "row",
"cargoBays": ["cargo-bay4", "cargo-bay5", "cargo-bay6"],
"asteroidTypes": ["asteroid14", "asteroid15"]
},
{
"ships": [
{ "capacity": 5, "fillCount": 2 },
{ "capacity": 10, "fillCount": 4 },
{ "capacity": 15, "fillCount": 5 }
],
"heroImage": "assets/hero-images/splitters/splitter9.png",
"footerImage": "assets/footers/cabin9.jpeg",
"heroDirection": "row-reverse",
"cargoBays": ["cargo-bay7", "cargo-bay8", "cargo-bay9"],
"asteroidTypes": ["asteroid1", "asteroid9"]
}
]
}

View File

@ -1,131 +0,0 @@
{
"id": "collecting-asteroids-2",
"title": "Собери Астероиды",
"description": "9-page asteroid-matching worksheet v2: reshuffled assets, doubled difficulty",
"labels": {
"title": "Собери Астероиды",
"subtitle": "Загрузи трюмы кораблей!",
"footerBubble": "Итого загружено:"
},
"theme": {
"style": "space-asteroids",
"template": "space-base",
"asteroids": "assets/icons/pack3-asteroids/"
},
"layout": {
"type": "asteroid-matching",
"shipsPerPage": 3,
"asteroidTypesPerPage": 2,
"asteroidTypeRatio": "70:30"
},
"pages": [
{
"ships": [
{ "capacity": 10, "fillCount": 2 },
{ "capacity": 10, "fillCount": 2 },
{ "capacity": 14, "fillCount": 3 }
],
"heroImage": "assets/hero-images/splitters/splitter5.png",
"footerImage": "assets/footers/cabin7.jpeg",
"heroDirection": "row",
"cargoBays": ["cargo-bay4", "cargo-bay5", "cargo-bay6"],
"asteroidTypes": ["asteroid7", "asteroid14"]
},
{
"ships": [
{ "capacity": 14, "fillCount": 3 },
{ "capacity": 14, "fillCount": 3 },
{ "capacity": 20, "fillCount": 4 }
],
"heroImage": "assets/hero-images/splitters/splitter2.png",
"footerImage": "assets/footers/cabin4.jpeg",
"heroDirection": "row-reverse",
"cargoBays": ["cargo-bay7", "cargo-bay8", "cargo-bay9"],
"asteroidTypes": ["asteroid4", "asteroid11"]
},
{
"ships": [
{ "capacity": 10, "fillCount": 2 },
{ "capacity": 10, "fillCount": 3 },
{ "capacity": 12, "fillCount": 3 }
],
"heroImage": "assets/hero-images/splitters/splitter8.png",
"footerImage": "assets/footers/cabin1.jpeg",
"heroDirection": "row",
"cargoBays": ["cargo-bay1", "cargo-bay2", "cargo-bay3"],
"asteroidTypes": ["asteroid10", "asteroid3"]
},
{
"ships": [
{ "capacity": 16, "fillCount": 2 },
{ "capacity": 16, "fillCount": 3 },
{ "capacity": 12, "fillCount": 2 }
],
"heroImage": "assets/hero-images/splitters/splitter3.png",
"footerImage": "assets/footers/cabin9.jpeg",
"heroDirection": "row-reverse",
"cargoBays": ["cargo-bay4", "cargo-bay5", "cargo-bay6"],
"asteroidTypes": ["asteroid16", "asteroid5"]
},
{
"ships": [
{ "capacity": 8, "fillCount": 1 },
{ "capacity": 8, "fillCount": 2 },
{ "capacity": 8, "fillCount": 3 }
],
"heroImage": "assets/hero-images/splitters/splitter9.png",
"footerImage": "assets/footers/cabin2.jpeg",
"heroDirection": "row",
"cargoBays": ["cargo-bay7", "cargo-bay8", "cargo-bay9"],
"asteroidTypes": ["asteroid2", "asteroid13"]
},
{
"ships": [
{ "capacity": 20, "fillCount": 4 },
{ "capacity": 20, "fillCount": 3 },
{ "capacity": 16, "fillCount": 3 }
],
"heroImage": "assets/hero-images/splitters/splitter1.png",
"footerImage": "assets/footers/cabin6.jpeg",
"heroDirection": "row-reverse",
"cargoBays": ["cargo-bay1", "cargo-bay2", "cargo-bay3"],
"asteroidTypes": ["asteroid8", "asteroid12"]
},
{
"ships": [
{ "capacity": 12, "fillCount": 2 },
{ "capacity": 18, "fillCount": 3 },
{ "capacity": 24, "fillCount": 4 }
],
"heroImage": "assets/hero-images/splitters/splitter6.png",
"footerImage": "assets/footers/cabin3.jpeg",
"heroDirection": "row",
"cargoBays": ["cargo-bay4", "cargo-bay5", "cargo-bay6"],
"asteroidTypes": ["asteroid15", "asteroid6"]
},
{
"ships": [
{ "capacity": 28, "fillCount": 3 },
{ "capacity": 20, "fillCount": 2 },
{ "capacity": 32, "fillCount": 4 }
],
"heroImage": "assets/hero-images/splitters/splitter4.png",
"footerImage": "assets/footers/cabin8.jpeg",
"heroDirection": "row-reverse",
"cargoBays": ["cargo-bay7", "cargo-bay8", "cargo-bay9"],
"asteroidTypes": ["asteroid9", "asteroid1"]
},
{
"ships": [
{ "capacity": 10, "fillCount": 2 },
{ "capacity": 20, "fillCount": 4 },
{ "capacity": 30, "fillCount": 5 }
],
"heroImage": "assets/hero-images/splitters/splitter7.png",
"footerImage": "assets/footers/cabin5.jpeg",
"heroDirection": "row",
"cargoBays": ["cargo-bay1", "cargo-bay2", "cargo-bay3"],
"asteroidTypes": ["asteroid11", "asteroid4"]
}
]
}

View File

@ -1,141 +0,0 @@
{
"id": "collecting-asteroids-3",
"title": "Собери Астероиды",
"description": "9-page asteroid-matching worksheet v3: reshuffled assets, halved asteroid values",
"labels": {
"title": "Собери Астероиды",
"subtitle": "Загрузи трюмы кораблей!",
"footerBubble": "Итого загружено:"
},
"theme": {
"style": "space-asteroids",
"template": "space-base",
"asteroids": "assets/icons/pack3-asteroids/"
},
"layout": {
"type": "asteroid-matching",
"shipsPerPage": 3,
"asteroidTypesPerPage": 2,
"asteroidTypeRatio": "70:30"
},
"pages": [
{
"ships": [
{ "capacity": 11, "fillCount": 2 },
{ "capacity": 9, "fillCount": 2 },
{ "capacity": 13, "fillCount": 6 }
],
"heroImage": "assets/hero-images/splitters/splitter4.png",
"footerImage": "assets/footers/cabin3.jpeg",
"heroDirection": "row",
"cargoBays": ["cargo-bay7", "cargo-bay8", "cargo-bay9"],
"asteroidTypes": ["asteroid3", "asteroid10"],
"asteroidValues": [3, 2, 1, 4, 5, 2, 3, 6, 5, 4, 1, 6]
},
{
"ships": [
{ "capacity": 12, "fillCount": 3 },
{ "capacity": 12, "fillCount": 3 },
{ "capacity": 18, "fillCount": 4 }
],
"heroImage": "assets/hero-images/splitters/splitter7.png",
"footerImage": "assets/footers/cabin6.jpeg",
"heroDirection": "row-reverse",
"cargoBays": ["cargo-bay1", "cargo-bay2", "cargo-bay3"],
"asteroidTypes": ["asteroid6", "asteroid13"],
"asteroidValues": [4, 5, 3, 6, 2, 7, 4, 3, 5, 2, 6, 4]
},
{
"ships": [
{ "capacity": 9, "fillCount": 5 },
{ "capacity": 11, "fillCount": 3 },
{ "capacity": 11, "fillCount": 2 }
],
"heroImage": "assets/hero-images/splitters/splitter1.png",
"footerImage": "assets/footers/cabin9.jpeg",
"heroDirection": "row",
"cargoBays": ["cargo-bay4", "cargo-bay5", "cargo-bay6"],
"asteroidTypes": ["asteroid2", "asteroid8"],
"asteroidValues": [2, 4, 1, 3, 5, 2, 1, 3, 4, 6, 5, 2]
},
{
"ships": [
{ "capacity": 15, "fillCount": 4 },
{ "capacity": 17, "fillCount": 5 },
{ "capacity": 11, "fillCount": 2 }
],
"heroImage": "assets/hero-images/splitters/splitter6.png",
"footerImage": "assets/footers/cabin2.jpeg",
"heroDirection": "row-reverse",
"cargoBays": ["cargo-bay7", "cargo-bay8", "cargo-bay9"],
"asteroidTypes": ["asteroid12", "asteroid15"],
"asteroidValues": [4, 3, 5, 2, 6, 1, 3, 4, 6, 2, 5, 4]
},
{
"ships": [
{ "capacity": 7, "fillCount": 2 },
{ "capacity": 9, "fillCount": 4 },
{ "capacity": 7, "fillCount": 2 }
],
"heroImage": "assets/hero-images/splitters/splitter2.png",
"footerImage": "assets/footers/cabin5.jpeg",
"heroDirection": "row",
"cargoBays": ["cargo-bay1", "cargo-bay2", "cargo-bay3"],
"asteroidTypes": ["asteroid1", "asteroid9"],
"asteroidValues": [3, 1, 4, 2, 5, 1, 6, 2, 3, 4, 5]
},
{
"ships": [
{ "capacity": 18, "fillCount": 4 },
{ "capacity": 18, "fillCount": 5 },
{ "capacity": 14, "fillCount": 3 }
],
"heroImage": "assets/hero-images/splitters/splitter8.png",
"footerImage": "assets/footers/cabin7.jpeg",
"heroDirection": "row-reverse",
"cargoBays": ["cargo-bay4", "cargo-bay5", "cargo-bay6"],
"asteroidTypes": ["asteroid5", "asteroid16"],
"asteroidValues": [3, 4, 5, 6, 2, 4, 7, 3, 2, 5, 6, 4, 3, 7]
},
{
"ships": [
{ "capacity": 10, "fillCount": 2 },
{ "capacity": 16, "fillCount": 3 },
{ "capacity": 22, "fillCount": 6 }
],
"heroImage": "assets/hero-images/splitters/splitter9.png",
"footerImage": "assets/footers/cabin4.jpeg",
"heroDirection": "row",
"cargoBays": ["cargo-bay7", "cargo-bay8", "cargo-bay9"],
"asteroidTypes": ["asteroid11", "asteroid7"],
"asteroidValues": [4, 3, 2, 6, 5, 3, 7, 4, 5, 2, 6, 4]
},
{
"ships": [
{ "capacity": 26, "fillCount": 0 },
{ "capacity": 18, "fillCount": 0 },
{ "capacity": 30, "fillCount": 0 }
],
"_unsolvable": true,
"heroImage": "assets/hero-images/splitters/splitter5.png",
"footerImage": "assets/footers/cabin1.jpeg",
"heroDirection": "row-reverse",
"cargoBays": ["cargo-bay1", "cargo-bay2", "cargo-bay3"],
"asteroidTypes": ["asteroid14", "asteroid4"],
"asteroidValues": [6, 4, 5, 3, 7, 2, 4, 6, 5, 7, 3, 4, 6]
},
{
"ships": [
{ "capacity": 8, "fillCount": 2 },
{ "capacity": 18, "fillCount": 3 },
{ "capacity": 28, "fillCount": 8 }
],
"heroImage": "assets/hero-images/splitters/splitter3.png",
"footerImage": "assets/footers/cabin8.jpeg",
"heroDirection": "row",
"cargoBays": ["cargo-bay4", "cargo-bay5", "cargo-bay6"],
"asteroidTypes": ["asteroid10", "asteroid6"],
"asteroidValues": [4, 3, 2, 5, 6, 3, 4, 7, 2, 5, 4, 6, 3, 7, 5]
}
]
}

View File

@ -0,0 +1,46 @@
# Collecting Asteroids Task Type
Match asteroids to cargo ships by weight sum. Each page has 3 ships with cargo bays and ~12 asteroids scattered across the page. Child draws lines connecting asteroids to ships so that asteroid values sum to ship capacity.
## Layout
- 3 ships per page with cargo bay images
- 2 asteroid types per page (70:30 ratio distribution)
- 12 asteroids per page scattered with absolute positioning
- Hero images: splitter ships from `assets/hero-images/splitters/`
- Footer images: cabin interiors from `assets/footers/cabin{1-9}.jpeg`
- Cargo bay images: `assets/icons/pack4-cargobay/cargo-bay{1-9}.png`
- Asteroid images: `assets/icons/pack3-asteroids/asteroid{1-16}.png`
## Asteroid Placement Rules
- Distribute asteroids evenly across the page area using grid-based approach
- Asteroids must not overlap with ships or cargo bays
- Each asteroid has a numeric value (1-20) displayed on it
- Scale formula: `scale = baseScale + 0.15 * value` (default baseScale: 0.30)
- No editor-first approach — generate everything via AI first, editor comes later for fine-tuning
## Validation
Use verify script to check that asteroid values can be partitioned to ship capacities:
```bash
node scripts/verify.mjs --ships 10,10,14 --asteroids 3,2,1,4,5,2,3,6,5,4,1,6
```
Always verify solvability after generating or editing asteroid values.
## Scripts
- `scripts/verify.mjs` — solver to verify asteroid-to-ship partition (stdout → Claude reads)
- `scripts/transform-collecting3.mjs` — bulk asset replacement utility
## Editor
`editor.html?file={docId}` — drag asteroids and ship circles, adjust values and scales.
Key controls:
- Drag: move asteroid/ship position
- `+/-`: change asteroid value (1-20 range)
- `[/]`: rotate ±5° (Shift = ±1°)
- `</.>`: adjust base scale per asteroid type
- Save: writes to `docs/{docId}.data.json`

View File

@ -0,0 +1,66 @@
# Collecting Asteroids 1
**Title:** Собери Астероиды
**Subtitle:** Загрузи трюмы кораблей!
**Footer bubble:** Итого загружено:
## Layout
- 3 ships per page, 2 asteroid types per page (70:30 ratio)
- Asteroids: assets/icons/pack3-asteroids/
## Pages
### Page 1
- **Ships:** capacity 5 (fill 2), capacity 5 (fill 2), capacity 7 (fill 3)
- **Hero:** splitter1.png, direction: row-reverse
- **Cargo bays:** cargo-bay1, cargo-bay2, cargo-bay3
- **Asteroid types:** asteroid1, asteroid6
### Page 2
- **Ships:** capacity 7 (fill 3), capacity 7 (fill 3), capacity 10 (fill 4)
- **Hero:** splitter2.png, direction: row
- **Cargo bays:** cargo-bay4, cargo-bay5, cargo-bay6
- **Asteroid types:** asteroid3, asteroid9
### Page 3
- **Ships:** capacity 5 (fill 2), capacity 5 (fill 3), capacity 6 (fill 3)
- **Hero:** splitter3.png, direction: row-reverse
- **Cargo bays:** cargo-bay7, cargo-bay8, cargo-bay9
- **Asteroid types:** asteroid5, asteroid11
### Page 4
- **Ships:** capacity 8 (fill 2), capacity 8 (fill 3), capacity 6 (fill 2)
- **Hero:** splitter4.png, direction: row
- **Cargo bays:** cargo-bay1, cargo-bay2, cargo-bay3
- **Asteroid types:** asteroid2, asteroid8
### Page 5
- **Ships:** capacity 4 (fill 1), capacity 4 (fill 2), capacity 4 (fill 3)
- **Hero:** splitter5.png, direction: row-reverse
- **Cargo bays:** cargo-bay4, cargo-bay5, cargo-bay6
- **Asteroid types:** asteroid4, asteroid10
### Page 6
- **Ships:** capacity 10 (fill 4), capacity 10 (fill 3), capacity 8 (fill 3)
- **Hero:** splitter6.png, direction: row
- **Cargo bays:** cargo-bay7, cargo-bay8, cargo-bay9
- **Asteroid types:** asteroid7, asteroid13
### Page 7
- **Ships:** capacity 6 (fill 2), capacity 9 (fill 3), capacity 12 (fill 4)
- **Hero:** splitter7.png, direction: row-reverse
- **Cargo bays:** cargo-bay1, cargo-bay2, cargo-bay3
- **Asteroid types:** asteroid12, asteroid16
### Page 8
- **Ships:** capacity 14 (fill 3), capacity 10 (fill 2), capacity 16 (fill 4)
- **Hero:** splitter8.png, direction: row
- **Cargo bays:** cargo-bay4, cargo-bay5, cargo-bay6
- **Asteroid types:** asteroid14, asteroid15
### Page 9
- **Ships:** capacity 5 (fill 2), capacity 10 (fill 4), capacity 15 (fill 5)
- **Hero:** splitter9.png, direction: row-reverse
- **Cargo bays:** cargo-bay7, cargo-bay8, cargo-bay9
- **Asteroid types:** asteroid1, asteroid9

View File

@ -0,0 +1,348 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.tailwindcss.com"></script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700;800;900&display=swap" rel="stylesheet">
<title>Собери Астероиды</title>
<script>
tailwind.config = {
theme: {
extend: {
fontFamily: { nunito: ['Nunito', 'sans-serif'] },
}
}
}
</script>
<style>
@page { size: A4; margin: 0; }
</style>
</head>
<body class="bg-gray-200 font-nunito">
<!-- PAGE 1: ships 5(2), 5(2), 7(3) — L-R-L -->
<div class="w-[210mm] h-[297mm] relative overflow-hidden mx-auto bg-white" style="break-after: page;">
<div class="absolute bottom-0 left-0 right-0 z-0">
<div class="absolute top-0 left-0 right-0 z-10" style="height: 10%; background: linear-gradient(to bottom, white, transparent);"></div>
<img src="../../assets/footers/cabin1.jpeg" class="w-full" alt="">
</div>
<div class="relative z-10 w-full h-full px-[12mm] pt-[1mm] pb-[65mm] flex flex-col">
<div class="flex items-center gap-2 mb-1 flex-row-reverse">
<img src="../../assets/hero-images/splitters/splitter1.png" class="w-[66%] shrink-0 object-contain" style="transform: scaleX(-1);" alt="">
<div class="w-[34%] shrink-0 flex flex-col items-center justify-center text-center">
<h1 class="text-2xl font-extrabold leading-tight tracking-tight text-indigo-950">Собери Астероиды</h1>
<p class="text-sm font-medium text-indigo-400 mt-0.5">Загрузи трюмы кораблей!</p>
</div>
</div>
<div class="relative flex-1">
<div class="absolute" style="left: -82mm; top: 2%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay1.png" class="w-[500px] object-contain" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 65%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">5</span></div></div></div>
<div class="absolute" style="left: 120mm; top: 30%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay2.png" class="w-[500px] min-w-[500px] object-contain" style="transform: scaleX(-1);" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 35%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">5</span></div></div></div>
<div class="absolute" style="left: -82mm; top: 58%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay3.png" class="w-[500px] object-contain" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 65%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">7</span></div></div></div>
<div class="absolute" style="left: 67mm; top: 1mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid1.png" class="w-full h-full object-contain" style="transform: rotate(-15deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 111mm; top: 15mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid6.png" class="w-full h-full object-contain" style="transform: rotate(22deg) scale(0.88);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">3</span></div></div></div>
<div class="absolute" style="left: 146mm; top: 28mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid1.png" class="w-full h-full object-contain" style="transform: rotate(-8deg) scale(1.12);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">1</span></div></div></div>
<div class="absolute" style="left: 22mm; top: 55mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid1.png" class="w-full h-full object-contain" style="transform: rotate(12deg) scale(0.92);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 57mm; top: 43mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid6.png" class="w-full h-full object-contain" style="transform: rotate(-20deg) scale(1.08);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">1</span></div></div></div>
<div class="absolute" style="left: 93mm; top: 49mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid1.png" class="w-full h-full object-contain" style="transform: rotate(15deg) scale(0.90);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 80mm; top: 87mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid1.png" class="w-full h-full object-contain" style="transform: rotate(25deg) scale(0.95);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 33mm; top: 87mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid6.png" class="w-full h-full object-contain" style="transform: rotate(-5deg) scale(1.02);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
<div class="absolute" style="left: 115mm; top: 132mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid1.png" class="w-full h-full object-contain" style="transform: rotate(18deg) scale(1.10);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">5</span></div></div></div>
<div class="absolute" style="left: 45mm; top: 125mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid1.png" class="w-full h-full object-contain" style="transform: rotate(-22deg) scale(0.85);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">3</span></div></div></div>
<div class="absolute" style="left: 79mm; top: 141mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid6.png" class="w-full h-full object-contain" style="transform: rotate(8deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">5</span></div></div></div>
<div class="absolute" style="left: 132mm; top: 160mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid1.png" class="w-full h-full object-contain" style="transform: rotate(-10deg) scale(0.92);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">3</span></div></div></div>
</div>
</div>
</div>
<!-- PAGE 2: ships 7(3), 7(3), 10(4) — R-L-R -->
<div class="w-[210mm] h-[297mm] relative overflow-hidden mx-auto bg-white" style="break-after: page;">
<div class="absolute bottom-0 left-0 right-0 z-0">
<div class="absolute top-0 left-0 right-0 z-10" style="height: 10%; background: linear-gradient(to bottom, white, transparent);"></div>
<img src="../../assets/footers/cabin2.jpeg" class="w-full" alt="">
</div>
<div class="relative z-10 w-full h-full px-[12mm] pt-[1mm] pb-[65mm] flex flex-col">
<div class="flex items-center gap-2 mb-1">
<img src="../../assets/hero-images/splitters/splitter2.png" class="w-[66%] shrink-0 object-contain" alt="">
<div class="w-[34%] shrink-0 flex flex-col items-center justify-center text-center">
<h1 class="text-2xl font-extrabold leading-tight tracking-tight text-indigo-950">Собери Астероиды</h1>
<p class="text-sm font-medium text-indigo-400 mt-0.5">Загрузи трюмы кораблей!</p>
</div>
</div>
<div class="relative flex-1">
<div class="absolute" style="left: 120mm; top: 2%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay4.png" class="w-[500px] min-w-[500px] object-contain" style="transform: scaleX(-1);" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 35%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">7</span></div></div></div>
<div class="absolute" style="left: -82mm; top: 30%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay5.png" class="w-[500px] object-contain" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 65%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">7</span></div></div></div>
<div class="absolute" style="left: 120mm; top: 58%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay6.png" class="w-[500px] min-w-[500px] object-contain" style="transform: scaleX(-1);" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 35%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">10</span></div></div></div>
<div class="absolute" style="left: 15mm; top: 5mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid3.png" class="w-full h-full object-contain" style="transform: rotate(10deg) scale(0.90);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">1</span></div></div></div>
<div class="absolute" style="left: 42mm; top: 37mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid9.png" class="w-full h-full object-contain" style="transform: rotate(-18deg) scale(1.08);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 96mm; top: 2mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid3.png" class="w-full h-full object-contain" style="transform: rotate(22deg) scale(0.92);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 86mm; top: 46mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid3.png" class="w-full h-full object-contain" style="transform: rotate(-12deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 44mm; top: -5mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid9.png" class="w-full h-full object-contain" style="transform: rotate(15deg) scale(0.88);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 140mm; top: 77mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid3.png" class="w-full h-full object-contain" style="transform: rotate(-8deg) scale(1.12);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">3</span></div></div></div>
<div class="absolute" style="left: 96mm; top: 88mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid3.png" class="w-full h-full object-contain" style="transform: rotate(20deg) scale(0.95);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">1</span></div></div></div>
<div class="absolute" style="left: 56mm; top: 73mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid9.png" class="w-full h-full object-contain" style="transform: rotate(-25deg) scale(1.10);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">3</span></div></div></div>
<div class="absolute" style="left: 8mm; top: 154mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid3.png" class="w-full h-full object-contain" style="transform: rotate(5deg) scale(0.85);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 6mm; top: 39mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid3.png" class="w-full h-full object-contain" style="transform: rotate(12deg) scale(1.02);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 70mm; top: 106mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid9.png" class="w-full h-full object-contain" style="transform: rotate(-15deg) scale(0.92);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">5</span></div></div></div>
<div class="absolute" style="left: 31mm; top: 120mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid3.png" class="w-full h-full object-contain" style="transform: rotate(18deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
<div class="absolute" style="left: 83mm; top: 154mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid3.png" class="w-full h-full object-contain" style="transform: rotate(-22deg) scale(0.88);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">5</span></div></div></div>
</div>
</div>
</div>
<!-- PAGE 3: ships 5(2), 5(3), 6(3) — L-R-L -->
<div class="w-[210mm] h-[297mm] relative overflow-hidden mx-auto bg-white" style="break-after: page;">
<div class="absolute bottom-0 left-0 right-0 z-0">
<div class="absolute top-0 left-0 right-0 z-10" style="height: 10%; background: linear-gradient(to bottom, white, transparent);"></div>
<img src="../../assets/footers/cabin3.jpeg" class="w-full" alt="">
</div>
<div class="relative z-10 w-full h-full px-[12mm] pt-[1mm] pb-[65mm] flex flex-col">
<div class="flex items-center gap-2 mb-1 flex-row-reverse">
<img src="../../assets/hero-images/splitters/splitter3.png" class="w-[66%] shrink-0 object-contain" style="transform: scaleX(-1);" alt="">
<div class="w-[34%] shrink-0 flex flex-col items-center justify-center text-center">
<h1 class="text-2xl font-extrabold leading-tight tracking-tight text-indigo-950">Собери Астероиды</h1>
<p class="text-sm font-medium text-indigo-400 mt-0.5">Загрузи трюмы кораблей!</p>
</div>
</div>
<div class="relative flex-1">
<div class="absolute" style="left: -82mm; top: 2%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay7.png" class="w-[500px] object-contain" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 65%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">5</span></div></div></div>
<div class="absolute" style="left: 120mm; top: 30%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay8.png" class="w-[500px] min-w-[500px] object-contain" style="transform: scaleX(-1);" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 35%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">5</span></div></div></div>
<div class="absolute" style="left: -82mm; top: 58%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay9.png" class="w-[500px] object-contain" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 65%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">6</span></div></div></div>
<div class="absolute" style="left: 80mm; top: 5mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid5.png" class="w-full h-full object-contain" style="transform: rotate(-20deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">3</span></div></div></div>
<div class="absolute" style="left: 118mm; top: 5mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid11.png" class="w-full h-full object-contain" style="transform: rotate(15deg) scale(0.88);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 158mm; top: 22mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid5.png" class="w-full h-full object-contain" style="transform: rotate(-8deg) scale(1.12);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">1</span></div></div></div>
<div class="absolute" style="left: 11mm; top: 73mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid5.png" class="w-full h-full object-contain" style="transform: rotate(22deg) scale(0.92);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">1</span></div></div></div>
<div class="absolute" style="left: 72mm; top: 49mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid11.png" class="w-full h-full object-contain" style="transform: rotate(-15deg) scale(1.08);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">3</span></div></div></div>
<div class="absolute" style="left: 103mm; top: 37mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid5.png" class="w-full h-full object-contain" style="transform: rotate(10deg) scale(0.90);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 47mm; top: 81mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid5.png" class="w-full h-full object-contain" style="transform: rotate(25deg) scale(0.95);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 82mm; top: 99mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid11.png" class="w-full h-full object-contain" style="transform: rotate(-12deg) scale(1.02);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 117mm; top: 127mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid5.png" class="w-full h-full object-contain" style="transform: rotate(18deg) scale(1.10);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 52mm; top: 134mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid5.png" class="w-full h-full object-contain" style="transform: rotate(8deg) scale(0.92);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">5</span></div></div></div>
<div class="absolute" style="left: 69mm; top: 157mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid11.png" class="w-full h-full object-contain" style="transform: rotate(-22deg) scale(0.85);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
<div class="absolute" style="left: 162mm; top: 144mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid5.png" class="w-full h-full object-contain" style="transform: rotate(12deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
</div>
</div>
</div>
<!-- PAGE 4: ships 8(2), 8(3), 6(2) — R-L-R -->
<div class="w-[210mm] h-[297mm] relative overflow-hidden mx-auto bg-white" style="break-after: page;">
<div class="absolute bottom-0 left-0 right-0 z-0">
<div class="absolute top-0 left-0 right-0 z-10" style="height: 10%; background: linear-gradient(to bottom, white, transparent);"></div>
<img src="../../assets/footers/cabin4.jpeg" class="w-full" alt="">
</div>
<div class="relative z-10 w-full h-full px-[12mm] pt-[1mm] pb-[65mm] flex flex-col">
<div class="flex items-center gap-2 mb-1">
<img src="../../assets/hero-images/splitters/splitter4.png" class="w-[66%] shrink-0 object-contain" alt="">
<div class="w-[34%] shrink-0 flex flex-col items-center justify-center text-center">
<h1 class="text-2xl font-extrabold leading-tight tracking-tight text-indigo-950">Собери Астероиды</h1>
<p class="text-sm font-medium text-indigo-400 mt-0.5">Загрузи трюмы кораблей!</p>
</div>
</div>
<div class="relative flex-1">
<div class="absolute" style="left: 120mm; top: 2%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay1.png" class="w-[500px] min-w-[500px] object-contain" style="transform: scaleX(-1);" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 35%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">8</span></div></div></div>
<div class="absolute" style="left: -82mm; top: 30%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay2.png" class="w-[500px] object-contain" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 65%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">8</span></div></div></div>
<div class="absolute" style="left: 120mm; top: 58%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay3.png" class="w-[500px] min-w-[500px] object-contain" style="transform: scaleX(-1);" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 35%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">6</span></div></div></div>
<div class="absolute" style="left: -2mm; top: 13mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid2.png" class="w-full h-full object-contain" style="transform: rotate(15deg) scale(0.92);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">3</span></div></div></div>
<div class="absolute" style="left: 36mm; top: 22mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid8.png" class="w-full h-full object-contain" style="transform: rotate(-22deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">5</span></div></div></div>
<div class="absolute" style="left: 77mm; top: 25mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid2.png" class="w-full h-full object-contain" style="transform: rotate(8deg) scale(0.88);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 75mm; top: 60mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid2.png" class="w-full h-full object-contain" style="transform: rotate(-18deg) scale(1.12);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">3</span></div></div></div>
<div class="absolute" style="left: 112mm; top: 49mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid8.png" class="w-full h-full object-contain" style="transform: rotate(12deg) scale(0.90);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">3</span></div></div></div>
<div class="absolute" style="left: 110mm; top: -5mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid2.png" class="w-full h-full object-contain" style="transform: rotate(-5deg) scale(1.08);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 40mm; top: 78mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid2.png" class="w-full h-full object-contain" style="transform: rotate(22deg) scale(0.95);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 55mm; top: 113mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid8.png" class="w-full h-full object-contain" style="transform: rotate(-15deg) scale(0.85);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">5</span></div></div></div>
<div class="absolute" style="left: 82mm; top: 107mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid2.png" class="w-full h-full object-contain" style="transform: rotate(10deg) scale(1.10);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">1</span></div></div></div>
<div class="absolute" style="left: 14mm; top: 122mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid2.png" class="w-full h-full object-contain" style="transform: rotate(20deg) scale(1.02);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
<div class="absolute" style="left: 139mm; top: 76mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid8.png" class="w-full h-full object-contain" style="transform: rotate(-8deg) scale(0.92);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">1</span></div></div></div>
<div class="absolute" style="left: 74mm; top: 145mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid2.png" class="w-full h-full object-contain" style="transform: rotate(18deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
</div>
</div>
</div>
<!-- PAGE 5: ships 4(1), 4(2), 4(3) — L-R-L -->
<div class="w-[210mm] h-[297mm] relative overflow-hidden mx-auto bg-white" style="break-after: page;">
<div class="absolute bottom-0 left-0 right-0 z-0">
<div class="absolute top-0 left-0 right-0 z-10" style="height: 10%; background: linear-gradient(to bottom, white, transparent);"></div>
<img src="../../assets/footers/cabin5.jpeg" class="w-full" alt="">
</div>
<div class="relative z-10 w-full h-full px-[12mm] pt-[1mm] pb-[65mm] flex flex-col">
<div class="flex items-center gap-2 mb-1 flex-row-reverse">
<img src="../../assets/hero-images/splitters/splitter5.png" class="w-[66%] shrink-0 object-contain" style="transform: scaleX(-1);" alt="">
<div class="w-[34%] shrink-0 flex flex-col items-center justify-center text-center">
<h1 class="text-2xl font-extrabold leading-tight tracking-tight text-indigo-950">Собери Астероиды</h1>
<p class="text-sm font-medium text-indigo-400 mt-0.5">Загрузи трюмы кораблей!</p>
</div>
</div>
<div class="relative flex-1">
<div class="absolute" style="left: -82mm; top: 2%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay4.png" class="w-[500px] object-contain" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 65%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">4</span></div></div></div>
<div class="absolute" style="left: 120mm; top: 30%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay5.png" class="w-[500px] min-w-[500px] object-contain" style="transform: scaleX(-1);" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 35%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">4</span></div></div></div>
<div class="absolute" style="left: -82mm; top: 58%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay6.png" class="w-[500px] object-contain" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 65%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">4</span></div></div></div>
<div class="absolute" style="left: 50mm; top: 0mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid4.png" class="w-full h-full object-contain" style="transform: rotate(-20deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 119mm; top: 6mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid10.png" class="w-full h-full object-contain" style="transform: rotate(15deg) scale(0.88);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">1</span></div></div></div>
<div class="absolute" style="left: 162mm; top: 18mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid4.png" class="w-full h-full object-contain" style="transform: rotate(-8deg) scale(1.12);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">3</span></div></div></div>
<div class="absolute" style="left: -3mm; top: 71mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid4.png" class="w-full h-full object-contain" style="transform: rotate(22deg) scale(0.92);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">1</span></div></div></div>
<div class="absolute" style="left: 54mm; top: 42mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid10.png" class="w-full h-full object-contain" style="transform: rotate(-15deg) scale(1.08);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">1</span></div></div></div>
<div class="absolute" style="left: 90mm; top: 29mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid4.png" class="w-full h-full object-contain" style="transform: rotate(10deg) scale(0.90);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 46mm; top: 82mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid4.png" class="w-full h-full object-contain" style="transform: rotate(25deg) scale(0.95);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">5</span></div></div></div>
<div class="absolute" style="left: 85mm; top: 90mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid10.png" class="w-full h-full object-contain" style="transform: rotate(-12deg) scale(1.02);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
<div class="absolute" style="left: 149mm; top: 126mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid4.png" class="w-full h-full object-contain" style="transform: rotate(18deg) scale(1.10);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">3</span></div></div></div>
<div class="absolute" style="left: 68mm; top: 129mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid4.png" class="w-full h-full object-contain" style="transform: rotate(-22deg) scale(0.85);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">5</span></div></div></div>
<div class="absolute" style="left: 101mm; top: 148mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid4.png" class="w-full h-full object-contain" style="transform: rotate(8deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
</div>
</div>
</div>
<!-- PAGE 6: ships 10(4), 10(3), 8(3) — R-L-R -->
<div class="w-[210mm] h-[297mm] relative overflow-hidden mx-auto bg-white" style="break-after: page;">
<div class="absolute bottom-0 left-0 right-0 z-0">
<div class="absolute top-0 left-0 right-0 z-10" style="height: 10%; background: linear-gradient(to bottom, white, transparent);"></div>
<img src="../../assets/footers/cabin6.jpeg" class="w-full" alt="">
</div>
<div class="relative z-10 w-full h-full px-[12mm] pt-[1mm] pb-[65mm] flex flex-col">
<div class="flex items-center gap-2 mb-1">
<img src="../../assets/hero-images/splitters/splitter6.png" class="w-[66%] shrink-0 object-contain" alt="">
<div class="w-[34%] shrink-0 flex flex-col items-center justify-center text-center">
<h1 class="text-2xl font-extrabold leading-tight tracking-tight text-indigo-950">Собери Астероиды</h1>
<p class="text-sm font-medium text-indigo-400 mt-0.5">Загрузи трюмы кораблей!</p>
</div>
</div>
<div class="relative flex-1">
<div class="absolute" style="left: 120mm; top: 2%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay7.png" class="w-[500px] min-w-[500px] object-contain" style="transform: scaleX(-1);" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 35%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">10</span></div></div></div>
<div class="absolute" style="left: -82mm; top: 30%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay8.png" class="w-[500px] object-contain" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 65%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">10</span></div></div></div>
<div class="absolute" style="left: 120mm; top: 58%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay9.png" class="w-[500px] min-w-[500px] object-contain" style="transform: scaleX(-1);" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 35%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">8</span></div></div></div>
<div class="absolute" style="left: -3mm; top: 22mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid7.png" class="w-full h-full object-contain" style="transform: rotate(10deg) scale(0.90);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">1</span></div></div></div>
<div class="absolute" style="left: 48mm; top: 8mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid13.png" class="w-full h-full object-contain" style="transform: rotate(-18deg) scale(1.08);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 97mm; top: 6mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid7.png" class="w-full h-full object-contain" style="transform: rotate(22deg) scale(0.92);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">3</span></div></div></div>
<div class="absolute" style="left: 31mm; top: 40mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid7.png" class="w-full h-full object-contain" style="transform: rotate(-12deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 77mm; top: 34mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid13.png" class="w-full h-full object-contain" style="transform: rotate(15deg) scale(0.88);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 102mm; top: 66mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid7.png" class="w-full h-full object-contain" style="transform: rotate(-8deg) scale(1.12);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">3</span></div></div></div>
<div class="absolute" style="left: 154mm; top: 82mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid7.png" class="w-full h-full object-contain" style="transform: rotate(20deg) scale(0.95);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">5</span></div></div></div>
<div class="absolute" style="left: 68mm; top: 84mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid13.png" class="w-full h-full object-contain" style="transform: rotate(-25deg) scale(1.10);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">1</span></div></div></div>
<div class="absolute" style="left: 57mm; top: 114mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid7.png" class="w-full h-full object-contain" style="transform: rotate(5deg) scale(0.85);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">3</span></div></div></div>
<div class="absolute" style="left: 122mm; top: 88mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid7.png" class="w-full h-full object-contain" style="transform: rotate(12deg) scale(1.02);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 1mm; top: 157mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid13.png" class="w-full h-full object-contain" style="transform: rotate(-15deg) scale(0.92);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
<div class="absolute" style="left: 34mm; top: 133mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid7.png" class="w-full h-full object-contain" style="transform: rotate(18deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">5</span></div></div></div>
<div class="absolute" style="left: 89mm; top: 122mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid7.png" class="w-full h-full object-contain" style="transform: rotate(-22deg) scale(0.88);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 82mm; top: 145mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid7.png" class="w-full h-full object-contain" style="transform: rotate(8deg) scale(1.00);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
</div>
</div>
</div>
<!-- PAGE 7: ships 6(2), 9(3), 12(4) — L-R-L -->
<div class="w-[210mm] h-[297mm] relative overflow-hidden mx-auto bg-white" style="break-after: page;">
<div class="absolute bottom-0 left-0 right-0 z-0">
<div class="absolute top-0 left-0 right-0 z-10" style="height: 10%; background: linear-gradient(to bottom, white, transparent);"></div>
<img src="../../assets/footers/cabin7.jpeg" class="w-full" alt="">
</div>
<div class="relative z-10 w-full h-full px-[12mm] pt-[1mm] pb-[65mm] flex flex-col">
<div class="flex items-center gap-2 mb-1 flex-row-reverse">
<img src="../../assets/hero-images/splitters/splitter7.png" class="w-[66%] shrink-0 object-contain" style="transform: scaleX(-1);" alt="">
<div class="w-[34%] shrink-0 flex flex-col items-center justify-center text-center">
<h1 class="text-2xl font-extrabold leading-tight tracking-tight text-indigo-950">Собери Астероиды</h1>
<p class="text-sm font-medium text-indigo-400 mt-0.5">Загрузи трюмы кораблей!</p>
</div>
</div>
<div class="relative flex-1">
<div class="absolute" style="left: -82mm; top: 2%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay1.png" class="w-[500px] object-contain" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 65%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">6</span></div></div></div>
<div class="absolute" style="left: 120mm; top: 30%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay2.png" class="w-[500px] min-w-[500px] object-contain" style="transform: scaleX(-1);" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 35%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">9</span></div></div></div>
<div class="absolute" style="left: -82mm; top: 58%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay3.png" class="w-[500px] object-contain" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 65%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">12</span></div></div></div>
<div class="absolute" style="left: 59mm; top: -1mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid12.png" class="w-full h-full object-contain" style="transform: rotate(-15deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 116mm; top: 12mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid16.png" class="w-full h-full object-contain" style="transform: rotate(22deg) scale(0.88);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 151mm; top: 18mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid12.png" class="w-full h-full object-contain" style="transform: rotate(-8deg) scale(1.12);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">1</span></div></div></div>
<div class="absolute" style="left: 8mm; top: 74mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid12.png" class="w-full h-full object-contain" style="transform: rotate(12deg) scale(0.92);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">3</span></div></div></div>
<div class="absolute" style="left: 55mm; top: 45mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid16.png" class="w-full h-full object-contain" style="transform: rotate(-20deg) scale(1.08);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">5</span></div></div></div>
<div class="absolute" style="left: 90mm; top: 44mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid12.png" class="w-full h-full object-contain" style="transform: rotate(15deg) scale(0.90);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 64mm; top: 79mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid12.png" class="w-full h-full object-contain" style="transform: rotate(25deg) scale(0.95);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 94mm; top: 99mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid16.png" class="w-full h-full object-contain" style="transform: rotate(-5deg) scale(1.02);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">3</span></div></div></div>
<div class="absolute" style="left: 147mm; top: 133mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid12.png" class="w-full h-full object-contain" style="transform: rotate(18deg) scale(1.10);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">3</span></div></div></div>
<div class="absolute" style="left: 35mm; top: 96mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid12.png" class="w-full h-full object-contain" style="transform: rotate(-22deg) scale(0.85);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
<div class="absolute" style="left: 71mm; top: 127mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid16.png" class="w-full h-full object-contain" style="transform: rotate(8deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">5</span></div></div></div>
<div class="absolute" style="left: 112mm; top: 148mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid12.png" class="w-full h-full object-contain" style="transform: rotate(-10deg) scale(0.92);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">1</span></div></div></div>
</div>
</div>
</div>
<!-- PAGE 8: ships 14(3), 10(2), 16(4) — R-L-R -->
<div class="w-[210mm] h-[297mm] relative overflow-hidden mx-auto bg-white" style="break-after: page;">
<div class="absolute bottom-0 left-0 right-0 z-0">
<div class="absolute top-0 left-0 right-0 z-10" style="height: 10%; background: linear-gradient(to bottom, white, transparent);"></div>
<img src="../../assets/footers/cabin8.jpeg" class="w-full" alt="">
</div>
<div class="relative z-10 w-full h-full px-[12mm] pt-[1mm] pb-[65mm] flex flex-col">
<div class="flex items-center gap-2 mb-1">
<img src="../../assets/hero-images/splitters/splitter8.png" class="w-[66%] shrink-0 object-contain" alt="">
<div class="w-[34%] shrink-0 flex flex-col items-center justify-center text-center">
<h1 class="text-2xl font-extrabold leading-tight tracking-tight text-indigo-950">Собери Астероиды</h1>
<p class="text-sm font-medium text-indigo-400 mt-0.5">Загрузи трюмы кораблей!</p>
</div>
</div>
<div class="relative flex-1">
<div class="absolute" style="left: 120mm; top: 2%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay4.png" class="w-[500px] min-w-[500px] object-contain" style="transform: scaleX(-1);" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 35%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">14</span></div></div></div>
<div class="absolute" style="left: -82mm; top: 30%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay5.png" class="w-[500px] object-contain" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 65%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">10</span></div></div></div>
<div class="absolute" style="left: 120mm; top: 58%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay6.png" class="w-[500px] min-w-[500px] object-contain" style="transform: scaleX(-1);" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 35%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">16</span></div></div></div>
<div class="absolute" style="left: -6mm; top: 4mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid14.png" class="w-full h-full object-contain" style="transform: rotate(10deg) scale(0.90);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 8mm; top: 30mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid15.png" class="w-full h-full object-contain" style="transform: rotate(-18deg) scale(1.08);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">5</span></div></div></div>
<div class="absolute" style="left: 49mm; top: 11mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid14.png" class="w-full h-full object-contain" style="transform: rotate(22deg) scale(0.92);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">5</span></div></div></div>
<div class="absolute" style="left: 63mm; top: 44mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid14.png" class="w-full h-full object-contain" style="transform: rotate(-12deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 101mm; top: -3mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid15.png" class="w-full h-full object-contain" style="transform: rotate(15deg) scale(0.88);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
<div class="absolute" style="left: 168mm; top: 68mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid14.png" class="w-full h-full object-contain" style="transform: rotate(-8deg) scale(1.12);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">3</span></div></div></div>
<div class="absolute" style="left: 119mm; top: 79mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid14.png" class="w-full h-full object-contain" style="transform: rotate(20deg) scale(0.95);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 59mm; top: 78mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid15.png" class="w-full h-full object-contain" style="transform: rotate(-25deg) scale(1.10);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 90mm; top: 98mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid14.png" class="w-full h-full object-contain" style="transform: rotate(5deg) scale(0.85);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">5</span></div></div></div>
<div class="absolute" style="left: 70mm; top: 128mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid14.png" class="w-full h-full object-contain" style="transform: rotate(12deg) scale(1.02);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
<div class="absolute" style="left: -2mm; top: 130mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid15.png" class="w-full h-full object-contain" style="transform: rotate(-15deg) scale(0.92);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 32mm; top: 144mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid14.png" class="w-full h-full object-contain" style="transform: rotate(18deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">3</span></div></div></div>
<div class="absolute" style="left: 88mm; top: 158mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid14.png" class="w-full h-full object-contain" style="transform: rotate(-22deg) scale(0.88);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
</div>
</div>
</div>
<!-- PAGE 9: ships 5(2), 10(4), 15(5) — L-R-L -->
<div class="w-[210mm] h-[297mm] relative overflow-hidden mx-auto bg-white">
<div class="absolute bottom-0 left-0 right-0 z-0">
<div class="absolute top-0 left-0 right-0 z-10" style="height: 10%; background: linear-gradient(to bottom, white, transparent);"></div>
<img src="../../assets/footers/cabin9.jpeg" class="w-full" alt="">
</div>
<div class="relative z-10 w-full h-full px-[12mm] pt-[1mm] pb-[65mm] flex flex-col">
<div class="flex items-center gap-2 mb-1 flex-row-reverse">
<img src="../../assets/hero-images/splitters/splitter9.png" class="w-[66%] shrink-0 object-contain" style="transform: scaleX(-1);" alt="">
<div class="w-[34%] shrink-0 flex flex-col items-center justify-center text-center">
<h1 class="text-2xl font-extrabold leading-tight tracking-tight text-indigo-950">Собери Астероиды</h1>
<p class="text-sm font-medium text-indigo-400 mt-0.5">Загрузи трюмы кораблей!</p>
</div>
</div>
<div class="relative flex-1">
<div class="absolute" style="left: -82mm; top: 2%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay7.png" class="w-[500px] object-contain" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 65%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">5</span></div></div></div>
<div class="absolute" style="left: 120mm; top: 30%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay8.png" class="w-[500px] min-w-[500px] object-contain" style="transform: scaleX(-1);" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 35%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">10</span></div></div></div>
<div class="absolute" style="left: -82mm; top: 58%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay9.png" class="w-[500px] object-contain" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 65%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">15</span></div></div></div>
<div class="absolute" style="left: 31mm; top: -2mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid1.png" class="w-full h-full object-contain" style="transform: rotate(-20deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 132mm; top: 5mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid9.png" class="w-full h-full object-contain" style="transform: rotate(15deg) scale(0.88);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">3</span></div></div></div>
<div class="absolute" style="left: 162mm; top: 13mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid1.png" class="w-full h-full object-contain" style="transform: rotate(-8deg) scale(1.12);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">1</span></div></div></div>
<div class="absolute" style="left: 89mm; top: 7mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid1.png" class="w-full h-full object-contain" style="transform: rotate(22deg) scale(0.92);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 39mm; top: 59mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid9.png" class="w-full h-full object-contain" style="transform: rotate(-15deg) scale(1.08);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">3</span></div></div></div>
<div class="absolute" style="left: 68mm; top: 39mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid1.png" class="w-full h-full object-contain" style="transform: rotate(10deg) scale(0.90);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 115mm; top: 35mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid1.png" class="w-full h-full object-contain" style="transform: rotate(25deg) scale(0.95);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">1</span></div></div></div>
<div class="absolute" style="left: 1mm; top: 91mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid9.png" class="w-full h-full object-contain" style="transform: rotate(-12deg) scale(1.02);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 77mm; top: 71mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid1.png" class="w-full h-full object-contain" style="transform: rotate(18deg) scale(1.10);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">3</span></div></div></div>
<div class="absolute" style="left: 85mm; top: 114mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid1.png" class="w-full h-full object-contain" style="transform: rotate(-5deg) scale(0.85);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 131mm; top: 129mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid9.png" class="w-full h-full object-contain" style="transform: rotate(12deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">5</span></div></div></div>
<div class="absolute" style="left: 52mm; top: 110mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid1.png" class="w-full h-full object-contain" style="transform: rotate(-22deg) scale(0.92);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
<div class="absolute" style="left: 63mm; top: 155mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid1.png" class="w-full h-full object-contain" style="transform: rotate(8deg) scale(0.95);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">5</span></div></div></div>
<div class="absolute" style="left: 103mm; top: 143mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid1.png" class="w-full h-full object-contain" style="transform: rotate(20deg) scale(1.00);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 146mm; top: 157mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid1.png" class="w-full h-full object-contain" style="transform: rotate(-18deg) scale(0.88);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
</div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,35 @@
# Collecting Asteroids 2
**Title:** Собери Астероиды
**Subtitle:** Загрузи трюмы кораблей!
**Footer bubble:** Итого загружено:
## Notes
v2: reshuffled assets, doubled difficulty compared to v1.
## Layout
- 3 ships per page, 2 asteroid types per page (70:30 ratio)
- Asteroids: assets/icons/pack3-asteroids/
- Uses different splitters, cabins, cargo bays and asteroid types than v1
## Pages
### Page 1
- **Ships:** capacity 10 (fill 2), capacity 10 (fill 2), capacity 14 (fill 3)
- **Hero:** splitter5.png, direction: row
- **Cargo bays:** cargo-bay4, cargo-bay5, cargo-bay6
- **Asteroid types:** asteroid7, asteroid14
### Page 2
- **Ships:** capacity 14 (fill 3), capacity 14 (fill 3), capacity 20 (fill 4)
- **Hero:** splitter2.png, direction: row-reverse
- **Cargo bays:** cargo-bay7, cargo-bay8, cargo-bay9
- **Asteroid types:** asteroid4, asteroid11
### Page 3
- **Ships:** capacity 10 (fill 2), capacity 10 (fill 3), capacity 12 (fill 3)
- **Hero:** splitter8.png, direction: row
- **Cargo bays:** cargo-bay1, cargo-bay2, cargo-bay3
- **Asteroid types:** asteroid2, asteroid9

View File

@ -0,0 +1,347 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.tailwindcss.com"></script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700;800;900&display=swap" rel="stylesheet">
<title>Собери Астероиды</title>
<script>
tailwind.config = {
theme: {
extend: {
fontFamily: { nunito: ['Nunito', 'sans-serif'] },
}
}
}
</script>
<style>
@page { size: A4; margin: 0; }
</style>
</head>
<body class="bg-gray-200 font-nunito">
<!-- PAGE 1: ships 10(2), 10(2), 14(3) — R-L-R -->
<div class="w-[210mm] h-[297mm] relative overflow-hidden mx-auto bg-white" style="break-after: page;">
<div class="absolute bottom-0 left-0 right-0 z-0">
<div class="absolute top-0 left-0 right-0 z-10" style="height: 10%; background: linear-gradient(to bottom, white, transparent);"></div>
<img src="../../assets/footers/cabin7.jpeg" class="w-full" alt="">
</div>
<div class="relative z-10 w-full h-full px-[12mm] pt-[1mm] pb-[65mm] flex flex-col">
<div class="flex items-center gap-2 mb-1">
<img src="../../assets/hero-images/splitters/splitter5.png" class="w-[66%] shrink-0 object-contain" alt="">
<div class="w-[34%] shrink-0 flex flex-col items-center justify-center text-center">
<h1 class="text-2xl font-extrabold leading-tight tracking-tight text-indigo-950">Собери Астероиды</h1>
<p class="text-sm font-medium text-indigo-400 mt-0.5">Загрузи трюмы кораблей!</p>
</div>
</div>
<div class="relative flex-1">
<div class="absolute" style="left: 120mm; top: 2%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay4.png" class="w-[500px] min-w-[500px] object-contain" style="transform: scaleX(-1);" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 35%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">10</span></div></div></div>
<div class="absolute" style="left: -82mm; top: 30%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay5.png" class="w-[500px] object-contain" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 65%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">10</span></div></div></div>
<div class="absolute" style="left: 120mm; top: 58%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay6.png" class="w-[500px] min-w-[500px] object-contain" style="transform: scaleX(-1);" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 35%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">14</span></div></div></div>
<div class="absolute" style="left: 4mm; top: 6mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid7.png" class="w-full h-full object-contain" style="transform: rotate(33deg) scale(1.50);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
<div class="absolute" style="left: 91mm; top: 18mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid14.png" class="w-full h-full object-contain" style="transform: rotate(-12deg) scale(0.68);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 65mm; top: -5mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid7.png" class="w-full h-full object-contain" style="transform: rotate(23deg) scale(1.20);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 14mm; top: 28mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid7.png" class="w-full h-full object-contain" style="transform: rotate(18deg) scale(1.85);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">8</span></div></div></div>
<div class="absolute" style="left: 58mm; top: 59mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid14.png" class="w-full h-full object-contain" style="transform: rotate(-18deg) scale(1.12);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">10</span></div></div></div>
<div class="absolute" style="left: 160mm; top: 74mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid7.png" class="w-full h-full object-contain" style="transform: rotate(15deg) scale(1.35);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 53mm; top: 107mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid7.png" class="w-full h-full object-contain" style="transform: rotate(10deg) scale(1.57);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
<div class="absolute" style="left: 101mm; top: 76mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid14.png" class="w-full h-full object-contain" style="transform: rotate(22deg) scale(1.60);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">12</span></div></div></div>
<div class="absolute" style="left: 62mm; top: 134mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid7.png" class="w-full h-full object-contain" style="transform: rotate(0deg) scale(1.90);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">10</span></div></div></div>
<div class="absolute" style="left: 24mm; top: 117mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid7.png" class="w-full h-full object-contain" style="transform: rotate(15deg) scale(1.75);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">8</span></div></div></div>
<div class="absolute" style="left: 40mm; top: 156mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid14.png" class="w-full h-full object-contain" style="transform: rotate(-80deg) scale(0.62);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 3mm; top: 129mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid7.png" class="w-full h-full object-contain" style="transform: rotate(7deg) scale(2.00);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">12</span></div></div></div>
</div>
</div>
</div>
<!-- PAGE 2: ships 14(3), 14(3), 20(4) — L-R-L -->
<div class="w-[210mm] h-[297mm] relative overflow-hidden mx-auto bg-white" style="break-after: page;">
<div class="absolute bottom-0 left-0 right-0 z-0">
<div class="absolute top-0 left-0 right-0 z-10" style="height: 10%; background: linear-gradient(to bottom, white, transparent);"></div>
<img src="../../assets/footers/cabin4.jpeg" class="w-full" alt="">
</div>
<div class="relative z-10 w-full h-full px-[12mm] pt-[1mm] pb-[65mm] flex flex-col">
<div class="flex items-center gap-2 mb-1 flex-row-reverse">
<img src="../../assets/hero-images/splitters/splitter2.png" class="w-[66%] shrink-0 object-contain" style="transform: scaleX(-1);" alt="">
<div class="w-[34%] shrink-0 flex flex-col items-center justify-center text-center">
<h1 class="text-2xl font-extrabold leading-tight tracking-tight text-indigo-950">Собери Астероиды</h1>
<p class="text-sm font-medium text-indigo-400 mt-0.5">Загрузи трюмы кораблей!</p>
</div>
</div>
<div class="relative flex-1">
<div class="absolute" style="left: -82mm; top: 2%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay7.png" class="w-[500px] object-contain" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 65%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">14</span></div></div></div>
<div class="absolute" style="left: 120mm; top: 30%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay8.png" class="w-[500px] min-w-[500px] object-contain" style="transform: scaleX(-1);" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 35%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">14</span></div></div></div>
<div class="absolute" style="left: -82mm; top: 58%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay9.png" class="w-[500px] object-contain" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 65%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">20</span></div></div></div>
<div class="absolute" style="left: 60mm; top: -3mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid4.png" class="w-full h-full object-contain" style="transform: rotate(20deg) scale(0.95);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
<div class="absolute" style="left: 105mm; top: 10mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid11.png" class="w-full h-full object-contain" style="transform: rotate(-15deg) scale(1.08);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">8</span></div></div></div>
<div class="absolute" style="left: 150mm; top: 19mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid4.png" class="w-full h-full object-contain" style="transform: rotate(10deg) scale(0.73);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 22mm; top: 0mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid4.png" class="w-full h-full object-contain" style="transform: rotate(-63deg) scale(1.12);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">10</span></div></div></div>
<div class="absolute" style="left: 85mm; top: 82mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid11.png" class="w-full h-full object-contain" style="transform: rotate(22deg) scale(0.67);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 80mm; top: 50mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid4.png" class="w-full h-full object-contain" style="transform: rotate(-25deg) scale(1.50);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">12</span></div></div></div>
<div class="absolute" style="left: 161mm; top: 124mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid4.png" class="w-full h-full object-contain" style="transform: rotate(95deg) scale(1.00);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
<div class="absolute" style="left: 44mm; top: 75mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid11.png" class="w-full h-full object-contain" style="transform: rotate(15deg) scale(0.85);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: -5mm; top: 87mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid4.png" class="w-full h-full object-contain" style="transform: rotate(-18deg) scale(0.85);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">8</span></div></div></div>
<div class="absolute" style="left: 101mm; top: 157mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid4.png" class="w-full h-full object-contain" style="transform: rotate(12deg) scale(0.62);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 73mm; top: 120mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid11.png" class="w-full h-full object-contain" style="transform: rotate(-12deg) scale(1.42);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">10</span></div></div></div>
<div class="absolute" style="left: 140mm; top: 150mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid4.png" class="w-full h-full object-contain" style="transform: rotate(18deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
</div>
</div>
</div>
<!-- PAGE 3: ships 10(2), 10(3), 12(3) — R-L-R -->
<div class="w-[210mm] h-[297mm] relative overflow-hidden mx-auto bg-white" style="break-after: page;">
<div class="absolute bottom-0 left-0 right-0 z-0">
<div class="absolute top-0 left-0 right-0 z-10" style="height: 10%; background: linear-gradient(to bottom, white, transparent);"></div>
<img src="../../assets/footers/cabin1.jpeg" class="w-full" alt="">
</div>
<div class="relative z-10 w-full h-full px-[12mm] pt-[1mm] pb-[65mm] flex flex-col">
<div class="flex items-center gap-2 mb-1">
<img src="../../assets/hero-images/splitters/splitter8.png" class="w-[66%] shrink-0 object-contain" alt="">
<div class="w-[34%] shrink-0 flex flex-col items-center justify-center text-center">
<h1 class="text-2xl font-extrabold leading-tight tracking-tight text-indigo-950">Собери Астероиды</h1>
<p class="text-sm font-medium text-indigo-400 mt-0.5">Загрузи трюмы кораблей!</p>
</div>
</div>
<div class="relative flex-1">
<div class="absolute" style="left: 120mm; top: 2%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay1.png" class="w-[500px] min-w-[500px] object-contain" style="transform: scaleX(-1);" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 35%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">10</span></div></div></div>
<div class="absolute" style="left: -82mm; top: 30%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay2.png" class="w-[500px] object-contain" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 65%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">10</span></div></div></div>
<div class="absolute" style="left: 120mm; top: 58%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay3.png" class="w-[500px] min-w-[500px] object-contain" style="transform: scaleX(-1);" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 35%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">12</span></div></div></div>
<div class="absolute" style="left: 37mm; top: 7mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid10.png" class="w-full h-full object-contain" style="transform: rotate(-18deg) scale(0.83);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 78mm; top: 12mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid3.png" class="w-full h-full object-contain" style="transform: rotate(15deg) scale(0.90);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">8</span></div></div></div>
<div class="absolute" style="left: 109mm; top: -5mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid10.png" class="w-full h-full object-contain" style="transform: rotate(-8deg) scale(0.47);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 0mm; top: 31mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid10.png" class="w-full h-full object-contain" style="transform: rotate(22deg) scale(0.97);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
<div class="absolute" style="left: 60mm; top: 59mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid3.png" class="w-full h-full object-contain" style="transform: rotate(-20deg) scale(1.40);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">10</span></div></div></div>
<div class="absolute" style="left: 102mm; top: 42mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid10.png" class="w-full h-full object-contain" style="transform: rotate(10deg) scale(0.88);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 132mm; top: 71mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid10.png" class="w-full h-full object-contain" style="transform: rotate(25deg) scale(0.50);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 2mm; top: 128mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid3.png" class="w-full h-full object-contain" style="transform: rotate(-12deg) scale(1.02);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
<div class="absolute" style="left: 67mm; top: 98mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid10.png" class="w-full h-full object-contain" style="transform: rotate(3deg) scale(1.35);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">8</span></div></div></div>
<div class="absolute" style="left: 81mm; top: 147mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid10.png" class="w-full h-full object-contain" style="transform: rotate(-25deg) scale(1.65);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">12</span></div></div></div>
<div class="absolute" style="left: 36mm; top: 160mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid3.png" class="w-full h-full object-contain" style="transform: rotate(12deg) scale(1.45);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">10</span></div></div></div>
<div class="absolute" style="left: 109mm; top: 85mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid10.png" class="w-full h-full object-contain" style="transform: rotate(8deg) scale(0.77);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
</div>
</div>
</div>
<!-- PAGE 4: ships 16(2), 16(3), 12(2) — L-R-L -->
<div class="w-[210mm] h-[297mm] relative overflow-hidden mx-auto bg-white" style="break-after: page;">
<div class="absolute bottom-0 left-0 right-0 z-0">
<div class="absolute top-0 left-0 right-0 z-10" style="height: 10%; background: linear-gradient(to bottom, white, transparent);"></div>
<img src="../../assets/footers/cabin9.jpeg" class="w-full" alt="">
</div>
<div class="relative z-10 w-full h-full px-[12mm] pt-[1mm] pb-[65mm] flex flex-col">
<div class="flex items-center gap-2 mb-1 flex-row-reverse">
<img src="../../assets/hero-images/splitters/splitter3.png" class="w-[66%] shrink-0 object-contain" style="transform: scaleX(-1);" alt="">
<div class="w-[34%] shrink-0 flex flex-col items-center justify-center text-center">
<h1 class="text-2xl font-extrabold leading-tight tracking-tight text-indigo-950">Собери Астероиды</h1>
<p class="text-sm font-medium text-indigo-400 mt-0.5">Загрузи трюмы кораблей!</p>
</div>
</div>
<div class="relative flex-1">
<div class="absolute" style="left: -82mm; top: 2%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay4.png" class="w-[500px] object-contain" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 65%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">16</span></div></div></div>
<div class="absolute" style="left: 120mm; top: 30%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay5.png" class="w-[500px] min-w-[500px] object-contain" style="transform: scaleX(-1);" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 35%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">16</span></div></div></div>
<div class="absolute" style="left: -82mm; top: 58%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay6.png" class="w-[500px] object-contain" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 65%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">12</span></div></div></div>
<div class="absolute" style="left: 71mm; top: 3mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid16.png" class="w-full h-full object-contain" style="transform: rotate(12deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">8</span></div></div></div>
<div class="absolute" style="left: 66mm; top: 86mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid5.png" class="w-full h-full object-contain" style="transform: rotate(-22deg) scale(1.08);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
<div class="absolute" style="left: 160mm; top: 28mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid16.png" class="w-full h-full object-contain" style="transform: rotate(8deg) scale(0.88);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">10</span></div></div></div>
<div class="absolute" style="left: -10mm; top: 72mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid16.png" class="w-full h-full object-contain" style="transform: rotate(-15deg) scale(0.72);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 63mm; top: 42mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid5.png" class="w-full h-full object-contain" style="transform: rotate(20deg) scale(1.82);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">12</span></div></div></div>
<div class="absolute" style="left: 76mm; top: 73mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid16.png" class="w-full h-full object-contain" style="transform: rotate(-5deg) scale(0.40);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 149mm; top: 132mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid16.png" class="w-full h-full object-contain" style="transform: rotate(15deg) scale(0.90);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
<div class="absolute" style="left: 22mm; top: 82mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid5.png" class="w-full h-full object-contain" style="transform: rotate(-18deg) scale(1.35);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">8</span></div></div></div>
<div class="absolute" style="left: 125mm; top: 7mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid16.png" class="w-full h-full object-contain" style="transform: rotate(22deg) scale(1.40);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">12</span></div></div></div>
<div class="absolute" style="left: 103mm; top: 120mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid16.png" class="w-full h-full object-contain" style="transform: rotate(-10deg) scale(0.57);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 67mm; top: 128mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid5.png" class="w-full h-full object-contain" style="transform: rotate(10deg) scale(1.47);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">10</span></div></div></div>
<div class="absolute" style="left: 103mm; top: 155mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid16.png" class="w-full h-full object-contain" style="transform: rotate(18deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">8</span></div></div></div>
</div>
</div>
</div>
<!-- PAGE 5: ships 8(1), 8(2), 8(3) — R-L-R -->
<div class="w-[210mm] h-[297mm] relative overflow-hidden mx-auto bg-white" style="break-after: page;">
<div class="absolute bottom-0 left-0 right-0 z-0">
<div class="absolute top-0 left-0 right-0 z-10" style="height: 10%; background: linear-gradient(to bottom, white, transparent);"></div>
<img src="../../assets/footers/cabin2.jpeg" class="w-full" alt="">
</div>
<div class="relative z-10 w-full h-full px-[12mm] pt-[1mm] pb-[65mm] flex flex-col">
<div class="flex items-center gap-2 mb-1">
<img src="../../assets/hero-images/splitters/splitter9.png" class="w-[66%] shrink-0 object-contain" alt="">
<div class="w-[34%] shrink-0 flex flex-col items-center justify-center text-center">
<h1 class="text-2xl font-extrabold leading-tight tracking-tight text-indigo-950">Собери Астероиды</h1>
<p class="text-sm font-medium text-indigo-400 mt-0.5">Загрузи трюмы кораблей!</p>
</div>
</div>
<div class="relative flex-1">
<div class="absolute" style="left: 120mm; top: 2%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay7.png" class="w-[500px] min-w-[500px] object-contain" style="transform: scaleX(-1);" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 35%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">8</span></div></div></div>
<div class="absolute" style="left: -82mm; top: 30%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay8.png" class="w-[500px] object-contain" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 65%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">8</span></div></div></div>
<div class="absolute" style="left: 120mm; top: 58%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay9.png" class="w-[500px] min-w-[500px] object-contain" style="transform: scaleX(-1);" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 35%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">8</span></div></div></div>
<div class="absolute" style="left: 45mm; top: 5mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid2.png" class="w-full h-full object-contain" style="transform: rotate(-15deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
<div class="absolute" style="left: 83mm; top: 16mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid13.png" class="w-full h-full object-contain" style="transform: rotate(18deg) scale(0.53);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 27mm; top: 160mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid2.png" class="w-full h-full object-contain" style="transform: rotate(37deg) scale(1.12);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">8</span></div></div></div>
<div class="absolute" style="left: -1mm; top: 30mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid2.png" class="w-full h-full object-contain" style="transform: rotate(22deg) scale(0.92);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 66mm; top: 51mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid13.png" class="w-full h-full object-contain" style="transform: rotate(-20deg) scale(1.58);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">10</span></div></div></div>
<div class="absolute" style="left: 108mm; top: 65mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid2.png" class="w-full h-full object-contain" style="transform: rotate(10deg) scale(0.90);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 7mm; top: 126mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid2.png" class="w-full h-full object-contain" style="transform: rotate(75deg) scale(1.75);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">12</span></div></div></div>
<div class="absolute" style="left: 73mm; top: 102mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid13.png" class="w-full h-full object-contain" style="transform: rotate(-12deg) scale(0.72);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 140mm; top: 86mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid2.png" class="w-full h-full object-contain" style="transform: rotate(15deg) scale(1.10);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
<div class="absolute" style="left: 0mm; top: 6mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid2.png" class="w-full h-full object-contain" style="transform: rotate(-22deg) scale(0.85);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">8</span></div></div></div>
<div class="absolute" style="left: 83mm; top: 155mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid2.png" class="w-full h-full object-contain" style="transform: rotate(8deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">10</span></div></div></div>
</div>
</div>
</div>
<!-- PAGE 6: ships 20(4), 20(3), 16(3) — L-R-L -->
<div class="w-[210mm] h-[297mm] relative overflow-hidden mx-auto bg-white" style="break-after: page;">
<div class="absolute bottom-0 left-0 right-0 z-0">
<div class="absolute top-0 left-0 right-0 z-10" style="height: 10%; background: linear-gradient(to bottom, white, transparent);"></div>
<img src="../../assets/footers/cabin6.jpeg" class="w-full" alt="">
</div>
<div class="relative z-10 w-full h-full px-[12mm] pt-[1mm] pb-[65mm] flex flex-col">
<div class="flex items-center gap-2 mb-1 flex-row-reverse">
<img src="../../assets/hero-images/splitters/splitter1.png" class="w-[66%] shrink-0 object-contain" style="transform: scaleX(-1);" alt="">
<div class="w-[34%] shrink-0 flex flex-col items-center justify-center text-center">
<h1 class="text-2xl font-extrabold leading-tight tracking-tight text-indigo-950">Собери Астероиды</h1>
<p class="text-sm font-medium text-indigo-400 mt-0.5">Загрузи трюмы кораблей!</p>
</div>
</div>
<div class="relative flex-1">
<div class="absolute" style="left: -82mm; top: 2%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay1.png" class="w-[500px] object-contain" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 65%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">20</span></div></div></div>
<div class="absolute" style="left: 120mm; top: 30%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay2.png" class="w-[500px] min-w-[500px] object-contain" style="transform: scaleX(-1);" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 35%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">20</span></div></div></div>
<div class="absolute" style="left: -82mm; top: 58%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay3.png" class="w-[500px] object-contain" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 65%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">16</span></div></div></div>
<div class="absolute" style="left: 79mm; top: 24mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid8.png" class="w-full h-full object-contain" style="transform: rotate(65deg) scale(0.67);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 66mm; top: -5mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid12.png" class="w-full h-full object-contain" style="transform: rotate(-22deg) scale(1.08);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
<div class="absolute" style="left: 148mm; top: 18mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid8.png" class="w-full h-full object-contain" style="transform: rotate(73deg) scale(0.88);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">8</span></div></div></div>
<div class="absolute" style="left: 99mm; top: 135mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid8.png" class="w-full h-full object-contain" style="transform: rotate(-42deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">10</span></div></div></div>
<div class="absolute" style="left: 47mm; top: 59mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid12.png" class="w-full h-full object-contain" style="transform: rotate(20deg) scale(0.60);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 84mm; top: 48mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid8.png" class="w-full h-full object-contain" style="transform: rotate(40deg) scale(0.92);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
<div class="absolute" style="left: 114mm; top: 21mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid8.png" class="w-full h-full object-contain" style="transform: rotate(53deg) scale(1.60);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">12</span></div></div></div>
<div class="absolute" style="left: 16mm; top: 74mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid12.png" class="w-full h-full object-contain" style="transform: rotate(-18deg) scale(0.90);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 65mm; top: 82mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid8.png" class="w-full h-full object-contain" style="transform: rotate(10deg) scale(0.50);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 84mm; top: 82mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid8.png" class="w-full h-full object-contain" style="transform: rotate(15deg) scale(1.17);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">8</span></div></div></div>
<div class="absolute" style="left: 146mm; top: 157mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid12.png" class="w-full h-full object-contain" style="transform: rotate(22deg) scale(1.82);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">10</span></div></div></div>
<div class="absolute" style="left: 60mm; top: 108mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid8.png" class="w-full h-full object-contain" style="transform: rotate(-8deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
<div class="absolute" style="left: 81mm; top: 113mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid8.png" class="w-full h-full object-contain" style="transform: rotate(-18deg) scale(0.68);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 80mm; top: 160mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid8.png" class="w-full h-full object-contain" style="transform: rotate(-15deg) scale(1.78);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">12</span></div></div></div>
</div>
</div>
</div>
<!-- PAGE 7: ships 12(2), 18(3), 24(4) — R-L-R -->
<div class="w-[210mm] h-[297mm] relative overflow-hidden mx-auto bg-white" style="break-after: page;">
<div class="absolute bottom-0 left-0 right-0 z-0">
<div class="absolute top-0 left-0 right-0 z-10" style="height: 10%; background: linear-gradient(to bottom, white, transparent);"></div>
<img src="../../assets/footers/cabin3.jpeg" class="w-full" alt="">
</div>
<div class="relative z-10 w-full h-full px-[12mm] pt-[1mm] pb-[65mm] flex flex-col">
<div class="flex items-center gap-2 mb-1">
<img src="../../assets/hero-images/splitters/splitter6.png" class="w-[66%] shrink-0 object-contain" alt="">
<div class="w-[34%] shrink-0 flex flex-col items-center justify-center text-center">
<h1 class="text-2xl font-extrabold leading-tight tracking-tight text-indigo-950">Собери Астероиды</h1>
<p class="text-sm font-medium text-indigo-400 mt-0.5">Загрузи трюмы кораблей!</p>
</div>
</div>
<div class="relative flex-1">
<div class="absolute" style="left: 120mm; top: 2%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay4.png" class="w-[500px] min-w-[500px] object-contain" style="transform: scaleX(-1);" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 35%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">12</span></div></div></div>
<div class="absolute" style="left: -82mm; top: 30%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay5.png" class="w-[500px] object-contain" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 65%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">18</span></div></div></div>
<div class="absolute" style="left: 120mm; top: 58%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay6.png" class="w-[500px] min-w-[500px] object-contain" style="transform: scaleX(-1);" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 35%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">24</span></div></div></div>
<div class="absolute" style="left: 37mm; top: 4mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid15.png" class="w-full h-full object-contain" style="transform: rotate(-10deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
<div class="absolute" style="left: 78mm; top: -3mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid6.png" class="w-full h-full object-contain" style="transform: rotate(17deg) scale(0.68);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 112mm; top: -1mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid15.png" class="w-full h-full object-contain" style="transform: rotate(50deg) scale(0.62);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 2mm; top: 13mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid15.png" class="w-full h-full object-contain" style="transform: rotate(15deg) scale(0.92);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">10</span></div></div></div>
<div class="absolute" style="left: 68mm; top: 58mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid6.png" class="w-full h-full object-contain" style="transform: rotate(-8deg) scale(1.08);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">8</span></div></div></div>
<div class="absolute" style="left: 99mm; top: 45mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid15.png" class="w-full h-full object-contain" style="transform: rotate(-5deg) scale(0.90);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 66mm; top: 98mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid15.png" class="w-full h-full object-contain" style="transform: rotate(-55deg) scale(1.50);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">12</span></div></div></div>
<div class="absolute" style="left: 88mm; top: 78mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid6.png" class="w-full h-full object-contain" style="transform: rotate(-15deg) scale(0.87);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
<div class="absolute" style="left: 123mm; top: 81mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid15.png" class="w-full h-full object-contain" style="transform: rotate(18deg) scale(1.10);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">8</span></div></div></div>
<div class="absolute" style="left: -10mm; top: 136mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid15.png" class="w-full h-full object-contain" style="transform: rotate(-22deg) scale(0.65);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 50mm; top: 128mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid6.png" class="w-full h-full object-contain" style="transform: rotate(5deg) scale(0.92);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">10</span></div></div></div>
<div class="absolute" style="left: 84mm; top: 160mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid15.png" class="w-full h-full object-contain" style="transform: rotate(-118deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
</div>
</div>
</div>
<!-- PAGE 8: ships 28(3), 20(2), 32(4) — L-R-L -->
<div class="w-[210mm] h-[297mm] relative overflow-hidden mx-auto bg-white" style="break-after: page;">
<div class="absolute bottom-0 left-0 right-0 z-0">
<div class="absolute top-0 left-0 right-0 z-10" style="height: 10%; background: linear-gradient(to bottom, white, transparent);"></div>
<img src="../../assets/footers/cabin8.jpeg" class="w-full" alt="">
</div>
<div class="relative z-10 w-full h-full px-[12mm] pt-[1mm] pb-[65mm] flex flex-col">
<div class="flex items-center gap-2 mb-1 flex-row-reverse">
<img src="../../assets/hero-images/splitters/splitter4.png" class="w-[66%] shrink-0 object-contain" style="transform: scaleX(-1);" alt="">
<div class="w-[34%] shrink-0 flex flex-col items-center justify-center text-center">
<h1 class="text-2xl font-extrabold leading-tight tracking-tight text-indigo-950">Собери Астероиды</h1>
<p class="text-sm font-medium text-indigo-400 mt-0.5">Загрузи трюмы кораблей!</p>
</div>
</div>
<div class="relative flex-1">
<div class="absolute" style="left: -82mm; top: 2%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay7.png" class="w-[500px] object-contain" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 65%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">28</span></div></div></div>
<div class="absolute" style="left: 120mm; top: 30%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay8.png" class="w-[500px] min-w-[500px] object-contain" style="transform: scaleX(-1);" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 35%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">20</span></div></div></div>
<div class="absolute" style="left: -82mm; top: 58%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay9.png" class="w-[500px] object-contain" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 65%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">32</span></div></div></div>
<div class="absolute" style="left: 72mm; top: 13mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid9.png" class="w-full h-full object-contain" style="transform: rotate(-13deg) scale(1.80);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">10</span></div></div></div>
<div class="absolute" style="left: 166mm; top: -1mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid1.png" class="w-full h-full object-contain" style="transform: rotate(-18deg) scale(0.83);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
<div class="absolute" style="left: 47mm; top: -5mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid9.png" class="w-full h-full object-contain" style="transform: rotate(-43deg) scale(1.67);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">8</span></div></div></div>
<div class="absolute" style="left: 101mm; top: 16mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid9.png" class="w-full h-full object-contain" style="transform: rotate(3deg) scale(1.15);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 42mm; top: 52mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid1.png" class="w-full h-full object-contain" style="transform: rotate(15deg) scale(1.48);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">12</span></div></div></div>
<div class="absolute" style="left: 79mm; top: 60mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid9.png" class="w-full h-full object-contain" style="transform: rotate(-8deg) scale(0.87);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 91mm; top: 43mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid9.png" class="w-full h-full object-contain" style="transform: rotate(-5deg) scale(1.45);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
<div class="absolute" style="left: 6mm; top: 82mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid1.png" class="w-full h-full object-contain" style="transform: rotate(-25deg) scale(1.10);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">10</span></div></div></div>
<div class="absolute" style="left: 68mm; top: 87mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid9.png" class="w-full h-full object-contain" style="transform: rotate(0deg) scale(1.75);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">8</span></div></div></div>
<div class="absolute" style="left: 93mm; top: 91mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid9.png" class="w-full h-full object-contain" style="transform: rotate(3deg) scale(2.00);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">12</span></div></div></div>
<div class="absolute" style="left: 137mm; top: 133mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid1.png" class="w-full h-full object-contain" style="transform: rotate(-15deg) scale(0.62);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 74mm; top: 125mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid9.png" class="w-full h-full object-contain" style="transform: rotate(5deg) scale(1.60);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
<div class="absolute" style="left: 95mm; top: 146mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid9.png" class="w-full h-full object-contain" style="transform: rotate(-7deg) scale(1.85);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">10</span></div></div></div>
</div>
</div>
</div>
<!-- PAGE 9: ships 10(2), 20(4), 30(5) — R-L-R -->
<div class="w-[210mm] h-[297mm] relative overflow-hidden mx-auto bg-white">
<div class="absolute bottom-0 left-0 right-0 z-0">
<div class="absolute top-0 left-0 right-0 z-10" style="height: 10%; background: linear-gradient(to bottom, white, transparent);"></div>
<img src="../../assets/footers/cabin5.jpeg" class="w-full" alt="">
</div>
<div class="relative z-10 w-full h-full px-[12mm] pt-[1mm] pb-[65mm] flex flex-col">
<div class="flex items-center gap-2 mb-1">
<img src="../../assets/hero-images/splitters/splitter7.png" class="w-[66%] shrink-0 object-contain" alt="">
<div class="w-[34%] shrink-0 flex flex-col items-center justify-center text-center">
<h1 class="text-2xl font-extrabold leading-tight tracking-tight text-indigo-950">Собери Астероиды</h1>
<p class="text-sm font-medium text-indigo-400 mt-0.5">Загрузи трюмы кораблей!</p>
</div>
</div>
<div class="relative flex-1">
<div class="absolute" style="left: 120mm; top: 2%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay1.png" class="w-[500px] min-w-[500px] object-contain" style="transform: scaleX(-1);" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 35%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">10</span></div></div></div>
<div class="absolute" style="left: -82mm; top: 30%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay2.png" class="w-[500px] object-contain" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 65%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">20</span></div></div></div>
<div class="absolute" style="left: 120mm; top: 58%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay3.png" class="w-[500px] min-w-[500px] object-contain" style="transform: scaleX(-1);" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 35%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">30</span></div></div></div>
<div class="absolute" style="left: 53mm; top: 1mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid11.png" class="w-full h-full object-contain" style="transform: rotate(-20deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
<div class="absolute" style="left: 97mm; top: 9mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid4.png" class="w-full h-full object-contain" style="transform: rotate(15deg) scale(0.88);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 129mm; top: -5mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid11.png" class="w-full h-full object-contain" style="transform: rotate(-8deg) scale(0.47);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 3mm; top: 16mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid11.png" class="w-full h-full object-contain" style="transform: rotate(22deg) scale(0.92);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">8</span></div></div></div>
<div class="absolute" style="left: 74mm; top: 36mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid4.png" class="w-full h-full object-contain" style="transform: rotate(-15deg) scale(1.08);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">10</span></div></div></div>
<div class="absolute" style="left: 41mm; top: 40mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid11.png" class="w-full h-full object-contain" style="transform: rotate(10deg) scale(0.60);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 130mm; top: 56mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid11.png" class="w-full h-full object-contain" style="transform: rotate(25deg) scale(0.95);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
<div class="absolute" style="left: 61mm; top: 91mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid4.png" class="w-full h-full object-contain" style="transform: rotate(-12deg) scale(1.72);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">12</span></div></div></div>
<div class="absolute" style="left: 93mm; top: 63mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid11.png" class="w-full h-full object-contain" style="transform: rotate(18deg) scale(0.50);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 164mm; top: 86mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid11.png" class="w-full h-full object-contain" style="transform: rotate(-5deg) scale(1.15);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">8</span></div></div></div>
<div class="absolute" style="left: -5mm; top: 123mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid4.png" class="w-full h-full object-contain" style="transform: rotate(12deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
<div class="absolute" style="left: 71mm; top: 138mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid11.png" class="w-full h-full object-contain" style="transform: rotate(-22deg) scale(1.42);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">10</span></div></div></div>
<div class="absolute" style="left: 114mm; top: 96mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid11.png" class="w-full h-full object-contain" style="transform: rotate(8deg) scale(0.65);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 19mm; top: 155mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid11.png" class="w-full h-full object-contain" style="transform: rotate(20deg) scale(1.75);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">12</span></div></div></div>
<div class="absolute" style="left: 112mm; top: 158mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid11.png" class="w-full h-full object-contain" style="transform: rotate(-18deg) scale(0.88);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">8</span></div></div></div>
</div>
</div>
</div>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,36 @@
# Collecting Asteroids 3
**Title:** Собери Астероиды
**Subtitle:** Загрузи трюмы кораблей!
**Footer bubble:** Итого загружено:
## Notes
v3: reshuffled assets, halved asteroid values. Includes explicit asteroidValues per page.
## Layout
- 3 ships per page, 2 asteroid types per page (70:30 ratio)
- Asteroids: assets/icons/pack3-asteroids/
## Pages
### Page 1
- **Ships:** capacity 11 (fill 2), capacity 9 (fill 2), capacity 13 (fill 6)
- **Hero:** splitter4.png, direction: row
- **Cargo bays:** cargo-bay7, cargo-bay8, cargo-bay9
- **Asteroid types:** asteroid3, asteroid10
- **Asteroid values:** 3, 2, 1, 4, 5, 2, 3, 6, 5, 4, 1, 6
### Page 2
- **Ships:** capacity 12 (fill 3), capacity 12 (fill 3), capacity 18 (fill 4)
- **Hero:** splitter7.png, direction: row-reverse
- **Cargo bays:** cargo-bay1, cargo-bay2, cargo-bay3
- **Asteroid types:** asteroid6, asteroid13
- **Asteroid values:** 4, 5, 3, 6, 2, 7, 4, 3, 5, 2, 6, 4
### Page 3
- **Ships:** capacity 9 (fill 5), capacity 9 (fill 5), capacity 11 (fill 2)
- **Hero:** splitter1.png, direction: row
- **Cargo bays:** cargo-bay4, cargo-bay5, cargo-bay6
- **Asteroid types:** asteroid1, asteroid8

View File

@ -0,0 +1,347 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.tailwindcss.com"></script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700;800;900&display=swap" rel="stylesheet">
<title>Собери Астероиды</title>
<script>
tailwind.config = {
theme: {
extend: {
fontFamily: { nunito: ['Nunito', 'sans-serif'] },
}
}
}
</script>
<style>
@page { size: A4; margin: 0; }
</style>
</head>
<body class="bg-gray-200 font-nunito">
<!-- PAGE 1: ships 11(2), 9(2), 13(6) — R-L-R -->
<div class="w-[210mm] h-[297mm] relative overflow-hidden mx-auto bg-white" style="break-after: page;">
<div class="absolute bottom-0 left-0 right-0 z-0">
<div class="absolute top-0 left-0 right-0 z-10" style="height: 10%; background: linear-gradient(to bottom, white, transparent);"></div>
<img src="../../assets/footers/cabin3.jpeg" class="w-full" alt="">
</div>
<div class="relative z-10 w-full h-full px-[12mm] pt-[1mm] pb-[65mm] flex flex-col">
<div class="flex items-center gap-2 mb-1">
<img src="../../assets/hero-images/splitters/splitter4.png" class="w-[66%] shrink-0 object-contain" alt="">
<div class="w-[34%] shrink-0 flex flex-col items-center justify-center text-center">
<h1 class="text-2xl font-extrabold leading-tight tracking-tight text-indigo-950">Собери Астероиды</h1>
<p class="text-sm font-medium text-indigo-400 mt-0.5">Загрузи трюмы кораблей!</p>
</div>
</div>
<div class="relative flex-1">
<div class="absolute" style="left: 120mm; top: 2%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay7.png" class="w-[500px] min-w-[500px] object-contain" style="transform: scaleX(-1);" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 28%; top: 54%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">10</span></div></div></div>
<div class="absolute" style="left: -82mm; top: 30%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay8.png" class="w-[500px] object-contain" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 72%; top: 44%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">11</span></div></div></div>
<div class="absolute" style="left: 120mm; top: 58%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay9.png" class="w-[500px] min-w-[500px] object-contain" style="transform: scaleX(-1);" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 26%; top: 46%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">12</span></div></div></div>
<div class="absolute" style="left: 149mm; top: 78mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid3.png" class="w-full h-full object-contain" style="transform: rotate(33deg) scale(0.75);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">3</span></div></div></div>
<div class="absolute" style="left: 81mm; top: 26mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid10.png" class="w-full h-full object-contain" style="transform: rotate(-12deg) scale(0.60);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 64mm; top: 52mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid3.png" class="w-full h-full object-contain" style="transform: rotate(23deg) scale(0.60);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 14mm; top: 28mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid3.png" class="w-full h-full object-contain" style="transform: rotate(18deg) scale(0.90);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 50mm; top: 9mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid10.png" class="w-full h-full object-contain" style="transform: rotate(-18deg) scale(0.90);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 87mm; top: -2mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid3.png" class="w-full h-full object-contain" style="transform: rotate(15deg) scale(0.60);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 82mm; top: 105mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid3.png" class="w-full h-full object-contain" style="transform: rotate(10deg) scale(0.90);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 93mm; top: 60mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid10.png" class="w-full h-full object-contain" style="transform: rotate(22deg) scale(1.20);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
<div class="absolute" style="left: 66mm; top: 142mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid3.png" class="w-full h-full object-contain" style="transform: rotate(0deg) scale(1.20);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
<div class="absolute" style="left: 129mm; top: -5mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid3.png" class="w-full h-full object-contain" style="transform: rotate(15deg) scale(0.90);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 45mm; top: 117mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid10.png" class="w-full h-full object-contain" style="transform: rotate(-80deg) scale(0.60);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 6mm; top: 123mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid3.png" class="w-full h-full object-contain" style="transform: rotate(7deg) scale(1.20);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
</div>
</div>
</div>
<!-- PAGE 2: ships 12(3), 12(3), 18(4) — L-R-L -->
<div class="w-[210mm] h-[297mm] relative overflow-hidden mx-auto bg-white" style="break-after: page;">
<div class="absolute bottom-0 left-0 right-0 z-0">
<div class="absolute top-0 left-0 right-0 z-10" style="height: 10%; background: linear-gradient(to bottom, white, transparent);"></div>
<img src="../../assets/footers/cabin6.jpeg" class="w-full" alt="">
</div>
<div class="relative z-10 w-full h-full px-[12mm] pt-[1mm] pb-[65mm] flex flex-col">
<div class="flex items-center gap-2 mb-1 flex-row-reverse">
<img src="../../assets/hero-images/splitters/splitter7.png" class="w-[66%] shrink-0 object-contain" style="transform: scaleX(-1);" alt="">
<div class="w-[34%] shrink-0 flex flex-col items-center justify-center text-center">
<h1 class="text-2xl font-extrabold leading-tight tracking-tight text-indigo-950">Собери Астероиды</h1>
<p class="text-sm font-medium text-indigo-400 mt-0.5">Загрузи трюмы кораблей!</p>
</div>
</div>
<div class="relative flex-1">
<div class="absolute" style="left: -82mm; top: 2%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay1.png" class="w-[500px] object-contain" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 62%; top: 40%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">12</span></div></div></div>
<div class="absolute" style="left: 120mm; top: 30%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay2.png" class="w-[500px] min-w-[500px] object-contain" style="transform: scaleX(-1);" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 28%; top: 39%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">12</span></div></div></div>
<div class="absolute" style="left: -82mm; top: 58%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay3.png" class="w-[500px] object-contain" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 73%; top: 51%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">18</span></div></div></div>
<div class="absolute" style="left: 72mm; top: -5mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid6.png" class="w-full h-full object-contain" style="transform: rotate(20deg) scale(0.90);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 105mm; top: 10mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid13.png" class="w-full h-full object-contain" style="transform: rotate(-15deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">5</span></div></div></div>
<div class="absolute" style="left: 150mm; top: 19mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid6.png" class="w-full h-full object-contain" style="transform: rotate(10deg) scale(0.75);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">3</span></div></div></div>
<div class="absolute" style="left: 52mm; top: 30mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid6.png" class="w-full h-full object-contain" style="transform: rotate(-63deg) scale(1.20);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
<div class="absolute" style="left: 85mm; top: 82mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid13.png" class="w-full h-full object-contain" style="transform: rotate(22deg) scale(0.60);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 86mm; top: 51mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid6.png" class="w-full h-full object-contain" style="transform: rotate(-25deg) scale(1.35);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">7</span></div></div></div>
<div class="absolute" style="left: 164mm; top: 127mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid6.png" class="w-full h-full object-contain" style="transform: rotate(95deg) scale(0.90);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 44mm; top: 75mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid13.png" class="w-full h-full object-contain" style="transform: rotate(15deg) scale(0.75);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">3</span></div></div></div>
<div class="absolute" style="left: -5mm; top: 87mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid6.png" class="w-full h-full object-contain" style="transform: rotate(-18deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">5</span></div></div></div>
<div class="absolute" style="left: 108mm; top: 152mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid6.png" class="w-full h-full object-contain" style="transform: rotate(12deg) scale(0.60);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 73mm; top: 120mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid13.png" class="w-full h-full object-contain" style="transform: rotate(-12deg) scale(1.20);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
<div class="absolute" style="left: 136mm; top: 154mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid6.png" class="w-full h-full object-contain" style="transform: rotate(18deg) scale(0.90);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
</div>
</div>
</div>
<!-- PAGE 3: ships 9(5), 11(3), 11(2) — R-L-R -->
<div class="w-[210mm] h-[297mm] relative overflow-hidden mx-auto bg-white" style="break-after: page;">
<div class="absolute bottom-0 left-0 right-0 z-0">
<div class="absolute top-0 left-0 right-0 z-10" style="height: 10%; background: linear-gradient(to bottom, white, transparent);"></div>
<img src="../../assets/footers/cabin9.jpeg" class="w-full" alt="">
</div>
<div class="relative z-10 w-full h-full px-[12mm] pt-[1mm] pb-[65mm] flex flex-col">
<div class="flex items-center gap-2 mb-1">
<img src="../../assets/hero-images/splitters/splitter1.png" class="w-[66%] shrink-0 object-contain" alt="">
<div class="w-[34%] shrink-0 flex flex-col items-center justify-center text-center">
<h1 class="text-2xl font-extrabold leading-tight tracking-tight text-indigo-950">Собери Астероиды</h1>
<p class="text-sm font-medium text-indigo-400 mt-0.5">Загрузи трюмы кораблей!</p>
</div>
</div>
<div class="relative flex-1">
<div class="absolute" style="left: 120mm; top: 2%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay4.png" class="w-[500px] min-w-[500px] object-contain" style="transform: scaleX(-1);" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 28%; top: 34%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">7</span></div></div></div>
<div class="absolute" style="left: -82mm; top: 30%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay5.png" class="w-[500px] object-contain" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 75%; top: 47%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">5</span></div></div></div>
<div class="absolute" style="left: 120mm; top: 58%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay6.png" class="w-[500px] min-w-[500px] object-contain" style="transform: scaleX(-1);" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 22%; top: 39%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">6</span></div></div></div>
<div class="absolute" style="left: 38mm; top: 8mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid2.png" class="w-full h-full object-contain" style="transform: rotate(-13deg) scale(0.90);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 76mm; top: 10mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid8.png" class="w-full h-full object-contain" style="transform: rotate(15deg) scale(1.50);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">8</span></div></div></div>
<div class="absolute" style="left: 109mm; top: -5mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid2.png" class="w-full h-full object-contain" style="transform: rotate(-8deg) scale(0.75);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">3</span></div></div></div>
<div class="absolute" style="left: -4mm; top: 25mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid2.png" class="w-full h-full object-contain" style="transform: rotate(22deg) scale(1.65);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">9</span></div></div></div>
<div class="absolute" style="left: 64mm; top: 56mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid8.png" class="w-full h-full object-contain" style="transform: rotate(-20deg) scale(1.80);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">10</span></div></div></div>
<div class="absolute" style="left: 97mm; top: 49mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid2.png" class="w-full h-full object-contain" style="transform: rotate(10deg) scale(0.60);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 175mm; top: 78mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid2.png" class="w-full h-full object-contain" style="transform: rotate(25deg) scale(2.10);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">12</span></div></div></div>
<div class="absolute" style="left: -10mm; top: 124mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid8.png" class="w-full h-full object-contain" style="transform: rotate(-12deg) scale(0.60);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 48mm; top: 113mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid2.png" class="w-full h-full object-contain" style="transform: rotate(3deg) scale(0.90);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 65mm; top: 151mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid2.png" class="w-full h-full object-contain" style="transform: rotate(-25deg) scale(1.80);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">10</span></div></div></div>
<div class="absolute" style="left: 18mm; top: 144mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid8.png" class="w-full h-full object-contain" style="transform: rotate(17deg) scale(1.50);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">8</span></div></div></div>
<div class="absolute" style="left: 106mm; top: 86mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid2.png" class="w-full h-full object-contain" style="transform: rotate(13deg) scale(0.75);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">3</span></div></div></div>
</div>
</div>
</div>
<!-- PAGE 4: ships 15(4), 17(5), 11(2) — L-R-L -->
<div class="w-[210mm] h-[297mm] relative overflow-hidden mx-auto bg-white" style="break-after: page;">
<div class="absolute bottom-0 left-0 right-0 z-0">
<div class="absolute top-0 left-0 right-0 z-10" style="height: 10%; background: linear-gradient(to bottom, white, transparent);"></div>
<img src="../../assets/footers/cabin2.jpeg" class="w-full" alt="">
</div>
<div class="relative z-10 w-full h-full px-[12mm] pt-[1mm] pb-[65mm] flex flex-col">
<div class="flex items-center gap-2 mb-1 flex-row-reverse">
<img src="../../assets/hero-images/splitters/splitter6.png" class="w-[66%] shrink-0 object-contain" style="transform: scaleX(-1);" alt="">
<div class="w-[34%] shrink-0 flex flex-col items-center justify-center text-center">
<h1 class="text-2xl font-extrabold leading-tight tracking-tight text-indigo-950">Собери Астероиды</h1>
<p class="text-sm font-medium text-indigo-400 mt-0.5">Загрузи трюмы кораблей!</p>
</div>
</div>
<div class="relative flex-1">
<div class="absolute" style="left: -82mm; top: 2%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay7.png" class="w-[500px] object-contain" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 71%; top: 55%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">15</span></div></div></div>
<div class="absolute" style="left: 120mm; top: 30%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay8.png" class="w-[500px] min-w-[500px] object-contain" style="transform: scaleX(-1);" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 28%; top: 43%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">10</span></div></div></div>
<div class="absolute" style="left: -82mm; top: 58%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay9.png" class="w-[500px] object-contain" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 76%; top: 49%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">25</span></div></div></div>
<div class="absolute" style="left: 64mm; top: 2mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid12.png" class="w-full h-full object-contain" style="transform: rotate(-68deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">5</span></div></div></div>
<div class="absolute" style="left: 58mm; top: 88mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid15.png" class="w-full h-full object-contain" style="transform: rotate(-22deg) scale(0.75);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">3</span></div></div></div>
<div class="absolute" style="left: 160mm; top: 28mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid12.png" class="w-full h-full object-contain" style="transform: rotate(8deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">5</span></div></div></div>
<div class="absolute" style="left: -10mm; top: 76mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid12.png" class="w-full h-full object-contain" style="transform: rotate(-15deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">5</span></div></div></div>
<div class="absolute" style="left: 63mm; top: 42mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid15.png" class="w-full h-full object-contain" style="transform: rotate(20deg) scale(0.75);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">3</span></div></div></div>
<div class="absolute" style="left: 82mm; top: 71mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid12.png" class="w-full h-full object-contain" style="transform: rotate(-5deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">5</span></div></div></div>
<div class="absolute" style="left: 149mm; top: 132mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid12.png" class="w-full h-full object-contain" style="transform: rotate(15deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">5</span></div></div></div>
<div class="absolute" style="left: 22mm; top: 82mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid15.png" class="w-full h-full object-contain" style="transform: rotate(-18deg) scale(0.60);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 121mm; top: 7mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid12.png" class="w-full h-full object-contain" style="transform: rotate(22deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">5</span></div></div></div>
<div class="absolute" style="left: 103mm; top: 120mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid12.png" class="w-full h-full object-contain" style="transform: rotate(-10deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">5</span></div></div></div>
<div class="absolute" style="left: 62mm; top: 130mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid15.png" class="w-full h-full object-contain" style="transform: rotate(10deg) scale(0.60);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 103mm; top: 155mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid12.png" class="w-full h-full object-contain" style="transform: rotate(18deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">5</span></div></div></div>
</div>
</div>
</div>
<!-- PAGE 5: ships 7(2), 9(4), 7(2) — R-L-R -->
<div class="w-[210mm] h-[297mm] relative overflow-hidden mx-auto bg-white" style="break-after: page;">
<div class="absolute bottom-0 left-0 right-0 z-0">
<div class="absolute top-0 left-0 right-0 z-10" style="height: 10%; background: linear-gradient(to bottom, white, transparent);"></div>
<img src="../../assets/footers/cabin5.jpeg" class="w-full" alt="">
</div>
<div class="relative z-10 w-full h-full px-[12mm] pt-[1mm] pb-[65mm] flex flex-col">
<div class="flex items-center gap-2 mb-1">
<img src="../../assets/hero-images/splitters/splitter2.png" class="w-[66%] shrink-0 object-contain" alt="">
<div class="w-[34%] shrink-0 flex flex-col items-center justify-center text-center">
<h1 class="text-2xl font-extrabold leading-tight tracking-tight text-indigo-950">Собери Астероиды</h1>
<p class="text-sm font-medium text-indigo-400 mt-0.5">Загрузи трюмы кораблей!</p>
</div>
</div>
<div class="relative flex-1">
<div class="absolute" style="left: 120mm; top: 2%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay1.png" class="w-[500px] min-w-[500px] object-contain" style="transform: scaleX(-1);" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 37%; top: 38%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">13</span></div></div></div>
<div class="absolute" style="left: -82mm; top: 30%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay2.png" class="w-[500px] object-contain" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 71%; top: 41%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">11</span></div></div></div>
<div class="absolute" style="left: 120mm; top: 58%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay3.png" class="w-[500px] min-w-[500px] object-contain" style="transform: scaleX(-1);" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 23%; top: 47%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">15</span></div></div></div>
<div class="absolute" style="left: 45mm; top: 5mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid1.png" class="w-full h-full object-contain" style="transform: rotate(-15deg) scale(0.60);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 64mm; top: 62mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid9.png" class="w-full h-full object-contain" style="transform: rotate(3deg) scale(0.85);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">1</span></div></div></div>
<div class="absolute" style="left: 27mm; top: 160mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid1.png" class="w-full h-full object-contain" style="transform: rotate(37deg) scale(0.90);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: -1mm; top: 32mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid1.png" class="w-full h-full object-contain" style="transform: rotate(22deg) scale(0.60);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 82mm; top: 16mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid9.png" class="w-full h-full object-contain" style="transform: rotate(-20deg) scale(1.15);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">3</span></div></div></div>
<div class="absolute" style="left: 108mm; top: 65mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid1.png" class="w-full h-full object-contain" style="transform: rotate(10deg) scale(0.60);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 7mm; top: 126mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid1.png" class="w-full h-full object-contain" style="transform: rotate(75deg) scale(1.20);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
<div class="absolute" style="left: 71mm; top: 104mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid9.png" class="w-full h-full object-contain" style="transform: rotate(-12deg) scale(1.45);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">5</span></div></div></div>
<div class="absolute" style="left: 145mm; top: 86mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid1.png" class="w-full h-full object-contain" style="transform: rotate(15deg) scale(1.20);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
<div class="absolute" style="left: 3mm; top: 4mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid1.png" class="w-full h-full object-contain" style="transform: rotate(-22deg) scale(1.20);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
<div class="absolute" style="left: 80mm; top: 154mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid1.png" class="w-full h-full object-contain" style="transform: rotate(8deg) scale(0.90);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
</div>
</div>
</div>
<!-- PAGE 6: ships 18(4), 18(5), 14(3) — L-R-L -->
<div class="w-[210mm] h-[297mm] relative overflow-hidden mx-auto bg-white" style="break-after: page;">
<div class="absolute bottom-0 left-0 right-0 z-0">
<div class="absolute top-0 left-0 right-0 z-10" style="height: 10%; background: linear-gradient(to bottom, white, transparent);"></div>
<img src="../../assets/footers/cabin7.jpeg" class="w-full" alt="">
</div>
<div class="relative z-10 w-full h-full px-[12mm] pt-[1mm] pb-[65mm] flex flex-col">
<div class="flex items-center gap-2 mb-1 flex-row-reverse">
<img src="../../assets/hero-images/splitters/splitter8.png" class="w-[66%] shrink-0 object-contain" style="transform: scaleX(-1);" alt="">
<div class="w-[34%] shrink-0 flex flex-col items-center justify-center text-center">
<h1 class="text-2xl font-extrabold leading-tight tracking-tight text-indigo-950">Собери Астероиды</h1>
<p class="text-sm font-medium text-indigo-400 mt-0.5">Загрузи трюмы кораблей!</p>
</div>
</div>
<div class="relative flex-1">
<div class="absolute" style="left: -82mm; top: 2%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay4.png" class="w-[500px] object-contain" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 65%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">18</span></div></div></div>
<div class="absolute" style="left: 120mm; top: 30%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay5.png" class="w-[500px] min-w-[500px] object-contain" style="transform: scaleX(-1);" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 35%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">18</span></div></div></div>
<div class="absolute" style="left: -82mm; top: 58%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay6.png" class="w-[500px] object-contain" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 65%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">14</span></div></div></div>
<div class="absolute" style="left: 79mm; top: 24mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid5.png" class="w-full h-full object-contain" style="transform: rotate(65deg) scale(0.60);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 65mm; top: -5mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid16.png" class="w-full h-full object-contain" style="transform: rotate(-22deg) scale(1.35);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">7</span></div></div></div>
<div class="absolute" style="left: 148mm; top: 18mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid5.png" class="w-full h-full object-contain" style="transform: rotate(73deg) scale(1.20);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
<div class="absolute" style="left: 99mm; top: 135mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid5.png" class="w-full h-full object-contain" style="transform: rotate(-42deg) scale(1.20);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
<div class="absolute" style="left: 47mm; top: 59mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid16.png" class="w-full h-full object-contain" style="transform: rotate(20deg) scale(0.45);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">1</span></div></div></div>
<div class="absolute" style="left: 84mm; top: 48mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid5.png" class="w-full h-full object-contain" style="transform: rotate(40deg) scale(0.90);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 114mm; top: 21mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid5.png" class="w-full h-full object-contain" style="transform: rotate(53deg) scale(1.20);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
<div class="absolute" style="left: 7mm; top: 80mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid16.png" class="w-full h-full object-contain" style="transform: rotate(-18deg) scale(0.75);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">3</span></div></div></div>
<div class="absolute" style="left: 65mm; top: 82mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid5.png" class="w-full h-full object-contain" style="transform: rotate(10deg) scale(0.60);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 84mm; top: 82mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid5.png" class="w-full h-full object-contain" style="transform: rotate(15deg) scale(0.90);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 146mm; top: 157mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid16.png" class="w-full h-full object-contain" style="transform: rotate(22deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">5</span></div></div></div>
<div class="absolute" style="left: 60mm; top: 108mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid5.png" class="w-full h-full object-contain" style="transform: rotate(-8deg) scale(0.90);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 81mm; top: 113mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid5.png" class="w-full h-full object-contain" style="transform: rotate(-18deg) scale(0.60);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 80mm; top: 160mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid5.png" class="w-full h-full object-contain" style="transform: rotate(-15deg) scale(1.20);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
</div>
</div>
</div>
<!-- PAGE 7: ships 10(2), 16(3), 22(6) — R-L-R -->
<div class="w-[210mm] h-[297mm] relative overflow-hidden mx-auto bg-white" style="break-after: page;">
<div class="absolute bottom-0 left-0 right-0 z-0">
<div class="absolute top-0 left-0 right-0 z-10" style="height: 10%; background: linear-gradient(to bottom, white, transparent);"></div>
<img src="../../assets/footers/cabin4.jpeg" class="w-full" alt="">
</div>
<div class="relative z-10 w-full h-full px-[12mm] pt-[1mm] pb-[65mm] flex flex-col">
<div class="flex items-center gap-2 mb-1">
<img src="../../assets/hero-images/splitters/splitter9.png" class="w-[66%] shrink-0 object-contain" alt="">
<div class="w-[34%] shrink-0 flex flex-col items-center justify-center text-center">
<h1 class="text-2xl font-extrabold leading-tight tracking-tight text-indigo-950">Собери Астероиды</h1>
<p class="text-sm font-medium text-indigo-400 mt-0.5">Загрузи трюмы кораблей!</p>
</div>
</div>
<div class="relative flex-1">
<div class="absolute" style="left: 120mm; top: 2%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay7.png" class="w-[500px] min-w-[500px] object-contain" style="transform: scaleX(-1);" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 29%; top: 51%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">25</span></div></div></div>
<div class="absolute" style="left: -82mm; top: 30%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay8.png" class="w-[500px] object-contain" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 71%; top: 45%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">21</span></div></div></div>
<div class="absolute" style="left: 120mm; top: 58%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay9.png" class="w-[500px] min-w-[500px] object-contain" style="transform: scaleX(-1);" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 23%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">32</span></div></div></div>
<div class="absolute" style="left: 37mm; top: 4mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid11.png" class="w-full h-full object-contain" style="transform: rotate(-10deg) scale(0.90);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 78mm; top: -3mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid7.png" class="w-full h-full object-contain" style="transform: rotate(17deg) scale(2.30);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">8</span></div></div></div>
<div class="absolute" style="left: 112mm; top: -1mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid11.png" class="w-full h-full object-contain" style="transform: rotate(50deg) scale(0.60);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 2mm; top: 13mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid11.png" class="w-full h-full object-contain" style="transform: rotate(15deg) scale(1.50);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">8</span></div></div></div>
<div class="absolute" style="left: 65mm; top: 34mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid7.png" class="w-full h-full object-contain" style="transform: rotate(-8deg) scale(2.75);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">11</span></div></div></div>
<div class="absolute" style="left: 99mm; top: 45mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid11.png" class="w-full h-full object-contain" style="transform: rotate(-5deg) scale(0.75);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">3</span></div></div></div>
<div class="absolute" style="left: 72mm; top: 107mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid11.png" class="w-full h-full object-contain" style="transform: rotate(-55deg) scale(1.35);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">7</span></div></div></div>
<div class="absolute" style="left: 78mm; top: 71mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid7.png" class="w-full h-full object-contain" style="transform: rotate(-15deg) scale(2.60);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">10</span></div></div></div>
<div class="absolute" style="left: 132mm; top: 81mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid11.png" class="w-full h-full object-contain" style="transform: rotate(18deg) scale(1.20);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
<div class="absolute" style="left: -10mm; top: 140mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid11.png" class="w-full h-full object-contain" style="transform: rotate(-22deg) scale(0.90);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 38mm; top: 130mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid7.png" class="w-full h-full object-contain" style="transform: rotate(5deg) scale(3.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">13</span></div></div></div>
<div class="absolute" style="left: 88mm; top: 155mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid11.png" class="w-full h-full object-contain" style="transform: rotate(-118deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">5</span></div></div></div>
</div>
</div>
</div>
<!-- PAGE 8: ships 26(0), 18(0), 30(0) — UNSOLVABLE — L-R-L -->
<div class="w-[210mm] h-[297mm] relative overflow-hidden mx-auto bg-white" style="break-after: page;">
<div class="absolute bottom-0 left-0 right-0 z-0">
<div class="absolute top-0 left-0 right-0 z-10" style="height: 10%; background: linear-gradient(to bottom, white, transparent);"></div>
<img src="../../assets/footers/cabin1.jpeg" class="w-full" alt="">
</div>
<div class="relative z-10 w-full h-full px-[12mm] pt-[1mm] pb-[65mm] flex flex-col">
<div class="flex items-center gap-2 mb-1 flex-row-reverse">
<img src="../../assets/hero-images/splitters/splitter5.png" class="w-[66%] shrink-0 object-contain" style="transform: scaleX(-1);" alt="">
<div class="w-[34%] shrink-0 flex flex-col items-center justify-center text-center">
<h1 class="text-2xl font-extrabold leading-tight tracking-tight text-indigo-950">Собери Астероиды</h1>
<p class="text-sm font-medium text-indigo-400 mt-0.5">Загрузи трюмы кораблей!</p>
</div>
</div>
<div class="relative flex-1">
<div class="absolute" style="left: -82mm; top: 2%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay1.png" class="w-[500px] object-contain" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 65%; top: 35%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">26</span></div></div></div>
<div class="absolute" style="left: 120mm; top: 30%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay2.png" class="w-[500px] min-w-[500px] object-contain" style="transform: scaleX(-1);" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 29%; top: 39%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">28</span></div></div></div>
<div class="absolute" style="left: -82mm; top: 58%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay3.png" class="w-[500px] object-contain" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 74%; top: 51%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">30</span></div></div></div>
<div class="absolute" style="left: 70mm; top: 13mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid14.png" class="w-full h-full object-contain" style="transform: rotate(-13deg) scale(1.50);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">8</span></div></div></div>
<div class="absolute" style="left: 172mm; top: 7mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid4.png" class="w-full h-full object-contain" style="transform: rotate(-38deg) scale(1.80);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">10</span></div></div></div>
<div class="absolute" style="left: 36mm; top: -5mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid14.png" class="w-full h-full object-contain" style="transform: rotate(-43deg) scale(1.35);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">7</span></div></div></div>
<div class="absolute" style="left: 108mm; top: 10mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid14.png" class="w-full h-full object-contain" style="transform: rotate(-12deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">5</span></div></div></div>
<div class="absolute" style="left: 41mm; top: 50mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid4.png" class="w-full h-full object-contain" style="transform: rotate(15deg) scale(1.50);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">8</span></div></div></div>
<div class="absolute" style="left: 78mm; top: 63mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid14.png" class="w-full h-full object-contain" style="transform: rotate(-8deg) scale(0.75);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">3</span></div></div></div>
<div class="absolute" style="left: 97mm; top: 41mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid14.png" class="w-full h-full object-contain" style="transform: rotate(-30deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">5</span></div></div></div>
<div class="absolute" style="left: -5mm; top: 83mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid4.png" class="w-full h-full object-contain" style="transform: rotate(-25deg) scale(1.80);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">10</span></div></div></div>
<div class="absolute" style="left: 56mm; top: 88mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid14.png" class="w-full h-full object-contain" style="transform: rotate(-35deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">5</span></div></div></div>
<div class="absolute" style="left: 102mm; top: 100mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid14.png" class="w-full h-full object-contain" style="transform: rotate(3deg) scale(1.35);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">7</span></div></div></div>
<div class="absolute" style="left: 147mm; top: 142mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid4.png" class="w-full h-full object-contain" style="transform: rotate(20deg) scale(1.80);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">10</span></div></div></div>
<div class="absolute" style="left: 59mm; top: 132mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid14.png" class="w-full h-full object-contain" style="transform: rotate(5deg) scale(1.35);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">7</span></div></div></div>
<div class="absolute" style="left: 95mm; top: 146mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid14.png" class="w-full h-full object-contain" style="transform: rotate(-7deg) scale(1.20);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
</div>
</div>
</div>
<!-- PAGE 9: ships 8(2), 18(3), 28(8) — R-L-R -->
<div class="w-[210mm] h-[297mm] relative overflow-hidden mx-auto bg-white">
<div class="absolute bottom-0 left-0 right-0 z-0">
<div class="absolute top-0 left-0 right-0 z-10" style="height: 10%; background: linear-gradient(to bottom, white, transparent);"></div>
<img src="../../assets/footers/cabin8.jpeg" class="w-full" alt="">
</div>
<div class="relative z-10 w-full h-full px-[12mm] pt-[1mm] pb-[65mm] flex flex-col">
<div class="flex items-center gap-2 mb-1">
<img src="../../assets/hero-images/splitters/splitter3.png" class="w-[66%] shrink-0 object-contain" alt="">
<div class="w-[34%] shrink-0 flex flex-col items-center justify-center text-center">
<h1 class="text-2xl font-extrabold leading-tight tracking-tight text-indigo-950">Собери Астероиды</h1>
<p class="text-sm font-medium text-indigo-400 mt-0.5">Загрузи трюмы кораблей!</p>
</div>
</div>
<div class="relative flex-1">
<div class="absolute" style="left: 120mm; top: 2%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay4.png" class="w-[500px] min-w-[500px] object-contain" style="transform: scaleX(-1);" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 27%; top: 33%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">26</span></div></div></div>
<div class="absolute" style="left: -82mm; top: 30%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay5.png" class="w-[500px] object-contain" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 65%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">18</span></div></div></div>
<div class="absolute" style="left: 120mm; top: 58%;"><div class="relative"><img src="../../assets/icons/pack4-cargobay/cargo-bay6.png" class="w-[500px] min-w-[500px] object-contain" style="transform: scaleX(-1);" alt=""><div class="absolute w-12 h-12 rounded-full bg-indigo-600 flex items-center justify-center border-2 border-indigo-300 shadow-lg" style="left: 35%; top: 50%; transform: translate(-50%, -50%);"><span class="text-white font-extrabold text-xl">34</span></div></div></div>
<div class="absolute" style="left: 45mm; top: 1mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid10.png" class="w-full h-full object-contain" style="transform: rotate(-20deg) scale(1.20);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
<div class="absolute" style="left: 95mm; top: 6mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid6.png" class="w-full h-full object-contain" style="transform: rotate(15deg) scale(0.75);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">3</span></div></div></div>
<div class="absolute" style="left: 125mm; top: -5mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid10.png" class="w-full h-full object-contain" style="transform: rotate(-8deg) scale(0.60);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: -10mm; top: 16mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid10.png" class="w-full h-full object-contain" style="transform: rotate(22deg) scale(1.35);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">7</span></div></div></div>
<div class="absolute" style="left: 72mm; top: 35mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid6.png" class="w-full h-full object-contain" style="transform: rotate(-15deg) scale(1.35);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">7</span></div></div></div>
<div class="absolute" style="left: 27mm; top: 38mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid10.png" class="w-full h-full object-contain" style="transform: rotate(10deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">5</span></div></div></div>
<div class="absolute" style="left: 120mm; top: 67mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid10.png" class="w-full h-full object-contain" style="transform: rotate(25deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">5</span></div></div></div>
<div class="absolute" style="left: 57mm; top: 91mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid6.png" class="w-full h-full object-contain" style="transform: rotate(-12deg) scale(1.65);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">9</span></div></div></div>
<div class="absolute" style="left: 91mm; top: 63mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid10.png" class="w-full h-full object-contain" style="transform: rotate(18deg) scale(0.60);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">2</span></div></div></div>
<div class="absolute" style="left: 175mm; top: 81mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid10.png" class="w-full h-full object-contain" style="transform: rotate(-5deg) scale(1.50);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">8</span></div></div></div>
<div class="absolute" style="left: -5mm; top: 123mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid6.png" class="w-full h-full object-contain" style="transform: rotate(12deg) scale(0.90);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">4</span></div></div></div>
<div class="absolute" style="left: 67mm; top: 139mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid10.png" class="w-full h-full object-contain" style="transform: rotate(-22deg) scale(1.20);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">6</span></div></div></div>
<div class="absolute" style="left: 108mm; top: 95mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid10.png" class="w-full h-full object-contain" style="transform: rotate(8deg) scale(0.75);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">3</span></div></div></div>
<div class="absolute" style="left: 15mm; top: 155mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid10.png" class="w-full h-full object-contain" style="transform: rotate(20deg) scale(2.10);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">12</span></div></div></div>
<div class="absolute" style="left: 99mm; top: 160mm;"><div class="relative w-[88px] h-[88px]"><img src="../../assets/icons/pack3-asteroids/asteroid10.png" class="w-full h-full object-contain" style="transform: rotate(-18deg) scale(1.05);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow: 0 0 6px rgba(0,0,0,0.9), 0 2px 4px rgba(0,0,0,0.7);">5</span></div></div></div>
</div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,489 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Asteroid Position Editor</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #1e1e2e; color: #cdd6f4; font-family: 'Segoe UI', system-ui, sans-serif; }
#toolbar {
position: fixed; top: 0; left: 0; right: 0; z-index: 1000;
background: #181825; border-bottom: 1px solid #313244;
display: flex; align-items: center; gap: 12px; padding: 8px 16px; height: 48px;
}
#toolbar button {
background: #313244; color: #cdd6f4; border: 1px solid #45475a;
padding: 6px 14px; border-radius: 6px; cursor: pointer; font-size: 13px;
transition: background 0.15s;
}
#toolbar button:hover { background: #45475a; }
#toolbar button.primary { background: #6366f1; border-color: #818cf8; color: white; }
#toolbar button.primary:hover { background: #818cf8; }
#toolbar .page-nav { display: flex; align-items: center; gap: 6px; }
#toolbar .page-nav span { font-size: 14px; min-width: 90px; text-align: center; }
#toolbar .spacer { flex: 1; }
#toolbar .title { font-weight: 600; font-size: 14px; color: #a6adc8; }
#statusbar {
position: fixed; bottom: 0; left: 0; right: 0; z-index: 1000;
background: #181825; border-top: 1px solid #313244;
padding: 6px 16px; font-size: 13px; height: 32px;
display: flex; align-items: center; gap: 20px;
}
#statusbar .pos { color: #89b4fa; }
#statusbar .info { color: #a6adc8; }
#worksheet-container {
padding: 48px 0 32px;
display: flex; flex-direction: column; align-items: center; gap: 20px;
min-height: 100vh;
}
.editor-draggable { cursor: grab; user-select: none; }
.editor-draggable:hover { outline: 2px solid rgba(99, 102, 241, 0.5); outline-offset: 2px; border-radius: 50%; }
.editor-selected { outline: 3px solid #6366f1 !important; outline-offset: 2px; border-radius: 50%; }
.editor-changed::after {
content: ''; position: absolute; top: 2px; right: 2px;
width: 8px; height: 8px; background: #f59e0b; border-radius: 50%;
border: 1px solid #1e1e2e;
}
body.dragging { cursor: grabbing !important; }
body.dragging * { cursor: grabbing !important; }
.ship-draggable { z-index: 50; }
.ship-draggable:hover { outline-color: rgba(251, 146, 60, 0.6); }
.ship-selected { outline-color: #fb923c !important; }
#coord-tooltip {
position: fixed; z-index: 2000; pointer-events: none;
background: #181825; color: #89b4fa; border: 1px solid #6366f1;
padding: 3px 8px; border-radius: 4px; font-size: 12px; font-family: monospace;
display: none;
}
#toast {
position: fixed; top: 60px; right: 16px; z-index: 2000;
background: #6366f1; color: white; padding: 8px 16px; border-radius: 6px;
font-size: 13px; opacity: 0; transition: opacity 0.3s; pointer-events: none;
}
#toast.show { opacity: 1; }
.page-label {
position: absolute; top: 4px; right: 4px; z-index: 100;
background: rgba(0,0,0,0.6); color: white; padding: 2px 8px;
border-radius: 4px; font-size: 12px; pointer-events: none;
}
</style>
</head>
<body>
<div id="toolbar">
<span class="title">Asteroid Editor</span>
<div class="page-nav">
<button id="btn-prev" title="Previous page">&larr;</button>
<span id="page-indicator">Page 1 / ?</span>
<button id="btn-next" title="Next page">&rarr;</button>
</div>
<div class="spacer"></div>
<button id="btn-reset">Reset Page</button>
<button id="btn-copy-changes">Copy Changes</button>
<button id="btn-copy" class="primary">Copy All JSON</button>
<button id="btn-save" class="primary" style="background:#22c55e;border-color:#4ade80;">Save</button>
</div>
<div id="worksheet-container"></div>
<div id="statusbar">
<span id="status-info" class="info">Click an asteroid or ship circle to select it</span>
<span id="status-pos" class="pos"></span>
</div>
<div id="coord-tooltip"></div>
<div id="toast"></div>
<script src="/src/editor/editor-core.js"></script>
<script>
(function() {
// === Asteroid-specific state ===
const baseScales = {};
let asteroids = [];
let ships = [];
let originalPositions = new Map();
let selectedElement = null;
let dragging = null;
let dragStart = null;
// Scale formula
function getBaseKey(p, t) { return 'p' + p + '-' + t; }
function getBaseScale(p, t) { return baseScales[getBaseKey(p, t)] || 0.30; }
function setBaseScale(p, t, v) { baseScales[getBaseKey(p, t)] = Math.round(v * 100) / 100; }
function valueToScale(val, p, t) { return ((p && t) ? getBaseScale(p, t) : 0.30) + 0.15 * val; }
// === Init via EditorCore ===
const core = EditorCore.init({
taskType: 'collecting-asteroids',
serialize: buildConfig,
onReset: resetCurrentPage,
onReady: function(pages, mmToPx) {
setupAsteroids(pages);
setupShips(pages);
setupGlobalEvents(mmToPx);
window.getConfig = () => buildConfig(false);
window.getChanges = () => buildConfig(true);
}
});
if (!core) return;
// === Setup asteroids ===
function setupAsteroids(pages) {
document.querySelectorAll('.absolute:has(img[src*="pack3-asteroids"])').forEach((el, globalIndex) => {
const page = el.closest('[data-page]');
const pageNum = page ? parseInt(page.dataset.page) : 0;
const left = parseFloat(el.style.left) || 0;
const top = parseFloat(el.style.top) || 0;
const img = el.querySelector('img[src*="pack3-asteroids"]');
const span = el.querySelector('span');
const astMatch = img ? img.src.match(/asteroid\d+/) : null;
let rotate = 0, scale = 1;
if (img && img.style.transform) {
const rotMatch = img.style.transform.match(/rotate\(([-\d.]+)deg\)/);
const scMatch = img.style.transform.match(/scale\(([\d.]+)\)/);
if (rotMatch) rotate = parseFloat(rotMatch[1]);
if (scMatch) scale = parseFloat(scMatch[1]);
}
const value = span ? parseInt(span.textContent.trim()) || 0 : 0;
const id = `p${pageNum}-a${globalIndex}`;
el.dataset.editorId = id;
el.dataset.editorType = 'asteroid';
el.dataset.pageNum = pageNum;
originalPositions.set(id, { left, top, rotate, scale, value });
el.classList.add('editor-draggable');
el.querySelectorAll('img').forEach(i => { i.style.pointerEvents = 'none'; i.draggable = false; });
asteroids.push({ el, id, pageNum, globalIndex, span, value, asteroid: astMatch ? astMatch[0] : 'unknown' });
el.addEventListener('mousedown', (e) => {
e.preventDefault(); e.stopPropagation();
selectElement(el, id, 'asteroid');
startDragAsteroid(el, e);
});
});
}
// === Setup ships ===
function setupShips(pages) {
document.querySelectorAll('.rounded-full.bg-indigo-600').forEach((circleEl, globalIndex) => {
const page = circleEl.closest('[data-page]');
const pageNum = page ? parseInt(page.dataset.page) : 0;
const span = circleEl.querySelector('span');
const value = span ? parseInt(span.textContent.trim()) || 0 : 0;
const origLeft = circleEl.style.left || '50%';
const origTop = circleEl.style.top || '50%';
const id = `p${pageNum}-s${globalIndex}`;
circleEl.dataset.editorId = id;
circleEl.dataset.editorType = 'ship';
circleEl.dataset.pageNum = pageNum;
originalPositions.set(id, { left: origLeft, top: origTop, value });
circleEl.classList.add('editor-draggable', 'ship-draggable');
circleEl.style.cursor = 'grab';
ships.push({ el: circleEl, id, pageNum, globalIndex, span, value });
circleEl.addEventListener('mousedown', (e) => {
e.preventDefault(); e.stopPropagation();
selectElement(circleEl, id, 'ship');
startDragShip(circleEl, e);
});
});
}
// === Global events ===
function setupGlobalEvents(mmToPx) {
document.addEventListener('mousemove', onMouseMove);
document.addEventListener('mouseup', onMouseUp);
document.addEventListener('keydown', onKeyDown);
document.getElementById('worksheet-container').addEventListener('mousedown', (e) => {
if (!e.target.closest('.editor-draggable')) deselectAll();
});
}
// === Selection ===
function selectElement(el, id, type) {
deselectAll();
el.classList.add(type === 'ship' ? 'ship-selected' : 'editor-selected');
selectedElement = { el, id, type };
updateStatus();
}
function deselectAll() {
document.querySelectorAll('.editor-selected, .ship-selected').forEach(el => {
el.classList.remove('editor-selected', 'ship-selected');
});
selectedElement = null;
document.getElementById('status-info').textContent = 'Click an asteroid or ship circle to select it';
document.getElementById('status-pos').textContent = '';
}
// === Asteroid helpers ===
function getAsteroidTransform(el) {
const img = el.querySelector('img[src*="pack3-asteroids"]');
let rotate = 0, scale = 1;
if (img && img.style.transform) {
const rotMatch = img.style.transform.match(/rotate\(([-\d.]+)deg\)/);
const scMatch = img.style.transform.match(/scale\(([\d.]+)\)/);
if (rotMatch) rotate = parseFloat(rotMatch[1]);
if (scMatch) scale = parseFloat(scMatch[1]);
}
return { rotate, scale, img };
}
function setAsteroidTransform(el, rotate, scale) {
const img = el.querySelector('img[src*="pack3-asteroids"]');
if (img) img.style.transform = `rotate(${rotate}deg) scale(${scale.toFixed(2)})`;
}
// === Status ===
function updateStatus() {
if (!selectedElement) return;
const { el, id, type } = selectedElement;
if (type === 'asteroid') {
const left = Math.round(parseFloat(el.style.left));
const top = Math.round(parseFloat(el.style.top));
const { rotate, scale } = getAsteroidTransform(el);
const ast = asteroids.find(a => a.id === id);
const base = ast ? getBaseScale(parseInt(el.dataset.pageNum), ast.asteroid) : 0.30;
document.getElementById('status-info').textContent =
`Page ${el.dataset.pageNum} | val=${ast ? ast.value : '?'} | ${ast ? ast.asteroid : ''} | base=${base.toFixed(2)} | [/] rot, +/- val, </.> base`;
document.getElementById('status-pos').textContent =
`left: ${left}mm, top: ${top}mm | rot: ${Math.round(rotate)}° | scale: ${scale.toFixed(2)}`;
} else {
const ship = ships.find(s => s.id === id);
document.getElementById('status-info').textContent =
`Page ${el.dataset.pageNum} | Ship capacity=${ship ? ship.value : '?'} | +/- change value`;
document.getElementById('status-pos').textContent =
`left: ${el.style.left}, top: ${el.style.top}`;
}
}
// === Dragging ===
function startDragAsteroid(el, e) {
dragging = { el, type: 'asteroid' };
dragStart = { mouseX: e.clientX, mouseY: e.clientY, left: parseFloat(el.style.left) || 0, top: parseFloat(el.style.top) || 0 };
document.body.classList.add('dragging');
}
function startDragShip(el, e) {
const parent = el.offsetParent || el.parentElement;
dragging = { el, type: 'ship', parentRect: parent.getBoundingClientRect() };
dragStart = { mouseX: e.clientX, mouseY: e.clientY, leftPct: parseFloat(el.style.left) || 50, topPct: parseFloat(el.style.top) || 50 };
document.body.classList.add('dragging');
}
function onMouseMove(e) {
if (!dragging) return;
e.preventDefault();
if (dragging.type === 'asteroid') {
const dx = (e.clientX - dragStart.mouseX) / core.mmToPx;
const dy = (e.clientY - dragStart.mouseY) / core.mmToPx;
let newLeft = Math.max(-10, Math.min(175, Math.round(dragStart.left + dx)));
let newTop = Math.max(-5, Math.min(160, Math.round(dragStart.top + dy)));
dragging.el.style.left = newLeft + 'mm';
dragging.el.style.top = newTop + 'mm';
core.showTooltip(e, `${newLeft}mm, ${newTop}mm`);
} else if (dragging.type === 'ship') {
const pW = dragging.parentRect.width;
const pH = dragging.parentRect.height;
if (pW === 0 || pH === 0) return;
let newLeftPct = Math.round(dragStart.leftPct + ((e.clientX - dragStart.mouseX) / pW) * 100);
let newTopPct = Math.round(dragStart.topPct + ((e.clientY - dragStart.mouseY) / pH) * 100);
dragging.el.style.left = newLeftPct + '%';
dragging.el.style.top = newTopPct + '%';
core.showTooltip(e, `${newLeftPct}%, ${newTopPct}%`);
}
updateStatus();
markChanged(dragging.el);
}
function onMouseUp() {
if (!dragging) return;
document.body.classList.remove('dragging');
core.hideTooltip();
dragging = null; dragStart = null;
}
// === Keyboard ===
function onKeyDown(e) {
if (!selectedElement) return;
const { el, id, type } = selectedElement;
if (type === 'asteroid') onKeyDownAsteroid(e, el, id);
else onKeyDownShip(e, el, id);
}
function onKeyDownAsteroid(e, el, id) {
const step = e.shiftKey ? 5 : 1;
let left = parseFloat(el.style.left) || 0;
let top = parseFloat(el.style.top) || 0;
const { rotate, scale } = getAsteroidTransform(el);
const rotStep = e.shiftKey ? 1 : 5;
const ast = asteroids.find(a => a.id === id);
const pageNum = parseInt(el.dataset.pageNum);
switch (e.key) {
case 'ArrowLeft': left -= step; break;
case 'ArrowRight': left += step; break;
case 'ArrowUp': top -= step; break;
case 'ArrowDown': top += step; break;
case '[': setAsteroidTransform(el, rotate - rotStep, scale); break;
case ']': setAsteroidTransform(el, rotate + rotStep, scale); break;
case '-': case '_':
if (ast && ast.value > 1) { ast.value--; ast.span.textContent = ast.value; setAsteroidTransform(el, rotate, valueToScale(ast.value, pageNum, ast.asteroid)); }
break;
case '=': case '+':
if (ast && ast.value < 20) { ast.value++; ast.span.textContent = ast.value; setAsteroidTransform(el, rotate, valueToScale(ast.value, pageNum, ast.asteroid)); }
break;
case ',': case '<':
if (ast) { const bs = e.shiftKey ? 0.01 : 0.05; setBaseScale(pageNum, ast.asteroid, Math.max(0.05, getBaseScale(pageNum, ast.asteroid) - bs)); applyBaseToType(pageNum, ast.asteroid); core.showToast(`Base ${ast.asteroid}: ${getBaseScale(pageNum, ast.asteroid).toFixed(2)}`); }
break;
case '.': case '>':
if (ast) { const bs = e.shiftKey ? 0.01 : 0.05; setBaseScale(pageNum, ast.asteroid, getBaseScale(pageNum, ast.asteroid) + bs); applyBaseToType(pageNum, ast.asteroid); core.showToast(`Base ${ast.asteroid}: ${getBaseScale(pageNum, ast.asteroid).toFixed(2)}`); }
break;
case 'Escape': deselectAll(); return;
default: return;
}
e.preventDefault();
el.style.left = Math.max(-10, Math.min(175, Math.round(left))) + 'mm';
el.style.top = Math.max(-5, Math.min(160, Math.round(top))) + 'mm';
updateStatus(); markChanged(el);
}
function onKeyDownShip(e, el, id) {
const ship = ships.find(s => s.id === id);
if (!ship) return;
const step = e.shiftKey ? 5 : 1;
switch (e.key) {
case '-': case '_': ship.value = Math.max(1, ship.value - step); ship.span.textContent = ship.value; break;
case '=': case '+': ship.value += step; ship.span.textContent = ship.value; break;
case 'ArrowLeft': el.style.left = ((parseFloat(el.style.left) || 50) - step) + '%'; break;
case 'ArrowRight': el.style.left = ((parseFloat(el.style.left) || 50) + step) + '%'; break;
case 'ArrowUp': el.style.top = ((parseFloat(el.style.top) || 50) - step) + '%'; break;
case 'ArrowDown': el.style.top = ((parseFloat(el.style.top) || 50) + step) + '%'; break;
case 'Escape': deselectAll(); return;
default: return;
}
e.preventDefault(); updateStatus(); markChanged(el);
}
// === Change tracking ===
function markChanged(el) {
const id = el.dataset.editorId;
const type = el.dataset.editorType;
const orig = originalPositions.get(id);
if (!orig) return;
let changed = false;
if (type === 'asteroid') {
const { rotate, scale } = getAsteroidTransform(el);
const ast = asteroids.find(a => a.id === id);
changed = Math.round(orig.left) !== Math.round(parseFloat(el.style.left)) ||
Math.round(orig.top) !== Math.round(parseFloat(el.style.top)) ||
Math.round(orig.rotate) !== Math.round(rotate) ||
Math.abs(orig.scale - scale) > 0.005 ||
(ast && orig.value !== ast.value);
} else {
const ship = ships.find(s => s.id === id);
changed = el.style.left !== orig.left || el.style.top !== orig.top || (ship && orig.value !== ship.value);
}
el.classList.toggle('editor-changed', changed);
}
function applyBaseToType(pageNum, asteroidType) {
asteroids.filter(a => a.pageNum === pageNum && a.asteroid === asteroidType).forEach(ast => {
const { rotate } = getAsteroidTransform(ast.el);
setAsteroidTransform(ast.el, rotate, valueToScale(ast.value, pageNum, asteroidType));
markChanged(ast.el);
});
}
// === Serialization ===
function buildConfig(changesOnly) {
const result = { file: core.docId, pages: [] };
core.pages.forEach((pageEl, pageIndex) => {
const pageNum = pageIndex + 1;
const pageData = { page: pageNum };
const pageAsteroids = asteroids.filter(a => a.pageNum === pageNum);
const asteroidItems = [];
pageAsteroids.forEach((ast, localIndex) => {
const curLeft = Math.round(parseFloat(ast.el.style.left));
const curTop = Math.round(parseFloat(ast.el.style.top));
const { rotate, scale } = getAsteroidTransform(ast.el);
const orig = originalPositions.get(ast.id);
if (changesOnly && orig &&
Math.round(orig.left) === curLeft && Math.round(orig.top) === curTop &&
Math.round(orig.rotate) === Math.round(rotate) && Math.abs(orig.scale - scale) < 0.005 &&
orig.value === ast.value) return;
asteroidItems.push({ index: localIndex, left: curLeft + 'mm', top: curTop + 'mm', rotate: Math.round(rotate) + 'deg', scale: parseFloat(scale.toFixed(2)), value: ast.value, asteroid: ast.asteroid });
});
const pageShips = ships.filter(s => s.pageNum === pageNum);
const shipItems = [];
pageShips.forEach((ship, localIndex) => {
const orig = originalPositions.get(ship.id);
if (changesOnly && orig && ship.el.style.left === orig.left && ship.el.style.top === orig.top && orig.value === ship.value) return;
shipItems.push({ index: localIndex, left: ship.el.style.left, top: ship.el.style.top, value: ship.value });
});
const pageBaseScales = {};
for (const [key, val] of Object.entries(baseScales)) {
if (key.startsWith('p' + pageNum + '-') && val !== 0.30) {
pageBaseScales[key.replace('p' + pageNum + '-', '')] = val;
}
}
if (asteroidItems.length > 0 || shipItems.length > 0 || Object.keys(pageBaseScales).length > 0) {
if (asteroidItems.length > 0) pageData.asteroids = asteroidItems;
if (shipItems.length > 0) pageData.ships = shipItems;
if (Object.keys(pageBaseScales).length > 0) pageData.baseScales = pageBaseScales;
result.pages.push(pageData);
}
});
return result;
}
// === Reset ===
function resetCurrentPage(pageNum) {
asteroids.filter(a => a.pageNum === pageNum).forEach(ast => {
const orig = originalPositions.get(ast.id);
if (!orig) return;
ast.el.style.left = orig.left + 'mm'; ast.el.style.top = orig.top + 'mm';
setAsteroidTransform(ast.el, orig.rotate, orig.scale);
ast.value = orig.value; ast.span.textContent = orig.value;
ast.el.classList.remove('editor-changed');
});
ships.filter(s => s.pageNum === pageNum).forEach(ship => {
const orig = originalPositions.get(ship.id);
if (!orig) return;
ship.el.style.left = orig.left; ship.el.style.top = orig.top;
ship.value = orig.value; ship.span.textContent = orig.value;
ship.el.classList.remove('editor-changed');
});
core.showToast(`Page ${pageNum} reset`);
}
})();
</script>
</body>
</html>

View File

@ -0,0 +1,171 @@
#!/usr/bin/env node
/**
* Generate output HTML from template + data for collecting-asteroids documents.
*
* Usage: node generate.mjs <docId>
* Example: node generate.mjs collecting-asteroids-3
*
* Reads: docs/<docId>.template.html
* Reads: docs/<docId>.data.json (optional)
* Writes: docs/<docId>.output.html
*
* data.json format:
* {
* pages: [{
* page: 1,
* asteroids: [{ index, left, top, rotate, scale, value, asteroid }],
* ships: [{ index, left, top, value }],
* baseScales: { "asteroid5": 0.35 }
* }]
* }
*/
import { readFileSync, writeFileSync, existsSync } from 'fs';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';
const __dirname = dirname(fileURLToPath(import.meta.url));
const docsDir = join(__dirname, '..', 'docs');
const docId = process.argv[2];
if (!docId) {
console.error('Usage: node generate.mjs <docId>');
process.exit(1);
}
const templatePath = join(docsDir, `${docId}.template.html`);
const dataPath = join(docsDir, `${docId}.data.json`);
const outputPath = join(docsDir, `${docId}.output.html`);
if (!existsSync(templatePath)) {
console.error(`Template not found: ${templatePath}`);
process.exit(1);
}
let html = readFileSync(templatePath, 'utf-8');
if (existsSync(dataPath)) {
const data = JSON.parse(readFileSync(dataPath, 'utf-8'));
html = applyData(html, data);
console.log(`Applied data from ${data.pages?.length || 0} pages`);
}
writeFileSync(outputPath, html);
console.log(`Generated: ${outputPath}`);
function applyData(html, data) {
if (!data.pages) return html;
// Split HTML into pages by PAGE comment markers or by w-[210mm] divs
const pageMarker = /<!-- PAGE (\d+)/g;
const hasPageComments = pageMarker.test(html);
if (hasPageComments) {
// Split by page comments
return applyByPageComments(html, data.pages);
} else {
// Split by page divs
return applyByPageDivs(html, data.pages);
}
}
function applyByPageDivs(html, pages) {
// Find page boundaries: <div class="w-[210mm] h-[297mm]"
const pageRegex = /<div class="w-\[210mm\] h-\[297mm\]"/g;
const starts = [];
let match;
while ((match = pageRegex.exec(html)) !== null) {
starts.push(match.index);
}
if (starts.length === 0) return html;
// Process pages in reverse order to preserve indices
for (let i = pages.length - 1; i >= 0; i--) {
const pageData = pages[i];
const pageNum = pageData.page || (i + 1);
const pageIdx = pageNum - 1;
if (pageIdx >= starts.length) continue;
const pageStart = starts[pageIdx];
const pageEnd = pageIdx + 1 < starts.length ? starts[pageIdx + 1] : html.length;
let pageHtml = html.slice(pageStart, pageEnd);
// Apply asteroid positions
if (pageData.asteroids) {
pageHtml = applyAsteroids(pageHtml, pageData.asteroids);
}
// Apply ship positions
if (pageData.ships) {
pageHtml = applyShips(pageHtml, pageData.ships);
}
html = html.slice(0, pageStart) + pageHtml + html.slice(pageEnd);
}
return html;
}
function applyByPageComments(html, pages) {
// Same logic but split by <!-- PAGE N -->
const parts = html.split(/(<!-- PAGE \d+)/);
const pageChunks = [];
let prelude = parts[0];
for (let i = 1; i < parts.length; i += 2) {
pageChunks.push(parts[i] + (parts[i + 1] || ''));
}
for (const pageData of pages) {
const pageIdx = (pageData.page || 1) - 1;
if (pageIdx >= pageChunks.length) continue;
if (pageData.asteroids) {
pageChunks[pageIdx] = applyAsteroids(pageChunks[pageIdx], pageData.asteroids);
}
if (pageData.ships) {
pageChunks[pageIdx] = applyShips(pageChunks[pageIdx], pageData.ships);
}
}
return prelude + pageChunks.join('');
}
function applyAsteroids(pageHtml, asteroids) {
// Match asteroid containers: <div class="absolute" style="left: Xmm; top: Ymm;">
// followed by pack3-asteroids image
const asteroidRegex = /(<div class="absolute" style="left: )-?\d+mm; top: -?\d+mm(;"><div class="relative w-\[88px\] h-\[88px\]"><img src="[^"]*pack3-asteroids\/[^"]*" class="w-full h-full object-contain" style="transform: rotate\()-?\d+deg(\) scale\()[\d.]+(\);" alt=""><div class="absolute inset-0 flex items-center justify-center"><span class="text-white font-extrabold text-2xl" style="text-shadow[^"]*">)\d+(<\/span>)/g;
let idx = 0;
return pageHtml.replace(asteroidRegex, (match, prefix, rotPrefix, scalePrefix, scaleSuffix, valueSuffix) => {
const ast = asteroids[idx++];
if (!ast) return match;
const left = ast.left.replace('mm', '');
const top = ast.top.replace('mm', '');
const rotate = ast.rotate.replace('deg', '');
const scale = ast.scale.toFixed(2);
const value = ast.value;
return `${prefix}${left}mm; top: ${top}mm${rotPrefix}${rotate}deg${scalePrefix}${scale}${scaleSuffix}${value}${valueSuffix}`;
});
}
function applyShips(pageHtml, ships) {
// Match ship capacity circles
const shipRegex = /(<div class="absolute w-12 h-12 rounded-full bg-indigo-600[^"]*" style="left: )[\d.]+%(; top: )[\d.]+(%[^>]*><span class="text-white font-extrabold text-xl">)\d+(<\/span>)/g;
let idx = 0;
return pageHtml.replace(shipRegex, (match, prefix, topPrefix, valueSuffix, spanClose) => {
const ship = ships[idx++];
if (!ship) return match;
const left = ship.left.replace('%', '');
const top = ship.top.replace('%', '');
return `${prefix}${left}%${topPrefix}${top}${valueSuffix}${ship.value}${spanClose}`;
});
}

View File

@ -1,26 +0,0 @@
{
"id": "multiply-2-3",
"title": "Умножение на 2 и 3",
"description": "Worksheet for practicing multiplication by 2 and 3",
"template": "{a} × {b} = ___",
"variables": {
"a": { "type": "range", "min": 1, "max": 10 },
"b": { "type": "set", "values": [2, 3] }
},
"problemCount": 20,
"layout": {
"columns": 2,
"problemsPerPage": 20
},
"labels": {
"title": "Умножение",
"subtitle": "Реши примеры",
"name": "Имя: _______________",
"date": "Дата: _______________"
},
"theme": {
"background": null,
"icons": null,
"iconReward": 5
}
}

127
tasks/index.html Normal file
View File

@ -0,0 +1,127 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Math Tasks — Документы</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700&display=swap" rel="stylesheet">
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: 'Nunito', sans-serif;
background: #f5f3ff;
color: #1e1b4b;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
padding: 60px 24px;
}
h1 { font-size: 2rem; font-weight: 700; margin-bottom: 8px; }
.subtitle { color: #6366f1; font-size: 1.05rem; margin-bottom: 48px; }
h2 {
font-size: 1.3rem; font-weight: 700;
margin: 32px 0 12px; width: 100%; max-width: 720px;
border-bottom: 2px solid #e0e7ff; padding-bottom: 6px;
}
.cards {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 16px;
width: 100%; max-width: 720px;
}
.card {
background: white;
border: 1px solid #e0e7ff;
border-radius: 12px;
padding: 20px 24px;
color: #1e1b4b;
}
.card-title { font-weight: 600; font-size: 1.1rem; margin-bottom: 8px; }
.card-links { display: flex; gap: 12px; }
.card-links a {
font-size: 0.88rem; font-weight: 600;
text-decoration: none; color: #6366f1;
padding: 4px 12px; border-radius: 6px;
border: 1px solid #e0e7ff;
transition: background 0.15s, border-color 0.15s;
}
.card-links a:hover {
background: #f5f3ff; border-color: #a5b4fc;
}
.card-links a.edit {
color: #059669; border-color: #d1fae5;
}
.card-links a.edit:hover {
background: #ecfdf5; border-color: #6ee7b7;
}
</style>
</head>
<body>
<h1>Math Tasks</h1>
<p class="subtitle">Документы для предпросмотра</p>
<!-- Space Exploration -->
<h2>Исследуй Планету</h2>
<div class="cards">
<div class="card">
<div class="card-title">Space Exploration 1 (3 pages)</div>
<div class="card-links">
<a href="/tasks/space-exploration/docs/space-exploration-1.template.html">View</a>
</div>
</div>
<div class="card">
<div class="card-title">Space Worksheet 2 (3 pages)</div>
<div class="card-links">
<a href="/tasks/space-exploration/docs/space-worksheet2.template.html">View</a>
</div>
</div>
<div class="card">
<div class="card-title">Space Worksheet 3 (9 pages)</div>
<div class="card-links">
<a href="/tasks/space-exploration/docs/space-worksheet3.template.html">View</a>
</div>
</div>
</div>
<!-- Collecting Asteroids -->
<h2>Собери Астероиды</h2>
<div class="cards">
<div class="card">
<div class="card-title">Collecting Asteroids 1</div>
<div class="card-links">
<a href="/tasks/collecting-asteroids/docs/collecting-asteroids-1.template.html">View</a>
<a class="edit" href="/tasks/collecting-asteroids/editor.html?file=collecting-asteroids-1">Edit</a>
</div>
</div>
<div class="card">
<div class="card-title">Collecting Asteroids 2</div>
<div class="card-links">
<a href="/tasks/collecting-asteroids/docs/collecting-asteroids-2.template.html">View</a>
<a class="edit" href="/tasks/collecting-asteroids/editor.html?file=collecting-asteroids-2">Edit</a>
</div>
</div>
<div class="card">
<div class="card-title">Collecting Asteroids 3</div>
<div class="card-links">
<a href="/tasks/collecting-asteroids/docs/collecting-asteroids-3.template.html">View</a>
<a class="edit" href="/tasks/collecting-asteroids/editor.html?file=collecting-asteroids-3">Edit</a>
</div>
</div>
</div>
<!-- Space Route -->
<h2>Проложи Маршрут</h2>
<div class="cards">
<div class="card">
<div class="card-title">Space Route 1</div>
<div class="card-links">
<a href="/tasks/space-route/docs/space-route-1.template.html">View</a>
<a class="edit" href="/tasks/space-route/editor.html?file=space-route-1">Edit</a>
</div>
</div>
</div>
</body>
</html>

View File

@ -1,42 +0,0 @@
{
"id": "space-exploration-1",
"title": "Исследуй Планету",
"description": "3-page space worksheet: addition ±, multiply by 5 ±, multiplication table ±",
"labels": {
"title": "Исследуй Планету",
"subtitle": "Собери ресурсы, решая примеры!",
"footerBubble": "Итого собрано на планете:"
},
"theme": {
"style": "space",
"template": "space-base",
"icons": "assets/icons/pack1/"
},
"layout": {
"columns": 2,
"problemsPerPage": 20
},
"pages": [
{
"task": "A + B ± C, где A от 8 до 16, B от 4 до 8, C от 1 до 3. Знак ± выбирается случайно",
"problemCount": 20,
"heroImage": "assets/hero-images/spaceship2.jpeg",
"footerImage": "assets/footers/planet3.jpeg",
"heroDirection": "row-reverse"
},
{
"task": "5 × N ± C, где N от 1 до 5, C от 1 до 6. Знак ± выбирается случайно",
"problemCount": 20,
"heroImage": "assets/hero-images/spaceship4.jpeg",
"footerImage": "assets/footers/planet5.jpeg",
"heroDirection": "row"
},
{
"task": "A × B ± C, где A и B от 1 до 4, C от 1 до 8. Знак ± выбирается случайно",
"problemCount": 20,
"heroImage": "assets/hero-images/spaceship6.jpeg",
"footerImage": "assets/footers/planet1.jpeg",
"heroDirection": "row-reverse"
}
]
}

View File

@ -0,0 +1,45 @@
# Space Exploration Task Type
Math problem worksheets with space theme: hero images, footer panoramas, icon-decorated problem cards.
## Base References
- Base template: `src/templates/space-base.html` (layout/styling reference)
- Example outputs in `docs/` (existing worksheets serve as reference for new ones)
## What to Vary Per Worksheet
1. **Hero image** — from `assets/hero-images/spaceship{1-9}.jpeg`
2. **Footer image** — from `assets/footers/planet{1-9}.jpeg`
3. **Hero position**`flex-row-reverse` (hero right) or default (hero left)
4. **Problem icons** — from `assets/icons/pack1/` or `pack2/`. **Every icon must be unique across the entire document** (no repeats across pages). Shuffle minerals and plants randomly — do not sort by type
5. **Problem alignment** — randomly assign `justify-start`, `justify-center`, or `justify-end` per card. No patterns — should look chaotic/scattered
6. **Problems** — generate from the task description in the `.md` file
## Layout Structure (do not change)
- Page: `w-[210mm] h-[297mm]` white container
- Footer: absolute bottom, `h-[80mm]`, with white-to-transparent fade on top. **No `overflow-hidden`** on footer (causes 1px hairline artifact in PDF)
- Footer bubble: absolute `bottom-[12mm]`, pill-shaped with semi-transparent white bg
- Content area: `px-[12mm] pt-[4mm] pb-[65mm]` flex column
- Header: hero image `w-[48%]` + title block centered, `flex-row-reverse` for hero-right
- Footer gradient: `linear-gradient(to bottom, white 0%, rgba(255,255,255,0.6) 25%, transparent 50%)` with `h-full`
- Problems: `grid grid-cols-2 gap-x-3 gap-y-[3px]` — 20 problems total
- Each problem: 58px icon outside pill + `text-[1.2rem]` expression + `w-16` answer underline inside pill
- Font: Nunito via Google Fonts
- Uses Tailwind CDN
## Color Palette (do not change)
| Element | Hex |
|---------|-----|
| Title text | `text-indigo-950` (#1e1b4b) |
| Subtitle | `text-indigo-400` (#6366f1) |
| Card border | `border-indigo-100` (#e0e7ff) |
| Answer underline | `border-indigo-300` (#a5b4fc) |
| Card bg gradient | `from-white to-indigo-50/40` |
| Footer bubble border | `border-indigo-200` |
## Scripts
- `scripts/generate-worksheet3.mjs` — generator for 9-page combined worksheets

View File

@ -0,0 +1,200 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.tailwindcss.com"></script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700;800;900&display=swap" rel="stylesheet">
<title>Исследуй Планету</title>
<script>
tailwind.config = {
theme: {
extend: {
fontFamily: { nunito: ['Nunito', 'sans-serif'] },
}
}
}
</script>
<style>
@page { size: A4; margin: 0; }
:root {
--hero-direction: row-reverse;
}
.page-header { flex-direction: var(--hero-direction); }
</style>
</head>
<body class="bg-gray-200 font-nunito">
<div class="w-[210mm] h-[297mm] relative overflow-hidden mx-auto bg-white">
<div class="absolute bottom-0 left-0 right-0 h-[80mm] overflow-hidden z-0">
<div class="absolute top-0 left-0 right-0 h-[40%] bg-gradient-to-b from-white to-transparent z-10"></div>
<img src="../../assets/footers/planet1.jpeg" class="w-full h-full object-cover object-top" alt="">
</div>
<div class="absolute bottom-[12mm] left-0 right-0 z-20 flex justify-center">
<div style="background: rgba(255,255,255,0.85);" class="rounded-full px-6 py-1.5 border-[1.5px] border-indigo-200 shadow-md">
<span class="text-[0.95rem] font-bold text-indigo-950">Итого собрано на планете: <span class="inline-block w-14 border-b-2 border-indigo-400 text-center ml-1">&nbsp;</span></span>
</div>
</div>
<div class="relative z-10 w-full h-full px-[12mm] pt-[8mm] pb-[65mm] flex flex-col">
<div class="page-header flex items-center gap-4 mb-4">
<img src="../../assets/hero-images/spaceship1.jpeg" class="w-[48%] shrink-0 object-contain" alt="">
<div class="flex-1 flex flex-col items-center justify-center text-center">
<h1 class="text-2xl font-extrabold leading-tight tracking-tight text-indigo-950">Исследуй Планету</h1>
<p class="text-sm font-medium text-indigo-400 mt-1">Собери ресурсы, решая примеры!</p>
</div>
</div>
<div class="grid grid-cols-2 gap-x-3 gap-y-[8px] flex-1 content-start">
<div class="flex justify-end py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[3px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit">
<img src="../../assets/icons/pack1/minerals1-0-0.png" class="w-11 h-11 shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 3 + 8 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-center py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[3px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit">
<img src="../../assets/icons/pack1/plants1-0-0.png" class="w-11 h-11 shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">7 × 4 6 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-start py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[3px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit">
<img src="../../assets/icons/pack1/minerals3-1-0.png" class="w-11 h-11 shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">3 × 6 + 5 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-end py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[3px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit">
<img src="../../assets/icons/pack1/plants2-0-0.png" class="w-11 h-11 shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">8 × 2 + 3 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-center py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[3px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit">
<img src="../../assets/icons/pack1/minerals2-0-1.png" class="w-11 h-11 shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">4 × 5 7 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-center py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[3px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit">
<img src="../../assets/icons/pack1/minerals5-0-0.png" class="w-11 h-11 shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">6 × 3 + 9 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-end py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[3px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit">
<img src="../../assets/icons/pack1/plants1-1-0.png" class="w-11 h-11 shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">9 × 2 4 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-start py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[3px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit">
<img src="../../assets/icons/pack1/minerals4-0-0.png" class="w-11 h-11 shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">7 × 3 + 2 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-center py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[3px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit">
<img src="../../assets/icons/pack1/plants3-0-0.png" class="w-11 h-11 shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">2 × 8 + 6 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-start py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[3px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit">
<img src="../../assets/icons/pack1/minerals6-0-0.png" class="w-11 h-11 shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 4 3 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-end py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[3px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit">
<img src="../../assets/icons/pack1/minerals1-2-1.png" class="w-11 h-11 shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">3 × 7 + 4 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-center py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[3px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit">
<img src="../../assets/icons/pack1/plants1-3-0.png" class="w-11 h-11 shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">9 × 3 5 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-start py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[3px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit">
<img src="../../assets/icons/pack1/minerals1-1-0.png" class="w-11 h-11 shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">4 × 6 + 7 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-start py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[3px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit">
<img src="../../assets/icons/pack1/plants2-1-0.png" class="w-11 h-11 shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">8 × 3 9 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-end py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[3px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit">
<img src="../../assets/icons/pack1/minerals2-1-0.png" class="w-11 h-11 shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">6 × 4 + 2 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-end py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[3px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit">
<img src="../../assets/icons/pack1/plants3-1-0.png" class="w-11 h-11 shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">7 × 2 + 8 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-start py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[3px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit">
<img src="../../assets/icons/pack1/minerals3-0-0.png" class="w-11 h-11 shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">2 × 9 3 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-center py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[3px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit">
<img src="../../assets/icons/pack1/minerals5-1-0.png" class="w-11 h-11 shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 5 + 4 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-center py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[3px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit">
<img src="../../assets/icons/pack1/plants1-2-0.png" class="w-11 h-11 shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">3 × 8 6 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-start py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[3px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit">
<img src="../../assets/icons/pack1/minerals4-1-0.png" class="w-11 h-11 shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">4 × 7 + 5 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,537 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.tailwindcss.com"></script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700;800;900&display=swap" rel="stylesheet">
<title>Исследуй Планету</title>
<script>
tailwind.config = {
theme: {
extend: {
fontFamily: { nunito: ['Nunito', 'sans-serif'] },
}
}
}
</script>
<style>
@page { size: A4; margin: 0; }
</style>
</head>
<body class="bg-gray-200 font-nunito">
<!-- PAGE 1: A + B ± C (A:8-16, B:4-8, C:±1-3) — hero right, spaceship2, planet3 -->
<div class="w-[210mm] h-[297mm] relative overflow-hidden mx-auto bg-white" style="break-after: page;">
<div class="absolute bottom-0 left-0 right-0 h-[80mm] z-0">
<div class="absolute top-0 left-0 right-0 h-full z-10" style="background: linear-gradient(to bottom, white 0%, rgba(255,255,255,0.6) 25%, transparent 50%);"></div>
<img src="../../assets/footers/planet3.jpeg" class="w-full h-full object-cover object-top" alt="">
</div>
<div class="absolute bottom-[12mm] left-0 right-0 z-20 flex justify-center">
<div style="background: rgba(255,255,255,0.85);" class="rounded-full px-6 py-1.5 border-[1.5px] border-indigo-200 shadow-md">
<span class="text-[0.95rem] font-bold text-indigo-950">Итого собрано на планете: <span class="inline-block w-14 border-b-2 border-indigo-400 text-center ml-1">&nbsp;</span></span>
</div>
</div>
<div class="relative z-10 w-full h-full px-[12mm] pt-[4mm] pb-[65mm] flex flex-col">
<div class="flex items-center gap-4 mb-4 flex-row-reverse">
<img src="../../assets/hero-images/spaceship2.jpeg" class="w-[48%] shrink-0 object-contain" alt="">
<div class="flex-1 flex flex-col items-center justify-center text-center">
<h1 class="text-2xl font-extrabold leading-tight tracking-tight text-indigo-950">Исследуй Планету</h1>
<p class="text-sm font-medium text-indigo-400 mt-1">Собери ресурсы, решая примеры!</p>
</div>
</div>
<div class="grid grid-cols-2 gap-x-3 gap-y-[8px] flex-1 content-start">
<div class="flex justify-center py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/plants1-2-0.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">12 + 7 + 2 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-end py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/minerals4-0-3.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">9 + 5 1 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-end py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/plants5-1-0.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">14 + 6 + 3 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-start py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/minerals3-2-1.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">11 + 4 2 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-start py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/minerals2-3-3.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">8 + 8 + 1 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-center py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/plants3-3-2.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">15 + 5 3 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-center py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/plants6-3-2.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">10 + 7 + 2 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-end py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/minerals3-2-0.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">13 + 4 1 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-end py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/plants1-1-1.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">16 + 6 + 3 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-start py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/plants6-0-3.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">9 + 8 2 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-start py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/minerals5-2-2.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">11 + 5 + 1 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-center py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/plants5-3-1.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">14 + 7 3 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-center py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/plants3-1-3.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">8 + 6 + 2 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-end py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/plants3-0-1.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">12 + 4 1 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-end py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/plants1-2-3.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">15 + 8 + 3 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-start py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/plants3-1-0.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">10 + 5 2 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-start py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/plants4-2-0.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">13 + 7 + 1 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-center py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/plants3-2-0.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">16 + 4 3 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-center py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/plants1-0-1.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">9 + 6 + 2 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-end py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/minerals2-3-1.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">11 + 8 1 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
</div>
</div>
<!-- PAGE 2: 5 × N ± C (N:1-5, C:-3..+6) — hero left, spaceship4, planet5 -->
<div class="w-[210mm] h-[297mm] relative overflow-hidden mx-auto bg-white" style="break-after: page;">
<div class="absolute bottom-0 left-0 right-0 h-[80mm] z-0">
<div class="absolute top-0 left-0 right-0 h-full z-10" style="background: linear-gradient(to bottom, white 0%, rgba(255,255,255,0.6) 25%, transparent 50%);"></div>
<img src="../../assets/footers/planet5.jpeg" class="w-full h-full object-cover object-top" alt="">
</div>
<div class="absolute bottom-[12mm] left-0 right-0 z-20 flex justify-center">
<div style="background: rgba(255,255,255,0.85);" class="rounded-full px-6 py-1.5 border-[1.5px] border-indigo-200 shadow-md">
<span class="text-[0.95rem] font-bold text-indigo-950">Итого собрано на планете: <span class="inline-block w-14 border-b-2 border-indigo-400 text-center ml-1">&nbsp;</span></span>
</div>
</div>
<div class="relative z-10 w-full h-full px-[12mm] pt-[4mm] pb-[65mm] flex flex-col">
<div class="flex items-center gap-4 mb-4">
<img src="../../assets/hero-images/spaceship4.jpeg" class="w-[48%] shrink-0 object-contain" alt="">
<div class="flex-1 flex flex-col items-center justify-center text-center">
<h1 class="text-2xl font-extrabold leading-tight tracking-tight text-indigo-950">Исследуй Планету</h1>
<p class="text-sm font-medium text-indigo-400 mt-1">Собери ресурсы, решая примеры!</p>
</div>
</div>
<div class="grid grid-cols-2 gap-x-3 gap-y-[8px] flex-1 content-start">
<div class="flex justify-start py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/minerals4-3-3.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 3 + 4 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-end py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/minerals1-2-1.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 1 2 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-center py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/minerals5-3-3.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 5 + 6 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-start py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/plants2-1-3.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 2 1 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-end py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/minerals6-1-2.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 4 + 3 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-center py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/minerals5-3-0.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 1 + 5 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-start py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/plants2-1-0.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 3 3 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-center py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/minerals5-0-0.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 5 + 2 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-end py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/minerals1-3-0.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 2 + 6 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-start py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/minerals4-1-0.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 4 2 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-center py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/minerals1-0-3.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 1 + 4 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-end py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/plants4-3-1.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 3 + 1 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-start py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/plants4-3-3.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 5 1 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-end py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/plants4-3-0.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 2 + 3 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-center py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/minerals6-0-0.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 4 + 5 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-start py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/minerals4-0-0.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 1 3 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-end py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/minerals4-2-1.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 3 + 6 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-end py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/plants2-3-1.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 2 2 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-center py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/minerals3-1-1.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 5 + 4 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-start py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/minerals2-0-3.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 4 1 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
</div>
</div>
<!-- PAGE 3: A × B ± C (A,B:1-4, C:-4..+8) — hero right, spaceship6, planet1 -->
<div class="w-[210mm] h-[297mm] relative overflow-hidden mx-auto bg-white">
<div class="absolute bottom-0 left-0 right-0 h-[80mm] z-0">
<div class="absolute top-0 left-0 right-0 h-full z-10" style="background: linear-gradient(to bottom, white 0%, rgba(255,255,255,0.6) 25%, transparent 50%);"></div>
<img src="../../assets/footers/planet1.jpeg" class="w-full h-full object-cover object-top" alt="">
</div>
<div class="absolute bottom-[12mm] left-0 right-0 z-20 flex justify-center">
<div style="background: rgba(255,255,255,0.85);" class="rounded-full px-6 py-1.5 border-[1.5px] border-indigo-200 shadow-md">
<span class="text-[0.95rem] font-bold text-indigo-950">Итого собрано на планете: <span class="inline-block w-14 border-b-2 border-indigo-400 text-center ml-1">&nbsp;</span></span>
</div>
</div>
<div class="relative z-10 w-full h-full px-[12mm] pt-[4mm] pb-[65mm] flex flex-col">
<div class="flex items-center gap-4 mb-4 flex-row-reverse">
<img src="../../assets/hero-images/spaceship6.jpeg" class="w-[48%] shrink-0 object-contain" alt="">
<div class="flex-1 flex flex-col items-center justify-center text-center">
<h1 class="text-2xl font-extrabold leading-tight tracking-tight text-indigo-950">Исследуй Планету</h1>
<p class="text-sm font-medium text-indigo-400 mt-1">Собери ресурсы, решая примеры!</p>
</div>
</div>
<div class="grid grid-cols-2 gap-x-3 gap-y-[8px] flex-1 content-start">
<div class="flex justify-end py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/plants6-0-1.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">3 × 4 + 5 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-start py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/minerals6-2-0.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">2 × 3 2 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-center py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/minerals4-1-1.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">4 × 4 + 7 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-end py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/plants6-1-2.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">1 × 3 + 6 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-start py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/minerals2-2-0.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">3 × 2 3 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-center py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/plants1-0-3.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">4 × 3 + 2 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-center py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/minerals1-3-3.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">2 × 4 1 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-end py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/plants5-2-0.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">1 × 4 + 8 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-end py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/plants2-2-1.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">3 × 3 4 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-center py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/plants4-0-2.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">4 × 2 + 3 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-start py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/minerals4-1-2.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">2 × 2 + 5 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-start py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/minerals5-1-1.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">1 × 2 + 7 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-end py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/plants4-0-1.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">4 × 4 3 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-center py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/minerals3-3-2.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">3 × 1 + 4 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-center py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/minerals6-0-2.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">2 × 3 + 6 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-end py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/plants5-1-3.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">4 × 1 2 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-start py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/plants1-3-2.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">3 × 4 + 8 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-start py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/plants4-2-2.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">1 × 3 + 3 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-end py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/minerals5-2-0.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">2 × 4 + 1 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
<div class="flex justify-center py-[3px]">
<div class="flex items-center gap-1.5 pl-0.5 pr-4 py-[1px] border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30 w-fit overflow-hidden">
<img src="../../assets/icons/pack1/plants3-0-3.png" class="w-[39px] h-[39px] shrink-0 object-contain" alt="">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">4 × 3 4 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,27 @@
# Space Exploration 1
**Title:** Исследуй Планету
**Subtitle:** Собери ресурсы, решая примеры!
**Footer bubble:** Итого собрано на планете:
## Layout
- 2 columns, 20 problems per page
- Icons: assets/icons/pack1/
## Pages
### Page 1
- **Task:** A + B +/- C, where A from 8 to 16, B from 4 to 8, C from 1 to 3. Sign +/- chosen randomly
- **Problem count:** 20
- **Hero:** spaceship2.jpeg, direction: row-reverse
### Page 2
- **Task:** 5 * N +/- C, where N from 1 to 5, C from 1 to 6. Sign +/- chosen randomly
- **Problem count:** 20
- **Hero:** spaceship4.jpeg, direction: row
### Page 3
- **Task:** A * B +/- C, where A and B from 1 to 4, C from 1 to 8. Sign +/- chosen randomly
- **Problem count:** 20
- **Hero:** spaceship6.jpeg, direction: row-reverse

View File

@ -0,0 +1,657 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.tailwindcss.com"></script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700;800;900&display=swap" rel="stylesheet">
<title>Исследуй Планету</title>
<script>
tailwind.config = {
theme: {
extend: {
fontFamily: { nunito: ['Nunito', 'sans-serif'] },
}
}
}
</script>
<style>
@page { size: A4; margin: 0; }
</style>
</head>
<body class="bg-gray-200 font-nunito">
<!-- PAGE 1: A + B ± C (A:8-16, B:4-8, C:±1-3) — hero right, spaceship2, planet3 -->
<div class="w-[210mm] h-[297mm] relative overflow-hidden mx-auto bg-white" style="break-after: page;">
<div class="absolute bottom-0 left-0 right-0 h-[80mm] z-0">
<div class="absolute top-0 left-0 right-0 h-full z-10" style="background: linear-gradient(to bottom, white 0%, rgba(255,255,255,0.6) 25%, transparent 50%);"></div>
<img src="../../assets/footers/planet3.jpeg" class="w-full h-full object-cover object-top" alt="">
</div>
<div class="absolute bottom-[12mm] left-0 right-0 z-20 flex justify-center">
<div style="background: rgba(255,255,255,0.85);" class="rounded-full px-6 py-1.5 border-[1.5px] border-indigo-200 shadow-md">
<span class="text-[0.95rem] font-bold text-indigo-950">Итого собрано на планете: <span class="inline-block w-14 border-b-2 border-indigo-400 text-center ml-1">&nbsp;</span></span>
</div>
</div>
<div class="relative z-10 w-full h-full px-[12mm] pt-[4mm] pb-[65mm] flex flex-col">
<div class="flex items-center gap-4 mb-4 flex-row-reverse">
<img src="../../assets/hero-images/spaceship2.png" class="w-[48%] shrink-0 object-contain" alt="">
<div class="flex-1 flex flex-col items-center justify-center text-center">
<h1 class="text-2xl font-extrabold leading-tight tracking-tight text-indigo-950">Исследуй Планету</h1>
<p class="text-sm font-medium text-indigo-400 mt-1">Собери ресурсы, решая примеры!</p>
</div>
</div>
<div class="grid grid-cols-2 gap-x-3 gap-y-[3px] flex-1 content-start">
<div class="flex justify-center">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/plants1-2-0.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">12 + 7 + 2 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-end">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/minerals4-0-3.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">9 + 5 1 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-end">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/plants5-1-0.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">14 + 6 + 3 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-start">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/minerals3-2-1.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">11 + 4 2 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-start">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/minerals2-3-3.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">8 + 8 + 1 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-center">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/plants3-3-2.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">15 + 5 3 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-center">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/plants6-3-2.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">10 + 7 + 2 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-end">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/minerals3-2-0.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">13 + 4 1 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-end">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/plants1-1-1.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">16 + 6 + 3 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-start">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/plants6-0-3.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">9 + 8 2 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-start">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/minerals5-2-2.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">11 + 5 + 1 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-center">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/plants5-3-1.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">14 + 7 3 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-center">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/plants3-1-3.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">8 + 6 + 2 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-end">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/plants3-0-1.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">12 + 4 1 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-end">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/plants1-2-3.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">15 + 8 + 3 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-start">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/plants3-1-0.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">10 + 5 2 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-start">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/plants4-2-0.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">13 + 7 + 1 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-center">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/plants3-2-0.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">16 + 4 3 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-center">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/plants1-0-1.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">9 + 6 + 2 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-end">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/minerals2-3-1.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">11 + 8 1 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- PAGE 2: 5 × N ± C (N:1-5, C:-3..+6) — hero left, spaceship4, planet5 -->
<div class="w-[210mm] h-[297mm] relative overflow-hidden mx-auto bg-white" style="break-after: page;">
<div class="absolute bottom-0 left-0 right-0 h-[80mm] z-0">
<div class="absolute top-0 left-0 right-0 h-full z-10" style="background: linear-gradient(to bottom, white 0%, rgba(255,255,255,0.6) 25%, transparent 50%);"></div>
<img src="../../assets/footers/planet5.jpeg" class="w-full h-full object-cover object-top" alt="">
</div>
<div class="absolute bottom-[12mm] left-0 right-0 z-20 flex justify-center">
<div style="background: rgba(255,255,255,0.85);" class="rounded-full px-6 py-1.5 border-[1.5px] border-indigo-200 shadow-md">
<span class="text-[0.95rem] font-bold text-indigo-950">Итого собрано на планете: <span class="inline-block w-14 border-b-2 border-indigo-400 text-center ml-1">&nbsp;</span></span>
</div>
</div>
<div class="relative z-10 w-full h-full px-[12mm] pt-[4mm] pb-[65mm] flex flex-col">
<div class="flex items-center gap-4 mb-4">
<img src="../../assets/hero-images/spaceship4.jpeg" class="w-[48%] shrink-0 object-contain" alt="">
<div class="flex-1 flex flex-col items-center justify-center text-center">
<h1 class="text-2xl font-extrabold leading-tight tracking-tight text-indigo-950">Исследуй Планету</h1>
<p class="text-sm font-medium text-indigo-400 mt-1">Собери ресурсы, решая примеры!</p>
</div>
</div>
<div class="grid grid-cols-2 gap-x-3 gap-y-[3px] flex-1 content-start">
<div class="flex justify-start">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/minerals4-3-3.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 3 + 4 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-end">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/minerals1-2-1.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 1 2 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-center">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/minerals5-3-3.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 5 + 6 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-start">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/plants2-1-3.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 2 1 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-end">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/minerals6-1-2.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 4 + 3 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-center">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/minerals5-3-0.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 1 + 5 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-start">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/plants2-1-0.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 3 3 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-center">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/minerals5-0-0.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 5 + 2 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-end">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/minerals1-3-0.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 2 + 6 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-start">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/minerals4-1-0.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 4 2 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-center">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/minerals1-0-3.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 1 + 4 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-end">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/plants4-3-1.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 3 + 1 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-start">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/plants4-3-3.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 5 1 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-end">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/plants4-3-0.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 2 + 3 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-center">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/minerals6-0-0.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 4 + 5 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-start">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/minerals4-0-0.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 1 3 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-end">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/minerals4-2-1.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 3 + 6 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-end">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/plants2-3-1.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 2 2 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-center">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/minerals3-1-1.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 5 + 4 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-start">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/minerals2-0-3.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 4 1 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- PAGE 3: A × B ± C (A,B:1-4, C:-4..+8) — hero right, spaceship6, planet1 -->
<div class="w-[210mm] h-[297mm] relative overflow-hidden mx-auto bg-white">
<div class="absolute bottom-0 left-0 right-0 h-[80mm] z-0">
<div class="absolute top-0 left-0 right-0 h-full z-10" style="background: linear-gradient(to bottom, white 0%, rgba(255,255,255,0.6) 25%, transparent 50%);"></div>
<img src="../../assets/footers/planet1.jpeg" class="w-full h-full object-cover object-top" alt="">
</div>
<div class="absolute bottom-[12mm] left-0 right-0 z-20 flex justify-center">
<div style="background: rgba(255,255,255,0.85);" class="rounded-full px-6 py-1.5 border-[1.5px] border-indigo-200 shadow-md">
<span class="text-[0.95rem] font-bold text-indigo-950">Итого собрано на планете: <span class="inline-block w-14 border-b-2 border-indigo-400 text-center ml-1">&nbsp;</span></span>
</div>
</div>
<div class="relative z-10 w-full h-full px-[12mm] pt-[4mm] pb-[65mm] flex flex-col">
<div class="flex items-center gap-4 mb-4 flex-row-reverse">
<img src="../../assets/hero-images/spaceship6.jpeg" class="w-[48%] shrink-0 object-contain" alt="">
<div class="flex-1 flex flex-col items-center justify-center text-center">
<h1 class="text-2xl font-extrabold leading-tight tracking-tight text-indigo-950">Исследуй Планету</h1>
<p class="text-sm font-medium text-indigo-400 mt-1">Собери ресурсы, решая примеры!</p>
</div>
</div>
<div class="grid grid-cols-2 gap-x-3 gap-y-[3px] flex-1 content-start">
<div class="flex justify-end">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/plants6-0-1.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">3 × 4 + 5 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-start">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/minerals6-2-0.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">2 × 3 2 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-center">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/minerals4-1-1.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">4 × 4 + 7 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-end">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/plants6-1-2.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">1 × 3 + 6 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-start">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/minerals2-2-0.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">3 × 2 3 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-center">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/plants1-0-3.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">4 × 3 + 2 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-center">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/minerals1-3-3.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">2 × 4 1 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-end">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/plants5-2-0.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">1 × 4 + 8 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-end">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/plants2-2-1.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">3 × 3 4 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-center">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/plants4-0-2.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">4 × 2 + 3 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-start">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/minerals4-1-2.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">2 × 2 + 5 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-start">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/minerals5-1-1.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">1 × 2 + 7 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-end">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/plants4-0-1.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">4 × 4 3 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-center">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/minerals3-3-2.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">3 × 1 + 4 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-center">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/minerals6-0-2.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">2 × 3 + 6 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-end">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/plants5-1-3.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">4 × 1 2 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-start">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/plants1-3-2.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">3 × 4 + 8 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-start">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/plants4-2-2.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">1 × 3 + 3 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-end">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/minerals5-2-0.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">2 × 4 + 1 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-center">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack1/plants3-0-3.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">4 × 3 4 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,659 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.tailwindcss.com"></script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700;800;900&display=swap" rel="stylesheet">
<title>Исследуй Планету</title>
<script>
tailwind.config = {
theme: {
extend: {
fontFamily: { nunito: ['Nunito', 'sans-serif'] },
}
}
}
</script>
<style>
@page { size: A4; margin: 0; }
</style>
</head>
<body class="bg-gray-200 font-nunito">
<!-- PAGE 1: A + B + C (A:12-24, B:±6-10, C:±2-5, result 0-40) — hero right, spaceship1, planet2 -->
<div class="w-[210mm] h-[297mm] relative overflow-hidden mx-auto bg-white" style="break-after: page;">
<div class="absolute bottom-0 left-0 right-0 h-[80mm] z-0">
<div class="absolute top-0 left-0 right-0 h-full z-10" style="background: linear-gradient(to bottom, white 0%, rgba(255,255,255,0.6) 25%, transparent 50%);"></div>
<img src="../../assets/footers/planet2.jpeg" class="w-full h-full object-cover object-top" alt="">
</div>
<div class="absolute bottom-[12mm] left-0 right-0 z-20 flex justify-center">
<div style="background: rgba(255,255,255,0.85);" class="rounded-full px-6 py-1.5 border-[1.5px] border-indigo-200 shadow-md">
<span class="text-[0.95rem] font-bold text-indigo-950">Итого собрано на планете: <span class="inline-block w-14 border-b-2 border-indigo-400 text-center ml-1">&nbsp;</span></span>
</div>
</div>
<div class="relative z-10 w-full h-full px-[12mm] pt-[4mm] pb-[65mm] flex flex-col">
<div class="flex items-center gap-4 mb-4 flex-row-reverse">
<img src="../../assets/hero-images/spaceship1.jpeg" class="w-[48%] shrink-0 object-contain" alt="">
<div class="flex-1 flex flex-col items-center justify-center text-center">
<h1 class="text-2xl font-extrabold leading-tight tracking-tight text-indigo-950">Исследуй Планету</h1>
<p class="text-sm font-medium text-indigo-400 mt-1">Собери ресурсы, решая примеры!</p>
</div>
</div>
<div class="grid grid-cols-2 gap-x-3 gap-y-[3px] flex-1 content-start">
<div class="flex justify-start">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem3-2-1.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">18 + 7 3 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-end">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem1-0-3.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">15 9 + 4 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-end">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem4-1-2.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">22 + 6 5 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-center">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem2-3-0.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">12 8 + 2 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-center">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem1-2-1.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">20 + 10 + 3 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-start">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem3-0-2.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">16 7 4 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-start">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem4-2-3.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">24 + 8 + 5 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-end">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem2-1-1.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">14 6 + 3 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-center">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem1-3-0.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">19 + 9 2 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-start">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem3-1-3.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">13 10 + 5 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-end">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem2-0-2.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">21 + 7 + 4 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-center">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem4-0-1.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">17 8 3 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-start">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem1-1-0.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">23 + 6 4 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-end">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem3-3-1.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">12 + 10 5 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-center">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem2-2-3.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">15 + 9 + 2 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-start">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem4-1-0.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">20 7 + 3 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-end">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem1-0-1.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">24 6 5 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-center">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem3-2-0.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">18 + 8 2 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-center">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem2-3-2.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">14 + 10 + 4 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-start">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem4-0-3.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">16 9 + 5 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- PAGE 2: 5+5+5 / 5×N / 5×N±5 — hero left, spaceship3, planet4 -->
<div class="w-[210mm] h-[297mm] relative overflow-hidden mx-auto bg-white" style="break-after: page;">
<div class="absolute bottom-0 left-0 right-0 h-[80mm] z-0">
<div class="absolute top-0 left-0 right-0 h-full z-10" style="background: linear-gradient(to bottom, white 0%, rgba(255,255,255,0.6) 25%, transparent 50%);"></div>
<img src="../../assets/footers/planet4.jpeg" class="w-full h-full object-cover object-top" alt="">
</div>
<div class="absolute bottom-[12mm] left-0 right-0 z-20 flex justify-center">
<div style="background: rgba(255,255,255,0.85);" class="rounded-full px-6 py-1.5 border-[1.5px] border-indigo-200 shadow-md">
<span class="text-[0.95rem] font-bold text-indigo-950">Итого собрано на планете: <span class="inline-block w-14 border-b-2 border-indigo-400 text-center ml-1">&nbsp;</span></span>
</div>
</div>
<div class="relative z-10 w-full h-full px-[12mm] pt-[4mm] pb-[65mm] flex flex-col">
<div class="flex items-center gap-4 mb-4">
<img src="../../assets/hero-images/spaceship3.png" class="w-[48%] shrink-0 object-contain" alt="">
<div class="flex-1 flex flex-col items-center justify-center text-center">
<h1 class="text-2xl font-extrabold leading-tight tracking-tight text-indigo-950">Исследуй Планету</h1>
<p class="text-sm font-medium text-indigo-400 mt-1">Собери ресурсы, решая примеры!</p>
</div>
</div>
<div class="font-semibold text-indigo-950 mb-3 text-center" style="font-size: 0.8rem; margin-top: -10px;">Посчитай пятёрками: <span style="font-size: 1rem; word-spacing: 0.25em;">5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60</span> для зарядки расщепителя</div>
<div class="grid grid-cols-2 gap-x-3 gap-y-[3px] flex-1 content-start">
<div class="flex justify-end">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem2-0-0.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 + 5 + 5 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-start">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem4-2-1.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 7 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-center">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem1-3-2.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 3 + 5 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-end">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem3-0-3.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 + 5 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-start">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem2-1-3.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 11 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-center">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem4-0-0.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 5 5 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-end">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem1-1-2.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 + 5 + 5 + 5 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-start">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem3-3-0.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 9 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-start">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem2-2-0.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 6 + 5 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-center">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem4-1-3.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 2 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-center">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem1-0-0.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 8 5 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-end">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem3-1-0.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 4 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-end">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem2-3-1.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 10 + 5 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-start">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem4-2-0.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 + 5 + 5 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-start">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem1-2-3.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 12 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-center">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem3-0-1.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 3 5 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-center">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem2-0-3.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 1 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-end">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem4-1-1.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 7 5 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-end">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem1-3-3.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 8 + 5 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-start">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem3-2-2.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">5 × 6 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- PAGE 3: A×B + C×D (A:2-4, B:1-3, C:2-3, D:1-2) — hero right, spaceship5, planet6 -->
<div class="w-[210mm] h-[297mm] relative overflow-hidden mx-auto bg-white">
<div class="absolute bottom-0 left-0 right-0 h-[80mm] z-0">
<div class="absolute top-0 left-0 right-0 h-full z-10" style="background: linear-gradient(to bottom, white 0%, rgba(255,255,255,0.6) 25%, transparent 50%);"></div>
<img src="../../assets/footers/planet6.jpeg" class="w-full h-full object-cover object-top" alt="">
</div>
<div class="absolute bottom-[12mm] left-0 right-0 z-20 flex justify-center">
<div style="background: rgba(255,255,255,0.85);" class="rounded-full px-6 py-1.5 border-[1.5px] border-indigo-200 shadow-md">
<span class="text-[0.95rem] font-bold text-indigo-950">Итого собрано на планете: <span class="inline-block w-14 border-b-2 border-indigo-400 text-center ml-1">&nbsp;</span></span>
</div>
</div>
<div class="relative z-10 w-full h-full px-[12mm] pt-[4mm] pb-[65mm] flex flex-col">
<div class="flex items-center gap-4 mb-4 flex-row-reverse">
<img src="../../assets/hero-images/spaceship5.jpeg" class="w-[48%] shrink-0 object-contain" alt="">
<div class="flex-1 flex flex-col items-center justify-center text-center">
<h1 class="text-2xl font-extrabold leading-tight tracking-tight text-indigo-950">Исследуй Планету</h1>
<p class="text-sm font-medium text-indigo-400 mt-1">Собери ресурсы, решая примеры!</p>
</div>
</div>
<div class="grid grid-cols-2 gap-x-3 gap-y-[3px] flex-1 content-start">
<div class="flex justify-center">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem2-1-0.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">3 × 2 + 2 × 1 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-start">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem4-0-2.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">4 × 3 + 3 × 2 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-start">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem1-2-0.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">2 × 1 + 3 × 1 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-end">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem3-1-1.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">4 × 2 + 2 × 2 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-end">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem2-2-1.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">3 × 3 + 2 × 1 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-center">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem4-2-2.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">2 × 3 + 3 × 2 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-center">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem1-0-2.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">4 × 1 + 2 × 2 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-start">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem3-3-2.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">3 × 1 + 3 × 1 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-end">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem2-0-1.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">4 × 3 + 2 × 1 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-center">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem3-3-3.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">2 × 2 + 3 × 2 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-start">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem1-1-1.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">3 × 3 + 3 × 2 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-end">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem3-0-0.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">4 × 1 + 2 × 1 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-center">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem2-3-3.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">2 × 3 + 2 × 2 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-start">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem3-2-3.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">4 × 2 + 3 × 1 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-end">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem1-3-1.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">3 × 1 + 2 × 2 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-center">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem3-1-2.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">4 × 3 + 3 × 1 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-start">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem2-2-2.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">2 × 1 + 2 × 1 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-end">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem1-2-2.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">3 × 2 + 3 × 2 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-end">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem2-1-2.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">4 × 2 + 2 × 1 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
<div class="flex justify-start">
<div class="flex items-center gap-1">
<img src="../../assets/icons/pack2/elem1-1-3.png" class="w-[58px] h-[58px] shrink-0 object-contain" alt="">
<div class="pl-3 pr-4 py-1 border-[1.5px] border-indigo-100 rounded-full bg-gradient-to-br from-white to-indigo-50/40 shadow-sm shadow-indigo-100/30">
<span class="text-[1.2rem] font-semibold text-indigo-950 whitespace-nowrap">2 × 2 + 3 × 1 = <span class="inline-block w-16 border-b-[2px] border-indigo-300">&nbsp;</span></span>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,27 @@
# Space Worksheet 2
**Title:** Исследуй Планету
**Subtitle:** Собери ресурсы, ре<D180><D0B5>ая примеры!
**Footer bubble:** Итого собрано на планете:
## Layout
- 2 columns, 20 problems per page
- Icons: assets/icons/pack2/
## Pages
### Page 1
- **Task:** A + B + C, where A from 12 to 24, B +/-(from 6 to 10), C +/-(from 2 to 5). Result from 0 to 40 inclusive
- **Problem count:** 20
- **Hero:** spaceship1.jpeg, direction: row-reverse
### Page 2
- **Task:** 5 + 5 + 5 (adding fives: 2, 3 or 4 of them) OR 5 * N (N from 1 to 12) OR 5 * N +/- 5
- **Problem count:** 20
- **Hero:** spaceship3.png, direction: row
### Page 3
- **Task:** A * B + C * D, where A from 2 to 4, B from 1 to 3, C from 2 to 3, D from 1 to 2
- **Problem count:** 20
- **Hero:** spaceship5.jpeg, direction: row-reverse

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,53 @@
# Space Worksheet 3
**Title:** Исследуй Планету
**Subtitle:** Собери ресу<D181><D183>сы, решая примеры!
**Footer bubble:** Итого собрано на планете:
## Layout
- 2 columns, 20 problems per page
- Icons: mixed from pack1 and pack2
## Notes
9-page worksheet combining patterns from worksheet1 and worksheet2.
Pages 1-3 use pack1 icons, pages 4-6 use pack2 icons, pages 7-9 use pack1 icons.
## Pages
### Page 1 (pack1)
- **Task:** A + B +/- C, where A from 8 to 16, B from 4 to 8, C from 1 to 3. Sign +/- chosen randomly
- **Hero:** spaceship1.jpeg, direction: row-reverse
### Page 2 (pack1)
- **Task:** 5 * N +/- C, where N from 1 to 5, C from 1 to 6. Sign +/- chosen randomly
- **Hero:** spaceship2.jpeg, direction: row
### Page 3 (pack1)
- **Task:** A * B +/- C, where A and B from 1 to 4, C from 1 to 8. Sign +/- chosen randomly
- **Hero:** spaceship3.png, direction: row-reverse
### Page 4 (pack2)
- **Task:** A + B + C, where A from 12 to 24, B +/-(from 6 to 10), C +/-(from 2 to 5). Result from 0 to 40 inclusive
- **Hero:** spaceship4.jpeg, direction: row
### Page 5 (pack2)
- **Task:** 5 + 5 + 5 (adding fives: 2, 3 or 4) OR 5 * N (N from 1 to 12) OR 5 * N +/- 5
- **Hero:** spaceship5.jpeg, direction: row-reverse
### Page 6 (pack2)
- **Task:** A * B + C * D, where A from 2 to 4, B from 1 to 3, C from 2 to 3, D from 1 to 2
- **Hero:** spaceship6.jpeg, direction: row
### Page 7 (pack1)
- **Task:** A + B +/- C, where A from 8 to 16, B from 4 to 8, C from 1 to 3. Sign +/- chosen randomly
- **Hero:** spaceship7.jpeg, direction: row-reverse
### Page 8 (pack1)
- **Task:** 5 * N +/- C, where N from 1 to 5, C from 1 to 6. Sign +/- chosen randomly
- **Hero:** spaceship8.jpeg, direction: row
### Page 9 (pack1)
- **Task:** A * B +/- C, where A and B from 1 to 4, C from 1 to 8. Sign +/- chosen randomly
- **Hero:** spaceship9.jpeg, direction: row-reverse

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,45 @@
#!/usr/bin/env node
/**
* Generate output HTML from template + data for space-exploration documents.
*
* Usage: node generate.mjs <docId>
* Example: node generate.mjs space-exploration-1
*
* Reads: docs/<docId>.template.html
* Reads: docs/<docId>.data.json (optional if missing, copies template as-is)
* Writes: docs/<docId>.output.html
*/
import { readFileSync, writeFileSync, existsSync } from 'fs';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';
const __dirname = dirname(fileURLToPath(import.meta.url));
const docsDir = join(__dirname, '..', 'docs');
const docId = process.argv[2];
if (!docId) {
console.error('Usage: node generate.mjs <docId>');
process.exit(1);
}
const templatePath = join(docsDir, `${docId}.template.html`);
const dataPath = join(docsDir, `${docId}.data.json`);
const outputPath = join(docsDir, `${docId}.output.html`);
if (!existsSync(templatePath)) {
console.error(`Template not found: ${templatePath}`);
process.exit(1);
}
let html = readFileSync(templatePath, 'utf-8');
// If data.json exists, apply it (space-exploration currently has no editor data)
if (existsSync(dataPath)) {
const data = JSON.parse(readFileSync(dataPath, 'utf-8'));
console.log(`Data file found with ${data.pages?.length || 0} pages — no transforms defined yet for space-exploration`);
}
writeFileSync(outputPath, html);
console.log(`Generated: ${outputPath}`);

View File

@ -0,0 +1,43 @@
# Space Route Task Type
Navigate hex graph routes: player and enemy ships travel through a node graph. Child finds a path by following mathematical constraints between connected nodes.
## Generation
Generator script: `scripts/generate-route.mjs`
### Grid Rules
- 7×9 hex grid with jitter, nodes evenly distributed across map area
- Start nodes: Enemy = top-left corner, Player = bottom-left corner
- Start nodes trimmed to exactly 2 edges
### Route Rules
- No asteroids/decorations on route nodes or neighbors of start nodes
- Routes use waypoints: route goes toward an offset waypoint for ~40% of steps, then changes direction toward final target (prevents straight-line paths)
- Route length: 7-9 steps for enemy, player gets 10 empty cells
- Ship orientation: check each ship image and set `flipEnemy`/`flipPlayer` flags so ships face right
### Difficulty
- `diffRange: [minNodeValue, maxSpread]`
- First number = minimum node value
- Second = max |difference| between connected neighbors
## Scripts
- `scripts/generate-route.mjs` — full page generation (grid, edges, values, routes, HTML)
- `scripts/apply-edits.mjs` — apply editor JSON back to HTML (regex-based style replacement)
## Editor
`editor.html?file={docId}` — two edit modes:
**Objects mode** (default): drag space icons, edges auto-follow
**Nodes mode** (press M): Shift+click nodes, drag to reposition graph
Key controls:
- `M`: toggle Objects/Nodes mode
- `R`: toggle enemy route highlight
- `H`: flip selected object horizontally
- `+/-`: resize proportionally
- `[/]`: rotate ±5°
- Save: writes to `docs/{docId}.data.json`

View File

@ -0,0 +1,111 @@
{
"file": "space-route-1.html",
"pages": [
{
"page": 1,
"objects": [
{ "nodeId": 44, "type": "dest", "src": "asteroid5.png", "left": "157.0mm", "top": "183.5mm", "w": "30mm", "h": "30mm", "rotate": 5, "flipH": false },
{ "nodeId": 4, "type": "deco", "src": "asteroid3.png", "left": "133.5mm", "top": "54.5mm", "w": "20mm", "h": "20mm", "rotate": 0, "flipH": false },
{ "nodeId": 15, "type": "deco", "src": "asteroid7.png", "left": "81.0mm", "top": "97.0mm", "w": "54mm", "h": "52mm", "rotate": -20, "flipH": false },
{ "nodeId": 17, "type": "deco", "src": "asteroid11.png", "left": "130.5mm", "top": "97.5mm", "w": "20mm", "h": "20mm", "rotate": 0, "flipH": false },
{ "nodeId": 23, "type": "deco", "src": "pod1.png", "left": "115.5mm", "top": "122.0mm", "w": "34mm", "h": "22mm", "rotate": 0, "flipH": false },
{ "nodeId": 29, "type": "deco", "src": "pod2.png", "left": "109.0mm", "top": "146.5mm", "w": "38mm", "h": "24mm", "rotate": 50, "flipH": false },
{ "nodeId": 42, "type": "deco", "src": "freighter1.png", "left": "104.0mm", "top": "191.5mm", "w": "50mm", "h": "26mm", "rotate": -5, "flipH": false }
],
"nodes": [
{ "nodeId": 0, "left": "53.0mm", "top": "48.0mm" }, { "nodeId": 1, "left": "54.0mm", "top": "69.5mm" }, { "nodeId": 2, "left": "84.0mm", "top": "59.0mm" }, { "nodeId": 3, "left": "108.5mm", "top": "56.5mm" }, { "nodeId": 4, "left": "137.5mm", "top": "59.5mm" }, { "nodeId": 5, "left": "160.0mm", "top": "59.5mm" }, { "nodeId": 6, "left": "190.0mm", "top": "78.0mm" }, { "nodeId": 7, "left": "26.0mm", "top": "72.5mm" }, { "nodeId": 8, "left": "53.5mm", "top": "91.0mm" }, { "nodeId": 9, "left": "96.5mm", "top": "73.5mm" }, { "nodeId": 10, "left": "115.7mm", "top": "74.1mm" }, { "nodeId": 11, "left": "144.4mm", "top": "81.4mm" }, { "nodeId": 12, "left": "167.5mm", "top": "83.5mm" }, { "nodeId": 13, "left": "16.0mm", "top": "107.0mm" }, { "nodeId": 14, "left": "47.5mm", "top": "112.0mm" }, { "nodeId": 15, "left": "80.0mm", "top": "96.5mm" }, { "nodeId": 16, "left": "108.5mm", "top": "97.7mm" }, { "nodeId": 17, "left": "131.2mm", "top": "103.4mm" }, { "nodeId": 18, "left": "155.9mm", "top": "95.4mm" }, { "nodeId": 19, "left": "189.0mm", "top": "114.5mm" }, { "nodeId": 20, "left": "29.0mm", "top": "125.0mm" }, { "nodeId": 21, "left": "70.0mm", "top": "118.5mm" }, { "nodeId": 22, "left": "91.6mm", "top": "117.7mm" }, { "nodeId": 23, "left": "113.5mm", "top": "119.8mm" }, { "nodeId": 24, "left": "142.3mm", "top": "117.4mm" }, { "nodeId": 25, "left": "174.0mm", "top": "125.0mm" }, { "nodeId": 26, "left": "23.5mm", "top": "142.1mm" }, { "nodeId": 27, "left": "50.0mm", "top": "145.1mm" }, { "nodeId": 28, "left": "78.0mm", "top": "149.0mm" }, { "nodeId": 29, "left": "103.2mm", "top": "146.3mm" }, { "nodeId": 30, "left": "135.0mm", "top": "139.5mm" }, { "nodeId": 31, "left": "158.9mm", "top": "143.9mm" }, { "nodeId": 32, "left": "177.7mm", "top": "148.2mm" }, { "nodeId": 33, "left": "36.9mm", "top": "166.8mm" }, { "nodeId": 34, "left": "62.6mm", "top": "162.8mm" }, { "nodeId": 35, "left": "100.5mm", "top": "169.0mm" }, { "nodeId": 36, "left": "129.5mm", "top": "170.5mm" }, { "nodeId": 37, "left": "146.0mm", "top": "155.0mm" }, { "nodeId": 38, "left": "166.1mm", "top": "160.7mm" }, { "nodeId": 39, "left": "23.8mm", "top": "191.2mm" }, { "nodeId": 40, "left": "55.3mm", "top": "183.2mm" }, { "nodeId": 41, "left": "78.0mm", "top": "176.0mm" }, { "nodeId": 42, "left": "102.0mm", "top": "199.5mm" }, { "nodeId": 43, "left": "139.5mm", "top": "195.0mm" }, { "nodeId": 44, "left": "157.5mm", "top": "176.0mm" }, { "nodeId": 45, "left": "180.8mm", "top": "190.7mm" }, { "nodeId": 46, "left": "36.3mm", "top": "208.1mm" }, { "nodeId": 47, "left": "57.5mm", "top": "209.0mm" }, { "nodeId": 48, "left": "79.5mm", "top": "215.0mm" }, { "nodeId": 49, "left": "121.0mm", "top": "209.0mm" }, { "nodeId": 50, "left": "146.0mm", "top": "211.5mm" }, { "nodeId": 51, "left": "169.5mm", "top": "206.0mm" }, { "nodeId": 52, "left": "24.3mm", "top": "235.9mm" }, { "nodeId": 53, "left": "57.2mm", "top": "230.9mm" }, { "nodeId": 54, "left": "82.5mm", "top": "232.7mm" }, { "nodeId": 55, "left": "102.5mm", "top": "227.0mm" }, { "nodeId": 56, "left": "125.6mm", "top": "227.0mm" }, { "nodeId": 57, "left": "157.3mm", "top": "233.1mm" }, { "nodeId": 58, "left": "181.5mm", "top": "226.4mm" }
]
},
{
"page": 2,
"objects": [
{ "nodeId": 44, "type": "dest", "src": "pod6.png", "left": "174.5mm", "top": "179.5mm", "w": "20mm", "h": "19mm", "rotate": 0, "flipH": false },
{ "nodeId": 5, "type": "deco", "src": "asteroid9.png", "left": "157.2mm", "top": "56.0mm", "w": "54mm", "h": "52mm", "rotate": 55, "flipH": false },
{ "nodeId": 11, "type": "deco", "src": "asteroid14.png", "left": "146.9mm", "top": "82.1mm", "w": "16mm", "h": "15mm", "rotate": 0, "flipH": false },
{ "nodeId": 21, "type": "deco", "src": "asteroid2.png", "left": "60.5mm", "top": "122.0mm", "w": "24mm", "h": "24mm", "rotate": 0, "flipH": false },
{ "nodeId": 28, "type": "deco", "src": "pod4.png", "left": "85.0mm", "top": "142.5mm", "w": "24mm", "h": "15mm", "rotate": 0, "flipH": false },
{ "nodeId": 34, "type": "deco", "src": "pod5.png", "left": "62.0mm", "top": "168.0mm", "w": "24mm", "h": "15mm", "rotate": 0, "flipH": false },
{ "nodeId": 43, "type": "deco", "src": "freighter2.png", "left": "130.5mm", "top": "194.5mm", "w": "58mm", "h": "30mm", "rotate": -5, "flipH": false }
],
"nodes": [
{ "nodeId": 0, "left": "44.5mm", "top": "47.5mm" }, { "nodeId": 1, "left": "62.0mm", "top": "58.5mm" }, { "nodeId": 2, "left": "93.0mm", "top": "69.5mm" }, { "nodeId": 3, "left": "101.0mm", "top": "54.5mm" }, { "nodeId": 4, "left": "127.1mm", "top": "52.9mm" }, { "nodeId": 5, "left": "152.5mm", "top": "58.0mm" }, { "nodeId": 6, "left": "185.0mm", "top": "54.5mm" }, { "nodeId": 7, "left": "19.5mm", "top": "76.5mm" }, { "nodeId": 8, "left": "63.0mm", "top": "78.5mm" }, { "nodeId": 9, "left": "104.0mm", "top": "86.5mm" }, { "nodeId": 10, "left": "120.9mm", "top": "75.2mm" }, { "nodeId": 11, "left": "146.9mm", "top": "82.1mm" }, { "nodeId": 12, "left": "166.6mm", "top": "75.0mm" }, { "nodeId": 13, "left": "12.0mm", "top": "106.0mm" }, { "nodeId": 14, "left": "31.0mm", "top": "100.5mm" }, { "nodeId": 15, "left": "62.5mm", "top": "98.5mm" }, { "nodeId": 16, "left": "106.8mm", "top": "103.6mm" }, { "nodeId": 17, "left": "128.7mm", "top": "102.1mm" }, { "nodeId": 18, "left": "155.9mm", "top": "99.8mm" }, { "nodeId": 19, "left": "180.8mm", "top": "96.9mm" }, { "nodeId": 20, "left": "22.0mm", "top": "124.5mm" }, { "nodeId": 21, "left": "59.0mm", "top": "120.0mm" }, { "nodeId": 22, "left": "89.5mm", "top": "119.0mm" }, { "nodeId": 23, "left": "121.5mm", "top": "119.5mm" }, { "nodeId": 24, "left": "141.9mm", "top": "124.3mm" }, { "nodeId": 25, "left": "168.5mm", "top": "118.0mm" }, { "nodeId": 26, "left": "14.0mm", "top": "155.0mm" }, { "nodeId": 27, "left": "50.8mm", "top": "142.4mm" }, { "nodeId": 28, "left": "85.5mm", "top": "141.0mm" }, { "nodeId": 29, "left": "110.3mm", "top": "147.9mm" }, { "nodeId": 30, "left": "128.0mm", "top": "153.5mm" }, { "nodeId": 31, "left": "162.3mm", "top": "144.4mm" }, { "nodeId": 32, "left": "188.0mm", "top": "129.0mm" }, { "nodeId": 33, "left": "36.2mm", "top": "163.9mm" }, { "nodeId": 34, "left": "66.0mm", "top": "167.5mm" }, { "nodeId": 35, "left": "90.1mm", "top": "164.2mm" }, { "nodeId": 36, "left": "113.3mm", "top": "169.1mm" }, { "nodeId": 37, "left": "140.5mm", "top": "170.5mm" }, { "nodeId": 38, "left": "187.5mm", "top": "153.5mm" }, { "nodeId": 39, "left": "15.0mm", "top": "184.0mm" }, { "nodeId": 40, "left": "51.0mm", "top": "188.5mm" }, { "nodeId": 41, "left": "69.5mm", "top": "185.5mm" }, { "nodeId": 42, "left": "93.0mm", "top": "189.5mm" }, { "nodeId": 43, "left": "137.5mm", "top": "196.0mm" }, { "nodeId": 44, "left": "172.0mm", "top": "177.5mm" }, { "nodeId": 45, "left": "197.0mm", "top": "173.5mm" }, { "nodeId": 46, "left": "26.0mm", "top": "202.5mm" }, { "nodeId": 47, "left": "66.0mm", "top": "202.0mm" }, { "nodeId": 48, "left": "81.5mm", "top": "207.5mm" }, { "nodeId": 49, "left": "107.5mm", "top": "211.0mm" }, { "nodeId": 50, "left": "160.0mm", "top": "213.5mm" }, { "nodeId": 51, "left": "181.5mm", "top": "222.5mm" }, { "nodeId": 52, "left": "36.5mm", "top": "236.0mm" }, { "nodeId": 53, "left": "49.0mm", "top": "214.0mm" }, { "nodeId": 54, "left": "76.5mm", "top": "223.5mm" }, { "nodeId": 55, "left": "100.5mm", "top": "232.0mm" }, { "nodeId": 56, "left": "134.0mm", "top": "222.5mm" }, { "nodeId": 57, "left": "156.2mm", "top": "233.5mm" }, { "nodeId": 58, "left": "200.5mm", "top": "214.0mm" }
]
},
{
"page": 3,
"objects": [
{ "nodeId": 51, "type": "dest", "src": "freighter8.png", "left": "160.0mm", "top": "217.5mm", "w": "52mm", "h": "32mm", "rotate": -15, "flipH": false },
{ "nodeId": 2, "type": "deco", "src": "asteroid1.png", "left": "67.5mm", "top": "67.5mm", "w": "20mm", "h": "20mm", "rotate": 0, "flipH": false },
{ "nodeId": 9, "type": "deco", "src": "asteroid10.png", "left": "93.5mm", "top": "74.0mm", "w": "26mm", "h": "26mm", "rotate": 0, "flipH": false },
{ "nodeId": 19, "type": "deco", "src": "asteroid6.png", "left": "187.6mm", "top": "100.3mm", "w": "16mm", "h": "15mm", "rotate": 0, "flipH": false },
{ "nodeId": 23, "type": "deco", "src": "pod8.png", "left": "113.1mm", "top": "126.1mm", "w": "20mm", "h": "12mm", "rotate": -25, "flipH": false },
{ "nodeId": 26, "type": "deco", "src": "pod10.png", "left": "19.5mm", "top": "143.0mm", "w": "36mm", "h": "23mm", "rotate": 0, "flipH": false },
{ "nodeId": 35, "type": "deco", "src": "freighter5.png", "left": "86.5mm", "top": "168.5mm", "w": "58mm", "h": "30mm", "rotate": 0, "flipH": false }
],
"nodes": [
{ "nodeId": 0, "left": "41.5mm", "top": "46.5mm" }, { "nodeId": 1, "left": "48.5mm", "top": "77.0mm" }, { "nodeId": 2, "left": "67.0mm", "top": "67.0mm" }, { "nodeId": 3, "left": "110.1mm", "top": "57.1mm" }, { "nodeId": 4, "left": "134.4mm", "top": "59.9mm" }, { "nodeId": 5, "left": "158.2mm", "top": "52.6mm" }, { "nodeId": 6, "left": "185.4mm", "top": "49.6mm" }, { "nodeId": 7, "left": "25.0mm", "top": "63.0mm" }, { "nodeId": 8, "left": "57.0mm", "top": "96.5mm" }, { "nodeId": 9, "left": "93.0mm", "top": "74.0mm" }, { "nodeId": 10, "left": "116.9mm", "top": "73.4mm" }, { "nodeId": 11, "left": "140.3mm", "top": "80.8mm" }, { "nodeId": 12, "left": "165.0mm", "top": "81.8mm" }, { "nodeId": 13, "left": "17.0mm", "top": "107.0mm" }, { "nodeId": 14, "left": "39.0mm", "top": "103.5mm" }, { "nodeId": 15, "left": "82.5mm", "top": "97.4mm" }, { "nodeId": 16, "left": "108.9mm", "top": "100.6mm" }, { "nodeId": 17, "left": "133.1mm", "top": "93.6mm" }, { "nodeId": 18, "left": "156.3mm", "top": "100.2mm" }, { "nodeId": 19, "left": "187.6mm", "top": "100.3mm" }, { "nodeId": 20, "left": "34.7mm", "top": "124.1mm" }, { "nodeId": 21, "left": "70.7mm", "top": "123.2mm" }, { "nodeId": 22, "left": "90.0mm", "top": "117.0mm" }, { "nodeId": 23, "left": "113.1mm", "top": "126.1mm" }, { "nodeId": 24, "left": "141.7mm", "top": "125.1mm" }, { "nodeId": 25, "left": "175.2mm", "top": "117.0mm" }, { "nodeId": 26, "left": "23.5mm", "top": "141.5mm" }, { "nodeId": 27, "left": "54.0mm", "top": "135.5mm" }, { "nodeId": 28, "left": "74.5mm", "top": "139.5mm" }, { "nodeId": 29, "left": "94.5mm", "top": "145.5mm" }, { "nodeId": 30, "left": "146.5mm", "top": "141.5mm" }, { "nodeId": 31, "left": "166.5mm", "top": "134.5mm" }, { "nodeId": 32, "left": "187.9mm", "top": "139.2mm" }, { "nodeId": 33, "left": "23.5mm", "top": "166.5mm" }, { "nodeId": 34, "left": "48.0mm", "top": "165.5mm" }, { "nodeId": 35, "left": "89.0mm", "top": "167.0mm" }, { "nodeId": 36, "left": "128.5mm", "top": "153.0mm" }, { "nodeId": 37, "left": "149.0mm", "top": "160.5mm" }, { "nodeId": 38, "left": "168.7mm", "top": "168.2mm" }, { "nodeId": 39, "left": "28.6mm", "top": "188.9mm" }, { "nodeId": 40, "left": "50.8mm", "top": "185.4mm" }, { "nodeId": 41, "left": "68.0mm", "top": "194.0mm" }, { "nodeId": 42, "left": "108.0mm", "top": "191.5mm" }, { "nodeId": 43, "left": "130.0mm", "top": "187.1mm" }, { "nodeId": 44, "left": "151.5mm", "top": "181.5mm" }, { "nodeId": 45, "left": "185.4mm", "top": "184.6mm" }, { "nodeId": 46, "left": "21.0mm", "top": "219.0mm" }, { "nodeId": 47, "left": "46.5mm", "top": "208.0mm" }, { "nodeId": 48, "left": "90.1mm", "top": "205.9mm" }, { "nodeId": 49, "left": "110.0mm", "top": "211.5mm" }, { "nodeId": 50, "left": "134.0mm", "top": "205.5mm" }, { "nodeId": 51, "left": "167.0mm", "top": "215.5mm" }, { "nodeId": 52, "left": "54.5mm", "top": "243.0mm" }, { "nodeId": 53, "left": "59.5mm", "top": "223.0mm" }, { "nodeId": 54, "left": "83.5mm", "top": "225.5mm" }, { "nodeId": 55, "left": "108.0mm", "top": "243.0mm" }, { "nodeId": 56, "left": "127.5mm", "top": "230.0mm" }, { "nodeId": 57, "left": "161.0mm", "top": "242.5mm" }, { "nodeId": 58, "left": "199.5mm", "top": "235.5mm" }
]
},
{
"page": 4,
"objects": [
{ "nodeId": 44, "type": "dest", "src": "pod16.png", "left": "157.5mm", "top": "189.5mm", "w": "58mm", "h": "49mm", "rotate": 0, "flipH": false },
{ "nodeId": 2, "type": "deco", "src": "asteroid12.png", "left": "73.5mm", "top": "69.5mm", "w": "20mm", "h": "20mm", "rotate": -60, "flipH": false },
{ "nodeId": 10, "type": "deco", "src": "asteroid4.png", "left": "122.0mm", "top": "78.5mm", "w": "16mm", "h": "15mm", "rotate": -35, "flipH": false },
{ "nodeId": 14, "type": "deco", "src": "asteroid15.png", "left": "38.0mm", "top": "103.5mm", "w": "20mm", "h": "20mm", "rotate": -35, "flipH": false },
{ "nodeId": 27, "type": "deco", "src": "pod11.png", "left": "49.0mm", "top": "139.8mm", "w": "30mm", "h": "19mm", "rotate": 0, "flipH": false },
{ "nodeId": 35, "type": "deco", "src": "pod13.png", "left": "91.1mm", "top": "166.1mm", "w": "32mm", "h": "20mm", "rotate": 0, "flipH": false },
{ "nodeId": 40, "type": "deco", "src": "freighter3.png", "left": "52.5mm", "top": "190.0mm", "w": "58mm", "h": "34mm", "rotate": 0, "flipH": false }
],
"nodes": [
{ "nodeId": 0, "left": "40.0mm", "top": "49.0mm" }, { "nodeId": 1, "left": "43.0mm", "top": "84.5mm" }, { "nodeId": 2, "left": "74.0mm", "top": "70.0mm" }, { "nodeId": 3, "left": "99.6mm", "top": "49.7mm" }, { "nodeId": 4, "left": "133.4mm", "top": "53.4mm" }, { "nodeId": 5, "left": "155.4mm", "top": "52.9mm" }, { "nodeId": 6, "left": "178.0mm", "top": "62.5mm" }, { "nodeId": 7, "left": "20.0mm", "top": "65.0mm" }, { "nodeId": 8, "left": "73.5mm", "top": "87.5mm" }, { "nodeId": 9, "left": "93.3mm", "top": "77.4mm" }, { "nodeId": 10, "left": "122.5mm", "top": "79.0mm" }, { "nodeId": 11, "left": "146.3mm", "top": "81.5mm" }, { "nodeId": 12, "left": "166.5mm", "top": "81.0mm" }, { "nodeId": 13, "left": "14.0mm", "top": "84.0mm" }, { "nodeId": 14, "left": "38.5mm", "top": "104.0mm" }, { "nodeId": 15, "left": "81.9mm", "top": "100.0mm" }, { "nodeId": 16, "left": "101.1mm", "top": "96.3mm" }, { "nodeId": 17, "left": "135.6mm", "top": "97.4mm" }, { "nodeId": 18, "left": "152.0mm", "top": "99.0mm" }, { "nodeId": 19, "left": "180.4mm", "top": "100.8mm" }, { "nodeId": 20, "left": "26.5mm", "top": "117.5mm" }, { "nodeId": 21, "left": "66.3mm", "top": "126.0mm" }, { "nodeId": 22, "left": "86.5mm", "top": "123.1mm" }, { "nodeId": 23, "left": "117.3mm", "top": "120.7mm" }, { "nodeId": 24, "left": "149.4mm", "top": "117.2mm" }, { "nodeId": 25, "left": "166.6mm", "top": "123.3mm" }, { "nodeId": 26, "left": "18.0mm", "top": "139.0mm" }, { "nodeId": 27, "left": "48.0mm", "top": "137.5mm" }, { "nodeId": 28, "left": "81.6mm", "top": "143.1mm" }, { "nodeId": 29, "left": "102.5mm", "top": "141.1mm" }, { "nodeId": 30, "left": "127.0mm", "top": "144.8mm" }, { "nodeId": 31, "left": "158.0mm", "top": "137.9mm" }, { "nodeId": 32, "left": "181.3mm", "top": "142.7mm" }, { "nodeId": 33, "left": "27.0mm", "top": "160.0mm" }, { "nodeId": 34, "left": "68.0mm", "top": "166.8mm" }, { "nodeId": 35, "left": "91.5mm", "top": "168.0mm" }, { "nodeId": 36, "left": "131.5mm", "top": "161.0mm" }, { "nodeId": 37, "left": "154.0mm", "top": "154.0mm" }, { "nodeId": 38, "left": "172.1mm", "top": "163.0mm" }, { "nodeId": 39, "left": "9.5mm", "top": "175.0mm" }, { "nodeId": 40, "left": "62.0mm", "top": "190.0mm" }, { "nodeId": 41, "left": "99.0mm", "top": "195.5mm" }, { "nodeId": 42, "left": "111.5mm", "top": "176.5mm" }, { "nodeId": 43, "left": "133.5mm", "top": "181.0mm" }, { "nodeId": 44, "left": "158.5mm", "top": "192.0mm" }, { "nodeId": 45, "left": "184.1mm", "top": "184.2mm" }, { "nodeId": 46, "left": "10.5mm", "top": "199.0mm" }, { "nodeId": 47, "left": "72.0mm", "top": "218.5mm" }, { "nodeId": 48, "left": "98.0mm", "top": "220.5mm" }, { "nodeId": 49, "left": "122.0mm", "top": "207.5mm" }, { "nodeId": 50, "left": "145.6mm", "top": "207.9mm" }, { "nodeId": 51, "left": "168.9mm", "top": "207.7mm" }, { "nodeId": 52, "left": "35.5mm", "top": "241.0mm" }, { "nodeId": 53, "left": "40.5mm", "top": "221.0mm" }, { "nodeId": 54, "left": "82.7mm", "top": "234.9mm" }, { "nodeId": 55, "left": "112.0mm", "top": "242.0mm" }, { "nodeId": 56, "left": "127.5mm", "top": "226.9mm" }, { "nodeId": 57, "left": "160.6mm", "top": "226.6mm" }, { "nodeId": 58, "left": "178.5mm", "top": "235.8mm" }
]
},
{
"page": 5,
"objects": [
{ "nodeId": 44, "type": "dest", "src": "asteroid16.png", "left": "148.5mm", "top": "182.0mm", "w": "24mm", "h": "24mm", "rotate": 0, "flipH": false },
{ "nodeId": 4, "type": "deco", "src": "asteroid8.png", "left": "132.5mm", "top": "55.5mm", "w": "28mm", "h": "28mm", "rotate": -10, "flipH": false },
{ "nodeId": 9, "type": "deco", "src": "asteroid13.png", "left": "91.0mm", "top": "81.0mm", "w": "18mm", "h": "17mm", "rotate": -20, "flipH": false },
{ "nodeId": 13, "type": "deco", "src": "asteroid3.png", "left": "16.5mm", "top": "104.0mm", "w": "20mm", "h": "20mm", "rotate": 0, "flipH": false },
{ "nodeId": 24, "type": "deco", "src": "pod7.png", "left": "146.5mm", "top": "125.0mm", "w": "40mm", "h": "25mm", "rotate": 10, "flipH": false },
{ "nodeId": 38, "type": "deco", "src": "pod9.png", "left": "179.5mm", "top": "159.5mm", "w": "26mm", "h": "17mm", "rotate": 15, "flipH": false },
{ "nodeId": 50, "type": "deco", "src": "freighter6.png", "left": "147.0mm", "top": "221.5mm", "w": "60mm", "h": "31mm", "rotate": 0, "flipH": false }
],
"nodes": [
{ "nodeId": 0, "left": "37.5mm", "top": "47.0mm" }, { "nodeId": 1, "left": "48.0mm", "top": "64.0mm" }, { "nodeId": 2, "left": "76.0mm", "top": "58.2mm" }, { "nodeId": 3, "left": "103.3mm", "top": "60.2mm" }, { "nodeId": 4, "left": "132.5mm", "top": "57.0mm" }, { "nodeId": 5, "left": "155.6mm", "top": "59.8mm" }, { "nodeId": 6, "left": "185.8mm", "top": "55.4mm" }, { "nodeId": 7, "left": "13.0mm", "top": "68.0mm" }, { "nodeId": 8, "left": "57.0mm", "top": "80.5mm" }, { "nodeId": 9, "left": "91.5mm", "top": "81.5mm" }, { "nodeId": 10, "left": "118.4mm", "top": "79.0mm" }, { "nodeId": 11, "left": "142.3mm", "top": "75.3mm" }, { "nodeId": 12, "left": "170.3mm", "top": "81.6mm" }, { "nodeId": 13, "left": "15.0mm", "top": "104.0mm" }, { "nodeId": 14, "left": "49.2mm", "top": "96.4mm" }, { "nodeId": 15, "left": "78.6mm", "top": "99.7mm" }, { "nodeId": 16, "left": "102.2mm", "top": "103.0mm" }, { "nodeId": 17, "left": "129.1mm", "top": "100.7mm" }, { "nodeId": 18, "left": "154.4mm", "top": "99.9mm" }, { "nodeId": 19, "left": "193.5mm", "top": "103.0mm" }, { "nodeId": 20, "left": "27.0mm", "top": "126.5mm" }, { "nodeId": 21, "left": "69.9mm", "top": "117.8mm" }, { "nodeId": 22, "left": "92.8mm", "top": "121.9mm" }, { "nodeId": 23, "left": "113.9mm", "top": "116.1mm" }, { "nodeId": 24, "left": "146.5mm", "top": "123.5mm" }, { "nodeId": 25, "left": "180.0mm", "top": "119.5mm" }, { "nodeId": 26, "left": "16.0mm", "top": "152.0mm" }, { "nodeId": 27, "left": "45.5mm", "top": "143.0mm" }, { "nodeId": 28, "left": "76.6mm", "top": "146.3mm" }, { "nodeId": 29, "left": "99.5mm", "top": "137.9mm" }, { "nodeId": 30, "left": "122.5mm", "top": "138.5mm" }, { "nodeId": 31, "left": "160.6mm", "top": "144.4mm" }, { "nodeId": 32, "left": "187.5mm", "top": "138.5mm" }, { "nodeId": 33, "left": "43.3mm", "top": "163.2mm" }, { "nodeId": 34, "left": "62.0mm", "top": "162.4mm" }, { "nodeId": 35, "left": "87.4mm", "top": "161.9mm" }, { "nodeId": 36, "left": "115.5mm", "top": "166.0mm" }, { "nodeId": 37, "left": "143.5mm", "top": "154.0mm" }, { "nodeId": 38, "left": "179.0mm", "top": "163.5mm" }, { "nodeId": 39, "left": "31.0mm", "top": "187.2mm" }, { "nodeId": 40, "left": "52.0mm", "top": "185.4mm" }, { "nodeId": 41, "left": "78.0mm", "top": "191.1mm" }, { "nodeId": 42, "left": "105.5mm", "top": "189.6mm" }, { "nodeId": 43, "left": "126.9mm", "top": "188.7mm" }, { "nodeId": 44, "left": "150.5mm", "top": "183.5mm" }, { "nodeId": 45, "left": "194.5mm", "top": "184.0mm" }, { "nodeId": 46, "left": "14.5mm", "top": "216.5mm" }, { "nodeId": 47, "left": "46.5mm", "top": "205.5mm" }, { "nodeId": 48, "left": "73.0mm", "top": "212.0mm" }, { "nodeId": 49, "left": "104.0mm", "top": "208.5mm" }, { "nodeId": 50, "left": "163.5mm", "top": "221.5mm" }, { "nodeId": 51, "left": "196.0mm", "top": "217.5mm" }, { "nodeId": 52, "left": "45.0mm", "top": "244.5mm" }, { "nodeId": 53, "left": "40.5mm", "top": "224.0mm" }, { "nodeId": 54, "left": "75.1mm", "top": "231.5mm" }, { "nodeId": 55, "left": "102.0mm", "top": "232.0mm" }, { "nodeId": 56, "left": "130.5mm", "top": "245.0mm" }, { "nodeId": 57, "left": "169.0mm", "top": "252.5mm" }, { "nodeId": 58, "left": "200.0mm", "top": "251.5mm" }
]
},
{
"page": 6,
"objects": [
{ "nodeId": 51, "type": "dest", "src": "freighter2.png", "left": "174.5mm", "top": "211.0mm", "w": "60mm", "h": "40mm", "rotate": 0, "flipH": false },
{ "nodeId": 4, "type": "deco", "src": "freighter9.png", "left": "133.5mm", "top": "48.5mm", "w": "52mm", "h": "27mm", "rotate": 0, "flipH": false },
{ "nodeId": 10, "type": "deco", "src": "freighter10.png", "left": "104.0mm", "top": "84.5mm", "w": "54mm", "h": "28mm", "rotate": -5, "flipH": false },
{ "nodeId": 13, "type": "deco", "src": "pod14.png", "left": "20.5mm", "top": "106.5mm", "w": "48mm", "h": "30mm", "rotate": -20, "flipH": false },
{ "nodeId": 24, "type": "deco", "src": "pod15.png", "left": "140.0mm", "top": "114.5mm", "w": "28mm", "h": "18mm", "rotate": 0, "flipH": false },
{ "nodeId": 32, "type": "deco", "src": "pod17.png", "left": "182.5mm", "top": "142.0mm", "w": "38mm", "h": "24mm", "rotate": 0, "flipH": false },
{ "nodeId": 35, "type": "deco", "src": "asteroid3.png", "left": "77.5mm", "top": "161.0mm", "w": "20mm", "h": "20mm", "rotate": 0, "flipH": false },
{ "nodeId": 42, "type": "deco", "src": "asteroid11.png", "left": "101.0mm", "top": "191.5mm", "w": "20mm", "h": "20mm", "rotate": 0, "flipH": false }
],
"nodes": [
{ "nodeId": 0, "left": "35.5mm", "top": "49.5mm" }, { "nodeId": 1, "left": "53.5mm", "top": "68.0mm" }, { "nodeId": 2, "left": "82.1mm", "top": "54.4mm" }, { "nodeId": 3, "left": "102.5mm", "top": "59.5mm" }, { "nodeId": 4, "left": "132.0mm", "top": "53.5mm" }, { "nodeId": 5, "left": "164.5mm", "top": "49.0mm" }, { "nodeId": 6, "left": "189.5mm", "top": "52.0mm" }, { "nodeId": 7, "left": "18.5mm", "top": "80.0mm" }, { "nodeId": 8, "left": "60.9mm", "top": "80.5mm" }, { "nodeId": 9, "left": "84.5mm", "top": "70.5mm" }, { "nodeId": 10, "left": "101.5mm", "top": "85.5mm" }, { "nodeId": 11, "left": "155.0mm", "top": "75.5mm" }, { "nodeId": 12, "left": "189.5mm", "top": "80.0mm" }, { "nodeId": 13, "left": "26.5mm", "top": "103.5mm" }, { "nodeId": 14, "left": "56.0mm", "top": "99.8mm" }, { "nodeId": 15, "left": "78.0mm", "top": "104.0mm" }, { "nodeId": 16, "left": "107.7mm", "top": "103.0mm" }, { "nodeId": 17, "left": "133.0mm", "top": "93.8mm" }, { "nodeId": 18, "left": "158.8mm", "top": "97.4mm" }, { "nodeId": 19, "left": "188.1mm", "top": "104.0mm" }, { "nodeId": 20, "left": "40.0mm", "top": "123.0mm" }, { "nodeId": 21, "left": "62.0mm", "top": "131.5mm" }, { "nodeId": 22, "left": "92.1mm", "top": "121.0mm" }, { "nodeId": 23, "left": "113.5mm", "top": "123.5mm" }, { "nodeId": 24, "left": "141.0mm", "top": "114.5mm" }, { "nodeId": 25, "left": "174.8mm", "top": "122.5mm" }, { "nodeId": 26, "left": "20.0mm", "top": "140.5mm" }, { "nodeId": 27, "left": "49.1mm", "top": "138.9mm" }, { "nodeId": 28, "left": "74.5mm", "top": "144.0mm" }, { "nodeId": 29, "left": "107.5mm", "top": "142.0mm" }, { "nodeId": 30, "left": "127.9mm", "top": "142.6mm" }, { "nodeId": 31, "left": "146.5mm", "top": "146.5mm" }, { "nodeId": 32, "left": "177.0mm", "top": "140.0mm" }, { "nodeId": 33, "left": "23.0mm", "top": "162.5mm" }, { "nodeId": 34, "left": "53.5mm", "top": "157.5mm" }, { "nodeId": 35, "left": "77.5mm", "top": "160.0mm" }, { "nodeId": 36, "left": "119.0mm", "top": "160.5mm" }, { "nodeId": 37, "left": "141.5mm", "top": "173.5mm" }, { "nodeId": 38, "left": "174.0mm", "top": "168.5mm" }, { "nodeId": 39, "left": "30.0mm", "top": "186.9mm" }, { "nodeId": 40, "left": "53.7mm", "top": "181.6mm" }, { "nodeId": 41, "left": "73.6mm", "top": "190.8mm" }, { "nodeId": 42, "left": "101.0mm", "top": "192.5mm" }, { "nodeId": 43, "left": "121.0mm", "top": "186.0mm" }, { "nodeId": 44, "left": "153.7mm", "top": "187.6mm" }, { "nodeId": 45, "left": "182.3mm", "top": "189.9mm" }, { "nodeId": 46, "left": "13.5mm", "top": "210.5mm" }, { "nodeId": 47, "left": "42.5mm", "top": "207.0mm" }, { "nodeId": 48, "left": "79.5mm", "top": "209.5mm" }, { "nodeId": 49, "left": "115.9mm", "top": "208.0mm" }, { "nodeId": 50, "left": "132.5mm", "top": "212.5mm" }, { "nodeId": 51, "left": "176.5mm", "top": "212.5mm" }, { "nodeId": 52, "left": "44.5mm", "top": "243.5mm" }, { "nodeId": 53, "left": "46.0mm", "top": "224.0mm" }, { "nodeId": 54, "left": "81.5mm", "top": "225.9mm" }, { "nodeId": 55, "left": "96.5mm", "top": "242.5mm" }, { "nodeId": 56, "left": "124.5mm", "top": "243.0mm" }, { "nodeId": 57, "left": "147.5mm", "top": "230.0mm" }, { "nodeId": 58, "left": "180.0mm", "top": "240.0mm" }
]
},
{
"page": 7,
"objects": [
{ "nodeId": 43, "type": "dest", "src": "pod18.png", "left": "121.0mm", "top": "202.5mm", "w": "32mm", "h": "28mm", "rotate": 0, "flipH": false },
{ "nodeId": 4, "type": "deco", "src": "asteroid7.png", "left": "132.0mm", "top": "42.5mm", "w": "46mm", "h": "44mm", "rotate": -10, "flipH": false },
{ "nodeId": 12, "type": "deco", "src": "asteroid15.png", "left": "175.5mm", "top": "71.0mm", "w": "20mm", "h": "20mm", "rotate": 0, "flipH": false },
{ "nodeId": 23, "type": "deco", "src": "asteroid5.png", "left": "111.0mm", "top": "113.0mm", "w": "22mm", "h": "22mm", "rotate": -10, "flipH": false },
{ "nodeId": 31, "type": "deco", "src": "pod3.png", "left": "157.0mm", "top": "142.5mm", "w": "40mm", "h": "25mm", "rotate": 0, "flipH": false },
{ "nodeId": 29, "type": "deco", "src": "pod12.png", "left": "96.5mm", "top": "139.0mm", "w": "28mm", "h": "18mm", "rotate": 0, "flipH": false },
{ "nodeId": 44, "type": "deco", "src": "freighter4.png", "left": "159.5mm", "top": "189.5mm", "w": "58mm", "h": "30mm", "rotate": 0, "flipH": false }
],
"nodes": [
{ "nodeId": 0, "left": "39.0mm", "top": "48.0mm" }, { "nodeId": 1, "left": "48.5mm", "top": "65.5mm" }, { "nodeId": 2, "left": "83.4mm", "top": "54.6mm" }, { "nodeId": 3, "left": "100.0mm", "top": "53.3mm" }, { "nodeId": 4, "left": "132.5mm", "top": "42.0mm" }, { "nodeId": 5, "left": "165.5mm", "top": "44.5mm" }, { "nodeId": 6, "left": "194.5mm", "top": "59.5mm" }, { "nodeId": 7, "left": "15.0mm", "top": "62.5mm" }, { "nodeId": 8, "left": "52.5mm", "top": "83.5mm" }, { "nodeId": 9, "left": "90.9mm", "top": "75.7mm" }, { "nodeId": 10, "left": "122.8mm", "top": "80.9mm" }, { "nodeId": 11, "left": "144.8mm", "top": "72.0mm" }, { "nodeId": 12, "left": "175.5mm", "top": "71.0mm" }, { "nodeId": 13, "left": "16.5mm", "top": "96.5mm" }, { "nodeId": 14, "left": "41.5mm", "top": "95.0mm" }, { "nodeId": 15, "left": "78.3mm", "top": "97.0mm" }, { "nodeId": 16, "left": "99.5mm", "top": "97.5mm" }, { "nodeId": 17, "left": "132.2mm", "top": "100.3mm" }, { "nodeId": 18, "left": "155.8mm", "top": "96.1mm" }, { "nodeId": 19, "left": "195.0mm", "top": "93.0mm" }, { "nodeId": 20, "left": "30.5mm", "top": "118.0mm" }, { "nodeId": 21, "left": "65.5mm", "top": "118.4mm" }, { "nodeId": 22, "left": "85.5mm", "top": "123.0mm" }, { "nodeId": 23, "left": "111.0mm", "top": "113.0mm" }, { "nodeId": 24, "left": "141.0mm", "top": "123.5mm" }, { "nodeId": 25, "left": "168.0mm", "top": "116.0mm" }, { "nodeId": 26, "left": "18.0mm", "top": "148.0mm" }, { "nodeId": 27, "left": "53.5mm", "top": "140.0mm" }, { "nodeId": 28, "left": "81.7mm", "top": "142.4mm" }, { "nodeId": 29, "left": "97.5mm", "top": "138.5mm" }, { "nodeId": 30, "left": "129.5mm", "top": "145.0mm" }, { "nodeId": 31, "left": "157.0mm", "top": "142.5mm" }, { "nodeId": 32, "left": "189.8mm", "top": "136.1mm" }, { "nodeId": 33, "left": "30.0mm", "top": "168.5mm" }, { "nodeId": 34, "left": "54.5mm", "top": "162.0mm" }, { "nodeId": 35, "left": "89.4mm", "top": "160.7mm" }, { "nodeId": 36, "left": "117.5mm", "top": "166.5mm" }, { "nodeId": 37, "left": "139.0mm", "top": "172.5mm" }, { "nodeId": 38, "left": "173.0mm", "top": "158.5mm" }, { "nodeId": 39, "left": "22.0mm", "top": "192.0mm" }, { "nodeId": 40, "left": "52.8mm", "top": "190.0mm" }, { "nodeId": 41, "left": "73.0mm", "top": "186.0mm" }, { "nodeId": 42, "left": "98.0mm", "top": "199.5mm" }, { "nodeId": 43, "left": "123.0mm", "top": "197.5mm" }, { "nodeId": 44, "left": "160.0mm", "top": "190.0mm" }, { "nodeId": 45, "left": "186.3mm", "top": "184.2mm" }, { "nodeId": 46, "left": "43.0mm", "top": "214.5mm" }, { "nodeId": 47, "left": "70.0mm", "top": "207.0mm" }, { "nodeId": 48, "left": "82.5mm", "top": "221.5mm" }, { "nodeId": 49, "left": "109.0mm", "top": "219.5mm" }, { "nodeId": 50, "left": "140.0mm", "top": "212.5mm" }, { "nodeId": 51, "left": "167.0mm", "top": "215.5mm" }, { "nodeId": 52, "left": "21.5mm", "top": "237.0mm" }, { "nodeId": 53, "left": "52.5mm", "top": "230.5mm" }, { "nodeId": 54, "left": "78.5mm", "top": "238.5mm" }, { "nodeId": 55, "left": "102.0mm", "top": "242.0mm" }, { "nodeId": 56, "left": "129.5mm", "top": "238.5mm" }, { "nodeId": 57, "left": "160.0mm", "top": "240.0mm" }, { "nodeId": 58, "left": "190.0mm", "top": "241.0mm" }
]
}
]
}

View File

@ -0,0 +1,13 @@
# Space Route 1
**Title:** Проложи Маршрут
## Notes
9-page space route worksheet. Player and enemy navigate a hex graph.
Generated by `scripts/generate-route.mjs` with per-page seed configs.
See `scripts/generate-route.mjs` PAGES array for full page configs including:
- diffRange (difficulty), routeLength, seeds
- Ship/enemy images, destination objects, decorative objects
- flipEnemy/flipPlayer flags for ship orientation

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,687 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.tailwindcss.com"></script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700;800;900&display=swap" rel="stylesheet">
<title>Проложи Маршрут</title>
<script>
tailwind.config = {
theme: {
extend: {
fontFamily: { nunito: ['Nunito', 'sans-serif'] },
}
}
}
</script>
<style>
@page { size: A4; margin: 0; }
body { font-family: 'Nunito', sans-serif; }
</style>
</head>
<body class="bg-gray-200 font-nunito">
<script>
// ============================================================
// CONFIGURATION PER PAGE
// ============================================================
// diffRange: [minNodeValue, maxSpread]
const PAGES = [
{
enemyShipImg: '../../assets/hero-images/spaceship4.jpeg',
enemyLabel: 'Пиратский крейсер',
playerShipImg: '../../assets/hero-images/spaceship2.png',
footerImg: '../../assets/footers/planet3.jpeg',
destObjectImg: '../../assets/icons/pack3-asteroids/asteroid5.png',
decoObjects: [
{ img: '../../assets/icons/pack3-asteroids/asteroid3.png' },
{ img: '../../assets/icons/pack3-asteroids/asteroid7.png' },
{ img: '../../assets/icons/pack3-asteroids/asteroid11.png' },
],
diffRange: [3, 6],
routeLength: 5,
seed: 42001,
flipEnemy: false, // spaceship4 faces right
flipPlayer: true, // spaceship2 faces left
},
{
enemyShipImg: '../../assets/hero-images/spaceship6.jpeg',
enemyLabel: 'Патрульный разведчик',
playerShipImg: '../../assets/hero-images/spaceship7.png',
footerImg: '../../assets/footers/planet5.jpeg',
destObjectImg: '../../assets/icons/pack3-asteroids/asteroid9.png',
decoObjects: [
{ img: '../../assets/icons/pack3-asteroids/asteroid14.png' },
{ img: '../../assets/icons/pack3-asteroids/asteroid2.png' },
{ img: '../../assets/icons/pack3-asteroids/asteroid16.png' },
{ img: '../../assets/icons/pack3-asteroids/asteroid4.png' },
],
diffRange: [4, 10],
routeLength: 5,
seed: 42002,
flipEnemy: true, // spaceship6 faces left
flipPlayer: true, // spaceship7 faces left
},
{
enemyShipImg: '../../assets/hero-images/spaceship3.jpeg',
enemyLabel: 'Контрабандист',
playerShipImg: '../../assets/hero-images/spaceship9.png',
footerImg: '../../assets/footers/planet1.jpeg',
destObjectImg: '../../assets/icons/pack3-asteroids/asteroid1.png',
decoObjects: [
{ img: '../../assets/icons/pack3-asteroids/asteroid10.png' },
{ img: '../../assets/icons/pack3-asteroids/asteroid6.png' },
{ img: '../../assets/icons/pack3-asteroids/asteroid12.png' },
],
diffRange: [2, 18],
routeLength: 6,
seed: 42003,
flipEnemy: false, // spaceship3 faces right
flipPlayer: true, // spaceship9 faces left
},
];
const PLAYER_ROUTE_CELLS = 10;
const GRID_COLS = 6;
const GRID_ROWS = 7;
// ============================================================
// SEEDED PRNG (mulberry32) — stable output across reloads
// ============================================================
let _seed = 0;
function seedRng(s) { _seed = s | 0; }
function seededRandom() {
_seed |= 0; _seed = _seed + 0x6D2B79F5 | 0;
let t = Math.imul(_seed ^ _seed >>> 15, 1 | _seed);
t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t;
return ((t ^ t >>> 14) >>> 0) / 4294967296;
}
// ============================================================
// GRAPH ALGORITHM
// ============================================================
const NODE_R_MM = 5;
const MAP_TOP = 44;
const MAP_BOTTOM = 242;
const MAP_LEFT = 14;
const MAP_RIGHT = 196;
function rand(min, max) {
return Math.floor(seededRandom() * (max - min + 1)) + min;
}
function randF(min, max) {
return min + seededRandom() * (max - min);
}
function distN(a, b) {
return Math.sqrt((a.x - b.x) ** 2 + (a.y - b.y) ** 2);
}
function generateNodes() {
const nodes = [];
const cellW = (MAP_RIGHT - MAP_LEFT) / GRID_COLS;
const cellH = (MAP_BOTTOM - MAP_TOP) / GRID_ROWS;
const jitter = Math.min(cellW, cellH) * 0.25;
let id = 0;
for (let row = 0; row < GRID_ROWS; row++) {
for (let col = 0; col < GRID_COLS; col++) {
const hexOffset = (row % 2 === 1) ? cellW * 0.5 : 0;
const baseX = MAP_LEFT + col * cellW + cellW / 2 + hexOffset;
const baseY = MAP_TOP + row * cellH + cellH / 2;
if (baseX < MAP_LEFT + 5 || baseX > MAP_RIGHT - 5) continue;
const x = baseX + randF(-jitter, jitter);
const y = baseY + randF(-jitter, jitter);
const cx = Math.max(MAP_LEFT + NODE_R_MM, Math.min(MAP_RIGHT - NODE_R_MM, x));
const cy = Math.max(MAP_TOP + NODE_R_MM, Math.min(MAP_BOTTOM - NODE_R_MM, y));
nodes.push({ x: cx, y: cy, id: id++, value: 0, neighbors: [] });
}
}
return nodes;
}
function generateEdges(nodes) {
const edges = [];
const maxEdgeDist = 45;
const candidates = [];
for (let i = 0; i < nodes.length; i++) {
for (let j = i + 1; j < nodes.length; j++) {
const d = distN(nodes[i], nodes[j]);
if (d <= maxEdgeDist) candidates.push({ i, j, d });
}
}
candidates.sort((a, b) => a.d - b.d);
const MAX_DEGREE = 5;
for (const { i, j } of candidates) {
if (nodes[i].neighbors.length >= MAX_DEGREE || nodes[j].neighbors.length >= MAX_DEGREE) continue;
let crosses = false;
for (const e of edges) {
if (e.i === i || e.j === i || e.i === j || e.j === j) continue;
if (segmentsIntersect(nodes[i], nodes[j], nodes[e.i], nodes[e.j])) { crosses = true; break; }
}
if (!crosses) {
edges.push({ i, j });
nodes[i].neighbors.push(j);
nodes[j].neighbors.push(i);
}
}
ensureConnected(nodes, edges);
// Ensure min degree 2
for (const n of nodes) {
if (n.neighbors.length < 2) {
let best = null, bestDist = Infinity;
for (const other of nodes) {
if (other.id === n.id || n.neighbors.includes(other.id)) continue;
const d = distN(n, other);
if (d < bestDist) { bestDist = d; best = other; }
}
if (best) {
edges.push({ i: n.id, j: best.id });
n.neighbors.push(best.id);
best.neighbors.push(n.id);
}
}
}
return edges;
}
// Trim a node's edges down to exactly targetDegree, keeping nearest neighbors
function trimNodeDegree(nodes, edges, nodeId, targetDegree) {
const n = nodes[nodeId];
while (n.neighbors.length > targetDegree) {
// Remove the farthest neighbor
let farthestNb = -1, farthestDist = 0;
for (const nb of n.neighbors) {
const d = distN(n, nodes[nb]);
if (d > farthestDist) { farthestDist = d; farthestNb = nb; }
}
// Remove edge
n.neighbors = n.neighbors.filter(nb => nb !== farthestNb);
nodes[farthestNb].neighbors = nodes[farthestNb].neighbors.filter(nb => nb !== nodeId);
// Remove from edges array
for (let ei = edges.length - 1; ei >= 0; ei--) {
const e = edges[ei];
if ((e.i === nodeId && e.j === farthestNb) || (e.j === nodeId && e.i === farthestNb)) {
edges.splice(ei, 1);
}
}
}
}
function ensureConnected(nodes, edges) {
const component = new Array(nodes.length).fill(-1);
let compId = 0;
for (let i = 0; i < nodes.length; i++) {
if (component[i] !== -1) continue;
const queue = [i];
component[i] = compId;
while (queue.length) {
const cur = queue.shift();
for (const nb of nodes[cur].neighbors) {
if (component[nb] === -1) { component[nb] = compId; queue.push(nb); }
}
}
compId++;
}
for (let c = 1; c < compId; c++) {
let best = null, bestDist = Infinity;
for (let i = 0; i < nodes.length; i++) {
if (component[i] !== 0) continue;
for (let j = 0; j < nodes.length; j++) {
if (component[j] !== c) continue;
const d = distN(nodes[i], nodes[j]);
if (d < bestDist) { bestDist = d; best = { i, j }; }
}
}
if (best) {
edges.push(best);
nodes[best.i].neighbors.push(best.j);
nodes[best.j].neighbors.push(best.i);
for (let k = 0; k < nodes.length; k++) {
if (component[k] === c) component[k] = 0;
}
}
}
}
function segmentsIntersect(p1, p2, p3, p4) {
const d1 = crossP(p3, p4, p1), d2 = crossP(p3, p4, p2);
const d3 = crossP(p1, p2, p3), d4 = crossP(p1, p2, p4);
return ((d1 > 0 && d2 < 0) || (d1 < 0 && d2 > 0)) &&
((d3 > 0 && d4 < 0) || (d3 < 0 && d4 > 0));
}
function crossP(pi, pj, pk) {
return (pk.x - pi.x) * (pj.y - pi.y) - (pj.x - pi.x) * (pk.y - pi.y);
}
// ============================================================
// VALUE ASSIGNMENT
// ============================================================
function assignValues(nodes, minVal, maxSpread) {
const maxVal = minVal + Math.ceil(maxSpread * 1.3);
const order = [...Array(nodes.length).keys()];
order.sort((a, b) => nodes[b].neighbors.length - nodes[a].neighbors.length);
for (let attempt = 0; attempt < 300; attempt++) {
if (tryAssign(nodes, order, minVal, maxSpread, maxVal)) {
if (validateGraph(nodes, minVal, maxSpread)) return true;
}
for (let i = order.length - 1; i > 0; i--) {
if (Math.random() < 0.4) {
const j = rand(0, i);
[order[i], order[j]] = [order[j], order[i]];
}
}
}
return false;
}
function tryAssign(nodes, order, minVal, maxSpread, maxVal) {
for (const n of nodes) n.value = -1;
for (const idx of order) {
const candidates = [];
for (let v = minVal; v <= maxVal; v++) {
let valid = true;
const signedDiffs = [];
for (const nb of nodes[idx].neighbors) {
if (nodes[nb].value === -1) continue;
const absDiff = Math.abs(v - nodes[nb].value);
if (absDiff < 1 || absDiff > maxSpread) { valid = false; break; }
const sd = v - nodes[nb].value;
if (signedDiffs.includes(sd)) { valid = false; break; }
signedDiffs.push(sd);
}
if (!valid) continue;
for (const nb of nodes[idx].neighbors) {
if (nodes[nb].value === -1) continue;
const myDiff = v - nodes[nb].value;
for (const nb2 of nodes[nb].neighbors) {
if (nb2 === idx || nodes[nb2].value === -1) continue;
if (nodes[nb2].value - nodes[nb].value === myDiff) { valid = false; break; }
}
if (!valid) break;
}
if (valid) candidates.push(v);
}
if (candidates.length === 0) return false;
const center = minVal + maxSpread * 0.5;
candidates.sort((a, b) => Math.abs(a - center) - Math.abs(b - center));
const pick = Math.min(candidates.length - 1, Math.floor(Math.random() * Math.min(candidates.length, 4)));
nodes[idx].value = candidates[pick];
}
return true;
}
function validateGraph(nodes, minVal, maxSpread) {
for (const n of nodes) {
if (n.value < minVal) return false;
const diffs = [];
for (const nb of n.neighbors) {
const d = nodes[nb].value - n.value;
const ad = Math.abs(d);
if (ad < 1 || ad > maxSpread) return false;
if (diffs.includes(d)) return false;
diffs.push(d);
}
}
return true;
}
// ============================================================
// ROUTE FINDING — directional, avoids loops
// ============================================================
// Find corner node: top-left or bottom-left
function findCornerNode(nodes, corner) {
let sorted;
if (corner === 'top-left') {
sorted = [...nodes].sort((a, b) => (a.x + a.y * 2) - (b.x + b.y * 2));
} else {
// bottom-left: low x, high y
sorted = [...nodes].sort((a, b) => (a.x - a.y * 2) - (b.x - b.y * 2));
}
return sorted[0];
}
// Directional route: prefer moving toward a target area, avoid backtracking
function findDirectionalRoute(nodes, startId, length, targetArea) {
// targetArea: {x, y} — general direction to aim for
const best = { path: null, score: -Infinity };
for (let trial = 0; trial < 30; trial++) {
const path = [startId];
if (buildDirectionalPath(nodes, path, length, targetArea)) {
const score = routeQualityScore(nodes, path, targetArea);
if (score > best.score) {
best.path = [...path];
best.score = score;
}
}
}
return best.path;
}
function buildDirectionalPath(nodes, path, targetLen, target) {
if (path.length === targetLen + 1) return true;
const current = nodes[path[path.length - 1]];
const nbs = [...current.neighbors].filter(nb => !path.includes(nb));
if (nbs.length === 0) return false;
// Score each neighbor: prefer those closer to target, penalize going backward
const scored = nbs.map(nb => {
const n = nodes[nb];
const distToTarget = Math.sqrt((n.x - target.x) ** 2 + (n.y - target.y) ** 2);
// Progress: how much closer we get vs current position
const curDist = Math.sqrt((current.x - target.x) ** 2 + (current.y - target.y) ** 2);
const progress = curDist - distToTarget;
// Small random factor for variety
return { nb, score: progress + randF(-15, 15) };
});
scored.sort((a, b) => b.score - a.score);
for (const { nb } of scored) {
path.push(nb);
if (buildDirectionalPath(nodes, path, targetLen, target)) return true;
path.pop();
}
return false;
}
// Score route: higher = more directional, less loopy
function routeQualityScore(nodes, path, target) {
const start = nodes[path[0]];
const end = nodes[path[path.length - 1]];
// Distance from end to target
const endDist = Math.sqrt((end.x - target.x) ** 2 + (end.y - target.y) ** 2);
// Straightness: total path length vs straight-line distance
let totalDist = 0;
for (let i = 1; i < path.length; i++) {
totalDist += distN(nodes[path[i - 1]], nodes[path[i]]);
}
const straightLine = distN(start, end);
const straightness = straightLine / (totalDist + 1);
return -endDist * 0.5 + straightness * 50 + straightLine * 0.3;
}
function findShortestPath(nodes, fromId, toId) {
const prev = new Array(nodes.length).fill(-1);
const visited = new Set([fromId]);
const queue = [fromId];
while (queue.length) {
const cur = queue.shift();
if (cur === toId) break;
for (const nb of nodes[cur].neighbors) {
if (!visited.has(nb)) { visited.add(nb); prev[nb] = cur; queue.push(nb); }
}
}
if (!visited.has(toId)) return null;
const path = [];
let cur = toId;
while (cur !== -1) { path.unshift(cur); cur = prev[cur]; }
return path;
}
// ============================================================
// PAGE GENERATION
// ============================================================
function generatePage(config, pageIndex) {
seedRng(config.seed); // deterministic output per page
let nodes, edges, enemyRoute, playerRoute;
let success = false;
for (let attempt = 0; attempt < 80; attempt++) {
nodes = generateNodes();
edges = generateEdges(nodes);
// Find corner starts
const enemyStartNode = findCornerNode(nodes, 'top-left');
const playerStartNode = findCornerNode(nodes, 'bottom-left');
// Trim start nodes to exactly 2 edges
trimNodeDegree(nodes, edges, enemyStartNode.id, 2);
trimNodeDegree(nodes, edges, playerStartNode.id, 2);
const [minVal, maxSpread] = config.diffRange;
if (!assignValues(nodes, minVal, maxSpread)) continue;
// Enemy route: from top-left corner toward bottom-right area
const targetArea = { x: MAP_RIGHT - 30, y: MAP_BOTTOM - 40 };
enemyRoute = findDirectionalRoute(nodes, enemyStartNode.id, config.routeLength, targetArea);
if (!enemyRoute) continue;
const dest = enemyRoute[enemyRoute.length - 1];
// Player route: from bottom-left corner to destination
if (playerStartNode.id === dest || enemyRoute.includes(playerStartNode.id)) continue;
playerRoute = findShortestPath(nodes, playerStartNode.id, dest);
if (playerRoute && playerRoute.length >= 3) {
success = true;
break;
}
}
if (!success) {
return `<div class="w-[210mm] h-[297mm] mx-auto bg-white flex items-center justify-center text-red-500 text-xl">Page ${pageIndex + 1}: Generation failed after 80 attempts</div>`;
}
return renderPage(nodes, edges, enemyRoute, playerRoute, config, pageIndex);
}
function renderPage(nodes, edges, enemyRoute, playerRoute, config, pageIndex) {
const dest = enemyRoute[enemyRoute.length - 1];
const enemyStart = enemyRoute[0];
const playerStart = playerRoute[0];
// Pick nodes for decorative objects (not start/dest nodes, spread across map)
const decoNodeIds = [];
const usedIds = new Set([enemyStart, playerStart, dest, ...enemyRoute, ...playerRoute]);
const availableNodes = nodes.filter(n => !usedIds.has(n.id));
// Spread them out by picking from different y-regions
const sortedByRegion = [...availableNodes].sort((a, b) => a.y - b.y);
const regionSize = Math.floor(sortedByRegion.length / (config.decoObjects.length + 1));
for (let di = 0; di < config.decoObjects.length; di++) {
const regionStart = regionSize * (di + 0.5);
const idx = Math.min(Math.floor(regionStart + randF(-2, 2)), sortedByRegion.length - 1);
if (idx >= 0 && !decoNodeIds.includes(sortedByRegion[idx].id)) {
decoNodeIds.push(sortedByRegion[Math.max(0, idx)].id);
}
}
// Build SVG for edges
let edgeSvg = '';
for (const e of edges) {
const n1 = nodes[e.i], n2 = nodes[e.j];
edgeSvg += `<line x1="${n1.x}mm" y1="${n1.y}mm" x2="${n2.x}mm" y2="${n2.y}mm"
stroke="#a5b4fc" stroke-width="0.7" stroke-dasharray="2.5 2" stroke-linecap="round" opacity="0.45"/>`;
}
// Build node circles
const asteroidNodeIds = new Set([dest, ...decoNodeIds]);
let nodesHtml = '';
for (const n of nodes) {
const isEnemyStart = n.id === enemyStart;
const isPlayerStart = n.id === playerStart;
const isStartNode = isEnemyStart || isPlayerStart;
const hasAsteroid = asteroidNodeIds.has(n.id);
const borderWidth = isStartNode ? '2.5px' : '1.5px';
const borderColor = isStartNode ? 'border-indigo-600' : 'border-indigo-300';
const bgColor = isStartNode ? 'bg-indigo-50' : 'bg-white';
const fontSize = isStartNode ? '13px' : '11px';
const shadow = isStartNode ? 'shadow-md shadow-indigo-200' : 'shadow-sm';
const baseSize = isStartNode ? NODE_R_MM * 2.4 : NODE_R_MM * 2;
const size = hasAsteroid ? baseSize / 1.5 : baseSize;
const offset = size / 2;
nodesHtml += `
<div class="absolute flex items-center justify-center rounded-full ${borderColor} ${bgColor} ${shadow}"
style="left:${n.x}mm;top:${n.y}mm;width:${size}mm;height:${size}mm;margin-left:-${offset}mm;margin-top:-${offset}mm;z-index:15;border-width:${borderWidth};">
<span class="font-extrabold text-indigo-950 leading-none" style="font-size:${fontSize};">${n.value}</span>
</div>`;
}
// Destination object — large asteroid under the destination node
const destNode = nodes[dest];
let destObjHtml = `
<img src="${config.destObjectImg}" class="absolute object-contain"
style="left:${destNode.x}mm;top:${destNode.y}mm;width:30mm;height:30mm;margin-left:-15mm;margin-top:-15mm;z-index:4;" alt="">`;
// Decorative objects — placed under specific nodes, large
let decosHtml = '';
for (let di = 0; di < config.decoObjects.length && di < decoNodeIds.length; di++) {
const dn = nodes[decoNodeIds[di]];
decosHtml += `
<img src="${config.decoObjects[di].img}" class="absolute object-contain"
style="left:${dn.x}mm;top:${dn.y}mm;width:24mm;height:24mm;margin-left:-12mm;margin-top:-12mm;z-index:4;" alt="">`;
}
// Decorative stars — bigger, darker, more
let starsHtml = '';
for (let i = 0; i < 70; i++) {
const sx = randF(6, 204);
const sy = randF(30, 270);
const size = randF(10, 22);
const opacity = randF(0.12, 0.35);
const symbols = ['✦', '✧', '⋆', '·', '', '⊹'];
starsHtml += `<span class="absolute text-indigo-300" style="left:${sx}mm;top:${sy}mm;font-size:${size}px;opacity:${opacity};z-index:2;pointer-events:none;">${symbols[rand(0, symbols.length - 1)]}</span>`;
}
// Enemy route: circle with start value + diff cells
const enemyDiffs = [];
for (let i = 1; i < enemyRoute.length; i++) {
enemyDiffs.push(nodes[enemyRoute[i]].value - nodes[enemyRoute[i - 1]].value);
}
let enemyRouteCells = `<div class="inline-flex items-center justify-center rounded-full border-[2px] border-indigo-500 bg-indigo-50 shrink-0" style="width:8mm;height:8mm;">
<span class="text-[12px] font-extrabold text-indigo-950">${nodes[enemyStart].value}</span>
</div>`;
for (const diff of enemyDiffs) {
const diffStr = (diff > 0 ? '+' : '') + diff;
enemyRouteCells += `<div class="inline-flex items-center justify-center shrink-0 border-[1.5px] border-indigo-300 rounded bg-white" style="width:9mm;height:7mm;margin-left:1mm;">
<span class="text-[11px] font-bold text-indigo-950">${diffStr}</span>
</div>`;
}
// Player route: circle + 10 empty cells
const cellCount = Math.max(PLAYER_ROUTE_CELLS, playerRoute.length - 1);
let playerRouteCells = `<div class="inline-flex items-center justify-center rounded-full border-[2px] border-indigo-500 bg-indigo-50 shrink-0" style="width:8mm;height:8mm;">
<span class="text-[12px] font-extrabold text-indigo-950">${nodes[playerStart].value}</span>
</div>`;
for (let i = 0; i < cellCount; i++) {
playerRouteCells += `<div class="inline-flex items-center justify-center shrink-0 border-[1.5px] border-indigo-200 border-dashed rounded bg-white" style="width:9mm;height:7mm;margin-left:1mm;">
</div>`;
}
const isLastPage = pageIndex === PAGES.length - 1;
const pageBreak = isLastPage ? '' : 'break-after: page;';
const [minVal, maxSpread] = config.diffRange;
const nodeValues = nodes.map(n => n.value);
const actualMin = Math.min(...nodeValues);
const actualMax = Math.max(...nodeValues);
return `
<div class="w-[210mm] h-[297mm] relative overflow-hidden mx-auto bg-white" style="${pageBreak}">
<!-- Footer with planet -->
<div class="absolute bottom-0 left-0 right-0 h-[80mm] z-0">
<div class="absolute top-0 left-0 right-0 h-full z-10" style="background: linear-gradient(to bottom, white 0%, rgba(255,255,255,0.6) 25%, transparent 50%);"></div>
<img src="${config.footerImg}" class="w-full h-full object-cover object-top" alt="">
</div>
<!-- Map content -->
<div class="absolute inset-0" style="z-index:3;">
<!-- Stars -->
${starsHtml}
<!-- Destination object -->
${destObjHtml}
<!-- Decorative objects -->
${decosHtml}
<!-- Edges SVG -->
<svg class="absolute inset-0 w-full h-full" style="z-index:5;" xmlns="http://www.w3.org/2000/svg">
${edgeSvg}
</svg>
<!-- Nodes -->
${nodesHtml}
<!-- Header with enemy ship -->
<div class="absolute top-0 left-0 right-0 z-30">
<div class="flex items-start">
<!-- Enemy ship image — 40% of header -->
<img src="${config.enemyShipImg}" class="shrink-0 object-contain" style="width:48%;max-height:50mm;z-index:4;${config.flipEnemy ? 'transform:scaleX(-1);' : ''}" alt="">
<!-- Title — right side -->
<div class="flex-1 flex flex-col items-center justify-center text-center pt-[5mm]">
<h1 class="text-[1.4rem] font-extrabold leading-tight tracking-tight text-indigo-950">Проложи Маршрут</h1>
<p class="text-[0.75rem] font-medium text-indigo-300 mt-0">Найди путь в космосе!</p>
</div>
</div>
</div>
<!-- Enemy route card (right side, under title) -->
<div class="absolute z-30" style="top:19mm;right:8mm;">
<div class="flex items-center gap-[2mm] px-[3mm] py-[1.5mm] rounded-lg border-[1.5px] border-indigo-100" style="background:rgba(255,255,255,0.75);">
<div class="text-[11px] font-bold text-indigo-900 whitespace-nowrap">${config.enemyLabel}:</div>
<div class="flex items-center flex-nowrap">${enemyRouteCells}</div>
</div>
<div class="text-[10px] text-indigo-400 mt-[0.5mm] text-right pr-[2mm]">📍 Проследи маршрут — куда он летит?</div>
</div>
<!-- Player ship image (over footer, left side) -->
<img src="${config.playerShipImg}" class="absolute object-contain" style="bottom:8mm;left:0;width:48%;max-height:60mm;z-index:4;${config.flipPlayer ? 'transform:scaleX(-1);' : ''}" alt="">
<!-- Player route card (right side) -->
<div class="absolute z-30" style="bottom:14mm;right:8mm;">
<div class="text-[12px] font-semibold text-gray-800 mb-[1mm] text-right pr-[2mm]">Рассчитай маршрут до цели перехвата</div>
<div class="flex items-center gap-[2mm] px-[3mm] py-[1.5mm] rounded-lg border-[1.5px] border-indigo-100" style="background:rgba(255,255,255,0.75);">
<div class="text-[11px] font-bold text-indigo-900 whitespace-nowrap">Твой истребитель:</div>
<div class="flex items-center flex-nowrap">${playerRouteCells}</div>
</div>
<div class="text-[12px] font-semibold text-gray-800 mt-[1mm] text-right pr-[2mm]">✏️ Запиши разницу чисел, чтобы добраться до цели!</div>
</div>
<!-- Debug info -->
<div class="absolute z-40 text-[7px] text-indigo-300" style="bottom:3mm;left:3mm;">
[${minVal},${maxSpread}] | ${nodes.length} nodes | values ${actualMin}-${actualMax} | enemy ${enemyRoute.length} steps | player shortest ${playerRoute.length - 1} steps
</div>
</div>
</div>`;
}
// ============================================================
// GENERATE ALL PAGES
// ============================================================
document.addEventListener('DOMContentLoaded', () => {
let html = '';
for (let i = 0; i < PAGES.length; i++) {
html += generatePage(PAGES[i], i);
}
document.body.innerHTML = html;
});
</script>
</body>
</html>

View File

@ -0,0 +1,792 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Space Route Editor</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #1e1e2e; color: #cdd6f4; font-family: 'Segoe UI', system-ui, sans-serif; }
#toolbar {
position: fixed; top: 0; left: 0; right: 0; z-index: 1000;
background: #181825; border-bottom: 1px solid #313244;
display: flex; align-items: center; gap: 8px; padding: 8px 12px; height: 48px;
flex-wrap: nowrap; overflow-x: auto;
}
#toolbar button {
background: #313244; color: #cdd6f4; border: 1px solid #45475a;
padding: 5px 10px; border-radius: 6px; cursor: pointer; font-size: 12px;
transition: background 0.15s; white-space: nowrap;
}
#toolbar button:hover { background: #45475a; }
#toolbar button.primary { background: #6366f1; border-color: #818cf8; color: white; }
#toolbar button.primary:hover { background: #818cf8; }
#toolbar button.active { background: #f59e0b; border-color: #fbbf24; color: #1e1e2e; }
#toolbar .page-nav { display: flex; align-items: center; gap: 4px; }
#toolbar .page-nav span { font-size: 13px; min-width: 80px; text-align: center; }
#toolbar .spacer { flex: 1; }
#toolbar .sep { width: 1px; height: 24px; background: #45475a; }
#toolbar .title { font-weight: 600; font-size: 13px; color: #a6adc8; }
#statusbar {
position: fixed; bottom: 0; left: 0; right: 0; z-index: 1000;
background: #181825; border-top: 1px solid #313244;
padding: 6px 16px; font-size: 12px; height: 32px;
display: flex; align-items: center; gap: 16px;
}
#statusbar .pos { color: #89b4fa; }
#statusbar .info { color: #a6adc8; }
#statusbar .keys { color: #6c7086; font-size: 11px; }
#worksheet-container {
padding: 56px 0 32px;
display: flex; flex-direction: column; align-items: center; gap: 20px;
}
.obj-draggable { cursor: grab; user-select: none; z-index: 20 !important; position: absolute; }
/* In node mode, objects become click-through */
body.node-mode .obj-draggable { pointer-events: none !important; z-index: 4 !important; }
body.node-mode .node-draggable { z-index: 20 !important; cursor: grab; }
.obj-draggable:hover { outline: 2px solid rgba(99, 102, 241, 0.6); outline-offset: 2px; }
.obj-selected { outline: 3px solid #6366f1 !important; outline-offset: 2px; }
.obj-changed::after {
content: ''; position: absolute; top: -2px; right: -2px;
width: 8px; height: 8px; background: #f59e0b; border-radius: 50%;
border: 1px solid #1e1e2e; z-index: 100;
}
/* Node dragging (Shift+click) */
.node-draggable { cursor: grab; user-select: none; }
.node-draggable:hover { box-shadow: 0 0 0 3px rgba(251, 191, 36, 0.4) !important; }
.node-selected { box-shadow: 0 0 0 3px #f59e0b !important; }
.node-changed { box-shadow: 0 0 0 2px #f59e0b, 0 0 8px rgba(251, 191, 36, 0.3) !important; }
body.dragging, body.dragging * { cursor: grabbing !important; }
#coord-tooltip {
position: fixed; z-index: 2000; pointer-events: none;
background: #181825; color: #89b4fa; border: 1px solid #6366f1;
padding: 3px 8px; border-radius: 4px; font-size: 12px; font-family: monospace;
display: none;
}
#toast {
position: fixed; top: 60px; right: 16px; z-index: 2000;
background: #6366f1; color: white; padding: 8px 16px; border-radius: 6px;
font-size: 13px; opacity: 0; transition: opacity 0.3s; pointer-events: none;
}
#toast.show { opacity: 1; }
.page-label {
position: absolute; top: 4px; right: 4px; z-index: 100;
background: rgba(0,0,0,0.6); color: white; padding: 2px 8px;
border-radius: 4px; font-size: 12px; pointer-events: none;
}
/* Route highlight */
line.route-highlight {
stroke: #f87171 !important; stroke-width: 2.5 !important;
opacity: 0.8 !important; stroke-dasharray: none !important;
}
</style>
</head>
<body>
<div id="toolbar">
<span class="title">Route Editor</span>
<div class="page-nav">
<button id="btn-prev">&larr;</button>
<span id="page-indicator">Page 1 / ?</span>
<button id="btn-next">&rarr;</button>
</div>
<div class="sep"></div>
<button id="btn-mode" title="Switch between Objects and Nodes mode (M)">Mode: Objects</button>
<button id="btn-route" title="Toggle enemy route highlight">Route HL</button>
<button id="btn-flip" title="Flip selected object horizontally (H)">Flip H</button>
<div class="sep"></div>
<button id="btn-reset">Reset Page</button>
<button id="btn-copy-changes">Copy Changes</button>
<button id="btn-copy" class="primary">Copy All JSON</button>
<button id="btn-save" class="primary" style="background:#22c55e;border-color:#4ade80;">Save</button>
</div>
<div id="worksheet-container"></div>
<div id="statusbar">
<span id="status-info" class="info">Click an object to select</span>
<span id="status-pos" class="pos"></span>
<span class="keys">M: switch mode | Arrows: move | [ ] rotate | - + scale | H: flip | R: route</span>
</div>
<div id="coord-tooltip"></div>
<div id="toast"></div>
<script>
(function() {
const params = new URLSearchParams(location.search);
const fileParam = params.get('file') || 'space-route-1';
const file = 'docs/' + fileParam + '.template.html';
const docId = fileParam;
let pages = [];
let objects = []; // draggable objects (images with data-node-id)
let nodeEls = []; // all node divs
let originalState = new Map(); // obj originals
let nodeOrigState = new Map(); // node originals
let selectedObj = null; // selected object OR node
let selectedType = null; // 'obj' or 'node'
let dragging = null;
let dragStart = null;
let mmToPx = 1;
let currentPage = 0;
let routeHighlight = false;
let editMode = 'objects'; // 'objects' or 'nodes'
fetch(file)
.then(r => { if (!r.ok) throw new Error(r.status); return r.text(); })
.then(html => {
const parser = new DOMParser();
const doc = parser.parseFromString(html, 'text/html');
const container = document.getElementById('worksheet-container');
const tw = document.createElement('script');
tw.src = 'https://cdn.tailwindcss.com';
document.head.appendChild(tw);
doc.querySelectorAll('head script:not([src])').forEach(s => {
const ns = document.createElement('script');
ns.textContent = s.textContent;
document.head.appendChild(ns);
});
doc.querySelectorAll('head style').forEach(s => {
const ns = document.createElement('style');
ns.textContent = s.textContent;
document.head.appendChild(ns);
});
doc.querySelectorAll('head link').forEach(l => {
document.head.appendChild(l.cloneNode(true));
});
container.innerHTML = doc.body.innerHTML;
setTimeout(() => initEditor(), 400);
})
.catch(err => {
document.getElementById('worksheet-container').innerHTML =
`<p style="padding:80px 20px;color:#f38ba8;">Failed to load ${file}: ${err.message}</p>`;
});
function initEditor() {
pages = Array.from(document.querySelectorAll('.w-\\[210mm\\]'));
pages.forEach((p, i) => {
p.dataset.page = i + 1;
p.style.position = 'relative';
const label = document.createElement('div');
label.className = 'page-label';
label.textContent = `Page ${i + 1}`;
p.appendChild(label);
});
document.getElementById('page-indicator').textContent = `Page 1 / ${pages.length}`;
if (pages.length > 0) {
mmToPx = pages[0].getBoundingClientRect().width / 210;
}
// Find all space objects (images with data-node-id)
document.querySelectorAll('img.space-obj').forEach((img, idx) => {
const page = img.closest('[data-page]');
const pageNum = page ? parseInt(page.dataset.page) : 0;
const nodeId = img.dataset.nodeId;
// Wrap in a container div for positioning if not already
// Objects are already absolutely positioned images
const left = parseFloat(img.style.left) || 0;
const top = parseFloat(img.style.top) || 0;
const w = parseFloat(img.style.width) || 24;
const h = parseFloat(img.style.height) || 24;
// Parse transform
let rotate = 0, scaleX = 1, scaleY = 1;
if (img.style.transform) {
const rotM = img.style.transform.match(/rotate\(([-\d.]+)deg\)/);
const scxM = img.style.transform.match(/scaleX\(([-\d.]+)\)/);
const scyM = img.style.transform.match(/scaleY\(([-\d.]+)\)/);
const scM = img.style.transform.match(/scale\(([-\d.]+)\)/);
if (rotM) rotate = parseFloat(rotM[1]);
if (scxM) scaleX = parseFloat(scxM[1]);
if (scyM) scaleY = parseFloat(scyM[1]);
if (scM) scaleX = scaleY = parseFloat(scM[1]);
}
const id = `p${pageNum}-obj${idx}`;
img.dataset.objId = id;
img.dataset.pageNum = pageNum;
img.style.position = 'absolute';
originalState.set(id, { left, top, w, h, rotate, scaleX, scaleY });
img.classList.add('obj-draggable');
img.draggable = false;
objects.push({
el: img, id, pageNum, nodeId,
type: img.dataset.type,
src: img.src.split('/').pop()
});
img.addEventListener('mousedown', (e) => {
e.preventDefault();
e.stopPropagation();
selectObj(img, id);
startDrag(img, e);
});
});
// Init nodes (Shift+click to select)
document.querySelectorAll('[data-node-id]').forEach(nodeDiv => {
if (nodeDiv.tagName === 'IMG') return; // skip objects, only div nodes
const page = nodeDiv.closest('[data-page]');
const pageNum = page ? parseInt(page.dataset.page) : 0;
const nodeId = nodeDiv.dataset.nodeId;
const left = parseFloat(nodeDiv.style.left) || 0;
const top = parseFloat(nodeDiv.style.top) || 0;
const nid = `p${pageNum}-n${nodeId}`;
nodeDiv.dataset.nid = nid;
nodeDiv.dataset.pageNum = pageNum;
nodeOrigState.set(nid, { left, top });
nodeDiv.classList.add('node-draggable');
nodeEls.push({ el: nodeDiv, nid, pageNum, nodeId });
nodeDiv.addEventListener('mousedown', (e) => {
if (editMode !== 'nodes') return;
e.preventDefault();
e.stopPropagation();
selectNode(nodeDiv, nid);
startDrag(nodeDiv, e);
});
});
// Page scroll tracking
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting && entry.intersectionRatio > 0.3) {
currentPage = parseInt(entry.target.dataset.page) - 1;
document.getElementById('page-indicator').textContent =
`Page ${currentPage + 1} / ${pages.length}`;
}
});
}, { threshold: [0.3] });
pages.forEach(p => observer.observe(p));
document.addEventListener('mousemove', onMouseMove);
document.addEventListener('mouseup', onMouseUp);
document.getElementById('worksheet-container').addEventListener('mousedown', (e) => {
if (!e.target.closest('.obj-draggable')) deselectAll();
});
document.addEventListener('keydown', onKeyDown);
document.getElementById('btn-prev').addEventListener('click', () => scrollToPage(currentPage - 1));
document.getElementById('btn-next').addEventListener('click', () => scrollToPage(currentPage + 1));
document.getElementById('btn-copy').addEventListener('click', () => copyConfig(false));
document.getElementById('btn-copy-changes').addEventListener('click', () => copyConfig(true));
document.getElementById('btn-reset').addEventListener('click', resetCurrentPage);
document.getElementById('btn-flip').addEventListener('click', flipSelected);
document.getElementById('btn-mode').addEventListener('click', toggleMode);
document.getElementById('btn-route').addEventListener('click', toggleRouteHL);
document.getElementById('btn-save').addEventListener('click', saveToServer);
window.getConfig = () => buildConfig(false);
window.getChanges = () => buildConfig(true);
window.addEventListener('resize', () => {
if (pages.length > 0) mmToPx = pages[0].getBoundingClientRect().width / 210;
});
}
function selectObj(el, id) {
deselectAll();
el.classList.add('obj-selected');
selectedObj = el;
selectedType = 'obj';
updateStatus(el, id);
}
function selectNode(el, nid) {
deselectAll();
el.classList.add('node-selected');
selectedObj = el;
selectedType = 'node';
const left = parseFloat(el.style.left).toFixed(1);
const top = parseFloat(el.style.top).toFixed(1);
const val = el.querySelector('span')?.textContent || '?';
document.getElementById('status-info').textContent =
`NODE | Page ${el.dataset.pageNum} | id:${el.dataset.nodeId} | value:${val}`;
document.getElementById('status-pos').textContent = `pos: ${left}, ${top}mm`;
}
function deselectAll() {
document.querySelectorAll('.obj-selected').forEach(el => el.classList.remove('obj-selected'));
document.querySelectorAll('.node-selected').forEach(el => el.classList.remove('node-selected'));
selectedObj = null;
selectedType = null;
document.getElementById('status-info').textContent = 'Click object / Shift+click node';
document.getElementById('status-pos').textContent = '';
}
function updateStatus(el, id) {
const left = parseFloat(el.style.left).toFixed(1);
const top = parseFloat(el.style.top).toFixed(1);
const w = parseFloat(el.style.width).toFixed(0);
const h = parseFloat(el.style.height).toFixed(0);
const obj = objects.find(o => o.id === id);
const page = el.dataset.pageNum || '?';
let rotStr = '0', flipStr = '';
if (el.style.transform) {
const rotM = el.style.transform.match(/rotate\(([-\d.]+)deg\)/);
const scxM = el.style.transform.match(/scaleX\(([-\d.]+)\)/);
if (rotM) rotStr = Math.round(parseFloat(rotM[1]));
if (scxM && parseFloat(scxM[1]) < 0) flipStr = ' FLIP';
}
document.getElementById('status-info').textContent =
`Page ${page} | node:${obj?.nodeId} | ${obj?.src || ''}`;
document.getElementById('status-pos').textContent =
`pos: ${left}, ${top}mm | size: ${w}×${h}mm | rot: ${rotStr}°${flipStr}`;
}
// Move the corresponding node and connected edges when an object moves
function moveNodeAndEdges(el, newLeft, newTop) {
const nodeId = el.dataset.nodeId;
if (!nodeId) return;
const page = el.closest('[data-page]');
if (!page) return;
// Find the node div
const nodeDiv = page.querySelector(`[data-node-id="${nodeId}"]`);
if (nodeDiv) {
nodeDiv.style.left = newLeft.toFixed(1) + 'mm';
nodeDiv.style.top = newTop.toFixed(1) + 'mm';
}
// Update all edges connected to this node
const svg = page.querySelector('svg');
if (!svg) return;
svg.querySelectorAll(`line[data-edge]`).forEach(line => {
const [a, b] = line.dataset.edge.split('-');
if (a === nodeId) {
line.setAttribute('x1', newLeft.toFixed(1) + 'mm');
line.setAttribute('y1', newTop.toFixed(1) + 'mm');
}
if (b === nodeId) {
line.setAttribute('x2', newLeft.toFixed(1) + 'mm');
line.setAttribute('y2', newTop.toFixed(1) + 'mm');
}
});
}
// Move only edges for a node (without moving the node itself — used when dragging node directly)
function moveEdgesForNode(nodeDiv, newLeft, newTop) {
const nodeId = nodeDiv.dataset.nodeId;
const page = nodeDiv.closest('[data-page]');
if (!page) return;
const svg = page.querySelector('svg');
if (!svg) return;
svg.querySelectorAll('line[data-edge]').forEach(line => {
const [a, b] = line.dataset.edge.split('-');
if (a === nodeId) {
line.setAttribute('x1', newLeft.toFixed(1) + 'mm');
line.setAttribute('y1', newTop.toFixed(1) + 'mm');
}
if (b === nodeId) {
line.setAttribute('x2', newLeft.toFixed(1) + 'mm');
line.setAttribute('y2', newTop.toFixed(1) + 'mm');
}
});
}
function markNodeChanged(nodeDiv) {
const nid = nodeDiv.dataset.nid;
const orig = nodeOrigState.get(nid);
if (!orig) return;
const curLeft = parseFloat(nodeDiv.style.left);
const curTop = parseFloat(nodeDiv.style.top);
const changed = Math.abs(orig.left - curLeft) > 0.3 || Math.abs(orig.top - curTop) > 0.3;
nodeDiv.classList.toggle('node-changed', changed);
}
function startDrag(el, e) {
dragging = el;
dragStart = {
mouseX: e.clientX, mouseY: e.clientY,
left: parseFloat(el.style.left) || 0,
top: parseFloat(el.style.top) || 0
};
document.body.classList.add('dragging');
document.getElementById('coord-tooltip').style.display = 'block';
}
function onMouseMove(e) {
if (!dragging) return;
e.preventDefault();
const dx = (e.clientX - dragStart.mouseX) / mmToPx;
const dy = (e.clientY - dragStart.mouseY) / mmToPx;
const newLeft = Math.round((dragStart.left + dx) * 2) / 2;
const newTop = Math.round((dragStart.top + dy) * 2) / 2;
dragging.style.left = newLeft.toFixed(1) + 'mm';
dragging.style.top = newTop.toFixed(1) + 'mm';
if (selectedType === 'obj') {
// Update margin to keep object centered
const w = parseFloat(dragging.style.width) || 24;
const h = parseFloat(dragging.style.height) || 24;
dragging.style.marginLeft = (-w / 2) + 'mm';
dragging.style.marginTop = (-h / 2) + 'mm';
updateStatus(dragging, dragging.dataset.objId);
markChanged(dragging);
} else if (selectedType === 'node') {
// Update margin for node centering
const size = parseFloat(dragging.style.width) || 10;
dragging.style.marginLeft = (-size / 2) + 'mm';
dragging.style.marginTop = (-size / 2) + 'mm';
// Move connected edges
moveEdgesForNode(dragging, newLeft, newTop);
markNodeChanged(dragging);
// Update status
const val = dragging.querySelector('span')?.textContent || '?';
document.getElementById('status-info').textContent =
`NODE | Page ${dragging.dataset.pageNum} | id:${dragging.dataset.nodeId} | value:${val}`;
document.getElementById('status-pos').textContent = `pos: ${newLeft.toFixed(1)}, ${newTop.toFixed(1)}mm`;
}
const tooltip = document.getElementById('coord-tooltip');
tooltip.textContent = `${newLeft.toFixed(1)}, ${newTop.toFixed(1)}mm`;
tooltip.style.left = (e.clientX + 15) + 'px';
tooltip.style.top = (e.clientY - 10) + 'px';
}
function onMouseUp() {
if (!dragging) return;
document.body.classList.remove('dragging');
document.getElementById('coord-tooltip').style.display = 'none';
dragging = null;
dragStart = null;
}
function onKeyDown(e) {
if (e.key === 'm' || e.key === 'M') { toggleMode(); return; }
if (e.key === 'r' || e.key === 'R') { toggleRouteHL(); return; }
if (e.key === 'h' || e.key === 'H') { if (selectedType === 'obj') flipSelected(); return; }
if (e.key === 'Escape') { deselectAll(); return; }
if (!selectedObj) return;
// Node mode: only arrows
if (selectedType === 'node') {
const step = e.shiftKey ? 5 : 1;
let left = parseFloat(selectedObj.style.left) || 0;
let top = parseFloat(selectedObj.style.top) || 0;
switch (e.key) {
case 'ArrowLeft': left -= step; break;
case 'ArrowRight': left += step; break;
case 'ArrowUp': top -= step; break;
case 'ArrowDown': top += step; break;
default: return;
}
e.preventDefault();
selectedObj.style.left = left.toFixed(1) + 'mm';
selectedObj.style.top = top.toFixed(1) + 'mm';
const size = parseFloat(selectedObj.style.width) || 10;
selectedObj.style.marginLeft = (-size / 2) + 'mm';
selectedObj.style.marginTop = (-size / 2) + 'mm';
moveEdgesForNode(selectedObj, left, top);
markNodeChanged(selectedObj);
const val = selectedObj.querySelector('span')?.textContent || '?';
document.getElementById('status-pos').textContent = `pos: ${left.toFixed(1)}, ${top.toFixed(1)}mm`;
return;
}
// Object mode: arrows + rotate + resize
const step = e.shiftKey ? 5 : 1;
let left = parseFloat(selectedObj.style.left) || 0;
let top = parseFloat(selectedObj.style.top) || 0;
let w = parseFloat(selectedObj.style.width) || 24;
let h = parseFloat(selectedObj.style.height) || 24;
const sizeStep = e.shiftKey ? 1 : 2;
const rotStep = e.shiftKey ? 1 : 5;
switch (e.key) {
case 'ArrowLeft': left -= step; break;
case 'ArrowRight': left += step; break;
case 'ArrowUp': top -= step; break;
case 'ArrowDown': top += step; break;
case '[': applyRotate(selectedObj, -rotStep); break;
case ']': applyRotate(selectedObj, rotStep); break;
case '-': case '_':
w = Math.max(8, w - sizeStep);
h = Math.max(8, h - sizeStep * (h / w));
selectedObj.style.width = w + 'mm';
selectedObj.style.height = h + 'mm';
selectedObj.style.marginLeft = (-w / 2) + 'mm';
selectedObj.style.marginTop = (-h / 2) + 'mm';
break;
case '=': case '+':
w = Math.min(60, w + sizeStep);
h = Math.min(60, h + sizeStep * (h / w));
selectedObj.style.width = w + 'mm';
selectedObj.style.height = h + 'mm';
selectedObj.style.marginLeft = (-w / 2) + 'mm';
selectedObj.style.marginTop = (-h / 2) + 'mm';
break;
default: return;
}
e.preventDefault();
selectedObj.style.left = left.toFixed(1) + 'mm';
selectedObj.style.top = top.toFixed(1) + 'mm';
selectedObj.style.marginLeft = (-parseFloat(selectedObj.style.width) / 2) + 'mm';
selectedObj.style.marginTop = (-parseFloat(selectedObj.style.height) / 2) + 'mm';
updateStatus(selectedObj, selectedObj.dataset.objId);
markChanged(selectedObj);
}
function applyRotate(el, delta) {
let transform = el.style.transform || '';
const rotM = transform.match(/rotate\(([-\d.]+)deg\)/);
let rot = rotM ? parseFloat(rotM[1]) : 0;
rot += delta;
if (rotM) {
transform = transform.replace(/rotate\([-\d.]+deg\)/, `rotate(${rot}deg)`);
} else {
transform += ` rotate(${rot}deg)`;
}
el.style.transform = transform.trim();
markChanged(el);
}
function flipSelected() {
if (!selectedObj) return;
let transform = selectedObj.style.transform || '';
const scxM = transform.match(/scaleX\(([-\d.]+)\)/);
let scx = scxM ? parseFloat(scxM[1]) : 1;
scx = scx < 0 ? 1 : -1;
if (scxM) {
transform = transform.replace(/scaleX\([-\d.]+\)/, `scaleX(${scx})`);
} else {
transform += ` scaleX(${scx})`;
}
selectedObj.style.transform = transform.trim();
updateStatus(selectedObj, selectedObj.dataset.objId);
markChanged(selectedObj);
}
function toggleMode() {
deselectAll();
editMode = editMode === 'objects' ? 'nodes' : 'objects';
document.body.classList.toggle('node-mode', editMode === 'nodes');
const btn = document.getElementById('btn-mode');
btn.textContent = editMode === 'objects' ? 'Mode: Objects' : 'Mode: Nodes';
btn.classList.toggle('active', editMode === 'nodes');
document.getElementById('status-info').textContent =
editMode === 'objects' ? 'Click an object to select' : 'Click a node to select';
}
function toggleRouteHL() {
routeHighlight = !routeHighlight;
const btn = document.getElementById('btn-route');
btn.classList.toggle('active', routeHighlight);
pages.forEach(pageEl => {
const routeStr = pageEl.dataset.enemyRoute;
if (!routeStr) return;
const route = routeStr.split(',');
// Build set of edge keys on the route
const routeEdges = new Set();
for (let i = 0; i < route.length - 1; i++) {
const a = parseInt(route[i]), b = parseInt(route[i + 1]);
routeEdges.add(`${Math.min(a, b)}-${Math.max(a, b)}`);
}
pageEl.querySelectorAll('line[data-edge]').forEach(line => {
const [ea, eb] = line.dataset.edge.split('-').map(Number);
const key = `${Math.min(ea, eb)}-${Math.max(ea, eb)}`;
if (routeEdges.has(key)) {
line.classList.toggle('route-highlight', routeHighlight);
}
});
});
}
function markChanged(el) {
const id = el.dataset.objId;
const orig = originalState.get(id);
if (!orig) return;
const curLeft = parseFloat(el.style.left);
const curTop = parseFloat(el.style.top);
const curW = parseFloat(el.style.width);
const curH = parseFloat(el.style.height);
const changed = (
Math.abs(orig.left - curLeft) > 0.3 ||
Math.abs(orig.top - curTop) > 0.3 ||
Math.abs(orig.w - curW) > 0.3 ||
Math.abs(orig.h - curH) > 0.3 ||
(el.style.transform || '') !== buildOrigTransform(orig)
);
el.classList.toggle('obj-changed', changed);
}
function buildOrigTransform(orig) {
let t = '';
if (orig.scaleX < 0) t += `scaleX(${orig.scaleX})`;
if (orig.rotate) t += ` rotate(${orig.rotate}deg)`;
return t.trim();
}
function scrollToPage(index) {
if (index < 0 || index >= pages.length) return;
pages[index].scrollIntoView({ behavior: 'smooth', block: 'start' });
}
function buildConfig(changesOnly) {
const result = { file, pages: [] };
pages.forEach((pageEl, pageIndex) => {
const pageObjs = objects.filter(o => o.pageNum === pageIndex + 1);
const items = [];
pageObjs.forEach(obj => {
const el = obj.el;
const left = parseFloat(el.style.left);
const top = parseFloat(el.style.top);
const w = parseFloat(el.style.width);
const h = parseFloat(el.style.height);
let rotate = 0, flipH = false;
if (el.style.transform) {
const rotM = el.style.transform.match(/rotate\(([-\d.]+)deg\)/);
const scxM = el.style.transform.match(/scaleX\(([-\d.]+)\)/);
if (rotM) rotate = Math.round(parseFloat(rotM[1]));
if (scxM && parseFloat(scxM[1]) < 0) flipH = true;
}
const orig = originalState.get(obj.id);
if (changesOnly && orig) {
const origTransform = buildOrigTransform(orig);
const same = Math.abs(orig.left - left) < 0.3 &&
Math.abs(orig.top - top) < 0.3 &&
Math.abs(orig.w - w) < 0.3 &&
Math.abs(orig.h - h) < 0.3 &&
(el.style.transform || '') === origTransform;
if (same) return;
}
items.push({
nodeId: parseInt(obj.nodeId),
type: obj.type,
src: obj.src,
left: left.toFixed(1) + 'mm',
top: top.toFixed(1) + 'mm',
w: w.toFixed(0) + 'mm',
h: h.toFixed(0) + 'mm',
rotate, flipH
});
});
// Collect changed nodes for this page
const pageNodes = nodeEls.filter(n => n.pageNum === pageIndex + 1);
const movedNodes = [];
pageNodes.forEach(nd => {
const el = nd.el;
const left = parseFloat(el.style.left);
const top = parseFloat(el.style.top);
const orig = nodeOrigState.get(nd.nid);
if (changesOnly && orig && Math.abs(orig.left - left) < 0.3 && Math.abs(orig.top - top) < 0.3) return;
movedNodes.push({
nodeId: parseInt(nd.nodeId),
left: left.toFixed(1) + 'mm',
top: top.toFixed(1) + 'mm'
});
});
if (items.length > 0 || movedNodes.length > 0) {
const pageData = { page: pageIndex + 1 };
if (items.length > 0) pageData.objects = items;
if (movedNodes.length > 0) pageData.nodes = movedNodes;
result.pages.push(pageData);
}
});
return result;
}
function copyConfig(changesOnly) {
const config = buildConfig(changesOnly);
const json = JSON.stringify(config, null, 2);
navigator.clipboard.writeText(json).then(() => {
showToast(changesOnly ? 'Changes copied!' : 'Full config copied!');
}).catch(() => {
console.log(json);
showToast('Copied to console (clipboard blocked)');
});
}
function resetCurrentPage() {
const pageNum = currentPage + 1;
objects.filter(o => o.pageNum === pageNum).forEach(obj => {
const orig = originalState.get(obj.id);
if (!orig) return;
obj.el.style.left = orig.left + 'mm';
obj.el.style.top = orig.top + 'mm';
obj.el.style.width = orig.w + 'mm';
obj.el.style.height = orig.h + 'mm';
obj.el.style.marginLeft = (-orig.w / 2) + 'mm';
obj.el.style.marginTop = (-orig.h / 2) + 'mm';
obj.el.style.transform = buildOrigTransform(orig);
obj.el.classList.remove('obj-changed');
// Reset node and edges too
moveNodeAndEdges(obj.el, orig.left, orig.top);
});
showToast(`Page ${pageNum} reset`);
}
async function saveToServer() {
const config = buildConfig(false);
try {
const resp = await fetch('/api/save-edits', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
taskType: 'space-route',
docId: docId,
data: config
})
});
const result = await resp.json();
if (result.ok) {
showToast('Saved!');
} else {
showToast('Error: ' + result.error);
}
} catch (e) {
showToast('Save failed: ' + e.message);
}
}
function showToast(msg) {
const toast = document.getElementById('toast');
toast.textContent = msg;
toast.classList.add('show');
setTimeout(() => toast.classList.remove('show'), 1500);
}
})();
</script>
</body>
</html>

View File

@ -0,0 +1,161 @@
#!/usr/bin/env node
/**
* Generate output HTML from template + data for space-route documents.
*
* Usage: node generate.mjs <docId>
* Example: node generate.mjs space-route-1
*
* Reads: docs/<docId>.template.html
* Reads: docs/<docId>.data.json (optional)
* Writes: docs/<docId>.output.html
*
* data.json format (from space-route editor):
* {
* pages: [{
* page: 1,
* objects: [{ nodeId, type, src, left, top, w, h, rotate, flipH }],
* nodes: [{ nodeId, left, top }]
* }]
* }
*/
import { readFileSync, writeFileSync, existsSync } from 'fs';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';
const __dirname = dirname(fileURLToPath(import.meta.url));
const docsDir = join(__dirname, '..', 'docs');
const docId = process.argv[2];
if (!docId) {
console.error('Usage: node generate.mjs <docId>');
process.exit(1);
}
const templatePath = join(docsDir, `${docId}.template.html`);
const dataPath = join(docsDir, `${docId}.data.json`);
const outputPath = join(docsDir, `${docId}.output.html`);
if (!existsSync(templatePath)) {
console.error(`Template not found: ${templatePath}`);
process.exit(1);
}
let html = readFileSync(templatePath, 'utf-8');
if (existsSync(dataPath)) {
const data = JSON.parse(readFileSync(dataPath, 'utf-8'));
html = applyData(html, data);
console.log(`Applied data from ${data.pages?.length || 0} pages`);
}
writeFileSync(outputPath, html);
console.log(`Generated: ${outputPath}`);
function applyData(html, data) {
if (!data.pages) return html;
// Split by page divs
const pageRegex = /<div class="w-\[210mm\] h-\[297mm\]"/g;
const starts = [];
let match;
while ((match = pageRegex.exec(html)) !== null) {
starts.push(match.index);
}
if (starts.length === 0) return html;
for (let i = data.pages.length - 1; i >= 0; i--) {
const pageData = data.pages[i];
const pageNum = pageData.page || (i + 1);
const pageIdx = pageNum - 1;
if (pageIdx >= starts.length) continue;
const pageStart = starts[pageIdx];
const pageEnd = pageIdx + 1 < starts.length ? starts[pageIdx + 1] : html.length;
let pageHtml = html.slice(pageStart, pageEnd);
// Apply object positions
if (pageData.objects) {
for (const obj of pageData.objects) {
pageHtml = applyObject(pageHtml, obj);
}
}
// Apply node positions and update edges
if (pageData.nodes) {
for (const node of pageData.nodes) {
pageHtml = applyNode(pageHtml, node);
}
}
html = html.slice(0, pageStart) + pageHtml + html.slice(pageEnd);
}
return html;
}
function applyObject(pageHtml, obj) {
// Match: <img class="space-obj" data-node-id="N" data-type="..." style="..."
const nodeId = obj.nodeId;
const regex = new RegExp(
`(<img class="space-obj"[^>]*data-node-id="${nodeId}"[^>]*style=")([^"]*)(")`
);
return pageHtml.replace(regex, (match, prefix, oldStyle, suffix) => {
const parts = [];
parts.push(`left: ${obj.left}`);
parts.push(`top: ${obj.top}`);
if (obj.w) parts.push(`width: ${obj.w}`);
if (obj.h) parts.push(`height: ${obj.h}`);
const transforms = [];
if (obj.rotate) transforms.push(`rotate(${obj.rotate}deg)`);
if (obj.flipH) transforms.push('scaleX(-1)');
if (transforms.length) parts.push(`transform: ${transforms.join(' ')}`);
// Preserve margin if present in old style
const marginMatch = oldStyle.match(/margin[^;]+;/);
if (marginMatch) parts.push(marginMatch[0].replace(/;$/, ''));
return prefix + parts.join('; ') + ';' + suffix;
});
}
function applyNode(pageHtml, node) {
// Update node div position
const nodeRegex = new RegExp(
`(<div[^>]*data-node-id="${node.nodeId}"[^>]*style=")([^"]*)(")`
);
pageHtml = pageHtml.replace(nodeRegex, (match, prefix, oldStyle, suffix) => {
const newStyle = oldStyle
.replace(/left:\s*[^;]+/, `left: ${node.left}`)
.replace(/top:\s*[^;]+/, `top: ${node.top}`);
return prefix + newStyle + suffix;
});
// Update edges connected to this node
const leftMm = parseFloat(node.left);
const topMm = parseFloat(node.top);
// Edges where this node is first: <line data-edge="N-M" x1="..." y1="..."
const edgeRegex1 = new RegExp(
`(<line[^>]*data-edge="${node.nodeId}-\\d+"[^>]*)(x1=")[^"]*("\\s*y1=")[^"]*(")`,'g'
);
pageHtml = pageHtml.replace(edgeRegex1, (match, prefix, x1p, y1p, suffix) => {
return `${prefix}${x1p}${leftMm}mm${y1p}${topMm}mm${suffix}`;
});
// Edges where this node is second: <line data-edge="M-N" ... x2="..." y2="..."
const edgeRegex2 = new RegExp(
`(<line[^>]*data-edge="\\d+-${node.nodeId}"[^>]*)(x2=")[^"]*("\\s*y2=")[^"]*(")`,'g'
);
pageHtml = pageHtml.replace(edgeRegex2, (match, prefix, x2p, y2p, suffix) => {
return `${prefix}${x2p}${leftMm}mm${y2p}${topMm}mm${suffix}`;
});
return pageHtml;
}

View File

@ -1,42 +0,0 @@
{
"id": "space-worksheet2",
"title": "Исследуй Планету",
"description": "3-page space worksheet: addition A+B±C (result 0-40), multiply by 5 variants, compound A×B+C×D",
"labels": {
"title": "Исследуй Планету",
"subtitle": "Собери ресурсы, решая примеры!",
"footerBubble": "Итого собрано на планете:"
},
"theme": {
"style": "space",
"template": "space-base",
"icons": "assets/icons/pack2/"
},
"layout": {
"columns": 2,
"problemsPerPage": 20
},
"pages": [
{
"task": "A + B + C, где A от 12 до 24, B ±(от 6 до 10), C ±(от 2 до 5). Результат от 0 до 40 включительно",
"problemCount": 20,
"heroImage": "assets/hero-images/spaceship1.jpeg",
"footerImage": "assets/footers/planet2.jpeg",
"heroDirection": "row-reverse"
},
{
"task": "5 + 5 + 5 (сложение пятерок: 2, 3 или 4 штуки) ИЛИ 5 × N (N от 1 до 12) ИЛИ 5 × N ± 5",
"problemCount": 20,
"heroImage": "assets/hero-images/spaceship3.png",
"footerImage": "assets/footers/planet4.jpeg",
"heroDirection": "row"
},
{
"task": "A × B + C × D, где A от 2 до 4, B от 1 до 3, C от 2 до 3, D от 1 до 2",
"problemCount": 20,
"heroImage": "assets/hero-images/spaceship5.jpeg",
"footerImage": "assets/footers/planet6.jpeg",
"heroDirection": "row-reverse"
}
]
}

View File

@ -1,93 +0,0 @@
{
"id": "space-worksheet3",
"title": "Исследуй Планету",
"description": "9-page space worksheet combining patterns from worksheet1 and worksheet2: addition, multiply by 5, multiplication table, constrained addition, mixed fives, compound multiplication",
"labels": {
"title": "Исследуй Планету",
"subtitle": "Собери ресурсы, решая примеры!",
"footerBubble": "Итого собрано на планете:"
},
"theme": {
"style": "space",
"template": "space-base",
"icons": ["assets/icons/pack1/", "assets/icons/pack2/"]
},
"layout": {
"columns": 2,
"problemsPerPage": 20
},
"pages": [
{
"task": "A + B ± C, где A от 8 до 16, B от 4 до 8, C от 1 до 3. Знак ± выбирается случайно",
"problemCount": 20,
"heroImage": "assets/hero-images/spaceship1.jpeg",
"footerImage": "assets/footers/planet1.jpeg",
"heroDirection": "row-reverse",
"iconPack": "pack1"
},
{
"task": "5 × N ± C, где N от 1 до 5, C от 1 до 6. Знак ± выбирается случайно",
"problemCount": 20,
"heroImage": "assets/hero-images/spaceship2.jpeg",
"footerImage": "assets/footers/planet2.jpeg",
"heroDirection": "row",
"iconPack": "pack1"
},
{
"task": "A × B ± C, где A и B от 1 до 4, C от 1 до 8. Знак ± выбирается случайно",
"problemCount": 20,
"heroImage": "assets/hero-images/spaceship3.png",
"footerImage": "assets/footers/planet3.jpeg",
"heroDirection": "row-reverse",
"iconPack": "pack1"
},
{
"task": "A + B + C, где A от 12 до 24, B ±(от 6 до 10), C ±(от 2 до 5). Результат от 0 до 40 включительно",
"problemCount": 20,
"heroImage": "assets/hero-images/spaceship4.jpeg",
"footerImage": "assets/footers/planet4.jpeg",
"heroDirection": "row",
"iconPack": "pack2"
},
{
"task": "5 + 5 + 5 (сложение пятерок: 2, 3 или 4 штуки) ИЛИ 5 × N (N от 1 до 12) ИЛИ 5 × N ± 5",
"problemCount": 20,
"heroImage": "assets/hero-images/spaceship5.jpeg",
"footerImage": "assets/footers/planet5.jpeg",
"heroDirection": "row-reverse",
"iconPack": "pack2"
},
{
"task": "A × B + C × D, где A от 2 до 4, B от 1 до 3, C от 2 до 3, D от 1 до 2",
"problemCount": 20,
"heroImage": "assets/hero-images/spaceship6.jpeg",
"footerImage": "assets/footers/planet6.jpeg",
"heroDirection": "row",
"iconPack": "pack2"
},
{
"task": "A + B ± C, где A от 8 до 16, B от 4 до 8, C от 1 до 3. Знак ± выбирается случайно",
"problemCount": 20,
"heroImage": "assets/hero-images/spaceship7.jpeg",
"footerImage": "assets/footers/planet7.jpeg",
"heroDirection": "row-reverse",
"iconPack": "pack1"
},
{
"task": "5 × N ± C, где N от 1 до 5, C от 1 до 6. Знак ± выбирается случайно",
"problemCount": 20,
"heroImage": "assets/hero-images/spaceship8.jpeg",
"footerImage": "assets/footers/planet8.jpeg",
"heroDirection": "row",
"iconPack": "pack1"
},
{
"task": "A × B ± C, где A и B от 1 до 4, C от 1 до 8. Знак ± выбирается случайно",
"problemCount": 20,
"heroImage": "assets/hero-images/spaceship9.jpeg",
"footerImage": "assets/footers/planet9.jpeg",
"heroDirection": "row-reverse",
"iconPack": "pack1"
}
]
}