create-issflow 1.9.0 → 1.9.1
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.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-issflow",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.1",
|
|
4
4
|
"description": "Scaffold the iStartSoftFlow AI-coding workflow into a project. Stack-agnostic, tool-agnostic (Claude Code, Codex, Cursor, Gemini, Aider), non-destructive.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"create-issflow": "bin/cli.js"
|
|
@@ -77,7 +77,8 @@ Show me CR-<n> (impact + price delta + new total — no rate). **STOP for approv
|
|
|
77
77
|
(commercial gate — always interactive).
|
|
78
78
|
- **Approved** -> set CR status `approved`; bump PROPOSAL.md to a new version (vN+1)
|
|
79
79
|
with the delta folded in (**totals only**); re-render `docs/proposal.html` from it
|
|
80
|
-
(same
|
|
80
|
+
(same `/propose` package rows + screen appendix — do not dump every PLAN phase
|
|
81
|
+
onto the sign table; same template + language; no contingency note / rate); then dispatch `/replan` to
|
|
81
82
|
apply the phase changes to PLAN.md (done phases stay frozen). Update STATE.md.
|
|
82
83
|
NOTE: `/replan` reverts PLAN.md to `> Approval: PENDING` and re-runs the
|
|
83
84
|
PLAN-APPROVAL gate (hard rule 13) — the commercial CR sign-off is SEPARATE from
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Turn approved requirements + tech stack into a client proposal — scope,
|
|
2
|
+
description: Turn approved requirements + tech stack into a client proposal — scope, packages, effort + cost estimate, timeline, assumptions, screen appendix, and a sign-off gate. Run after /overview, before building.
|
|
3
3
|
argument-hint: [optional: rate / budget / constraints · "dry-run" to preview]
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
Caveman ULTRA mode. You are the ORCHESTRATOR.
|
|
7
7
|
|
|
8
|
-
Purpose: produce `docs/PROPOSAL.md` — WHAT we build, in what
|
|
8
|
+
Purpose: produce `docs/PROPOSAL.md` — WHAT we build, in what packages, how long, how
|
|
9
9
|
much, and on what assumptions — for the client to approve BEFORE any build starts.
|
|
10
10
|
A proposal is a commercial gate: always interactive (both AUTO and GUIDED).
|
|
11
11
|
|
|
12
12
|
DRY-RUN: if `$ARGUMENTS` contains `dry-run`/`--dry-run`, do the full analysis but
|
|
13
|
-
EXECUTE NOTHING — print the ACTION PLAN (scope, phase breakdown,
|
|
14
|
-
and STOP. No PROPOSAL.md / proposal.html is written.
|
|
13
|
+
EXECUTE NOTHING — print the ACTION PLAN (scope, phase breakdown, package collapse,
|
|
14
|
+
rough estimate) and STOP. No PROPOSAL.md / proposal.html is written.
|
|
15
|
+
(METHODOLOGY → Dry-run.)
|
|
15
16
|
|
|
16
17
|
## PRE-FLIGHT
|
|
17
18
|
Read `docs/OVERVIEW.md` (scope, stack, success criteria) and `docs/PRD.md` if
|
|
@@ -28,12 +29,15 @@ List the deliverables (features / epics) from OVERVIEW / PRD. Mark each
|
|
|
28
29
|
**in-scope** or **out-of-scope** explicitly — naming out-of-scope items now is what
|
|
29
30
|
prevents silent scope creep (and grounds change-order re-pricing later).
|
|
30
31
|
|
|
31
|
-
## STEP 2 — PHASE BREAKDOWN
|
|
32
|
+
## STEP 2 — PHASE BREAKDOWN (internal)
|
|
32
33
|
Derive the vertical-slice phases (or read `docs/PLAN.md` if it exists). Size each:
|
|
33
34
|
- complexity: **S | M | L | XL**
|
|
34
35
|
- effort: an ideal-days RANGE (e.g. 2–3d), + story points if your team uses them
|
|
35
36
|
- risk / unknowns: what could move the estimate
|
|
36
37
|
|
|
38
|
+
Keep this sizing for the **chat math**. Do **not** dump every PLAN phase onto the
|
|
39
|
+
client table — collapse into packages in STEP 5.
|
|
40
|
+
|
|
37
41
|
## STEP 3 — ESTIMATE (ask rate · never invent a kit default)
|
|
38
42
|
Estimation config is **project-private**. The public kit ships **no** default rate
|
|
39
43
|
card and **no** sample salary/rate numbers — rates are confidential.
|
|
@@ -46,22 +50,35 @@ card and **no** sample salary/rate numbers — rates are confidential.
|
|
|
46
50
|
3. Optional: store the answered rate/contingency in a **project-local** file the
|
|
47
51
|
team keeps private (e.g. `docs/ESTIMATE.local.md` gitignored, or OVERVIEW fields
|
|
48
52
|
that never get published). Never commit personal rate/salary into a public kit
|
|
49
|
-
or template.
|
|
53
|
+
or template. If you create `docs/ESTIMATE.local.md`, add it to the project's
|
|
54
|
+
`.gitignore` when it is not already listed.
|
|
50
55
|
4. Configurable fields (ask or read — no invented kit defaults for money):
|
|
51
56
|
- **unit:** ideal-days | hours | story-points | both
|
|
52
57
|
- **rate card:** blended OR per-role (senior / mid / junior…)
|
|
53
58
|
- **currency:** as declared (ask if unset; THB is common for Thai clients)
|
|
54
59
|
- **contingency:** % buffer for unknowns (ask if unset)
|
|
55
|
-
- **payment
|
|
60
|
+
- **payment split:** e.g. 30/40/30 — **ASK once; do not guess** a ratio
|
|
56
61
|
- **language:** rendered doc language (default = project language)
|
|
57
62
|
|
|
63
|
+
Ask these **once each** if unset (commercial input — do not invent kit defaults):
|
|
64
|
+
|
|
65
|
+
- **Hours columns:** does the client table show estimated hours next to billed
|
|
66
|
+
hours? If yes → columns ประเมิน / คิดเงิน / ยอด. If no / unset → ชุดงาน + ยอด
|
|
67
|
+
only. Hours are effort, not a rate — still never print the rate.
|
|
68
|
+
- **Managed hosting / database:** is platform hosting+database **in** the quoted
|
|
69
|
+
total? If **not included**, write clearly on page 1 (out of scope + exclusions)
|
|
70
|
+
that the client pays the provider directly. A one-line exclusion is enough —
|
|
71
|
+
do **not** paste vendor SKU/price tables into the kit or invent list prices.
|
|
72
|
+
- **Bank:** include a bank block **only if the human provides** account details
|
|
73
|
+
in this project. No kit default. If none given, omit the column.
|
|
74
|
+
|
|
58
75
|
Compute cost per phase, then a **Total as a RANGE (low–high)** that already folds
|
|
59
76
|
in contingency. Show the math **in chat to the human** (rate × effort + contingency).
|
|
60
77
|
**Timeline:** phases in dependency order → calendar estimate (note parallelism).
|
|
61
78
|
|
|
62
79
|
### CLIENT-DOC RULE (hard — commercial privacy)
|
|
63
80
|
Client-facing artifacts (`docs/PROPOSAL.md` client sections, `docs/proposal.html`,
|
|
64
|
-
and any PDF/print) MUST show **totals and
|
|
81
|
+
and any PDF/print) MUST show **totals and package costs only**.
|
|
65
82
|
**Never** print: hourly/day rates, rate cards, contingency %, “incl. X% buffer”,
|
|
66
83
|
salary, or the estimate math. Contingency is already inside the numbers — do not
|
|
67
84
|
label it on the client page.
|
|
@@ -71,38 +88,83 @@ List every assumption the estimate rests on (infra provided, third-party/licence
|
|
|
71
88
|
costs excluded, content/design provided, etc.). These are the baseline that
|
|
72
89
|
change-orders re-price against.
|
|
73
90
|
|
|
91
|
+
If hosting/database is not in the quote, the exclusion **must** say the client
|
|
92
|
+
pays the provider directly.
|
|
93
|
+
|
|
74
94
|
## STEP 5 — WRITE + RENDER
|
|
95
|
+
Collapse the internal PLAN phases into **3–6 client packages / sprints** that a
|
|
96
|
+
non-engineer can read. PLAN may have any number of phases; the sign page does not
|
|
97
|
+
list them all.
|
|
98
|
+
|
|
99
|
+
Payment copy = short **software delivery events** tied to those packages, e.g.
|
|
100
|
+
deposit on sign-off then work starts · when the main package is usable · when
|
|
101
|
+
production is up within the scope on this quote. **Never** construction wording
|
|
102
|
+
(% structure, house handover, site prep / equipment staging).
|
|
103
|
+
|
|
75
104
|
1. Write `docs/PROPOSAL.md` — the SOURCE OF TRUTH (versioned v1 + date). This is
|
|
76
105
|
what `CHANGES.md` re-prices against. **Client-safe** body (no rate / no
|
|
77
106
|
contingency %):
|
|
78
107
|
```
|
|
79
108
|
# Proposal — <project> (v1, <date>)
|
|
80
109
|
## Scope — in-scope: … | out-of-scope: …
|
|
81
|
-
##
|
|
110
|
+
## Packages — table: package | cost
|
|
111
|
+
— or package | estimated | billed | cost (only if hours columns requested)
|
|
82
112
|
## Total — <low>–<high> ← totals only; no “incl. X% contingency”
|
|
83
113
|
## Timeline — <estimate>, dependency order
|
|
84
114
|
## Assumptions — …
|
|
85
|
-
## Exclusions — …
|
|
86
|
-
## Payment —
|
|
115
|
+
## Exclusions — … (hosting/database: client pays provider, if that was the answer)
|
|
116
|
+
## Payment — software delivery events + the asked split (if any)
|
|
117
|
+
## Screens — docs/proposal.html pages 2–N (or “none — no UI in scope”)
|
|
118
|
+
— not pixel-binding; sign page 1 only; page count must match the HTML
|
|
87
119
|
## Sign-off — approved by: ___ date: ___ version: v1
|
|
88
120
|
```
|
|
121
|
+
Point the Screens section at the **real** HTML page range after render
|
|
122
|
+
(page 1 = sign · remaining sheets = screen appendix). Keep PROPOSAL.md and
|
|
123
|
+
`docs/proposal.html` in sync.
|
|
89
124
|
If you keep an internal rate memo, put it in a **separate private** file (not
|
|
90
125
|
the client PROPOSAL.md / HTML). PROPOSAL.md itself stays client-safe so it can
|
|
91
126
|
be shared.
|
|
92
127
|
|
|
93
|
-
2. RENDER a client-facing `docs/proposal.html` from `.issflow/templates/proposal.html
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
128
|
+
2. RENDER a client-facing `docs/proposal.html` from `.issflow/templates/proposal.html`
|
|
129
|
+
(Claude Code also mirrors this under `.claude/templates/` — same file). Copy it,
|
|
130
|
+
replace every `{{PLACEHOLDER}}`, and fill the CONTENT in the declared language
|
|
131
|
+
(the section labels are already bilingual TH / EN).
|
|
132
|
+
|
|
133
|
+
**Page 1 = the only signable A4 sheet.** Be terse (≈ 3–6 package rows, ≈ 4
|
|
134
|
+
assumptions, short scope items). If page 1 overflows A4, **trim the sign-page
|
|
135
|
+
copy first** — never spill the sign block onto page 2. The screen appendix may
|
|
136
|
+
grow extra `.sheet` pages.
|
|
137
|
+
|
|
138
|
+
Fill `{{PACKAGE_TABLE}}` with the matching header:
|
|
139
|
+
- default: ชุดงาน / Packages + Cost
|
|
140
|
+
- if hours columns requested: ประเมิน / คิดเงิน / ยอด (and EN equivalents)
|
|
141
|
+
Fill `{{BANK_COL}}` only when the human gave bank details; otherwise leave
|
|
142
|
+
empty so payment takes the full width.
|
|
143
|
+
Fill `{{COMPANY}}` / `{{COMPANY_TAGLINE}}` / `{{LOGO}}` from the ISSUING
|
|
144
|
+
company's brand declared in OVERVIEW (or ask once) — white-label, never
|
|
145
|
+
hardcode the kit's name. Leave `{{TOTAL_NOTE}}` empty or a non-rate line
|
|
100
146
|
(e.g. currency / “ราคารวมทั้งโครงการ”) — **never** a contingency % or rate.
|
|
147
|
+
Set `{{PAGE_FOOTER}}` to the real page count (e.g. sign page 1 of N).
|
|
148
|
+
|
|
149
|
+
**Screen appendix (required when UI is in scope)** — same `docs/proposal.html`,
|
|
150
|
+
not a second signable file. After page 1's page-break, emit `.sheet.screens`
|
|
151
|
+
into `{{SCREEN_SHEETS}}`:
|
|
152
|
+
- Build frames from **PLAN + OVERVIEW** modules/capabilities (empty chrome is
|
|
153
|
+
fine). Do **not** wait for UX-PACK (that gate is after sign-off).
|
|
154
|
+
- Cover **every** in-scope module and capability — not a 4–8 frame sampler.
|
|
155
|
+
- Group sheets by package; module bar on each sheet; numbered short captions
|
|
156
|
+
under frames.
|
|
157
|
+
- Label: not pixel-binding. Sign on page 1 only. **No emoji as icons.**
|
|
158
|
+
- Use the template's desk/phone/sidebar/card/table CSS. Do not invent a
|
|
159
|
+
parallel stylesheet.
|
|
160
|
+
|
|
101
161
|
Print-ready (Ctrl/Cmd-P → A4 → Save as PDF). Keep PROPOSAL.md and proposal.html
|
|
102
162
|
in sync.
|
|
103
163
|
|
|
104
164
|
## STEP 6 — SIGN-OFF GATE
|
|
105
165
|
Show me the proposal. **STOP for approval** (commercial gate — always interactive).
|
|
166
|
+
Do **not** run `/design` or `/phase` yourself.
|
|
167
|
+
|
|
106
168
|
On approval: record the approved version + date in PROPOSAL.md and STATE.md, and
|
|
107
169
|
append a HISTORY line `proposal v<n> approved (<total>)`.
|
|
108
170
|
|
|
@@ -109,10 +109,12 @@ from idea to closeout:
|
|
|
109
109
|
the proposal estimates *these* phases.
|
|
110
110
|
5. **Proposal & estimate (OPTIONAL — depends on the job)** — for client / quoted
|
|
111
111
|
work, `/propose` reads OVERVIEW + PLAN → `docs/PROPOSAL.md` + a rendered
|
|
112
|
-
`docs/proposal.html`: scope,
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
112
|
+
`docs/proposal.html`: scope, **package** rows on the signable A4 page (not every
|
|
113
|
+
PLAN phase), effort + cost estimate, timeline, assumptions, and a screen
|
|
114
|
+
appendix in the **same HTML** after a page-break, with a **client sign-off gate**
|
|
115
|
+
before build. **Ask rate + contingency in chat** when missing — the kit stores
|
|
116
|
+
**no** default rate (rates are confidential). Client docs show **totals only**
|
|
117
|
+
(never rate or contingency %).
|
|
116
118
|
Internal / personal projects skip straight from plan to build (and may set
|
|
117
119
|
design/architecture gates to `n/a`).
|
|
118
120
|
6. **Design + architecture gates (rule 15 — after proposal, before build)** —
|
|
@@ -620,10 +622,12 @@ the KB. The kit works normally without a KB.
|
|
|
620
622
|
## File contract
|
|
621
623
|
|
|
622
624
|
- `docs/PRD.md` — crystallised product requirements (or your BMAD/iSSM stories).
|
|
623
|
-
- `docs/PROPOSAL.md` — scope +
|
|
624
|
-
+ sign-off. Versioned; client-safe commercial
|
|
625
|
+
- `docs/PROPOSAL.md` — scope + package rows + effort/cost totals + assumptions
|
|
626
|
+
+ screen-appendix page range + sign-off. Versioned; client-safe commercial
|
|
627
|
+
baseline (no rate / contingency %).
|
|
625
628
|
- `docs/proposal.html` — the client-facing proposal, rendered from PROPOSAL.md via
|
|
626
|
-
`.issflow/templates/proposal.html`, in the project language;
|
|
629
|
+
`.issflow/templates/proposal.html`, in the project language; page 1 is the
|
|
630
|
+
signable A4 sheet, then screen frames in the same file (print A4).
|
|
627
631
|
- `docs/UX-PACK.md` · `docs/ARCHITECTURE.md` — pre-build design/arch frames
|
|
628
632
|
(rule 15); templates under `.issflow/templates/`.
|
|
629
633
|
- `.issflow/templates/` — document templates (proposal.html, UX-PACK, ARCHITECTURE,
|
|
@@ -1,12 +1,51 @@
|
|
|
1
1
|
<!doctype html>
|
|
2
2
|
<!--
|
|
3
|
-
Client-facing proposal
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
3
|
+
Client-facing proposal (rendered by /propose from docs/PROPOSAL.md).
|
|
4
|
+
|
|
5
|
+
PAGE 1 = the only signable A4 sheet (packages 3–6 rows, short scope). Trim
|
|
6
|
+
sign-page copy before it overflows. Screen sheets after the first page-break
|
|
7
|
+
may grow extra A4 pages.
|
|
8
|
+
|
|
9
|
+
HOW TO USE (agent): copy to docs/proposal.html, replace every {{PLACEHOLDER}}.
|
|
10
|
+
Localise CONTENT to the project language; section labels are bilingual (TH / EN).
|
|
11
|
+
WHITE-LABEL: fill {{COMPANY}} / {{LOGO}} with the ISSUING company's brand (not
|
|
12
|
+
the kit's). {{LOGO}} optional: an <img src="…">, an SVG, or delete the monogram.
|
|
13
|
+
{{BANK_COL}}: omit unless the human gave bank details (no kit default).
|
|
14
|
+
{{PACKAGE_TABLE}}: default head = ชุดงาน / Packages + Cost; if hours columns
|
|
15
|
+
were requested = ประเมิน / คิดเงิน / ยอด. Never leave sample amounts in the file.
|
|
16
|
+
{{SCREEN_SHEETS}}: one .sheet.screens per appendix page; cover every in-scope
|
|
17
|
+
module from PLAN + OVERVIEW; numbered captions; no emoji icons; not pixel-binding.
|
|
18
|
+
{{PAGE_FOOTER}}: real page count (sign page 1 of N).
|
|
19
|
+
Print: Ctrl/Cmd-P → A4 → "Save as PDF".
|
|
20
|
+
|
|
21
|
+
Example screen frame (fill {{SCREEN_SHEETS}}; placeholders only — no domain copy):
|
|
22
|
+
<div class="sheet screens">
|
|
23
|
+
<div class="head">… {{COMPANY}} · ตัวอย่างจอ — ไม่ผูกพิกเซล / Screens — not pixel-binding</div>
|
|
24
|
+
<div class="modbar"><span class="here">{{MODULE}}</span></div>
|
|
25
|
+
<p class="note">{{SCREEN_NOTE}}</p>
|
|
26
|
+
<div class="figs">
|
|
27
|
+
<figure>
|
|
28
|
+
<div class="desk">
|
|
29
|
+
<div class="top"><span class="mark">{{MARK}}</span><span class="brand">{{APP_NAME}}</span></div>
|
|
30
|
+
<div class="body">
|
|
31
|
+
<div class="nav"><span class="on">{{NAV_ON}}</span></div>
|
|
32
|
+
<div class="main">
|
|
33
|
+
<div class="kpis"><div class="card">{{CARD}}</div></div>
|
|
34
|
+
<table class="ui">{{UI_ROWS}}</table>
|
|
35
|
+
</div>
|
|
36
|
+
</div>
|
|
37
|
+
</div>
|
|
38
|
+
<figcaption><b>{{FRAME_N}}. {{FRAME_TITLE}}</b> — {{FRAME_CAPTION}}</figcaption>
|
|
39
|
+
</figure>
|
|
40
|
+
<figure>
|
|
41
|
+
<div class="phone">
|
|
42
|
+
<div class="top"><span class="mark">{{MARK}}</span><span class="brand">{{APP_NAME}}</span></div>
|
|
43
|
+
<div class="screen">{{PHONE_BODY}}</div>
|
|
44
|
+
</div>
|
|
45
|
+
<figcaption><b>{{FRAME_N}}. {{FRAME_TITLE}}</b> — {{FRAME_CAPTION}}</figcaption>
|
|
46
|
+
</figure>
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
10
49
|
-->
|
|
11
50
|
<html lang="{{LANG}}">
|
|
12
51
|
<head>
|
|
@@ -16,23 +55,21 @@
|
|
|
16
55
|
@page { size: A4; margin: 0 }
|
|
17
56
|
:root{
|
|
18
57
|
--ink:#162033; --muted:#5d6a7d; --line:#dbe3ee; --soft:#f6f8fb;
|
|
19
|
-
--violet:#635bff; --green:#15803d;
|
|
58
|
+
--violet:#635bff; --green:#15803d; --bad:#b42318;
|
|
20
59
|
--sans:"Inter","Noto Sans Thai",-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;
|
|
21
60
|
--mono:ui-monospace,Menlo,Consolas,monospace;
|
|
22
61
|
}
|
|
23
62
|
*{box-sizing:border-box}
|
|
24
|
-
body{margin:0;background:#e9edf3;color:var(--ink);font-family:var(--sans);font-size:10.5px;line-height:1.
|
|
25
|
-
.sheet{width:210mm;min-height:297mm;margin:10mm auto;background:#fff;padding:15mm
|
|
26
|
-
.lbl{color:var(--muted);font-size:
|
|
63
|
+
body{margin:0;background:#e9edf3;color:var(--ink);font-family:var(--sans);font-size:10.5px;line-height:1.4}
|
|
64
|
+
.sheet{width:210mm;min-height:297mm;margin:10mm auto;background:#fff;padding:13mm 15mm;display:flex;flex-direction:column;gap:8px}
|
|
65
|
+
.lbl{color:var(--muted);font-size:8px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;margin:0 0 3px}
|
|
27
66
|
.lbl em{font-style:normal;opacity:.6;font-weight:600}
|
|
28
|
-
h1{font-size:
|
|
29
|
-
.muted{color:var(--muted)} ul{margin:0;padding-left:15px} li{margin:
|
|
30
|
-
hr{border:none;border-top:1px solid var(--line);margin:0}
|
|
67
|
+
h1{font-size:19px;margin:0;letter-spacing:-.3px;line-height:1.15}
|
|
68
|
+
.muted{color:var(--muted)} ul{margin:0;padding-left:15px} li{margin:1px 0}
|
|
31
69
|
|
|
32
|
-
|
|
33
|
-
.head{display:flex;justify-content:space-between;align-items:flex-start;border-bottom:2px solid var(--ink);padding-bottom:11px}
|
|
70
|
+
.head{display:flex;justify-content:space-between;align-items:flex-start;border-bottom:2px solid var(--ink);padding-bottom:9px}
|
|
34
71
|
.co{display:flex;align-items:center;gap:10px}
|
|
35
|
-
.logo{width:
|
|
72
|
+
.logo{width:40px;height:40px;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
73
|
.logo img{width:100%;height:100%;object-fit:contain}
|
|
37
74
|
.co .name{font-weight:800;font-size:15px;line-height:1.15}
|
|
38
75
|
.co .tag{color:var(--muted);font-size:9px}
|
|
@@ -40,19 +77,69 @@
|
|
|
40
77
|
.head .meta .big{font:800 12px/1.2 var(--sans);letter-spacing:.12em;color:var(--violet)}
|
|
41
78
|
.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
79
|
|
|
43
|
-
.cols{display:flex;gap:
|
|
44
|
-
table{width:100%;border-collapse:collapse;font-size:10px}
|
|
45
|
-
th
|
|
46
|
-
th{background:var(--soft);font-size:8px;text-transform:uppercase;letter-spacing:.04em;color:var(--muted)}
|
|
47
|
-
td.n
|
|
48
|
-
tfoot td{font-weight:800;border-top:1.5px solid var(--ink);border-bottom:none}
|
|
49
|
-
.total{display:flex;align-items:
|
|
50
|
-
.total .amt{font-size:
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
.sign
|
|
54
|
-
|
|
55
|
-
|
|
80
|
+
.cols{display:flex;gap:16px} .cols>div{flex:1;min-width:0}
|
|
81
|
+
table.quote{width:100%;border-collapse:collapse;font-size:10px}
|
|
82
|
+
.quote th,.quote td{text-align:left;padding:4px 6px;border-bottom:1px solid var(--line)}
|
|
83
|
+
.quote th{background:var(--soft);font-size:8px;text-transform:uppercase;letter-spacing:.04em;color:var(--muted)}
|
|
84
|
+
.quote td.n,.quote th.n{text-align:right;font-family:var(--mono)}
|
|
85
|
+
.quote tfoot td{font-weight:800;border-top:1.5px solid var(--ink);border-bottom:none}
|
|
86
|
+
.total{display:flex;align-items:flex-end;justify-content:space-between;background:var(--soft);border-radius:9px;padding:8px 12px;gap:12px}
|
|
87
|
+
.total .amt{font-size:18px;font-weight:800;text-align:right}
|
|
88
|
+
.total .amt small{display:block;font-size:9px;color:var(--muted);font-weight:600}
|
|
89
|
+
|
|
90
|
+
.sign{display:flex;gap:34px;margin-top:auto;padding-top:10px}
|
|
91
|
+
.sign>div{flex:1} .line{border-bottom:1px solid var(--ink);height:26px} .sign .lbl{margin-top:4px}
|
|
92
|
+
footer{border-top:1px solid var(--line);padding-top:7px;color:var(--muted);font-size:8px;display:flex;justify-content:space-between}
|
|
93
|
+
|
|
94
|
+
/* screen appendix — empty chrome; fill from PLAN + OVERVIEW */
|
|
95
|
+
.sheet.screens{padding:10mm 12mm;gap:6px}
|
|
96
|
+
.screens .head{padding-bottom:6px}
|
|
97
|
+
.screens .note{font-size:9px;margin:0;color:var(--muted)}
|
|
98
|
+
.modbar{display:flex;flex-wrap:wrap;gap:4px}
|
|
99
|
+
.modbar span{border:1px solid var(--line);border-radius:999px;padding:2px 7px;font-size:8px;font-weight:700;color:var(--muted)}
|
|
100
|
+
.modbar .here{background:#ecebff;border-color:#d4d1ff;color:var(--violet)}
|
|
101
|
+
.figs{display:grid;grid-template-columns:1fr 1fr;gap:8px 10px;flex:1}
|
|
102
|
+
figure{margin:0;display:flex;flex-direction:column;min-width:0}
|
|
103
|
+
figcaption{margin-top:3px;font-size:8px;color:var(--muted);line-height:1.35}
|
|
104
|
+
figcaption b{color:var(--ink);font-weight:700}
|
|
105
|
+
.desk,.phone{background:#fff;border:1px solid var(--line);border-radius:10px;overflow:hidden;flex:1;min-height:0}
|
|
106
|
+
.top{display:flex;align-items:center;gap:6px;padding:5px 8px;border-bottom:1px solid var(--line);background:var(--soft)}
|
|
107
|
+
.mark{width:16px;height:16px;border-radius:4px;background:var(--violet);color:#fff;font-size:8px;font-weight:800;display:flex;align-items:center;justify-content:center}
|
|
108
|
+
.brand{font-weight:800;font-size:10px;color:var(--violet)}
|
|
109
|
+
.sub{font-size:8px;color:var(--muted)}
|
|
110
|
+
.body{display:flex;min-height:148px}
|
|
111
|
+
.nav{width:64px;border-right:1px solid var(--line);padding:5px;font-size:8px}
|
|
112
|
+
.nav span{display:block;padding:2px 4px;border-radius:4px;margin-bottom:1px;color:#334155}
|
|
113
|
+
.nav .on{background:#ecebff;color:var(--violet);font-weight:700}
|
|
114
|
+
.nav .tail{margin-top:6px;padding-top:4px;border-top:1px solid var(--line)}
|
|
115
|
+
.main{flex:1;padding:6px;min-width:0}
|
|
116
|
+
.kpis{display:grid;grid-template-columns:1fr 1fr 1fr;gap:4px}
|
|
117
|
+
.kpis.two{grid-template-columns:1fr 1fr}
|
|
118
|
+
.card{border:1px solid var(--line);border-radius:6px;padding:4px 5px;font-size:8px;background:#fff}
|
|
119
|
+
.card .n{font-size:12px;font-weight:800}
|
|
120
|
+
.red{border-color:#f0c4c0;background:#fff7f6}
|
|
121
|
+
.red .n{color:var(--bad)}
|
|
122
|
+
.ok{border-color:#b7d4c2;background:#f4faf6}
|
|
123
|
+
.ok .n{color:var(--green)}
|
|
124
|
+
.warn{border-color:#ead8a4;background:#fffbeb}
|
|
125
|
+
.ui{width:100%;border-collapse:collapse;font-size:8px;margin-top:4px}
|
|
126
|
+
.ui th,.ui td{text-align:left;padding:2px 3px;border-bottom:1px solid var(--line)}
|
|
127
|
+
.ui th{color:var(--muted);font-weight:600}
|
|
128
|
+
.btn{display:inline-block;background:var(--violet);color:#fff;border-radius:4px;padding:3px 7px;font-size:8px;font-weight:700;margin-top:5px}
|
|
129
|
+
.btn.ghost{background:#fff;color:var(--violet);border:1px solid var(--violet)}
|
|
130
|
+
.field{display:flex;justify-content:space-between;gap:8px;border-bottom:1px dashed var(--line);padding:3px 0;font-size:8px}
|
|
131
|
+
.crumbs{font-size:8px;color:var(--muted);margin-bottom:3px}
|
|
132
|
+
.login{padding:12px;min-height:148px;display:flex;flex-direction:column;justify-content:center;align-items:flex-start;gap:6px}
|
|
133
|
+
.login h3{margin:0;font-size:12px}
|
|
134
|
+
.phone{max-width:168px;margin:0 auto;width:100%}
|
|
135
|
+
.screen{padding:7px}
|
|
136
|
+
.tiny{font-size:7px;color:var(--muted)}
|
|
137
|
+
|
|
138
|
+
@media print{
|
|
139
|
+
body{background:#fff}
|
|
140
|
+
.sheet{margin:0;min-height:297mm;page-break-after:always;box-shadow:none}
|
|
141
|
+
.sheet:last-child{page-break-after:auto}
|
|
142
|
+
}
|
|
56
143
|
</style>
|
|
57
144
|
</head>
|
|
58
145
|
<body>
|
|
@@ -81,12 +168,8 @@
|
|
|
81
168
|
</div>
|
|
82
169
|
|
|
83
170
|
<div>
|
|
84
|
-
<p class="lbl"
|
|
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>
|
|
171
|
+
<p class="lbl">ชุดงาน & ค่าใช้จ่าย <em>Packages & cost</em></p>
|
|
172
|
+
<table class="quote">{{PACKAGE_TABLE}}</table>
|
|
90
173
|
</div>
|
|
91
174
|
|
|
92
175
|
<div class="total">
|
|
@@ -100,14 +183,22 @@
|
|
|
100
183
|
<div><p class="lbl">ข้อยกเว้น <em>Exclusions</em></p><ul>{{EXCLUSION_ITEMS}}</ul></div>
|
|
101
184
|
</div>
|
|
102
185
|
|
|
103
|
-
<div
|
|
186
|
+
<div class="cols">
|
|
187
|
+
<div>
|
|
188
|
+
<p class="lbl">เงื่อนไขการชำระเงิน <em>Payment</em></p>
|
|
189
|
+
<ul>{{PAYMENT_ITEMS}}</ul>
|
|
190
|
+
</div>
|
|
191
|
+
{{BANK_COL}}
|
|
192
|
+
</div>
|
|
104
193
|
|
|
105
194
|
<div class="sign">
|
|
106
195
|
<div><div class="line"></div><p class="lbl">ลงนามลูกค้า <em>Client sign-off</em></p></div>
|
|
107
196
|
<div><div class="line"></div><p class="lbl">วันที่ <em>Date</em></p></div>
|
|
108
197
|
</div>
|
|
109
198
|
|
|
110
|
-
<footer><span>{{COMPANY}} · {{
|
|
199
|
+
<footer><span>{{COMPANY}} · {{PAGE_FOOTER}}</span><span>{{VERSION}}</span></footer>
|
|
111
200
|
</div>
|
|
201
|
+
|
|
202
|
+
{{SCREEN_SHEETS}}
|
|
112
203
|
</body>
|
|
113
204
|
</html>
|