# THIS YOU — DEV HANDOFF / CODE MAP
## Current project state, how the system works, where everything lives, and how to continue safely

**Current reference build:** `personalized_magazine_engine_v1_4`  
**Runtime target:** PHP 7.4 + MySQL / MariaDB  
**Development environment used:** Laragon  
**Public product name:** **THIS YOU**

This document is intended to be the **single DEV handoff file**.  
If conversation context is ever lost, read this file first before modifying the code.

---

# 1. PRODUCT CORE — DO NOT LOSE THIS

THIS YOU is not a face-swap generator and not an AI novelty toy.

It is a real fashion + culture magazine with a shared editorial world and a personalized fashion layer.

Core concept:

> **The same world. The same moment. A different you.**

Editorial/system rule:

> **The event belongs to the magazine. The outfit belongs to the reader.**

Production rule:

> **Shared magazine. Personalized arrivals.**

Quality positioning:

> **Human-edited. AI-assisted. Individually reviewed.**

The magazine creates shared:
- stories
- interviews
- culture
- art
- music
- places
- events
- situations / Moments

Each reader gets unique:
- cover
- Arrival image
- styling
- products
- Why it works
- Style notes
- stylist comments / summary

The system must always preserve this separation.

---

# 2. EDITORIAL GRAMMAR

The current editorial frame is:

> **STORY → SCENE → THE MOMENT → YOUR ARRIVAL → THE STYLE**

Meaning:

## STORY
Shared article / editorial context.

## SCENE
Shared atmosphere / visual world / mood / objects / image / playlist / supporting page.

## THE MOMENT
Shared concrete situation:
- where
- when
- what is happening
- social context
- environment
- what happens next

## YOUR ARRIVAL
Personalized:
- reader image
- personal styling direction

## THE STYLE
Personalized:
- products
- Why it works
- Style notes
- feedback

Most chapter blocks are represented as four print/digital pages:

```text
01 STORY
02 SCENE
03 THE MOMENT + YOUR ARRIVAL
04 THE STYLE
```

Conceptually:

```text
WORLD → WORLD → YOU → YOU
```

---

# 3. CURRENT PUBLIC OFFER

Current customer-facing product:

## PRINT + DIGITAL ONLY

Price:

> **$39 + shipping calculated at checkout**

There is currently **no Digital Only product** in the intended UX.

The landing page supports:

- **ORDER CURRENT ISSUE**
- **PRE-ORDER NEXT ISSUE**

Current implementation shows the latest published issue plus the immediately following non-archived issue.

Real Stripe checkout is **not yet connected**.

---

# 4. ACCOUNT / PROFILE MODEL

Do not build a classic SaaS password signup unless the product direction changes.

Current intended flow:

```text
Choose issue
→ fill short profile + 4 photos
→ checkout
→ payment success
→ email secure magic link
→ reader can edit profile later
```

Current MVP uses the existing private `user_issue.private_token` as the magic-link credential.

Profile URL:

```text
/profile.php?token=PRIVATE_TOKEN
```

The reader can update:
- first name
- last name
- email
- four photos
- height
- clothing size
- shoe size
- fit preference
- favorite brands
- style vibes
- use cases
- budget

Important principle:

> **Profile = current truth. Generated issue = frozen snapshot.**

Profile edits should affect future generation.

Already human-approved pages must **not silently regenerate**.

Later improvement:
- add explicit profile snapshot/version per generated issue
- show `Profile changed after generation`
- offer deliberate regenerate

---

# 5. REQUIRED READER PHOTOS

The current onboarding asks for four reference photos:

1. `full_body`
2. `three_quarter`
3. `portrait`
4. `casual_reference`

A new reader is expected to provide all four.

Returning readers can reuse already stored photos.

These are stored in `user_photos`.

---

# 6. HIGH-LEVEL ENGINE ARCHITECTURE

There is **one reusable publishing engine**.

Do NOT copy the PHP codebase for Magazine 02, 03, etc.

Architecture:

```text
                         THIS YOU ENGINE
                               │
            ┌──────────────────┼──────────────────┐
            │                  │                  │
        ISSUE 01           ISSUE 02           ISSUE 03
            │                  │                  │
      shared editorial   shared editorial   shared editorial
      chapters/pages     chapters/pages     chapters/pages
            │                  │                  │
        Reader A             Reader A             Reader A
        Reader B             Reader B             Reader B
        Reader C             Reader C             Reader C
            │
      personalized
      arrivals/products
```

A new issue should be mostly:

```text
new DB data
+ theme CSS
+ existing layouts
+ optional new layout files
```

NOT:

```text
copy whole project
+ rewrite PHP
```

---

# 7. CURRENT PROJECT ROOT

Reference folder:

```text
personalized_magazine_engine_v1_4/
```

Main structure:

```text
/
├── index.php
├── issue.php
├── share.php
├── start.php
├── profile.php
├── action.php
├── print-render.php
├── setup.php
├── seed.php
├── bootstrap.php
│
├── config/
│   ├── config.php
│   └── config.example.php
│
├── lib/
│   ├── helpers.php
│   ├── db.php
│   ├── auth.php
│   ├── migrations.php
│   ├── issues.php
│   ├── readers.php
│   ├── generation.php
│   ├── renderer.php
│   ├── print.php
│   └── seed.php
│
├── layouts/
│   ├── cover/
│   ├── concept/
│   ├── story/
│   ├── scene/
│   ├── moment/
│   ├── style/
│   ├── summary/
│   ├── ad/
│   ├── credits/
│   └── back/
│
├── themes/
│   ├── issue-001.css
│   └── issue-002.css
│
├── assets/
│   ├── css/
│   │   ├── base.css
│   │   ├── digital.css
│   │   ├── print.css
│   │   └── admin.css
│   ├── js/
│   │   ├── app.js
│   │   └── admin.js
│   └── images/
│
├── admin/
│   ├── index.php
│   ├── issues.php
│   ├── issue-edit.php
│   ├── chapter-edit.php
│   ├── page-edit.php
│   ├── readers.php
│   ├── reader.php
│   ├── generate.php
│   ├── review.php
│   ├── personal-page-edit.php
│   ├── products.php
│   ├── print-preview.php
│   ├── generate-print.php
│   ├── download.php
│   ├── migrate.php
│   ├── login.php
│   └── logout.php
│
├── seed/
│   └── issue1_data.php
│
├── docs/
│   ├── CORE.md
│   ├── EDITORIAL.md
│   ├── IMPLEMENTED_SYSTEM.md
│   └── SYSTEM_ARCHITECTURE_ORIGINAL.md
│
└── tests/
    ├── render_layouts.php
    └── static_checks.php
```

---

# 8. BOOTSTRAP

File:

```text
/bootstrap.php
```

This loads the application libraries in this order:

```php
helpers.php
db.php
auth.php
migrations.php
issues.php
readers.php
generation.php
renderer.php
print.php
```

If adding a new reusable service, load it here.

Do not make random top-level files each reimplement DB/config logic.

---

# 9. CONFIGURATION

Main local config:

```text
/config/config.php
```

Important current values:

```php
'app_name' => 'THIS YOU'
```

DB default:

```text
fashion_magazine_engine_v1
```

Laragon default:

```text
host: 127.0.0.1
user: root
pass: ''
```

Admin default local key:

```text
change-this-admin-key
```

Change for any real deployment.

Current commerce:

```text
price_usd = 39
shipping_copy = shipping calculated at checkout
```

Current generation provider:

```text
demo
```

Current print dimensions are **preview defaults only**:

```text
8.5 × 11 in interior
17 × 11 in cover preview
```

Do NOT assume these are final POD specifications.

---

# 10. IMPORTANT DATABASE RULE

Current engine must use the new DB:

```text
fashion_magazine_engine_v1
```

Do NOT point it at the old prototype database:

```text
fashion_magazine
```

Earlier bug:

```text
Unknown column 'slug' in 'where clause'
```

Cause:
- new engine connected to an old incompatible `issues` table
- old table did not contain `slug`
- `CREATE TABLE IF NOT EXISTS` could not replace the old schema

If this error ever appears again:
1. inspect `config/config.php`
2. verify DB name
3. use the engine database
4. run `setup.php`
5. run migrations / seed as needed

Do not delete the legacy DB unless deliberately cleaning up.

---

# 11. DATABASE TABLE MAP

Current schema migration version is effectively the initial multi-issue schema.

Tables:

```text
schema_migrations

issues
issue_chapters
issue_pages

users
user_profiles
user_photos

user_issues
user_issue_pages
user_issue_products

products

reactions
comments

generation_jobs
review_log

share_links
```

---

# 12. SHARED ISSUE TABLES

## `issues`

One row = one Magazine issue.

Key fields:
- `id`
- `issue_number`
- `slug`
- `title`
- `subtitle`
- `season`
- `issue_year`
- `theme_name`
- `status`
- `theme_key`
- `page_count`
- `published_at`

Statuses:

```text
draft
editorial_review
published
archived
```

Every issue must have its own `slug`.

---

## `issue_chapters`

One row = one editorial chapter inside one issue.

Key fields:
- `issue_id`
- `chapter_number`
- `title`
- `category`
- `place_name`
- `time_label`
- `accent_key`
- `accent_value`
- `graphic_key`
- `sort_order`

Example:

```text
Chapter 01
ART
CHELSEA
18:40
cobalt accent
```

Chapter identity should visually connect STORY / SCENE / MOMENT / STYLE pages.

---

## `issue_pages`

One row = one shared page definition.

Key fields:
- `issue_id`
- `chapter_id`
- `page_number`
- `sort_order`
- `page_type`
- `layout_key`
- `personalization_mode`
- `title`
- `subtitle`
- `eyebrow`
- `body_html`
- `excerpt`
- `image_asset`
- `data_json`
- `is_published`

This is the central CMS page table.

---

# 13. PERSONALIZATION MODES

`issue_pages.personalization_mode` has:

```text
shared
personalized
hybrid
```

Use these intentionally.

## shared
Same for everyone.

Examples:
- STORY
- SCENE
- interview
- art
- poem
- house ad

## personalized
Reader-specific content.

Examples:
- cover
- STYLE
- final reader style summary

## hybrid
Shared context + personal content.

Main example:
- THE MOMENT is shared
- YOUR ARRIVAL image/text is personal

---

# 14. PAGE TYPES CURRENTLY USED

Current engine supports layouts for:

```text
cover
concept
story
scene
moment
style
style_summary
house_ad
credits
back_cover
```

The architecture can later add:
- interview
- music
- art
- poem
- city
- photo essay
- objects
etc.

A page's **meaning** is `page_type`.

A page's **design** is `layout_key`.

Do not confuse these.

---

# 15. READER TABLES

## `users`

Identity:
- email
- first_name
- last_name
- status
- is_demo

Email is intended as the main commerce/access identity.

---

## `user_profiles`

Long-term style profile:
- height
- clothing size
- shoe size
- fit preference
- favorite brands
- style vibes
- use cases
- budget notes
- budget max per item
- `style_profile_json`

The profile belongs to the person, not a specific issue.

---

## `user_photos`

Reader reference images.

Fields:
- `user_id`
- `file_path`
- `photo_type`
- `is_primary`

Current intended types:
- `full_body`
- `three_quarter`
- `portrait`
- `casual_reference`

---

# 16. READER × ISSUE TABLE

## `user_issues`

This table means:

> **This reader receives this issue.**

Fields:
- `user_id`
- `issue_id`
- `private_token`
- `status`
- `generation_version`
- `edition_type`
- `personalized_cover`
- `is_demo`
- timestamps

Unique:

```text
(user_id, issue_id)
```

Current intended edition:

```text
print_digital
```

Statuses:

```text
pending
generating
review
ready
published
printed
```

The `private_token` currently powers:
- owner issue access
- profile magic link

---

# 17. PERSONALIZED PAGE TABLE

## `user_issue_pages`

This stores reader-specific overrides/results for an `issue_page`.

Fields:
- `user_issue_id`
- `issue_page_id`
- `hero_image`
- `personal_title`
- `personal_subtitle`
- `personal_intro`
- `why_it_works`
- `style_notes`
- `stylist_note`
- `generation_prompt`
- `generation_data_json`
- `review_status`
- reviewer info

This is extremely important.

The shared Moment may say:

```text
CHELSEA GALLERY OPENING
6:40 PM
```

But Jānis can have unique:
- hero image
- arrival subtitle
- Why it works
- Style notes
- products

Another reader gets different values in their own row.

---

# 18. PERSONALIZED PRODUCTS

## `products`

Shared product pool.

Stores:
- brand
- product name
- category
- price
- currency
- exact product URL
- optional affiliate URL
- source image URL
- metadata JSON
- availability status

Currently mainly manual/demo.

---

## `user_issue_products`

Products chosen for one reader's one personalized style page.

Fields:
- `user_issue_page_id`
- `product_id`
- copied brand/name/price/url
- `slot_name`
- sort order
- verification status

Typical slots:
- top
- bottom
- shoes
- outerwear
- bag

The page renderer shows:

```text
€39.95  SHOP ↗
```

The arrow means the link goes to the external retailer.

Important UX decision:
- keep `SHOP`
- do not rely on `↗` alone because users may not understand it

---

# 19. FEEDBACK MEMORY

## `reactions`

Supports:
- whole look reaction
- individual product reaction

Reaction types:

```text
love
not_me
too_expensive
more_like_this
```

Visual UI:

```text
♥
×
$
＋
```

Owner feedback is training data for future issues.

Guest feedback is intentionally disabled.

---

## `comments`

Private stylist notes.

Current owner UI:

```text
PRIVATE NOTE TO YOUR STYLIST
```

These comments are included in future style-memory generation context.

---

# 20. GENERATION / REVIEW TABLES

## `generation_jobs`

Tracks generation work:
- job type
- status
- input JSON
- output JSON
- errors
- timestamps

Statuses:

```text
queued
running
completed
failed
```

---

## `review_log`

Tracks human approval/rejection.

This supports the brand promise:

> **Every personalized edition is individually reviewed.**

---

# 21. SHARE LINKS

## `share_links`

Fields:
- `user_issue_id`
- token
- scope
- start page
- active flag

Scopes:

```text
page_only
page_and_issue
full_issue
```

Shared versions are read-only.

They do not train the owner's style memory.

---

# 22. PUBLIC ROUTES

## `/index.php`

Main THIS YOU landing page.

Current content:
- brand
- core idea
- `$39`
- `PRINT MAGAZINE + PRIVATE DIGITAL EDITION`
- current issue
- next issue
- public archive
- CTA
- `by absurd.website`

This is the main marketing landing page.

---

## `/issue.php`

Main magazine renderer.

Two modes:

### Owner mode

```text
issue.php?token=PRIVATE_TOKEN&p=7
```

Owner gets:
- private edition
- voting
- product voting
- private stylist notes
- Profile
- Share

### Public preview mode

```text
issue.php?slug=ny-summer-street&p=7
```

Gets:
- public demo edition
- locked/disabled feedback icons
- no ability to contaminate owner profile

If no slug is given:
- loads latest published issue

---

## `/share.php`

Read-only shared reader edition.

Example:

```text
share.php?t=SHARE_TOKEN&p=7
```

Honors share scope.

---

## `/start.php`

Customer onboarding.

Current intended flow:
- choose current or next issue
- enter reader details
- upload four photos
- see price
- Continue to checkout

Current CTA:

```text
CONTINUE TO CHECKOUT · $39
```

Important:
- real checkout is NOT connected yet
- current implementation stops before real Stripe payment

---

## `/profile.php`

Passwordless profile editing via private token.

Example:

```text
profile.php?token=PRIVATE_TOKEN
```

Allows reader to:
- update profile
- replace photo slots
- see magazine history
- reopen issues

---

## `/action.php`

Owner-only JSON endpoint.

POST actions:
- `reaction`
- `comment`
- `create_share`

Requires valid `private_token`.

Never allow guest reactions through this route.

---

## `/print-render.php`

Internal print rendering route.

Used by admin print preview / Chrome export.

Not a normal public page.

---

## `/setup.php`

Database installation/migration/setup.

Use for fresh engine installation.

---

## `/seed.php`

Seeds demo data.

---

# 23. ADMIN ROUTES

Admin root:

```text
/admin/
```

Authentication currently uses one admin key stored in config.

This is sufficient for local MVP only.

---

## `/admin/index.php`

Dashboard.

Use for:
- system overview
- schema status
- shortcuts

---

## `/admin/issues.php`

Magazine list.

Use:
- create a new issue
- open issue editor

---

## `/admin/issue-edit.php?id=ISSUE_ID`

Central issue CMS.

Can:
- edit issue title
- subtitle
- season
- year
- theme
- intro
- publish/unpublish
- view chapters
- assign readers
- see page stack
- move pages up/down
- open page editor
- preview digital issue

Important principle shown in UI:

> Editing this issue changes the shared magazine, not other issues.

---

## `/admin/chapter-edit.php?id=CHAPTER_ID`

Edit shared chapter identity:
- title
- category
- place
- time
- accent
- graphic key

This should keep a 4-page chapter visually coherent.

---

## `/admin/page-edit.php?id=PAGE_ID`

Edit one shared issue page.

Handles page-level:
- title
- subtitle
- eyebrow
- body content
- page data
- layout
- personalization mode
- asset fields

This is where future shared issue content created with ChatGPT should be inserted.

---

## `/admin/readers.php`

Reader list.

---

## `/admin/reader.php?id=USER_ID`

Reader control center.

Shows/edits:
- personal info
- profile
- photos
- style memory
- issue history
- assign issue

This is where future profile-memory UX should grow.

---

## `/admin/generate.php?id=USER_ISSUE_ID`

`GEN MAGAZINE` screen for one reader + one issue.

Current generation provider is demo.

This initiates personal page generation workflow.

---

## `/admin/review.php?id=USER_ISSUE_ID`

Human review queue for one edition.

Goal:
- inspect all personalized pages
- approve / reject
- ensure the complete issue is reviewed before production

---

## `/admin/personal-page-edit.php?id=USER_ISSUE_PAGE_ID`

Manual correction of a personalized page.

Can edit reader-specific:
- image
- titles
- Why it works
- Style notes
- Stylist note
- products

This is critical for:
- manual ChatGPT workflow
- human finishing
- quality control

Future admin improvement requested:
show a stronger visual comparison:

```text
SHARED MOMENT
↓
JĀNIS — PERSONALIZED COPY
```

so it is immediately obvious what is shared vs unique.

---

## `/admin/products.php`

Shared product pool CMS.

Currently MVP/manual.

Future:
- product feeds
- stock
- affiliate links
- product metadata
- image analysis

---

## `/admin/print-preview.php?id=USER_ISSUE_ID`

Preflight + preview for print.

---

## `/admin/generate-print.php?id=USER_ISSUE_ID`

Attempts PDF generation.

---

## `/admin/download.php`

Secure-ish admin PDF download from exports folder.

---

## `/admin/migrate.php`

Runs DB migrations.

---

# 24. LIBRARY CODE MAP

## `/lib/helpers.php`

Generic helpers:
- config loading
- HTML escaping
- UTF-8 uppercase
- THIS YOU brand helper
- price helper
- shipping copy
- reader display name
- JSON
- URLs
- redirects
- request helpers
- flash messages
- CSRF
- random token
- slugify
- uploaded image storage

Important function:

```php
unicode_upper()
```

This fixed:

```text
JāNIS
```

to:

```text
JĀNIS
```

even if `mbstring` is unavailable.

Important function:

```php
reader_display_name()
```

Magazine header currently uses **first name only**.

---

## `/lib/db.php`

PDO layer.

Functions:
- `db()`
- `db_table_exists()`
- `db_column_exists()`
- `db_fetch_one()`
- `db_fetch_all()`
- `db_execute()`

Keep DB access centralized here.

---

## `/lib/auth.php`

Admin session/key authentication.

Current model is local MVP, not production-grade multi-admin auth.

---

## `/lib/migrations.php`

Contains database schema migration definitions and migration runner.

Important:
- migrations are idempotent
- MySQL DDL implicit commits are expected
- schema version is stored in `schema_migrations`

When adding DB columns/tables:
1. add a NEW migration version
2. do not manually patch production DB ad hoc
3. keep old migrations immutable

Current legacy lesson:
schema changes must be explicit or old DB structures can silently conflict.

---

## `/lib/issues.php`

Issue/chapter/page service.

Important functions include:
- `issue_list()`
- `issue_get()`
- `issue_get_by_slug()`
- `issue_chapters()`
- `issue_pages()`
- `issue_page_by_number()`
- `layout_registry()`
- `issue_update()`
- `chapter_update()`
- `issue_page_update()`
- `issue_publish()`
- `issue_unpublish()`
- `issue_move_page()`
- `normalize_issue_page_numbers()`
- `create_standard_issue()`
- `orderable_issue_choices()`

`create_standard_issue()` builds a default 32-page skeleton.

---

# 25. STANDARD 32-PAGE SKELETON

A newly created issue currently starts as:

```text
01 cover
02 concept
03 opening moment / arrival
04 opening style

05 story
06 scene
07 moment / arrival
08 style

09 story
10 scene
11 moment / arrival
12 style

13 story
14 scene
15 moment / arrival
16 style

17 story
18 scene
19 moment / arrival
20 style

21 story
22 scene
23 moment / arrival
24 style

25 story
26 scene
27 moment / arrival
28 style

29 style summary
30 house ad
31 next issue / credits
32 back cover
```

That is:
- 4 opening pages
- 6 chapters × 4 pages = 24
- 4 closing pages

Future issue creation should usually start here and be editorially customized.

---

# 26. `/lib/readers.php`

Reader/personalization service.

Important functions:
- `reader_list()`
- `reader_get()`
- `reader_photos()`
- `reader_primary_photo()`
- `reader_issues()`
- `reader_create()`
- `reader_update()`
- `reader_add_photo()`
- `reader_replace_photo_slot()`
- `reader_photo_by_type()`
- `user_issue_get()`
- `user_issue_by_token()`
- `user_issue_for_user_and_issue()`
- `user_issue_assign()`
- `user_issue_page_get()`
- `user_issue_page_by_number()`
- `user_issue_page_upsert()`
- `user_issue_products()`
- `replace_user_issue_products()`
- `reader_feedback_memory()`
- `reader_refresh_style_memory()`
- `toggle_reaction()`
- `reaction_map_for_user_issue()`
- `add_reader_comment()`

This is where reader cross-issue memory currently lives.

---

# 27. `/lib/generation.php`

Current personalization generation layer.

Provider:

```text
demo
```

Important:
this is a **workflow demo**, not real AI generation yet.

Current generation can:
- build context from profile
- include historical reactions/comments
- produce draft personalized copy
- select demo products
- create demo SVG editorial images
- save generation jobs
- mark pages for review
- approve/reject pages
- update edition readiness

Important functions:
- `generation_build_context()`
- `generate_user_issue()`
- `generation_select_products()`
- `generation_why_it_works()`
- `generation_style_notes()`
- `generation_stylist_note()`
- `generate_demo_editorial_svg()`
- `approve_user_issue_page()`
- `reject_user_issue_page()`
- `update_user_issue_ready_state()`

Future OpenAI/API provider should be added here or behind a new provider abstraction.

Do not rewrite the magazine engine to add AI.

---

# 28. MANUAL ChatGPT + API HYBRID PLAN

The engine is intentionally compatible with all three:

```text
manual ChatGPT
OpenAI API
human-written
```

All generation paths should finish by populating the same final fields:

```text
user_issue_pages
user_issue_products
```

Therefore:
- manual ChatGPT results can be pasted into admin
- API drafts can be reviewed in admin
- human editor can overwrite either

Recommended future metadata:
- `manual_chatgpt`
- `openai_api`
- `human_written`
- `hybrid`

This source field is not fully implemented yet.

---

# 29. `/lib/renderer.php`

Digital page rendering.

Important responsibilities:
- resolve assets
- load personalized page context
- select layout by `layout_key`
- render chapter marker
- render products
- render owner/locked feedback
- render private comment box
- contents drawer
- magazine header
- page navigation
- share modal
- full digital document

Header currently displays:

```text
THIS YOU
JĀNIS
PRIVATE EDITION / PUBLIC PREVIEW
CONTENTS
PROFILE (owner)
SHARE (owner)
GET YOUR ISSUE
PG 01 / 32
ISSUE 01 · SUMMER 2026
```

Page count is real issue page count, not hardcoded.

---

# 30. LAYOUT SYSTEM

Layouts are reusable PHP components.

Current files:

```text
layouts/cover/cover-01.php

layouts/concept/concept-01.php

layouts/story/story-editorial-01.php
layouts/story/story-editorial-02.php

layouts/scene/scene-grid-01.php
layouts/scene/scene-photo-01.php

layouts/moment/moment-arrival-01.php
layouts/moment/moment-arrival-02.php

layouts/style/style-products-01.php
layouts/style/style-products-02.php

layouts/summary/style-summary-01.php

layouts/ad/house-ad-01.php

layouts/credits/next-credits-01.php

layouts/back/back-01.php
```

Critical safety rule:

> **Do not rewrite an old published layout just because a new issue needs a different design.**

Instead create:

```text
story-editorial-03.php
scene-art-01.php
moment-arrival-03.php
```

Then assign the new `layout_key` only to the new issue.

This is how old magazines remain visually stable.

---

# 31. THEMES

Current theme files:

```text
/themes/issue-001.css
/themes/issue-002.css
```

Base system CSS:
- `base.css`
- `digital.css`

Per-issue art direction:
- theme CSS

A new issue may:
- reuse an existing theme
- add `issue-003.css`

Do not hard-code each issue's colors in PHP.

---

# 32. CSS RESPONSIBILITIES

## `assets/css/base.css`

Shared magazine visual system:
- typography
- common page modules
- product cards
- style detail geometry
- chapter labels
- base responsive behavior

Recent fixes:
- Moment divider no longer draws line through text
- Why It Works and Style Notes top alignment
- SHOP link clarity

---

## `assets/css/digital.css`

Digital-only shell:
- site header
- page arrows
- contents drawer
- share modal
- guest banner
- responsive web interaction

---

## `assets/css/print.css`

Fixed print renderer styling.

Not final POD production CSS yet.

---

## `assets/css/admin.css`

Admin CMS UI.

---

# 33. JAVASCRIPT

## `assets/js/app.js`

Digital magazine behavior:
- left/right keyboard navigation
- swipe/page navigation where supported
- reaction POSTs
- comment saving
- share link creation
- contents drawer
- share modal
- toast feedback

Owner behavior depends on `window.MAGAZINE`.

Important values:
- `owner`
- `privateToken`
- `actionUrl`
- `prevUrl`
- `nextUrl`

---

## `assets/js/admin.js`

Admin interaction helpers.

---

# 34. DIGITAL OWNER VS PUBLIC PREVIEW

This distinction is intentional.

## Owner edition

URL:
```text
issue.php?token=...
```

Has:
- working reactions
- working product reactions
- comments
- profile
- sharing

## Public preview

URL:
```text
issue.php?slug=...
```

Has:
- same visual magazine
- disabled feedback controls
- banner explaining it is a public preview

Reason:
a stranger must not modify the actual reader's style memory.

---

# 35. PRODUCT LINK UX

Current product row is explicitly clickable.

Renderer displays:
- brand
- product name
- product slot
- price
- `SHOP ↗`

Do not return to price-only links such as:

```text
€39.95 ↗
```

because it was too ambiguous.

`↗` is just an external-link cue.

`SHOP` is the semantic label.

---

# 36. CONTENTS

A contents drawer exists in the digital issue.

It includes selected significant page types such as:
- cover
- concept
- story
- moment
- style summary
- house ad
- credits

This was positively received and should be kept.

---

# 37. CURRENT SEASONAL DATA

V1.4 intentionally removed the old Summer/NY seeded magazine.

Fresh seed or the admin seasonal reset creates exactly:

## Issue 01

```text
AUTUMN
Autumn 2026
draft
32-page clean editorial skeleton
```

This is the issue being built now.

## Issue 02

```text
WINTER
Winter 2026/27
draft
32-page clean editorial skeleton
```

This is the next issue shell.

## Dev reader

One Jānis dev reader is attached to Autumn for owner/profile/generation testing. The engine does not seed final personalized Autumn pages.

## One-time reset tool

```text
/admin/reset-seasons.php
```

Typing `RESET` removes old issue-specific data and old demo identities, preserves products and non-demo readers, then recreates AUTUMN + WINTER.

---

# 38. LEGACY DEMO ASSETS / REFERENCES

Old visual assets and previous prototype references may still include:

```text
ART → CHELSEA
MUSIC → AFTERSHOCK
DESIGN → SOHO
FOOD → DOWNTOWN
NIGHT → LOWER EAST SIDE
CITY → BROOKLYN ROOFTOP
```

These are legacy visual/reference assets only. They are not active Autumn issue data.

---

# 39. CURRENT REAL-EVENT EXAMPLE

One recurring editorial concept:

> **HOW WOULD YOU ARRIVE?**

Example used:
- Aftershock
- rock/metal festival
- shared event article/Scene/Moment
- personalized festival Arrival

This demonstrates the core model especially well.

Future issues may use:
- concerts
- art fairs
- festivals
- design weeks
- gallery openings
- real cultural events

---

# 40. PRINT PIPELINE

Files:

```text
/lib/print.php
/print-render.php
/admin/print-preview.php
/admin/generate-print.php
```

Concept:

```text
same DB
├── digital renderer
└── print renderer → PDF
```

Print process:
1. run preflight
2. render print pages
3. use Chromium headless PDF export if available
4. generate:
   - interior PDF
   - cover PDF
5. store in exports directory

Current exports folder comes from config.

---

# 41. PRINT STATUS — IMPORTANT LIMITATION

The current print engine is **prototype infrastructure**, not final POD-ready production.

Current dimensions are preview defaults only.

Before real print:
- choose POD provider / exact product
- use exact trim size
- use exact bleed
- safe zones
- exact cover spread size
- spine calculation
- image DPI checks
- color workflow
- PDF preflight

Do not tell a future user that the current generated PDF is already guaranteed POD-ready.

---

# 42. IMAGE ASSET STRATEGY

For real production, use:

```text
MASTER
WEB
PRINT
```

Suggested shared asset structure:

```text
assets/uploads/issues/issue-002/shared/
```

Suggested reader generated assets:

```text
assets/uploads/generated/issue-002/user-0047/
```

Reader example:

```text
cover/
arrival-01/
arrival-02/
...
```

Recommended naming:

```text
arrival-01-master.jpg
arrival-01-web.webp
arrival-01-print.jpg
```

Do not use low-resolution web thumbnails in print renderer.

---

# 43. IMAGE QUALITY GUIDELINE

Until exact POD dimensions are fixed:

MASTER:
- best original
- ideally 3000–5000 px long edge

WEB:
- WebP/JPG
- roughly 1600–2200 px long edge

PRINT:
- high quality
- rough full-page target around 3300×4200 px portrait or better

This is a working guideline, not final printer spec.

---

# 44. SHARED ISSUE CREATION WORKFLOW WITH CHATGPT

A separate manual exists:

```text
THIS_YOU_SHARED_ISSUE_WORKFLOW.md
```

Core workflow:

```text
1. User explains issue vision
2. ChatGPT proposes concept
3. Create 32-page structure
4. Refine chapters
5. Write shared content
6. Create asset checklist
7. Create file naming plan
8. Convert content to CMS-ready page data
9. User/admin imports content
```

The shared issue is created once.

Personalization comes later.

---

# 45. PERSONALIZATION WORKFLOW WITH CHATGPT

A separate manual exists:

```text
THIS_YOU_PERSONALIZATION_WORKFLOW.md
```

Core input:

```text
reader profile
+ 4 photos
+ previous feedback
+ shared Moment
+ product candidates
```

Core output:

```text
Arrival direction
hero image
products
Why it works
Style notes
Stylist note
```

All outputs should end in existing DB/admin fields.

---

# 46. NEW ISSUE CREATION — SAFE PROCEDURE

For Magazine 03:

1. Admin → Issues → Create issue
2. engine creates 32-page skeleton
3. define issue concept
4. edit chapters
5. edit STORY pages
6. edit SCENE pages
7. edit shared MOMENT descriptions
8. choose layouts
9. create/assign theme CSS
10. upload shared assets
11. preview issue
12. publish shared issue
13. assign readers
14. generate personalized slots
15. human review
16. publish owner editions
17. print preview/export

Do not copy Issue 01 PHP files.

---

# 47. ADDING A NEW LAYOUT — SAFE PROCEDURE

If a new issue needs a new design:

Example:

```text
layouts/scene/scene-artwork-01.php
```

Then:
1. create new layout file
2. register it in `layout_registry()` in `/lib/issues.php`
3. select it in admin/page data
4. add CSS if needed
5. leave existing layout files untouched

This avoids retroactively altering published issues.

---

# 48. ADDING A DB FIELD — SAFE PROCEDURE

Do NOT manually edit the production table only.

Procedure:
1. add migration version `2`, `3`, etc. in `lib/migrations.php`
2. make migration idempotent
3. run `/admin/migrate.php` or setup migration
4. update code to tolerate old/new state if rollout requires
5. document the change here

Never reuse migration version 1 for new schema changes.

---

# 49. CURRENT GENERATION LIMITATIONS

Not implemented yet:
- real OpenAI text API generation
- real OpenAI image generation via engine
- direct ChatGPT import helper
- automatic real-product internet research/feed
- Stripe payment
- checkout success webhook
- transactional email
- robust magic-link expiration/auth
- order DB tables
- shipping addresses
- POD API/order submission
- true profile snapshot/versioning
- exact final POD specs
- source-type metadata for manual/API/human generation

These are future features, not bugs.

---

# 50. CURRENT CHECKOUT LIMITATION

The landing/onboarding UX is prepared for:

```text
$39 + shipping
```

But the code currently stops **before real checkout**.

Production flow still needs:

```text
Stripe Checkout
→ payment confirmation/webhook
→ create/confirm order
→ mark user_issue paid/pending
→ email magic link
→ generation queue
```

Do not accidentally generate expensive production work before payment.

---

# 51. CURRENT EMAIL LIMITATION

No real email provider is connected.

Planned email after payment:

```text
Your THIS YOU issue is underway.
Manage your profile →
```

Link should be a secure passwordless link.

Current private token can serve MVP, but production may benefit from:
- dedicated login/magic token
- expiration / rotation
- separate ownership token from edition token

---

# 52. CURRENT COMMERCE MODEL

Current UX:
- Current issue can be ordered
- Next issue can be pre-ordered
- both are shown separately

A single basket containing **both current + next in one checkout** is not implemented.

If desired later:
- add cart/order_items
- allow multiple issue IDs per order

Do not confuse “both are orderable” with “bundle both in one transaction”.

---

# 53. CURRENT PROFILE UPDATE BEHAVIOR

`profile.php` updates current profile data.

It does **not** intentionally regenerate approved pages.

Desired future improvement:

When profile `updated_at` is newer than generation snapshot:
show admin warning:

```text
PROFILE CHANGED AFTER GENERATION
[ REGENERATE PERSONALIZED PAGES ]
```

Do not silently replace approved content.

---

# 54. HUMAN REVIEW REQUIREMENT

Before a personalized paid edition is final:

```text
AI/manual draft
↓
human review
↓
edit if needed
↓
approve
↓
publish / print
```

A page has review status:
- not_generated
- generated
- needs_review
- approved
- rejected

`update_user_issue_ready_state()` checks whether all required non-shared pages are approved.

This should remain a hard quality gate.

---

# 55. PERSONALIZED COPY IS UNIQUE PER READER

This is intentional and important.

Shared:

```text
THE MOMENT
Chelsea Gallery Opening
6:40 PM
shared situation text
```

Jānis:

```text
YOUR ARRIVAL
personal title
personal image
WHY IT WORKS for Jānis
STYLE NOTES for Jānis
products for Jānis
```

Amara/Kenji:
different personal content.

Admin must make this distinction obvious.

---

# 56. IMPORTANT NEXT ADMIN UX IMPROVEMENT

Requested and not yet fully implemented:

On personalized page editor, clearly separate:

```text
SHARED MOMENT
----------------
Chelsea Gallery Opening
shared description

JĀNIS — PERSONALIZED LAYER
----------------
hero image
arrival line
Why it works
Style notes
products
```

This will become increasingly important as there are many readers per issue.

---

# 57. TESTING

Current project includes:

```text
/tests/render_layouts.php
/tests/static_checks.php
```

Before packaging a new version:
- PHP lint all PHP files
- render every layout
- check warnings/notices/fatal
- verify all 32 issue pages
- verify public mode
- verify owner mode
- verify reaction actions
- verify profile edit
- verify admin issue edit
- verify multi-issue isolation

On Laragon also test actual MySQL round trips because the original build environment did not have the same MySQL runtime.

---

# 58. UX DECISIONS ALREADY MADE

Do not casually regress these:

### Brand
`THIS YOU`

### Header reader name
first name only:
`JĀNIS`

not:
`JĀNIS KAUSS`

### Page position
show:
`PG 01 / 32`

### Product links
show explicit:
`SHOP ↗`

### Feedback
owner:
working

public/share:
visible but locked/read-only

### Profile
4 photos

### Navigation
reader can go back / Profile link exists

### Purchase
PRINT + DIGITAL only

### Price
$39 + shipping calculated at checkout

### Order timing
current issue + next issue both orderable

### Digital magazine
same editorial content as print, enhanced by interaction

### Shared editorial label
use `SCENE`, not `WORLD`

---

# 59. DEV HISTORY — IMPORTANT FIXES ALREADY MADE

## Legacy DB conflict
Fixed by using a dedicated engine DB and schema checks.

## Missing `product_reactions`
Earlier prototype issue; current engine uses unified `reactions`.

## Two-scroll digital layout
Rejected. Current direction is one normal browser page scroll.

## Hero image crop
Digital page should allow full/appropriate image, not aggressive `cover` crop.

## Moment text divider
Fixed CSS so divider does not cross the text.

## WHY IT WORKS / STYLE NOTES alignment
Fixed top margin mismatch.

## Latvian uppercase
Fixed `JĀNIS`.

## Public/owner confusion
Header now explicitly says:
- `PRIVATE EDITION`
- `PUBLIC PREVIEW`

## Product links unclear
Changed to explicit `SHOP ↗`.

## `WORLD`
Renamed conceptual layer to:
`SCENE`.

---

# 60. DEVELOPMENT PHILOSOPHY

This project should remain:

```text
simple
modular
manual-first
human-reviewed
automation-ready
```

Avoid premature complexity.

The first goal is not:
> automate every SKU and every magazine.

The first goal is:
> make excellent magazines people actually pay for, then automate repeated work.

---

# 61. WHAT MUST NEVER BE HARD-CODED TO ISSUE 01

Avoid:

```php
WHERE issue_id = 1
```

unless specifically seed/demo-only.

Everything runtime should derive from:
- issue context
- user_issue context
- current page context

Likewise do not assume:
- 32 forever
- Summer forever
- Jānis forever
- NY forever

Issue 01 is only the first seeded example.

---

# 62. CONTENT DATA MUST NOT LIVE IN LAYOUT PHP

Bad:

```php
<h1>ART AFTER DARK</h1>
<p>hard coded article...</p>
```

Good:

```php
<h1><?= h($page['title']) ?></h1>
<?= $page['body_html'] ?>
```

Layouts define presentation.

DB defines content.

Reader page records define personalization.

This separation is essential.

---

# 63. FUTURE AI PROVIDER ARCHITECTURE

Recommended direction:

```text
generation provider interface
├── demo
├── manual
└── openai
```

The provider should receive:

```text
reader context
+ history
+ Moment
+ product candidates
```

Return structured:

```text
personal_title
personal_subtitle
why_it_works
style_notes
stylist_note
product selections
image instructions / generated image
```

Then save into existing personalized tables.

Do not let OpenAI own database/rendering concerns.

---

# 64. FUTURE MANUAL ChatGPT IMPORT

Useful future admin feature:

```text
[ IMPORT MANUAL PERSONALIZATION ]
```

Could accept structured JSON pasted from ChatGPT:

```json
{
  "personal_title": "...",
  "personal_subtitle": "...",
  "why_it_works": "...",
  "style_notes": ["...", "..."],
  "stylist_note": "...",
  "products": [...]
}
```

Then:
- validate
- populate `user_issue_pages`
- populate `user_issue_products`
- mark `needs_review`

This would make the manual workflow extremely efficient.

---

# 65. FUTURE SHARED ISSUE IMPORT

Likewise useful future feature:

```text
[ IMPORT ISSUE PACKAGE ]
```

Input from editorial ChatGPT workflow:
- issue data
- chapters
- page map
- shared copy
- data_json
- image file references
- layout keys

This would let a new issue be created collaboratively in another chat, then inserted into the engine without manual page-by-page copy/paste.

This is a strong next tooling opportunity.

---

# 66. RECOMMENDED NEXT DEV MILESTONES

In sensible order:

## 1. Stronger shared vs personalized admin UI
Especially personal page editor.

## 2. Issue package import
Turn editorial MD/JSON into DB pages.

## 3. Manual personalization import
Turn ChatGPT structured output into reader pages.

## 4. Profile snapshot / dirty-state
Know if profile changed after generation.

## 5. Real Stripe checkout
Only after purchase flow is stable.

## 6. Transactional email / magic links

## 7. Real OpenAI provider
Text first, image second.

## 8. Exact POD print specification / export

## 9. Orders / fulfillment / POD integration

This order preserves the manual-first strategy.

---

# 67. DOCUMENTS THAT DEFINE THE PROJECT

Keep these together:

```text
personalized_magazine_CORE.md
personalized_magazine_EDITORIAL.md
personalized_magazine_SYSTEM_ARCHITECTURE.md

THIS_YOU_SHARED_ISSUE_WORKFLOW.md
THIS_YOU_PERSONALIZATION_WORKFLOW.md

THIS_YOU_DEV_CODEMAP_CURRENT.md
```

Their roles:

## CORE
What the product is and why.

## EDITORIAL
How the magazine is structured creatively.

## SYSTEM ARCHITECTURE
The ideal technical design.

## SHARED ISSUE WORKFLOW
How to create a new shared issue with ChatGPT.

## PERSONALIZATION WORKFLOW
How to create reader-specific pages manually/API/hybrid.

## DEV CODEMAP CURRENT
What the current code actually does today.

If ideal docs and actual implementation differ:
- this current CODEMAP describes the current code
- architecture docs describe intended direction

Do not confuse aspiration with implemented state.

---

# 68. ONE-PARAGRAPH HANDOFF TO A FUTURE DEVELOPER / CHATGPT

THIS YOU is a PHP 7.4 + MySQL multi-issue fashion/culture publishing engine. Shared editorial content (`issues`, `issue_chapters`, `issue_pages`) is stored once per magazine. Each reader has a persistent profile and photos, and receives a `user_issue` for a specific issue. Personalized Arrival/Style content and products live in `user_issue_pages` and `user_issue_products`, allowing the same STORY/SCENE/MOMENT to render differently for each reader. Digital public previews are read-only; private token editions allow look/product reactions and stylist comments that feed future issue generation. Admin can edit shared issues, assign readers, generate demo personalized drafts, human-review/approve pages, manually correct reader copy/products, and preview/export print. The current generator is a demo provider; Stripe, email, real OpenAI generation and final POD specs are not yet connected. Preserve the rule: **shared magazine + personalized arrivals**, use new layouts/themes instead of modifying old published issues, and use migrations for every schema change.

---

# 69. FAST RECOVERY CHECKLIST

If opening the project after months away:

1. Read this file.
2. Open `config/config.php`.
3. Confirm DB = `fashion_magazine_engine_v1`.
4. Run `setup.php` only if installation/schema needs it.
5. Open `/admin/`.
6. Check Issues.
7. Open Issue 01 public preview.
8. Open one reader owner token edition.
9. Test:
   - Contents
   - PG count
   - product SHOP links
   - look reaction
   - product reaction
   - stylist note
   - Profile
10. Check AUTUMN and WINTER are the only active issue records and are separately editable.
11. Run static/layout tests before changing shared code.
12. Never alter a published layout/theme blindly.

---

# 70. CURRENT NORTH STAR

A successful THIS YOU edition should feel like:

> **“This is a real magazine I would want to read anyway — but when the story enters a real moment, the editors have styled how I arrive.”**

Not:

> “AI pasted my face into a fashion image.”

Technically, every architectural choice should support that difference.


---

# V1.6 UPDATE — SCENE VARIANTS + STYLE EXPLORATION

## New core services

```text
/lib/scene-variants.php
/lib/style-exploration.php
```

SCENE pages now resolve object content centrally before issue-local/global layouts render. New data can use `data_json.objects[].variants.default/male/female`, while legacy `scene_assets` and simple object records remain supported. The same resolution path is used for digital and print.

Reader profiles now include optional `gender` (used as the current normalized SCENE presentation variant) and `style_exploration_mode` (`familiar | elevated | surprise`, default `elevated`). The exploration service distinguishes hard constraints from soft preferences and resolves optional STYLE-page `recommended_style_mode` / `style_exploration_override` values.

The product-first workflow is mode-aware before product selection and carries the resolved policy into the final hero brief. Admin pages show the effective styling mode and brand policy for QA.

## Migration 3

Run `/admin/migrate.php` after installing V1.6. It adds the two profile fields and `reader_profile_events`.

## Issue package format

The portable template is now `format_version: 3`. V2 remains readable/importable. V3 adds validated SCENE object variants. Current AUTUMN package manifest is marked V3, but legacy SCENE data remains valid until individual scenes are edited/saved into the explicit `objects` representation.

---

# V1.6.2 UPDATE — FRESH REGULAR-PRICE VERIFICATION

PRODUCT-FIRST price authority is now **fresh exact-page verification only**. Imported/stored price metadata is a candidate for UI convenience and is never authoritative during verification.

New core service:

```text
/lib/product-price-verification.php
```

Admin canonical workflow:

```text
GPT product JSON
→ imported as UNVERIFIED
→ VERIFY / RECHECK PRICE (fresh no-cache exact-page fetch)
→ regular/base price replaces candidate price
→ OPEN PRODUCT visually
→ human verifies product / colour / construction
→ VERIFIED BY HUMAN
→ HERO gate
```

Fresh verification state is stored directly on `user_issue_products` and tied to a fingerprint of brand + product name + selected colour + exact URL + verified regular price + currency. Editing any of those values invalidates the prior fresh check.

Migration 4 adds:

```text
price_verification_status
price_verified_at
price_verification_note
price_verification_meta
price_verification_fingerprint
```

The authoritative `price` contract across PRODUCT-FIRST, budget validation, digital magazine and print is:

> **regular/base non-discounted retail price only**

Sale/member/promo/coupon/campaign prices are ignored. A failed fresh fetch clears the old candidate price rather than falling back to cached/stored metadata.

---

# V1.7 ADDENDUM — PRODUCT VISUAL LOCK + HERO FIDELITY

The PRODUCT-FIRST chapter pipeline now has two additional hard quality gates:

```text
verified real products
→ approved Product Visual Locks
→ HERO
→ Product Fidelity Check
→ final human MOMENT/STYLE approval
```

New library:

```text
/lib/product-visual-lock.php
```

New admin routes:

```text
/admin/visual-lock.php
/admin/visual-lock-export.php
/admin/hero-fidelity.php
/admin/fidelity-check-export.php
/admin/fidelity-correction-export.php
```

Migration 6 stores per-product exact visual references/specification and per-style-page HERO fidelity state.

A product Visual Lock is invalidated by changes to exact product identity/variant (brand + product name + colour + exact URL), but not merely by a price refresh.

MOMENT/STYLE approval is blocked until chapter HERO fidelity is `pass` or `approved_override`.
