create-issflow 1.2.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -59,6 +59,37 @@ non-TDD before SCAFFOLD fires.
59
59
 
60
60
  -----
61
61
 
62
+ ## Sprint layer (the Scrum wrapper — optional)
63
+
64
+ Between the PLAN (the product backlog) and the PHASE (the build loop) sits an
65
+ optional **sprint layer** (`/sprint`): consecutive PLAN phases are grouped behind ONE
66
+ sprint goal and ship ONE deployable increment, wrapped in the full Scrum ceremony set.
67
+ The hierarchy is **PLAN (backlog) → SPRINT (committed slice) → PHASE (loop)**. Phases
68
+ run unchanged inside a sprint; the layer only adds cadence + inspect-and-adapt around them.
69
+
70
+ Scrum maps onto the kit with no new vocabulary to learn:
71
+
72
+ | Scrum | iStartSoftFlow |
73
+ |-------|----------------|
74
+ | Product Backlog | `docs/PLAN.md` (all phases) |
75
+ | Sprint Backlog | `docs/sprints/sprint-<n>.md` (committed phases + goal) |
76
+ | Scrum Master / Dev Team | the orchestrator (facilitates) / the subagent fleet (builds) |
77
+ | Sprint Planning | `/sprint plan` — slice the approved PLAN into a capacity-bounded sprint |
78
+ | Daily Scrum | `/sprint standup` — rebound to a **per-phase-close tick** (the AI loop has no calendar days) |
79
+ | Sprint Review / demo | `/sprint review` — demo the increment + run the boundary audits |
80
+ | Retrospective | `/sprint retro` — routed, concrete process actions |
81
+ | Increment · Burndown · Velocity | the deployable slice · remaining-points table · completed pts/sprint |
82
+
83
+ **AUTO-facilitated.** Sprint planning only SLICES an ALREADY-APPROVED plan (the
84
+ requirements gate happened at `/overview` plan approval), so the ceremonies are
85
+ AUTO-safe: `/sprint run` drives a whole sprint — or every remaining sprint — hands-off
86
+ (plan → loop `/phase` → standup tick → review → retro → close → next sprint), pausing
87
+ only at a methodology hard-stop. The PLAN-approval, commercial, and release gates are
88
+ SEPARATE and stay interactive (see Autonomy). The layer is opt-in: skip it and drive
89
+ phases directly off the PLAN exactly as before.
90
+
91
+ -----
92
+
62
93
  ## Project lifecycle (real-world delivery)
63
94
 
64
95
  The loop above is the BUILD engine. Around it runs a full client-delivery lifecycle
@@ -68,20 +99,31 @@ from idea to closeout:
68
99
  1. **Discover** — idea → requirements, captured by `/overview` (the double-grill).
69
100
  2. **PRD** — crystallised requirements in `docs/PRD.md` (or your BMAD/iSSM stories).
70
101
  3. **Stack & architecture** — decided in `/overview` design-research → `OVERVIEW.md`.
71
- 4. **Plan** — `/overview`'s `planner` → `docs/PLAN.md` (the vertical-slice phases).
72
- The plan exists before the proposal, because the proposal estimates *these* phases.
102
+ 4. **Plan** — `/overview`'s `planner` → `docs/PLAN.md` (the vertical-slice phases),
103
+ then the **PLAN-APPROVAL gate** (rule 13): build cannot start until a human signs the
104
+ plan off and the approval is recorded. The plan exists before the proposal, because
105
+ the proposal estimates *these* phases.
73
106
  5. **Proposal & estimate (OPTIONAL — depends on the job)** — for client / quoted
74
107
  work, `/propose` reads OVERVIEW + PLAN → `docs/PROPOSAL.md` + a rendered
75
108
  `docs/proposal.html`: scope, phase breakdown, effort + cost estimate, timeline,
76
109
  assumptions, with a **client sign-off gate** before build. Internal / personal
77
110
  projects skip straight from plan to build.
78
- 6. **Build** — the loop, one phase at a time (`/phase`, AUTO dev loop).
111
+ 6. **Build** — the loop, one phase at a time (`/phase`, AUTO dev loop). Each phase's
112
+ tests (unit + integration + e2e) are automated and MUST pass before the next phase.
113
+ Optionally wrap the phases in the **sprint layer** (`/sprint`): group them into
114
+ capacity-bounded sprints, each shipping one demoable increment with planning →
115
+ standups → review → retro. `/sprint run` drives this end-to-end (see Sprint layer).
79
116
  7. **Change mid-flight** — `/change-request`: impact analysis + re-estimate + a logged
80
117
  change order (`docs/CHANGES.md`) + sign-off, then `/replan`. Scope and cost never
81
118
  change silently.
82
- 8. **Deploy** — in the final phase.
83
- 9. **Closeout** `/synthesize` (final pass) → a project summary: what was built, key
84
- decisions, every change order, and the final cost vs the original estimate.
119
+ 8. **Release** — `/release`: full regression (functional/integration/e2e) → auto
120
+ audits (UI / QA / security / code) → smoke **manual UAT** (`/uat`, scenario sheet
121
+ + captured results) defect loop **sign-off** (`docs/SIGNOFF-…`) promote to
122
+ production (a human-signed hard-stop).
123
+ 9. **Go-live & support** — after-go-live hypercare; new scope routes through
124
+ `/change-request`. The project is live; the loop continues.
125
+ 10. **Closeout** — `/synthesize` → a project summary: what was built, key decisions,
126
+ every change order, and the final cost vs the original estimate.
85
127
 
86
128
  **Logging is continuous and total.** Every stage writes to a durable artifact:
87
129
  requirements (PRD / OVERVIEW), commercial (PROPOSAL / CHANGES), execution
@@ -89,9 +131,9 @@ requirements (PRD / OVERVIEW), commercial (PROPOSAL / CHANGES), execution
89
131
  Nothing important lives only in chat — it is on disk, so the project can always be
90
132
  reconstructed and summarised.
91
133
 
92
- **Commercial gates are always interactive** (both modes): the proposal sign-off and
93
- every change-order approval pause for the human. AUTO governs the *dev loop between*
94
- those gates, never the money decisions.
134
+ **Approval gates are always interactive** (both modes): the **PLAN-APPROVAL** gate
135
+ (rule 13), the proposal sign-off, and every change-order approval pause for the human.
136
+ AUTO governs the *dev loop between* those gates, never the plan or the money decisions.
95
137
 
96
138
  -----
97
139
 
@@ -105,6 +147,7 @@ front-end. They compose — BMAD plans, iStartSoftFlow builds — with no duplic
105
147
  | Analyst / PM / Architect / PO agents | → | `/overview` grill + `researcher` + `planner` |
106
148
  | PRD + Architecture | → | `docs/OVERVIEW.md` (+ `docs/PRD.md`) |
107
149
  | sharded epics / story files | → | `docs/PLAN.md` phases (1 story ≈ 1 phase) |
150
+ | epics / sprint grouping | → | the **sprint layer** (`/sprint`) — phases grouped behind one sprint goal |
108
151
  | SM "story with embedded context" | → | the phase **context package** (rationale + architecture + impl notes + qa focus + sharp acceptance) |
109
152
  | Dev → QA | → | `implementer` → `test-author` + the phase gates (TDD · UX · security · code-standards) |
110
153
 
@@ -149,7 +192,8 @@ can. Escalation is at most two hops.
149
192
  structural, not honor-system. Writes a MOCK suite + a REAL API suite.
150
193
  - **e2e-runner** — writes/runs functional browser E2E (your declared E2E runner,
151
194
  e.g. Playwright) BLIND. Reads only the acceptance spec + `docs/ENDPOINTS.md`,
152
- never the implementation.
195
+ never the implementation. Writes a trace to `docs/research/e2e-<phase-slug>.md`;
196
+ returns a terse summary.
153
197
  - **debugger** — debugs in an ISOLATED context. Writes a trace to
154
198
  `docs/research/debug-<slug>.md`; returns a summary.
155
199
  - **synthesizer** — compresses `docs/STATE.md` / `docs/ISSUES.md`, prunes
@@ -171,7 +215,12 @@ Named procedures, each with a canonical body in `.claude/commands/<name>.md`.
171
215
  a logged change order (`CHANGES.md`) + sign-off, then `replan`.
172
216
  - **phase [n]** — run one phase end-to-end with the circuit breaker. Chooses the
173
217
  TDD or non-TDD order at RESEARCH. CLOSE runs the regression guard + ENDPOINTS
174
- coverage gate.
218
+ coverage gate. When a sprint is active, CLOSE also fires a `/sprint standup` tick.
219
+ - **sprint [run|plan|standup|review|retro|close|status] [n]** — the Scrum wrapper
220
+ around the build loop: slice the approved PLAN into a capacity-bounded sprint, run
221
+ the ceremonies (planning → standups → review/demo + boundary audits → retro → close)
222
+ with burndown + velocity. `/sprint run` drives a whole sprint (or every remaining
223
+ one) AUTO end-to-end. Opt-in; phases run unchanged inside it.
175
224
  - **quick [change]** — small, obvious, non-phase change; no agent chain. Stays
176
225
  non-TDD. Runs the mock regression corpus after the change.
177
226
  - **ui-audit** — whole-product UI audit against the `ux-design` cookbook (a11y /
@@ -183,12 +232,20 @@ Named procedures, each with a canonical body in `.claude/commands/<name>.md`.
183
232
  - **security-audit** — whole-product SECURITY audit against the `security` cookbook
184
233
  (OWASP/ASVS/WSTG/secrets/SCA/SAST/supply-chain); scored report. On-demand; a
185
234
  precondition for the pre-deploy pentest. Distinct from the per-phase rule-11 gate.
235
+ - **release** — the pre-production pipeline (run after all build phases): full
236
+ regression → auto audits → smoke → UAT handoff → defect loop → sign-off → promote
237
+ to production → go-live support. The automated SDLC backbone.
238
+ - **uat** — manual UAT cycle: generate an all-case scenario sheet for human testers,
239
+ capture their results, drive the defect loop to 100% pass. Used inside `release`.
186
240
  - **unstuck** — deep re-research after a circuit breaker (auto-run once in AUTO on
187
241
  first stuck; human-triggered in GUIDED).
188
242
  - **synthesize** — compress STATE.md, dedup ISSUES.md, prune snapshots. Run
189
243
  before a context reset.
190
244
  - **replan** — revise `PLAN.md` (add/cut/split/merge/reorder pending phases) and
191
- reconcile the regression corpus in step.
245
+ reconcile the regression corpus in step. Reshaping unbuilt scope reverts the plan
246
+ to `PENDING` and re-runs the PLAN-APPROVAL gate (rule 13).
247
+ - **runbook** — capture an operational / incident scenario in `docs/RUNBOOK.md` so
248
+ prod-debug knowledge isn't re-derived under pressure.
192
249
  - **log-issue** — append an error to `ISSUES.md` with root cause + failed attempts.
193
250
  - **log-decision** — record an architectural change in `docs/DESIGN_LOG.md`.
194
251
  - **store-wisdom** — promote resolved issues + research to the shared KB.
@@ -205,13 +262,22 @@ inject context, the model performs them itself.
205
262
 
206
263
  At the start of every session, before any other work, surface:
207
264
  1. git state (branch, uncommitted count, last 3 commits).
208
- 2. `docs/STATE.md` — the current position. READ THIS FIRST.
265
+ 2. `docs/STATE.md` — the current position. READ THIS FIRST. If a sprint is active,
266
+ surface its goal + burndown from `docs/sprints/sprint-<n>.md`.
209
267
  3. open items in `docs/ISSUES.md`.
210
268
  4. `docs/research/INDEX.md` (research map) + infra/auth status.
211
269
  5. shared KB: pull latest + load `docs/.kb-snapshot.md` if `.claude/kb-config.json`
212
270
  exists.
213
271
  6. a one-line reminder of the hard rules below.
214
272
 
273
+ ### SPRINT-STANDUP (auto — at phase close inside an active sprint)
274
+
275
+ When a sprint is active, every `/phase` CLOSE fires one standup tick: append a
276
+ one-line entry to the active `docs/sprints/sprint-<n>.md` (done / next / blockers)
277
+ and update the burndown (remaining points + the sparkline). The "daily" Scrum is
278
+ rebound to per-phase-close because the AI dev loop has no calendar days — the phase
279
+ boundary is the real unit of progress. Blockers surface immediately. See `/sprint`.
280
+
215
281
  ### COMPRESS (before a context compaction)
216
282
 
217
283
  Snapshot the live position to `docs/.snapshots/` so a post-compact session can
@@ -223,7 +289,8 @@ The cheapest token is the one never loaded. The kit is built to minimise context
223
289
 
224
290
  - **Phase boundary is the primary reset.** `/synthesize -> /clear` ends every
225
291
  phase so the next one starts with a small, fresh context instead of carrying
226
- the whole history forward.
292
+ the whole history forward. The **sprint boundary** (`/sprint close`) is a second,
293
+ coarser reset — synthesize + clear there too before the next sprint plans.
227
294
  - **Lazy, not always-on.** This methodology + the skills load on demand; only the
228
295
  SessionStart hook output is paid every session, and it injects just the live
229
296
  STATE + *open* issues (resolved ones stay on disk for grep, not re-paid in tokens).
@@ -243,8 +310,8 @@ The cheapest token is the one never loaded. The kit is built to minimise context
243
310
  The kit runs in one of two modes, declared in `docs/OVERVIEW.md` (default: **AUTO**):
244
311
 
245
312
  **Planning always asks; development doesn't.** Asking is cheap and decisive while
246
- *planning* — so `/overview` (the double-grill) and plan approval stay interactive in
247
- both modes. AUTO governs only the **development loop** (implement → test → debug →
313
+ *planning* — so `/overview` (the double-grill) and the **PLAN-APPROVAL gate** (rule 13,
314
+ a recorded sign-off) stay interactive in both modes. AUTO governs only the **development loop** (implement → test → debug →
248
315
  close): there, interruptions are expensive, so it follows the plan instead of asking.
249
316
 
250
317
  - **AUTO (default) — during DEVELOPMENT, follow the plan, don't interrupt.** Once a
@@ -284,7 +351,7 @@ development run that follows the spec and logs every problem so it never recurs.
284
351
 
285
352
  -----
286
353
 
287
- ## Hard rules (1–12)
354
+ ## Hard rules (1–13)
288
355
 
289
356
  1. Before debugging ANY error: grep `docs/ISSUES.md` AND `docs/research/INDEX.md`.
290
357
  The SESSION-OPEN ritual surfaces ISSUES.md — there is no excuse to miss it.
@@ -338,6 +405,16 @@ development run that follows the spec and logs every problem so it never recurs.
338
405
  (the language's standard tool), names follow the language's OWN idiom, and the
339
406
  code conforms to the declared architecture (Feature-Based by default) — checked
340
407
  at CLOSE. Lint/format errors or idiom violations BLOCK the close. (`code-standards`.)
408
+ 13. **PLAN-APPROVAL gate.** No phase / sprint / build work starts until `docs/PLAN.md`
409
+ carries a human approval. `/overview` ends by presenting the plan and STOPPING for
410
+ sign-off; on approval the gate is RECORDED in three places — the PLAN.md
411
+ `> Approval:` header (`approved <date> v<n>`), `plan:` in `docs/STATE.md`, and a
412
+ `plan v<n> approved` line in `docs/HISTORY.md`. `/phase` and `/sprint` REFUSE to
413
+ start while that header still reads `PENDING`. Interactive in BOTH modes: AUTO
414
+ governs the dev loop that runs AFTER approval, never the approval itself — it is
415
+ the planning twin of the commercial sign-off gate (`/propose`). A `/replan` that
416
+ adds or reshapes UNBUILT scope reverts the affected plan to `PENDING` and
417
+ re-surfaces it for confirmation before those phases run.
341
418
 
342
419
  -----
343
420
 
@@ -381,18 +458,35 @@ the KB. The kit works normally without a KB.
381
458
  commands render into `docs/`.
382
459
  - `docs/CHANGES.md` — change-order log (append-only): each scope change with its
383
460
  impact, effort/cost delta, new total, and approval status. The commercial audit trail.
461
+ - `docs/UAT-<date>.md` — UAT scenario sheet (all cases) + captured tester results
462
+ (PASS/FAIL + notes). Drives the release defect loop.
463
+ - `docs/SIGNOFF-<date>.md` — release sign-off: scope delivered, test/audit/UAT
464
+ summary, known limitations, approver — the gate to promote to production.
465
+ - `docs/ui-audit-<date>.md` · `docs/qa-audit-<date>.md` · `docs/security-audit-<date>.md`
466
+ — scored whole-product audit reports (from the `*-audit` commands).
384
467
  - `docs/STATE.md` — current position. Small. Rewritten, not appended.
385
468
  - `docs/ISSUES.md` — error log. Deduped by synthesizer.
386
- - `docs/PLAN.md` — the phase plan. The last phase has the deploy task.
387
- - `docs/HISTORY.md` one line per finished phase.
469
+ - `docs/PLAN.md` — the phase plan (the product backlog). Carries an `> Approval:`
470
+ header `PENDING` until the rule-13 PLAN-APPROVAL gate stamps `approved <date> v<n>`;
471
+ no phase runs while it reads `PENDING`. The last phase has the deploy task. Phases may
472
+ carry a `[N pts]` estimate and be grouped under `## Sprint` headers when the sprint
473
+ layer is used.
474
+ - `docs/sprints/sprint-<n>.md` — one per sprint (sprint layer): goal, committed phases
475
+ + points, burndown, standup log, review (demo + audit scores), retro. Maintained by
476
+ `/sprint`.
477
+ - `docs/sprints/VELOCITY.md` — rolling velocity table (committed vs completed pts per
478
+ sprint). Drives the next sprint's capacity.
479
+ - `docs/HISTORY.md` — one line per finished phase (and per closed sprint).
388
480
  - `docs/DESIGN_LOG.md` — kit architectural rationale (§5.x decision log).
389
481
  - `docs/OVERVIEW.md` — project scope. Written after the double-grill in `overview`.
390
482
  E2E target.
391
483
  - `docs/ENDPOINTS.md` — API/service endpoint catalogue. Maintained by implementer
392
484
  each phase. Drives the CLOSE coverage gate.
485
+ - `docs/RUNBOOK.md` — operational / incident runbook (grep-able): per-scenario
486
+ symptoms, diagnosis, and recovery steps. Maintained by `/runbook`.
393
487
  - `docs/research/` — full research + debug files. `INDEX.md` is the searchable map.
394
488
  `design-<slug>.md` (design research), `<slug>.md` (impl research),
395
- `debug-<slug>.md` (debugger traces).
489
+ `debug-<slug>.md` (debugger traces), `e2e-<slug>.md` (e2e-runner traces).
396
490
  - `docs/.snapshots/` — pre-compact recovery markers (auto-pruned, gitignored).
397
491
  Holds no secrets.
398
492
  - your E2E stack — runner config + any ephemeral test services (e.g. `e2e/`,
@@ -421,7 +515,7 @@ the same everywhere — only the *wiring* differs.
421
515
 
422
516
  | Host | Entry file | Commands | Subagents | Lifecycle hooks | Shared KB |
423
517
  |------|-----------|----------|-----------|-----------------|-----------|
424
- | **Claude Code** (reference) | `AGENTS.md` + `.claude/` | `.claude/commands/` | native | SessionStart · PreCompact · SubagentStop (with context injection) | yes |
518
+ | **Claude Code** (reference) | `CLAUDE.md` (`@AGENTS.md`) + `.claude/` | `.claude/commands/` | native | SessionStart · PreToolUse (context-budget watchdog) · PreCompact · SubagentStop | yes |
425
519
  | **Codex CLI** | `AGENTS.md` (native) | `.claude/commands/` (read as prompts) | read as reference | model-run | yes |
426
520
  | **Cursor** | `.cursor/rules/` + `AGENTS.md` | `.cursor/commands/` | reads `.claude/agents/` | `.cursor/hooks.json` (sessionStart · subagentStop) | yes |
427
521
  | **Gemini CLI** | `GEMINI.md` + `AGENTS.md` | `.claude/commands/` (read as prompts) | read as reference | model-run | yes |
@@ -1,126 +1,112 @@
1
1
  <!doctype html>
2
2
  <!--
3
- Client-facing proposal template (rendered by /propose from docs/PROPOSAL.md).
4
- HOW TO USE (agent): copy this file to docs/proposal.html and replace every
5
- {{PLACEHOLDER}}. LOCALISE the labels + content to the project's declared
6
- language (e.g. natural Thai) keep technical terms in English where a Thai dev
7
- team would. Light + print-friendly on purpose (Ctrl/Cmd-P "Save as PDF").
8
- Repeat the <tr> in the phases table per phase; repeat <li> lists as needed.
9
-
10
- WHITE-LABEL: this template is brand-neutral. Fill {{COMPANY}} / {{LOGO}} with the
11
- ISSUING company's brand (whoever is sending the proposal) — NOT the kit's. {{LOGO}}
12
- is optional: replace with an <img src="…"> or a text wordmark, or delete it.
13
- Icons: none by design (no emoji) — keep it clean and typographic.
3
+ Client-facing proposal ONE A4 PAGE (rendered by /propose from docs/PROPOSAL.md).
4
+ HOW TO USE (agent): copy to docs/proposal.html, replace every {{PLACEHOLDER}}, and
5
+ keep it to a SINGLE A4 page be terse (≈3–6 phases, ≈4 assumptions). Localise the
6
+ CONTENT to the project language; the section labels are bilingual (TH / EN) already.
7
+ WHITE-LABEL: fill {{COMPANY}} / {{LOGO}} with the ISSUING company's brand (not the
8
+ kit's). {{LOGO}} optional: an <img src="…">, an SVG, or delete to keep the monogram.
9
+ Print: Ctrl/Cmd-P → A4 → "Save as PDF" (fits one page).
14
10
  -->
15
11
  <html lang="{{LANG}}">
16
12
  <head>
17
13
  <meta charset="utf-8" />
18
- <meta name="viewport" content="width=device-width, initial-scale=1" />
19
14
  <title>{{TITLE}} — Proposal {{VERSION}}</title>
20
15
  <style>
21
- :root{ --ink:#1a2230; --muted:#5b6878; --line:#e3e8f0; --accent:#5b4cf0;
22
- --accent2:#0ea5b7; --bg:#fff; --soft:#f6f8fc;
23
- --sans:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Noto Sans Thai",system-ui,sans-serif;
24
- --mono:ui-monospace,Menlo,Consolas,monospace; }
16
+ @page { size: A4; margin: 0 }
17
+ :root{
18
+ --ink:#162033; --muted:#5d6a7d; --line:#dbe3ee; --soft:#f6f8fb;
19
+ --violet:#635bff; --green:#15803d;
20
+ --sans:"Inter","Noto Sans Thai",-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;
21
+ --mono:ui-monospace,Menlo,Consolas,monospace;
22
+ }
25
23
  *{box-sizing:border-box}
26
- body{margin:0;background:var(--soft);color:var(--ink);font-family:var(--sans);line-height:1.6}
27
- .sheet{max-width:880px;margin:24px auto;background:var(--bg);border:1px solid var(--line);
28
- border-radius:14px;overflow:hidden}
29
- .head{padding:34px 40px;border-bottom:3px solid var(--accent);
30
- background:linear-gradient(120deg,#f3f1ff,#eafcff)}
31
- .brand-row{display:flex;align-items:center;gap:10px;margin-bottom:14px;font-size:1rem}
32
- .brand-row .logo{display:inline-flex;align-items:center}
33
- .head .ey{font:600 .72rem/1 var(--mono);letter-spacing:.18em;text-transform:uppercase;color:var(--accent)}
34
- .head h1{margin:.3em 0 .1em;font-size:1.9rem;letter-spacing:-.02em}
35
- .head .meta{color:var(--muted);font-size:.9rem}
36
- main{padding:14px 40px 40px}
37
- section{padding:20px 0;border-bottom:1px solid var(--line)}
38
- section:last-child{border:none}
39
- h2{font-size:1.05rem;margin:0 0 .5em;display:flex;align-items:center;gap:9px}
40
- h2::before{content:"";width:10px;height:10px;border-radius:3px;
41
- background:linear-gradient(120deg,var(--accent),var(--accent2))}
42
- table{width:100%;border-collapse:collapse;font-size:.92rem}
43
- th,td{text-align:left;padding:10px 12px;border-bottom:1px solid var(--line)}
44
- th{background:var(--soft);font-size:.74rem;text-transform:uppercase;letter-spacing:.04em;color:var(--muted)}
45
- td.num,th.num{text-align:right;font-family:var(--mono)}
46
- tfoot td{font-weight:700;border-top:2px solid var(--ink);border-bottom:none}
47
- ul{margin:.2em 0;padding-left:1.2em} li{margin:.2em 0;color:var(--muted)}
48
- .total{font-size:1.5rem;font-weight:800}
49
- .total small{font-size:.8rem;color:var(--muted);font-weight:500}
50
- .cols{display:flex;gap:32px;flex-wrap:wrap} .cols>div{flex:1;min-width:220px}
51
- .sign{display:flex;gap:40px;flex-wrap:wrap;margin-top:10px}
52
- .sign div{flex:1;min-width:220px} .line{border-bottom:1px solid var(--ink);height:34px;margin-top:18px}
53
- .muted{color:var(--muted)} .pill{display:inline-block;font:600 .7rem/1 var(--mono);
54
- padding:3px 8px;border-radius:6px;background:var(--soft);border:1px solid var(--line);color:var(--muted)}
55
- footer{padding:18px 40px;color:var(--muted);font-size:.8rem;background:var(--soft)}
56
- @media print{ body{background:#fff} .sheet{margin:0;border:none;border-radius:0;max-width:none}
57
- .head{background:#fff} section{break-inside:avoid} }
24
+ body{margin:0;background:#e9edf3;color:var(--ink);font-family:var(--sans);font-size:10.5px;line-height:1.45}
25
+ .sheet{width:210mm;min-height:297mm;margin:10mm auto;background:#fff;padding:15mm 16mm;display:flex;flex-direction:column;gap:11px}
26
+ .lbl{color:var(--muted);font-size:8.5px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;margin:0 0 3px}
27
+ .lbl em{font-style:normal;opacity:.6;font-weight:600}
28
+ h1{font-size:21px;margin:0;letter-spacing:-.3px;line-height:1.1}
29
+ .muted{color:var(--muted)} ul{margin:0;padding-left:15px} li{margin:1.5px 0}
30
+ hr{border:none;border-top:1px solid var(--line);margin:0}
31
+
32
+ /* header */
33
+ .head{display:flex;justify-content:space-between;align-items:flex-start;border-bottom:2px solid var(--ink);padding-bottom:11px}
34
+ .co{display:flex;align-items:center;gap:10px}
35
+ .logo{width:42px;height:42px;border-radius:9px;background:var(--ink);color:#fff;display:flex;align-items:center;justify-content:center;font-weight:800;font-size:13px;flex:0 0 auto;overflow:hidden}
36
+ .logo img{width:100%;height:100%;object-fit:contain}
37
+ .co .name{font-weight:800;font-size:15px;line-height:1.15}
38
+ .co .tag{color:var(--muted);font-size:9px}
39
+ .head .meta{text-align:right;font-size:9px;color:var(--muted)}
40
+ .head .meta .big{font:800 12px/1.2 var(--sans);letter-spacing:.12em;color:var(--violet)}
41
+ .pill{display:inline-block;border:1px solid var(--line);border-radius:999px;padding:2px 8px;font:800 8px/1 var(--mono);color:var(--muted);margin-top:4px}
42
+
43
+ .cols{display:flex;gap:18px} .cols>div{flex:1;min-width:0}
44
+ table{width:100%;border-collapse:collapse;font-size:10px}
45
+ th,td{text-align:left;padding:5px 7px;border-bottom:1px solid var(--line)}
46
+ th{background:var(--soft);font-size:8px;text-transform:uppercase;letter-spacing:.04em;color:var(--muted)}
47
+ td.n,th.n{text-align:right;font-family:var(--mono)}
48
+ tfoot td{font-weight:800;border-top:1.5px solid var(--ink);border-bottom:none}
49
+ .total{display:flex;align-items:baseline;justify-content:space-between;background:var(--soft);border-radius:9px;padding:9px 13px}
50
+ .total .amt{font-size:19px;font-weight:800} .total .amt small{font-size:9px;color:var(--muted);font-weight:600}
51
+
52
+ .sign{display:flex;gap:34px;margin-top:auto;padding-top:14px}
53
+ .sign>div{flex:1} .line{border-bottom:1px solid var(--ink);height:30px} .sign .lbl{margin-top:5px}
54
+ footer{border-top:1px solid var(--line);padding-top:8px;color:var(--muted);font-size:8.5px;display:flex;justify-content:space-between}
55
+ @media print{ body{background:#fff} .sheet{margin:0;min-height:auto;box-shadow:none} }
58
56
  </style>
59
57
  </head>
60
58
  <body>
61
59
  <div class="sheet">
60
+
62
61
  <div class="head">
63
- <div class="brand-row"><span class="logo">{{LOGO}}</span><strong>{{COMPANY}}</strong></div>
64
- <div class="ey">Proposal · {{VERSION}}</div>
62
+ <div class="co">
63
+ <span class="logo">{{LOGO}}</span>
64
+ <span><span class="name">{{COMPANY}}</span><br><span class="tag">{{COMPANY_TAGLINE}}</span></span>
65
+ </div>
66
+ <div class="meta">
67
+ <div class="big">PROPOSAL</div>
68
+ {{VERSION}} · {{DATE}}<br><span class="pill">{{STATUS}}</span>
69
+ </div>
70
+ </div>
71
+
72
+ <div>
73
+ <p class="lbl">ใบเสนอราคา <em>Prepared for</em></p>
65
74
  <h1>{{TITLE}}</h1>
66
- <div class="meta">{{L_PREPARED_FOR}} {{CLIENT}} · {{DATE}} · <span class="pill">{{STATUS}}</span></div>
75
+ <p class="muted" style="margin:3px 0 0">{{CLIENT}} {{SUMMARY}}</p>
67
76
  </div>
68
- <main>
69
- <section>
70
- <h2>{{L_OVERVIEW}}</h2>
71
- <p class="muted">{{SUMMARY}}</p>
72
- </section>
73
77
 
74
- <section>
75
- <h2>{{L_SCOPE}}</h2>
76
- <div class="cols">
77
- <div><strong>{{L_IN_SCOPE}}</strong><ul>{{SCOPE_IN_ITEMS}}</ul></div>
78
- <div><strong>{{L_OUT_SCOPE}}</strong><ul>{{SCOPE_OUT_ITEMS}}</ul></div>
79
- </div>
80
- </section>
78
+ <div class="cols">
79
+ <div><p class="lbl">ขอบเขตงาน <em>In scope</em></p><ul>{{SCOPE_IN_ITEMS}}</ul></div>
80
+ <div><p class="lbl">นอกขอบเขต <em>Out of scope</em></p><ul>{{SCOPE_OUT_ITEMS}}</ul></div>
81
+ </div>
82
+
83
+ <div>
84
+ <p class="lbl">เฟส &amp; ค่าใช้จ่าย <em>Phases &amp; cost</em></p>
85
+ <table>
86
+ <thead><tr><th>เฟส <em style="font-style:normal;opacity:.5">Phase</em></th><th>Complexity</th><th class="n">Effort</th><th class="n">Cost</th></tr></thead>
87
+ <tbody>{{PHASE_ROWS}}<!-- <tr><td>1. Auth</td><td>M</td><td class="n">2–3d</td><td class="n">฿16k–24k</td></tr> --></tbody>
88
+ <tfoot><tr><td colspan="2">รวม <em style="font-style:normal;opacity:.5">Total</em></td><td class="n">{{TOTAL_EFFORT}}</td><td class="n">{{TOTAL_COST}}</td></tr></tfoot>
89
+ </table>
90
+ </div>
81
91
 
82
- <section>
83
- <h2>{{L_PHASES}}</h2>
84
- <table>
85
- <thead><tr>
86
- <th>{{L_PHASE}}</th><th>{{L_COMPLEXITY}}</th>
87
- <th class="num">{{L_EFFORT}}</th><th class="num">{{L_COST}}</th>
88
- </tr></thead>
89
- <tbody>
90
- {{PHASE_ROWS}}
91
- <!-- e.g. <tr><td>1. Auth</td><td>M</td><td class="num">2–3d</td><td class="num">฿16,000–24,000</td></tr> -->
92
- </tbody>
93
- <tfoot><tr><td colspan="2">{{L_TOTAL}}</td><td class="num">{{TOTAL_EFFORT}}</td><td class="num">{{TOTAL_COST}}</td></tr></tfoot>
94
- </table>
95
- <p class="total" style="margin-top:14px">{{TOTAL_COST}} <small>{{CONTINGENCY_NOTE}}</small></p>
96
- </section>
92
+ <div class="total">
93
+ <span><span class="lbl" style="margin:0">ราคารวม <em>Total</em></span><br><span class="muted" style="font-size:9px">{{TIMELINE}}</span></span>
94
+ <span class="amt">{{TOTAL_COST}} <small>{{CONTINGENCY_NOTE}}</small></span>
95
+ </div>
97
96
 
98
- <section>
99
- <h2>{{L_TIMELINE}}</h2>
100
- <p class="muted">{{TIMELINE}}</p>
101
- </section>
97
+ <div class="cols">
98
+ <div><p class="lbl">สมมุติฐาน <em>Assumptions</em></p><ul>{{ASSUMPTION_ITEMS}}</ul></div>
99
+ <div><p class="lbl">ข้อยกเว้น <em>Exclusions</em></p><ul>{{EXCLUSION_ITEMS}}</ul></div>
100
+ </div>
102
101
 
103
- <section>
104
- <div class="cols">
105
- <div><h2>{{L_ASSUMPTIONS}}</h2><ul>{{ASSUMPTION_ITEMS}}</ul></div>
106
- <div><h2>{{L_EXCLUSIONS}}</h2><ul>{{EXCLUSION_ITEMS}}</ul></div>
107
- </div>
108
- </section>
102
+ <div><p class="lbl">เงื่อนไขการชำระเงิน <em>Payment</em></p><p class="muted" style="margin:0">{{PAYMENT_ITEMS}}</p></div>
109
103
 
110
- <section>
111
- <h2>{{L_PAYMENT}}</h2>
112
- <ul>{{PAYMENT_ITEMS}}</ul>
113
- </section>
104
+ <div class="sign">
105
+ <div><div class="line"></div><p class="lbl">ลงนามลูกค้า <em>Client sign-off</em></p></div>
106
+ <div><div class="line"></div><p class="lbl">วันที่ <em>Date</em></p></div>
107
+ </div>
114
108
 
115
- <section>
116
- <h2>{{L_SIGNOFF}}</h2>
117
- <div class="sign">
118
- <div><div class="line"></div><div class="muted">{{L_CLIENT_SIGN}}</div></div>
119
- <div><div class="line"></div><div class="muted">{{L_DATE}}</div></div>
120
- </div>
121
- </section>
122
- </main>
123
- <footer>{{FOOTER}}</footer>
109
+ <footer><span>{{COMPANY}} · {{FOOTER}}</span><span>{{VERSION}}</span></footer>
124
110
  </div>
125
111
  </body>
126
112
  </html>