@roottale/cms-renderer-next 0.41.1 → 0.42.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 (60) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/dist/before-after-client.d.ts +15 -0
  3. package/dist/before-after-client.js +8 -0
  4. package/dist/before-after-client.js.map +1 -0
  5. package/dist/chunk-4LQPZDXZ.js +75 -0
  6. package/dist/chunk-4LQPZDXZ.js.map +1 -0
  7. package/dist/chunk-6GQCFFHU.js +540 -0
  8. package/dist/chunk-6GQCFFHU.js.map +1 -0
  9. package/dist/chunk-F3G6RVIR.js +220 -0
  10. package/dist/chunk-F3G6RVIR.js.map +1 -0
  11. package/dist/chunk-H46JUIHZ.js +79 -0
  12. package/dist/chunk-H46JUIHZ.js.map +1 -0
  13. package/dist/chunk-K62RR4UQ.js +53 -0
  14. package/dist/chunk-K62RR4UQ.js.map +1 -0
  15. package/dist/chunk-NUUTTSGT.js +916 -0
  16. package/dist/chunk-NUUTTSGT.js.map +1 -0
  17. package/dist/chunk-RSNUZ4BF.js +3378 -0
  18. package/dist/chunk-RSNUZ4BF.js.map +1 -0
  19. package/dist/chunk-U5AKACPN.js +113 -0
  20. package/dist/chunk-U5AKACPN.js.map +1 -0
  21. package/dist/chunk-WWS43XCT.js +206 -0
  22. package/dist/chunk-WWS43XCT.js.map +1 -0
  23. package/dist/cms-public.css +164 -51
  24. package/dist/concerns-client.d.ts +12 -0
  25. package/dist/concerns-client.js +8 -0
  26. package/dist/concerns-client.js.map +1 -0
  27. package/dist/expertise-client.d.ts +10 -0
  28. package/dist/expertise-client.js +8 -0
  29. package/dist/expertise-client.js.map +1 -0
  30. package/dist/hero-carousel-client.d.ts +36 -0
  31. package/dist/hero-carousel-client.js +8 -0
  32. package/dist/hero-carousel-client.js.map +1 -0
  33. package/dist/routes.d.ts +51 -5
  34. package/dist/routes.js +109 -62
  35. package/dist/routes.js.map +1 -1
  36. package/dist/seo-checks.d.ts +87 -0
  37. package/dist/seo-checks.js +27 -0
  38. package/dist/seo-checks.js.map +1 -0
  39. package/dist/server.d.ts +51 -2
  40. package/dist/server.js +8 -2
  41. package/dist/site-config-DgYGGwu1.d.ts +3910 -0
  42. package/dist/spaces-client.d.ts +10 -0
  43. package/dist/spaces-client.js +8 -0
  44. package/dist/spaces-client.js.map +1 -0
  45. package/dist/templates.css +3246 -194
  46. package/dist/templates.d.ts +20 -1028
  47. package/dist/templates.js +70 -2
  48. package/dist/templates.js.map +1 -1
  49. package/dist/{theme-css-vars-BiyHBsJG.d.ts → theme-css-vars-CD3jcEkp.d.ts} +2 -2
  50. package/dist/ui-react-motion-client.d.ts +73 -0
  51. package/dist/ui-react-motion-client.js +14 -0
  52. package/dist/ui-react-motion-client.js.map +1 -0
  53. package/dist/validate.d.ts +15 -1
  54. package/dist/validate.js +806 -17
  55. package/dist/validate.js.map +1 -1
  56. package/package.json +18 -6
  57. package/dist/chunk-GOHP7RWD.js +0 -1647
  58. package/dist/chunk-GOHP7RWD.js.map +0 -1
  59. package/dist/chunk-IOYBEH6E.js +0 -271
  60. package/dist/chunk-IOYBEH6E.js.map +0 -1
@@ -0,0 +1,3378 @@
1
+ import {
2
+ BeforeAfterSlider
3
+ } from "./chunk-U5AKACPN.js";
4
+ import {
5
+ ExpertiseTabStage
6
+ } from "./chunk-4LQPZDXZ.js";
7
+ import {
8
+ SpacesStage
9
+ } from "./chunk-K62RR4UQ.js";
10
+ import {
11
+ ConcernsFigureMap
12
+ } from "./chunk-H46JUIHZ.js";
13
+ import {
14
+ AnimateOnScroll,
15
+ Marquee,
16
+ StaggerGroup,
17
+ StaggerItem
18
+ } from "./chunk-WWS43XCT.js";
19
+ import {
20
+ collectCategories,
21
+ collectCategoriesWithCounts,
22
+ collectCollectionCategories,
23
+ defaultCategoryHref,
24
+ filterPostsByCategory
25
+ } from "./chunk-FUA5H6JE.js";
26
+ import {
27
+ SectionSchema
28
+ } from "./chunk-NUUTTSGT.js";
29
+ import {
30
+ HeroCarouselViewport
31
+ } from "./chunk-F3G6RVIR.js";
32
+
33
+ // src/server.tsx
34
+ import {
35
+ DEFAULT_BLOG_SETTINGS,
36
+ fetchBlogSettings,
37
+ fetchPost,
38
+ fetchPosts,
39
+ fetchTheme,
40
+ jsonLdJson,
41
+ resolvePostDisplay,
42
+ selectRelatedPosts
43
+ } from "@roottale/cms-client/server";
44
+
45
+ // ../cms-i18n/src/index.ts
46
+ var DICTS = {
47
+ ko: {
48
+ blogListEmpty: "\uC544\uC9C1 \uBC1C\uD589\uB41C \uAE00\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.",
49
+ blogCategoriesEmpty: "\uC544\uC9C1 \uCE74\uD14C\uACE0\uB9AC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
50
+ allCategoriesLabel: "\uC804\uCCB4",
51
+ relatedPostsTitle: "\uAD00\uB828 \uAE00",
52
+ postNotFound: "\uAE00\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.",
53
+ pageNotFound: "\uD398\uC774\uC9C0\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.",
54
+ tableOfContentsTitle: "\uBAA9\uCC28"
55
+ },
56
+ en: {
57
+ blogListEmpty: "No posts published yet.",
58
+ blogCategoriesEmpty: "No categories yet.",
59
+ allCategoriesLabel: "All",
60
+ relatedPostsTitle: "Related posts",
61
+ postNotFound: "Post not found.",
62
+ pageNotFound: "Page not found.",
63
+ tableOfContentsTitle: "Table of contents"
64
+ }
65
+ };
66
+ function resolveLocale(locale) {
67
+ return locale === "en" ? "en" : "ko";
68
+ }
69
+ function t(locale, key) {
70
+ return DICTS[resolveLocale(locale)][key];
71
+ }
72
+
73
+ // src/server.tsx
74
+ import {
75
+ bindingSrcValue,
76
+ bindingTextValue,
77
+ boundFieldValue,
78
+ extractFaqEntries,
79
+ faqPageJsonLd,
80
+ isAllowedEmbedSrc as isAllowedEmbedSrc2,
81
+ postsForCollection,
82
+ postsNotInAnyCollection,
83
+ resolvePostPath
84
+ } from "@roottale/cms-core";
85
+
86
+ // src/LeadForm.tsx
87
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
88
+ var VERTICAL_LABEL = {
89
+ consulting: "\uCEE8\uC124\uD305",
90
+ medical: "\uC758\uB8CC",
91
+ tax: "\uC138\uBB34",
92
+ legal: "\uBC95\uB960"
93
+ };
94
+ var VERTICAL_OPTIONS = [
95
+ { value: "consulting", label: "\uCEE8\uC124\uD305 / \uC77C\uBC18" },
96
+ { value: "medical", label: "\uC758\uB8CC (\uBCD1\uC758\uC6D0\xB7\uCE58\uACFC\xB7\uD55C\uC758\uC6D0)" },
97
+ { value: "tax", label: "\uC138\uBB34 (\uC138\uBB34\uC0AC\xB7\uD68C\uACC4\uC0AC)" },
98
+ { value: "legal", label: "\uBC95\uB960 (\uBC95\uBB34\uBC95\uC778\xB7\uBCC0\uD638\uC0AC)" }
99
+ ];
100
+ function RootTaleLeadForm(props) {
101
+ const {
102
+ action,
103
+ vertical,
104
+ redirectUrl,
105
+ heading,
106
+ description,
107
+ submitLabel = "\uC9C4\uB2E8 \uC2E0\uCCAD",
108
+ turnstileSiteKey,
109
+ className
110
+ } = props;
111
+ const formClass = ["rt-cms-lead-form", className].filter(Boolean).join(" ");
112
+ const isMedical = vertical === "medical";
113
+ return /* @__PURE__ */ jsxs(
114
+ "form",
115
+ {
116
+ method: "post",
117
+ action,
118
+ "data-roottale-cms": "lead-form",
119
+ className: formClass,
120
+ children: [
121
+ heading ? /* @__PURE__ */ jsx("h2", { className: "rt-cms-lead-heading", children: heading }) : null,
122
+ description ? /* @__PURE__ */ jsx("p", { className: "rt-cms-lead-description", children: description }) : null,
123
+ redirectUrl ? /* @__PURE__ */ jsx("input", { type: "hidden", name: "_redirect_url", value: redirectUrl }) : null,
124
+ vertical ? /* @__PURE__ */ jsxs(Fragment, { children: [
125
+ /* @__PURE__ */ jsx("input", { type: "hidden", name: "vertical", value: vertical }),
126
+ /* @__PURE__ */ jsxs("p", { className: "rt-cms-lead-vertical-label", children: [
127
+ "\uBD84\uC57C: ",
128
+ /* @__PURE__ */ jsx("strong", { children: VERTICAL_LABEL[vertical] })
129
+ ] })
130
+ ] }) : /* @__PURE__ */ jsxs("label", { className: "rt-cms-field", children: [
131
+ /* @__PURE__ */ jsxs("span", { className: "rt-cms-field-label", children: [
132
+ "\uBD84\uC57C ",
133
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "*" })
134
+ ] }),
135
+ /* @__PURE__ */ jsxs(
136
+ "select",
137
+ {
138
+ name: "vertical",
139
+ required: true,
140
+ className: "rt-cms-field-input rt-cms-field-select",
141
+ defaultValue: "",
142
+ children: [
143
+ /* @__PURE__ */ jsx("option", { value: "", disabled: true, children: "\uC120\uD0DD\uD558\uC138\uC694" }),
144
+ VERTICAL_OPTIONS.map((opt) => /* @__PURE__ */ jsx("option", { value: opt.value, children: opt.label }, opt.value))
145
+ ]
146
+ }
147
+ )
148
+ ] }),
149
+ /* @__PURE__ */ jsxs("label", { className: "rt-cms-field", children: [
150
+ /* @__PURE__ */ jsxs("span", { className: "rt-cms-field-label", children: [
151
+ "\uC774\uB984 ",
152
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "*" })
153
+ ] }),
154
+ /* @__PURE__ */ jsx(
155
+ "input",
156
+ {
157
+ type: "text",
158
+ name: "contact_name",
159
+ required: true,
160
+ autoComplete: "name",
161
+ className: "rt-cms-field-input"
162
+ }
163
+ )
164
+ ] }),
165
+ isMedical ? (
166
+ // 환자 문의에는 "사업체명" 개념이 없다 — 화면에는 노출하지 않되,
167
+ // intake 가 vertical 불문 hard-required 로 검증하는 계약(위 파일
168
+ // 헤더 코멘트 참조)을 만족시키기 위해 자리표시자만 hidden 전송.
169
+ /* @__PURE__ */ jsx("input", { type: "hidden", name: "business_name", value: "-" })
170
+ ) : /* @__PURE__ */ jsxs("label", { className: "rt-cms-field", children: [
171
+ /* @__PURE__ */ jsxs("span", { className: "rt-cms-field-label", children: [
172
+ "\uC0AC\uC5C5\uCCB4\uBA85 ",
173
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "*" })
174
+ ] }),
175
+ /* @__PURE__ */ jsx(
176
+ "input",
177
+ {
178
+ type: "text",
179
+ name: "business_name",
180
+ required: true,
181
+ autoComplete: "organization",
182
+ className: "rt-cms-field-input"
183
+ }
184
+ )
185
+ ] }),
186
+ /* @__PURE__ */ jsxs("label", { className: "rt-cms-field", children: [
187
+ /* @__PURE__ */ jsxs("span", { className: "rt-cms-field-label", children: [
188
+ "\uC804\uD654\uBC88\uD638 ",
189
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "*" })
190
+ ] }),
191
+ /* @__PURE__ */ jsx(
192
+ "input",
193
+ {
194
+ type: "tel",
195
+ name: "phone",
196
+ required: true,
197
+ autoComplete: "tel",
198
+ inputMode: "tel",
199
+ pattern: "0\\d{1,2}-?\\d{3,4}-?\\d{4}",
200
+ placeholder: "010-1234-5678",
201
+ className: "rt-cms-field-input"
202
+ }
203
+ )
204
+ ] }),
205
+ /* @__PURE__ */ jsxs("label", { className: "rt-cms-field", children: [
206
+ /* @__PURE__ */ jsxs("span", { className: "rt-cms-field-label", children: [
207
+ "\uC774\uBA54\uC77C ",
208
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "*" })
209
+ ] }),
210
+ /* @__PURE__ */ jsx(
211
+ "input",
212
+ {
213
+ type: "email",
214
+ name: "email",
215
+ required: true,
216
+ autoComplete: "email",
217
+ className: "rt-cms-field-input"
218
+ }
219
+ )
220
+ ] }),
221
+ isMedical ? /* @__PURE__ */ jsxs(Fragment, { children: [
222
+ /* @__PURE__ */ jsxs("label", { className: "rt-cms-field", children: [
223
+ /* @__PURE__ */ jsx("span", { className: "rt-cms-field-label", children: "\uC0C1\uB2F4 \uD76C\uB9DD \uBD84\uC57C\xB7\uC99D\uC0C1 (\uC120\uD0DD)" }),
224
+ /* @__PURE__ */ jsx(
225
+ "input",
226
+ {
227
+ type: "text",
228
+ name: "consultation_field",
229
+ placeholder: "\uC608: \uBB34\uB98E \uD1B5\uC99D, \uC815\uAE30\uAC80\uC9C4",
230
+ className: "rt-cms-field-input"
231
+ }
232
+ )
233
+ ] }),
234
+ /* @__PURE__ */ jsxs("label", { className: "rt-cms-field", children: [
235
+ /* @__PURE__ */ jsx("span", { className: "rt-cms-field-label", children: "\uBB38\uC758 \uB0B4\uC6A9 (\uC120\uD0DD)" }),
236
+ /* @__PURE__ */ jsx(
237
+ "textarea",
238
+ {
239
+ name: "message",
240
+ rows: 4,
241
+ placeholder: "\uC99D\uC0C1\uC774 \uC5B8\uC81C\uBD80\uD130 \uC788\uC5C8\uB294\uC9C0, \uAD81\uAE08\uD558\uC2E0 \uC810\uC744 \uC790\uC720\uB86D\uAC8C \uC801\uC5B4\uC8FC\uC138\uC694.",
242
+ className: "rt-cms-field-input rt-cms-field-textarea"
243
+ }
244
+ )
245
+ ] })
246
+ ] }) : /* @__PURE__ */ jsxs("label", { className: "rt-cms-field", children: [
247
+ /* @__PURE__ */ jsx("span", { className: "rt-cms-field-label", children: "\uD604\uC7AC \uC0AC\uC774\uD2B8 URL (\uC120\uD0DD)" }),
248
+ /* @__PURE__ */ jsx(
249
+ "input",
250
+ {
251
+ type: "url",
252
+ name: "current_site_url",
253
+ placeholder: "https://",
254
+ className: "rt-cms-field-input"
255
+ }
256
+ ),
257
+ /* @__PURE__ */ jsx("span", { className: "rt-cms-field-hint", children: "\uC5C6\uC73C\uBA74 \uBE44\uC6CC\uB450\uC138\uC694." })
258
+ ] }),
259
+ /* @__PURE__ */ jsxs("label", { className: "rt-cms-lead-consent", children: [
260
+ /* @__PURE__ */ jsx("input", { type: "checkbox", name: "privacy_consent", required: true }),
261
+ /* @__PURE__ */ jsxs("span", { children: [
262
+ /* @__PURE__ */ jsx("strong", { children: "(\uD544\uC218)" }),
263
+ " \uAC1C\uC778\uC815\uBCF4 \uC218\uC9D1\xB7\uC774\uC6A9\uC5D0 \uB3D9\uC758\uD569\uB2C8\uB2E4. (\uC218\uC9D1 \uD56D\uBAA9:",
264
+ " ",
265
+ isMedical ? "\uC774\uB984\xB7\uC5F0\uB77D\uCC98\xB7\uC774\uBA54\uC77C\xB7\uC0C1\uB2F4 \uB0B4\uC6A9(\uC791\uC131 \uC2DC)" : "\uC774\uB984\xB7\uC5F0\uB77D\uCC98\xB7\uC774\uBA54\uC77C\xB7\uC0AC\uC5C5\uCCB4\uBA85",
266
+ ". \uBCF4\uAD00 \uAE30\uAC04: \uBB38\uC758 \uC885\uB8CC \uD6C4 3\uB144)"
267
+ ] })
268
+ ] }),
269
+ vertical === "medical" ? /* @__PURE__ */ jsxs("label", { className: "rt-cms-lead-consent", children: [
270
+ /* @__PURE__ */ jsx(
271
+ "input",
272
+ {
273
+ type: "checkbox",
274
+ name: "overseas_transfer_consent",
275
+ required: true
276
+ }
277
+ ),
278
+ /* @__PURE__ */ jsxs("span", { children: [
279
+ /* @__PURE__ */ jsx("strong", { children: "(\uD544\uC218, \uC758\uB8CC)" }),
280
+ " \uC758\uB8CC PII \uC758 \uAD6D\uC678\uC774\uC804(\uBCF4\uAD00\xB7\uCC98\uB9AC)\uC5D0 \uB3D9\uC758\uD569\uB2C8\uB2E4. (\uC758\uB8CC\uBC95 \xA721\xB7\uAC1C\uC778\uC815\uBCF4\uBCF4\uD638\uBC95 \xA728 \u2014 ADR-0018)"
281
+ ] })
282
+ ] }) : null,
283
+ turnstileSiteKey ? /* @__PURE__ */ jsxs(Fragment, { children: [
284
+ /* @__PURE__ */ jsx(
285
+ "script",
286
+ {
287
+ src: "https://challenges.cloudflare.com/turnstile/v0/api.js",
288
+ async: true,
289
+ defer: true
290
+ }
291
+ ),
292
+ /* @__PURE__ */ jsx(
293
+ "div",
294
+ {
295
+ className: "cf-turnstile",
296
+ "data-sitekey": turnstileSiteKey,
297
+ "data-action": "turnstile-spin-v1"
298
+ }
299
+ )
300
+ ] }) : null,
301
+ /* @__PURE__ */ jsx("div", { className: "rt-cms-lead-actions", children: /* @__PURE__ */ jsx("button", { type: "submit", className: "rt-cms-lead-submit", children: submitLabel }) })
302
+ ]
303
+ }
304
+ );
305
+ }
306
+
307
+ // src/templates/sections.tsx
308
+ import { isAllowedEmbedSrc } from "@roottale/cms-core";
309
+ import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
310
+ function sectionThemeStyle(theme) {
311
+ if (!theme) return void 0;
312
+ const style = {};
313
+ for (const [key, value] of Object.entries(theme)) {
314
+ if (key.startsWith("--")) style[key] = value;
315
+ }
316
+ return Object.keys(style).length > 0 ? style : void 0;
317
+ }
318
+ function CtaLink({
319
+ cta,
320
+ className,
321
+ track
322
+ }) {
323
+ return /* @__PURE__ */ jsx2(
324
+ "a",
325
+ {
326
+ className: className ?? "rt-tpl-btn rt-tpl-btn--primary",
327
+ href: cta.href,
328
+ "data-track": track,
329
+ children: cta.label
330
+ }
331
+ );
332
+ }
333
+ function ctaTrackForHref(href) {
334
+ return href.startsWith("tel:") ? "cta_banner" : "cta_hero";
335
+ }
336
+ function TemplateHeroProof({
337
+ proofMetrics
338
+ }) {
339
+ if (!proofMetrics || proofMetrics.items.length === 0) return null;
340
+ return /* @__PURE__ */ jsx2(
341
+ "div",
342
+ {
343
+ className: "rt-tpl-hero-proof",
344
+ "data-position": proofMetrics.position,
345
+ "aria-label": "\uC2E0\uB8B0 \uC9C0\uD45C",
346
+ children: proofMetrics.items.map((metric) => /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-hero-proof-item", children: [
347
+ metric.imageSrc ? /* @__PURE__ */ jsx2(
348
+ "img",
349
+ {
350
+ className: "rt-tpl-hero-proof-icon",
351
+ src: metric.imageSrc,
352
+ alt: metric.imageAlt ?? "",
353
+ loading: "lazy"
354
+ }
355
+ ) : null,
356
+ /* @__PURE__ */ jsxs2("span", { className: "rt-tpl-hero-proof-value", children: [
357
+ metric.value,
358
+ metric.unit ? /* @__PURE__ */ jsx2("span", { children: metric.unit }) : null
359
+ ] }),
360
+ /* @__PURE__ */ jsx2("span", { className: "rt-tpl-hero-proof-label", children: metric.label }),
361
+ metric.source ? /* @__PURE__ */ jsx2("span", { className: "rt-tpl-hero-proof-source", children: metric.source }) : null
362
+ ] }, `${metric.value}-${metric.label}`))
363
+ }
364
+ );
365
+ }
366
+ function TemplateHeroCarousel(section) {
367
+ const {
368
+ eyebrow,
369
+ title,
370
+ subtitle,
371
+ cta,
372
+ slides,
373
+ autoplay,
374
+ intervalMs,
375
+ proofMetrics,
376
+ scrim
377
+ } = section.props;
378
+ const safeSlides = slides ?? [];
379
+ return /* @__PURE__ */ jsxs2(
380
+ "section",
381
+ {
382
+ "data-roottale-tpl": "hero",
383
+ "data-variant": "carousel",
384
+ id: section.id,
385
+ className: "rt-tpl-section rt-tpl-hero rt-tpl-hero--carousel",
386
+ style: sectionThemeStyle(section.theme),
387
+ children: [
388
+ safeSlides.length >= 2 ? /* @__PURE__ */ jsx2(
389
+ HeroCarouselViewport,
390
+ {
391
+ slides: safeSlides,
392
+ autoplay: autoplay ?? true,
393
+ intervalMs: intervalMs ?? 6e3,
394
+ scrim
395
+ }
396
+ ) : null,
397
+ /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-container rt-tpl-hero-carousel-overlay", children: [
398
+ eyebrow ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-hero-eyebrow", children: eyebrow }) : null,
399
+ /* @__PURE__ */ jsx2("h1", { className: "rt-tpl-hero-title rt-tpl-hero-carousel-title", children: title.split("\n").map((line, i) => /* @__PURE__ */ jsx2("span", { className: "rt-tpl-hero-title-line", children: line }, i)) }),
400
+ subtitle ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-hero-desc rt-tpl-hero-carousel-subtitle", children: subtitle }) : null,
401
+ cta ? /* @__PURE__ */ jsx2(
402
+ CtaLink,
403
+ {
404
+ cta,
405
+ track: "cta_hero",
406
+ className: "rt-tpl-btn rt-tpl-btn--primary rt-tpl-hero-carousel-cta"
407
+ }
408
+ ) : null,
409
+ /* @__PURE__ */ jsx2(TemplateHeroProof, { proofMetrics })
410
+ ] })
411
+ ]
412
+ }
413
+ );
414
+ }
415
+ function TemplateHeroOverlayPanel(section) {
416
+ const { eyebrow, title, description, imageSrc, imageAlt, cta, proofMetrics } = section.props;
417
+ return /* @__PURE__ */ jsxs2(
418
+ "section",
419
+ {
420
+ "data-roottale-tpl": "hero",
421
+ "data-variant": "overlay-panel",
422
+ id: section.id,
423
+ className: "rt-tpl-section rt-tpl-hero rt-tpl-hero--overlay-panel",
424
+ style: sectionThemeStyle(section.theme),
425
+ children: [
426
+ /* @__PURE__ */ jsx2(
427
+ "img",
428
+ {
429
+ className: "rt-tpl-hero-overlay-img",
430
+ src: imageSrc ?? "",
431
+ alt: imageAlt ?? "",
432
+ loading: "eager"
433
+ }
434
+ ),
435
+ /* @__PURE__ */ jsx2("div", { className: "rt-tpl-hero-overlay-scrim", "aria-hidden": "true" }),
436
+ /* @__PURE__ */ jsx2("div", { className: "rt-tpl-container rt-tpl-hero-overlay-inner", children: /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-hero-overlay-panel", children: [
437
+ eyebrow ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-hero-eyebrow", children: eyebrow }) : null,
438
+ /* @__PURE__ */ jsx2("h1", { className: "rt-tpl-hero-title", children: title.split("\n").map((line, i) => /* @__PURE__ */ jsx2("span", { className: "rt-tpl-hero-title-line", children: line }, i)) }),
439
+ description ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-hero-desc", children: description }) : null,
440
+ cta ? /* @__PURE__ */ jsx2(CtaLink, { cta, track: "cta_hero" }) : null,
441
+ /* @__PURE__ */ jsx2(TemplateHeroProof, { proofMetrics })
442
+ ] }) })
443
+ ]
444
+ }
445
+ );
446
+ }
447
+ function TemplateHero(section) {
448
+ if (section.variant === "carousel") return TemplateHeroCarousel(section);
449
+ if (section.variant === "overlay-panel")
450
+ return TemplateHeroOverlayPanel(section);
451
+ const { eyebrow, title, description, imageSrc, imageAlt, cta, proofMetrics } = section.props;
452
+ const variant = section.variant;
453
+ const showImage = variant !== "minimal" && imageSrc;
454
+ return /* @__PURE__ */ jsx2(
455
+ "section",
456
+ {
457
+ "data-roottale-tpl": "hero",
458
+ "data-variant": variant,
459
+ id: section.id,
460
+ className: "rt-tpl-section rt-tpl-hero",
461
+ style: sectionThemeStyle(section.theme),
462
+ children: /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-container rt-tpl-hero-inner", children: [
463
+ /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-hero-copy", children: [
464
+ eyebrow ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-hero-eyebrow", children: eyebrow }) : null,
465
+ /* @__PURE__ */ jsx2("h1", { className: "rt-tpl-hero-title", children: title.split("\n").map((line, i) => /* @__PURE__ */ jsx2("span", { className: "rt-tpl-hero-title-line", children: line }, i)) }),
466
+ description ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-hero-desc", children: description }) : null,
467
+ cta ? /* @__PURE__ */ jsx2(CtaLink, { cta, track: "cta_hero" }) : null,
468
+ /* @__PURE__ */ jsx2(TemplateHeroProof, { proofMetrics })
469
+ ] }),
470
+ showImage ? /* @__PURE__ */ jsx2("div", { className: "rt-tpl-hero-media", children: /* @__PURE__ */ jsx2(
471
+ "img",
472
+ {
473
+ className: "rt-tpl-hero-img",
474
+ src: imageSrc,
475
+ alt: imageAlt ?? "",
476
+ loading: "eager"
477
+ }
478
+ ) }) : null
479
+ ] })
480
+ }
481
+ );
482
+ }
483
+ function TemplateRichText(section) {
484
+ const { heading, body } = section.props;
485
+ return /* @__PURE__ */ jsx2(
486
+ "section",
487
+ {
488
+ "data-roottale-tpl": "rich-text",
489
+ id: section.id,
490
+ className: "rt-tpl-section rt-tpl-rich-text",
491
+ style: sectionThemeStyle(section.theme),
492
+ children: /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-container", children: [
493
+ heading ? /* @__PURE__ */ jsx2("h2", { className: "rt-tpl-heading", children: heading }) : null,
494
+ body.split("\n\n").map((para, i) => /* @__PURE__ */ jsx2("p", { className: "rt-tpl-rich-text-p", children: para }, i))
495
+ ] })
496
+ }
497
+ );
498
+ }
499
+ function servicesIndexNum(i) {
500
+ return String(i + 1).padStart(2, "0");
501
+ }
502
+ function ServicesItemMeta({
503
+ item
504
+ }) {
505
+ const hasChips = Boolean(item.chips && item.chips.length > 0);
506
+ const hasMeta = Boolean(item.meta && item.meta.length > 0);
507
+ if (!hasChips && !hasMeta) return null;
508
+ return /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-services-meta-block", children: [
509
+ hasChips ? /* @__PURE__ */ jsx2("ul", { className: "rt-tpl-services-chips", "aria-label": `${item.title} \uD0DC\uADF8`, children: (item.chips ?? []).map((chip) => /* @__PURE__ */ jsx2("li", { children: chip }, chip)) }) : null,
510
+ hasMeta ? /* @__PURE__ */ jsx2("ul", { className: "rt-tpl-services-meta", "aria-label": `${item.title} \uBA54\uD0C0`, children: (item.meta ?? []).map((meta) => /* @__PURE__ */ jsx2("li", { children: meta }, meta)) }) : null
511
+ ] });
512
+ }
513
+ function ServicesIcon({
514
+ item
515
+ }) {
516
+ if (!item.iconSrc) return null;
517
+ return /* @__PURE__ */ jsx2(
518
+ "img",
519
+ {
520
+ className: "rt-tpl-services-icon",
521
+ src: item.iconSrc,
522
+ alt: item.iconAlt ?? "",
523
+ loading: "lazy"
524
+ }
525
+ );
526
+ }
527
+ function TemplateServicesActionRail(section) {
528
+ const { heading, description, items } = section.props;
529
+ return /* @__PURE__ */ jsx2(
530
+ "section",
531
+ {
532
+ "data-roottale-tpl": "services",
533
+ "data-variant": "action-rail",
534
+ id: section.id,
535
+ className: "rt-tpl-section rt-tpl-services",
536
+ style: sectionThemeStyle(section.theme),
537
+ children: /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-container", children: [
538
+ heading ? /* @__PURE__ */ jsx2("h2", { className: "rt-tpl-heading", children: heading }) : null,
539
+ description ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-section-desc", children: description }) : null,
540
+ /* @__PURE__ */ jsx2("ul", { className: "rt-tpl-services-action-rail", children: items.map((item, i) => {
541
+ const body = /* @__PURE__ */ jsxs2(Fragment2, { children: [
542
+ /* @__PURE__ */ jsx2(ServicesIcon, { item }),
543
+ /* @__PURE__ */ jsxs2("span", { className: "rt-tpl-services-action-body", children: [
544
+ /* @__PURE__ */ jsx2("span", { className: "rt-tpl-services-title", children: item.title }),
545
+ item.subtitle ? /* @__PURE__ */ jsx2("span", { className: "rt-tpl-services-subtitle", children: item.subtitle }) : null,
546
+ item.description ? /* @__PURE__ */ jsx2("span", { className: "rt-tpl-services-desc", children: item.description }) : null,
547
+ /* @__PURE__ */ jsx2(ServicesItemMeta, { item }),
548
+ item.ctaLabel ? /* @__PURE__ */ jsx2("span", { className: "rt-tpl-services-action-label", children: item.ctaLabel }) : null
549
+ ] })
550
+ ] });
551
+ return /* @__PURE__ */ jsx2("li", { "data-kind": item.kind, children: item.href ? /* @__PURE__ */ jsx2(
552
+ "a",
553
+ {
554
+ className: "rt-tpl-services-action-card",
555
+ href: item.href,
556
+ "data-track": "service_card",
557
+ children: body
558
+ }
559
+ ) : /* @__PURE__ */ jsx2("div", { className: "rt-tpl-services-action-card", children: body }) }, `${item.title}-${i}`);
560
+ }) })
561
+ ] })
562
+ }
563
+ );
564
+ }
565
+ function TemplateServicesPhotoCards(section) {
566
+ const { heading, description, items } = section.props;
567
+ return /* @__PURE__ */ jsx2(
568
+ "section",
569
+ {
570
+ "data-roottale-tpl": "services",
571
+ "data-variant": "photo-cards",
572
+ id: section.id,
573
+ className: "rt-tpl-section rt-tpl-services",
574
+ style: sectionThemeStyle(section.theme),
575
+ children: /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-container", children: [
576
+ heading ? /* @__PURE__ */ jsx2("h2", { className: "rt-tpl-heading", children: heading }) : null,
577
+ description ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-section-desc", children: description }) : null,
578
+ /* @__PURE__ */ jsx2("ul", { className: "rt-tpl-services-photo-list", children: items.map((item, i) => {
579
+ const card = /* @__PURE__ */ jsxs2("article", { className: "rt-tpl-services-photo-card", children: [
580
+ /* @__PURE__ */ jsx2(
581
+ "img",
582
+ {
583
+ className: "rt-tpl-services-photo-img",
584
+ src: item.imageSrc ?? "",
585
+ alt: item.imageAlt ?? "",
586
+ loading: "lazy"
587
+ }
588
+ ),
589
+ /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-services-photo-body", children: [
590
+ /* @__PURE__ */ jsx2("h3", { className: "rt-tpl-services-title", children: item.title }),
591
+ item.description ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-services-desc", children: item.description }) : null,
592
+ item.ctaLabel ? /* @__PURE__ */ jsx2("span", { className: "rt-tpl-services-action-label", children: item.ctaLabel }) : null
593
+ ] })
594
+ ] });
595
+ return /* @__PURE__ */ jsx2("li", { children: item.href ? /* @__PURE__ */ jsx2(
596
+ "a",
597
+ {
598
+ className: "rt-tpl-services-photo-link",
599
+ href: item.href,
600
+ "data-track": "service_card",
601
+ children: card
602
+ }
603
+ ) : card }, `${item.title}-${i}`);
604
+ }) })
605
+ ] })
606
+ }
607
+ );
608
+ }
609
+ function TemplateServicesIndexRows(section) {
610
+ const { heading, description, items } = section.props;
611
+ return /* @__PURE__ */ jsx2(
612
+ "section",
613
+ {
614
+ "data-roottale-tpl": "services",
615
+ "data-variant": "index-rows",
616
+ id: section.id,
617
+ className: "rt-tpl-section rt-tpl-services",
618
+ style: sectionThemeStyle(section.theme),
619
+ children: /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-container", children: [
620
+ heading ? /* @__PURE__ */ jsx2("h2", { className: "rt-tpl-heading", children: heading }) : null,
621
+ description ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-section-desc", children: description }) : null,
622
+ /* @__PURE__ */ jsx2(StaggerGroup, { as: "ol", className: "rt-tpl-services-index-list", children: items.map((item, i) => {
623
+ const body = /* @__PURE__ */ jsxs2(Fragment2, { children: [
624
+ /* @__PURE__ */ jsx2("span", { className: "rt-tpl-services-index-num", "aria-hidden": "true", children: servicesIndexNum(i) }),
625
+ /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-services-index-body", children: [
626
+ /* @__PURE__ */ jsx2("h3", { className: "rt-tpl-services-index-title", children: item.title }),
627
+ item.description ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-services-index-desc", children: item.description }) : null
628
+ ] })
629
+ ] });
630
+ return /* @__PURE__ */ jsx2(StaggerItem, { as: "li", className: "rt-tpl-services-index-row", children: item.href ? /* @__PURE__ */ jsx2(
631
+ "a",
632
+ {
633
+ className: "rt-tpl-services-index-link",
634
+ href: item.href,
635
+ "data-track": "service_card",
636
+ children: body
637
+ }
638
+ ) : /* @__PURE__ */ jsx2("div", { className: "rt-tpl-services-index-link", children: body }) }, i);
639
+ }) })
640
+ ] })
641
+ }
642
+ );
643
+ }
644
+ function TemplateServicesSplitFeatured(section) {
645
+ const { heading, description, items } = section.props;
646
+ const [featured, ...rest] = items;
647
+ return /* @__PURE__ */ jsx2(
648
+ "section",
649
+ {
650
+ "data-roottale-tpl": "services",
651
+ "data-variant": "split-featured",
652
+ id: section.id,
653
+ className: "rt-tpl-section rt-tpl-services",
654
+ style: sectionThemeStyle(section.theme),
655
+ children: /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-container", children: [
656
+ heading ? /* @__PURE__ */ jsx2("h2", { className: "rt-tpl-heading", children: heading }) : null,
657
+ description ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-section-desc", children: description }) : null,
658
+ /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-services-split", children: [
659
+ /* @__PURE__ */ jsx2(
660
+ AnimateOnScroll,
661
+ {
662
+ as: "div",
663
+ variant: "fade-up",
664
+ className: "rt-tpl-services-split-featured",
665
+ children: featured ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
666
+ /* @__PURE__ */ jsx2("h3", { className: "rt-tpl-services-split-featured-title", children: featured.title }),
667
+ featured.subtitle ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-services-subtitle", children: featured.subtitle }) : null,
668
+ featured.description ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-services-split-featured-desc", children: featured.description }) : null,
669
+ /* @__PURE__ */ jsx2(ServicesItemMeta, { item: featured }),
670
+ featured.href ? /* @__PURE__ */ jsx2(
671
+ "a",
672
+ {
673
+ className: "rt-tpl-btn rt-tpl-btn--primary rt-tpl-services-split-featured-cta",
674
+ href: featured.href,
675
+ "data-track": "service_card",
676
+ children: featured.ctaLabel ?? "\uC790\uC138\uD788 \uBCF4\uAE30"
677
+ }
678
+ ) : null
679
+ ] }) : null
680
+ }
681
+ ),
682
+ /* @__PURE__ */ jsx2(StaggerGroup, { as: "ol", className: "rt-tpl-services-split-list", children: rest.map((item, i) => {
683
+ const body = /* @__PURE__ */ jsxs2(Fragment2, { children: [
684
+ /* @__PURE__ */ jsx2("h4", { className: "rt-tpl-services-split-item-title", children: item.title }),
685
+ item.description ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-services-split-item-desc", children: item.description }) : null,
686
+ /* @__PURE__ */ jsx2(ServicesItemMeta, { item })
687
+ ] });
688
+ return /* @__PURE__ */ jsx2(
689
+ StaggerItem,
690
+ {
691
+ as: "li",
692
+ className: "rt-tpl-services-split-item",
693
+ children: item.href ? /* @__PURE__ */ jsx2(
694
+ "a",
695
+ {
696
+ className: "rt-tpl-services-split-item-link",
697
+ href: item.href,
698
+ "data-track": "service_card",
699
+ children: body
700
+ }
701
+ ) : body
702
+ },
703
+ i
704
+ );
705
+ }) })
706
+ ] })
707
+ ] })
708
+ }
709
+ );
710
+ }
711
+ function TemplateServices(section) {
712
+ if (section.variant === "index-rows") return TemplateServicesIndexRows(section);
713
+ if (section.variant === "split-featured")
714
+ return TemplateServicesSplitFeatured(section);
715
+ if (section.variant === "action-rail")
716
+ return TemplateServicesActionRail(section);
717
+ if (section.variant === "photo-cards")
718
+ return TemplateServicesPhotoCards(section);
719
+ const { heading, description, items } = section.props;
720
+ return /* @__PURE__ */ jsx2(
721
+ "section",
722
+ {
723
+ "data-roottale-tpl": "services",
724
+ "data-variant": section.variant,
725
+ id: section.id,
726
+ className: "rt-tpl-section rt-tpl-services",
727
+ style: sectionThemeStyle(section.theme),
728
+ children: /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-container", children: [
729
+ heading ? /* @__PURE__ */ jsx2("h2", { className: "rt-tpl-heading", children: heading }) : null,
730
+ description ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-section-desc", children: description }) : null,
731
+ /* @__PURE__ */ jsx2(StaggerGroup, { as: "ul", className: "rt-tpl-services-list", children: items.map((item, i) => {
732
+ const body = /* @__PURE__ */ jsxs2(Fragment2, { children: [
733
+ /* @__PURE__ */ jsx2("h3", { className: "rt-tpl-services-title", children: item.title }),
734
+ item.subtitle ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-services-subtitle", children: item.subtitle }) : null,
735
+ item.description ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-services-desc", children: item.description }) : null,
736
+ /* @__PURE__ */ jsx2(ServicesItemMeta, { item }),
737
+ item.ctaLabel ? /* @__PURE__ */ jsx2("span", { className: "rt-tpl-services-action-label", children: item.ctaLabel }) : null
738
+ ] });
739
+ return /* @__PURE__ */ jsx2(StaggerItem, { as: "li", className: "rt-tpl-services-item", children: item.href ? /* @__PURE__ */ jsxs2(
740
+ "a",
741
+ {
742
+ className: "rt-tpl-services-link",
743
+ href: item.href,
744
+ "data-track": "service_card",
745
+ children: [
746
+ /* @__PURE__ */ jsx2(ServicesIcon, { item }),
747
+ body
748
+ ]
749
+ }
750
+ ) : /* @__PURE__ */ jsxs2(Fragment2, { children: [
751
+ /* @__PURE__ */ jsx2(ServicesIcon, { item }),
752
+ body
753
+ ] }) }, i);
754
+ }) })
755
+ ] })
756
+ }
757
+ );
758
+ }
759
+ function FooterBrand(section) {
760
+ const { businessName, logo, description } = section.props;
761
+ return /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-footer-brand", children: [
762
+ logo ? /* @__PURE__ */ jsx2(
763
+ "img",
764
+ {
765
+ className: "rt-tpl-footer-logo",
766
+ src: logo.src,
767
+ alt: logo.alt,
768
+ loading: "lazy"
769
+ }
770
+ ) : null,
771
+ /* @__PURE__ */ jsx2("p", { className: "rt-tpl-footer-name", children: businessName }),
772
+ description ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-footer-description", children: description }) : null
773
+ ] });
774
+ }
775
+ function FooterContact({
776
+ contactInfo
777
+ }) {
778
+ if (!contactInfo?.address && !contactInfo?.phone && !contactInfo?.email) {
779
+ return null;
780
+ }
781
+ return /* @__PURE__ */ jsxs2("address", { className: "rt-tpl-footer-contact", children: [
782
+ contactInfo.address ? /* @__PURE__ */ jsx2("span", { children: contactInfo.address }) : null,
783
+ contactInfo.phone ? /* @__PURE__ */ jsx2("a", { href: telHref(contactInfo.phone), children: contactInfo.phone }) : null,
784
+ contactInfo.email ? /* @__PURE__ */ jsx2("a", { href: `mailto:${contactInfo.email}`, children: contactInfo.email }) : null
785
+ ] });
786
+ }
787
+ function FooterLegal(section) {
788
+ const { legalInfo, privacyHref, termsHref, copyright, socialLinks, credit } = section.props;
789
+ return /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-footer-bottom", children: [
790
+ /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-footer-legal", children: [
791
+ legalInfo ? /* @__PURE__ */ jsx2("p", { children: legalInfo }) : null,
792
+ copyright ? /* @__PURE__ */ jsx2("p", { children: copyright }) : null
793
+ ] }),
794
+ /* @__PURE__ */ jsxs2("nav", { className: "rt-tpl-footer-policy", "aria-label": "\uBC95\uC801 \uACE0\uC9C0", children: [
795
+ privacyHref ? /* @__PURE__ */ jsx2("a", { href: privacyHref, children: "\uAC1C\uC778\uC815\uBCF4\uCC98\uB9AC\uBC29\uCE68" }) : null,
796
+ termsHref ? /* @__PURE__ */ jsx2("a", { href: termsHref, children: "\uC774\uC6A9\uC57D\uAD00" }) : null,
797
+ socialLinks?.map((link) => /* @__PURE__ */ jsx2("a", { href: link.href, children: link.kind }, `${link.kind}-${link.href}`))
798
+ ] }),
799
+ credit === "hidden" ? null : /* @__PURE__ */ jsxs2("p", { className: "rt-tpl-footer-credit", children: [
800
+ "Website by",
801
+ " ",
802
+ /* @__PURE__ */ jsx2("a", { href: "https://roottale.com", target: "_blank", rel: "noopener", children: "RootTale" })
803
+ ] })
804
+ ] });
805
+ }
806
+ function TemplateFooterColumns(section) {
807
+ const { columns, contactInfo } = section.props;
808
+ return /* @__PURE__ */ jsx2(
809
+ "footer",
810
+ {
811
+ role: "contentinfo",
812
+ "data-roottale-tpl": "footer",
813
+ "data-variant": "columns",
814
+ id: section.id,
815
+ className: "rt-tpl-footer",
816
+ style: sectionThemeStyle(section.theme),
817
+ children: /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-container", children: [
818
+ /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-footer-columns", children: [
819
+ /* @__PURE__ */ jsx2(FooterBrand, { ...section }),
820
+ /* @__PURE__ */ jsx2("nav", { className: "rt-tpl-footer-nav", "aria-label": "\uD478\uD130 \uB9C1\uD06C", children: (columns ?? []).map((column) => /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-footer-column", children: [
821
+ /* @__PURE__ */ jsx2("p", { className: "rt-tpl-footer-column-title", children: column.title }),
822
+ /* @__PURE__ */ jsx2("ul", { children: column.links.map((link) => /* @__PURE__ */ jsx2("li", { children: /* @__PURE__ */ jsx2("a", { href: link.href, children: link.label }) }, `${column.title}-${link.label}-${link.href}`)) })
823
+ ] }, column.title)) }),
824
+ /* @__PURE__ */ jsx2(FooterContact, { contactInfo })
825
+ ] }),
826
+ /* @__PURE__ */ jsx2(FooterLegal, { ...section })
827
+ ] })
828
+ }
829
+ );
830
+ }
831
+ function TemplateFooterMinimal(section) {
832
+ return /* @__PURE__ */ jsx2(
833
+ "footer",
834
+ {
835
+ role: "contentinfo",
836
+ "data-roottale-tpl": "footer",
837
+ "data-variant": "minimal",
838
+ id: section.id,
839
+ className: "rt-tpl-footer rt-tpl-footer--minimal",
840
+ style: sectionThemeStyle(section.theme),
841
+ children: /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-container", children: [
842
+ /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-footer-minimal-row", children: [
843
+ /* @__PURE__ */ jsx2(FooterBrand, { ...section }),
844
+ /* @__PURE__ */ jsx2(FooterContact, { contactInfo: section.props.contactInfo })
845
+ ] }),
846
+ /* @__PURE__ */ jsx2(FooterLegal, { ...section })
847
+ ] })
848
+ }
849
+ );
850
+ }
851
+ function TemplateFooter(section) {
852
+ if (section.variant === "minimal") return TemplateFooterMinimal(section);
853
+ return TemplateFooterColumns(section);
854
+ }
855
+ function faqItemsForJsonLd(section) {
856
+ if (section.props.groups && section.props.groups.length > 0) {
857
+ return section.props.groups.flatMap((group) => group.items);
858
+ }
859
+ return section.props.items ?? [];
860
+ }
861
+ function TemplateFaqAccordion(section) {
862
+ const { heading, items, contact } = section.props;
863
+ const list = items ?? [];
864
+ return /* @__PURE__ */ jsxs2(
865
+ "div",
866
+ {
867
+ className: section.variant === "with-contact" ? "rt-tpl-faq-with-contact" : void 0,
868
+ children: [
869
+ /* @__PURE__ */ jsxs2("div", { children: [
870
+ heading ? /* @__PURE__ */ jsx2("h2", { className: "rt-tpl-heading", children: heading }) : null,
871
+ /* @__PURE__ */ jsx2("div", { className: "rt-tpl-faq-list", children: list.map((item, i) => /* @__PURE__ */ jsxs2("details", { className: "rt-tpl-faq-item", children: [
872
+ /* @__PURE__ */ jsx2("summary", { className: "rt-tpl-faq-q", children: item.question }),
873
+ /* @__PURE__ */ jsx2("p", { className: "rt-tpl-faq-a", children: item.answer })
874
+ ] }, i)) })
875
+ ] }),
876
+ section.variant === "with-contact" && contact ? /* @__PURE__ */ jsxs2("aside", { className: "rt-tpl-faq-contact", "aria-label": "\uC0C1\uB2F4 \uBB38\uC758", children: [
877
+ /* @__PURE__ */ jsx2("h3", { className: "rt-tpl-faq-contact-title", children: contact.title }),
878
+ contact.description ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-faq-contact-desc", children: contact.description }) : null,
879
+ contact.phone ? /* @__PURE__ */ jsx2(
880
+ "a",
881
+ {
882
+ className: "rt-tpl-faq-contact-phone",
883
+ href: telHref(contact.phone),
884
+ "data-track": "cta_call",
885
+ children: contact.phone
886
+ }
887
+ ) : null,
888
+ contact.cta ? /* @__PURE__ */ jsx2(
889
+ CtaLink,
890
+ {
891
+ cta: contact.cta,
892
+ track: ctaTrackForHref(contact.cta.href),
893
+ className: "rt-tpl-btn rt-tpl-btn--primary rt-tpl-faq-contact-cta"
894
+ }
895
+ ) : null
896
+ ] }) : null
897
+ ]
898
+ }
899
+ );
900
+ }
901
+ function TemplateFaqTwoColumn(section) {
902
+ const { heading, items, groups } = section.props;
903
+ const hasGroups = Boolean(groups && groups.length > 0);
904
+ return /* @__PURE__ */ jsxs2(Fragment2, { children: [
905
+ heading ? /* @__PURE__ */ jsx2("h2", { className: "rt-tpl-heading", children: heading }) : null,
906
+ hasGroups ? /* @__PURE__ */ jsx2("div", { className: "rt-tpl-faq-groups", children: (groups ?? []).map((group) => /* @__PURE__ */ jsxs2("section", { className: "rt-tpl-faq-group", children: [
907
+ /* @__PURE__ */ jsx2("h3", { className: "rt-tpl-faq-group-title", children: group.title }),
908
+ /* @__PURE__ */ jsx2("div", { className: "rt-tpl-faq-two-column-list", children: group.items.map((item, i) => /* @__PURE__ */ jsxs2("article", { className: "rt-tpl-faq-open-item", children: [
909
+ /* @__PURE__ */ jsx2("h4", { className: "rt-tpl-faq-open-q", children: item.question }),
910
+ /* @__PURE__ */ jsx2("p", { className: "rt-tpl-faq-open-a", children: item.answer })
911
+ ] }, `${group.title}-${i}`)) })
912
+ ] }, group.title)) }) : /* @__PURE__ */ jsx2("div", { className: "rt-tpl-faq-two-column-list", children: (items ?? []).map((item, i) => /* @__PURE__ */ jsxs2("article", { className: "rt-tpl-faq-open-item", children: [
913
+ /* @__PURE__ */ jsx2("h3", { className: "rt-tpl-faq-open-q", children: item.question }),
914
+ /* @__PURE__ */ jsx2("p", { className: "rt-tpl-faq-open-a", children: item.answer })
915
+ ] }, i)) })
916
+ ] });
917
+ }
918
+ function TemplateFaqContentAccordion(section) {
919
+ const { heading, contentGroups } = section.props;
920
+ return /* @__PURE__ */ jsxs2(Fragment2, { children: [
921
+ heading ? /* @__PURE__ */ jsx2("h2", { className: "rt-tpl-heading", children: heading }) : null,
922
+ /* @__PURE__ */ jsx2("div", { className: "rt-tpl-faq-content-groups", children: (contentGroups ?? []).map((group) => /* @__PURE__ */ jsxs2("section", { className: "rt-tpl-faq-content-group", children: [
923
+ /* @__PURE__ */ jsx2("h3", { className: "rt-tpl-faq-group-title", children: group.title }),
924
+ /* @__PURE__ */ jsx2("div", { className: "rt-tpl-faq-list", children: group.items.map((item) => /* @__PURE__ */ jsxs2("details", { className: "rt-tpl-faq-item", children: [
925
+ /* @__PURE__ */ jsxs2("summary", { className: "rt-tpl-faq-q", children: [
926
+ /* @__PURE__ */ jsx2("span", { children: item.title }),
927
+ item.summary ? /* @__PURE__ */ jsx2("small", { children: item.summary }) : null
928
+ ] }),
929
+ /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-faq-a rt-tpl-faq-content-body", children: [
930
+ /* @__PURE__ */ jsx2("p", { children: item.body }),
931
+ item.signs && item.signs.length > 0 ? /* @__PURE__ */ jsx2("ul", { className: "rt-tpl-faq-content-signs", children: item.signs.map((sign) => /* @__PURE__ */ jsx2("li", { children: sign }, sign)) }) : null,
932
+ item.href ? /* @__PURE__ */ jsx2("a", { className: "rt-tpl-faq-content-link", href: item.href, children: "\uC790\uC138\uD788 \uBCF4\uAE30" }) : null
933
+ ] })
934
+ ] }, item.title)) })
935
+ ] }, group.title)) })
936
+ ] });
937
+ }
938
+ function TemplateFaq(section) {
939
+ const { jsonLd } = section.props;
940
+ const jsonLdItems = faqItemsForJsonLd(section);
941
+ return /* @__PURE__ */ jsxs2(
942
+ "section",
943
+ {
944
+ "data-roottale-tpl": "faq",
945
+ "data-variant": section.variant,
946
+ id: section.id,
947
+ className: "rt-tpl-section rt-tpl-faq",
948
+ style: sectionThemeStyle(section.theme),
949
+ children: [
950
+ /* @__PURE__ */ jsx2("div", { className: "rt-tpl-container", children: section.variant === "content-accordion" ? TemplateFaqContentAccordion(section) : section.variant === "two-column" ? TemplateFaqTwoColumn(section) : TemplateFaqAccordion(section) }),
951
+ section.variant !== "content-accordion" && jsonLd && jsonLdItems.length > 0 ? /* @__PURE__ */ jsx2(
952
+ "script",
953
+ {
954
+ type: "application/ld+json",
955
+ dangerouslySetInnerHTML: {
956
+ __html: JSON.stringify({
957
+ "@context": "https://schema.org",
958
+ "@type": "FAQPage",
959
+ mainEntity: jsonLdItems.map((item) => ({
960
+ "@type": "Question",
961
+ name: item.question,
962
+ acceptedAnswer: { "@type": "Answer", text: item.answer }
963
+ }))
964
+ })
965
+ }
966
+ }
967
+ ) : null
968
+ ]
969
+ }
970
+ );
971
+ }
972
+ function TemplateCtaBannerPhotoOverlay(section) {
973
+ const { title, description, cta, image, imageAlt } = section.props;
974
+ return /* @__PURE__ */ jsx2(
975
+ "section",
976
+ {
977
+ "data-roottale-tpl": "cta-banner",
978
+ "data-variant": "photo-overlay",
979
+ id: section.id,
980
+ className: "rt-tpl-section rt-tpl-cta-banner rt-tpl-cta-banner--photo-overlay",
981
+ style: sectionThemeStyle(section.theme),
982
+ children: /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-cta-banner-photo", children: [
983
+ /* @__PURE__ */ jsx2(
984
+ "img",
985
+ {
986
+ className: "rt-tpl-cta-banner-photo-img",
987
+ src: image ?? "",
988
+ alt: imageAlt ?? "",
989
+ loading: "lazy"
990
+ }
991
+ ),
992
+ /* @__PURE__ */ jsx2("div", { className: "rt-tpl-cta-banner-photo-scrim", "aria-hidden": "true" }),
993
+ /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-container rt-tpl-cta-banner-photo-inner", children: [
994
+ /* @__PURE__ */ jsx2("h2", { className: "rt-tpl-cta-banner-photo-title", children: title }),
995
+ description ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-cta-banner-photo-desc", children: description }) : null,
996
+ cta ? /* @__PURE__ */ jsx2(
997
+ CtaLink,
998
+ {
999
+ cta,
1000
+ track: "cta_banner",
1001
+ className: "rt-tpl-btn rt-tpl-btn--primary rt-tpl-cta-banner-photo-cta"
1002
+ }
1003
+ ) : null
1004
+ ] })
1005
+ ] })
1006
+ }
1007
+ );
1008
+ }
1009
+ function TemplateCtaBanner(section) {
1010
+ if (section.variant === "photo-overlay")
1011
+ return TemplateCtaBannerPhotoOverlay(section);
1012
+ const { title, description, cta } = section.props;
1013
+ return /* @__PURE__ */ jsx2(
1014
+ "section",
1015
+ {
1016
+ "data-roottale-tpl": "cta-banner",
1017
+ "data-variant": section.variant,
1018
+ id: section.id,
1019
+ className: "rt-tpl-section rt-tpl-cta-banner",
1020
+ style: sectionThemeStyle(section.theme),
1021
+ children: /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-container rt-tpl-cta-banner-inner", children: [
1022
+ /* @__PURE__ */ jsx2("h2", { className: "rt-tpl-cta-banner-title", children: title }),
1023
+ description ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-cta-banner-desc", children: description }) : null,
1024
+ cta ? /* @__PURE__ */ jsx2(CtaLink, { cta, track: "cta_banner" }) : null
1025
+ ] })
1026
+ }
1027
+ );
1028
+ }
1029
+ function TrustCredentialIcon() {
1030
+ return /* @__PURE__ */ jsxs2(
1031
+ "svg",
1032
+ {
1033
+ className: "rt-cred__icon",
1034
+ viewBox: "0 0 16 16",
1035
+ "aria-hidden": "true",
1036
+ focusable: "false",
1037
+ children: [
1038
+ /* @__PURE__ */ jsx2("path", { d: "M8 1.75 13 3.5v3.75c0 3-2 5.45-5 7-3-1.55-5-4-5-7V3.5z" }),
1039
+ /* @__PURE__ */ jsx2("path", { d: "m5.75 8 1.45 1.45 3.2-3.4" })
1040
+ ]
1041
+ }
1042
+ );
1043
+ }
1044
+ function TemplateTrust(section) {
1045
+ const { heading, metrics, credentials, logos, marqueeLogos, chart, disclaimer } = section.props;
1046
+ const chartMax = chart?.points.reduce((max, point) => Math.max(max, point.value), 0) ?? 0;
1047
+ return /* @__PURE__ */ jsx2(
1048
+ "section",
1049
+ {
1050
+ "data-roottale-tpl": "trust",
1051
+ "data-variant": section.variant,
1052
+ id: section.id,
1053
+ className: "rt-tpl-section rt-tpl-trust",
1054
+ style: sectionThemeStyle(section.theme),
1055
+ children: /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-container rt-tpl-trust-inner", children: [
1056
+ heading ? /* @__PURE__ */ jsx2("h2", { className: "rt-tpl-heading", children: heading }) : null,
1057
+ section.variant === "stat-band" ? (
1058
+ // 수치 밴드 진입 시 fade-up(C8). 카운트업은 미채택 — 이 seed 의
1059
+ // disclaimer 계약("과장된 카운트업 모션 미사용")과 tabular-nums 결정성
1060
+ // 유지를 위해 즉시-표시. reduce·SSR 시 <div> 그대로(마크업 불변).
1061
+ /* @__PURE__ */ jsx2(AnimateOnScroll, { as: "div", variant: "fade-up", className: "rt-tpl-trust-stat-band", children: (metrics ?? []).map((metric) => /* @__PURE__ */ jsxs2(
1062
+ "div",
1063
+ {
1064
+ className: "rt-stat",
1065
+ "data-variant": "band-item",
1066
+ children: [
1067
+ /* @__PURE__ */ jsxs2("span", { className: "rt-stat__value", children: [
1068
+ metric.value,
1069
+ metric.unit ? /* @__PURE__ */ jsx2("span", { className: "rt-stat__unit", children: metric.unit }) : null
1070
+ ] }),
1071
+ /* @__PURE__ */ jsx2("span", { className: "rt-stat__label", children: metric.label }),
1072
+ metric.source ? /* @__PURE__ */ jsx2("span", { className: "rt-stat__source", children: metric.source }) : null
1073
+ ]
1074
+ },
1075
+ `${metric.value}-${metric.label}`
1076
+ )) })
1077
+ ) : null,
1078
+ section.variant === "logo-cloud" ? /* @__PURE__ */ jsx2("ul", { className: "rt-tpl-trust-logo-list", children: (logos ?? []).map((logo) => /* @__PURE__ */ jsx2("li", { className: "rt-tpl-trust-logo-item", children: logo.href ? /* @__PURE__ */ jsx2("a", { className: "rt-tpl-trust-logo-link", href: logo.href, children: /* @__PURE__ */ jsx2(
1079
+ "img",
1080
+ {
1081
+ className: "rt-tpl-trust-logo",
1082
+ src: logo.src,
1083
+ alt: logo.alt,
1084
+ loading: "lazy"
1085
+ }
1086
+ ) }) : /* @__PURE__ */ jsx2(
1087
+ "img",
1088
+ {
1089
+ className: "rt-tpl-trust-logo",
1090
+ src: logo.src,
1091
+ alt: logo.alt,
1092
+ loading: "lazy"
1093
+ }
1094
+ ) }, `${logo.src}-${logo.alt}`)) }) : null,
1095
+ section.variant === "feature-grid" ? /* @__PURE__ */ jsx2("ul", { className: "rt-tpl-trust-cred-list", children: (credentials ?? []).map((credential) => /* @__PURE__ */ jsx2("li", { children: /* @__PURE__ */ jsxs2("span", { className: "rt-cred", "data-kind": credential.kind, children: [
1096
+ /* @__PURE__ */ jsx2(TrustCredentialIcon, {}),
1097
+ /* @__PURE__ */ jsx2("span", { className: "rt-cred__label", children: credential.name }),
1098
+ credential.issuer ? /* @__PURE__ */ jsx2("span", { className: "rt-cred__issuer", children: credential.issuer }) : null
1099
+ ] }) }, `${credential.name}-${credential.issuer ?? ""}`)) }) : null,
1100
+ section.variant === "logo-marquee" ? (
1101
+ // C8 Marquee 소비(직접 재구현 금지, C10 §1-3). 로고는 흑백/저채도
1102
+ // 처리(CSS filter) — hover 시에만 원색 복원.
1103
+ /* @__PURE__ */ jsx2(
1104
+ Marquee,
1105
+ {
1106
+ className: "rt-tpl-trust-marquee",
1107
+ ariaLabel: heading ?? "\uD30C\uD2B8\uB108/\uC778\uC99D \uB85C\uACE0",
1108
+ children: (marqueeLogos ?? []).map(
1109
+ (logo, i) => logo.href ? /* @__PURE__ */ jsx2(
1110
+ "a",
1111
+ {
1112
+ className: "rt-tpl-trust-marquee-link",
1113
+ href: logo.href,
1114
+ children: /* @__PURE__ */ jsx2(
1115
+ "img",
1116
+ {
1117
+ className: "rt-tpl-trust-marquee-logo",
1118
+ src: logo.src,
1119
+ alt: logo.alt,
1120
+ loading: "lazy"
1121
+ }
1122
+ )
1123
+ },
1124
+ `${logo.alt}-${i}`
1125
+ ) : /* @__PURE__ */ jsx2(
1126
+ "img",
1127
+ {
1128
+ className: "rt-tpl-trust-marquee-logo",
1129
+ src: logo.src,
1130
+ alt: logo.alt,
1131
+ loading: "lazy"
1132
+ },
1133
+ `${logo.alt}-${i}`
1134
+ )
1135
+ )
1136
+ }
1137
+ )
1138
+ ) : null,
1139
+ section.variant === "credential-list" ? (
1140
+ // hairline 자격·이력·수상 리스트 — 연도는 tabular-nums, 위계는
1141
+ // 작은 크기로(AI-slop #3 대체: 장식용 큰 숫자 금지).
1142
+ /* @__PURE__ */ jsx2("ol", { className: "rt-tpl-trust-credential-list", children: (credentials ?? []).map((credential, i) => /* @__PURE__ */ jsxs2(
1143
+ "li",
1144
+ {
1145
+ className: "rt-tpl-trust-credential-row",
1146
+ children: [
1147
+ credential.year ? /* @__PURE__ */ jsx2("span", { className: "rt-tpl-trust-credential-year", children: credential.year }) : null,
1148
+ /* @__PURE__ */ jsx2("span", { className: "rt-tpl-trust-credential-name", children: credential.name }),
1149
+ credential.issuer ? /* @__PURE__ */ jsx2("span", { className: "rt-tpl-trust-credential-issuer", children: credential.issuer }) : null
1150
+ ]
1151
+ },
1152
+ `${credential.name}-${credential.year ?? i}`
1153
+ )) })
1154
+ ) : null,
1155
+ section.variant === "dashboard" && chart ? /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-trust-dashboard", children: [
1156
+ /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-trust-dashboard-chart", children: [
1157
+ /* @__PURE__ */ jsxs2("div", { children: [
1158
+ /* @__PURE__ */ jsx2("h3", { className: "rt-tpl-trust-dashboard-title", children: chart.title }),
1159
+ chart.description ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-trust-dashboard-desc", children: chart.description }) : null
1160
+ ] }),
1161
+ /* @__PURE__ */ jsx2(
1162
+ "ul",
1163
+ {
1164
+ className: "rt-tpl-trust-dashboard-bars",
1165
+ "data-chart-type": chart.type,
1166
+ children: chart.points.map((point) => {
1167
+ const percent = chartMax > 0 ? `${Math.max(4, Math.round(point.value / chartMax * 100))}%` : "4%";
1168
+ return /* @__PURE__ */ jsxs2("li", { children: [
1169
+ /* @__PURE__ */ jsx2("span", { children: point.label }),
1170
+ /* @__PURE__ */ jsx2("span", { className: "rt-tpl-trust-dashboard-track", children: /* @__PURE__ */ jsx2(
1171
+ "span",
1172
+ {
1173
+ className: "rt-tpl-trust-dashboard-bar",
1174
+ style: { inlineSize: percent }
1175
+ }
1176
+ ) }),
1177
+ /* @__PURE__ */ jsx2("strong", { children: point.display ?? String(point.value) })
1178
+ ] }, point.label);
1179
+ })
1180
+ }
1181
+ )
1182
+ ] }),
1183
+ /* @__PURE__ */ jsx2("ul", { className: "rt-tpl-trust-dashboard-metrics", children: (metrics ?? []).map((metric) => /* @__PURE__ */ jsxs2("li", { className: "rt-stat", children: [
1184
+ metric.imageSrc ? /* @__PURE__ */ jsx2(
1185
+ "img",
1186
+ {
1187
+ className: "rt-tpl-trust-dashboard-icon",
1188
+ src: metric.imageSrc,
1189
+ alt: metric.imageAlt ?? "",
1190
+ loading: "lazy"
1191
+ }
1192
+ ) : null,
1193
+ /* @__PURE__ */ jsxs2("span", { className: "rt-stat__value", children: [
1194
+ metric.value,
1195
+ metric.unit ? /* @__PURE__ */ jsx2("span", { className: "rt-stat__unit", children: metric.unit }) : null
1196
+ ] }),
1197
+ /* @__PURE__ */ jsx2("span", { className: "rt-stat__label", children: metric.label }),
1198
+ metric.source ? /* @__PURE__ */ jsx2("span", { className: "rt-stat__source", children: metric.source }) : null
1199
+ ] }, `${metric.value}-${metric.label}`)) })
1200
+ ] }) : null,
1201
+ disclaimer ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-trust-disclaimer", children: disclaimer }) : null
1202
+ ] })
1203
+ }
1204
+ );
1205
+ }
1206
+ function TemplateTestimonialsEditorialQuote(section) {
1207
+ const { heading, description, items, disclaimer } = section.props;
1208
+ const layout = items.length > 1 ? "stack" : "single";
1209
+ return /* @__PURE__ */ jsx2(
1210
+ "section",
1211
+ {
1212
+ "data-roottale-tpl": "testimonials",
1213
+ "data-variant": "editorial-quote",
1214
+ id: section.id,
1215
+ className: "rt-tpl-section rt-tpl-testimonials",
1216
+ style: sectionThemeStyle(section.theme),
1217
+ children: /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-container", children: [
1218
+ /* @__PURE__ */ jsx2("h2", { className: "rt-tpl-heading", children: heading }),
1219
+ description ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-section-desc", children: description }) : null,
1220
+ /* @__PURE__ */ jsx2(
1221
+ StaggerGroup,
1222
+ {
1223
+ as: "ul",
1224
+ className: `rt-tpl-testimonials-editorial-list rt-tpl-testimonials-editorial-list--${layout}`,
1225
+ children: items.map((item, i) => /* @__PURE__ */ jsx2(
1226
+ StaggerItem,
1227
+ {
1228
+ as: "li",
1229
+ className: "rt-tpl-testimonials-editorial-item",
1230
+ children: /* @__PURE__ */ jsxs2("blockquote", { className: "rt-tpl-testimonials-editorial-quote", children: [
1231
+ /* @__PURE__ */ jsx2("p", { className: "rt-tpl-testimonials-editorial-text", children: item.quote }),
1232
+ /* @__PURE__ */ jsxs2("footer", { className: "rt-tpl-testimonials-editorial-footer", children: [
1233
+ /* @__PURE__ */ jsx2("cite", { className: "rt-tpl-testimonials-editorial-author", children: item.author }),
1234
+ item.context ? /* @__PURE__ */ jsx2("span", { className: "rt-tpl-testimonials-editorial-context", children: item.context }) : null,
1235
+ /* @__PURE__ */ jsx2(TestimonialMeta, { item })
1236
+ ] }),
1237
+ item.reply ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-testimonials-reply", children: item.reply }) : null
1238
+ ] })
1239
+ },
1240
+ `${item.author}-${i}`
1241
+ ))
1242
+ }
1243
+ ),
1244
+ disclaimer ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-testimonials-disclaimer", children: disclaimer }) : null
1245
+ ] })
1246
+ }
1247
+ );
1248
+ }
1249
+ function TestimonialMeta({
1250
+ item
1251
+ }) {
1252
+ const values = [
1253
+ typeof item.rating === "number" ? `\uD3C9\uC810 ${item.rating.toFixed(1)}` : void 0,
1254
+ item.source,
1255
+ item.visitedAt,
1256
+ item.item
1257
+ ].filter((value) => Boolean(value));
1258
+ if (values.length === 0) return null;
1259
+ return /* @__PURE__ */ jsx2("span", { className: "rt-tpl-testimonials-meta", children: values.map((value) => /* @__PURE__ */ jsx2("span", { children: value }, value)) });
1260
+ }
1261
+ function TemplateTestimonialsQuoteRail(section) {
1262
+ const { heading, description, items, marquee, disclaimer } = section.props;
1263
+ return /* @__PURE__ */ jsx2(
1264
+ "section",
1265
+ {
1266
+ "data-roottale-tpl": "testimonials",
1267
+ "data-variant": "quote-rail",
1268
+ id: section.id,
1269
+ className: "rt-tpl-section rt-tpl-testimonials",
1270
+ style: sectionThemeStyle(section.theme),
1271
+ children: /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-container", children: [
1272
+ /* @__PURE__ */ jsx2("h2", { className: "rt-tpl-heading", children: heading }),
1273
+ description ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-section-desc", children: description }) : null,
1274
+ /* @__PURE__ */ jsx2(
1275
+ AnimateOnScroll,
1276
+ {
1277
+ as: "div",
1278
+ variant: "fade-up",
1279
+ className: "rt-tpl-testimonials-rail-viewport",
1280
+ children: /* @__PURE__ */ jsx2(
1281
+ "ul",
1282
+ {
1283
+ className: marquee ? "rt-tpl-testimonials-rail rt-tpl-testimonials-rail--marquee" : "rt-tpl-testimonials-rail",
1284
+ "data-marquee": marquee ? "true" : void 0,
1285
+ children: items.map((item, i) => /* @__PURE__ */ jsx2(
1286
+ "li",
1287
+ {
1288
+ className: "rt-tpl-testimonials-rail-item",
1289
+ children: /* @__PURE__ */ jsxs2("blockquote", { className: "rt-tpl-testimonials-rail-quote", children: [
1290
+ /* @__PURE__ */ jsx2("p", { className: "rt-tpl-testimonials-rail-text", children: item.quote }),
1291
+ /* @__PURE__ */ jsxs2("footer", { className: "rt-tpl-testimonials-rail-footer", children: [
1292
+ /* @__PURE__ */ jsx2("cite", { className: "rt-tpl-testimonials-rail-author", children: item.author }),
1293
+ item.context ? /* @__PURE__ */ jsx2("span", { className: "rt-tpl-testimonials-rail-context", children: item.context }) : null,
1294
+ /* @__PURE__ */ jsx2(TestimonialMeta, { item })
1295
+ ] }),
1296
+ item.reply ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-testimonials-reply", children: item.reply }) : null
1297
+ ] })
1298
+ },
1299
+ `${item.author}-${i}`
1300
+ ))
1301
+ }
1302
+ )
1303
+ }
1304
+ ),
1305
+ disclaimer ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-testimonials-disclaimer", children: disclaimer }) : null
1306
+ ] })
1307
+ }
1308
+ );
1309
+ }
1310
+ function TemplateTestimonials(section) {
1311
+ if (section.variant === "quote-rail")
1312
+ return TemplateTestimonialsQuoteRail(section);
1313
+ return TemplateTestimonialsEditorialQuote(section);
1314
+ }
1315
+ function memberInitials(name) {
1316
+ const parts = name.trim().split(/\s+/).filter(Boolean);
1317
+ if (parts.length === 0) return "?";
1318
+ const initials = parts.slice(0, 2).map((part) => part.at(0) ?? "").join("");
1319
+ return initials || "?";
1320
+ }
1321
+ function TeamMemberPhoto({
1322
+ member,
1323
+ featured = false
1324
+ }) {
1325
+ if (member.photoSrc) {
1326
+ return /* @__PURE__ */ jsx2(
1327
+ "img",
1328
+ {
1329
+ className: featured ? "rt-tpl-team-photo rt-tpl-team-photo--featured" : "rt-tpl-team-photo",
1330
+ src: member.photoSrc,
1331
+ alt: member.photoAlt ?? "",
1332
+ loading: "lazy"
1333
+ }
1334
+ );
1335
+ }
1336
+ return /* @__PURE__ */ jsx2(
1337
+ "div",
1338
+ {
1339
+ className: featured ? "rt-tpl-team-initials rt-tpl-team-initials--featured" : "rt-tpl-team-initials",
1340
+ "aria-hidden": "true",
1341
+ children: memberInitials(member.name)
1342
+ }
1343
+ );
1344
+ }
1345
+ function TeamMemberBody({
1346
+ member
1347
+ }) {
1348
+ return /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-team-body", children: [
1349
+ /* @__PURE__ */ jsx2("h3", { className: "rt-tpl-team-name", children: member.name }),
1350
+ /* @__PURE__ */ jsx2("p", { className: "rt-tpl-team-title", children: member.title }),
1351
+ member.specialties ? /* @__PURE__ */ jsx2("ul", { className: "rt-tpl-team-specialties", "aria-label": `${member.name} \uC804\uBB38 \uBD84\uC57C`, children: member.specialties.map((specialty) => /* @__PURE__ */ jsx2("li", { children: specialty }, specialty)) }) : null,
1352
+ member.credentials ? /* @__PURE__ */ jsx2("ul", { className: "rt-tpl-team-credentials", children: member.credentials.map((credential) => /* @__PURE__ */ jsx2("li", { children: credential }, credential)) }) : null,
1353
+ member.bio ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-team-bio", children: member.bio }) : null,
1354
+ member.href ? /* @__PURE__ */ jsx2("a", { className: "rt-tpl-team-cta", href: member.href, children: member.ctaLabel ?? "\uD504\uB85C\uD544 \uBCF4\uAE30" }) : null
1355
+ ] });
1356
+ }
1357
+ function TemplateTeamGrid(section) {
1358
+ const { heading, description, members } = section.props;
1359
+ return /* @__PURE__ */ jsx2(
1360
+ "section",
1361
+ {
1362
+ "data-roottale-tpl": "team",
1363
+ "data-variant": "grid",
1364
+ id: section.id,
1365
+ className: "rt-tpl-section rt-tpl-team",
1366
+ style: sectionThemeStyle(section.theme),
1367
+ children: /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-container", children: [
1368
+ heading ? /* @__PURE__ */ jsx2("h2", { className: "rt-tpl-heading", children: heading }) : null,
1369
+ description ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-section-desc", children: description }) : null,
1370
+ /* @__PURE__ */ jsx2(StaggerGroup, { as: "ul", className: "rt-tpl-team-grid", children: members.map((member) => /* @__PURE__ */ jsxs2(StaggerItem, { as: "li", className: "rt-tpl-team-card", children: [
1371
+ /* @__PURE__ */ jsx2(TeamMemberPhoto, { member }),
1372
+ /* @__PURE__ */ jsx2(TeamMemberBody, { member })
1373
+ ] }, member.name)) })
1374
+ ] })
1375
+ }
1376
+ );
1377
+ }
1378
+ function TemplateTeamSpotlight(section) {
1379
+ const { heading, description, members } = section.props;
1380
+ const [featured, ...rest] = members;
1381
+ return /* @__PURE__ */ jsx2(
1382
+ "section",
1383
+ {
1384
+ "data-roottale-tpl": "team",
1385
+ "data-variant": "spotlight",
1386
+ id: section.id,
1387
+ className: "rt-tpl-section rt-tpl-team",
1388
+ style: sectionThemeStyle(section.theme),
1389
+ children: /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-container", children: [
1390
+ heading ? /* @__PURE__ */ jsx2("h2", { className: "rt-tpl-heading", children: heading }) : null,
1391
+ description ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-section-desc", children: description }) : null,
1392
+ /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-team-spotlight", children: [
1393
+ featured ? /* @__PURE__ */ jsxs2("article", { className: "rt-tpl-team-card rt-tpl-team-card--featured", children: [
1394
+ /* @__PURE__ */ jsx2(TeamMemberPhoto, { member: featured, featured: true }),
1395
+ /* @__PURE__ */ jsx2(TeamMemberBody, { member: featured })
1396
+ ] }) : null,
1397
+ /* @__PURE__ */ jsx2(StaggerGroup, { as: "ul", className: "rt-tpl-team-spotlight-list", children: rest.map((member) => /* @__PURE__ */ jsxs2(StaggerItem, { as: "li", className: "rt-tpl-team-card", children: [
1398
+ /* @__PURE__ */ jsx2(TeamMemberPhoto, { member }),
1399
+ /* @__PURE__ */ jsx2(TeamMemberBody, { member })
1400
+ ] }, member.name)) })
1401
+ ] })
1402
+ ] })
1403
+ }
1404
+ );
1405
+ }
1406
+ function TemplateTeamExpandingStage(section) {
1407
+ const { heading, description, members } = section.props;
1408
+ return /* @__PURE__ */ jsx2(
1409
+ "section",
1410
+ {
1411
+ "data-roottale-tpl": "team",
1412
+ "data-variant": "expanding-stage",
1413
+ id: section.id,
1414
+ className: "rt-tpl-section rt-tpl-team",
1415
+ style: sectionThemeStyle(section.theme),
1416
+ children: /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-container", children: [
1417
+ heading ? /* @__PURE__ */ jsx2("h2", { className: "rt-tpl-heading", children: heading }) : null,
1418
+ description ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-section-desc", children: description }) : null,
1419
+ /* @__PURE__ */ jsx2("ul", { className: "rt-tpl-team-expanding-stage", children: members.map((member, index) => /* @__PURE__ */ jsx2("li", { className: "rt-tpl-team-expanding-item", children: /* @__PURE__ */ jsxs2("article", { className: "rt-tpl-team-card", children: [
1420
+ /* @__PURE__ */ jsx2("span", { className: "rt-tpl-team-expanding-index", "aria-hidden": "true", children: String(index + 1).padStart(2, "0") }),
1421
+ /* @__PURE__ */ jsx2(TeamMemberPhoto, { member }),
1422
+ /* @__PURE__ */ jsx2(TeamMemberBody, { member })
1423
+ ] }) }, member.name)) })
1424
+ ] })
1425
+ }
1426
+ );
1427
+ }
1428
+ function TemplateTeamRow(section) {
1429
+ const { heading, description, members } = section.props;
1430
+ return /* @__PURE__ */ jsx2(
1431
+ "section",
1432
+ {
1433
+ "data-roottale-tpl": "team",
1434
+ "data-variant": "row",
1435
+ id: section.id,
1436
+ className: "rt-tpl-section rt-tpl-team",
1437
+ style: sectionThemeStyle(section.theme),
1438
+ children: /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-container", children: [
1439
+ heading ? /* @__PURE__ */ jsx2("h2", { className: "rt-tpl-heading", children: heading }) : null,
1440
+ description ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-section-desc", children: description }) : null,
1441
+ /* @__PURE__ */ jsx2(StaggerGroup, { as: "ul", className: "rt-tpl-team-row-list", children: members.map((member) => /* @__PURE__ */ jsx2(StaggerItem, { as: "li", className: "rt-tpl-team-row-item", children: /* @__PURE__ */ jsxs2("article", { className: "rt-tpl-team-card rt-tpl-team-card--row", children: [
1442
+ /* @__PURE__ */ jsx2(TeamMemberPhoto, { member }),
1443
+ /* @__PURE__ */ jsx2(TeamMemberBody, { member })
1444
+ ] }) }, member.name)) })
1445
+ ] })
1446
+ }
1447
+ );
1448
+ }
1449
+ function TemplateTeam(section) {
1450
+ if (section.variant === "expanding-stage")
1451
+ return TemplateTeamExpandingStage(section);
1452
+ if (section.variant === "row") return TemplateTeamRow(section);
1453
+ if (section.variant === "spotlight") return TemplateTeamSpotlight(section);
1454
+ return TemplateTeamGrid(section);
1455
+ }
1456
+ function telHref(phone) {
1457
+ return `tel:${phone.replace(/[^\d+]/g, "")}`;
1458
+ }
1459
+ function ContactMap({ url }) {
1460
+ if (isAllowedEmbedSrc(url)) {
1461
+ return /* @__PURE__ */ jsx2("div", { className: "rt-tpl-contact-map", children: /* @__PURE__ */ jsx2(
1462
+ "iframe",
1463
+ {
1464
+ src: url,
1465
+ title: "\uC624\uC2DC\uB294\uAE38 \uC9C0\uB3C4",
1466
+ loading: "lazy",
1467
+ referrerPolicy: "no-referrer-when-downgrade"
1468
+ }
1469
+ ) });
1470
+ }
1471
+ return /* @__PURE__ */ jsx2("p", { className: "rt-tpl-contact-map-fallback", children: /* @__PURE__ */ jsx2("a", { href: url, rel: "noopener noreferrer", target: "_blank", children: "\uAE38\uCC3E\uAE30" }) });
1472
+ }
1473
+ function ContactMapBlock({
1474
+ map,
1475
+ mapEmbedUrl
1476
+ }) {
1477
+ const embedUrl = map?.embedUrl ?? mapEmbedUrl;
1478
+ const externalUrl = map?.externalUrl ?? embedUrl;
1479
+ if (!embedUrl && !map?.facadeImageSrc && !externalUrl) return null;
1480
+ return /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-contact-map-block", "data-provider": map?.provider, children: [
1481
+ map?.facadeImageSrc ? /* @__PURE__ */ jsxs2("figure", { className: "rt-tpl-contact-map-facade", children: [
1482
+ /* @__PURE__ */ jsx2(
1483
+ "img",
1484
+ {
1485
+ src: map.facadeImageSrc,
1486
+ alt: map.facadeImageAlt ?? "",
1487
+ loading: "lazy"
1488
+ }
1489
+ ),
1490
+ externalUrl ? /* @__PURE__ */ jsx2("figcaption", { children: /* @__PURE__ */ jsx2("a", { href: externalUrl, target: "_blank", rel: "noopener noreferrer", children: "\uC9C0\uB3C4 \uD06C\uAC8C \uBCF4\uAE30" }) }) : null
1491
+ ] }) : null,
1492
+ embedUrl ? /* @__PURE__ */ jsx2(ContactMap, { url: embedUrl }) : null
1493
+ ] });
1494
+ }
1495
+ function ContactActions({
1496
+ actions
1497
+ }) {
1498
+ if (!actions || actions.length === 0) return null;
1499
+ return /* @__PURE__ */ jsx2("ul", { className: "rt-tpl-contact-actions", children: actions.map((action) => /* @__PURE__ */ jsx2("li", { "data-kind": action.kind, children: /* @__PURE__ */ jsx2("a", { href: action.href, children: action.label }) }, `${action.label}-${action.href}`)) });
1500
+ }
1501
+ function TemplateContactChannelCards(section) {
1502
+ const { heading, channels, map, mapEmbedUrl, actions } = section.props;
1503
+ return /* @__PURE__ */ jsx2(
1504
+ "section",
1505
+ {
1506
+ "data-roottale-tpl": "contact",
1507
+ "data-variant": "channel-cards",
1508
+ id: section.id,
1509
+ className: "rt-tpl-section rt-tpl-contact",
1510
+ style: sectionThemeStyle(section.theme),
1511
+ children: /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-container", children: [
1512
+ heading ? /* @__PURE__ */ jsx2("h2", { className: "rt-tpl-heading", children: heading }) : null,
1513
+ /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-contact-channel-layout", children: [
1514
+ /* @__PURE__ */ jsx2("ul", { className: "rt-tpl-contact-channel-list", children: (channels ?? []).map((channel) => {
1515
+ const content = /* @__PURE__ */ jsxs2(Fragment2, { children: [
1516
+ /* @__PURE__ */ jsxs2("span", { className: "rt-tpl-contact-channel-label", children: [
1517
+ channel.iconSrc ? /* @__PURE__ */ jsx2(
1518
+ "img",
1519
+ {
1520
+ className: "rt-tpl-contact-channel-icon",
1521
+ src: channel.iconSrc,
1522
+ alt: channel.iconAlt ?? "",
1523
+ loading: "lazy"
1524
+ }
1525
+ ) : null,
1526
+ channel.label
1527
+ ] }),
1528
+ channel.value ? /* @__PURE__ */ jsx2("span", { className: "rt-tpl-contact-channel-value", children: channel.value }) : null,
1529
+ channel.description ? /* @__PURE__ */ jsx2("span", { className: "rt-tpl-contact-channel-desc", children: channel.description }) : null,
1530
+ channel.href && channel.actionLabel ? /* @__PURE__ */ jsx2("span", { className: "rt-tpl-contact-channel-action", children: channel.actionLabel }) : null
1531
+ ] });
1532
+ return /* @__PURE__ */ jsx2(
1533
+ "li",
1534
+ {
1535
+ "data-kind": channel.kind,
1536
+ children: channel.href ? /* @__PURE__ */ jsx2(
1537
+ "a",
1538
+ {
1539
+ className: "rt-tpl-contact-channel-card",
1540
+ href: channel.href,
1541
+ "data-track": channel.href.startsWith("tel:") ? "cta_call" : "cta_banner",
1542
+ children: content
1543
+ }
1544
+ ) : /* @__PURE__ */ jsx2("div", { className: "rt-tpl-contact-channel-card", children: content })
1545
+ },
1546
+ `${channel.label}-${channel.value ?? channel.href ?? ""}`
1547
+ );
1548
+ }) }),
1549
+ /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-contact-channel-side", children: [
1550
+ /* @__PURE__ */ jsx2(ContactMapBlock, { map, mapEmbedUrl }),
1551
+ /* @__PURE__ */ jsx2(ContactActions, { actions })
1552
+ ] })
1553
+ ] })
1554
+ ] })
1555
+ }
1556
+ );
1557
+ }
1558
+ function ContactHoursSummary({
1559
+ hours
1560
+ }) {
1561
+ if (!hours || hours.length === 0) return null;
1562
+ return /* @__PURE__ */ jsxs2("table", { className: "rt-tpl-contact-visit-hours", children: [
1563
+ /* @__PURE__ */ jsx2("caption", { className: "rt-tpl-sr-only", children: "\uC9C4\uB8CC\uC2DC\uAC04" }),
1564
+ /* @__PURE__ */ jsx2("tbody", { children: hours.map((row) => /* @__PURE__ */ jsxs2("tr", { children: [
1565
+ /* @__PURE__ */ jsx2("th", { scope: "row", children: row.day }),
1566
+ /* @__PURE__ */ jsxs2("td", { children: [
1567
+ /* @__PURE__ */ jsx2("span", { children: row.open }),
1568
+ /* @__PURE__ */ jsx2("span", { "aria-hidden": "true", children: "-" }),
1569
+ /* @__PURE__ */ jsx2("span", { children: row.close }),
1570
+ row.note ? /* @__PURE__ */ jsx2("span", { className: "rt-tpl-contact-hours-note", children: row.note }) : null
1571
+ ] })
1572
+ ] }, `${row.day}-${row.open}-${row.close}`)) })
1573
+ ] });
1574
+ }
1575
+ function TemplateContactVisitBand(section) {
1576
+ const { heading, phone, address, hours, map, mapEmbedUrl, actions } = section.props;
1577
+ const mapAction = actions?.find((action) => action.kind === "map") ?? actions?.[0];
1578
+ const ctaAction = actions?.find((action) => action.kind === "reserve" || action.kind === "call") ?? actions?.[1] ?? mapAction;
1579
+ const phoneAction = phone ? { label: phone, href: telHref(phone) } : void 0;
1580
+ return /* @__PURE__ */ jsx2(
1581
+ "section",
1582
+ {
1583
+ "data-roottale-tpl": "contact",
1584
+ "data-variant": "visit-band",
1585
+ id: section.id,
1586
+ className: "rt-tpl-section rt-tpl-contact",
1587
+ style: sectionThemeStyle(section.theme),
1588
+ children: /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-container", children: [
1589
+ heading ? /* @__PURE__ */ jsx2("h2", { className: "rt-tpl-heading", children: heading }) : null,
1590
+ /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-contact-visit-band", children: [
1591
+ /* @__PURE__ */ jsxs2("section", { className: "rt-tpl-contact-visit-panel", "aria-label": "\uC9C4\uB8CC\uC2DC\uAC04", children: [
1592
+ /* @__PURE__ */ jsx2("h3", { className: "rt-tpl-contact-visit-title", children: "\uC9C4\uB8CC\uC2DC\uAC04" }),
1593
+ /* @__PURE__ */ jsx2(ContactHoursSummary, { hours })
1594
+ ] }),
1595
+ /* @__PURE__ */ jsxs2("section", { className: "rt-tpl-contact-visit-panel", "aria-label": "\uC624\uC2DC\uB294 \uAE38", children: [
1596
+ /* @__PURE__ */ jsx2("h3", { className: "rt-tpl-contact-visit-title", children: "\uC624\uC2DC\uB294 \uAE38" }),
1597
+ /* @__PURE__ */ jsx2(ContactMapBlock, { map, mapEmbedUrl }),
1598
+ address ? /* @__PURE__ */ jsx2("address", { className: "rt-tpl-contact-visit-address", children: address }) : null,
1599
+ mapAction ? /* @__PURE__ */ jsx2("a", { className: "rt-tpl-contact-visit-link", href: mapAction.href, children: mapAction.label }) : null
1600
+ ] }),
1601
+ /* @__PURE__ */ jsxs2("section", { className: "rt-tpl-contact-visit-panel", "aria-label": "\uC804\uD654", children: [
1602
+ /* @__PURE__ */ jsx2("h3", { className: "rt-tpl-contact-visit-title", children: "\uC804\uD654" }),
1603
+ phoneAction ? /* @__PURE__ */ jsx2(
1604
+ "a",
1605
+ {
1606
+ className: "rt-tpl-contact-visit-phone",
1607
+ href: phoneAction.href,
1608
+ "data-track": "cta_call",
1609
+ children: phoneAction.label
1610
+ }
1611
+ ) : null,
1612
+ hours ? /* @__PURE__ */ jsx2(ContactHoursSummary, { hours: hours.slice(0, 2) }) : null,
1613
+ ctaAction ? /* @__PURE__ */ jsx2("a", { className: "rt-tpl-btn rt-tpl-btn--primary", href: ctaAction.href, children: ctaAction.label }) : null
1614
+ ] })
1615
+ ] })
1616
+ ] })
1617
+ }
1618
+ );
1619
+ }
1620
+ function TemplateContact(section) {
1621
+ if (section.variant === "channel-cards")
1622
+ return TemplateContactChannelCards(section);
1623
+ if (section.variant === "visit-band") return TemplateContactVisitBand(section);
1624
+ const { heading, form, phone, address, hours, map, mapEmbedUrl, actions } = section.props;
1625
+ return /* @__PURE__ */ jsx2(
1626
+ "section",
1627
+ {
1628
+ "data-roottale-tpl": "contact",
1629
+ "data-variant": section.variant,
1630
+ id: section.id,
1631
+ className: "rt-tpl-section rt-tpl-contact",
1632
+ style: sectionThemeStyle(section.theme),
1633
+ children: /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-container rt-tpl-contact-inner", children: [
1634
+ /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-contact-info", children: [
1635
+ heading ? /* @__PURE__ */ jsx2("h2", { className: "rt-tpl-heading", children: heading }) : null,
1636
+ phone ? /* @__PURE__ */ jsx2("a", { className: "rt-tpl-contact-phone", href: telHref(phone), "data-track": "cta_call", children: phone }) : null,
1637
+ address ? /* @__PURE__ */ jsx2("address", { className: "rt-tpl-contact-address", children: address }) : null,
1638
+ hours ? /* @__PURE__ */ jsxs2("table", { className: "rt-tpl-contact-hours", children: [
1639
+ /* @__PURE__ */ jsx2("caption", { className: "rt-tpl-sr-only", children: "\uC9C4\uB8CC\uC2DC\uAC04" }),
1640
+ /* @__PURE__ */ jsx2("tbody", { children: hours.map((row) => /* @__PURE__ */ jsxs2("tr", { children: [
1641
+ /* @__PURE__ */ jsx2("th", { scope: "row", children: row.day }),
1642
+ /* @__PURE__ */ jsxs2("td", { children: [
1643
+ /* @__PURE__ */ jsx2("span", { children: row.open }),
1644
+ /* @__PURE__ */ jsx2("span", { "aria-hidden": "true", children: "-" }),
1645
+ /* @__PURE__ */ jsx2("span", { children: row.close }),
1646
+ row.note ? /* @__PURE__ */ jsx2("span", { className: "rt-tpl-contact-hours-note", children: row.note }) : null
1647
+ ] })
1648
+ ] }, `${row.day}-${row.open}-${row.close}`)) })
1649
+ ] }) : null,
1650
+ /* @__PURE__ */ jsx2(ContactMapBlock, { map, mapEmbedUrl }),
1651
+ /* @__PURE__ */ jsx2(ContactActions, { actions })
1652
+ ] }),
1653
+ form.enabled ? /* @__PURE__ */ jsx2("div", { className: "rt-tpl-contact-form", children: /* @__PURE__ */ jsx2(RootTaleLeadForm, { action: "/api/inquiry", vertical: form.vertical }) }) : null
1654
+ ] })
1655
+ }
1656
+ );
1657
+ }
1658
+ function renderPracticeHeader({
1659
+ eyebrow,
1660
+ heading,
1661
+ description
1662
+ }) {
1663
+ if (!eyebrow && !heading && !description) return null;
1664
+ return /* @__PURE__ */ jsxs2("header", { className: "rt-tpl-practice-header", children: [
1665
+ eyebrow ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-practice-eyebrow", children: eyebrow }) : null,
1666
+ heading ? /* @__PURE__ */ jsx2("h2", { className: "rt-tpl-heading", children: heading }) : null,
1667
+ description ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-section-desc", children: description }) : null
1668
+ ] });
1669
+ }
1670
+ function renderHoursBadges(badges) {
1671
+ if (!badges) return null;
1672
+ const values = [
1673
+ badges.lunch,
1674
+ badges.evening,
1675
+ badges.closed,
1676
+ ...badges.extra ?? []
1677
+ ].filter((value) => Boolean(value));
1678
+ if (values.length === 0) return null;
1679
+ return /* @__PURE__ */ jsx2("span", { className: "rt-tpl-practice-badges", children: values.map((value) => /* @__PURE__ */ jsx2("span", { className: "rt-tpl-practice-badge", children: value }, value)) });
1680
+ }
1681
+ function renderPracticeDisclaimer(disclaimer) {
1682
+ return disclaimer ? /* @__PURE__ */ jsx2("aside", { className: "rt-tpl-practice-disclaimer", children: disclaimer }) : null;
1683
+ }
1684
+ function TemplateHoursCompact(section) {
1685
+ const { eyebrow, heading, description, rows, note, disclaimer } = section.props;
1686
+ return /* @__PURE__ */ jsx2(
1687
+ "section",
1688
+ {
1689
+ "data-roottale-tpl": "hours",
1690
+ "data-variant": "compact",
1691
+ id: section.id,
1692
+ className: "rt-tpl-section rt-tpl-practice rt-tpl-hours",
1693
+ style: sectionThemeStyle(section.theme),
1694
+ children: /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-container", children: [
1695
+ renderPracticeHeader({ eyebrow, heading, description }),
1696
+ /* @__PURE__ */ jsx2("dl", { className: "rt-tpl-hours-compact-list", children: rows.map((row) => /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-hours-compact-row", children: [
1697
+ /* @__PURE__ */ jsx2("dt", { className: "rt-tpl-hours-compact-day", children: row.label }),
1698
+ /* @__PURE__ */ jsxs2("dd", { className: "rt-tpl-hours-compact-body", children: [
1699
+ /* @__PURE__ */ jsx2("span", { className: "rt-tpl-hours-time", children: row.hours }),
1700
+ row.lunchHours ? /* @__PURE__ */ jsx2("span", { className: "rt-tpl-hours-muted", children: row.lunchHours }) : null,
1701
+ renderHoursBadges(row.badges),
1702
+ row.note ? /* @__PURE__ */ jsx2("span", { className: "rt-tpl-hours-muted", children: row.note }) : null
1703
+ ] })
1704
+ ] }, row.day)) }),
1705
+ note ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-practice-note", children: note }) : null,
1706
+ renderPracticeDisclaimer(disclaimer)
1707
+ ] })
1708
+ }
1709
+ );
1710
+ }
1711
+ function TemplateHours(section) {
1712
+ if (section.variant === "compact") return TemplateHoursCompact(section);
1713
+ const { eyebrow, heading, description, rows, note, disclaimer } = section.props;
1714
+ return /* @__PURE__ */ jsx2(
1715
+ "section",
1716
+ {
1717
+ "data-roottale-tpl": "hours",
1718
+ "data-variant": section.variant,
1719
+ id: section.id,
1720
+ className: "rt-tpl-section rt-tpl-practice rt-tpl-hours",
1721
+ style: sectionThemeStyle(section.theme),
1722
+ children: /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-container", children: [
1723
+ renderPracticeHeader({ eyebrow, heading, description }),
1724
+ /* @__PURE__ */ jsx2("div", { className: "rt-tpl-practice-table-wrap", children: /* @__PURE__ */ jsxs2("table", { className: "rt-tpl-practice-table", children: [
1725
+ /* @__PURE__ */ jsx2("caption", { className: "rt-tpl-sr-only", children: "\uC601\uC5C5\uC2DC\uAC04" }),
1726
+ /* @__PURE__ */ jsx2("thead", { children: /* @__PURE__ */ jsxs2("tr", { children: [
1727
+ /* @__PURE__ */ jsx2("th", { scope: "col", children: "\uC694\uC77C" }),
1728
+ /* @__PURE__ */ jsx2("th", { scope: "col", children: "\uC2DC\uAC04" }),
1729
+ /* @__PURE__ */ jsx2("th", { scope: "col", children: "\uC810\uC2EC/\uD734\uAC8C" }),
1730
+ /* @__PURE__ */ jsx2("th", { scope: "col", children: "\uC548\uB0B4" })
1731
+ ] }) }),
1732
+ /* @__PURE__ */ jsxs2("tbody", { children: [
1733
+ rows.map((row) => /* @__PURE__ */ jsxs2("tr", { children: [
1734
+ /* @__PURE__ */ jsx2("th", { scope: "row", className: "rt-tpl-practice-primary", children: row.label }),
1735
+ /* @__PURE__ */ jsx2("td", { children: row.hours }),
1736
+ /* @__PURE__ */ jsx2("td", { className: "rt-tpl-practice-muted", children: row.lunchHours ?? "\uBCC4\uB3C4 \uC548\uB0B4" }),
1737
+ /* @__PURE__ */ jsxs2("td", { children: [
1738
+ renderHoursBadges(row.badges),
1739
+ row.note ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-practice-muted", children: row.note }) : null
1740
+ ] })
1741
+ ] }, row.day)),
1742
+ note ? /* @__PURE__ */ jsx2("tr", { className: "rt-tpl-practice-table-note", children: /* @__PURE__ */ jsx2("td", { colSpan: 4, children: note }) }) : null
1743
+ ] })
1744
+ ] }) }),
1745
+ renderPracticeDisclaimer(disclaimer)
1746
+ ] })
1747
+ }
1748
+ );
1749
+ }
1750
+ function TemplatePricingCards(section) {
1751
+ const { eyebrow, heading, description, groups, disclaimer } = section.props;
1752
+ return /* @__PURE__ */ jsx2(
1753
+ "section",
1754
+ {
1755
+ "data-roottale-tpl": "pricing",
1756
+ "data-variant": "cards",
1757
+ id: section.id,
1758
+ className: "rt-tpl-section rt-tpl-practice rt-tpl-pricing",
1759
+ style: sectionThemeStyle(section.theme),
1760
+ children: /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-container", children: [
1761
+ renderPracticeHeader({ eyebrow, heading, description }),
1762
+ /* @__PURE__ */ jsx2("div", { className: "rt-tpl-pricing-card-groups", children: groups.map((group) => /* @__PURE__ */ jsxs2("section", { className: "rt-tpl-pricing-card-group", children: [
1763
+ /* @__PURE__ */ jsx2("h3", { className: "rt-tpl-pricing-group-title", children: group.label }),
1764
+ /* @__PURE__ */ jsx2("ul", { className: "rt-tpl-pricing-card-list", children: group.items.map((item) => /* @__PURE__ */ jsxs2("li", { className: "rt-tpl-pricing-card", children: [
1765
+ /* @__PURE__ */ jsxs2("div", { children: [
1766
+ /* @__PURE__ */ jsx2("h4", { className: "rt-tpl-pricing-name", children: item.name }),
1767
+ item.description ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-pricing-desc", children: item.description }) : null
1768
+ ] }),
1769
+ /* @__PURE__ */ jsx2("p", { className: "rt-tpl-pricing-price", children: item.price }),
1770
+ /* @__PURE__ */ jsx2("p", { className: "rt-tpl-pricing-condition", children: item.condition ?? "\uC790\uB8CC \uD655\uC778 \uD6C4 \uD655\uC815" })
1771
+ ] }, `${group.label}-${item.name}`)) })
1772
+ ] }, group.label)) }),
1773
+ /* @__PURE__ */ jsx2("aside", { className: "rt-tpl-practice-disclaimer", children: disclaimer })
1774
+ ] })
1775
+ }
1776
+ );
1777
+ }
1778
+ function TemplatePricing(section) {
1779
+ if (section.variant === "cards") return TemplatePricingCards(section);
1780
+ const { eyebrow, heading, description, groups, disclaimer } = section.props;
1781
+ return /* @__PURE__ */ jsx2(
1782
+ "section",
1783
+ {
1784
+ "data-roottale-tpl": "pricing",
1785
+ "data-variant": section.variant,
1786
+ id: section.id,
1787
+ className: "rt-tpl-section rt-tpl-practice rt-tpl-pricing",
1788
+ style: sectionThemeStyle(section.theme),
1789
+ children: /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-container", children: [
1790
+ renderPracticeHeader({ eyebrow, heading, description }),
1791
+ /* @__PURE__ */ jsx2("div", { className: "rt-tpl-practice-table-wrap", children: /* @__PURE__ */ jsxs2("table", { className: "rt-tpl-practice-table", children: [
1792
+ /* @__PURE__ */ jsx2("caption", { className: "rt-tpl-sr-only", children: "\uC694\uAE08 \uC548\uB0B4" }),
1793
+ /* @__PURE__ */ jsx2("thead", { children: /* @__PURE__ */ jsxs2("tr", { children: [
1794
+ /* @__PURE__ */ jsx2("th", { scope: "col", children: "\uD56D\uBAA9" }),
1795
+ /* @__PURE__ */ jsx2("th", { scope: "col", children: "\uC124\uBA85" }),
1796
+ /* @__PURE__ */ jsx2("th", { scope: "col", children: "\uAC00\uACA9" }),
1797
+ /* @__PURE__ */ jsx2("th", { scope: "col", children: "\uC870\uAC74" })
1798
+ ] }) }),
1799
+ /* @__PURE__ */ jsx2("tbody", { children: groups.flatMap((group) => [
1800
+ /* @__PURE__ */ jsx2("tr", { className: "rt-tpl-pricing-group-row", children: /* @__PURE__ */ jsx2("td", { colSpan: 4, children: group.label }) }, `${group.label}-group`),
1801
+ ...group.items.map((item) => /* @__PURE__ */ jsxs2("tr", { children: [
1802
+ /* @__PURE__ */ jsx2("th", { scope: "row", className: "rt-tpl-practice-primary", children: item.name }),
1803
+ /* @__PURE__ */ jsx2("td", { className: "rt-tpl-practice-muted", children: item.description ?? "\uC0C1\uB2F4 \uD6C4 \uBC94\uC704 \uD655\uC778" }),
1804
+ /* @__PURE__ */ jsx2("td", { className: "rt-tpl-pricing-price", children: item.price }),
1805
+ /* @__PURE__ */ jsx2("td", { className: "rt-tpl-practice-muted", children: item.condition ?? "\uC790\uB8CC \uD655\uC778 \uD6C4 \uD655\uC815" })
1806
+ ] }, `${group.label}-${item.name}`))
1807
+ ]) })
1808
+ ] }) }),
1809
+ /* @__PURE__ */ jsx2("aside", { className: "rt-tpl-practice-disclaimer", children: disclaimer })
1810
+ ] })
1811
+ }
1812
+ );
1813
+ }
1814
+ function TemplateProcess(section) {
1815
+ const { eyebrow, heading, description, items, connector, disclaimer } = section.props;
1816
+ if (section.variant === "timeline-marked") {
1817
+ return /* @__PURE__ */ jsx2(
1818
+ "section",
1819
+ {
1820
+ "data-roottale-tpl": "process",
1821
+ "data-variant": "timeline-marked",
1822
+ id: section.id,
1823
+ className: "rt-tpl-section rt-tpl-practice rt-tpl-process",
1824
+ style: sectionThemeStyle(section.theme),
1825
+ children: /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-container", children: [
1826
+ renderPracticeHeader({ eyebrow, heading, description }),
1827
+ /* @__PURE__ */ jsx2("ol", { className: "rt-tpl-process-marked-list", children: items.map((item, index) => {
1828
+ const status = item.status ?? "complete";
1829
+ const mark = item.mark ?? (status === "complete" ? "check" : "dot");
1830
+ return /* @__PURE__ */ jsx2(
1831
+ "li",
1832
+ {
1833
+ className: "rt-tpl-process-marked-item",
1834
+ "data-status": status,
1835
+ children: /* @__PURE__ */ jsxs2("article", { className: "rt-tpl-process-marked-card", children: [
1836
+ /* @__PURE__ */ jsx2("div", { className: "rt-tpl-process-marked-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx2("span", { "data-mark": mark }) }),
1837
+ /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-process-marked-body", children: [
1838
+ /* @__PURE__ */ jsx2("p", { className: "rt-tpl-process-marked-step", children: item.eyebrow ?? `step ${String(index + 1).padStart(2, "0")}` }),
1839
+ /* @__PURE__ */ jsx2("h3", { className: "rt-tpl-process-title", children: item.title }),
1840
+ /* @__PURE__ */ jsx2("p", { className: "rt-tpl-process-desc", children: item.description }),
1841
+ item.duration || item.statusLabel ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-process-duration", children: item.statusLabel ?? item.duration }) : null
1842
+ ] })
1843
+ ] })
1844
+ },
1845
+ `${index}-${item.title}`
1846
+ );
1847
+ }) }),
1848
+ renderPracticeDisclaimer(disclaimer)
1849
+ ] })
1850
+ }
1851
+ );
1852
+ }
1853
+ return /* @__PURE__ */ jsx2(
1854
+ "section",
1855
+ {
1856
+ "data-roottale-tpl": "process",
1857
+ "data-variant": section.variant,
1858
+ id: section.id,
1859
+ className: "rt-tpl-section rt-tpl-practice rt-tpl-process",
1860
+ style: sectionThemeStyle(section.theme),
1861
+ children: /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-container", children: [
1862
+ renderPracticeHeader({ eyebrow, heading, description }),
1863
+ /* @__PURE__ */ jsx2(
1864
+ "ol",
1865
+ {
1866
+ className: "rt-tpl-process-list",
1867
+ "data-connector": connector ?? "line",
1868
+ children: items.map((item, index) => /* @__PURE__ */ jsx2("li", { className: "rt-tpl-process-item", children: /* @__PURE__ */ jsxs2("article", { className: "rt-tpl-process-content", children: [
1869
+ item.imageSrc ? /* @__PURE__ */ jsx2(
1870
+ "img",
1871
+ {
1872
+ className: "rt-tpl-process-image",
1873
+ src: item.imageSrc,
1874
+ alt: item.imageAlt ?? "",
1875
+ loading: "lazy"
1876
+ }
1877
+ ) : null,
1878
+ /* @__PURE__ */ jsx2("p", { className: "rt-tpl-process-step", children: item.eyebrow ?? `step ${String(index + 1).padStart(2, "0")}` }),
1879
+ /* @__PURE__ */ jsx2("h3", { className: "rt-tpl-process-title", children: item.title }),
1880
+ /* @__PURE__ */ jsx2("p", { className: "rt-tpl-process-desc", children: item.description }),
1881
+ item.duration ? /* @__PURE__ */ jsx2("p", { className: "rt-tpl-process-duration", children: item.duration }) : null
1882
+ ] }) }, `${index}-${item.title}`))
1883
+ }
1884
+ ),
1885
+ renderPracticeDisclaimer(disclaimer)
1886
+ ] })
1887
+ }
1888
+ );
1889
+ }
1890
+ function TemplateBeforeAfterSideBySide(section) {
1891
+ const { beforeImage, afterImage, beforeLabel, afterLabel } = section.props;
1892
+ return /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-before-after-pair", children: [
1893
+ /* @__PURE__ */ jsxs2("figure", { className: "rt-tpl-before-after-figure", children: [
1894
+ /* @__PURE__ */ jsx2(
1895
+ "img",
1896
+ {
1897
+ className: "rt-tpl-before-after-img",
1898
+ src: beforeImage.src,
1899
+ alt: beforeImage.alt,
1900
+ loading: "lazy"
1901
+ }
1902
+ ),
1903
+ /* @__PURE__ */ jsx2("figcaption", { className: "rt-tpl-before-after-caption", children: beforeLabel })
1904
+ ] }),
1905
+ /* @__PURE__ */ jsxs2("figure", { className: "rt-tpl-before-after-figure", children: [
1906
+ /* @__PURE__ */ jsx2(
1907
+ "img",
1908
+ {
1909
+ className: "rt-tpl-before-after-img",
1910
+ src: afterImage.src,
1911
+ alt: afterImage.alt,
1912
+ loading: "lazy"
1913
+ }
1914
+ ),
1915
+ /* @__PURE__ */ jsx2("figcaption", { className: "rt-tpl-before-after-caption", children: afterLabel })
1916
+ ] })
1917
+ ] });
1918
+ }
1919
+ function TemplateBeforeAfter(section) {
1920
+ const {
1921
+ heading,
1922
+ description,
1923
+ beforeImage,
1924
+ afterImage,
1925
+ beforeLabel,
1926
+ afterLabel,
1927
+ disclaimer
1928
+ } = section.props;
1929
+ return /* @__PURE__ */ jsx2(
1930
+ "section",
1931
+ {
1932
+ "data-roottale-tpl": "before-after",
1933
+ "data-variant": section.variant,
1934
+ id: section.id,
1935
+ className: "rt-tpl-section rt-tpl-practice rt-tpl-before-after",
1936
+ style: sectionThemeStyle(section.theme),
1937
+ children: /* @__PURE__ */ jsxs2("div", { className: "rt-tpl-container", children: [
1938
+ renderPracticeHeader({ heading, description }),
1939
+ section.variant === "side-by-side" ? /* @__PURE__ */ jsx2(TemplateBeforeAfterSideBySide, { ...section }) : /* @__PURE__ */ jsx2(
1940
+ BeforeAfterSlider,
1941
+ {
1942
+ beforeImage,
1943
+ afterImage,
1944
+ beforeLabel,
1945
+ afterLabel
1946
+ }
1947
+ ),
1948
+ renderPracticeDisclaimer(disclaimer)
1949
+ ] })
1950
+ }
1951
+ );
1952
+ }
1953
+
1954
+ // src/templates/professional-sections.tsx
1955
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
1956
+ function SectionHeader({
1957
+ heading,
1958
+ description
1959
+ }) {
1960
+ if (!heading && !description) return null;
1961
+ return /* @__PURE__ */ jsxs3("header", { className: "rt-tpl-client-section-header", children: [
1962
+ heading ? /* @__PURE__ */ jsx3("h2", { className: "rt-tpl-heading", children: heading }) : null,
1963
+ description ? /* @__PURE__ */ jsx3("p", { className: "rt-tpl-section-desc", children: description }) : null
1964
+ ] });
1965
+ }
1966
+ function TagList({
1967
+ tags,
1968
+ label
1969
+ }) {
1970
+ if (!tags || tags.length === 0) return null;
1971
+ return /* @__PURE__ */ jsx3("ul", { className: "rt-tpl-client-tags", "aria-label": label, children: tags.map((tag) => /* @__PURE__ */ jsx3("li", { children: tag }, tag)) });
1972
+ }
1973
+ function TemplateExpertiseCards(section) {
1974
+ const { heading, description, items } = section.props;
1975
+ return /* @__PURE__ */ jsx3(
1976
+ "section",
1977
+ {
1978
+ "data-roottale-tpl": "expertise",
1979
+ "data-variant": "cards",
1980
+ id: section.id,
1981
+ className: "rt-tpl-section rt-tpl-expertise",
1982
+ style: sectionThemeStyle(section.theme),
1983
+ children: /* @__PURE__ */ jsxs3("div", { className: "rt-tpl-container", children: [
1984
+ /* @__PURE__ */ jsx3(SectionHeader, { heading, description }),
1985
+ /* @__PURE__ */ jsx3("ul", { className: "rt-tpl-expertise-card-grid", children: items.map((item) => /* @__PURE__ */ jsxs3("li", { className: "rt-tpl-expertise-card", children: [
1986
+ item.imageSrc ? /* @__PURE__ */ jsx3(
1987
+ "img",
1988
+ {
1989
+ className: "rt-tpl-expertise-card-img",
1990
+ src: item.imageSrc,
1991
+ alt: item.imageAlt ?? "",
1992
+ loading: "lazy"
1993
+ }
1994
+ ) : null,
1995
+ /* @__PURE__ */ jsxs3("div", { className: "rt-tpl-expertise-card-body", children: [
1996
+ item.kicker ? /* @__PURE__ */ jsx3("p", { className: "rt-tpl-expertise-kicker", children: item.kicker }) : null,
1997
+ /* @__PURE__ */ jsx3("h3", { className: "rt-tpl-expertise-title", children: item.title }),
1998
+ /* @__PURE__ */ jsx3("p", { className: "rt-tpl-expertise-body", children: item.body }),
1999
+ /* @__PURE__ */ jsx3(TagList, { tags: item.tags, label: `${item.title} \uD0DC\uADF8` }),
2000
+ item.href ? /* @__PURE__ */ jsx3("a", { className: "rt-tpl-expertise-cta", href: item.href, children: item.ctaLabel ?? "\uC790\uC138\uD788 \uBCF4\uAE30" }) : null
2001
+ ] })
2002
+ ] }, item.id)) })
2003
+ ] })
2004
+ }
2005
+ );
2006
+ }
2007
+ function TemplateExpertise(section) {
2008
+ const { heading, description, items } = section.props;
2009
+ if (section.variant === "cards") return TemplateExpertiseCards(section);
2010
+ return /* @__PURE__ */ jsx3(
2011
+ "section",
2012
+ {
2013
+ "data-roottale-tpl": "expertise",
2014
+ "data-variant": "tab-stage",
2015
+ id: section.id,
2016
+ className: "rt-tpl-section rt-tpl-expertise",
2017
+ style: sectionThemeStyle(section.theme),
2018
+ children: /* @__PURE__ */ jsxs3("div", { className: "rt-tpl-container", children: [
2019
+ /* @__PURE__ */ jsx3(SectionHeader, { heading, description }),
2020
+ /* @__PURE__ */ jsx3(ExpertiseTabStage, { items })
2021
+ ] })
2022
+ }
2023
+ );
2024
+ }
2025
+ function TemplateSpacesMosaic(section) {
2026
+ const { heading, description, spaces, disclaimer } = section.props;
2027
+ return /* @__PURE__ */ jsx3(
2028
+ "section",
2029
+ {
2030
+ "data-roottale-tpl": "spaces",
2031
+ "data-variant": "mosaic",
2032
+ id: section.id,
2033
+ className: "rt-tpl-section rt-tpl-spaces",
2034
+ style: sectionThemeStyle(section.theme),
2035
+ children: /* @__PURE__ */ jsxs3("div", { className: "rt-tpl-container", children: [
2036
+ /* @__PURE__ */ jsx3(SectionHeader, { heading, description }),
2037
+ /* @__PURE__ */ jsx3("ul", { className: "rt-tpl-spaces-mosaic", children: spaces.map((space) => /* @__PURE__ */ jsxs3("li", { className: "rt-tpl-spaces-tile", children: [
2038
+ /* @__PURE__ */ jsx3("img", { src: space.imageSrc, alt: space.imageAlt, loading: "lazy" }),
2039
+ /* @__PURE__ */ jsxs3("div", { className: "rt-tpl-spaces-tile-caption", children: [
2040
+ space.kicker ? /* @__PURE__ */ jsx3("span", { className: "rt-tpl-spaces-kicker", children: space.kicker }) : null,
2041
+ /* @__PURE__ */ jsx3("h3", { children: space.title ?? space.label }),
2042
+ space.description ? /* @__PURE__ */ jsx3("p", { children: space.description }) : null,
2043
+ /* @__PURE__ */ jsx3(TagList, { tags: space.tags, label: `${space.label} \uD0DC\uADF8` })
2044
+ ] })
2045
+ ] }, space.id)) }),
2046
+ disclaimer ? /* @__PURE__ */ jsx3("aside", { className: "rt-tpl-client-disclaimer", children: disclaimer }) : null
2047
+ ] })
2048
+ }
2049
+ );
2050
+ }
2051
+ function TemplateSpaces(section) {
2052
+ const { heading, description, spaces, disclaimer } = section.props;
2053
+ if (section.variant === "mosaic") return TemplateSpacesMosaic(section);
2054
+ return /* @__PURE__ */ jsx3(
2055
+ "section",
2056
+ {
2057
+ "data-roottale-tpl": "spaces",
2058
+ "data-variant": "stage",
2059
+ id: section.id,
2060
+ className: "rt-tpl-section rt-tpl-spaces",
2061
+ style: sectionThemeStyle(section.theme),
2062
+ children: /* @__PURE__ */ jsxs3("div", { className: "rt-tpl-container", children: [
2063
+ /* @__PURE__ */ jsx3(SectionHeader, { heading, description }),
2064
+ /* @__PURE__ */ jsx3(SpacesStage, { spaces }),
2065
+ disclaimer ? /* @__PURE__ */ jsx3("aside", { className: "rt-tpl-client-disclaimer", children: disclaimer }) : null
2066
+ ] })
2067
+ }
2068
+ );
2069
+ }
2070
+ function TemplateConcernsList(section) {
2071
+ const { heading, description, regions, disclaimer } = section.props;
2072
+ return /* @__PURE__ */ jsx3(
2073
+ "section",
2074
+ {
2075
+ "data-roottale-tpl": "concerns",
2076
+ "data-variant": "list",
2077
+ id: section.id,
2078
+ className: "rt-tpl-section rt-tpl-concerns",
2079
+ style: sectionThemeStyle(section.theme),
2080
+ children: /* @__PURE__ */ jsxs3("div", { className: "rt-tpl-container", children: [
2081
+ /* @__PURE__ */ jsx3(SectionHeader, { heading, description }),
2082
+ /* @__PURE__ */ jsx3("ul", { className: "rt-tpl-concerns-list", children: regions.map((region) => /* @__PURE__ */ jsxs3("li", { className: "rt-tpl-concerns-card", children: [
2083
+ /* @__PURE__ */ jsx3("p", { className: "rt-tpl-concerns-label", children: region.label }),
2084
+ /* @__PURE__ */ jsx3("h3", { className: "rt-tpl-concerns-title", children: region.title }),
2085
+ /* @__PURE__ */ jsx3("p", { className: "rt-tpl-concerns-desc", children: region.description }),
2086
+ region.items ? /* @__PURE__ */ jsx3("ul", { className: "rt-tpl-concerns-items", children: region.items.map((item) => /* @__PURE__ */ jsx3("li", { children: item }, item)) }) : null,
2087
+ region.href ? /* @__PURE__ */ jsx3("a", { className: "rt-tpl-concerns-cta", href: region.href, children: region.ctaLabel ?? "\uC790\uC138\uD788 \uBCF4\uAE30" }) : null
2088
+ ] }, region.id)) }),
2089
+ /* @__PURE__ */ jsx3("aside", { className: "rt-tpl-client-disclaimer", children: disclaimer })
2090
+ ] })
2091
+ }
2092
+ );
2093
+ }
2094
+ function TemplateConcerns(section) {
2095
+ const {
2096
+ heading,
2097
+ description,
2098
+ figureImage,
2099
+ figureAlt,
2100
+ regions,
2101
+ disclaimer
2102
+ } = section.props;
2103
+ if (section.variant === "list") return TemplateConcernsList(section);
2104
+ return /* @__PURE__ */ jsx3(
2105
+ "section",
2106
+ {
2107
+ "data-roottale-tpl": "concerns",
2108
+ "data-variant": "figure-map",
2109
+ id: section.id,
2110
+ className: "rt-tpl-section rt-tpl-concerns",
2111
+ style: sectionThemeStyle(section.theme),
2112
+ children: /* @__PURE__ */ jsxs3("div", { className: "rt-tpl-container", children: [
2113
+ /* @__PURE__ */ jsx3(SectionHeader, { heading, description }),
2114
+ /* @__PURE__ */ jsx3(
2115
+ ConcernsFigureMap,
2116
+ {
2117
+ figureImage: figureImage ?? "",
2118
+ figureAlt: figureAlt ?? "",
2119
+ regions
2120
+ }
2121
+ ),
2122
+ /* @__PURE__ */ jsx3("aside", { className: "rt-tpl-client-disclaimer", children: disclaimer })
2123
+ ] })
2124
+ }
2125
+ );
2126
+ }
2127
+
2128
+ // src/render-section-node.tsx
2129
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
2130
+ function warnSkippedCmsBound(sectionType, isDev) {
2131
+ if (isDev()) {
2132
+ console.warn(
2133
+ `[cms-renderer-next] section \uB178\uB4DC sectionType=${sectionType} \uB294 apiKey \uCEE8\uD14D\uC2A4\uD2B8\uAC00 \uC5C6\uC5B4 \uB80C\uB354 skip`
2134
+ );
2135
+ }
2136
+ }
2137
+ function renderSectionNode(node, key, context) {
2138
+ const attrs = node.attrs ?? {};
2139
+ const input = {
2140
+ type: typeof attrs.sectionType === "string" ? attrs.sectionType : "",
2141
+ variant: attrs.variant ?? void 0,
2142
+ theme: attrs.theme ?? void 0,
2143
+ props: attrs.props ?? {}
2144
+ };
2145
+ const parsed = SectionSchema.safeParse(input);
2146
+ if (!parsed.success) {
2147
+ if (context.isDev()) {
2148
+ console.warn(
2149
+ `[cms-renderer-next] section \uB178\uB4DC parse \uC2E4\uD328 (sectionType=${input.type}) \u2014 \uB80C\uB354 skip:`,
2150
+ parsed.error.issues
2151
+ );
2152
+ }
2153
+ return null;
2154
+ }
2155
+ const section = parsed.data;
2156
+ switch (section.type) {
2157
+ case "hero":
2158
+ return /* @__PURE__ */ jsx4(TemplateHero, { ...section }, key);
2159
+ case "rich-text":
2160
+ return /* @__PURE__ */ jsx4(TemplateRichText, { ...section }, key);
2161
+ case "services":
2162
+ return /* @__PURE__ */ jsx4(TemplateServices, { ...section }, key);
2163
+ case "faq":
2164
+ return /* @__PURE__ */ jsx4(TemplateFaq, { ...section }, key);
2165
+ case "footer":
2166
+ return /* @__PURE__ */ jsx4(TemplateFooter, { ...section }, key);
2167
+ case "cta-banner":
2168
+ return /* @__PURE__ */ jsx4(TemplateCtaBanner, { ...section }, key);
2169
+ case "trust":
2170
+ return /* @__PURE__ */ jsx4(TemplateTrust, { ...section }, key);
2171
+ case "hours":
2172
+ return /* @__PURE__ */ jsx4(TemplateHours, { ...section }, key);
2173
+ case "pricing":
2174
+ return /* @__PURE__ */ jsx4(TemplatePricing, { ...section }, key);
2175
+ case "process":
2176
+ return /* @__PURE__ */ jsx4(TemplateProcess, { ...section }, key);
2177
+ case "before-after":
2178
+ return /* @__PURE__ */ jsx4(TemplateBeforeAfter, { ...section }, key);
2179
+ case "testimonials":
2180
+ return /* @__PURE__ */ jsx4(TemplateTestimonials, { ...section }, key);
2181
+ case "team":
2182
+ return /* @__PURE__ */ jsx4(TemplateTeam, { ...section }, key);
2183
+ case "expertise":
2184
+ return /* @__PURE__ */ jsx4(TemplateExpertise, { ...section }, key);
2185
+ case "spaces":
2186
+ return /* @__PURE__ */ jsx4(TemplateSpaces, { ...section }, key);
2187
+ case "concerns":
2188
+ return /* @__PURE__ */ jsx4(TemplateConcerns, { ...section }, key);
2189
+ case "contact":
2190
+ if (!context.cms) {
2191
+ warnSkippedCmsBound(section.type, context.isDev);
2192
+ return null;
2193
+ }
2194
+ return /* @__PURE__ */ jsx4(TemplateContact, { ...section }, key);
2195
+ case "blog-list": {
2196
+ if (!context.cms) {
2197
+ warnSkippedCmsBound(section.type, context.isDev);
2198
+ return null;
2199
+ }
2200
+ const s = section;
2201
+ const base = s.props.blogBasePath ?? "/blog";
2202
+ return /* @__PURE__ */ jsx4(
2203
+ "section",
2204
+ {
2205
+ "data-roottale-tpl": "blog-list",
2206
+ "data-roottale-cms": "list",
2207
+ id: s.id,
2208
+ className: "rt-tpl-section rt-tpl-blog-list",
2209
+ style: sectionThemeStyle(s.theme),
2210
+ children: /* @__PURE__ */ jsxs4("div", { className: "rt-tpl-container", children: [
2211
+ s.props.heading ? /* @__PURE__ */ jsx4("h2", { className: "rt-tpl-heading", children: s.props.heading }) : null,
2212
+ context.renderBlogList({
2213
+ apiKey: context.cms.apiKey,
2214
+ baseUrl: context.cms.baseUrl,
2215
+ limit: s.props.limit,
2216
+ emptyMessage: s.props.emptyMessage,
2217
+ postHref: (post) => `${base}/${post.slug}`
2218
+ })
2219
+ ] })
2220
+ },
2221
+ key
2222
+ );
2223
+ }
2224
+ case "lead-form": {
2225
+ if (!context.cms) {
2226
+ warnSkippedCmsBound(section.type, context.isDev);
2227
+ return null;
2228
+ }
2229
+ const s = section;
2230
+ return /* @__PURE__ */ jsx4(
2231
+ "section",
2232
+ {
2233
+ "data-roottale-tpl": "lead-form",
2234
+ "data-roottale-cms": "lead-form",
2235
+ id: s.id,
2236
+ className: "rt-tpl-section rt-tpl-lead-form",
2237
+ style: sectionThemeStyle(s.theme),
2238
+ children: /* @__PURE__ */ jsx4("div", { className: "rt-tpl-container", children: /* @__PURE__ */ jsx4(
2239
+ RootTaleLeadForm,
2240
+ {
2241
+ action: s.props.action,
2242
+ vertical: s.props.vertical,
2243
+ heading: s.props.heading,
2244
+ description: s.props.description,
2245
+ submitLabel: s.props.submitLabel
2246
+ }
2247
+ ) })
2248
+ },
2249
+ key
2250
+ );
2251
+ }
2252
+ default:
2253
+ if (context.isDev()) {
2254
+ console.warn(
2255
+ `[cms-renderer-next] section \uB178\uB4DC sectionType=${section.type} \uB294 renderNode \uC704\uC784 \uB300\uC0C1\uC774 \uC544\uB2D8(cms-bound/\uBBF8\uC9C0) \u2014 skip`
2256
+ );
2257
+ }
2258
+ return null;
2259
+ }
2260
+ }
2261
+
2262
+ // src/PostCard.tsx
2263
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
2264
+ function firstCategoryName(terms) {
2265
+ if (!terms) return null;
2266
+ const cat = terms.find((t2) => t2.taxonomy === "category");
2267
+ return cat ? cat.name : null;
2268
+ }
2269
+ function RootTalePostCard(props) {
2270
+ const { post, href = defaultHref, display } = props;
2271
+ const showDate = display ? display.showDate : true;
2272
+ const showAuthor = display ? display.showAuthor : false;
2273
+ const showImage = display?.showImage !== false;
2274
+ const showCategory = display?.showCategory !== false;
2275
+ const authorName = post.authorName;
2276
+ const publishedDate = showDate ? formatPublishedDate(post.publishedAt) : "";
2277
+ const views = typeof post.viewCount === "number" ? post.viewCount : null;
2278
+ const imageUrl = showImage ? post.featuredImageUrl : null;
2279
+ const category = showCategory ? firstCategoryName(post.terms) : null;
2280
+ return /* @__PURE__ */ jsx5("article", { "data-roottale-cms": "card", className: "rt-cms-card", children: /* @__PURE__ */ jsxs5("a", { className: "rt-cms-card-link", href: href(post), children: [
2281
+ imageUrl ? (
2282
+ // eslint-disable-next-line @next/next/no-img-element -- SSR string URL, framework-agnostic
2283
+ /* @__PURE__ */ jsx5(
2284
+ "img",
2285
+ {
2286
+ className: "rt-cms-card-image",
2287
+ src: imageUrl,
2288
+ alt: "",
2289
+ loading: "lazy",
2290
+ decoding: "async"
2291
+ }
2292
+ )
2293
+ ) : null,
2294
+ category ? /* @__PURE__ */ jsx5("span", { className: "rt-cms-card-category", children: category }) : null,
2295
+ publishedDate || showAuthor && authorName || views !== null ? /* @__PURE__ */ jsxs5("p", { className: "rt-cms-meta", children: [
2296
+ publishedDate ? /* @__PURE__ */ jsx5("span", { className: "rt-cms-meta-item", "data-rt-cms-meta": "date", children: publishedDate }) : null,
2297
+ showAuthor && authorName ? /* @__PURE__ */ jsxs5("span", { className: "rt-cms-meta-item", "data-rt-cms-meta": "author", children: [
2298
+ "\uC791\uC131\uC790 ",
2299
+ authorName
2300
+ ] }) : null,
2301
+ views !== null ? /* @__PURE__ */ jsxs5("span", { className: "rt-cms-meta-item", "data-rt-cms-meta": "views", children: [
2302
+ "\uC870\uD68C ",
2303
+ views.toLocaleString("ko-KR")
2304
+ ] }) : null
2305
+ ] }) : null,
2306
+ /* @__PURE__ */ jsx5("h2", { className: "rt-cms-title", children: post.title }),
2307
+ post.excerpt ? /* @__PURE__ */ jsx5("p", { className: "rt-cms-excerpt", children: post.excerpt }) : null,
2308
+ /* @__PURE__ */ jsx5("span", { className: "rt-cms-card-action", "aria-hidden": "true", children: "\uC77D\uAE30" })
2309
+ ] }) });
2310
+ }
2311
+ function defaultHref(post) {
2312
+ return `/blog/${post.slug}`;
2313
+ }
2314
+ function formatPublishedDate(iso) {
2315
+ const d = new Date(iso);
2316
+ if (Number.isNaN(d.getTime())) return "";
2317
+ return new Intl.DateTimeFormat("ko-KR", {
2318
+ year: "numeric",
2319
+ month: "2-digit",
2320
+ day: "2-digit"
2321
+ }).format(d);
2322
+ }
2323
+
2324
+ // src/TableOfContents.tsx
2325
+ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
2326
+ function RootTaleTableOfContents(props) {
2327
+ const { entries, locale, title = t(locale, "tableOfContentsTitle") } = props;
2328
+ if (entries.length === 0) return null;
2329
+ return /* @__PURE__ */ jsx6("nav", { "data-roottale-cms": "toc", className: "rt-cms-toc", "aria-label": title, children: /* @__PURE__ */ jsxs6("details", { className: "rt-cms-toc-details", open: true, children: [
2330
+ /* @__PURE__ */ jsxs6("summary", { className: "rt-cms-toc-summary", children: [
2331
+ title ? /* @__PURE__ */ jsx6("span", { className: "rt-cms-toc-title", children: title }) : null,
2332
+ /* @__PURE__ */ jsx6("span", { className: "rt-cms-toc-toggle", "aria-hidden": "true" })
2333
+ ] }),
2334
+ /* @__PURE__ */ jsx6("ol", { className: "rt-cms-toc-list", children: entries.map((entry) => /* @__PURE__ */ jsx6(
2335
+ "li",
2336
+ {
2337
+ className: `rt-cms-toc-item rt-cms-toc-level-${entry.level}`,
2338
+ children: /* @__PURE__ */ jsx6("a", { href: `#${entry.id}`, children: entry.text })
2339
+ },
2340
+ entry.id
2341
+ )) })
2342
+ ] }) });
2343
+ }
2344
+
2345
+ // ../ui-react/dist/theme/index.js
2346
+ import { jsx as _jsx } from "react/jsx-runtime";
2347
+ function themeToCssVars(theme) {
2348
+ return {
2349
+ ...theme.colors?.primary ? { "--rt-color-primary": theme.colors.primary } : {},
2350
+ ...theme.colors?.primaryForeground ? { "--rt-color-primary-foreground": theme.colors.primaryForeground } : {},
2351
+ ...theme.colors?.secondary ? { "--rt-color-secondary": theme.colors.secondary } : {},
2352
+ ...theme.colors?.secondaryForeground ? { "--rt-color-secondary-foreground": theme.colors.secondaryForeground } : {},
2353
+ ...theme.colors?.accent ? { "--rt-color-accent": theme.colors.accent } : {},
2354
+ ...theme.colors?.accentForeground ? { "--rt-color-accent-foreground": theme.colors.accentForeground } : {},
2355
+ ...theme.colors?.background ? { "--rt-color-background": theme.colors.background } : {},
2356
+ ...theme.colors?.foreground ? { "--rt-color-foreground": theme.colors.foreground } : {},
2357
+ ...theme.colors?.muted ? { "--rt-color-muted": theme.colors.muted } : {},
2358
+ ...theme.colors?.mutedForeground ? { "--rt-color-muted-foreground": theme.colors.mutedForeground } : {},
2359
+ ...theme.colors?.destructive ? { "--rt-color-destructive": theme.colors.destructive } : {},
2360
+ ...theme.colors?.destructiveForeground ? { "--rt-color-destructive-foreground": theme.colors.destructiveForeground } : {},
2361
+ ...theme.colors?.border ? { "--rt-color-border": theme.colors.border } : {},
2362
+ ...theme.colors?.input ? { "--rt-color-input": theme.colors.input } : {},
2363
+ ...theme.colors?.ring ? { "--rt-color-ring": theme.colors.ring } : {},
2364
+ ...theme.fonts?.body ? { "--rt-font-body": theme.fonts.body } : {},
2365
+ ...theme.fonts?.display ? { "--rt-font-display": theme.fonts.display } : {},
2366
+ ...theme.radius?.sm ? { "--rt-radius-sm": theme.radius.sm } : {},
2367
+ ...theme.radius?.md ? { "--rt-radius-md": theme.radius.md } : {},
2368
+ ...theme.radius?.lg ? { "--rt-radius-lg": theme.radius.lg } : {},
2369
+ ...theme.radius?.xl ? { "--rt-radius-xl": theme.radius.xl } : {}
2370
+ };
2371
+ }
2372
+
2373
+ // src/theme-css-vars.ts
2374
+ function themeToCssVars2(theme) {
2375
+ if (!theme) return null;
2376
+ const vars = themeToCssVars(theme);
2377
+ if (Object.keys(vars).length === 0) return null;
2378
+ return vars;
2379
+ }
2380
+
2381
+ // src/toc.ts
2382
+ function tocLevel(rawLevel) {
2383
+ if (rawLevel < 1 || rawLevel > 4) return null;
2384
+ if (rawLevel < 3) return 2;
2385
+ return rawLevel === 3 ? 3 : 4;
2386
+ }
2387
+ function headingToId(text) {
2388
+ return text.trim().toLowerCase().replace(/[^\p{L}\p{N}\s-]/gu, "").replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
2389
+ }
2390
+ function textOf(node) {
2391
+ if (typeof node.text === "string") return node.text;
2392
+ if (!Array.isArray(node.content)) return "";
2393
+ return node.content.map(textOf).join("");
2394
+ }
2395
+ function extractToc(doc) {
2396
+ const root = doc;
2397
+ const content = Array.isArray(root.content) ? root.content : [];
2398
+ const entries = [];
2399
+ const idCounts = /* @__PURE__ */ new Map();
2400
+ for (const node of content) {
2401
+ if (node?.type !== "heading") continue;
2402
+ const rawLevel = Number(node.attrs?.level ?? 2);
2403
+ const level = tocLevel(rawLevel);
2404
+ if (level === null) continue;
2405
+ const text = textOf(node).trim();
2406
+ if (!text) continue;
2407
+ const base = headingToId(text) || "heading";
2408
+ const count = idCounts.get(base) ?? 0;
2409
+ const id = count === 0 ? base : `${base}-${count}`;
2410
+ idCounts.set(base, count + 1);
2411
+ entries.push({ level, text, id });
2412
+ }
2413
+ return entries;
2414
+ }
2415
+ function attachHeadingIds(doc, entries) {
2416
+ const root = doc;
2417
+ const content = Array.isArray(root.content) ? root.content : [];
2418
+ let cursor = 0;
2419
+ const nextContent = content.map((node) => {
2420
+ if (node?.type !== "heading") return node;
2421
+ const rawLevel = Number(node.attrs?.level ?? 2);
2422
+ if (rawLevel < 1 || rawLevel > 4) return node;
2423
+ if (!textOf(node).trim()) return node;
2424
+ const entry = entries[cursor++];
2425
+ if (!entry) return node;
2426
+ return {
2427
+ ...node,
2428
+ attrs: { ...node.attrs ?? {}, id: entry.id }
2429
+ };
2430
+ });
2431
+ return { ...root, content: nextContent };
2432
+ }
2433
+
2434
+ // src/FloatingCta.tsx
2435
+ import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
2436
+ function RootTaleFloatingCta(props) {
2437
+ const { buttons, position = "bottom-right" } = props;
2438
+ if (!buttons || buttons.length === 0) return null;
2439
+ return /* @__PURE__ */ jsx7(
2440
+ "div",
2441
+ {
2442
+ "data-roottale-cms": "floating-cta",
2443
+ className: `rt-cms-floating-cta rt-cms-floating-cta--${position}`,
2444
+ children: buttons.map((btn, idx) => {
2445
+ const isExternal = btn.type === "kakao" || btn.type === "custom";
2446
+ return /* @__PURE__ */ jsxs7(
2447
+ "a",
2448
+ {
2449
+ href: btn.href,
2450
+ className: `rt-cms-floating-cta__btn rt-cms-floating-cta__btn--${btn.type}`,
2451
+ target: isExternal ? "_blank" : void 0,
2452
+ rel: isExternal ? "noopener noreferrer" : void 0,
2453
+ children: [
2454
+ /* @__PURE__ */ jsx7("span", { "aria-hidden": "true", className: "rt-cms-floating-cta__icon", children: btn.icon ?? defaultIcon(btn.type) }),
2455
+ /* @__PURE__ */ jsx7("span", { className: "rt-cms-floating-cta__label", children: btn.label })
2456
+ ]
2457
+ },
2458
+ `${btn.type}-${idx}`
2459
+ );
2460
+ })
2461
+ }
2462
+ );
2463
+ }
2464
+ function defaultIcon(type) {
2465
+ switch (type) {
2466
+ case "phone":
2467
+ return "\u260E";
2468
+ case "contact":
2469
+ return "\u2709";
2470
+ case "kakao":
2471
+ return "\u{1F4AC}";
2472
+ case "custom":
2473
+ return "\u2192";
2474
+ }
2475
+ }
2476
+
2477
+ // src/block-to-react.tsx
2478
+ import {
2479
+ applyBlockBindings,
2480
+ createFieldBindingResolver,
2481
+ sanitizeHtml
2482
+ } from "@roottale/cms-core";
2483
+ import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
2484
+ function isString(value) {
2485
+ return typeof value === "string";
2486
+ }
2487
+ function htmlContent(html) {
2488
+ return { __html: sanitizeHtml(html) };
2489
+ }
2490
+ function renderInner(blocks) {
2491
+ return blocks.map((b, i) => renderBlock(b, i));
2492
+ }
2493
+ function renderBlock(block, key = 0) {
2494
+ const dataBlockId = block._id;
2495
+ switch (block.name) {
2496
+ case "core/paragraph": {
2497
+ const text = isString(block.attributes.content) ? block.attributes.content : block.rawHtml ?? "";
2498
+ return /* @__PURE__ */ jsx8(
2499
+ "p",
2500
+ {
2501
+ "data-block-id": dataBlockId,
2502
+ dangerouslySetInnerHTML: htmlContent(text)
2503
+ },
2504
+ key
2505
+ );
2506
+ }
2507
+ case "core/heading": {
2508
+ const levelRaw = block.attributes.level;
2509
+ const level = typeof levelRaw === "number" && levelRaw >= 2 && levelRaw <= 4 ? levelRaw : 2;
2510
+ const text = isString(block.attributes.content) ? block.attributes.content : block.rawHtml ?? "";
2511
+ const props = {
2512
+ "data-block-id": dataBlockId,
2513
+ dangerouslySetInnerHTML: htmlContent(text)
2514
+ };
2515
+ if (level === 2) return /* @__PURE__ */ jsx8("h2", { ...props }, key);
2516
+ if (level === 3) return /* @__PURE__ */ jsx8("h3", { ...props }, key);
2517
+ return /* @__PURE__ */ jsx8("h4", { ...props }, key);
2518
+ }
2519
+ case "core/image": {
2520
+ const src = isString(block.attributes.url) ? block.attributes.url : "";
2521
+ const alt = isString(block.attributes.alt) ? block.attributes.alt : "";
2522
+ const caption = isString(block.attributes.caption) ? block.attributes.caption : null;
2523
+ return /* @__PURE__ */ jsxs8("figure", { "data-block-id": dataBlockId, children: [
2524
+ /* @__PURE__ */ jsx8("img", { src, alt, loading: "lazy" }),
2525
+ caption && /* @__PURE__ */ jsx8("figcaption", { children: caption })
2526
+ ] }, key);
2527
+ }
2528
+ case "core/list": {
2529
+ const ordered = block.attributes.ordered === true;
2530
+ const items = (block.innerBlocks ?? []).map(
2531
+ (item, i) => item.rawHtml ? /* @__PURE__ */ jsx8(
2532
+ "li",
2533
+ {
2534
+ dangerouslySetInnerHTML: htmlContent(item.rawHtml)
2535
+ },
2536
+ i
2537
+ ) : /* @__PURE__ */ jsx8("li", { children: renderInner(item.innerBlocks ?? []) }, i)
2538
+ );
2539
+ return ordered ? /* @__PURE__ */ jsx8("ol", { "data-block-id": dataBlockId, children: items }, key) : /* @__PURE__ */ jsx8("ul", { "data-block-id": dataBlockId, children: items }, key);
2540
+ }
2541
+ case "core/quote": {
2542
+ const inner = renderInner(block.innerBlocks ?? []);
2543
+ const citation = isString(block.attributes.citation) ? block.attributes.citation : null;
2544
+ return /* @__PURE__ */ jsxs8("blockquote", { "data-block-id": dataBlockId, children: [
2545
+ inner,
2546
+ citation && /* @__PURE__ */ jsx8("cite", { children: citation })
2547
+ ] }, key);
2548
+ }
2549
+ case "core/code": {
2550
+ const code = isString(block.attributes.content) ? block.attributes.content : block.rawHtml ?? "";
2551
+ const lang = isString(block.attributes.language) ? block.attributes.language : void 0;
2552
+ return /* @__PURE__ */ jsx8(
2553
+ "pre",
2554
+ {
2555
+ "data-block-id": dataBlockId,
2556
+ "data-language": lang,
2557
+ children: /* @__PURE__ */ jsx8("code", { children: code })
2558
+ },
2559
+ key
2560
+ );
2561
+ }
2562
+ case "core/columns": {
2563
+ return /* @__PURE__ */ jsx8(
2564
+ "div",
2565
+ {
2566
+ className: "rt-columns",
2567
+ "data-block-id": dataBlockId,
2568
+ children: renderInner(block.innerBlocks ?? [])
2569
+ },
2570
+ key
2571
+ );
2572
+ }
2573
+ case "core/separator":
2574
+ return /* @__PURE__ */ jsx8("hr", { "data-block-id": dataBlockId }, key);
2575
+ case "core/spacer": {
2576
+ const heightRaw = block.attributes.height;
2577
+ const height = isString(heightRaw) ? heightRaw : "32px";
2578
+ return /* @__PURE__ */ jsx8(
2579
+ "div",
2580
+ {
2581
+ className: "rt-spacer",
2582
+ "data-block-id": dataBlockId,
2583
+ style: { height }
2584
+ },
2585
+ key
2586
+ );
2587
+ }
2588
+ case "core/group": {
2589
+ return /* @__PURE__ */ jsx8(
2590
+ "div",
2591
+ {
2592
+ className: "rt-group",
2593
+ "data-block-id": dataBlockId,
2594
+ children: renderInner(block.innerBlocks ?? [])
2595
+ },
2596
+ key
2597
+ );
2598
+ }
2599
+ default: {
2600
+ const rawHtml = block.rawHtml;
2601
+ return /* @__PURE__ */ jsx8(
2602
+ "div",
2603
+ {
2604
+ className: "rt-unknown-block",
2605
+ "data-block-id": dataBlockId,
2606
+ "data-block-name": block.name,
2607
+ "data-rawhtml-suppressed": rawHtml ? "true" : void 0,
2608
+ children: renderInner(block.innerBlocks ?? [])
2609
+ },
2610
+ key
2611
+ );
2612
+ }
2613
+ }
2614
+ }
2615
+ function renderBlocks(blocks) {
2616
+ return blocks.map((b, i) => renderBlock(b, i));
2617
+ }
2618
+ function renderBoundBlocks(blocks, opts = {}) {
2619
+ const resolver = opts.resolver ?? createFieldBindingResolver(opts.fields);
2620
+ return renderBlocks(applyBlockBindings(blocks, resolver));
2621
+ }
2622
+
2623
+ // src/server.tsx
2624
+ import { Fragment as Fragment3, jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
2625
+ function authorImageRadiusCss(radius) {
2626
+ if (radius === "circle") return "999px";
2627
+ if (radius === "rounded") return "0.875rem";
2628
+ return "0";
2629
+ }
2630
+ function RootTaleThemeProvider(props) {
2631
+ const style = themeToCssVars2(props.theme ?? null);
2632
+ if (!style) return /* @__PURE__ */ jsx9(Fragment3, { children: props.children });
2633
+ return /* @__PURE__ */ jsx9("div", { "data-roottale-cms": "theme-root", "data-rt-theme": "", style, children: props.children });
2634
+ }
2635
+ async function RootTaleBlogList(props) {
2636
+ const {
2637
+ apiKey,
2638
+ baseUrl,
2639
+ limit,
2640
+ type = "post",
2641
+ collection,
2642
+ collections,
2643
+ excludeCollections = false,
2644
+ locale,
2645
+ emptyMessage = t(locale, "blogListEmpty"),
2646
+ showCategoryFilter = false,
2647
+ activeCategory,
2648
+ categoryHref = defaultCategoryHref,
2649
+ allCategoriesLabel = t(locale, "allCategoriesLabel"),
2650
+ author,
2651
+ theme: themeProp
2652
+ } = props;
2653
+ if (collection && excludeCollections) {
2654
+ throw new Error(
2655
+ "RootTaleBlogList: `collection` \uACFC `excludeCollections` \uB97C \uB3D9\uC2DC\uC5D0 \uC904 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4 \u2014 \uD3EC\uC9C0\uD2F0\uBE0C/\uB124\uAC70\uD2F0\uBE0C \uC2A4\uCF54\uD504\uB294 \uBC30\uD0C0\uC801\uC785\uB2C8\uB2E4."
2656
+ );
2657
+ }
2658
+ if (excludeCollections && !collections) {
2659
+ throw new Error(
2660
+ "RootTaleBlogList: `excludeCollections` \uB294 `collections` \uC640 \uD568\uAED8 \uC918\uC57C \uD569\uB2C8\uB2E4."
2661
+ );
2662
+ }
2663
+ const postHref = props.postHref ?? (collections ? makeCollectionPostHref(collections) : defaultPostHref);
2664
+ const [page, themeStyle, blogSettings] = await Promise.all([
2665
+ fetchPosts({
2666
+ apiKey,
2667
+ baseUrl,
2668
+ limit,
2669
+ type,
2670
+ ...author ? { author } : {},
2671
+ // blog-list-collection-scope.md §2② — 서버(api-core)가 이미 스트림 글을
2672
+ // 걸러 fetch 하게 한다(limit 이 스트림 글에 낭비되지 않음). 아래
2673
+ // `postsNotInAnyCollection` 클라이언트 필터는 방어선으로 유지.
2674
+ ...excludeCollections && collections ? { excludeCollections: true } : {},
2675
+ // ADR-0052 A안 (W4-6 PR C1) — 미지정 시 서버가 사이트 기본 locale 반환
2676
+ // (하위호환, 기존 소비자 diff 0).
2677
+ ...locale ? { locale } : {}
2678
+ }),
2679
+ resolveThemeStyle({ themeProp, apiKey, baseUrl }),
2680
+ fetchBlogSettings({ apiKey, baseUrl }).catch(() => DEFAULT_BLOG_SETTINGS)
2681
+ ]);
2682
+ const items = collection && collections ? postsForCollection(page.items, collections, collection) : excludeCollections && collections ? postsNotInAnyCollection(page.items, collections) : page.items;
2683
+ if (items.length === 0) {
2684
+ return /* @__PURE__ */ jsx9("div", { "data-roottale-cms": "list", style: themeStyle ?? void 0, children: /* @__PURE__ */ jsx9("p", { className: "rt-cms-empty", children: emptyMessage }) });
2685
+ }
2686
+ const categories = showCategoryFilter ? collectCategories(items) : [];
2687
+ const visiblePosts = showCategoryFilter ? filterPostsByCategory(items, activeCategory) : items;
2688
+ return /* @__PURE__ */ jsxs9("div", { "data-roottale-cms": "list", style: themeStyle ?? void 0, children: [
2689
+ showCategoryFilter && categories.length > 0 ? /* @__PURE__ */ jsxs9("nav", { className: "rt-cms-filter", "aria-label": "\uCE74\uD14C\uACE0\uB9AC \uD544\uD130", children: [
2690
+ /* @__PURE__ */ jsx9(
2691
+ "a",
2692
+ {
2693
+ className: "rt-cms-filter-chip",
2694
+ href: categoryHref(null),
2695
+ "data-active": !activeCategory ? "" : void 0,
2696
+ "aria-current": !activeCategory ? "true" : void 0,
2697
+ children: allCategoriesLabel
2698
+ }
2699
+ ),
2700
+ categories.map((c) => /* @__PURE__ */ jsx9(
2701
+ "a",
2702
+ {
2703
+ className: "rt-cms-filter-chip",
2704
+ href: categoryHref(c.slug),
2705
+ "data-active": activeCategory === c.slug ? "" : void 0,
2706
+ "aria-current": activeCategory === c.slug ? "true" : void 0,
2707
+ children: c.name
2708
+ },
2709
+ c.slug
2710
+ ))
2711
+ ] }) : null,
2712
+ visiblePosts.length === 0 ? /* @__PURE__ */ jsx9("p", { className: "rt-cms-empty", children: emptyMessage }) : /* @__PURE__ */ jsx9("ul", { className: "rt-cms-list", children: visiblePosts.map((post) => /* @__PURE__ */ jsx9("li", { className: "rt-cms-list-item", children: /* @__PURE__ */ jsx9(
2713
+ RootTalePostCard,
2714
+ {
2715
+ post,
2716
+ href: postHref,
2717
+ display: resolvePostDisplay(post, blogSettings)
2718
+ }
2719
+ ) }, post.id)) })
2720
+ ] });
2721
+ }
2722
+ async function RootTaleBlogCategories(props) {
2723
+ const {
2724
+ apiKey,
2725
+ baseUrl,
2726
+ limit,
2727
+ collection,
2728
+ collections,
2729
+ categoryHref = (slug) => defaultCategoryHref(slug),
2730
+ locale,
2731
+ emptyMessage = t(locale, "blogCategoriesEmpty"),
2732
+ theme: themeProp
2733
+ } = props;
2734
+ const [page, themeStyle] = await Promise.all([
2735
+ fetchPosts({ apiKey, baseUrl, limit, type: "post", ...locale ? { locale } : {} }),
2736
+ resolveThemeStyle({ themeProp, apiKey, baseUrl })
2737
+ ]);
2738
+ const categories = collection && collections ? collectCollectionCategories(page.items, collections, collection) : collectCategoriesWithCounts(page.items);
2739
+ return /* @__PURE__ */ jsx9(
2740
+ "nav",
2741
+ {
2742
+ "data-roottale-cms": "categories",
2743
+ className: "rt-cms-categories",
2744
+ "aria-label": "\uBE14\uB85C\uADF8 \uCE74\uD14C\uACE0\uB9AC",
2745
+ style: themeStyle ?? void 0,
2746
+ children: categories.length === 0 ? /* @__PURE__ */ jsx9("p", { className: "rt-cms-empty", children: emptyMessage }) : /* @__PURE__ */ jsx9("ul", { className: "rt-cms-category-list", children: categories.map((category) => /* @__PURE__ */ jsx9("li", { className: "rt-cms-category-list-item", children: /* @__PURE__ */ jsxs9(
2747
+ "a",
2748
+ {
2749
+ className: "rt-cms-category-link",
2750
+ href: categoryHref(category.slug),
2751
+ children: [
2752
+ /* @__PURE__ */ jsx9("span", { className: "rt-cms-category-name", children: category.name }),
2753
+ /* @__PURE__ */ jsx9("span", { className: "rt-cms-category-count", children: category.count })
2754
+ ]
2755
+ }
2756
+ ) }, category.slug)) })
2757
+ }
2758
+ );
2759
+ }
2760
+ async function RootTaleBlogPost(props) {
2761
+ const {
2762
+ apiKey,
2763
+ slugOrId,
2764
+ baseUrl,
2765
+ notFoundElement,
2766
+ showTableOfContents,
2767
+ tableOfContentsTitle,
2768
+ relatedPostsCount = 0,
2769
+ locale,
2770
+ relatedPostsTitle = t(locale, "relatedPostsTitle"),
2771
+ collections,
2772
+ showFieldFacts = false,
2773
+ theme: themeProp
2774
+ } = props;
2775
+ const [post, themeStyle, blogSettings] = await Promise.all([
2776
+ fetchPost({ apiKey, slugOrId, baseUrl, ...locale ? { locale } : {} }),
2777
+ resolveThemeStyle({ themeProp, apiKey, baseUrl }),
2778
+ // 사이트 기본 표시 설정 — 실패해도 렌더는 진행 (안전 기본값).
2779
+ fetchBlogSettings({ apiKey, baseUrl }).catch(() => DEFAULT_BLOG_SETTINGS)
2780
+ ]);
2781
+ if (!post) {
2782
+ return notFoundElement ?? /* @__PURE__ */ jsx9("div", { "data-roottale-cms": "post-missing", style: themeStyle ?? void 0, children: /* @__PURE__ */ jsx9("p", { className: "rt-cms-empty", children: t(locale, "postNotFound") }) });
2783
+ }
2784
+ const display = resolvePostDisplay(post, blogSettings, {
2785
+ showTableOfContents,
2786
+ tableOfContentsTitle
2787
+ });
2788
+ const toc = display.showTableOfContents ? extractToc(post.bodyJson) : [];
2789
+ const renderDoc = toc.length > 0 ? attachHeadingIds(post.bodyJson, toc) : post.bodyJson;
2790
+ let related = [];
2791
+ if (relatedPostsCount > 0) {
2792
+ try {
2793
+ const candidates = await fetchPosts({
2794
+ apiKey,
2795
+ baseUrl,
2796
+ type: "post",
2797
+ limit: 30,
2798
+ // ADR-0052 A안 (W4-6 PR C1) — 같은 언어판 후보로만 좁힌다(ko 글이 en
2799
+ // 페이지 관련 글에 섞이는 걸 방지).
2800
+ ...locale ? { locale } : {}
2801
+ });
2802
+ related = selectRelatedPosts(post, candidates.items, relatedPostsCount);
2803
+ } catch {
2804
+ }
2805
+ }
2806
+ const relatedHref = props.postHref ?? (collections ? makeCollectionPostHref(collections) : defaultPostHref);
2807
+ const authorName = post.authorName;
2808
+ const authorImageUrl = post.authorImageUrl;
2809
+ const postAuthorBio = post.authorBio;
2810
+ const views = typeof post.viewCount === "number" ? post.viewCount : null;
2811
+ const publishedDate = display.showDate ? formatPublishedDate2(post.publishedAt) : "";
2812
+ const showTopAuthor = display.showAuthor && Boolean(authorName);
2813
+ const displayAuthorName = authorName ?? display.authorProfileName;
2814
+ const authorBio = postAuthorBio ?? display.authorProfileBio ?? display.authorCardDescription;
2815
+ const authorImageUrlForCard = authorImageUrl ?? display.authorProfileImageUrl;
2816
+ const authorImageAlt = `${displayAuthorName ?? ""} \uD504\uB85C\uD544 \uC0AC\uC9C4`.trim();
2817
+ const authorImageStyle = {
2818
+ borderRadius: authorImageRadiusCss(display.authorProfileImageRadius),
2819
+ objectPosition: `${display.authorProfileImagePositionX}% ${display.authorProfileImagePositionY}%`
2820
+ };
2821
+ const showAuthorCard = display.showAuthorCard && Boolean(displayAuthorName);
2822
+ return /* @__PURE__ */ jsxs9(
2823
+ "article",
2824
+ {
2825
+ "data-roottale-cms": "post",
2826
+ className: "rt-cms-article",
2827
+ style: themeStyle ?? void 0,
2828
+ children: [
2829
+ /* @__PURE__ */ jsxs9("header", { className: "rt-cms-post-header", children: [
2830
+ /* @__PURE__ */ jsx9("h1", { className: "rt-cms-title", children: post.title }),
2831
+ post.excerpt ? /* @__PURE__ */ jsx9("p", { className: "rt-cms-excerpt", children: post.excerpt }) : null,
2832
+ publishedDate || showTopAuthor || views !== null ? /* @__PURE__ */ jsxs9("p", { className: "rt-cms-meta", children: [
2833
+ publishedDate ? /* @__PURE__ */ jsx9("span", { className: "rt-cms-meta-item", "data-rt-cms-meta": "date", children: publishedDate }) : null,
2834
+ showTopAuthor ? /* @__PURE__ */ jsxs9("span", { className: "rt-cms-meta-item", "data-rt-cms-meta": "author", children: [
2835
+ "\uC791\uC131\uC790 ",
2836
+ authorName
2837
+ ] }) : null,
2838
+ views !== null ? /* @__PURE__ */ jsxs9("span", { className: "rt-cms-meta-item", "data-rt-cms-meta": "views", children: [
2839
+ "\uC870\uD68C ",
2840
+ views.toLocaleString("ko-KR")
2841
+ ] }) : null
2842
+ ] }) : null
2843
+ ] }),
2844
+ renderArchiveRelated(post.archiveRelated, collections),
2845
+ showFieldFacts ? renderFieldFacts(post) : null,
2846
+ (() => {
2847
+ const tocEl = toc.length > 0 ? /* @__PURE__ */ jsx9(RootTaleTableOfContents, { entries: toc, title: display.tocTitle }) : null;
2848
+ const bodyEl = /* @__PURE__ */ jsx9("div", { "data-roottale-cms": "body", className: "rt-cms-body", children: /* @__PURE__ */ jsx9(
2849
+ RenderTiptap,
2850
+ {
2851
+ doc: renderDoc,
2852
+ fields: post.fields,
2853
+ apiKey,
2854
+ baseUrl
2855
+ }
2856
+ ) });
2857
+ if (display.tocPosition === "sidebar" && tocEl) {
2858
+ return /* @__PURE__ */ jsxs9("div", { className: "rt-cms-layout rt-cms-layout--toc-side", children: [
2859
+ bodyEl,
2860
+ /* @__PURE__ */ jsx9("aside", { className: "rt-cms-toc-side", children: tocEl })
2861
+ ] });
2862
+ }
2863
+ return /* @__PURE__ */ jsxs9(Fragment3, { children: [
2864
+ tocEl,
2865
+ bodyEl
2866
+ ] });
2867
+ })(),
2868
+ showAuthorCard && displayAuthorName ? /* @__PURE__ */ jsxs9("section", { className: "rt-cms-author-card", "aria-label": "\uC791\uC131\uC790", children: [
2869
+ authorImageUrlForCard ? /* @__PURE__ */ jsx9(
2870
+ "img",
2871
+ {
2872
+ className: "rt-cms-author-card__image",
2873
+ src: authorImageUrlForCard,
2874
+ alt: authorImageAlt,
2875
+ loading: "lazy",
2876
+ style: authorImageStyle
2877
+ }
2878
+ ) : /* @__PURE__ */ jsx9("div", { className: "rt-cms-author-card__avatar", "aria-hidden": "true", children: authorInitials(displayAuthorName) }),
2879
+ /* @__PURE__ */ jsxs9("div", { className: "rt-cms-author-card__body", children: [
2880
+ /* @__PURE__ */ jsx9("p", { className: "rt-cms-author-card__eyebrow", children: display.authorCardEyebrow }),
2881
+ /* @__PURE__ */ jsx9("p", { className: "rt-cms-author-card__name", children: displayAuthorName }),
2882
+ authorBio ? /* @__PURE__ */ jsx9("p", { className: "rt-cms-author-card__description", children: authorBio }) : null
2883
+ ] })
2884
+ ] }) : null,
2885
+ renderRelated(related, relatedHref, relatedPostsTitle),
2886
+ renderPostCta(blogSettings.postCta),
2887
+ renderFaqJsonLd(post.bodyJson)
2888
+ ]
2889
+ }
2890
+ );
2891
+ }
2892
+ function renderArchiveRelated(groups, collections) {
2893
+ const visible = groups.filter((group) => group.items.length > 0);
2894
+ if (visible.length === 0) return null;
2895
+ return /* @__PURE__ */ jsx9("aside", { className: "rt-archive-related", "aria-label": "\uC5F0\uAD00 \uC815\uBCF4", children: visible.map((group) => /* @__PURE__ */ jsxs9("section", { className: "rt-archive-related__group", children: [
2896
+ /* @__PURE__ */ jsx9("h2", { className: "rt-archive-related__title", children: archiveGroupTitle(group) }),
2897
+ /* @__PURE__ */ jsx9("ul", { className: "rt-archive-related__list", children: group.items.map((item) => /* @__PURE__ */ jsx9("li", { className: "rt-archive-related__item", children: /* @__PURE__ */ jsxs9(
2898
+ "a",
2899
+ {
2900
+ className: "rt-archive-related__link",
2901
+ href: archivePostHref(item.collectionKey, item.slug, collections),
2902
+ children: [
2903
+ /* @__PURE__ */ jsx9("span", { className: "rt-archive-related__item-title", children: item.title }),
2904
+ item.excerpt ? /* @__PURE__ */ jsx9("span", { className: "rt-archive-related__item-excerpt", children: item.excerpt }) : null
2905
+ ]
2906
+ }
2907
+ ) }, item.id)) })
2908
+ ] }, group.collectionKey)) });
2909
+ }
2910
+ var FIELD_FACT_TYPES = /* @__PURE__ */ new Set([
2911
+ "text",
2912
+ "textarea",
2913
+ "email",
2914
+ "url",
2915
+ "select",
2916
+ "radio",
2917
+ "button_group",
2918
+ "number",
2919
+ "range"
2920
+ ]);
2921
+ function fieldFactValue(raw, meta) {
2922
+ if (raw === null || raw === void 0) return null;
2923
+ if (typeof raw === "number") return raw.toLocaleString("ko-KR");
2924
+ if (typeof raw !== "string" || raw.trim() === "") return null;
2925
+ if (meta.choices) {
2926
+ const choice = meta.choices.find((c) => c.value === raw);
2927
+ return choice ? choice.label : raw;
2928
+ }
2929
+ return raw;
2930
+ }
2931
+ function renderFieldFacts(post) {
2932
+ const fields = post.fields;
2933
+ if (!fields) return null;
2934
+ const rows = post.fieldsMeta.filter((meta) => FIELD_FACT_TYPES.has(meta.type)).flatMap((meta) => {
2935
+ const value = fieldFactValue(fields[meta.name], meta);
2936
+ return value === null ? [] : [{ meta, value }];
2937
+ });
2938
+ if (rows.length === 0) return null;
2939
+ return /* @__PURE__ */ jsx9("aside", { className: "rt-archive-facts", "aria-label": "\uC0C1\uC138 \uC815\uBCF4", children: /* @__PURE__ */ jsx9("dl", { className: "rt-archive-facts__list", children: rows.map(({ meta, value }) => /* @__PURE__ */ jsxs9("div", { className: "rt-archive-facts__row", children: [
2940
+ /* @__PURE__ */ jsx9("dt", { className: "rt-archive-facts__label", children: meta.label }),
2941
+ /* @__PURE__ */ jsx9(
2942
+ "dd",
2943
+ {
2944
+ className: meta.type === "textarea" ? "rt-archive-facts__value rt-archive-facts__value--multiline" : "rt-archive-facts__value",
2945
+ children: value
2946
+ }
2947
+ )
2948
+ ] }, meta.name)) }) });
2949
+ }
2950
+ function archiveGroupTitle(group) {
2951
+ if (group.collectionKey === "conditions") {
2952
+ return `\uC774 \uC99D\uC0C1\uACFC \uAD00\uB828\uB41C \uC9C8\uD658 ${group.items.length}`;
2953
+ }
2954
+ if (group.collectionKey === "treatments") {
2955
+ return `\uAD00\uB828 \uCE58\uB8CC\uBC95 ${group.items.length}`;
2956
+ }
2957
+ if (group.collectionKey === "symptoms") {
2958
+ return `\uAD00\uB828 \uC99D\uC0C1 ${group.items.length}`;
2959
+ }
2960
+ return `${group.label} ${group.items.length}`;
2961
+ }
2962
+ function archivePostHref(collectionKey, slug, collections) {
2963
+ const collection = collections?.find((item) => item.key === collectionKey);
2964
+ const basePath = collection?.basePath ?? defaultArchiveBasePath(collectionKey);
2965
+ return `${basePath.replace(/\/+$/, "")}/${slug}`;
2966
+ }
2967
+ function defaultArchiveBasePath(collectionKey) {
2968
+ if (collectionKey === "symptoms") return "/symptoms";
2969
+ if (collectionKey === "conditions") return "/conditions";
2970
+ if (collectionKey === "treatments") return "/treatments";
2971
+ return "/blog";
2972
+ }
2973
+ function renderPostCta(cta) {
2974
+ if (!cta) return null;
2975
+ const href = cta.buttonHref.trim();
2976
+ const safe = href.startsWith("/") || href.startsWith("#") || /^(https?:|mailto:|tel:)/i.test(href);
2977
+ if (!safe) return null;
2978
+ const external = /^https?:/i.test(href);
2979
+ return /* @__PURE__ */ jsxs9("aside", { "data-roottale-cms": "post-cta", className: "rt-cms-post-cta", children: [
2980
+ cta.title ? /* @__PURE__ */ jsx9("p", { className: "rt-cms-post-cta__title", children: cta.title }) : null,
2981
+ cta.description ? /* @__PURE__ */ jsx9("p", { className: "rt-cms-post-cta__desc", children: cta.description }) : null,
2982
+ /* @__PURE__ */ jsx9(
2983
+ "a",
2984
+ {
2985
+ className: "rt-cms-post-cta__btn",
2986
+ href,
2987
+ target: external ? "_blank" : void 0,
2988
+ rel: external ? "noopener noreferrer" : void 0,
2989
+ children: cta.buttonLabel
2990
+ }
2991
+ )
2992
+ ] });
2993
+ }
2994
+ function renderRelated(posts, href, title) {
2995
+ if (posts.length === 0) return null;
2996
+ return /* @__PURE__ */ jsxs9("nav", { "data-roottale-cms": "related", className: "rt-cms-related", "aria-label": title, children: [
2997
+ /* @__PURE__ */ jsx9("h2", { className: "rt-cms-related-title", children: title }),
2998
+ /* @__PURE__ */ jsx9("ul", { className: "rt-cms-related-list", children: posts.map((p) => /* @__PURE__ */ jsx9("li", { className: "rt-cms-related-item", children: /* @__PURE__ */ jsxs9("a", { className: "rt-cms-related-link", href: href(p), children: [
2999
+ p.featuredImageUrl ? /* @__PURE__ */ jsx9(
3000
+ "img",
3001
+ {
3002
+ className: "rt-cms-related-thumb",
3003
+ src: p.featuredImageUrl,
3004
+ alt: "",
3005
+ loading: "lazy"
3006
+ }
3007
+ ) : null,
3008
+ /* @__PURE__ */ jsx9("span", { className: "rt-cms-related-post-title", children: p.title })
3009
+ ] }) }, p.id)) })
3010
+ ] });
3011
+ }
3012
+ function renderFaqJsonLd(doc) {
3013
+ const ld = faqPageJsonLd(extractFaqEntries(doc));
3014
+ if (!ld) return null;
3015
+ return /* @__PURE__ */ jsx9(
3016
+ "script",
3017
+ {
3018
+ type: "application/ld+json",
3019
+ dangerouslySetInnerHTML: { __html: jsonLdJson(ld) }
3020
+ }
3021
+ );
3022
+ }
3023
+ function RootTaleFaqJsonLd({
3024
+ doc
3025
+ }) {
3026
+ return renderFaqJsonLd(doc);
3027
+ }
3028
+ async function RootTalePage(props) {
3029
+ const {
3030
+ apiKey,
3031
+ slugOrId,
3032
+ baseUrl,
3033
+ notFoundElement,
3034
+ showTitle = true,
3035
+ theme: themeProp,
3036
+ locale
3037
+ } = props;
3038
+ const [post, themeStyle] = await Promise.all([
3039
+ fetchPost({ apiKey, slugOrId, baseUrl, ...locale ? { locale } : {} }),
3040
+ resolveThemeStyle({ themeProp, apiKey, baseUrl })
3041
+ ]);
3042
+ if (!post) {
3043
+ return notFoundElement ?? /* @__PURE__ */ jsx9("div", { "data-roottale-cms": "page-missing", style: themeStyle ?? void 0, children: /* @__PURE__ */ jsx9("p", { className: "rt-cms-empty", children: t(locale, "pageNotFound") }) });
3044
+ }
3045
+ return /* @__PURE__ */ jsxs9(
3046
+ "article",
3047
+ {
3048
+ "data-roottale-cms": "page",
3049
+ className: "rt-cms-article",
3050
+ style: themeStyle ?? void 0,
3051
+ children: [
3052
+ showTitle ? /* @__PURE__ */ jsx9("header", { className: "rt-cms-post-header", children: /* @__PURE__ */ jsx9("h1", { className: "rt-cms-title", children: post.title }) }) : null,
3053
+ /* @__PURE__ */ jsx9("div", { "data-roottale-cms": "body", className: "rt-cms-body", children: /* @__PURE__ */ jsx9(
3054
+ RenderTiptap,
3055
+ {
3056
+ doc: post.bodyJson,
3057
+ fields: post.fields,
3058
+ apiKey,
3059
+ baseUrl
3060
+ }
3061
+ ) })
3062
+ ]
3063
+ }
3064
+ );
3065
+ }
3066
+ function authorInitials(name) {
3067
+ const trimmed = name.trim();
3068
+ if (!trimmed) return "";
3069
+ const parts = trimmed.split(/\s+/).filter(Boolean);
3070
+ if (parts.length >= 2) {
3071
+ return `${parts[0]?.[0] ?? ""}${parts[1]?.[0] ?? ""}`.toUpperCase();
3072
+ }
3073
+ return [...trimmed].slice(0, 2).join("").toUpperCase();
3074
+ }
3075
+ async function resolveThemeStyle(input) {
3076
+ const { themeProp, apiKey, baseUrl } = input;
3077
+ if (themeProp === null) return null;
3078
+ if (themeProp !== void 0) return themeToCssVars2(themeProp);
3079
+ try {
3080
+ const fetched = await fetchTheme({ apiKey, baseUrl });
3081
+ return themeToCssVars2(fetched);
3082
+ } catch {
3083
+ return null;
3084
+ }
3085
+ }
3086
+ function defaultPostHref(post) {
3087
+ return `/blog/${post.slug}`;
3088
+ }
3089
+ function makeCollectionPostHref(collections) {
3090
+ return (post) => resolvePostPath(post, collections) ?? defaultPostHref(post);
3091
+ }
3092
+ function formatPublishedDate2(iso) {
3093
+ const d = new Date(iso);
3094
+ if (Number.isNaN(d.getTime())) return "";
3095
+ return new Intl.DateTimeFormat("ko-KR", {
3096
+ year: "numeric",
3097
+ month: "2-digit",
3098
+ day: "2-digit"
3099
+ }).format(d);
3100
+ }
3101
+ function RenderTiptap({
3102
+ doc,
3103
+ fields,
3104
+ apiKey,
3105
+ baseUrl
3106
+ }) {
3107
+ const rawContent = doc.content;
3108
+ const content = Array.isArray(rawContent) ? rawContent : [];
3109
+ const hasToc = content.some((n) => n?.type === "tableOfContents");
3110
+ const docRecord = doc;
3111
+ const entries = hasToc ? extractToc(docRecord) : [];
3112
+ const renderDoc = hasToc && entries.length > 0 ? attachHeadingIds(docRecord, entries) : docRecord;
3113
+ const nodes = Array.isArray(renderDoc.content) ? renderDoc.content : content;
3114
+ const cms = apiKey ? { apiKey, baseUrl } : null;
3115
+ const context = {
3116
+ fields: fields ?? null,
3117
+ section: {
3118
+ cms,
3119
+ isDev: isDevEnv,
3120
+ renderBlogList: (props) => /* @__PURE__ */ jsx9(RootTaleBlogList, { ...props })
3121
+ }
3122
+ };
3123
+ return /* @__PURE__ */ jsx9(Fragment3, { children: nodes.map(
3124
+ (node, i) => node?.type === "tableOfContents" ? /* @__PURE__ */ jsx9(
3125
+ RootTaleTableOfContents,
3126
+ {
3127
+ entries,
3128
+ title: typeof node.attrs?.title === "string" ? node.attrs.title : "\uBAA9\uCC28"
3129
+ },
3130
+ i
3131
+ ) : renderNode(node, i, context)
3132
+ ) });
3133
+ }
3134
+ function boundContentText(node, fields) {
3135
+ return bindingTextValue(
3136
+ boundFieldValue(node.attrs?.bindings, "content", fields)
3137
+ );
3138
+ }
3139
+ function isSafeHref(value) {
3140
+ if (typeof value !== "string") return false;
3141
+ const v = value.trim();
3142
+ if (v.length === 0) return false;
3143
+ if (v.startsWith("/") || v.startsWith("#") || v.startsWith("?")) return true;
3144
+ return /^(https?:|mailto:|tel:)/i.test(v);
3145
+ }
3146
+ function alignStyle(node) {
3147
+ const align = node.attrs?.textAlign;
3148
+ if (typeof align !== "string" || align === "" || align === "left") return void 0;
3149
+ if (align === "center" || align === "right" || align === "justify") {
3150
+ return { textAlign: align };
3151
+ }
3152
+ return void 0;
3153
+ }
3154
+ function tableCellSpans(node) {
3155
+ const colspan = Number(node.attrs?.colspan);
3156
+ const rowspan = Number(node.attrs?.rowspan);
3157
+ return {
3158
+ colSpan: Number.isFinite(colspan) && colspan > 1 ? colspan : void 0,
3159
+ rowSpan: Number.isFinite(rowspan) && rowspan > 1 ? rowspan : void 0
3160
+ };
3161
+ }
3162
+ function isDevEnv() {
3163
+ const env = globalThis.process?.env ?? {};
3164
+ return env.NODE_ENV !== "production";
3165
+ }
3166
+ function renderNode(node, key, context = {
3167
+ fields: null,
3168
+ section: {
3169
+ cms: null,
3170
+ isDev: isDevEnv,
3171
+ renderBlogList: (props) => /* @__PURE__ */ jsx9(RootTaleBlogList, { ...props })
3172
+ }
3173
+ }) {
3174
+ if (!node || typeof node !== "object") return null;
3175
+ const children = Array.isArray(node.content) ? node.content.map((child, i) => renderNode(child, i, context)) : void 0;
3176
+ switch (node.type) {
3177
+ case "paragraph": {
3178
+ const bound = boundContentText(node, context.fields);
3179
+ return /* @__PURE__ */ jsx9("p", { style: alignStyle(node), children: bound ?? children }, key);
3180
+ }
3181
+ case "heading": {
3182
+ const rawLevel = Number(node.attrs?.level ?? 2);
3183
+ const level = Math.min(Math.max(Number.isFinite(rawLevel) ? rawLevel : 2, 2), 4);
3184
+ const idAttr = node.attrs?.id;
3185
+ const id = typeof idAttr === "string" && idAttr.length > 0 ? idAttr : void 0;
3186
+ const style = alignStyle(node);
3187
+ const inner = boundContentText(node, context.fields) ?? children;
3188
+ if (level === 2) return /* @__PURE__ */ jsx9("h2", { id, style, children: inner }, key);
3189
+ if (level === 3) return /* @__PURE__ */ jsx9("h3", { id, style, children: inner }, key);
3190
+ return /* @__PURE__ */ jsx9("h4", { id, style, children: inner }, key);
3191
+ }
3192
+ case "bulletList":
3193
+ return /* @__PURE__ */ jsx9("ul", { children }, key);
3194
+ case "orderedList":
3195
+ return /* @__PURE__ */ jsx9("ol", { children }, key);
3196
+ case "listItem":
3197
+ return /* @__PURE__ */ jsx9("li", { children }, key);
3198
+ case "blockquote":
3199
+ return /* @__PURE__ */ jsx9("blockquote", { children }, key);
3200
+ case "codeBlock":
3201
+ return /* @__PURE__ */ jsx9("pre", { children: /* @__PURE__ */ jsx9("code", { children }) }, key);
3202
+ case "horizontalRule":
3203
+ return /* @__PURE__ */ jsx9("hr", {}, key);
3204
+ case "hardBreak":
3205
+ return /* @__PURE__ */ jsx9("br", {}, key);
3206
+ case "image": {
3207
+ const boundSrc = bindingSrcValue(
3208
+ boundFieldValue(node.attrs?.bindings, "src", context.fields)
3209
+ );
3210
+ const src = boundSrc ?? node.attrs?.src;
3211
+ if (typeof src !== "string" || src.length === 0) return null;
3212
+ const alt = typeof node.attrs?.alt === "string" ? node.attrs.alt : "";
3213
+ const title = typeof node.attrs?.title === "string" ? node.attrs.title : void 0;
3214
+ const width = typeof node.attrs?.width === "number" && node.attrs.width > 0 ? node.attrs.width : void 0;
3215
+ const height = typeof node.attrs?.height === "number" && node.attrs.height > 0 ? node.attrs.height : void 0;
3216
+ return /* @__PURE__ */ jsx9(
3217
+ "img",
3218
+ {
3219
+ src,
3220
+ alt,
3221
+ title,
3222
+ width,
3223
+ height,
3224
+ loading: "lazy"
3225
+ },
3226
+ key
3227
+ );
3228
+ }
3229
+ case "columns":
3230
+ return /* @__PURE__ */ jsx9("div", { className: "rt-columns", children }, key);
3231
+ case "column":
3232
+ return /* @__PURE__ */ jsx9("div", { className: "rt-column", children }, key);
3233
+ case "table":
3234
+ return /* @__PURE__ */ jsx9("div", { className: "rt-table-wrap", children: /* @__PURE__ */ jsx9("table", { className: "rt-table", children: /* @__PURE__ */ jsx9("tbody", { children }) }) }, key);
3235
+ case "tableRow":
3236
+ return /* @__PURE__ */ jsx9("tr", { children }, key);
3237
+ case "tableHeader": {
3238
+ const { colSpan, rowSpan } = tableCellSpans(node);
3239
+ return /* @__PURE__ */ jsx9("th", { colSpan, rowSpan, children }, key);
3240
+ }
3241
+ case "tableCell": {
3242
+ const { colSpan, rowSpan } = tableCellSpans(node);
3243
+ return /* @__PURE__ */ jsx9("td", { colSpan, rowSpan, children }, key);
3244
+ }
3245
+ case "embed":
3246
+ return renderEmbed(node, key);
3247
+ case "faq":
3248
+ return /* @__PURE__ */ jsx9("div", { "data-roottale-cms": "faq", className: "rt-cms-faq", children }, key);
3249
+ case "faqItem":
3250
+ return /* @__PURE__ */ jsx9("details", { className: "rt-cms-faq-item", children }, key);
3251
+ case "faqQuestion":
3252
+ return /* @__PURE__ */ jsx9("summary", { className: "rt-cms-faq-q", children }, key);
3253
+ case "faqAnswer":
3254
+ return /* @__PURE__ */ jsx9("div", { className: "rt-cms-faq-a", children }, key);
3255
+ case "tableOfContents":
3256
+ return null;
3257
+ case "section":
3258
+ return renderSectionNode(node, key, context.section);
3259
+ case "text":
3260
+ return renderText(node, key);
3261
+ default:
3262
+ return children ? /* @__PURE__ */ jsx9("span", { children }, key) : null;
3263
+ }
3264
+ }
3265
+ function renderEmbed(node, key) {
3266
+ const src = node.attrs?.src;
3267
+ if (isAllowedEmbedSrc2(src)) {
3268
+ const provider = typeof node.attrs?.provider === "string" ? node.attrs.provider : void 0;
3269
+ return /* @__PURE__ */ jsx9(
3270
+ "div",
3271
+ {
3272
+ className: "rt-embed",
3273
+ "data-provider": provider,
3274
+ style: { aspectRatio: "16 / 9" },
3275
+ children: /* @__PURE__ */ jsx9(
3276
+ "iframe",
3277
+ {
3278
+ src,
3279
+ title: "\uC784\uBCA0\uB4DC\uB41C \uC601\uC0C1",
3280
+ loading: "lazy",
3281
+ allowFullScreen: true,
3282
+ referrerPolicy: "strict-origin-when-cross-origin",
3283
+ allow: "accelerometer; clipboard-write; encrypted-media; picture-in-picture; web-share",
3284
+ style: { width: "100%", height: "100%", border: 0 }
3285
+ }
3286
+ )
3287
+ },
3288
+ key
3289
+ );
3290
+ }
3291
+ const orig = node.attrs?.originalUrl;
3292
+ if (isSafeHref(orig)) {
3293
+ return /* @__PURE__ */ jsx9("p", { className: "rt-embed-fallback", children: /* @__PURE__ */ jsx9("a", { href: orig, rel: "noopener noreferrer", target: "_blank", children: orig }) }, key);
3294
+ }
3295
+ return null;
3296
+ }
3297
+ function renderText(node, key) {
3298
+ const text = node.text ?? "";
3299
+ const marks = node.marks ?? [];
3300
+ if (marks.length === 0) return text;
3301
+ let element = text;
3302
+ for (const mark of marks) {
3303
+ element = applyMark(mark, element);
3304
+ }
3305
+ return /* @__PURE__ */ jsx9("span", { children: element }, key);
3306
+ }
3307
+ function applyMark(mark, child) {
3308
+ switch (mark.type) {
3309
+ case "bold":
3310
+ return /* @__PURE__ */ jsx9("strong", { children: child });
3311
+ case "italic":
3312
+ return /* @__PURE__ */ jsx9("em", { children: child });
3313
+ case "underline":
3314
+ return /* @__PURE__ */ jsx9("u", { children: child });
3315
+ case "strike":
3316
+ return /* @__PURE__ */ jsx9("s", { children: child });
3317
+ case "code":
3318
+ return /* @__PURE__ */ jsx9("code", { children: child });
3319
+ case "highlight": {
3320
+ const color = mark.attrs?.color;
3321
+ const style = typeof color === "string" && color.length > 0 ? { background: color } : void 0;
3322
+ return /* @__PURE__ */ jsx9("mark", { style, children: child });
3323
+ }
3324
+ case "textStyle": {
3325
+ const color = mark.attrs?.color;
3326
+ const style = typeof color === "string" && color.length > 0 ? { color } : void 0;
3327
+ if (!style) return /* @__PURE__ */ jsx9(Fragment3, { children: child });
3328
+ return /* @__PURE__ */ jsx9("span", { style, children: child });
3329
+ }
3330
+ case "link": {
3331
+ const raw = mark.attrs?.href;
3332
+ const href = isSafeHref(raw) ? raw : "#";
3333
+ return /* @__PURE__ */ jsx9("a", { href, rel: "noopener noreferrer", target: "_blank", children: child });
3334
+ }
3335
+ default:
3336
+ return /* @__PURE__ */ jsx9("span", { children: child });
3337
+ }
3338
+ }
3339
+
3340
+ export {
3341
+ RootTaleLeadForm,
3342
+ sectionThemeStyle,
3343
+ TemplateHero,
3344
+ TemplateRichText,
3345
+ TemplateServices,
3346
+ TemplateFooter,
3347
+ TemplateFaq,
3348
+ TemplateCtaBanner,
3349
+ TemplateTrust,
3350
+ TemplateTestimonials,
3351
+ TemplateTeam,
3352
+ TemplateContact,
3353
+ TemplateHours,
3354
+ TemplatePricing,
3355
+ TemplateProcess,
3356
+ TemplateBeforeAfter,
3357
+ TemplateExpertise,
3358
+ TemplateSpaces,
3359
+ TemplateConcerns,
3360
+ RootTalePostCard,
3361
+ RootTaleTableOfContents,
3362
+ themeToCssVars2 as themeToCssVars,
3363
+ headingToId,
3364
+ extractToc,
3365
+ attachHeadingIds,
3366
+ RootTaleFloatingCta,
3367
+ renderBlock,
3368
+ renderBlocks,
3369
+ renderBoundBlocks,
3370
+ RootTaleThemeProvider,
3371
+ RootTaleBlogList,
3372
+ RootTaleBlogCategories,
3373
+ RootTaleBlogPost,
3374
+ RootTaleFaqJsonLd,
3375
+ RootTalePage,
3376
+ RenderTiptap
3377
+ };
3378
+ //# sourceMappingURL=chunk-RSNUZ4BF.js.map