kamisaku 0.3.3 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +17 -0
  3. data/Gemfile.lock +1 -1
  4. data/README.md +28 -64
  5. data/examples/birthday_invitation/dino/invitation.pdf +0 -0
  6. data/examples/resume/chromatic/example.pdf +0 -0
  7. data/examples/resume/gradient/example.pdf +0 -0
  8. data/examples/resume/meridian/example.pdf +0 -0
  9. data/examples/resume/paper/example.pdf +0 -0
  10. data/examples/resume/prism/example.pdf +0 -0
  11. data/examples/resume/sleek/example.pdf +0 -0
  12. data/examples/resume/zenith/example.pdf +0 -0
  13. data/lib/kamisaku/arg_parser.rb +4 -0
  14. data/lib/kamisaku/cli_runner.rb +2 -2
  15. data/lib/kamisaku/content_validators/base_content_validator.rb +14 -0
  16. data/lib/kamisaku/content_validators/birthday_invitation_content_validator.rb +218 -0
  17. data/lib/kamisaku/{content_validator.rb → content_validators/resume_content_validator.rb} +28 -11
  18. data/lib/kamisaku/html_builder.rb +4 -3
  19. data/lib/kamisaku/pdf.rb +17 -12
  20. data/lib/kamisaku/template_helpers.rb +0 -2
  21. data/lib/kamisaku/version.rb +1 -1
  22. data/lib/kamisaku.rb +4 -2
  23. data/lib/schema/birthday_invitation/example.yml +45 -0
  24. data/lib/schema/birthday_invitation/schema.yml +40 -0
  25. data/lib/schema/resume/example.yml +274 -0
  26. data/lib/schema/resume/schema.yml +112 -0
  27. data/lib/templates/birthday_invitation/dino/template.html.erb +486 -0
  28. data/lib/templates/resume/chromatic/template.html.erb +275 -0
  29. data/lib/templates/resume/gradient/template.html.erb +793 -0
  30. data/lib/templates/resume/meridian/template.html.erb +535 -0
  31. data/lib/templates/resume/paper/template.html.erb +525 -0
  32. data/lib/templates/resume/prism/template.html.erb +818 -0
  33. data/lib/templates/{sleek → resume/sleek}/template.html.erb +1 -1
  34. data/lib/templates/resume/zenith/template.html.erb +546 -0
  35. data/scripts/rebuild_examples.rb +45 -0
  36. metadata +25 -9
  37. data/examples/paper/john_doe.pdf +0 -0
  38. data/examples/paper/john_doe.yml +0 -157
  39. data/examples/sleek/john_doe.pdf +0 -0
  40. data/examples/sleek/john_doe.yml +0 -157
  41. data/lib/templates/paper/template.html.erb +0 -420
  42. data/template.yml +0 -64
@@ -0,0 +1,486 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Birthday Party Invitation</title>
7
+ <style>
8
+ @import url('https://fonts.googleapis.com/css2?family=Fredoka+One:wght@400&family=Nunito:wght@400;600;700&display=swap');
9
+
10
+ * {
11
+ margin: 0;
12
+ padding: 0;
13
+ box-sizing: border-box;
14
+ }
15
+
16
+ /* Base print and preview styles */
17
+ @page {
18
+ margin: 0;
19
+ width: 5in;
20
+ height: 7in;
21
+ }
22
+
23
+ @media screen {
24
+ body {
25
+ background: #f8fafc;
26
+ }
27
+ .paper {
28
+ box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
29
+ }
30
+ }
31
+
32
+ @media screen, print {
33
+ .paper {
34
+ background: white;
35
+ margin: 0 auto;
36
+ width: 5in;
37
+ height: 7in;
38
+ }
39
+ }
40
+
41
+ .paper {
42
+ background: linear-gradient(135deg, #C8E6C9 0%, #A5D6A7 50%, #81C784 100%);
43
+ font-family: 'Nunito', sans-serif;
44
+ color: #2E7D32;
45
+ position: relative;
46
+ overflow: hidden;
47
+ }
48
+
49
+ .invitation-container {
50
+ width: 100%;
51
+ height: 100%;
52
+ position: relative;
53
+ background: rgba(255, 255, 255, 0.95);
54
+ border-radius: 20px;
55
+ border: 4px solid #4CAF50;
56
+ box-shadow: 0 8px 16px rgba(0,0,0,0.1);
57
+ padding: 0.3in;
58
+ display: flex;
59
+ flex-direction: column;
60
+ justify-content: space-between;
61
+ }
62
+
63
+ .decoration-top-right {
64
+ position: absolute;
65
+ top: 0.1in;
66
+ right: -0.4in;
67
+ width: 200px;
68
+ height: 200px;
69
+ transform: scalex(-1);
70
+ z-index: 10;
71
+ }
72
+
73
+ /* Decorative dinosaurs */
74
+ .dino-top-left {
75
+ position: absolute;
76
+ top: -0.1in;
77
+ left: -0.4in;
78
+ width: 200px;
79
+ height: auto;
80
+ transform: rotate(-10deg) scalex(-1);
81
+ z-index: 10;
82
+ }
83
+
84
+ .dino-bottom-right {
85
+ position: absolute;
86
+ bottom: -0.8in;
87
+ right: 1.1in;
88
+ width: 55px;
89
+ height: auto;
90
+ transform: rotate(-15deg);
91
+ z-index: 10;
92
+ }
93
+
94
+ /* Balloons */
95
+ .balloon {
96
+ position: absolute;
97
+ font-size: 1.5em;
98
+ animation: float 3s ease-in-out infinite;
99
+ z-index: 5;
100
+ }
101
+
102
+ .balloon-1 { top: 1.2in; left: 0.8in; animation-delay: 0s; color: #E91E63; }
103
+ .balloon-2 { top: 1.8in; right: 0.6in; animation-delay: 1s; color: #2196F3; }
104
+ .balloon-3 { bottom: 2.5in; left: 0.5in; animation-delay: 2s; color: #FF9800; }
105
+ .balloon-4 { top: 2.8in; right: 1in; animation-delay: 1.5s; color: #9C27B0; }
106
+
107
+ /* Tropical leaves */
108
+ .leaf {
109
+ position: absolute;
110
+ font-size: 1.8em;
111
+ color: #2E7D32;
112
+ z-index: 1;
113
+ opacity: 0.7;
114
+ }
115
+
116
+ .leaf-1 { top: 0.5in; left: 1.5in; transform: rotate(-20deg); }
117
+ .leaf-2 { top: 1.5in; right: 1.2in; transform: rotate(45deg); }
118
+ .leaf-3 { bottom: 1in; left: 1in; transform: rotate(-45deg); }
119
+ .leaf-4 { bottom: 2.5in; right: 0.3in; transform: rotate(30deg); }
120
+
121
+ /* Stars decoration */
122
+ .star {
123
+ position: absolute;
124
+ color: #FFD700;
125
+ font-size: 0.8em;
126
+ animation: twinkle 2s infinite;
127
+ z-index: 5;
128
+ }
129
+
130
+ .star-1 { top: 1.2in; left: 2.2in; animation-delay: 0s; }
131
+ .star-2 { top: 3in; left: 3.8in; animation-delay: 0.7s; }
132
+ .star-3 { top: 4.5in; left: 1.8in; animation-delay: 1.4s; }
133
+ .star-4 { top: 5.8in; left: 3.5in; animation-delay: 2.1s; }
134
+
135
+ @keyframes twinkle {
136
+ 0%, 100% { opacity: 1; transform: scale(1); }
137
+ 50% { opacity: 0.5; transform: scale(1.2); }
138
+ }
139
+
140
+ /* Typography */
141
+ .header {
142
+ text-align: center;
143
+ margin-bottom: 0.15in;
144
+ z-index: 20;
145
+ position: relative;
146
+ }
147
+
148
+ .title {
149
+ font-family: 'Fredoka One', cursive;
150
+ font-size: 22px;
151
+ color: #FF6B35;
152
+ text-shadow: 2px 2px 4px rgba(0,0,0,0.1);
153
+ margin-bottom: 5px;
154
+ line-height: 1.1;
155
+ }
156
+
157
+ .child-name {
158
+ font-family: 'Fredoka One', cursive;
159
+ font-size: 26px;
160
+ color: #FF5722;
161
+ text-shadow: 2px 2px 4px rgba(0,0,0,0.1);
162
+ margin-bottom: 3px;
163
+ }
164
+
165
+ .age {
166
+ font-size: 18px;
167
+ color: #E65100;
168
+ font-weight: 700;
169
+ }
170
+
171
+ /* Content sections */
172
+ .content {
173
+ flex: 1;
174
+ display: flex;
175
+ flex-direction: column;
176
+ justify-content: center;
177
+ z-index: 20;
178
+ position: relative;
179
+ margin: 0.1in 0;
180
+ }
181
+
182
+ .info-section {
183
+ background: rgba(255, 255, 255, 0.9);
184
+ border-radius: 12px;
185
+ padding: 10px;
186
+ margin: 6px 0;
187
+ border: 2px solid #4CAF50;
188
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
189
+ }
190
+
191
+ .info-label {
192
+ font-weight: 700;
193
+ color: #2E7D32;
194
+ font-size: 13px;
195
+ display: block;
196
+ margin-bottom: 3px;
197
+ }
198
+
199
+ .info-value {
200
+ color: #1B5E20;
201
+ font-size: 12px;
202
+ line-height: 1.4;
203
+ }
204
+
205
+ .theme-highlight {
206
+ background: linear-gradient(135deg, #FFF3E0 0%, #FFE0B2 100%);
207
+ border: 2px solid #FF8F00;
208
+ text-align: center;
209
+ font-weight: 700;
210
+ color: #E65100;
211
+ }
212
+
213
+ .rsvp-section {
214
+ background: linear-gradient(135deg, #FCE4EC 0%, #F8BBD9 50%);
215
+ border: 2px solid #E91E63;
216
+ text-align: center;
217
+ margin-top: 0.1in;
218
+ z-index: 20;
219
+ }
220
+
221
+ .footer-deco {
222
+ text-align: center;
223
+ font-size: 1.2em;
224
+ margin-top: 8px;
225
+ z-index: 20;
226
+ position: relative;
227
+ color: #4CAF50;
228
+ }
229
+
230
+ /* Print optimizations */
231
+ @media print {
232
+ body {
233
+ margin: 0;
234
+ -webkit-print-color-adjust: exact;
235
+ color-adjust: exact;
236
+ }
237
+ }
238
+ </style>
239
+ </head>
240
+ <body>
241
+ <div class="paper">
242
+ <div class="invitation-container">
243
+ <!-- Decorative dinosaur images -->
244
+ <div class="dino-top-left">
245
+ <?xml version="1.0" encoding="iso-8859-1"?>
246
+ <!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
247
+ <svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
248
+ viewBox="0 0 382.325 382.325" xml:space="preserve">
249
+ <g id="XMLID_800_">
250
+ <path id="XMLID_801_" style="fill:#DD916F;" d="M182.966,228.544v36h-4c-6.6,0-12,5.4-12,12c0,6.6,5.4,12,12,12h4h24v-24v-36
251
+ H182.966z"/>
252
+ <g id="XMLID_802_">
253
+
254
+ <rect id="XMLID_52_" x="221.674" y="222.703" transform="matrix(0.8321 -0.5547 0.5547 0.8321 -100.9291 172.0605)" style="fill:#DD916F;" width="24" height="60"/>
255
+ <path id="XMLID_51_" style="fill:#DD916F;" d="M246.987,251.039l-23.297,15.532c-5.492,3.661-6.989,11.149-3.328,16.641
256
+ c3.661,5.492,11.149,6.989,16.641,3.328l23.297-15.532L246.987,251.039z"/>
257
+ </g>
258
+ <polygon id="XMLID_803_" style="fill:#D87D60;" points="191.163,228.544 191.163,288.544 206.966,288.544 206.966,264.544
259
+ 206.966,228.544 "/>
260
+ <path id="XMLID_804_" style="fill:#D87D60;" d="M203.078,124.128c-9.166,0-16.59,2.153-22.696,5.62
261
+ c-1.335-5.063-1.692-9.868-1.692-12.65c0-9.402,17.057-23.317,23.007-23.317c5.949,0,23.006,13.915,23.006,23.317
262
+ c0,2.789-0.359,7.609-1.701,12.684C217.433,126.322,211.146,124.128,203.078,124.128z"/>
263
+ <path id="XMLID_805_" style="fill:#D46C5B;" d="M201.697,93.781c-2.354,0-6.447,2.183-10.535,5.398v26.329
264
+ c3.613-0.882,7.562-1.381,11.916-1.381c8.068,0,14.355,2.194,19.924,5.654c1.343-5.075,1.701-9.896,1.701-12.685
265
+ C224.704,107.696,207.647,93.781,201.697,93.781z"/>
266
+ <path id="XMLID_46_" style="fill:#D46C5B;" d="M238.713,136.213c-6.482-6.482-13.253-10.208-20.022-12.075
267
+ c2.636-4.524,5.781-8.174,7.749-10.141c6.648-6.648,28.549-4.426,32.756-0.219c4.207,4.207,6.429,26.107-0.219,32.755
268
+ c-1.972,1.972-5.634,5.127-10.172,7.766C247.311,147.914,244.417,141.917,238.713,136.213z"/>
269
+ <path id="XMLID_45_" style="fill:#D46C5B;" d="M264.213,166.213c-6.482-6.482-13.253-10.208-20.022-12.075
270
+ c2.636-4.524,5.781-8.174,7.749-10.141c6.648-6.648,28.549-4.426,32.756-0.219c4.207,4.207,6.429,26.107-0.219,32.755
271
+ c-1.972,1.972-5.634,5.127-10.172,7.766C272.812,177.914,269.918,171.917,264.213,166.213z"/>
272
+ <path id="XMLID_44_" style="fill:#D46C5B;" d="M290.847,185.83c-3.935-3.936-8.047-6.198-12.157-7.331
273
+ c1.6-2.747,3.51-4.963,4.705-6.158c4.036-4.036,17.334-2.687,19.889-0.133c2.554,2.554,3.903,15.852-0.133,19.888
274
+ c-1.197,1.197-3.421,3.113-6.176,4.715C296.068,192.935,294.311,189.294,290.847,185.83z"/>
275
+ <path id="XMLID_43_" style="fill:#D87D60;" d="M165.12,134.259c-6.482,6.482-10.208,13.253-12.075,20.023
276
+ c-4.524-2.636-8.174-5.781-10.141-7.749c-6.648-6.648-4.426-28.549-0.219-32.756c4.207-4.207,26.107-6.429,32.755,0.219
277
+ c1.972,1.972,5.127,5.634,7.766,10.172C176.822,125.66,170.825,128.554,165.12,134.259z"/>
278
+ <path id="XMLID_42_" style="fill:#D87D60;" d="M134.156,153.693c-5.209,5.209-8.203,10.65-9.703,16.09
279
+ c-3.635-2.118-6.569-4.646-8.15-6.227c-5.342-5.342-3.557-22.941-0.176-26.322c3.381-3.381,20.98-5.166,26.322,0.176
280
+ c1.585,1.585,4.12,4.527,6.241,8.174C143.559,146.783,138.74,149.108,134.156,153.693z"/>
281
+ <g id="XMLID_806_">
282
+ <path id="XMLID_41_" style="fill:#DD916F;" d="M128.159,212.031c-0.909,1.035-8.937,10.623-11.007,28.292
283
+ c-1.939,16.551,1.542,23.371,4.805,26.177c3.538,3.043,8.87,2.642,11.913-0.895c2.664-3.097,0.445-6.75,0.278-10.679
284
+ c-1.15-27.024,15.928-25.551,16.153-25.82l-9.444-5.929L128.159,212.031z"/>
285
+ </g>
286
+ <path id="XMLID_39_" style="fill:#DD916F;" d="M55.199,115.9c1.58,16.485,11.641,2.603,34.471,20s31.966,16.843,39.02,13.882
287
+ c37.37-15.686,43.5-38,88.632-30c44.701,7.924,46.089,37.5,57.017,50c24.166,27.642,84.576,5.667,104.252,40.149
288
+ c12.588,22.061-10.818,62.436-9.223,49.851c5.068-40-4.947-53.314-38.012-50s-57.6,21.657-85.526,33.125
289
+ c-42.784,17.569-93.466-2.431-110.214-16.569c-28.501-24.059-65.46-62.39-80.417-60.733c-14.958,1.657-28.713,5.4-37.438,4.177
290
+ c-7.803-1.094-26.441-8.319-13.058-20.745S53.238,95.449,55.199,115.9z"/>
291
+ <g id="XMLID_807_">
292
+ <path id="XMLID_38_" style="fill:#DD916F;" d="M111.653,189.782c-1.174,0.773-11.663,8.04-18.474,24.867
293
+ c-6.379,15.763-4.795,23.415-2.343,27.057c2.66,3.95,8.015,4.995,11.964,2.337c3.458-2.328,2.262-6.522,3.158-10.434
294
+ c6.168-26.904,22.576-20.841,22.87-21.045l-7.692-8.386L111.653,189.782z"/>
295
+ </g>
296
+ <circle id="XMLID_36_" style="fill:#FFE477;" cx="193.104" cy="162.159" r="10"/>
297
+ <path id="XMLID_808_" style="fill:#D87D60;" d="M378.591,209.931c-19.676-34.482-80.086-12.507-104.252-40.149
298
+ c-10.928-12.5-12.316-42.076-57.017-50c-10.553-1.871-18.973-2.083-26.159-1.111v129.743c17.572,2.602,36.805,1.828,54.668-5.507
299
+ c27.926-11.468,52.462-29.811,85.526-33.125c33.064-3.314,43.08,10,38.012,50C367.773,272.368,391.179,231.992,378.591,209.931z"/>
300
+ <circle id="XMLID_34_" style="fill:#F6E277;" cx="225.999" cy="149.199" r="15"/>
301
+ <circle id="XMLID_33_" style="fill:#F6E277;" cx="248.688" cy="179.78" r="10"/>
302
+ <path id="XMLID_809_" d="M44.69,137.782c-3.309,0-6,2.691-6,6s2.691,6,6,6s6-2.691,6-6S47.999,137.782,44.69,137.782z"/>
303
+ <path id="XMLID_810_" style="fill:#F6E277;" d="M202.833,159.846c-1.248-5.249-6.423-8.527-11.671-7.484v19.6
304
+ c1.367,0.272,2.81,0.27,4.255-0.073C200.791,170.611,204.111,165.219,202.833,159.846z"/>
305
+ </g>
306
+ </svg>
307
+ </div>
308
+
309
+ <div class="dino-bottom-right">
310
+ <?xml version="1.0" encoding="iso-8859-1"?>
311
+ <!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
312
+ <svg height="200px" width="200px" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
313
+ viewBox="0 0 353.123 353.123" xml:space="preserve">
314
+ <g id="XMLID_463_">
315
+ <path id="XMLID_464_" style="fill:#D570A7;" d="M104.581,57.7c4.223,21.21,10.669,46.599,20.944,69.996
316
+ c5.562-2.582,13.012-11.275,10.552-16.799c-1.799-4.038-8.399-5.271-14.023-4.704c5.212-3.253,10.759-9.974,8.939-14.812
317
+ c-1.724-4.585-9.539-6.081-15.514-5.385c5.299-3.049,10.975-9.372,9.418-14.222c-1.451-4.517-8.75-6.42-14.661-6.171
318
+ c5.242-3.091,10.762-9.319,9.223-14.109c-1.451-4.516-8.749-6.42-14.66-6.171c5.242-3.091,10.761-9.318,9.222-14.109
319
+ c-1.768-5.503-12.216-7.126-18.258-5.701C99.738,35.493,102.327,46.38,104.581,57.7z"/>
320
+ <path id="XMLID_42_" style="fill:#DA88B4;" d="M133.291,303.471l-2.898-0.826c-5.201-1.482-8.216-6.9-6.734-12.101l11.585-51.057
321
+ l21.733,6.193l-11.585,51.057C143.91,301.938,138.492,304.953,133.291,303.471z"/>
322
+ <path id="XMLID_41_" style="fill:#DA88B4;" d="M163.564,303.709h-3.013c-5.408,0-9.792-4.384-9.792-9.792l3.205-52.228h22.598
323
+ l-3.205,52.228C173.357,299.324,168.972,303.709,163.564,303.709z"/>
324
+ <path id="XMLID_40_" style="fill:#D570A7;" d="M249.704,303.471l2.898-0.826c5.201-1.482,8.216-6.9,6.734-12.101l-11.585-51.057
325
+ l-21.733,6.193l11.585,51.057C239.085,301.938,244.503,304.953,249.704,303.471z"/>
326
+ <path id="XMLID_39_" style="fill:#D570A7;" d="M219.43,303.709h3.013c5.408,0,9.792-4.384,9.792-9.792l-3.205-52.228h-22.598
327
+ l3.205,52.228C209.638,299.324,214.022,303.709,219.43,303.709z"/>
328
+ <path id="XMLID_466_" style="fill:#DA88B4;" d="M286.793,238.75c-27.199-27.357-30.171-49.76-88.887-79.118
329
+ c-36.069-18.034-64.83-21.45-72.108-41.205c-14.422-39.144-19.687-64.375-23.605-77.485c-1.183-4.131-4.209-33.439-38.202-31.894
330
+ c-17.067,0-30.903,9.224-30.903,20.602s13.836,20.602,30.903,20.602c6.501,0,19.229,5.337,20.602,16.668
331
+ c4.859,40.089,5.666,45.325,19.152,97.392c9.798,37.826,2.137,52.661,30.947,81.517c44.36,44.429,115.945,24.135,122.519,24.135
332
+ c0.98-0.125,43.589,19.794,30.495,49.064c-11.181,24.994-115.189,9.073-134.451,6.551c-53.211-6.967,48.365,39.132,139.027,24.742
333
+ C336.693,343.274,322.526,274.69,286.793,238.75z"/>
334
+ <path id="XMLID_467_" style="fill:#D570A7;" d="M286.793,238.75c-27.199-27.357-30.171-49.76-88.887-79.118
335
+ c-7.473-3.736-14.625-6.84-21.344-9.596v119.823c37.636,10.585,75.926,0.107,80.65,0.107c0.98-0.125,43.589,19.794,30.495,49.064
336
+ c-8.708,19.465-73.712,14.115-111.146,9.604v14.248c30.189,7.904,74.1,14.048,115.721,7.442
337
+ C336.693,343.274,322.526,274.69,286.793,238.75z"/>
338
+ <path id="XMLID_36_" style="fill:#DA88B4;" d="M51.455,25.024l0.147-19.846c0.03-4.009,4.388-6.483,7.845-4.453l17.114,10.05
339
+ L51.455,25.024z"/>
340
+ <path id="XMLID_468_" d="M60.561,15.024c-3.309,0-6,2.691-6,6s2.691,6,6,6s6-2.691,6-6S63.87,15.024,60.561,15.024z"/>
341
+ <circle id="XMLID_469_" style="fill:#98C79C;" cx="214.578" cy="217.007" r="8.017"/>
342
+ <circle id="XMLID_470_" style="fill:#98C79C;" cx="223.646" cy="192.108" r="7.085"/>
343
+ <circle id="XMLID_472_" style="fill:#98C79C;" cx="236.393" cy="215.214" r="9.695"/>
344
+ <circle id="XMLID_473_" style="fill:#98C79C;" cx="196.866" cy="194.72" r="9.695"/>
345
+ </g>
346
+ </svg>
347
+ </div>
348
+
349
+ <div class="decoration-top-right">
350
+ <?xml version="1.0" encoding="utf-8"?>
351
+ <!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
352
+ <svg viewBox="0 -3.57 537.296 537.296" xmlns="http://www.w3.org/2000/svg">
353
+ <g id="Group_10" data-name="Group 10" transform="translate(-1056.208 1535.36)">
354
+ <path id="path232" d="M1067.7-1116.731a8.07,8.07,0,0,1-10.751-3.987,8.194,8.194,0,0,1,3.965-10.84q142.406-66.26,234.63-165.839,92.092-99.44,134.341-232.293a8.075,8.075,0,0,1,10.173-5.28,8.191,8.191,0,0,1,5.24,10.267q-43.36,136.36-137.89,238.439Q1213-1184.324,1067.7-1116.731" fill="#465da9" fill-rule="evenodd"/>
355
+ <path id="path234" d="M1367.5-1168.97l2.027-36.693a12.961,12.961,0,0,1,11.093-12.227l36.066-5.32a12.766,12.766,0,0,0,10.547-9.12,12.925,12.925,0,0,0-3.654-13.507l-93.665-86.32a12.95,12.95,0,0,0-18.357.827l-60.276,66.467a13.2,13.2,0,0,0,.823,18.507l93.662,86.32a12.669,12.669,0,0,0,13.667,2.467,12.84,12.84,0,0,0,8.067-11.4" fill="#f0393c" fill-rule="evenodd"/>
356
+ <path id="path236" d="M1486.2-1324.437l-5.307-36.346a13,13,0,0,1,8.44-14.227l34.267-12.507a12.815,12.815,0,0,0,8.52-11.053,12.884,12.884,0,0,0-6.267-12.506l-108.933-65.64a12.965,12.965,0,0,0-17.813,4.52l-45.84,77.293a13.179,13.179,0,0,0,4.493,17.96l108.92,65.653a12.672,12.672,0,0,0,13.88-.347,12.882,12.882,0,0,0,5.64-12.8" fill="#f9b317" fill-rule="evenodd"/>
357
+ <path id="path238" d="M1214.952-1049.931,1225-1085.237a12.893,12.893,0,0,1,13.507-9.453l36.336,2.88a12.72,12.72,0,0,0,12.284-6.533,12.919,12.919,0,0,0-.592-13.987l-72.341-105.12a12.964,12.964,0,0,0-18.083-3.293l-73.394,51.333a13.193,13.193,0,0,0-3.269,18.227l72.343,105.12a12.7,12.7,0,0,0,12.792,5.453,12.766,12.766,0,0,0,10.372-9.32" fill="#43bb4e" fill-rule="evenodd"/>
358
+ <path id="path240" d="M1132.248-1005.211a17.976,17.976,0,0,0,17.867-18.013,17.976,17.976,0,0,0-17.867-18.013,17.977,17.977,0,0,0-17.868,18.013,17.977,17.977,0,0,0,17.868,18.013" fill="#f9b317" fill-rule="evenodd"/>
359
+ <path id="path242" d="M1346.637-1465.236a11.506,11.506,0,0,0,11.44-11.52,11.518,11.518,0,0,0-11.44-11.533,11.506,11.506,0,0,0-11.427,11.533,11.5,11.5,0,0,0,11.427,11.52" fill="#43bb4e" fill-rule="evenodd"/>
360
+ <path id="path244" d="M1368.8-1100.571a4.47,4.47,0,0,1,3.6-5.16,4.419,4.419,0,0,1,5.12,3.627l3.333,19.333a4.45,4.45,0,0,1-3.6,5.16,4.439,4.439,0,0,1-5.12-3.64l-3.333-19.32" fill="#5b7fc9" fill-rule="evenodd"/>
361
+ <path id="path246" d="M1375.17-1063.651a4.456,4.456,0,0,1,3.6-5.173,4.453,4.453,0,0,1,5.12,3.64l3.333,19.32a4.463,4.463,0,0,1-3.6,5.16,4.419,4.419,0,0,1-5.12-3.627l-3.333-19.32" fill="#5b7fc9" fill-rule="evenodd"/>
362
+ <path id="path248" d="M1350.877-1063.931a4.42,4.42,0,0,1-5.12-3.627,4.443,4.443,0,0,1,3.6-5.16l19.173-3.36a4.433,4.433,0,0,1,5.12,3.627,4.469,4.469,0,0,1-3.613,5.16l-19.16,3.36" fill="#5b7fc9" fill-rule="evenodd"/>
363
+ <path id="path250" d="M1387.49-1070.344a4.438,4.438,0,0,1-5.12-3.64,4.47,4.47,0,0,1,3.6-5.16l19.173-3.36a4.426,4.426,0,0,1,5.12,3.627,4.476,4.476,0,0,1-3.6,5.173l-19.173,3.36" fill="#5b7fc9" fill-rule="evenodd"/>
364
+ <path id="path252" d="M1228.576-1375.517a50.6,50.6,0,0,1,27.487-29.36,3.669,3.669,0,0,0,2.247-3.533,3.649,3.649,0,0,0-2.447-3.4,50.559,50.559,0,0,1-29.125-27.707,3.609,3.609,0,0,0-3.511-2.267,3.626,3.626,0,0,0-3.373,2.467,50.6,50.6,0,0,1-27.488,29.36,3.665,3.665,0,0,0-2.244,3.533,3.671,3.671,0,0,0,2.445,3.4,50.5,50.5,0,0,1,29.125,27.706,3.646,3.646,0,0,0,3.511,2.267,3.626,3.626,0,0,0,3.373-2.467" fill="#5b7fc9" fill-rule="evenodd"/>
365
+ <path id="path254" d="M1238.449-1422.623q-1.824,25.84-28.471,30.413a50.582,50.582,0,0,1,11.713,16.893,3.646,3.646,0,0,0,3.511,2.267,3.626,3.626,0,0,0,3.373-2.467,50.6,50.6,0,0,1,27.487-29.36,3.669,3.669,0,0,0,2.247-3.533,3.649,3.649,0,0,0-2.447-3.4,50.248,50.248,0,0,1-17.413-10.813" fill="#4267ba" fill-rule="evenodd"/>
366
+ <path id="path256" d="M1563.769-1449.77a50.566,50.566,0,0,1,27.48-29.36,3.681,3.681,0,0,0,2.253-3.533,3.685,3.685,0,0,0-2.453-3.413,50.468,50.468,0,0,1-29.12-27.707,3.674,3.674,0,0,0-3.52-2.267,3.674,3.674,0,0,0-3.373,2.467,50.549,50.549,0,0,1-27.48,29.373,3.681,3.681,0,0,0-2.253,3.533,3.682,3.682,0,0,0,2.453,3.4,50.51,50.51,0,0,1,29.12,27.706,3.636,3.636,0,0,0,3.52,2.267,3.637,3.637,0,0,0,3.373-2.467" fill="#6759b2" fill-rule="evenodd"/>
367
+ <path id="path258" d="M1573.636-1496.876q-1.82,25.84-28.467,30.413a50.392,50.392,0,0,1,11.707,16.893,3.636,3.636,0,0,0,3.52,2.267,3.637,3.637,0,0,0,3.373-2.467,50.566,50.566,0,0,1,27.48-29.36,3.681,3.681,0,0,0,2.253-3.533,3.685,3.685,0,0,0-2.453-3.413,50.141,50.141,0,0,1-17.413-10.8" fill="#5748a7" fill-rule="evenodd"/>
368
+ <path id="path260" d="M1126.5-1278.943l-4.051,29.8a4.987,4.987,0,0,1-5.6,4.28l-29.56-4.08a5.023,5.023,0,0,1-4.249-5.653l4.049-29.787a5,5,0,0,1,5.6-4.293l29.56,4.093a5.011,5.011,0,0,1,4.249,5.64" fill="#f0393c" fill-rule="evenodd"/>
369
+ <path id="path262" d="M1124.473-1264.05q-19.546,10.44-39.4-5.44l-2.028,14.893a5.022,5.022,0,0,0,4.249,5.653l29.559,4.08a4.984,4.984,0,0,0,5.6-4.28l2.025-14.907" fill="#cb3325" fill-rule="evenodd"/>
370
+ <path id="path264" d="M1534.183-1257.1l21.093,21.267a5.046,5.046,0,0,1,0,7.08l-21.093,21.266a4.957,4.957,0,0,1-7.027,0l-21.107-21.266a5.046,5.046,0,0,1,0-7.08l21.107-21.267a4.934,4.934,0,0,1,7.027,0" fill="#43bb4e" fill-rule="evenodd"/>
371
+ <path id="path266" d="M1544.73-1246.477q-3.58,22-28.12,28.36l10.547,10.627a4.957,4.957,0,0,0,7.027,0l21.093-21.267a5.046,5.046,0,0,0,0-7.08l-10.547-10.64" fill="#32a940" fill-rule="evenodd"/>
372
+ </g>
373
+ </svg>
374
+ </div>
375
+
376
+ <!-- Balloons -->
377
+ <div class="balloon balloon-1">🎈</div>
378
+ <div class="balloon balloon-2">🎈</div>
379
+ <div class="balloon balloon-3">🎈</div>
380
+ <div class="balloon balloon-4">🎈</div>
381
+
382
+ <!-- Tropical leaves -->
383
+ <div class="leaf leaf-1">🌿</div>
384
+ <div class="leaf leaf-2">🍃</div>
385
+ <div class="leaf leaf-3">🌿</div>
386
+ <div class="leaf leaf-4">🍃</div>
387
+
388
+ <!-- Stars -->
389
+ <div class="star star-1">⭐</div>
390
+ <div class="star star-2">✨</div>
391
+ <div class="star star-3">⭐</div>
392
+ <div class="star star-4">✨</div>
393
+
394
+ <!-- Header -->
395
+ <div class="header">
396
+ <div class="title">🎉 JOIN US FOR A BIRTHDAY PARTY 🎉</div>
397
+ <div class="child-name"><%= data[:party_details][:person_name] %> is turning <%= data[:party_details][:age] %>!</div>
398
+ </div>
399
+
400
+ <!-- Content -->
401
+ <div class="content">
402
+ <% if data[:party_details][:theme] %>
403
+ <div class="info-section theme-highlight">
404
+ <span class="info-label">🎭 PARTY THEME</span>
405
+ <div class="info-value"><%= data[:party_details][:theme] %></div>
406
+ </div>
407
+ <% end %>
408
+
409
+ <div style="display: flex">
410
+ <div class="info-section">
411
+ <span class="info-label">📅 WHEN</span>
412
+ <div class="info-value">
413
+ <%= Date.new(data[:party_details][:date][:year], data[:party_details][:date][:month], data[:party_details][:date][:day]).strftime("%A, %B %d, %Y") %>
414
+ <br>
415
+ <%= data[:party_details][:start_time] %><% if data[:party_details][:end_time] %> - <%= data[:party_details][:end_time] %><% end %>
416
+ </div>
417
+ </div>
418
+
419
+ <div class="info-section">
420
+ <span class="info-label">📍 WHERE</span>
421
+ <div class="info-value">
422
+ <% if data[:venue][:name] %>
423
+ <strong><%= data[:venue][:name] %></strong><br>
424
+ <% end %>
425
+ <%= data[:venue][:address] %>
426
+ <% if data[:venue][:additional_instructions] %>
427
+ <br><em><%= data[:venue][:additional_instructions] %></em>
428
+ <% end %>
429
+ </div>
430
+ </div>
431
+ </div>
432
+
433
+ <% if data[:activities] && (data[:activities][:main_activities] || data[:activities][:entertainment]) %>
434
+ <div class="info-section">
435
+ <span class="info-label">🎮 FUN ACTIVITIES</span>
436
+ <div class="info-value">
437
+ <% if data[:activities][:main_activities] %>
438
+ <%= [data[:activities][:main_activities]].flatten.join(" • ") %>
439
+ <% end %>
440
+ <% if data[:activities][:entertainment] %>
441
+ <% if data[:activities][:main_activities] %><br><% end %>
442
+ <strong>Special Guest:</strong> <%= data[:activities][:entertainment] %>
443
+ <% end %>
444
+ </div>
445
+ </div>
446
+ <% end %>
447
+
448
+ <div style="display: flex">
449
+ <% if data[:special_instructions] %>
450
+ <% if data[:special_instructions][:dress_code] %>
451
+ <div class="info-section">
452
+ <span class="info-label">👕 DRESS CODE</span>
453
+ <div class="info-value"><%= data[:special_instructions][:dress_code] %></div>
454
+ </div>
455
+ <% end %>
456
+
457
+ <% if data[:special_instructions][:what_to_bring] %>
458
+ <div class="info-section">
459
+ <span class="info-label">🎒 PLEASE BRING</span>
460
+ <div class="info-value"><%= data[:special_instructions][:what_to_bring] %></div>
461
+ </div>
462
+ <% end %>
463
+ <% end %>
464
+ </div>
465
+ </div>
466
+
467
+ <!-- RSVP Section -->
468
+ <div class="info-section rsvp-section">
469
+ <span class="info-label">💌 RSVP BY <%= Date.new(data[:rsvp][:deadline][:year], data[:rsvp][:deadline][:month], data[:rsvp][:deadline][:day]).strftime("%B %d").upcase %></span>
470
+ <div class="info-value">
471
+ <strong><%= data[:contact_info][:host_name] %></strong><br>
472
+ <% if data[:rsvp][:method].downcase.include?('phone') || data[:rsvp][:method].downcase.include?('text') %>
473
+ 📞 <%= data[:contact_info][:phone] %>
474
+ <% end %>
475
+ <% if data[:rsvp][:method].downcase.include?('email') && data[:contact_info][:email] %>
476
+ <% if data[:rsvp][:method].downcase.include?('phone') || data[:rsvp][:method].downcase.include?('text') %><br><% end %>
477
+ 📧 <%= data[:contact_info][:email] %>
478
+ <% end %>
479
+ </div>
480
+ </div>
481
+
482
+ <div class="footer-deco">🌟 Let's have a ROARING good time! 🌟</div>
483
+ </div>
484
+ </div>
485
+ </body>
486
+ </html>