-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathopp-flow.html
More file actions
348 lines (318 loc) · 25.2 KB
/
Copy pathopp-flow.html
File metadata and controls
348 lines (318 loc) · 25.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
<!doctype html>
<html lang="th">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Opp · Flow การพูด · UP Wellness</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,500;0,600;0,700;1,400;1,500&family=Manrope:wght@400;500;600;700;800&family=Sarabun:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;700&display=swap" rel="stylesheet" />
<script>
tailwind.config = {
theme: { extend: {
fontFamily: {
display: ['"Cormorant Garamond"', 'Georgia', 'serif'],
head: ['"Manrope"', 'Helvetica Neue', 'sans-serif'],
thai: ['"Sarabun"', 'system-ui', 'sans-serif'],
mono: ['"JetBrains Mono"', 'monospace'],
},
colors: {
rose: { DEFAULT: '#8C4C4C', deep: '#6B3535', soft: '#B57878', mist: '#F4ECEC' },
green: { DEFAULT: '#396755', deep: '#244438', soft: '#6AAF91', mist: '#D6EDE4' },
cream: { DEFAULT: '#F5F0EB', deep: '#EDE6DF' },
ink: { DEFAULT: '#1F1E1B', 80:'#3D3840', 60: '#5C5A56', 40: '#8B8884', 20: '#C9C6C0', 10: '#E5E2DD' },
gold: '#B8965A',
amber: '#C47A2A',
warm: '#FDFCFB',
},
} }
};
</script>
<style>
* { -webkit-font-smoothing: antialiased; }
body { font-family: 'Sarabun', sans-serif; background: #2A2724; }
.font-display { font-family: 'Cormorant Garamond', serif; }
.font-head { font-family: 'Manrope', sans-serif; }
.font-mono { font-family: 'JetBrains Mono', monospace; }
#flow-canvas {
background:
radial-gradient(ellipse 60% 40% at 20% 0%, rgba(140,76,76,0.07), transparent 60%),
radial-gradient(ellipse 50% 40% at 90% 30%, rgba(196,122,42,0.07), transparent 60%),
radial-gradient(ellipse 60% 40% at 10% 80%, rgba(57,103,85,0.07), transparent 60%),
#FDFCFB;
}
/* spine (vertical view only) */
.spine { position: relative; }
.spine::before {
content: ''; position: absolute; left: 27px; top: 30px; bottom: 30px; width: 2px;
background: linear-gradient(180deg, #6AAF91 0%, #6AAF91 38%, #C47A2A 42%, #C47A2A 72%, #B57878 75%, #B57878 86%, #B8965A 89%, #B8965A 100%);
opacity: 0.4;
}
@media (min-width: 768px) { .spine::before { left: 35px; } }
.node {
position: absolute; left: 16px; top: 8px;
width: 24px; height: 24px; border-radius: 100px;
display: flex; align-items: center; justify-content: center;
font-family: 'JetBrains Mono', monospace; font-size: 10px; font-weight: 700; color: white;
z-index: 2; box-shadow: 0 2px 8px rgba(0,0,0,0.15);
}
@media (min-width: 768px) { .node { left: 24px; } }
.card-jin { border-left: 4px solid #396755; }
.card-ton { border-left: 4px solid #C47A2A; }
.card-tao { border-left: 4px dashed #B57878; }
.card-close { border-left: 4px solid #B8965A; }
.zone-say { background: rgba(31,30,27,0.03); }
.zone-get { background: linear-gradient(135deg, rgba(184,150,90,0.10), rgba(184,150,90,0.03)); border: 1px solid rgba(184,150,90,0.25); }
.dur-track { height:5px; background:rgba(31,30,27,0.07); border-radius:100px; overflow:hidden; }
.dur-fill { height:100%; border-radius:100px; }
.seg-header { position: relative; z-index: 2; }
.btn { font-family:'JetBrains Mono',monospace; font-size:12px; font-weight:700; letter-spacing:.05em; cursor:pointer; transition:all .2s; display:inline-flex; align-items:center; gap:8px; border-radius:100px; }
.btn-save { background:#1F1E1B; color:#F5F0EB; border:none; padding:12px 22px; box-shadow:0 10px 30px rgba(0,0,0,.3); }
.btn-save:hover { background:#8C4C4C; transform:translateY(-2px); }
.btn-toggle { background:rgba(245,240,235,.92); color:#1F1E1B; border:1px solid rgba(31,30,27,.1); padding:12px 18px; box-shadow:0 10px 30px rgba(0,0,0,.25); }
.btn-toggle:hover { background:#fff; }
.controls { position:fixed; top:20px; right:20px; z-index:50; display:flex; gap:10px; }
.toast {
position: fixed; bottom: 24px; left: 50%; transform: translate(-50%, 100px);
background: rgba(31,30,27,0.92); color: #F5F0EB; padding: 12px 24px; border-radius: 100px;
font-family: 'JetBrains Mono', monospace; font-size: 13px; transition: transform 0.3s; z-index: 60;
}
.toast.show { transform: translate(-50%, 0); }
/* ===== Compact / A3 overview mode ===== */
body.compact #flow-canvas { max-width: 1600px; }
body.compact .vert-only { display: none !important; }
body.compact .spine { padding-left: 0 !important; }
body.compact .spine::before { display: none; }
body.compact .node { display: none; }
body.compact .spine { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
@media (min-width:1024px){ body.compact .spine { grid-template-columns: repeat(4, 1fr); } }
body.compact .step-card { font-size: 0.92em; }
body.compact .compact-hide { display: none; }
@media print {
@page { size: A3 landscape; margin: 8mm; }
body { background: #fff; }
.skip-export { display: none !important; }
.vert-only { display: none !important; }
.spine { display: grid !important; grid-template-columns: repeat(4, 1fr) !important; gap: 6px !important; padding-left:0 !important; }
.spine::before, .node { display: none !important; }
.compact-hide { display: none !important; }
#flow-canvas { max-width: none !important; box-shadow:none; }
}
</style>
</head>
<body class="py-8 px-4">
<div class="controls skip-export">
<button class="btn btn-toggle" id="toggleBtn">🖨 โหมด A3 แนวนอน</button>
<button class="btn btn-save" id="saveBtn">⬇ SAVE PNG</button>
</div>
<div id="flow-canvas" class="mx-auto max-w-5xl rounded-3xl px-6 md:px-12 py-12 md:py-16">
<!-- TITLE -->
<div class="text-center mb-10">
<div class="font-mono text-[11px] tracking-[0.3em] text-rose-deep uppercase font-bold">UP Wellness · Opp · Flow การพูด</div>
<h1 class="mt-3 font-display text-[44px] md:text-[64px] font-medium text-ink leading-none">
เส้นทางการพูด · <em class="italic text-rose">ทีละก้าว.</em>
</h1>
<p class="mt-4 font-thai text-[15px] text-ink-60 max-w-2xl mx-auto">
จิ้น 45 → ต้น 40 → พี่เต๋า (รอ interview) → ปิดร่วม · เห็นชัดว่าแต่ละก้าว
<span class="text-green-deep font-bold">พูดอะไร</span> ·
<span class="text-ink-80 font-bold">รายละเอียด</span> ·
<span class="text-amber font-bold">คนฟังได้อะไร</span> · พร้อม
<span class="text-rose font-bold">slide</span> + <span class="text-ink-60 font-bold">วิธีพูด</span> + <span class="text-green font-bold">เวลา</span>
</p>
<div class="mt-6 flex flex-wrap items-center justify-center gap-4 font-mono text-[10px] uppercase tracking-wide">
<span class="flex items-center gap-1.5"><span class="h-3 w-3 rounded bg-green"></span> จิ้น 45m</span>
<span class="flex items-center gap-1.5"><span class="h-3 w-3 rounded bg-amber"></span> ต้น 40m</span>
<span class="flex items-center gap-1.5"><span class="h-3 w-3 rounded border-2 border-dashed border-rose-soft"></span> พี่เต๋า 10-15m</span>
<span class="flex items-center gap-1.5"><span class="h-3 w-3 rounded bg-gold"></span> ปิดร่วม 5m</span>
</div>
</div>
<div class="vert-only flex items-center gap-3 mb-8 justify-center">
<span class="font-mono text-[10px] uppercase tracking-[0.2em] text-ink-40 font-bold px-4 py-1.5 rounded-full bg-ink/5">▼ เริ่ม · 0:00</span>
</div>
<!-- JIN -->
<div class="seg-header mb-5">
<div class="rounded-2xl bg-green p-5 text-cream shadow-lg">
<div class="flex items-center justify-between flex-wrap gap-2">
<div>
<div class="font-mono text-[10px] uppercase tracking-[0.2em] text-cream/70 font-bold">PART A · 45 นาที</div>
<div class="font-display text-[30px] font-medium leading-none mt-1">🌿 จิ้น · โอกาสของการมีสุขภาพดี</div>
</div>
<div class="font-display text-[14px] italic text-cream/80 text-right max-w-[210px]">กังวล → ตื่นรู้ → หวัง → พร้อมเริ่ม</div>
</div>
</div>
</div>
<div class="spine pl-14 md:pl-20 space-y-4" id="jin-steps"></div>
<div class="vert-only my-7 flex items-center justify-center gap-3">
<span class="h-px w-12 bg-ink-20"></span>
<span class="font-mono text-[10px] uppercase tracking-[0.2em] text-amber font-bold px-4 py-1.5 rounded-full bg-amber/10">↓ ส่งไม้ต่อ · "พื้นฐานพร้อม · ต่อด้วยอนาคต"</span>
<span class="h-px w-12 bg-ink-20"></span>
</div>
<!-- TON -->
<div class="seg-header mb-5">
<div class="rounded-2xl bg-amber p-5 text-cream shadow-lg">
<div class="flex items-center justify-between flex-wrap gap-2">
<div>
<div class="font-mono text-[10px] uppercase tracking-[0.2em] text-cream/80 font-bold">PART B · 40 นาที</div>
<div class="font-display text-[30px] font-medium leading-none mt-1">💼 ต้น · โอกาสของธุรกิจสุขภาพ</div>
</div>
<div class="font-display text-[14px] italic text-cream/90 text-right max-w-[210px]">ตื่นรู้ → เห็นภาพ → เชื่อข้อมูล → ลังเลแบบมีเหตุผล</div>
</div>
</div>
</div>
<div class="spine pl-14 md:pl-20 space-y-4" id="ton-steps"></div>
<div class="vert-only my-7 flex items-center justify-center gap-3">
<span class="h-px w-12 bg-ink-20"></span>
<span class="font-mono text-[10px] uppercase tracking-[0.2em] text-rose font-bold px-4 py-1.5 rounded-full bg-rose/10">↓ ส่งไม้ต่อ · "ตัวเลขคือกระดาษ · ชีวิตจริงเป็นยังไง"</span>
<span class="h-px w-12 bg-ink-20"></span>
</div>
<!-- PI TAO -->
<div class="seg-header mb-5">
<div class="rounded-2xl border-2 border-dashed border-rose-soft bg-rose-mist/40 p-5 text-ink shadow-lg">
<div class="flex items-center justify-between flex-wrap gap-2">
<div>
<div class="font-mono text-[10px] uppercase tracking-[0.2em] text-rose-deep font-bold">PART C · 10-15 นาที · ⚠ รอ interview</div>
<div class="font-display text-[30px] font-medium leading-none mt-1 text-rose-deep">🌟 พี่เต๋า · โอกาสของชีวิตที่ออกแบบได้</div>
</div>
<div class="font-display text-[14px] italic text-rose-deep/80 text-right max-w-[210px]">peak · "เขาเคยเป็นแบบฉัน · ฉันก็เป็นได้"</div>
</div>
</div>
</div>
<div class="spine pl-14 md:pl-20 space-y-4" id="tao-steps"></div>
<div class="vert-only my-7 flex items-center justify-center gap-3">
<span class="h-px w-12 bg-ink-20"></span>
<span class="font-mono text-[10px] uppercase tracking-[0.2em] text-gold font-bold px-4 py-1.5 rounded-full bg-gold/10">↓ ปิดร่วมกัน</span>
<span class="h-px w-12 bg-ink-20"></span>
</div>
<!-- CLOSING -->
<div class="seg-header mb-5">
<div class="rounded-2xl p-5 text-cream shadow-lg" style="background:#1F1E1B;">
<div class="font-mono text-[10px] uppercase tracking-[0.2em] text-gold font-bold">PART D · 5 นาที · จิ้น + ต้น</div>
<div class="font-display text-[30px] font-medium leading-none mt-1">🎯 ปิด · 3 ก้าวให้เลือก 1</div>
</div>
</div>
<div class="spine pl-14 md:pl-20 space-y-4" id="close-steps"></div>
<div class="mt-10 text-center">
<div class="inline-block rounded-3xl bg-ink px-8 py-6 text-cream max-w-xl">
<div class="font-mono text-[10px] uppercase tracking-[0.2em] text-gold font-bold">END · ~1:45:00</div>
<div class="mt-2 font-display text-[26px] italic leading-tight">
"ที่สำคัญไม่ใช่ตัดสินใจอะไร<br>แต่คือคุณ <span class="text-gold not-italic">ขยับ</span> 1 ก้าว"
</div>
</div>
</div>
<div class="mt-10 text-center font-mono text-[9px] uppercase tracking-widest text-ink-40">
UP Wellness · Opp Flow · จิ้น 45m + ต้น 40m + พี่เต๋า · 2026
</div>
</div>
<div class="toast skip-export" id="toast"></div>
<script type="module">
import { toPng } from "https://esm.sh/[email protected]";
/* [step, time, durMin, say, detail, get, slide, cue] */
const JIN = [
["A1","0:00",3,"เปิดตัว + ตั้งกติกา","\"เราจะแบ่งปัน 3 มุมมอง · ฟังจบถ้าใช่ค่อยคุย\"","รู้สึกปลอดภัย · ไม่ถูก pitch · เปิดใจ","Title card · UP Wellness","warm · ไม่รีบ · ยืนนิ่ง 3 วิ"],
["A2","3:00",5,"คำถามที่ทำให้คนเงียบ","\"อยู่ถึง 90 ป่วยตั้งแต่ 50?\" · Healthspan 67 vs 73","ตกใจ · \"เงินจะหมดช่วงติดเตียง\"","2 bars: Lifespan vs Healthspan","serious · pause 4 วิ หลังคำถาม"],
["A3","8:00",10,"Longevity Pyramid 5 ชั้น","ชั้น 0 ฟรี + ชั้น 1 (400-3,500฿) = 95%","โล่งใจ · \"เริ่มได้ทุกงบ\"","Pyramid 5 ชั้น · 0+1 สว่าง","อธิบายชัด · ชี้ slide ทีละชั้น"],
["A4","18:00",8,"\"5 ยาก\" ⭐ signature","โกรธ/เหนื่อย/หิว/อ้วน/เครียด ยาก · 80% lifestyle","จดจำได้ · เห็นผลจับต้องได้","5 คำใหญ่ font ใหญ่","signature reveal · ช้า ชัด · ปล่อย slide"],
["A5","26:00",7,"2 เรื่องเล่า (messy middle)","ผู้บริหาร 47 (หยุดแล้วกลับมา) + แม่ลูก 2 งบ 400฿","\"เห็นฉัน\" · เชื่อเพราะไม่ perfect","ภาพเคส (เบลอหน้า)","warm · เล่าเหมือนคุยเพื่อน"],
["A6","33:00",5,"ทำไมต้องมีคอมมูนิตี้","Harvard Waldinger · \"find a healthy friend\"","อยากมีเพื่อนสุขภาพดี","Harvard study + community photos","ทำให้คนหยุดฟังตรง reveal"],
["A7","38:00",3,"ความปลอดภัยก่อน ⚠","\"wellness ≠ medical advice\" + contraindications","ไว้ใจ · ทีมจริงจัง safety","Safety · 4 contraindications","FTC mode · พูดช้า ชัด ไม่กลบ"],
["A8","41:00",3,"1 habit + 1 supplement","เลือก 1 นิสัย + Vit D3 ตัวเดียว · ตรวจเลือดก่อน","มีก้าวทำได้พรุ่งนี้","1 habit + 1 supplement card","grounded · เน้นทำได้จริง"],
["A9","44:00",1,"ส่งไม้ต่อพี่ต้น","\"ร่างกายพร้อม · แต่ต้องมีงานรอดยุค AI\"","พร้อมฟังต่อ · เชื่อมโยง","transition (blank)","warm transition · ยกแก้วน้ำ"],
];
const TON = [
["B1","45:00",4,"เปิดไพ่ Amway ก่อน + disclaimer","นี่คือ Amway/Nutrilite · ขรก.เช็กระเบียบ · \"เสาที่ 2 ในยุค AI?\"","เปิดไพ่ก่อน ไม่ถูก setup","Amway/Nutrilite ขึ้นใหญ่ + จดทะเบียน สคบ.","เปิดไพ่ตรงๆ · สบตา"],
["B2","49:00",6,"3 สิ่งเปลี่ยนโลก (ภาษามนุษย์)","การค้า·AI·Longevity · mental model ไม่ใช่วิจัย · WEF 44%","\"งานเราอีก 10 ปีจะอยู่ไหม?\"","3 ภาพเรียบ ไม่มีศัพท์ปั้น","ไม่ปั่น FOMO · ตัด 'รวยก่อน'"],
["B3","55:00",5,"Longevity > Weight Loss","UN 2024 · ปี 2050 · 1 ใน 6 คนเกิน 65","ตลาดยั่งยืน ไม่ใช่กระแส","เปรียบเทียบ 2 ตลาด","มั่นใจ · เน้น market thesis"],
["B4","60:00",4,"แพลตฟอร์มพร้อม + 3 ชุด","สร้างเอง 2-5 ล้าน vs พร้อม · เสนอ Pack Longevity/คอร์สลดนน./ฟื้นฟู","\"ไม่ต้องเสี่ยงสร้างเอง\"","เทียบ + 3 การ์ดชุด Pack/คอร์ส","กระจ่าง · Amway เปิดที่ B1 แล้ว"],
["B5","64:00",6,"median + 3 เคส (เลิก n=1)","median หลักพัน-หมื่นต้น · 3 เคส A/B/C รวมเคสเลิก","\"เห็น median + เคสเลิก = เชื่อได้\"","bar median + 3 การ์ดเคส","ไม่ขายฝัน · กัน survivorship bias"],
["B6","70:00",8,"ตัวเลขจริง + Real Costs ⭐","FTC: 60-70% หยุดปีแรก · ต้นทุนจริง","เชื่อใจมาก · \"บอกความจริง\"","Real Costs table","FTC mode · directly · pause ยาว"],
["B7","78:00",4,"\"จะกลายเป็นใคร\" + Portfolio","ไม่ใช่ได้เงินเท่าไหร่ · Life Portfolio 4 มิติ","สะท้อนลึก · มองระยะยาว","Life Portfolio 4 มิติ","directly + warm"],
["B8","82:00",3,"ส่งไม้ต่อพี่เต๋า","\"ตัวเลขคือกระดาษ · ชีวิตจริงเป็นยังไง\"","อยากเห็นคนจริง · เปิดใจ","transition","setup emotion · ลดเสียง"],
];
const TAO = [
["C1","85:00",3,"ชีวิตก่อนหน้านี้","scene จริง · ตื่น 5 โมง กลับ 2 ทุ่ม ลูกหลับแล้ว","\"นี่คือชีวิตฉันเลย\"","ภาพ before / mood","vulnerable · grounded"],
["C2","88:00",2,"Turning Point","moment เดียวที่รู้ว่า \"ต้องเปลี่ยน\"","อิน · emotional connection","ภาพ turning moment","emotional · truthful"],
["C3","90:00",3,"Messy Middle ⭐ ห้ามข้าม","\"เกือบล้มเลิกตอนไหน\" · มีคนตั้งคำถาม","\"ไม่ใช่ overnight · เขาก็ลำบาก\"","(ไม่ต้องมี slide · ให้คนฟัง)","honest about struggle · ไม่เร่ง"],
["C4","93:00",3,"ชีวิตวันนี้","วันธรรมดา · 4 freedom · ไม่ flex ตัวเลข","เห็นปลายทางที่อยากได้","ภาพ today / 4 freedom","warm · ไม่ flex"],
["C5","96:00",1,"The Invitation","\"ผมไม่บอกให้เชื่อ · แต่ลองเปิดประตูดู\"","อยากลองก้าวแรก","(close-up พี่เต๋า)","soft · open · ไม่ close"],
];
const CLOSE = [
["D1","97:00",2,"ก้าวที่ 1 · สุขภาพ (ต้น)","1 habit + 1 supplement · \"ไม่ต้องซื้อกับเรา\"","ก้าวง่ายสุด · zero pressure","3 ก้าว · card 1","grounded"],
["D2","99:00",2,"ก้าวที่ 2 · ความรู้ (จิ้น)","คอมมูนิตี้ฟรี · ทุกวัย · QR scan","ก้าวกลาง · เข้าร่วมได้เลย","3 ก้าว · card 2 + QR","warm · invite"],
["D3","101:00",2,"ก้าวที่ 3 · ธุรกิจ (ต้น)","1-pager / voice / กาแฟ · \"ไม่ต้องตัดสินใจวันนี้\"","ก้าวลึก · เลือกจังหวะเอง","3 ก้าว · card 3","low-pressure · ให้ทางเลือก"],
["D4","103:00",2,"ปิด · \"ขยับ 1 ก้าวก็พอ\"","\"โลกของคนขยับเร็ว · มีเพื่อนที่ใช่\"","ออกจากห้องพร้อม 1 ก้าว · อบอุ่น","ปิด · ปรบมือ fade","warm + soft · สบตาทั่วห้อง"],
];
const COLORS = {
jin:{node:'#396755',card:'card-jin',bar:'#6AAF91'},
ton:{node:'#C47A2A',card:'card-ton',bar:'#C47A2A'},
tao:{node:'#B57878',card:'card-tao',bar:'#B57878'},
close:{node:'#B8965A',card:'card-close',bar:'#B8965A'},
};
const MAXDUR = 10; // longest beat (A3) for bar scaling
function renderSteps(containerId, data, kind) {
const c = COLORS[kind];
document.getElementById(containerId).innerHTML = data.map(([step,time,dur,say,detail,get,slide,cue]) => `
<div class="relative">
<div class="node" style="background:${c.node};">${step.replace(/[A-D]/,'')}</div>
<div class="step-card ${c.card} rounded-2xl bg-white shadow-[0_8px_24px_-12px_rgba(31,30,27,0.18)] overflow-hidden">
<div class="flex items-center justify-between px-5 pt-3.5 gap-3">
<div class="font-mono text-[10px] font-bold tracking-widest text-ink-40">${step} · ${time}</div>
<div class="flex items-center gap-2 min-w-[90px]">
<div class="dur-track flex-1"><div class="dur-fill" style="width:${Math.round(dur/MAXDUR*100)}%;background:${c.bar};"></div></div>
<span class="font-mono text-[10px] font-bold" style="color:${c.node};">${dur}'</span>
</div>
</div>
<div class="zone-say px-5 py-2.5 mt-2">
<div class="font-mono text-[8.5px] uppercase tracking-widest text-ink-40 font-bold mb-0.5">🗣 พูดอะไร</div>
<div class="font-head text-[16px] font-bold text-ink leading-tight">${say}</div>
</div>
<div class="px-5 py-2.5 text-ink-60">
<div class="font-mono text-[8.5px] uppercase tracking-widest text-ink-40 font-bold mb-0.5">📝 รายละเอียด</div>
<div class="font-thai text-[13px] leading-snug">${detail}</div>
</div>
<div class="zone-get px-5 py-3 m-2.5 rounded-xl">
<div class="font-mono text-[8.5px] uppercase tracking-widest text-amber font-bold mb-0.5">💡 คนฟังได้อะไร</div>
<div class="font-thai text-[13.5px] font-medium text-ink leading-snug">${get}</div>
</div>
<div class="flex gap-2 px-2.5 pb-2.5">
<div class="flex-1 rounded-lg px-3 py-2" style="background:rgba(140,76,76,0.06);">
<div class="font-mono text-[8px] uppercase tracking-widest text-rose font-bold mb-0.5">🖼 SLIDE</div>
<div class="font-thai text-[11.5px] text-ink-80 leading-tight">${slide}</div>
</div>
<div class="flex-1 rounded-lg px-3 py-2" style="background:rgba(31,30,27,0.04);">
<div class="font-mono text-[8px] uppercase tracking-widest text-ink-60 font-bold mb-0.5">🎭 วิธีพูด</div>
<div class="font-thai text-[11.5px] text-ink-80 leading-tight">${cue}</div>
</div>
</div>
</div>
</div>
`).join('');
}
renderSteps('jin-steps', JIN, 'jin');
renderSteps('ton-steps', TON, 'ton');
renderSteps('tao-steps', TAO, 'tao');
renderSteps('close-steps', CLOSE, 'close');
const toast = (msg) => { const t=document.getElementById('toast'); t.textContent=msg; t.classList.add('show'); setTimeout(()=>t.classList.remove('show'),2500); };
/* toggle compact / A3 mode */
const toggleBtn = document.getElementById('toggleBtn');
toggleBtn.addEventListener('click', () => {
document.body.classList.toggle('compact');
const on = document.body.classList.contains('compact');
toggleBtn.textContent = on ? '📖 โหมดอ่านเต็ม' : '🖨 โหมด A3 แนวนอน';
toast(on ? '🖨 โหมด A3 · กด Ctrl+P เพื่อ print แนวนอน' : '📖 โหมดอ่านเต็ม');
});
/* save PNG */
document.getElementById('saveBtn').addEventListener('click', async () => {
toast('📸 กำลังสร้างรูป...');
try {
const dataUrl = await toPng(document.getElementById('flow-canvas'), {
pixelRatio: 2, backgroundColor: '#FDFCFB', cacheBust: true,
filter:(n)=>!(n.classList && n.classList.contains('skip-export')),
});
const a=document.createElement('a'); a.download='opp-flow-การพูด.png'; a.href=dataUrl; a.click();
toast('✓ บันทึกแล้ว · opp-flow-การพูด.png');
} catch(e){ console.error(e); toast('⚠ ลองใหม่อีกครั้ง'); }
});
</script>
</body>
</html>