-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathEDITOR_HOOKUP_GUIDE.html
More file actions
6574 lines (6451 loc) Β· 459 KB
/
EDITOR_HOOKUP_GUIDE.html
File metadata and controls
6574 lines (6451 loc) Β· 459 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
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Carolina Futons - Editor Hookup Guide</title>
<style>
/* ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
CAROLINA FUTONS β EDITOR HOOKUP GUIDE v2.8
Design tokens match sharedTokens.js + designTokens.js exactly
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */
:root {
/* ββ Brand palette β sharedTokens.js + Figma Design System v1.0 ββ
EXACT values. Do not adjust. Source: colors.* in sharedTokens.js */
--espresso: #3A2518; /* colors.espresso β text, borders, headers */
--mountain-blue: #5B8FA8; /* colors.mountainBlue β accents, links */
--coral: #E8845C; /* colors.sunsetCoral β CTAs ALWAYS, badges */
--sand: #E8D5B7; /* colors.sand β primary warm bg */
--off-white: #FAF7F2; /* colors.offWhite β page canvas */
--sand-light: #F2E8D5; /* colors.sandLight β alt sections, hovers */
--charcoal: #2C2C2C; /* body text (not a named token, used in guide UI) */
/* Extended palette β Figma doc section 1 */
--espresso-light: #6B4D3A; /* secondary text, captions, metadata */
--mountain-blue-light:#8BB5C9; /* badges, info states, light accents */
--coral-light: #F0A882; /* hover states, softer highlights */
--sky-gradient-start: #B8D4E3; /* sky gradient top */
--sky-gradient-end: #F0C87A; /* sky gradient bottom (sunrise gold) */
/* Shadows β Figma doc section 5: espresso-tinted rgba(58,37,24,...) */
--shadow-sm: 0 2px 8px rgba(58,37,24,0.08); /* subtle β cards, inputs */
--shadow-md: 0 4px 16px rgba(58,37,24,0.12); /* medium β hover, dropdowns */
--shadow-lg: 0 8px 32px rgba(58,37,24,0.18); /* heavy β modals, overlays */
/* Transitions β Figma doc section 6 */
--transition-fast: 150ms; /* hover states, toggles, micro-interactions */
--transition-medium: 250ms; /* fade-in, show/hide */
--transition-slow: 400ms; /* modal open, drawer slide */
/* Spacing β 4px base scale, Figma doc section 4 */
--space-xs: 4px; /* spacing.xs */
--space-sm: 8px; /* spacing.sm */
--space-md: 16px; /* spacing.md */
--space-lg: 24px; /* spacing.lg */
--space-xl: 32px; /* spacing.xl */
--space-2xl: 48px; /* spacing.xxl */
--space-3xl: 64px; /* spacing.xxxl */
/* Aliases for guide UI convenience */
--sand-medium: var(--sand-light);
--cream: var(--off-white);
--success: #2e7d32;
--warning: #a06000;
--danger: #c00000;
/* Typography β Wix Studio fonts */
--font-heading: 'Playfair Display', Georgia, serif;
--font-body: 'Source Sans 3', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
--font-mono: 'SF Mono', Monaco, 'Cascadia Code', monospace;
/* Radius */
--radius-sm: 4px; --radius-md: 8px; --radius-lg: 12px; --radius-xl: 16px;
/* Shadows */
--shadow-sm: 0 1px 3px rgba(0,0,0,0.08);
--shadow-md: 0 2px 8px rgba(0,0,0,0.12);
--shadow-lg: 0 4px 20px rgba(0,0,0,0.15);
}
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: var(--font-body);
background: var(--sand-light);
color: var(--charcoal);
line-height: 1.5;
}
/* ββ HEADER ββ */
.header {
background: var(--espresso);
color: white;
padding: 16px var(--space-2xl);
position: sticky; top: 0; z-index: 100;
box-shadow: var(--shadow-md);
}
.header-top { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; }
.header h1 { font-family: var(--font-heading); font-size: 1.3em; margin-bottom: 6px; }
.header-subtitle { font-size: 0.8em; opacity: 0.7; }
.header-stats { display: flex; gap: 12px; flex-wrap: wrap; font-size: 0.8em; }
.stat-chip {
background: rgba(255,255,255,0.12);
border: 1px solid rgba(255,255,255,0.2);
padding: 3px 10px;
border-radius: 20px;
white-space: nowrap;
}
.stat-chip.done { background: rgba(232,132,92,0.4); border-color: var(--coral); }
.progress-bar { background: rgba(255,255,255,0.2); border-radius: 8px; height: 10px; overflow: hidden; margin-top: 8px; }
.progress-fill { background: linear-gradient(90deg, var(--coral), var(--coral-light)); height: 100%; border-radius: 8px; transition: width 0.4s ease; }
.progress-text { font-size: 0.82em; margin-top: 4px; opacity: 0.85; }
/* ββ CONTROLS BAR ββ */
.controls {
background: white;
padding: 10px var(--space-2xl);
border-bottom: 2px solid var(--sand-medium);
display: flex; gap: 10px; flex-wrap: wrap; align-items: center;
position: sticky; top: 80px; z-index: 99;
box-shadow: var(--shadow-sm);
}
.controls input[type="text"] {
flex: 1; min-width: 180px;
padding: 7px 12px;
border: 1px solid #ccc; border-radius: var(--radius-md);
font-size: 13.5px; font-family: var(--font-body);
transition: border-color 0.2s;
}
.controls input[type="text"]:focus { outline: none; border-color: var(--mountain-blue); }
.controls select {
padding: 7px 10px;
border: 1px solid #ccc; border-radius: var(--radius-md);
font-size: 13px; font-family: var(--font-body);
}
.ctrl-btn {
padding: 7px 14px;
border: 1px solid #ccc; border-radius: var(--radius-md);
background: white; font-size: 13px;
cursor: pointer; font-family: var(--font-body);
transition: all 0.15s;
white-space: nowrap;
}
.ctrl-btn:hover { background: var(--sand-light); border-color: var(--mountain-blue); }
.ctrl-btn.active { background: var(--mountain-blue); color: white; border-color: var(--mountain-blue); }
.ctrl-sep { width: 1px; height: 24px; background: #ddd; }
.shortcut-hint { font-size: 0.75em; color: #999; display: none; }
@media (min-width: 900px) { .shortcut-hint { display: inline; } }
/* ββ MAIN ββ */
.main { max-width: 1300px; margin: 0 auto; padding: var(--space-lg); }
/* ββ PAGE SECTIONS ββ */
.page-section {
background: white;
border-radius: var(--radius-lg);
margin-bottom: var(--space-md);
box-shadow: var(--shadow-sm);
overflow: hidden;
border: 1px solid transparent;
transition: border-color 0.2s;
}
.page-section.has-focus { border-color: var(--mountain-blue); }
.page-header {
padding: 14px var(--space-xl);
cursor: pointer;
display: flex; justify-content: space-between; align-items: center;
border-bottom: 1px solid #eee;
user-select: none;
gap: 12px;
}
.page-header:hover { background: var(--sand-light); }
.page-header h2 { font-size: 1.05em; color: var(--espresso); font-weight: 600; flex: 1; }
.page-meta { display: flex; gap: 10px; align-items: center; font-size: 0.82em; color: #666; flex-shrink: 0; }
.page-meta .badge { padding: 2px 8px; border-radius: 10px; font-size: 0.78em; font-weight: 700; }
.p0 { background: #ffe0e0; color: #c00; }
.p1 { background: #fff0d0; color: #a60; }
.p2 { background: #d0f0ff; color: #06a; }
.p3 { background: #e0e0e0; color: #666; }
.page-progress { font-weight: 700; }
.page-progress.complete { color: var(--success); }
/* Mark-all-done button */
.mark-all-btn {
padding: 3px 10px; border-radius: 20px;
font-size: 0.78em; font-weight: 600;
background: transparent;
border: 1px solid #ddd;
cursor: pointer; color: #666;
transition: all 0.15s;
white-space: nowrap;
}
.mark-all-btn:hover { background: var(--sand-light); border-color: var(--mountain-blue); color: var(--mountain-blue); }
.mark-all-btn.all-done { background: #e8f5e9; border-color: var(--success); color: var(--success); }
.arrow { transition: transform 0.2s; display: inline-block; }
.arrow.open { transform: rotate(90deg); }
/* ββ PAGE BODY ββ */
.page-body { padding: 0 var(--space-xl) var(--space-lg); }
.page-body.collapsed { display: none; }
.section-group { margin-top: var(--space-md); }
.section-group h3 {
font-size: 0.92em; color: var(--mountain-blue);
margin-bottom: var(--space-sm);
padding-bottom: var(--space-xs);
border-bottom: 1px solid #eee;
display: flex; align-items: center; gap: 8px;
}
/* ββ ELEMENT TABLE ββ */
.el-table { width: 100%; border-collapse: collapse; font-size: 0.88em; margin-bottom: var(--space-sm); }
.el-table th {
text-align: left; padding: 6px 8px;
background: var(--sand-medium); font-size: 0.83em; color: #555;
position: sticky; /* helps with very long pages */
}
.el-table td { padding: 6px 8px; border-bottom: 1px solid #f0f0f0; vertical-align: middle; }
.el-table tr:hover td { background: #f8f8f4; }
.el-table tr.done td { opacity: 0.45; text-decoration: line-through; }
.el-check { width: 24px; }
/* Element ID cell with copy button */
.el-id-cell { display: flex; align-items: center; gap: 6px; }
.el-id {
font-family: var(--font-mono);
font-size: 0.84em; color: var(--espresso); font-weight: 600;
cursor: pointer;
}
.copy-btn {
background: none; border: 1px solid transparent;
border-radius: var(--radius-sm); padding: 1px 5px;
font-size: 0.72em; cursor: pointer; color: #aaa;
transition: all 0.15s; white-space: nowrap;
}
.copy-btn:hover { color: var(--mountain-blue); border-color: var(--mountain-blue); background: #f0f7ff; }
.copy-btn.copied { color: var(--success); border-color: var(--success); background: #e8f5e9; }
/* CSS ownership badge */
.css-badge {
display: inline-block; padding: 1px 5px;
border-radius: 3px; font-size: 0.7em; font-weight: 600;
background: #e8f5e9; color: #2e7d32;
white-space: nowrap; vertical-align: middle;
}
.css-badge.code-only { background: #f3e5f5; color: #6a1b9a; }
/* ββ TYPE BADGES ββ */
.type-badge { display: inline-block; padding: 1px 6px; border-radius: var(--radius-sm); font-size: 0.73em; font-weight: 700; white-space: nowrap; }
.type-Section { background: #e8d5f5; color: #7b2d8e; }
.type-Box { background: #d5e8f5; color: #2d5f8e; }
.type-Text { background: #d5f5d5; color: #2d8e2d; }
.type-Button { background: #f5e8d5; color: #8e5f2d; }
.type-Image { background: #f5d5e8; color: #8e2d5f; }
.type-Repeater { background: #c62828; color: white; }
.type-Input { background: #ffe8d5; color: #a05020; }
.type-TextBox { background: #ffe8d5; color: #a05020; }
.type-Dropdown { background: #d5f5f5; color: #2d8e8e; }
.type-Toggle { background: #e0e0ff; color: #4040a0; }
.type-ProgressBar { background: #f0f0d0; color: #808020; }
.type-HtmlComponent { background: #1a1a1a; color: #00ff88; }
.type-Video { background: #ff4081; color: white; }
.type-Dataset { background: #455a64; color: white; }
.type-Gallery { background: #6a1b9a; color: white; }
.type-DatePicker { background: #bf360c; color: white; }
.type-CheckboxGroup { background: #1565c0; color: white; }
.type-RadioButton { background: #880e4f; color: white; }
/* ββ REPEATER NOTE ββ */
.repeater-note {
background: #fff3f3; border-left: 3px solid #c62828;
padding: 5px 10px; margin: 4px 0 8px;
font-size: 0.84em; color: #b71c1c;
border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}
/* ββ IMPL NOTES ββ */
.impl-notes {
background: #f0f7ff;
border-left: 4px solid var(--mountain-blue);
padding: 12px 16px; margin: 8px 0 12px;
border-radius: 0 var(--radius-md) var(--radius-md) 0;
font-size: 0.87em; line-height: 1.65;
}
.impl-notes h4 { color: var(--mountain-blue); margin: 0 0 6px; font-size: 0.94em; font-weight: 700; }
.impl-notes ul { padding-left: 18px; margin: 4px 0 8px; }
.impl-notes li { margin-bottom: 4px; }
.impl-notes .layer-diagram {
background: #e8f0f8; border: 1px solid #c0d8e8;
border-radius: var(--radius-md); padding: 10px 14px; margin: 8px 0;
font-family: var(--font-mono); font-size: 0.83em;
white-space: pre-line; color: #1e3a5a; line-height: 1.7;
}
.impl-notes .impl-warn { color: var(--warning); font-weight: 700; }
.impl-notes code { background: #dde8f4; padding: 1px 5px; border-radius: 3px; font-size: 0.9em; }
/* CSS note block inside impl */
.css-note {
background: #f3faf3; border-left: 3px solid #4caf50;
padding: 8px 12px; margin: 6px 0;
border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
font-size: 0.86em;
}
.css-note strong { color: #2e7d32; }
/* ββ DESIGN TOKENS PANEL ββ */
.tokens {
background: white; border-radius: var(--radius-lg);
padding: var(--space-xl); margin-bottom: var(--space-md);
box-shadow: var(--shadow-sm);
}
.tokens h2 { color: var(--espresso); margin-bottom: 12px; font-family: var(--font-heading); }
.tokens-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 16px; }
.token-group h3 { font-size: 0.85em; color: #888; text-transform: uppercase; letter-spacing: 0.08em; margin-bottom: 8px; }
.swatch-row { display: flex; gap: 12px; flex-wrap: wrap; }
.swatch { display: flex; align-items: center; gap: 8px; cursor: pointer; }
.swatch:hover .swatch-label { color: var(--mountain-blue); }
.swatch-color { width: 30px; height: 30px; border-radius: var(--radius-sm); border: 1px solid rgba(0,0,0,0.1); }
.swatch-label { font-size: 0.82em; }
.swatch-label code { font-family: var(--font-mono); font-size: 0.9em; color: #666; }
/* Typography preview */
.typo-row { display: flex; flex-direction: column; gap: 8px; }
.typo-sample { display: flex; align-items: baseline; gap: 10px; }
.typo-name { font-size: 0.78em; color: #888; min-width: 80px; }
.typo-preview { }
.typo-h1 { font-family: var(--font-heading); font-size: 1.4em; color: var(--espresso); }
.typo-h2 { font-family: var(--font-heading); font-size: 1.15em; color: var(--espresso); }
.typo-body { font-family: var(--font-body); font-size: 0.95em; }
.typo-mono { font-family: var(--font-mono); font-size: 0.85em; color: var(--espresso); }
.spacing-row { display: flex; gap: 8px; flex-wrap: wrap; align-items: flex-end; }
.spacing-chip { display: flex; flex-direction: column; align-items: center; gap: 3px; }
.spacing-bar { background: var(--mountain-blue); opacity: 0.6; border-radius: 2px; width: 12px; }
.spacing-label { font-size: 0.72em; color: #888; }
/* ββ HOW TO ββ */
.howto {
background: white; border-radius: var(--radius-lg);
padding: var(--space-xl); margin-bottom: var(--space-md);
box-shadow: var(--shadow-sm);
}
.howto h2 { color: var(--espresso); margin-bottom: 8px; font-family: var(--font-heading); }
.howto ol { padding-left: 20px; }
.howto li { margin-bottom: 5px; font-size: 0.9em; }
.howto .key {
display: inline-block; padding: 1px 6px;
background: var(--sand-medium); border: 1px solid #ccc;
border-radius: 3px; font-family: var(--font-mono);
font-size: 0.82em; color: var(--charcoal);
}
/* ββ TOAST ββ */
#toast {
position: fixed; bottom: 24px; right: 24px;
background: var(--espresso); color: white;
padding: 10px 18px; border-radius: var(--radius-md);
font-size: 0.88em; z-index: 9999;
opacity: 0; transform: translateY(8px);
transition: opacity 0.2s, transform 0.2s;
pointer-events: none;
}
#toast.show { opacity: 1; transform: translateY(0); }
/* ββ FOCUS MODE ββ */
body.focus-mode .page-section { display: none; }
body.focus-mode .page-section.focus-visible { display: block; }
/* ββ RESPONSIVE ββ */
@media (max-width: 700px) {
.header { padding: 12px 16px; }
.controls { padding: 8px 12px; }
.main { padding: 10px; }
.el-table th:nth-child(4), .el-table td:nth-child(4) { display: none; }
}
</style>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:wght@600;700&family=Source+Sans+3:wght@400;600&display=swap" rel="stylesheet">
</head>
<body>
<div class="header">
<div class="header-top">
<div>
<h1>Carolina Futons β Editor Hookup Guide</h1>
<div class="header-subtitle">Wix Studio element placement reference Β· v4.5 Β· Updated 2026-04-17 β CMS collections 32β36: added Landings, PressMentions, PressKitAssets, ComparisonFeatures to provisioning manifest + setup guide for cf-3qt Phase 4/5 migration. Dashboard needed: provision 4 new collections on STAGING_SITE (cf-3qt). Previous: v4.4 β CMS collections 28β32: added PushTokens, SpinGrants, MobileChallengeCompletions, CrossRigSyncLog. v4.3 β Phase 8 COMPLETE.</div>
</div>
<div class="header-stats" id="headerStats">
<span class="stat-chip" id="statTotal">0 total</span>
<span class="stat-chip done" id="statDone">0 done</span>
<span class="stat-chip" id="statPages">0 pages</span>
<span class="stat-chip" id="statEst">~0 min left</span>
</div>
</div>
<div class="progress-bar"><div class="progress-fill" id="progressFill"></div></div>
<div class="progress-text" id="progressText">0 / 0 elements complete</div>
</div>
<div class="controls">
<input type="text" id="searchBox" placeholder="π Search element IDs...">
<select id="typeFilter"><option value="">All Types</option></select>
<select id="priorityFilter">
<option value="">All Priorities</option>
<option value="P0">P0 β Critical (must be done first)</option>
<option value="P1">P1 β High</option>
<option value="P2">P2 β Medium</option>
<option value="P3">P3 β Low / Deferred</option>
</select>
<div class="ctrl-sep"></div>
<button class="ctrl-btn" id="expandAllBtn" title="Expand all sections">Expand All</button>
<button class="ctrl-btn" id="collapseAllBtn" title="Collapse all sections">Collapse All</button>
<button class="ctrl-btn" id="focusUndoneBtn" title="Show only pages with undone items">Undone Only</button>
<div class="ctrl-sep"></div>
<button class="ctrl-btn" id="resetBtn" title="Reset all checkboxes">Reset All</button>
<span class="shortcut-hint">Β· <kbd class="key">βK</kbd> search Β· <kbd class="key">E</kbd> expand Β· <kbd class="key">C</kbd> collapse</span>
</div>
<div id="toast"></div>
<div class="main" id="mainContent"></div>
<script>
// All page data
const PAGES = [
{
name: "Home", file: "Home.c1dmp.js", priority: "P0", est: "45 min",
sections: [
{ name: "Hero Section", impl: `<h4>ποΈ Implementation β Hero Section</h4>
<p><strong>Layout: Full-bleed layered stack</strong> β all 7 elements occupy the same visual space, layered on top of each other (NOT laid out vertically).</p>
<div class="layer-diagram">LAYER ORDER (bottom β top):
ββββββββββββββββββββββββββββ
β #heroSection β Section container, full viewport width
β‘ #heroBg β Image, stretched to fill section (1920Γ800)
β’ #heroOverlay β Box, same size as heroBg, sits ON TOP of image
β£ #heroTitle β Text (H1), centered on overlay
β€ #heroSubtitle β Text, below title, centered
β₯ #heroCTA β Button, below subtitle, centered
β¦ #heroSkyline β Box, pinned to BOTTOM EDGE of section</div>
<ul>
<li><strong>#heroSection</strong>: Add a Section (full-width strip). No background color needed β code sets it.</li>
<li><strong>#heroBg</strong>: Add an Image element <em>inside</em> the section. Stretch it to fill the entire section. Use any placeholder β code replaces it at runtime with a Blue Ridge cabin lifestyle photo (1920Γ800). Set <code>fitMode: cover</code>.</li>
<li><strong>#heroOverlay</strong>: Add a Box element on TOP of the image, same dimensions. Set opacity ~50% in editor as a visual guide β code sets <code>colors.overlay</code> (semi-transparent espresso) at runtime for text readability.</li>
<li><strong>#heroTitle</strong>: Add a Text element ON TOP of the overlay. <span class="impl-warn">Must be heading level H1</span> (critical for SEO). Placeholder text "Title" is fine β code sets it to "Handcrafted Comfort, Mountain Inspired." with Playfair Display font.</li>
<li><strong>#heroSubtitle</strong>: Text element below title, still on top of overlay. Placeholder "Subtitle" is fine β code sets the real copy.</li>
<li><strong>#heroCTA</strong>: Button element below subtitle. Label will be set to "Explore Our Collection" by code. Clicking navigates to <code>/shop-main</code>.</li>
<li><strong>#heroSkyline</strong>: Add an <em>empty</em> Box element pinned to the bottom edge of heroSection. Code injects a mountain skyline SVG gradient animation into this container via <code>MountainSkyline.js</code>. If the module isn't available, falls back to a static ridgeline SVG.</li>
</ul>
<p><strong>Animation sequence</strong>: Elements fade in with staggered delays β overlay (0ms) β title (200ms) β subtitle (400ms) β CTA (600ms). All use 300ms fade duration. Elements should be <strong>hidden by default</strong> in the editor; code calls <code>.show('fade')</code>.</p>
<p class="impl-warn">β οΈ Common mistake: Laying these out vertically (title, then image, then button in separate rows). They must be STACKED/OVERLAPPING in one section.</p>`, elements: [
["heroSection","Section","Full-width, bg set by code (#3A2518)"],
["heroBg","Image","Hero background image"],
["heroOverlay","Box","Transparent overlay"],
["heroTitle","Text","H1, code sets text"],
["heroSubtitle","Text","Subheading"],
["heroCTA","Button","Shop Now button"],
["heroSkyline","Box","Mountain skyline animation container"]
]},
{ name: "Featured Products", repeater: "featuredRepeater", impl: `<h4>ποΈ Implementation β Featured Products</h4>
<p><strong>Layout: Section heading + 4-column product card grid + hidden Quick View modal</strong></p>
<div class="layer-diagram">STRUCTURE:
ββββββββββββββββββββββββββββ
#featuredTitle β "Our Favorite Finds" heading (H2)
#featuredSubtitle β subheading text
#featuredSkeleton β placeholder box (shown during load, then fades out)
#featuredRepeater β 4-column grid (desktop), 2-column (mobile)
ββ per item template:
#featuredCard β Box wrapper (white bg, 12px radius, shadow)
#featuredImage β Product image (top, lazy-loaded)
#featuredRibbon β Badge corner (Bestseller/Sale/New/Featured)
#featuredName β Product name text
#featuredPrice β Sale price
#featuredOriginalPrice β Original price (strikethrough, hidden if no sale)
#featuredSaleBadge β "X% OFF" inline text
#featuredColorText β "Available in X colors" text
#featuredSwatchContainer β Box for color swatch dots
#featuredQuickViewBtn β "Quick View" button (appears on hover)
#featuredQuickViewModal β Hidden modal (overlay dialog)
#featuredQvClose β X close button (top-right)
#featuredQvImage β Large product image
#featuredQvName β Product name
#featuredQvPrice β Price
#featuredQvViewFull β "View Full Details" button
#featuredQvAddToCart β "Add to Cart" button</div>
<ul>
<li><strong>#featuredSkeleton</strong>: Visible by default. Code fades it out (300ms) once products load, then shows the repeater.</li>
<li><strong>#featuredRepeater</strong>: Set to 4 columns desktop, 2 columns mobile in editor grid settings.</li>
<li><strong>Card layout</strong>: Image fills top of card. Below: name β price line (original strikethrough + sale price + badge) β color swatches β star rating (injected by code). Code applies <code>styleCardContainer()</code> for white bg, rounded corners, shadow.</li>
<li><strong>#featuredOriginalPrice</strong>: Hidden by default β only shown when product is on sale (code shows it with strikethrough).</li>
<li><strong>#featuredQuickViewBtn</strong>: Hidden by default, appears on card hover via <code>initCardHover()</code>.</li>
<li><strong>#featuredQuickViewModal</strong>: Hidden by default. Must be a Box with high z-index. Code uses <code>setupAccessibleDialog()</code> for focus trap + Escape-to-close. Shows with 200ms fade.</li>
<li><strong>Wishlist heart + star ratings</strong>: Injected by code into each card β no editor elements needed for these.</li>
</ul>`, elements: [
["featuredTitle","Text","Section heading"],
["featuredSubtitle","Text","Section subheading"],
["featuredSkeleton","Box","Loading placeholder"],
["featuredRepeater","Repeater","4 product cards"],
["featuredQuickViewModal","Box","Hidden modal dialog"],
["featuredQvImage","Image","Modal child"],
["featuredQvName","Text","Modal child"],
["featuredQvPrice","Text","Modal child"],
["featuredQvViewFull","Button","Modal child"],
["featuredQvAddToCart","Button","Modal child"],
["featuredQvClose","Button","Modal child - X button"]
], children: [
["featuredCard","Box","Card container"],
["featuredImage","Image","Product image"],
["featuredName","Text","Product name"],
["featuredPrice","Text","Current price"],
["featuredOriginalPrice","Text","Strikethrough price"],
["featuredSaleBadge","Text","X% OFF badge"],
["featuredRibbon","Text","New/Sale ribbon"],
["featuredColorText","Text","Available in X colors"],
["featuredSwatchContainer","Box","Color swatch dots"],
["featuredQuickViewBtn","Button","Quick view trigger"]
]},
{ name: "Sale Products", repeater: "saleRepeater", impl: `<h4>π·οΈ Implementation β Sale Products</h4>
<p><strong>Layout: Horizontal scroll row of sale product cards</strong></p>
<ul>
<li><strong>#saleSection</strong>: Collapsible Section. <span class="impl-warn">Code auto-collapses this if no sale products exist</span> β so it must be a Section (not a Box) to support <code>.collapse()</code>.</li>
<li><strong>#saleSkeleton</strong>: Visible by default. Fades out (300ms) when products load.</li>
<li><strong>#saleRepeater</strong>: Horizontal scroll layout β set overflow to scroll in editor. Cards in a single row.</li>
<li><strong>Card layout</strong>: Same pattern as Featured β image top, name + price below. Original price shown with strikethrough, sale price beside it.</li>
<li>Code applies <code>styleCardContainer()</code> + <code>initCardHover()</code> to each card.</li>
<li>Clicking any card navigates to <code>/product-page/{slug}</code>.</li>
</ul>`, elements: [
["saleSection","Section","Collapsible - hides if no sales"],
["saleSkeleton","Box","Loading placeholder"],
["saleRepeater","Repeater","Sale product cards"]
], children: [
["saleCard","Box","Card container"],
["saleImage","Image","Product image"],
["saleName","Text","Product name"],
["salePrice","Text","Sale price"],
["saleOrigPrice","Text","Original price"]
]},
{ name: "Category Cards", repeater: "categoryRepeater", impl: `<h4>π Implementation β Category Cards</h4>
<p><strong>Layout: Grid of up to 8 category cards with background images</strong></p>
<div class="layer-diagram">CARD LAYER ORDER (each card):
ββββββββββββββββββββββββββββ
#categoryCard β Box container (has bg image set by code)
#categoryCardImage β Image element (category photo, layered)
#categoryCardTitle β Category name text (centered, on top)
#categoryCardTagline β Tagline text (below title)
#categoryCardCount β "X products" text (bottom-right corner)</div>
<ul>
<li><strong>#categorySkeleton</strong>: Visible by default. Fades out (300ms) when categories load.</li>
<li><strong>#categoryRepeater</strong>: Grid layout β code populates up to 8 categories (Futon Frames, Mattresses, Murphy Beds, Platform Beds, Casegoods, Sale, Wall Huggers, Unfinished Wood).</li>
<li><strong>Card hover</strong>: Code sets <code>backgroundColor = colors.sunsetCoral</code> (coral accent) on mouse-in, resets on mouse-out.</li>
<li><strong>Images</strong>: Code replaces template stock photos with real CF category images via <code>getCategoryCardImage()</code>.</li>
<li><strong>Product count</strong>: Fetched live from CMS β shows actual count per category.</li>
<li>Each card is made keyboard-accessible via <code>makeClickable()</code>. Clicking navigates to the category page.</li>
<li><strong>Fallback</strong>: If repeater unavailable, code falls back to 4 static hardcoded card boxes (<code>#box26, #box24, #box22, #box20</code> with matching images/text). These are template elements β you may see them in the editor already.</li>
</ul>`, elements: [
["categorySkeleton","Box","Loading placeholder"],
["categoryRepeater","Repeater","8 category cards"]
], children: [
["categoryCard","Box","Card with bg image"],
["categoryCardTitle","Text","Category name"],
["categoryCardTagline","Text","Category tagline"],
["categoryCardCount","Text","Product count"],
["categoryCardImage","Image","Category image"]
]},
{ name: "Trust Bar", impl: `<h4>β
Implementation β Trust Bar</h4>
<p><strong>Layout: Horizontal bar with 4β5 trust signals side-by-side</strong></p>
<div class="layer-diagram">STRUCTURE:
ββββββββββββββββββββββββββββ
#trustBar β Box, full-width, espresso bg (#3A2518)
#trustItem1 β Box (inline) β #trustIcon1 (β°οΈ) + #trustText1 ("Largest Selection in the Carolinas")
#trustItem2 β Box (inline) β #trustIcon2 (β€οΈ) + #trustText2 ("Family Owned Since 1991")
#trustItem3 β Box (inline) β #trustIcon3 (π¨) + #trustText3 ("700+ Fabric Swatches")
#trustItem4 β Box (inline) β #trustIcon4 (π) + #trustText4 ("Free Shipping") β DISABLED, code skips this
#trustItem5 β Box (inline) β #trustIcon5 (π§€) + #trustText5 ("White Glove Delivery")</div>
<ul>
<li><strong>#trustBar</strong>: Full-width Box with espresso background (#3A2518). Items arranged horizontally, evenly spaced.</li>
<li><strong>Per item</strong>: Each is a Box containing an icon Text (emoji/Unicode) on the left and a label Text on the right, vertically centered.</li>
<li><strong>Item 4 is currently disabled</strong> β code skips it. You can include it in the editor but it won't be visible at runtime.</li>
<li><strong>Animation</strong>: Staggered fade-in β items appear one by one with 150ms gaps (200ms β 350ms β 500ms β 650ms delay). Each fades in over 300ms.</li>
<li><strong>Text color</strong>: White on espresso background. Code sets icon + text content at runtime.</li>
<li>This is a <strong>critical section</strong> (above-fold) β loads immediately.</li>
</ul>`, elements: [
["trustBar","Box","DONE - Espresso bg #3A2518"],
["trustItem1","Box","Trust signal container"],["trustIcon1","Text","Emoji icon"],["trustText1","Text","Signal text"],
["trustItem2","Box","Trust signal container"],["trustIcon2","Text","Emoji icon"],["trustText2","Text","Signal text"],
["trustItem3","Box","Trust signal container"],["trustIcon3","Text","Emoji icon"],["trustText3","Text","Signal text"],
["trustItem4","Box","Trust signal container (may be hidden)"],["trustIcon4","Text","Emoji icon"],["trustText4","Text","Signal text"],
["trustItem5","Box","Trust signal container"],["trustIcon5","Text","Emoji icon"],["trustText5","Text","Signal text"]
]},
{ name: "Testimonials", repeater: "testimonialRepeater", impl: `<h4>π¬ Implementation β Testimonials</h4>
<p><strong>Layout: Auto-rotating slideshow showing one testimonial at a time</strong></p>
<ul>
<li><strong>#testimonialSection</strong>: Section container. <span class="impl-warn">Collapses on mobile</span> via <code>collapseOnMobile()</code>.</li>
<li><strong>#testimonialSlideshow</strong>: Box that wraps the repeater β acts as a slideshow/carousel viewport. Only one slide visible at a time.</li>
<li><strong>#testimonialRepeater</strong>: Populated from CMS (or falls back to hardcoded testimonials). Each item is a slide.</li>
<li><strong>Per slide</strong>: Large quote text (top) β customer name (attribution) β optional photo β star rating (Unicode β stars).</li>
<li><strong>#testimonialPhoto</strong>: Conditionally shown β code calls <code>.show()</code> or <code>.hide()</code> based on whether a photo exists.</li>
<li><strong>#testimonialPauseBtn</strong>: Pause/play toggle button. Position in corner of section. ARIA label toggles between "Pause testimonial slideshow" / "Resume testimonial slideshow" (WCAG 2.2.2 compliance).</li>
<li><strong>#testimonialSchemaScript</strong>: Hidden HtmlComponent β code injects testimonial JSON-LD schema for SEO.</li>
<li><strong>Auto-rotation</strong>: Slides advance every 5 seconds. Pauses on mouse hover, resumes on mouse out.</li>
<li>This is a <strong>deferred section</strong> (below-fold) β loads during idle time.</li>
</ul>`, elements: [
["testimonialSection","Section","Container"],
["testimonialRepeater","Repeater","Rotating testimonials"],
["testimonialSchemaScript","HtmlComponent","SEO schema (code uses testimonialSchemaScript)"],
["testimonialSlideshow","Box","Slideshow wrapper"],
["testimonialPauseBtn","Button","Pause/play toggle"]
], children: [
["testimonialQuote","Text","Quote text"],
["testimonialName","Text","Customer name"],
["testimonialPhoto","Image","Customer photo"],
["testimonialRating","Text","Star rating"]
]},
{ name: "Recently Viewed", repeater: "recentRepeater", impl: `<h4>ποΈ Implementation β Recently Viewed</h4>
<p><strong>Layout: Horizontal scroll row of recently browsed products</strong></p>
<ul>
<li><strong>#recentSection</strong>: Collapsible Section. <span class="impl-warn">Collapsed by default</span> β code expands it only if the visitor has browsing history. If no history, stays collapsed.</li>
<li><strong>#recentRepeater</strong>: Horizontal scroll layout (like Sale Products). Populated from session browsing history.</li>
<li><strong>Per card</strong>: Image (top) β name β price β "Add to Cart" button (bottom).</li>
<li><strong>#recentAddToCart</strong>: Button states cycle: normal β "Adding..." β "Added!" β normal (2s delay).</li>
<li>Clicking image/name navigates to the product page.</li>
<li>ARIA region labeled "Recently viewed products".</li>
<li>Deferred section (below-fold).</li>
</ul>`, elements: [
["recentSection","Section","Collapsible"],
["recentRepeater","Repeater","Recently viewed products"]
], children: [
["recentImage","Image","Product image"],
["recentName","Text","Product name"],
["recentPrice","Text","Price"],
["recentAddToCart","Button","Add to cart"]
]},
{ name: "Continue Shopping", repeater: "continueShoppingRepeater", impl: `<h4>ποΈ Implementation β Continue Shopping</h4>
<p><strong>Layout: Section heading + horizontal scroll strip of recently viewed product cards</strong></p>
<ul>
<li><strong>#continueShoppingSection</strong>: Section or Box. <span class="impl-warn">Hidden/collapsed by default</span> β code expands it only if the visitor has browsing history. First-time visitors never see it.</li>
<li><strong>#continueShoppingTitle</strong>: Text heading β code sets it to "Continue Shopping".</li>
<li><strong>#continueShoppingRepeater</strong>: Horizontal scroll layout. Populated from session-backed product view history (last 1β6 products). No backend call.</li>
<li><strong>Per card</strong>: Image β name β price β link button. Clicking the link navigates to <code>/product-page/<slug></code>.</li>
<li>On PDPs, pass <code>excludeId</code> to hide the current product from the strip.</li>
<li>Deferred section (below-fold).</li>
</ul>`, elements: [
["continueShoppingSection","Section","Collapsed by default"],
["continueShoppingTitle","Text","Section heading"]
], children: [
["continueShoppingImage","Image","Product image"],
["continueShoppingName","Text","Product name"],
["continueShoppingPrice","Text","Price"],
["continueShoppingLink","Button","Navigate to product page"]
]},
{ name: "Video Showcase", impl: `<h4>π¬ Implementation β Video Showcase</h4>
<p><strong>Layout: Section header + 3 video thumbnails in a row + CTA</strong></p>
<ul>
<li><strong>#videoShowcaseSection</strong>: Collapsible Section. Expands if available, collapses gracefully on error.</li>
<li><strong>#videoShowcaseTitle</strong>: H2 heading β "See Our Furniture in Action".</li>
<li><strong>#videoShowcaseSubtitle</strong>: Subheading text below title.</li>
<li><strong>#videoThumb1/2/3</strong>: Three Image elements in a row (grid). Each is clickable β navigates to <code>/product-videos</code>. Made keyboard-accessible via <code>makeClickable()</code>.</li>
<li><strong>#viewAllVideosCTA</strong>: "View All Videos" button below thumbnails. Also navigates to <code>/product-videos</code>.</li>
<li>Optional deferred section (below-fold).</li>
</ul>`, elements: [
["videoShowcaseSection","Section","Collapsible"],
["videoShowcaseTitle","Text","Heading"],
["videoShowcaseSubtitle","Text","Subheading"],
["viewAllVideosCTA","Button","Videos page link"],
["videoThumb1","Image","Clickable video thumbnail"],
["videoThumb2","Image","Clickable video thumbnail"],
["videoThumb3","Image","Clickable video thumbnail"]
]},
{ name: "Smooth Scroll Triggers", impl: `<h4>β¬οΈ Implementation β Smooth Scroll Triggers</h4>
<p><strong>Layout: Anchor buttons placed in header/navigation area</strong></p>
<ul>
<li>These are navigation buttons (likely in the hero or header area) that smooth-scroll to specific sections on the page.</li>
<li><strong>#scrollToFeatured</strong> β scrolls to <code>#featuredRepeater</code></li>
<li><strong>#scrollToCategories</strong> β scrolls to <code>#categoryRepeater</code></li>
<li><strong>#scrollToSale</strong> β scrolls to <code>#saleSection</code></li>
<li><strong>#scrollToReviews</strong> β scrolls to <code>#testimonialRepeater</code></li>
<li>Can be styled as text links or small buttons. Keyboard accessible with ARIA labels.</li>
</ul>`, elements: [
["scrollToFeatured","Button","Scroll to featured"],
["scrollToCategories","Button","Scroll to categories"],
["scrollToSale","Button","Scroll to sale"],
["scrollToReviews","Button","Scroll to reviews"]
]},
{ name: "Quiz CTA", impl: `<h4>π§© Implementation β Quiz CTA</h4>
<p><strong>Layout: Simple centered call-to-action block</strong></p>
<ul>
<li><strong>#quizCTASection</strong>: Collapsible Section. Expands if available, collapses on error.</li>
<li><strong>#quizCTATitle</strong>: H2 heading β "Not Sure Where to Start?" (centered).</li>
<li><strong>#quizCTASubtitle</strong>: Description text below title (centered).</li>
<li><strong>#quizCTAButton</strong>: "Take the Style Quiz" CTA button. Navigates to <code>/style-quiz</code>.</li>
<li>Simple vertical stack: title β subtitle β button, all centered. Deferred section.</li>
</ul>`, elements: [
["quizCTASection","Section","Collapsible"],
["quizCTATitle","Text","Find Your Perfect Futon"],
["quizCTASubtitle","Text","Description"],
["quizCTAButton","Button","Start quiz"]
]},
{ name: "Swatch Promo", impl: `<h4>π¨ Implementation β Swatch Promo</h4>
<p><strong>Layout: Simple centered call-to-action block</strong></p>
<ul>
<li><strong>#swatchPromoSection</strong>: Section container. Expands if available.</li>
<li><strong>#swatchPromoTitle</strong>: H2 heading β "700+ Free Fabric Swatches".</li>
<li><strong>#swatchPromoSubtitle</strong>: Description text below title.</li>
<li><strong>#swatchPromoCTA</strong>: "Request Free Swatches" button. Navigates to <code>/free-swatches</code>.</li>
<li>Same simple vertical stack pattern as Quiz CTA. Deferred section.</li>
</ul>`, elements: [
["swatchPromoSection","Section","Container"],
["swatchPromoTitle","Text","Heading"],
["swatchPromoSubtitle","Text","Subheading"],
["swatchPromoCTA","Button","Order swatches"]
]},
{ name: "Blog Teasers", impl: `<h4>π° Implementation β Blog Teasers</h4>
<p><strong>Layout: HtmlComponent that displays a grid of 3 recent blog posts</strong></p>
<ul>
<li><strong>#blogTeaserSection</strong>: HtmlComponent element. Code sets <code>.html</code> property with a grid of 3 recent blog posts via <code>HomeBlogTeasers.js</code>.</li>
<li>Content is rendered as HTML inside the iframe β no direct child elements needed.</li>
<li>Data sourced from <code>blogService.web.js</code> backend module.</li>
</ul>`, elements: [
["blogTeaserSection","HtmlComponent","Blog post cards β 3 recent posts"]
]},
{ name: "Social Feeds", impl: `<h4>π± Implementation β Social Feeds</h4>
<p><strong>Layout: Three HtmlComponent embeds for social media feeds</strong></p>
<ul>
<li><strong>#instagramFeedContainer</strong>: HtmlComponent. Code injects Instagram embed iframe via <code>SocialFeedEmbed.js</code>.</li>
<li><strong>#tiktokFeedContainer</strong>: HtmlComponent. Code injects TikTok follow card via <code>SocialFeedEmbed.js</code>.</li>
<li><strong>#pinterestBoardContainer</strong>: HtmlComponent. Code injects Pinterest follow card via <code>SocialFeedEmbed.js</code>.</li>
<li>All three set the <code>.html</code> property to inject content into the HtmlComponent.</li>
</ul>`, elements: [
["instagramFeedContainer","HtmlComponent","Instagram embed iframe"],
["tiktokFeedContainer","HtmlComponent","TikTok follow card"],
["pinterestBoardContainer","HtmlComponent","Pinterest follow card"]
]},
{ name: "Newsletter", impl: `<h4>π§ Implementation β Newsletter</h4>
<p><strong>Layout: Heading + subtitle + inline email form + hidden success/error messages</strong></p>
<ul>
<li><strong>#newsletterSection</strong>: Section container.</li>
<li><strong>#newsletterTitle</strong>: H2 heading β "Join the Carolina Futons Family".</li>
<li><strong>#newsletterSubtitle</strong>: Subheading text below title.</li>
<li><strong>#newsletterEmail + #newsletterSubmit</strong>: Place side-by-side (inline on desktop). Email Input + Subscribe Button. Code validates email format before submission.</li>
<li><strong>#newsletterSuccess</strong>: Text element, <span class="impl-warn">hidden by default</span>. Code shows it after successful signup β displays discount code <code>WELCOME10</code>.</li>
<li><strong>#newsletterError</strong>: Text element, <span class="impl-warn">hidden by default</span>. Code shows it if validation fails or submission errors.</li>
<li>Submit button cycles: normal β "Submitting..." β normal. Tracks <code>newsletter_signup</code> analytics event.</li>
<li>Deferred section.</li>
</ul>`, elements: [
["newsletterSection","Section","Container"],
["newsletterTitle","Text","Heading"],
["newsletterSubtitle","Text","Subheading"],
["newsletterEmail","Input","Email field"],
["newsletterSubmit","Button","Subscribe"],
["newsletterSuccess","Text","Hidden success msg"],
["newsletterError","Text","Hidden error msg"]
]},
{ name: "Gift Card Section (PR #533)", impl: `<h4>π Implementation β Gift Card Section</h4>
<p><strong>CF-mwpw</strong>: A hero CTA section for gift cards. Add as a Section on the Home page.</p>
<ul>
<li><strong>#giftCardSection</strong>: Section or Box container. <span class="impl-warn">Code collapses this if gift cards are disabled</span> β hidden until gift card feature is active.</li>
<li><strong>#giftCardHeading</strong>: Text element. Code sets to "Give the gift of great furniture".</li>
<li><strong>#giftCardDesc</strong>: Text element. Code sets description copy.</li>
<li><strong>#giftCardBtn</strong>: Button element. Label "Shop Gift Cards" β onClick navigates to <code>/gift-cards</code>.</li>
</ul>`, elements: [
["giftCardSection","Section","Gift card CTA container β collapsed if feature disabled"],
["giftCardHeading","Text","'Give the gift of great furniture'"],
["giftCardDesc","Text","Gift card description copy"],
["giftCardBtn","Button","'Shop Gift Cards' β /gift-cards"]
]},
{ name: "SEO / Decorative", impl: `<h4>π Implementation β SEO / Decorative</h4>
<ul>
<li><strong>#websiteSchemaHtml</strong>: Hidden HtmlComponent. Code injects WebSite JSON-LD schema (Google sitelinks searchbox). Place anywhere on page β not visible to users.</li>
<li><strong>#ridgelineHeader</strong>: Decorative Box element. Code injects a static Blue Ridge mountain ridgeline SVG if the animated <code>#heroSkyline</code> version isn't available. This is a fallback β if you have <code>#heroSkyline</code> working, this serves as a secondary decorative element elsewhere on the page. Alt text: "Blue Ridge Mountain ridgeline decoration".</li>
<li><strong>#section4</strong>: Template "As Seen In" / press logos section. <span class="impl-warn">Code auto-collapses this</span> β it contains Tera template branding, not Carolina Futons content. Can be left as-is; code hides it.</li>
</ul>`, elements: [
["websiteSchemaHtml","HtmlComponent","SEO schema"],
["ridgelineHeader","Box","Mountain skyline"],
["section4","Section","Collapsible misc"]
]}
]
},
{
name: "masterPage (Global)", file: "masterPage.js", priority: "P0", est: "60 min",
sections: [
{ name: "Accessibility", impl: `<h4>βΏ Implementation β Accessibility</h4>
<p><strong>Layout: Invisible infrastructure elements β no visual presence</strong></p>
<ul>
<li><strong>#mainContent</strong>: The main content Section that <code>#skipToContent</code> jumps to. Place it as the first Section after the header/nav area. Code sets it as the skip-nav target.</li>
<li><strong>#skipToContent</strong>: A Button element positioned off-screen (or at the very top of the page, visually hidden). <span class="impl-warn">Must be the first focusable element on the page</span> β when a keyboard user presses Tab, this button appears and clicking it jumps focus to <code>#mainContent</code>.</li>
<li><strong>#a11yLiveRegion</strong>: A Text element, <span class="impl-warn">hidden from visual display but NOT collapsed</span> (screen readers must be able to read it). Code sets <code>role='status'</code>, <code>ariaLive='polite'</code>, <code>ariaAtomic=true</code>. Used to announce dynamic content changes (cart updates, filter results, etc.) to screen readers.</li>
</ul>
<p>Global Escape key handler: pressing Escape closes <code>#sideCartPanel</code> with a slide-right animation (200ms).</p>`, elements: [
["mainContent","Section","Skip-nav target"],
["skipToContent","Button","Skip navigation link"],
["a11yLiveRegion","Text","Hidden screen reader"]
]},
{ name: "Navigation", impl: `<h4>π§ Implementation β Navigation</h4>
<p><strong>Layout: Horizontal nav bar with logo, nav links, search, and mega menu</strong></p>
<div class="layer-diagram">STRUCTURE:
ββββββββββββββββββββββββββββ
#desktopNavBar β Box container (full-width, horizontal layout)
#siteLogo β Image (left-aligned, clickable β home)
#navHome β¦ #navFreeSwatches β Text links (horizontal row, centered)
#headerSearchInput β Input (right side, search icon)
#megaMenuPanel β Box (hidden, dropdown below nav on hover)</div>
<ul>
<li><strong>Nav links</strong> (<code>#navHome</code> through <code>#navFreeSwatches</code>): Each is a Text element. Code applies active state styling (<code>fontWeight</code> = bold from design token) when URL path matches the link's target. All are made keyboard-accessible via <code>makeClickable()</code>.</li>
<li><strong>#headerSearchInput</strong>: Input with <code>role='search'</code> and <code>ariaLabel='Search Carolina Futons'</code> set by code.</li>
<li><strong>#megaMenuPanel</strong>: <span class="impl-warn">Hidden by default</span>. Box that drops down below nav on category hover. Contains subcategory links.</li>
<li><strong>#productTitle</strong>: Hidden Text element used to pass current product context to LiveChat widget. Not visible to users.</li>
<li><strong>#desktopNavBar</strong>: The main nav container Box. Code may apply sticky behavior and shadow on scroll.</li>
</ul>`, elements: [
["navHome","Text","Nav link"],["navShop","Text","Nav link"],
["navFutonFrames","Text","Nav link"],["navMattresses","Text","Nav link"],
["navMurphy","Text","Nav link"],["navPlatformBeds","Text","Nav link"],
["navSale","Text","Nav link"],["navProductVideos","Text","Nav link"],
["navGettingItHome","Text","Nav link"],["navContact","Text","Nav link"],
["navFAQ","Text","Nav link"],["navAbout","Text","Nav link"],
["navBlog","Text","Nav link"],["navFreeSwatches","Text","Nav link"],
["siteLogo","Image","Logo"],
["headerSearchInput","Input","Search bar"],
["megaMenuPanel","Box","Mega menu dropdown"],
["desktopNavBar","Box","Desktop nav container"],
["productTitle","Text","LiveChat context"]
]},
{ name: "Mobile Drawer", impl: `<h4>π± Implementation β Mobile Drawer</h4>
<p><strong>Layout: Full-height side panel (slide-in from left or right) with overlay backdrop</strong></p>
<div class="layer-diagram">LAYER ORDER (bottom β top):
ββββββββββββββββββββββββββββ
β Page content (behind overlay)
β‘ #mobileMenuOverlay β Full-screen Box (semi-transparent backdrop)
β’ Drawer panel (inside overlay)
#mobileMenuClose β Close button (top-right)
#mobileSearchInput β Search input (below close)
#mobileNavHome β¦ #mobileNavAbout β Nav links (vertical stack)</div>
<ul>
<li><strong>#mobileMenuButton</strong>: Hamburger toggle Button in the header. <span class="impl-warn">Only initialized on mobile</span> β code checks <code>isMobile()</code> before wiring up the drawer.</li>
<li><strong>#mobileMenuOverlay</strong>: Full-screen Box, <span class="impl-warn">hidden by default</span>. Acts as both backdrop and drawer container. Code applies focus trap (keyboard can't escape the drawer) and scroll lock on body when open.</li>
<li><strong>#mobileMenuClose</strong>: Close Button inside the drawer. Escape key also closes.</li>
<li><strong>Mobile nav links</strong>: Vertical stack of Text elements mirroring desktop nav. Each navigates to its page.</li>
<li><strong>Animation</strong>: Slide animation on open/close (~300ms). Focus restores to hamburger button on close.</li>
</ul>`, elements: [
["mobileMenuButton","Button","Hamburger toggle"],
["mobileMenuOverlay","Box","Full-screen drawer"],
["mobileMenuClose","Button","Close drawer"],
["mobileSearchInput","Input","Mobile search"],
["mobileNavHome","Text","Mobile nav"],["mobileNavShop","Text","Mobile nav"],
["mobileNavFutonFrames","Text","Mobile nav"],["mobileNavMattresses","Text","Mobile nav"],
["mobileNavMurphy","Text","Mobile nav"],["mobileNavPlatformBeds","Text","Mobile nav"],
["mobileNavSale","Text","Mobile nav"],["mobileNavContact","Text","Mobile nav"],
["mobileNavFAQ","Text","Mobile nav"],["mobileNavAbout","Text","Mobile nav"]
]},
{ name: "Cart (global)", impl: `<h4>π Implementation β Cart (global)</h4>
<p><strong>Layout: Cart icon with badge overlay in header + off-canvas side cart panel</strong></p>
<div class="layer-diagram">STRUCTURE:
ββββββββββββββββββββββββββββ
Header area:
#cartIcon β Image (clickable, opens side cart)
#cartBadge β Text (positioned OVER cart icon, top-right corner)
Off-canvas (right side):
#sideCartPanel β Box (dialog, slides in from right)
#justAddedHighlight β Box (flash highlight for newly added item)</div>
<ul>
<li><strong>#cartIcon</strong>: Clickable Image in the header. Code sets <code>ariaLabel='Shopping cart'</code>. Clicking opens <code>#sideCartPanel</code> with a slide-right animation (300ms).</li>
<li><strong>#cartBadge</strong>: Text element positioned absolutely over the cart icon (top-right). <span class="impl-warn">Hidden when cart is empty (0 items)</span>. Code updates text with item count on every cart change.</li>
<li><strong>#sideCartPanel</strong>: Off-canvas Box panel on the right side. <span class="impl-warn">Hidden by default</span>. Code sets <code>role='dialog'</code>, <code>ariaModal=true</code>. Opens via slide animation, closes via Escape key or overlay click.</li>
<li><strong>#justAddedHighlight</strong>: Box inside the side cart that flashes (fade 200ms in, 300ms out after 3s delay) when a new item is added. Only triggers on item additions, not removals.</li>
</ul>
<p>Cart badge and auto-open use a shared cart fetch (<code>getSharedCart()</code>) to avoid duplicate API calls.</p>`, elements: [
["cartIcon","Image","Cart icon clickable"],
["cartBadge","Text","Item count badge"],
["sideCartPanel","Box","Slide-in panel"],
["justAddedHighlight","Box","Just-added animation"]
]},
{ name: "Header Shipping Progress", impl: `<h4>π Implementation β Header Shipping Progress</h4>
<p><strong>Layout: Progress bar + status text in header area</strong></p>
<ul>
<li><strong>#headerShippingBar</strong>: ProgressBar element. Code sets <code>value</code> (0-100%) based on cart subtotal vs $999 free shipping threshold. ARIA attributes set: <code>ariaLabel</code>, <code>ariaValueNow</code>, <code>ariaValueMin=0</code>, <code>ariaValueMax=100</code>.</li>
<li><strong>#headerShippingText</strong>: Text below/beside the bar. Dynamically shows "$X away from free shipping!" or "You qualify for FREE shipping!". Code sets <code>ariaLive='polite'</code> for screen reader announcements.</li>
<li><strong>#headerSkyline</strong>: Decorative Box for mountain skyline SVG. Code injects the skyline graphic.</li>
</ul>
<p>Updates automatically on every cart change via <code>onCartChanged()</code> listener. No animations β values update instantly.</p>`, elements: [
["headerShippingBar","ProgressBar","Free shipping progress"],
["headerShippingText","Text","$X away from free shipping"],
["headerSkyline","Box","Mountain skyline"]
]},
{ name: "Schema", impl: `<h4>π Implementation β Schema</h4>
<p><strong>Layout: Two hidden HtmlComponent elements β no visual presence</strong></p>
<ul>
<li><strong>#businessSchemaHtml</strong>: Hidden HtmlComponent. Code injects LocalBusiness JSON-LD schema (address, phone, hours) via <code>postMessage()</code>. Place anywhere on the page β not visible to users.</li>
<li><strong>#websiteSchemaHtml</strong>: Hidden HtmlComponent. Code injects WebSite JSON-LD schema with SearchAction (enables Google sitelinks searchbox). Also injected via <code>postMessage()</code>.</li>
</ul>
<p>Both are async operations. Code also injects a canonical URL via <code>wix-seo-frontend</code> that strips query parameters (filters, sort) to prevent duplicate content indexing.</p>`, elements: [
["businessSchemaHtml","HtmlComponent","Business schema"],
["websiteSchemaHtml","HtmlComponent","Website schema"]
]},
{ name: "Breadcrumbs", impl: `<h4>π Implementation β Breadcrumbs</h4>
<p><strong>Layout: Horizontal "Home > Category > Page" navigation trail</strong></p>
<ul>
<li><strong>#breadcrumb1, #breadcrumb2, #breadcrumb3</strong>: Three Text elements in a horizontal row. Code populates them from the current URL path hierarchy. Each is made keyboard-accessible and clickable (navigates to that level). If a level doesn't exist, the element is hidden.</li>
<li><strong>#breadcrumbSchemaHtml</strong>: Hidden HtmlComponent. Code injects BreadcrumbList JSON-LD schema for SEO. Not visible to users.</li>
</ul>
<p>Built automatically from the current URL path segments. Active (current) page breadcrumb is styled differently (not clickable). Code is delegated to <code>navigationHelpers.renderBreadcrumbs()</code>.</p>`, elements: [
["breadcrumb1","Text","Breadcrumb level 1"],
["breadcrumb2","Text","Breadcrumb level 2"],
["breadcrumb3","Text","Breadcrumb level 3"],
["breadcrumbSchemaHtml","HtmlComponent","Breadcrumb JSON-LD"]
]},
{ name: "Announcement Bar", impl: `<h4>π’ Implementation β Announcement Bar</h4>
<p><strong>Layout: Fixed full-width bar at top of page with rotating messages</strong></p>
<ul>
<li><strong>#announcementBar</strong>: Full-width Box fixed at the top of the page. Espresso or dark background.</li>
<li><strong>#announcementText</strong>: Text element inside the bar. Code sets <code>role='status'</code>, <code>ariaLive='polite'</code>. Messages rotate every 5 seconds (500ms fade, 4.5s display):
<br>β’ "Visit Our Showroom: Wed-Sat 10-5 | 824 Locust St, Hendersonville NC"
<br>β’ "Over 700 Fabric Swatches Available In-Store"
<br>β’ "Request FREE fabric swatches - shipped to your door!"
<br>β’ "Family Owned Since 1991 - Carolina Futons"
<br>Flash sale messages are prepended dynamically (urgent promos appear first).</li>
<li><strong>#announcementBarLink</strong>: Button/Link. <span class="impl-warn">Hidden by default</span> β shown only when the active CMS bar has a <code>linkUrl</code> (HTTPS-only; HTTP URLs are rejected). Href set to the CMS <code>linkUrl</code> value. Hidden when no linkUrl present. <strong>NEW PR #658 / CF-qw65.</strong></li>
<li><strong>#announcementDismiss</strong>: Dismiss Button (X) to close the bar. Sets session flag so it won't reappear.</li>
</ul>
<p><strong>Animation</strong>: Text fades between messages every 5 seconds. Bar itself is static.</p>`, elements: [
["announcementBar","Box","Announcement container"],
["announcementText","Text","Announcement text"],
["announcementBarLink","Button","CTA link β shown when CMS bar has linkUrl (HTTPS-only)"],
["announcementDismiss","Button","Dismiss button"]
]},
{ name: "Sticky Nav / Back to Top", impl: `<h4>π Implementation β Sticky Nav / Back to Top</h4>
<p><strong>Layout: Sticky header with scroll shadow + fixed back-to-top button</strong></p>
<ul>
<li><strong>#headerStrip</strong>: Box element wrapping the header/nav. Code applies sticky positioning and adds a box-shadow when the user scrolls down (visual depth cue). Shadow disappears when scrolled back to top.</li>
<li><strong>#backToTop</strong>: Button element, <span class="impl-warn">hidden by default</span>. Positioned fixed at the bottom-right corner. Code shows it when the user scrolls past a threshold and hides it when back at the top. Clicking scrolls smoothly to the top of the page.</li>
</ul>
<p>Both are scroll-triggered behaviors managed by helper modules.</p>`, elements: [
["headerStrip","Box","Header for sticky nav"],
["backToTop","Button","Back-to-top button"]
]},
{ name: "Promo Lightbox", repeater: "promoRepeater", impl: `<h4>π Implementation β Promo Lightbox</h4>
<p><strong>Layout: Centered modal dialog over semi-transparent overlay</strong></p>
<div class="layer-diagram">LAYER ORDER (bottom β top):
ββββββββββββββββββββββββββββ
β Page content (behind overlay)
β‘ #promoOverlay β Full-screen Box (rgba overlay, clickable to close)
β’ #promoLightbox β Centered modal Box (high z-index, shadow)
#promoClose β Close X button (top-right)
#promoHeroImage β Large banner image (top)
#promoTitle β Promotion headline
#promoSubtitle β Subheading
#promoCode β Discount code display
#promoCopyCode β Copy code button
#promoCountdown β Countdown timer text
#promoRepeater β Product carousel (3-5 products)
#promoEmailInput β Email input
#promoEmailSubmit β Submit email button
#promoCTA β Main CTA button
#promoDismiss β "No thanks" button</div>
<ul>
<li><span class="impl-warn">All elements hidden by default</span> β modal appears 3 seconds after page load (only if a promotion exists in backend).</li>
<li><strong>Overlay</strong>: Fade in 300ms, fade out 200ms. Full-screen, semi-transparent.</li>
<li><strong>Lightbox</strong>: Uses <code>setupAccessibleDialog()</code> for focus trap + Escape-to-close.</li>
<li><strong>#promoCountdown</strong>: Updates every 1 second (text only, no animation).</li>
<li><strong>#promoCopyCode</strong>: Copies code to clipboard. Label changes to "Copied!" on success.</li>
<li><strong>#promoEmailSubmit</strong>: Label changes to "Subscribed!" on success. Integrates with Wix CRM.</li>
<li><strong>Product carousel</strong>: Each card has image, name, price (original + discounted), quick-add button.</li>
<li>Session-dismissed: won't re-show in the same session (uses <code>sessionStorage</code>).</li>
</ul>`, elements: [
["promoLightbox","Box","Modal dialog"],
["promoOverlay","Box","Background overlay"],
["promoClose","Button","Close X"],
["promoDismiss","Button","No thanks"],
["promoTitle","Text","Heading"],
["promoSubtitle","Text","Subheading"],
["promoHeroImage","Image","Banner image"],
["promoCode","Text","Discount code"],
["promoCopyCode","Button","Copy code"],
["promoCTA","Button","Shop now"],
["promoCountdown","Text","Timer"],
["promoRepeater","Repeater","Featured promo products"],
["promoEmailInput","Input","Email capture"],
["promoEmailSubmit","Button","Submit email"]
], children: [
["promoImage","Image","Product image"],
["promoName","Text","Product name"],
["promoPrice","Text","Price"],
["promoOrigPrice","Text","Original price"],
["promoQuickAdd","Button","Quick add"]
]},
{ name: "Newsletter Modal", impl: `<h4>π§ Implementation β Newsletter Modal</h4>
<p><strong>Layout: Overlay + centered modal dialog with email capture</strong></p>
<ul>
<li><strong>#newsletterModalTrigger</strong>: CTA Button placed anywhere (hero, footer, etc.) that opens the modal on click.</li>
<li><strong>#newsletterModalOverlay</strong>: Full-screen Box backdrop, <span class="impl-warn">hidden by default</span>. Fades in 300ms, out 200ms.</li>
<li><strong>#newsletterModal</strong>: Centered modal Box on top of overlay. Uses <code>setupAccessibleDialog()</code> for focus trap + Escape-to-close.</li>
<li><strong>#newsletterModalClose</strong>: Close X Button (top-right of modal).</li>
<li><strong>#newsletterModalEmail + #newsletterModalSubmit</strong>: Email Input + Subscribe Button (side-by-side or stacked). Code validates email format (RFC 5322).</li>
<li><strong>#newsletterModalSuccess</strong>: <span class="impl-warn">Hidden by default</span>. Shows "Use code WELCOME10 for 10% off your first order!" on successful signup. Fades in (300ms), then modal auto-closes after 4 seconds.</li>
<li><strong>#newsletterModalError</strong>: <span class="impl-warn">Hidden by default</span>. Shows on email validation failure.</li>
</ul>
<p>Won't show again if already subscribed in current session. Submits to backend + Wix CRM.</p>`, elements: [
["newsletterModalTrigger","Button","Open modal"],
["newsletterModal","Box","Modal panel"],
["newsletterModalClose","Button","Close X"],
["newsletterModalOverlay","Box","Background overlay"],
["newsletterModalEmail","Input","Email field"],
["newsletterModalSubmit","Button","Subscribe"],
["newsletterModalError","Text","Error msg"],
["newsletterModalSuccess","Text","Success msg"]
]},
{ name: "Exit Intent Popup", impl: `<h4>πͺ Implementation β Exit Intent Popup</h4>
<p><strong>Layout: Desktop = centered modal over overlay. Mobile = bottom sheet sliding up.</strong></p>
<div class="layer-diagram">DESKTOP:
ββββββββββββββββββββββββββββ
β‘ #exitOverlay β Full-screen semi-transparent backdrop
β’ #exitIntentPopup β Centered modal (constrained width, shadow)
#exitClose β Close X (top-right)
#exitTitle β Heading
#exitSubtitle β Subheading
#exitEmailInput β Email input
#exitEmailSubmit β Submit button
#exitSwatchLink β Alt CTA ("Request Free Fabric Swatches")
MOBILE:
ββββββββββββββββββββββββββββ