{"id":10,"date":"2026-07-28T20:23:20","date_gmt":"2026-07-28T20:23:20","guid":{"rendered":"https:\/\/okalura.com\/?page_id=10"},"modified":"2026-07-28T20:49:11","modified_gmt":"2026-07-28T20:49:11","slug":"home-page","status":"publish","type":"page","link":"https:\/\/okalura.com\/","title":{"rendered":"Home page"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"10\" class=\"elementor elementor-10\">\n\t\t\t\t<div class=\"elementor-element elementor-element-be3c896 e-con-full e-flex e-con e-parent\" data-id=\"be3c896\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-8bbd74c elementor-widget elementor-widget-html\" data-id=\"8bbd74c\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<x-dc>\n<helmet>\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" \/>\n<link rel=\"preconnect\" href=\"https:\/\/fonts.googleapis.com\" \/>\n<link rel=\"preconnect\" href=\"https:\/\/fonts.gstatic.com\" crossorigin=\"\" \/>\n<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&family=IBM+Plex+Mono:wght@400;500&display=swap\" rel=\"stylesheet\" \/>\n<style>\n  html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }\n  body { margin: 0; background: #050506; color: #f4f4f5; font-family: 'Plus Jakarta Sans', system-ui, sans-serif; -webkit-font-smoothing: antialiased; overflow-x: hidden; }\n  * { box-sizing: border-box; }\n  a { color: #f4f4f5; text-decoration: none; }\n  a:hover { color: oklch(0.78 0.13 255); }\n  ::selection { background: oklch(0.62 0.16 268); color: #fff; }\n  ::-webkit-scrollbar { height: 0; width: 0; }\n  @keyframes floatA { 0%,100% { transform: translate3d(0,0,0) scale(1); } 50% { transform: translate3d(0,-26px,0) scale(1.06); } }\n  @keyframes floatB { 0%,100% { transform: translate3d(0,0,0) scale(1); } 50% { transform: translate3d(18px,20px,0) scale(0.95); } }\n  @keyframes spinSlow { to { transform: rotate(360deg); } }\n  @keyframes shimmer { 0% { transform: translateX(-120%); } 100% { transform: translateX(220%); } }\n  @keyframes pulseDot { 0%,100% { opacity: .25; } 50% { opacity: 1; } }\n  @keyframes riseIn { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }\n  @keyframes marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }\n  @keyframes shake { 10%,90% { transform: translateX(-1px); } 20%,80% { transform: translateX(2px); } 30%,50%,70% { transform: translateX(-4px); } 40%,60% { transform: translateX(4px); } }\n  @keyframes shakeAlt { 10%,90% { transform: translateX(-1px); } 20%,80% { transform: translateX(2px); } 30%,50%,70% { transform: translateX(-4px); } 40%,60% { transform: translateX(4px); } }\n  @keyframes spin { to { transform: rotate(360deg); } }\n  @keyframes drawRing { from { stroke-dashoffset: 276; } to { stroke-dashoffset: 0; } }\n  @keyframes drawCheck { from { stroke-dashoffset: 62; } to { stroke-dashoffset: 0; } }\n  @keyframes popIn { 0% { opacity: 0; transform: scale(.86); } 60% { opacity: 1; transform: scale(1.04); } 100% { opacity: 1; transform: scale(1); } }\n  @keyframes spark { 0% { opacity: 0; transform: translate(0,0) scale(.4); } 40% { opacity: 1; } 100% { opacity: 0; transform: translate(var(--dx), var(--dy)) scale(1); } }\n  @keyframes fadeUp { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }\n  input:focus-visible, button:focus-visible, a:focus-visible { outline: 2px solid oklch(0.78 0.13 255); outline-offset: 2px; }\n  input::placeholder { color: #4f4f59; }\n<\/style>\n<\/helmet>\n\n<div style=\"position: relative; width: 100%; overflow: hidden; background: radial-gradient(120% 70% at 50% -10%, oklch(0.28 0.09 268 \/ 0.45), transparent 60%), #050506\">\n\n  <sc-if value=\"{{ isDesktop }}\" hint-placeholder-val=\"{{ true }}\">\n    <div style=\"position: fixed; top: 0; left: 0; width: 620px; height: 620px; margin: -310px 0 0 -310px; border-radius: 50%; pointer-events: none; z-index: 3; background: radial-gradient(circle, oklch(0.62 0.16 268 \/ 0.13), transparent 62%); transform: translate3d({{ mx }}px, {{ my }}px, 0); transition: transform .18s cubic-bezier(.22,1,.36,1)\"><\/div>\n  <\/sc-if>\n\n  <nav style=\"position: fixed; top: 0; left: 0; right: 0; z-index: 40; backdrop-filter: {{ navBlur }}; -webkit-backdrop-filter: {{ navBlur }}; background: {{ navBg }}; border-bottom: 1px solid {{ navBorder }}; transition: background .4s ease, border-color .4s ease, backdrop-filter .4s ease\">\n    <div style=\"display: flex; align-items: center; justify-content: space-between; gap: 24px; width: 100%; max-width: {{ maxW }}; margin: 0 auto; padding: {{ navPad }}\">\n      <a href=\"#top\" style=\"display: flex; align-items: center; gap: 10px\">\n        <img decoding=\"async\" src=\"https:\/\/okalura.com\/wp-content\/uploads\/2026\/07\/Okalura-Logo-White.png\" alt=\"okalura\" style=\"width: 40px; height: 40px; object-fit: contain; display: block; opacity: .95\" \/>\n        <span style=\"font-size: 16px; font-weight: 700; letter-spacing: -0.02em\">okalura<\/span>\n      <\/a>\n      <sc-if value=\"{{ isDesktop }}\" hint-placeholder-val=\"{{ true }}\">\n        <div style=\"display: flex; align-items: center; gap: 34px; font-size: 14.5px; color: #a1a1ab; font-weight: 500\">\n          <a href=\"#work\" style=\"color: inherit; transition: color .25s ease\" style-hover=\"color:#fff\">Work<\/a>\n          <a href=\"#why\" style=\"color: inherit; transition: color .25s ease\" style-hover=\"color:#fff\">Why us<\/a>\n          <a href=\"#process\" style=\"color: inherit; transition: color .25s ease\" style-hover=\"color:#fff\">Process<\/a>\n          <a href=\"#pricing\" style=\"color: inherit; transition: color .25s ease\" style-hover=\"color:#fff\">Pricing<\/a>\n          <a href=\"#faq\" style=\"color: inherit; transition: color .25s ease\" style-hover=\"color:#fff\">FAQ<\/a>\n        <\/div>\n      <\/sc-if>\n      <div style=\"display: flex; align-items: center; gap: 10px\">\n        <sc-if value=\"{{ isDesktop }}\" hint-placeholder-val=\"{{ true }}\">\n          <a href=\"#work\" style=\"font-size: 14.5px; font-weight: 600; color: #a1a1ab; padding: 10px 14px; border-radius: 999px; transition: color .25s ease, background .25s ease\" style-hover=\"color:#fff;background:rgba(255,255,255,.06)\">See our work<\/a>\n        <\/sc-if>\n        <a href=\"#cta\" onClick=\"{{ openModal }}\" style=\"display: inline-flex; align-items: center; gap: 8px; font-size: 14.5px; font-weight: 650; color: #08080a; background: linear-gradient(180deg, #ffffff, #d8d8e0); padding: 12px 20px; border-radius: 999px; box-shadow: 0 8px 26px rgba(255,255,255,.14); transition: transform .25s cubic-bezier(.22,1,.36,1), box-shadow .25s ease\" style-hover=\"transform:translateY(-1px);box-shadow:0 12px 34px rgba(255,255,255,.22)\">Start your project<\/a>\n      <\/div>\n    <\/div>\n  <\/nav>\n\n  <!-- HERO -->\n  <section id=\"top\" data-screen-label=\"Hero\" style=\"position: relative; padding: {{ heroPad }}\">\n    <div style=\"position: absolute; inset: 0; overflow: hidden; pointer-events: none\">\n      <div style=\"position: absolute; top: -12%; left: 8%; width: 46vw; height: 46vw; max-width: 620px; max-height: 620px; border-radius: 50%; filter: blur(80px); background: oklch(0.55 0.17 268 \/ 0.42); animation: floatA 16s ease-in-out infinite\"><\/div>\n      <div style=\"position: absolute; top: 18%; right: -8%; width: 40vw; height: 40vw; max-width: 520px; max-height: 520px; border-radius: 50%; filter: blur(90px); background: oklch(0.52 0.16 318 \/ 0.34); animation: floatB 20s ease-in-out infinite\"><\/div>\n      <div style=\"position: absolute; inset: 0; opacity: .5; background-image: linear-gradient(rgba(255,255,255,.045) 1px, transparent 1px), linear-gradient(90deg, rgba(255,255,255,.045) 1px, transparent 1px); background-size: 68px 68px; mask-image: radial-gradient(80% 60% at 50% 25%, #000 20%, transparent 75%); -webkit-mask-image: radial-gradient(80% 60% at 50% 25%, #000 20%, transparent 75%)\"><\/div>\n      <div style=\"position: absolute; top: 8%; left: 50%; width: min(1000px, 120vw); height: min(1000px, 120vw); margin-left: -50%; border-radius: 50%; border: 1px solid rgba(255,255,255,.05); animation: spinSlow 90s linear infinite\"><\/div>\n    <\/div>\n\n    <div style=\"position: relative; display: grid; grid-template-columns: {{ heroCols }}; gap: {{ heroGap }}; align-items: center; width: 100%; max-width: {{ maxW }}; margin: 0 auto; padding: {{ gutterPad }}\">\n      <div style=\"animation: riseIn .9s cubic-bezier(.22,1,.36,1) both\">\n        <div style=\"display: inline-flex; align-items: center; gap: 9px; padding: 7px 14px 7px 10px; border-radius: 999px; border: 1px solid rgba(255,255,255,.1); background: rgba(255,255,255,.04); backdrop-filter: blur(14px); font-family: 'IBM Plex Mono', monospace; font-size: 11.5px; letter-spacing: .1em; text-transform: uppercase; color: #b6b6c0\">\n          <span style=\"width: 6px; height: 6px; border-radius: 50%; background: oklch(0.78 0.13 255); box-shadow: 0 0 12px oklch(0.78 0.13 255); animation: pulseDot 2.4s ease-in-out infinite\"><\/span>\n          Creative production studio\n        <\/div>\n        <h1 style=\"margin: 24px 0 0; font-size: {{ h1Size }}; line-height: 0.98; letter-spacing: -0.045em; font-weight: 700; text-wrap: balance\">\n          Your Products.<br \/>\n          <span style=\"background: linear-gradient(96deg, #ffffff 8%, oklch(0.84 0.09 262) 46%, oklch(0.68 0.15 312) 96%); -webkit-background-clip: text; background-clip: text; color: transparent\">Styled to Sell.<\/span>\n        <\/h1>\n        <p style=\"margin: 26px 0 0; max-width: 560px; font-size: {{ pSize }}; line-height: 1.6; color: #9b9ba5; text-wrap: pretty\">\n          We are a creative production team that transforms your product photos into premium lifestyle images using AI-assisted workflows.\n        <\/p>\n        <p style=\"margin: 16px 0 0; max-width: 560px; font-size: {{ pSmall }}; line-height: 1.65; color: #6f6f7a; text-wrap: pretty\">\n          From fashion and footwear to accessories and ecommerce products, we create realistic visuals ready for your website, Shopify store, Instagram, Facebook, TikTok and advertising campaigns.\n        <\/p>\n        <div style=\"display: flex; flex-wrap: wrap; gap: 12px; margin-top: 34px\">\n          <a href=\"#cta\" onClick=\"{{ openModal }}\" style=\"display: inline-flex; align-items: center; justify-content: center; gap: 10px; min-height: {{ btnH }}; padding: 0 26px; border-radius: 999px; font-size: 15.5px; font-weight: 650; color: #08080a; background: linear-gradient(180deg, #ffffff, #d6d6df); box-shadow: 0 14px 40px rgba(255,255,255,.16); transition: transform .3s cubic-bezier(.22,1,.36,1), box-shadow .3s ease\" style-hover=\"transform:translateY(-2px);box-shadow:0 20px 52px rgba(255,255,255,.26)\">\n            Start Your Project\n            <span style=\"font-family: 'IBM Plex Mono', monospace; font-size: 15px\">\u2192<\/span>\n          <\/a>\n          <a href=\"#work\" style=\"display: inline-flex; align-items: center; justify-content: center; min-height: {{ btnH }}; padding: 0 24px; border-radius: 999px; font-size: 15.5px; font-weight: 600; color: #e8e8ee; border: 1px solid rgba(255,255,255,.14); background: rgba(255,255,255,.045); backdrop-filter: blur(14px); transition: background .3s ease, border-color .3s ease, transform .3s cubic-bezier(.22,1,.36,1)\" style-hover=\"background:rgba(255,255,255,.09);border-color:rgba(255,255,255,.26);transform:translateY(-2px)\">See Our Work<\/a>\n        <\/div>\n        <sc-if value=\"{{ showStats }}\" hint-placeholder-val=\"{{ true }}\">\n          <div style=\"display: grid; grid-template-columns: {{ statCols }}; gap: {{ statGap }}; margin-top: 46px; padding-top: 30px; border-top: 1px solid rgba(255,255,255,.08)\">\n            <sc-for list=\"{{ stats }}\" as=\"s\" hint-placeholder-count=\"3\">\n              <div>\n                <div style=\"font-size: {{ statSize }}; font-weight: 700; letter-spacing: -0.03em\">{{ s.v }}<\/div>\n                <div style=\"margin-top: 6px; font-family: 'IBM Plex Mono', monospace; font-size: 11.5px; letter-spacing: .08em; text-transform: uppercase; color: #6f6f7a\">{{ s.k }}<\/div>\n              <\/div>\n            <\/sc-for>\n          <\/div>\n        <\/sc-if>\n      <\/div>\n\n      <div style=\"position: relative; animation: riseIn 1.1s cubic-bezier(.22,1,.36,1) .12s both\">\n        <div style=\"position: relative; border-radius: 30px; padding: 12px; border: 1px solid rgba(255,255,255,.1); background: linear-gradient(160deg, rgba(255,255,255,.08), rgba(255,255,255,.02)); backdrop-filter: blur(18px); box-shadow: 0 40px 120px -30px oklch(0.4 0.14 275 \/ 0.65); transform: perspective(1400px) rotateY({{ tiltY }}deg) rotateX({{ tiltX }}deg); transition: transform .5s cubic-bezier(.22,1,.36,1)\">\n          <div style=\"position: relative; overflow: hidden; border-radius: 20px; aspect-ratio: 4 \/ 5; background-color: #0b0b0e\">\n            <img decoding=\"async\" src=\"https:\/\/okalura.com\/wp-content\/uploads\/2026\/07\/bag-after.avif\" alt=\"Styled on-model campaign frame\" style=\"position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 50% 22%; display: block\" \/>\n            <div style=\"position: absolute; inset: 0; background: linear-gradient(180deg, transparent 52%, rgba(5,5,7,.55))\"><\/div>\n            <div style=\"position: absolute; top: 0; bottom: 0; left: 0; width: 34%; background: linear-gradient(100deg, transparent, rgba(255,255,255,.08), transparent); animation: shimmer 4.6s ease-in-out infinite\"><\/div>\n          <\/div>\n          <div style=\"display: flex; align-items: center; justify-content: space-between; padding: 14px 8px 4px\">\n            <span style=\"font-family: 'IBM Plex Mono', monospace; font-size: 11px; letter-spacing: .1em; text-transform: uppercase; color: #8a8a95\">SS26 \u00b7 campaign set<\/span>\n            <span style=\"font-family: 'IBM Plex Mono', monospace; font-size: 11px; color: oklch(0.78 0.13 255)\">rendered<\/span>\n          <\/div>\n        <\/div>\n\n        <sc-if value=\"{{ isDesktop }}\" hint-placeholder-val=\"{{ true }}\">\n          <div style=\"position: absolute; left: -58px; bottom: 96px; width: 216px; padding: 16px; border-radius: 20px; border: 1px solid rgba(255,255,255,.12); background: rgba(12,12,16,.72); backdrop-filter: blur(22px); box-shadow: 0 24px 60px -20px rgba(0,0,0,.9); animation: floatA 11s ease-in-out infinite\">\n            <div style=\"border-radius: 14px; overflow: hidden; border: 1px solid rgba(255,255,255,.14)\">\n              <img decoding=\"async\" src=\"https:\/\/okalura.com\/wp-content\/uploads\/2026\/07\/set-1-before.avif\" alt=\"Product flat-lay reference\" loading=\"lazy\" style=\"width: 100%; aspect-ratio: 1 \/ 1; object-fit: cover; display: block\" \/>\n            <\/div>\n            <div style=\"display: flex; align-items: center; gap: 10px; margin-top: 12px\">\n              <div>\n                <div style=\"font-size: 13px; font-weight: 650\">Concept 04<\/div>\n                <div style=\"font-family: 'IBM Plex Mono', monospace; font-size: 10.5px; color: #7c7c88\">flat-lay input \u00b7 approved 2h<\/div>\n              <\/div>\n            <\/div>\n            <div style=\"margin-top: 12px; height: 4px; border-radius: 999px; background: rgba(255,255,255,.1); overflow: hidden\">\n              <div style=\"width: 78%; height: 100%; border-radius: 999px; background: linear-gradient(90deg, oklch(0.78 0.13 255), oklch(0.62 0.16 312))\"><\/div>\n            <\/div>\n          <\/div>\n          <div style=\"position: absolute; right: -46px; top: 54px; width: 190px; padding: 16px 18px; border-radius: 20px; border: 1px solid rgba(255,255,255,.12); background: rgba(12,12,16,.72); backdrop-filter: blur(22px); box-shadow: 0 24px 60px -20px rgba(0,0,0,.9); animation: floatB 14s ease-in-out infinite\">\n            <div style=\"font-family: 'IBM Plex Mono', monospace; font-size: 10.5px; letter-spacing: .14em; text-transform: uppercase; color: #7c7c88\">delivery<\/div>\n            <div style=\"margin-top: 8px; font-size: 26px; font-weight: 700; letter-spacing: -0.03em\">48h<\/div>\n            <div style=\"font-size: 12.5px; color: #8a8a95\">average turnaround<\/div>\n          <\/div>\n        <\/sc-if>\n      <\/div>\n    <\/div>\n  <\/section>\n\n  <!-- LOGOS -->\n  <section data-screen-label=\"Trust\" style=\"padding: {{ logoPad }}\">\n    <div style=\"width: 100%; max-width: {{ maxW }}; margin: 0 auto; padding: {{ gutterPad }}\">\n      <div style=\"text-align: center; font-family: 'IBM Plex Mono', monospace; font-size: 11.5px; letter-spacing: .18em; text-transform: uppercase; color: #63636d\">Trusted by ecommerce brands<\/div>\n      <div style=\"margin-top: 30px; overflow: hidden; mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent); -webkit-mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent)\">\n        <div style=\"display: flex; gap: 18px; width: max-content; animation: marquee 34s linear infinite\">\n          <sc-for list=\"{{ logos }}\" as=\"l\" hint-placeholder-count=\"12\">\n            <div style=\"display: flex; align-items: center; justify-content: center; min-width: 168px; height: 74px; padding: 0 22px; border-radius: 18px; border: 1px solid rgba(255,255,255,.07); background: rgba(255,255,255,.028); font-size: 15px; font-weight: 600; letter-spacing: -0.01em; color: #85858f\">{{ l }}<\/div>\n          <\/sc-for>\n        <\/div>\n      <\/div>\n    <\/div>\n  <\/section>\n\n  <!-- BEFORE \/ AFTER -->\n  <section id=\"work\" data-screen-label=\"Showcase\" style=\"padding: {{ secPad }}\">\n    <div style=\"width: 100%; max-width: {{ maxW }}; margin: 0 auto; padding: {{ gutterPad }}\">\n      <div style=\"display: grid; grid-template-columns: {{ headCols }}; gap: 28px; align-items: end\">\n        <div>\n          <div style=\"font-family: 'IBM Plex Mono', monospace; font-size: 11.5px; letter-spacing: .18em; text-transform: uppercase; color: oklch(0.72 0.13 262)\">Before \/ After<\/div>\n          <h2 style=\"margin: 16px 0 0; font-size: {{ h2Size }}; line-height: 1.04; letter-spacing: -0.04em; font-weight: 700; text-wrap: balance\">The same product.<br \/>A different league.<\/h2>\n        <\/div>\n        <p style=\"margin: 0; font-size: {{ pSmall }}; line-height: 1.6; color: #85858f; max-width: 420px\">Drag the handle to compare a raw supplier photo with the finished campaign frame we deliver.<\/p>\n      <\/div>\n\n      <div style=\"margin-top: 44px; border-radius: 30px; padding: {{ cardPad }}; border: 1px solid rgba(255,255,255,.09); background: linear-gradient(170deg, rgba(255,255,255,.055), rgba(255,255,255,.015)); backdrop-filter: blur(16px); box-shadow: 0 50px 140px -60px oklch(0.4 0.14 275 \/ 0.9)\">\n        <div ref=\"{{ sliderRef }}\" onPointerDown=\"{{ onDragStart }}\" style=\"position: relative; overflow: hidden; border-radius: 22px; aspect-ratio: {{ compareRatio }}; cursor: ew-resize; touch-action: pan-y; user-select: none; background: #0a0a0d\">\n          <div style=\"position: absolute; inset: 0; background-color: #0d0d12; background-image: repeating-linear-gradient(115deg, oklch(0.45 0.11 272 \/ 0.22) 0 2px, transparent 2px 12px)\">\n            <sc-if value=\"{{ hasAfter }}\" hint-placeholder-val=\"{{ false }}\">\n              <img decoding=\"async\" src=\"{{ activeAfter }}\" alt=\"Finished campaign frame\" draggable=\"false\" style=\"position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: center; display: block; pointer-events: none\" \/>\n            <\/sc-if>\n            <sc-if value=\"{{ noAfter }}\" hint-placeholder-val=\"{{ false }}\">\n              <div style=\"position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px\">\n                <span style=\"font-family: 'IBM Plex Mono', monospace; font-size: 11px; letter-spacing: .16em; text-transform: uppercase; color: #9a9aa6\">after \u00b7 {{ activeCase }}<\/span>\n                <span style=\"font-family: 'IBM Plex Mono', monospace; font-size: 11px; color: #5a5a66\">drop finished render here<\/span>\n              <\/div>\n            <\/sc-if>\n            <div style=\"position: absolute; left: 20px; bottom: 20px; padding: 7px 13px; border-radius: 999px; font-family: 'IBM Plex Mono', monospace; font-size: 10.5px; letter-spacing: .14em; text-transform: uppercase; background: oklch(0.62 0.16 268 \/ 0.22); border: 1px solid oklch(0.72 0.13 262 \/ 0.45); backdrop-filter: blur(10px); color: #e6e6ef\">After<\/div>\n          <\/div>\n          <div style=\"position: absolute; inset: 0; clip-path: inset(0 {{ clipRight }} 0 0); background-color: #0a0a0c; background-image: repeating-linear-gradient(115deg, rgba(255,255,255,.05) 0 2px, transparent 2px 12px)\">\n            <sc-if value=\"{{ hasBefore }}\" hint-placeholder-val=\"{{ false }}\">\n              <img decoding=\"async\" src=\"{{ activeBefore }}\" alt=\"Original supplier photo\" draggable=\"false\" style=\"position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: center; display: block; pointer-events: none\" \/>\n            <\/sc-if>\n            <sc-if value=\"{{ noBefore }}\" hint-placeholder-val=\"{{ false }}\">\n              <div style=\"position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px\">\n                <span style=\"font-family: 'IBM Plex Mono', monospace; font-size: 11px; letter-spacing: .16em; text-transform: uppercase; color: #6f6f7a\">before \u00b7 raw photo<\/span>\n                <span style=\"font-family: 'IBM Plex Mono', monospace; font-size: 11px; color: #45454e\">drop original here<\/span>\n              <\/div>\n            <\/sc-if>\n            <div style=\"position: absolute; left: 20px; top: 20px; padding: 7px 13px; border-radius: 999px; font-family: 'IBM Plex Mono', monospace; font-size: 10.5px; letter-spacing: .14em; text-transform: uppercase; background: rgba(255,255,255,.1); border: 1px solid rgba(255,255,255,.16); backdrop-filter: blur(10px); color: #d6d6dd\">Before<\/div>\n          <\/div>\n          <div style=\"position: absolute; top: 0; bottom: 0; left: {{ splitPct }}; width: 2px; margin-left: -1px; background: linear-gradient(180deg, transparent, #fff 18%, #fff 82%, transparent); box-shadow: 0 0 22px rgba(255,255,255,.5)\"><\/div>\n          <div style=\"position: absolute; top: 50%; left: {{ splitPct }}; width: 48px; height: 48px; margin: -24px 0 0 -24px; border-radius: 50%; display: flex; align-items: center; justify-content: center; gap: 3px; background: rgba(255,255,255,.92); box-shadow: 0 10px 30px rgba(0,0,0,.55)\">\n            <span style=\"color: #08080a; font-size: 13px; font-weight: 700\">\u2039<\/span>\n            <span style=\"color: #08080a; font-size: 13px; font-weight: 700\">\u203a<\/span>\n          <\/div>\n        <\/div>\n\n        <div style=\"display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-top: 20px\">\n          <div style=\"display: flex; gap: 8px\">\n            <sc-for list=\"{{ cases }}\" as=\"c\" hint-placeholder-count=\"4\">\n              <button onClick=\"{{ c.select }}\" style=\"appearance: none; cursor: pointer; min-height: 40px; padding: 0 16px; border-radius: 999px; font-family: 'IBM Plex Mono', monospace; font-size: 11px; letter-spacing: .1em; text-transform: uppercase; border: 1px solid {{ c.border }}; background: {{ c.bg }}; color: {{ c.color }}; transition: all .3s ease\">{{ c.label }}<\/button>\n            <\/sc-for>\n          <\/div>\n          <div style=\"display: flex; gap: 6px\">\n            <sc-for list=\"{{ cases }}\" as=\"c\" hint-placeholder-count=\"4\">\n              <span style=\"width: 22px; height: 3px; border-radius: 999px; background: {{ c.dot }}; transition: background .3s ease\"><\/span>\n            <\/sc-for>\n          <\/div>\n        <\/div>\n      <\/div>\n    <\/div>\n  <\/section>\n\n  <!-- WHY -->\n  <section id=\"why\" data-screen-label=\"Why us\" style=\"padding: {{ secPad }}\">\n    <div style=\"width: 100%; max-width: {{ maxW }}; margin: 0 auto; padding: {{ gutterPad }}\">\n      <div style=\"max-width: 720px\">\n        <div style=\"font-family: 'IBM Plex Mono', monospace; font-size: 11.5px; letter-spacing: .18em; text-transform: uppercase; color: oklch(0.72 0.13 262)\">Why brands choose us<\/div>\n        <h2 style=\"margin: 16px 0 0; font-size: {{ h2Size }}; line-height: 1.04; letter-spacing: -0.04em; font-weight: 700; text-wrap: balance\">A studio workflow, without the studio overhead.<\/h2>\n      <\/div>\n      <div style=\"display: grid; grid-template-columns: {{ featureCols }}; gap: {{ gridGap }}; margin-top: 48px\">\n        <sc-for list=\"{{ features }}\" as=\"f\" hint-placeholder-count=\"6\">\n          <div style=\"position: relative; overflow: hidden; border-radius: 24px; padding: {{ cardPad }}; border: 1px solid rgba(255,255,255,.08); background: linear-gradient(165deg, rgba(255,255,255,.05), rgba(255,255,255,.014)); transition: transform .4s cubic-bezier(.22,1,.36,1), border-color .4s ease, box-shadow .4s ease\" style-hover=\"transform:translateY(-6px);border-color:rgba(255,255,255,.2);box-shadow:0 30px 70px -40px oklch(0.5 0.16 272 \/ 0.9)\">\n            <div style=\"display: flex; align-items: center; justify-content: center; width: 46px; height: 46px; border-radius: 15px; border: 1px solid oklch(0.72 0.13 262 \/ 0.3); background: oklch(0.62 0.16 268 \/ 0.16); box-shadow: inset 0 0 22px oklch(0.72 0.13 262 \/ 0.2)\">\n              <span style=\"font-family: 'IBM Plex Mono', monospace; font-size: 15px; color: oklch(0.84 0.1 258)\">{{ f.glyph }}<\/span>\n            <\/div>\n            <h3 style=\"margin: 20px 0 0; font-size: {{ h3Size }}; font-weight: 650; letter-spacing: -0.02em\">{{ f.title }}<\/h3>\n            <p style=\"margin: 10px 0 0; font-size: {{ pSmall }}; line-height: 1.6; color: #85858f; text-wrap: pretty\">{{ f.body }}<\/p>\n          <\/div>\n        <\/sc-for>\n      <\/div>\n    <\/div>\n  <\/section>\n\n  <!-- PROCESS -->\n  <section id=\"process\" data-screen-label=\"Process\" style=\"padding: {{ secPad }}\">\n    <div style=\"display: grid; grid-template-columns: {{ processCols }}; gap: {{ processGap }}; width: 100%; max-width: {{ maxW }}; margin: 0 auto; padding: {{ gutterPad }}\">\n      <div>\n        <div style=\"font-family: 'IBM Plex Mono', monospace; font-size: 11.5px; letter-spacing: .18em; text-transform: uppercase; color: oklch(0.72 0.13 262)\">How it works<\/div>\n        <h2 style=\"margin: 16px 0 0; font-size: {{ h2Size }}; line-height: 1.04; letter-spacing: -0.04em; font-weight: 700; text-wrap: balance\">Five steps from photo to campaign.<\/h2>\n        <p style=\"margin: 20px 0 0; max-width: 420px; font-size: {{ pSmall }}; line-height: 1.6; color: #85858f\">One creative lead owns your project end to end. You stay in review, never in production.<\/p>\n      <\/div>\n      <div style=\"position: relative; display: flex; flex-direction: column; gap: {{ stepGap }}\">\n        <div style=\"position: absolute; left: 23px; top: 12px; bottom: 12px; width: 1px; background: linear-gradient(180deg, oklch(0.72 0.13 262 \/ 0.6), rgba(255,255,255,.06))\"><\/div>\n        <sc-for list=\"{{ steps }}\" as=\"st\" hint-placeholder-count=\"5\">\n          <div style=\"position: relative; display: grid; grid-template-columns: 48px 1fr; gap: 22px; align-items: start\">\n            <div style=\"display: flex; align-items: center; justify-content: center; width: 48px; height: 48px; border-radius: 16px; border: 1px solid rgba(255,255,255,.12); background: rgba(10,10,13,.92); backdrop-filter: blur(10px); font-family: 'IBM Plex Mono', monospace; font-size: 13px; color: oklch(0.84 0.1 258)\">{{ st.n }}<\/div>\n            <div style=\"padding-top: 4px\">\n              <h3 style=\"margin: 0; font-size: {{ h3Size }}; font-weight: 650; letter-spacing: -0.02em\">{{ st.title }}<\/h3>\n              <p style=\"margin: 8px 0 0; font-size: {{ pSmall }}; line-height: 1.6; color: #85858f; max-width: 460px; text-wrap: pretty\">{{ st.body }}<\/p>\n            <\/div>\n          <\/div>\n        <\/sc-for>\n      <\/div>\n    <\/div>\n  <\/section>\n\n  <!-- PRICING -->\n  <section id=\"pricing\" data-screen-label=\"Pricing\" style=\"padding: {{ secPad }}\">\n    <div style=\"width: 100%; max-width: {{ maxW }}; margin: 0 auto; padding: {{ gutterPad }}\">\n      <div style=\"text-align: center; max-width: 660px; margin: 0 auto\">\n        <div style=\"font-family: 'IBM Plex Mono', monospace; font-size: 11.5px; letter-spacing: .18em; text-transform: uppercase; color: oklch(0.72 0.13 262)\">Pricing<\/div>\n        <h2 style=\"margin: 16px 0 0; font-size: {{ h2Size }}; line-height: 1.04; letter-spacing: -0.04em; font-weight: 700; text-wrap: balance\">Flat packages. No day rates.<\/h2>\n        <p style=\"margin: 18px 0 0; font-size: {{ pSmall }}; line-height: 1.6; color: #85858f\">Every package includes unlimited refinements and full commercial usage rights.<\/p>\n      <\/div>\n      <div style=\"display: {{ priceDisplay }}; grid-template-columns: {{ priceCols }}; gap: {{ gridGap }}; align-items: {{ priceAlign }}; margin-top: 52px; overflow-x: {{ priceOverflow }}; scroll-snap-type: x mandatory; padding-bottom: 6px\">\n        <sc-for list=\"{{ plans }}\" as=\"p\" hint-placeholder-count=\"4\">\n          <div style=\"position: relative; flex: {{ p.flex }}; min-width: {{ p.minW }}; scroll-snap-align: center; border-radius: 26px; padding: {{ p.pad }}; border: 1px solid {{ p.border }}; background: {{ p.bg }}; box-shadow: {{ p.shadow }}; transform: {{ p.scale }}; transition: transform .4s cubic-bezier(.22,1,.36,1), border-color .4s ease\" style-hover=\"border-color:rgba(255,255,255,.28)\">\n            <sc-if value=\"{{ p.featured }}\" hint-placeholder-val=\"{{ false }}\">\n              <div style=\"position: absolute; top: 18px; right: 18px; padding: 6px 12px; border-radius: 999px; font-family: 'IBM Plex Mono', monospace; font-size: 10px; letter-spacing: .14em; text-transform: uppercase; background: linear-gradient(120deg, oklch(0.78 0.13 255), oklch(0.6 0.17 305)); color: #06060a; font-weight: 600\">Most chosen<\/div>\n            <\/sc-if>\n            <div style=\"font-size: 15px; font-weight: 650; letter-spacing: -0.01em\">{{ p.name }}<\/div>\n            <div style=\"margin-top: 6px; font-family: 'IBM Plex Mono', monospace; font-size: 11.5px; letter-spacing: .1em; text-transform: uppercase; color: #6f6f7a\">{{ p.volume }}<\/div>\n            <div style=\"margin-top: 26px; display: flex; align-items: baseline; gap: 6px\">\n              <span style=\"font-size: {{ p.priceSize }}; font-weight: 700; letter-spacing: -0.04em\">{{ p.price }}<\/span>\n              <sc-if value=\"{{ p.per }}\" hint-placeholder-val=\"{{ true }}\">\n                <span style=\"font-size: 13px; color: #6f6f7a\">{{ p.per }}<\/span>\n              <\/sc-if>\n            <\/div>\n            <div style=\"height: 1px; margin: 26px 0; background: rgba(255,255,255,.08)\"><\/div>\n            <div style=\"display: flex; flex-direction: column; gap: 12px\">\n              <sc-for list=\"{{ p.items }}\" as=\"it\" hint-placeholder-count=\"4\">\n                <div style=\"display: grid; grid-template-columns: 16px 1fr; gap: 10px; align-items: start\">\n                  <span style=\"margin-top: 6px; width: 6px; height: 6px; border-radius: 50%; background: oklch(0.78 0.13 255)\"><\/span>\n                  <span style=\"font-size: 14px; line-height: 1.5; color: #9b9ba5\">{{ it }}<\/span>\n                <\/div>\n              <\/sc-for>\n            <\/div>\n            <a href=\"#cta\" onClick=\"{{ openModal }}\" style=\"display: flex; align-items: center; justify-content: center; min-height: {{ btnH }}; margin-top: 30px; border-radius: 999px; font-size: 15px; font-weight: 650; color: {{ p.ctaColor }}; background: {{ p.ctaBg }}; border: 1px solid {{ p.ctaBorder }}; transition: transform .3s cubic-bezier(.22,1,.36,1), opacity .3s ease\" style-hover=\"transform:translateY(-2px);opacity:.92\">{{ p.cta }}<\/a>\n          <\/div>\n        <\/sc-for>\n      <\/div>\n    <\/div>\n  <\/section>\n\n  <!-- PLATFORMS -->\n  <section data-screen-label=\"Platforms\" style=\"padding: {{ secPad }}\">\n    <div style=\"width: 100%; max-width: {{ maxW }}; margin: 0 auto; padding: {{ gutterPad }}\">\n      <div style=\"text-align: center\">\n        <div style=\"font-family: 'IBM Plex Mono', monospace; font-size: 11.5px; letter-spacing: .18em; text-transform: uppercase; color: oklch(0.72 0.13 262)\">Delivery<\/div>\n        <h2 style=\"margin: 16px 0 0; font-size: {{ h2Size }}; line-height: 1.04; letter-spacing: -0.04em; font-weight: 700\">Use your images anywhere.<\/h2>\n      <\/div>\n      <div style=\"display: grid; grid-template-columns: {{ platformCols }}; gap: {{ platformGap }}; margin-top: 44px\">\n        <sc-for list=\"{{ platforms }}\" as=\"pl\" hint-placeholder-count=\"12\">\n          <div style=\"display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px; aspect-ratio: 1 \/ 0.86; border-radius: 20px; border: 1px solid rgba(255,255,255,.07); background: rgba(255,255,255,.026); transition: transform .35s cubic-bezier(.22,1,.36,1), background .35s ease, border-color .35s ease\" style-hover=\"transform:translateY(-4px);background:rgba(255,255,255,.06);border-color:rgba(255,255,255,.18)\">\n            <span style=\"display: flex; align-items: center; justify-content: center; width: 38px; height: 38px; border-radius: 12px; border: 1px solid rgba(255,255,255,.1); background: rgba(255,255,255,.04); font-family: 'IBM Plex Mono', monospace; font-size: 13px; color: oklch(0.84 0.1 258)\">{{ pl.g }}<\/span>\n            <span style=\"font-size: 13.5px; font-weight: 550; color: #9b9ba5; text-align: center\">{{ pl.n }}<\/span>\n          <\/div>\n        <\/sc-for>\n      <\/div>\n    <\/div>\n  <\/section>\n\n  <!-- TESTIMONIALS -->\n  <section data-screen-label=\"Testimonials\" style=\"padding: {{ secPad }}\">\n    <div style=\"width: 100%; max-width: {{ maxW }}; margin: 0 auto; padding: {{ gutterPad }}\">\n      <div style=\"max-width: 640px\">\n        <div style=\"font-family: 'IBM Plex Mono', monospace; font-size: 11.5px; letter-spacing: .18em; text-transform: uppercase; color: oklch(0.72 0.13 262)\">Clients<\/div>\n        <h2 style=\"margin: 16px 0 0; font-size: {{ h2Size }}; line-height: 1.04; letter-spacing: -0.04em; font-weight: 700\">Results, in their words.<\/h2>\n      <\/div>\n      <div style=\"display: {{ testDisplay }}; grid-template-columns: {{ testCols }}; gap: {{ gridGap }}; margin-top: 44px; overflow-x: {{ testOverflow }}; scroll-snap-type: x mandatory; align-items: start; padding-bottom: 6px\">\n        <sc-for list=\"{{ testimonials }}\" as=\"t\" hint-placeholder-count=\"4\">\n          <div style=\"min-width: {{ testMinW }}; scroll-snap-align: center; border-radius: 24px; padding: {{ cardPad }}; margin-top: {{ t.offset }}; border: 1px solid rgba(255,255,255,.08); background: linear-gradient(165deg, rgba(255,255,255,.055), rgba(255,255,255,.014)); transition: transform .4s cubic-bezier(.22,1,.36,1), border-color .4s ease\" style-hover=\"transform:translateY(-5px);border-color:rgba(255,255,255,.2)\">\n            <div style=\"font-size: 13px; letter-spacing: .22em; color: oklch(0.84 0.1 258)\">\u2605\u2605\u2605\u2605\u2605<\/div>\n            <p style=\"margin: 18px 0 0; font-size: {{ quoteSize }}; line-height: 1.45; letter-spacing: -0.02em; font-weight: 550; text-wrap: pretty\">\u201c{{ t.quote }}\u201d<\/p>\n            <div style=\"display: flex; align-items: center; gap: 12px; margin-top: 24px\">\n              <span style=\"width: 34px; height: 34px; border-radius: 50%; background: linear-gradient(140deg, rgba(255,255,255,.16), rgba(255,255,255,.04)); border: 1px solid rgba(255,255,255,.1)\"><\/span>\n              <div>\n                <div style=\"font-size: 14px; font-weight: 600\">{{ t.name }}<\/div>\n                <div style=\"font-family: 'IBM Plex Mono', monospace; font-size: 11px; color: #6f6f7a\">{{ t.role }}<\/div>\n              <\/div>\n            <\/div>\n          <\/div>\n        <\/sc-for>\n      <\/div>\n    <\/div>\n  <\/section>\n\n  <!-- FAQ -->\n  <section id=\"faq\" data-screen-label=\"FAQ\" style=\"padding: {{ secPad }}\">\n    <div style=\"display: grid; grid-template-columns: {{ faqCols }}; gap: {{ processGap }}; align-items: start; width: 100%; max-width: {{ maxW }}; margin: 0 auto; padding: {{ gutterPad }}\">\n      <div>\n        <div style=\"font-family: 'IBM Plex Mono', monospace; font-size: 11.5px; letter-spacing: .18em; text-transform: uppercase; color: oklch(0.72 0.13 262)\">FAQ<\/div>\n        <h2 style=\"margin: 16px 0 32px; font-size: {{ h2Size }}; line-height: 1.04; letter-spacing: -0.04em; font-weight: 700\">Frequently asked questions.<\/h2>\n        <div style=\"display: flex; flex-direction: column; gap: 12px\">\n          <sc-for list=\"{{ faqs }}\" as=\"q\" hint-placeholder-count=\"5\">\n            <div style=\"border-radius: 20px; border: 1px solid {{ q.border }}; background: {{ q.bg }}; overflow: hidden; transition: border-color .35s ease, background .35s ease\">\n              <button onClick=\"{{ q.toggle }}\" style=\"appearance: none; cursor: pointer; display: flex; align-items: center; justify-content: space-between; gap: 18px; width: 100%; min-height: 62px; padding: 18px {{ faqPadX }}; border: 0; background: transparent; color: #f4f4f5; text-align: left; font-family: inherit; font-size: {{ faqQSize }}; font-weight: 600; letter-spacing: -0.015em\">\n                {{ q.q }}\n                <span style=\"flex: 0 0 auto; display: flex; align-items: center; justify-content: center; width: 26px; height: 26px; border-radius: 50%; border: 1px solid rgba(255,255,255,.14); font-size: 14px; color: #b6b6c0; transform: rotate({{ q.rot }}deg); transition: transform .35s cubic-bezier(.22,1,.36,1)\">+<\/span>\n              <\/button>\n              <div style=\"display: grid; grid-template-rows: {{ q.rows }}; transition: grid-template-rows .4s cubic-bezier(.22,1,.36,1)\">\n                <div style=\"overflow: hidden\">\n                  <p style=\"margin: 0; padding: 0 {{ faqPadX }} 22px; font-size: {{ pSmall }}; line-height: 1.65; color: #8f8f99; text-wrap: pretty\">{{ q.a }}<\/p>\n                <\/div>\n              <\/div>\n            <\/div>\n          <\/sc-for>\n        <\/div>\n      <\/div>\n      <sc-if value=\"{{ isDesktop }}\" hint-placeholder-val=\"{{ true }}\">\n        <div style=\"position: sticky; top: 120px; border-radius: 26px; padding: 32px; border: 1px solid rgba(255,255,255,.1); background: linear-gradient(170deg, oklch(0.35 0.1 272 \/ 0.4), rgba(255,255,255,.02)); backdrop-filter: blur(16px)\">\n          <div style=\"display: flex; align-items: center; justify-content: center; width: 48px; height: 48px; border-radius: 16px; border: 1px solid oklch(0.72 0.13 262 \/ 0.35); background: oklch(0.62 0.16 268 \/ 0.18); font-family: 'IBM Plex Mono', monospace; color: oklch(0.86 0.09 258)\">?<\/div>\n          <h3 style=\"margin: 22px 0 0; font-size: 22px; font-weight: 650; letter-spacing: -0.02em\">Still deciding?<\/h3>\n          <p style=\"margin: 12px 0 0; font-size: 15px; line-height: 1.6; color: #9b9ba5\">Send us one product photo. We'll return a free sample frame within 24 hours so you can judge the quality before committing.<\/p>\n          <a href=\"#cta\" onClick=\"{{ openModal }}\" style=\"display: flex; align-items: center; justify-content: center; min-height: 50px; margin-top: 26px; border-radius: 999px; font-size: 15px; font-weight: 650; color: #08080a; background: linear-gradient(180deg, #ffffff, #d8d8e0); transition: transform .3s cubic-bezier(.22,1,.36,1)\" style-hover=\"transform:translateY(-2px)\">Request a free sample<\/a>\n          <div style=\"display: flex; align-items: center; gap: 8px; margin-top: 18px; font-family: 'IBM Plex Mono', monospace; font-size: 11px; letter-spacing: .1em; text-transform: uppercase; color: #63636d\">\n            <span style=\"width: 6px; height: 6px; border-radius: 50%; background: oklch(0.78 0.13 255); animation: pulseDot 2.4s ease-in-out infinite\"><\/span>\n            Replies in under 2 hours\n          <\/div>\n        <\/div>\n      <\/sc-if>\n    <\/div>\n  <\/section>\n\n  <!-- FINAL CTA -->\n  <section id=\"cta\" data-screen-label=\"Final CTA\" style=\"padding: {{ secPad }}\">\n    <div style=\"width: 100%; max-width: {{ maxW }}; margin: 0 auto; padding: {{ gutterPad }}\">\n      <div style=\"position: relative; overflow: hidden; border-radius: 34px; padding: {{ ctaPad }}; text-align: center; border: 1px solid rgba(255,255,255,.1); background: radial-gradient(120% 140% at 50% 0%, oklch(0.42 0.14 272 \/ 0.55), rgba(255,255,255,.02) 62%)\">\n        <div style=\"position: absolute; top: -40%; left: 50%; width: 70%; height: 120%; margin-left: -35%; border-radius: 50%; filter: blur(90px); background: oklch(0.55 0.17 285 \/ 0.35); pointer-events: none; animation: floatA 18s ease-in-out infinite\"><\/div>\n        <div style=\"position: relative\">\n          <h2 style=\"margin: 0 auto; max-width: 780px; font-size: {{ h1Small }}; line-height: 1.05; letter-spacing: -0.04em; font-weight: 700; text-wrap: balance\">Ready to Create Images That Actually Sell?<\/h2>\n          <p style=\"margin: 22px auto 0; max-width: 520px; font-size: {{ pSize }}; line-height: 1.6; color: #a5a5af\">Let's transform your products into premium marketing assets.<\/p>\n          <div style=\"display: flex; flex-wrap: wrap; justify-content: center; gap: 12px; margin-top: 36px\">\n            <a href=\"#top\" onClick=\"{{ openModal }}\" style=\"display: inline-flex; align-items: center; justify-content: center; gap: 10px; min-height: {{ btnH }}; padding: 0 28px; border-radius: 999px; font-size: 15.5px; font-weight: 650; color: #08080a; background: linear-gradient(180deg, #ffffff, #d6d6df); box-shadow: 0 14px 44px rgba(255,255,255,.18); transition: transform .3s cubic-bezier(.22,1,.36,1)\" style-hover=\"transform:translateY(-2px)\">Start Your Project <span style=\"font-family: 'IBM Plex Mono', monospace\">\u2192<\/span><\/a>\n            <a href=\"#top\" style=\"display: inline-flex; align-items: center; justify-content: center; gap: 10px; min-height: {{ btnH }}; padding: 0 26px; border-radius: 999px; font-size: 15.5px; font-weight: 600; color: #eaf6ee; border: 1px solid oklch(0.72 0.14 155 \/ 0.4); background: oklch(0.55 0.14 155 \/ 0.16); backdrop-filter: blur(12px); transition: background .3s ease, transform .3s cubic-bezier(.22,1,.36,1)\" style-hover=\"background:oklch(0.55 0.14 155 \/ 0.26);transform:translateY(-2px)\">\n              <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\"><path d=\"M4 20l1.3-4A8 8 0 1 1 8 18.7L4 20z\" stroke=\"oklch(0.82 0.16 155)\" stroke-width=\"1.6\" stroke-linejoin=\"round\"><\/path><circle cx=\"9.5\" cy=\"12\" r=\"1\" fill=\"oklch(0.82 0.16 155)\"><\/circle><circle cx=\"12.5\" cy=\"12\" r=\"1\" fill=\"oklch(0.82 0.16 155)\"><\/circle><circle cx=\"15.5\" cy=\"12\" r=\"1\" fill=\"oklch(0.82 0.16 155)\"><\/circle><\/svg>\n              Chat on WhatsApp\n            <\/a>\n          <\/div>\n        <\/div>\n      <\/div>\n    <\/div>\n  <\/section>\n\n  <!-- FOOTER -->\n  <footer data-screen-label=\"Footer\" style=\"padding: {{ footPad }}; border-top: 1px solid rgba(255,255,255,.07); margin-top: {{ footMargin }}\">\n    <div style=\"width: 100%; max-width: {{ maxW }}; margin: 0 auto; padding: {{ gutterPad }}\">\n      <div style=\"display: grid; grid-template-columns: {{ footCols }}; gap: {{ footGap }}\">\n        <div>\n          <div style=\"display: flex; align-items: center; gap: 10px\">\n            <img decoding=\"async\" src=\"https:\/\/okalura.com\/wp-content\/uploads\/2026\/07\/Okalura-Logo-White.png\" alt=\"okalura\" loading=\"lazy\" style=\"width: 40px; height: 40px; object-fit: contain; display: block; opacity: .95\" \/>\n            <span style=\"font-size: 16px; font-weight: 700; letter-spacing: -0.02em\">okalura<\/span>\n          <\/div>\n          <p style=\"margin: 16px 0 0; max-width: 260px; font-size: 14px; line-height: 1.6; color: #6f6f7a\">AI-assisted creative production for fashion, footwear and ecommerce brands.<\/p>\n        <\/div>\n        <sc-for list=\"{{ footerCols }}\" as=\"col\" hint-placeholder-count=\"4\">\n          <div>\n            <div style=\"font-family: 'IBM Plex Mono', monospace; font-size: 11px; letter-spacing: .16em; text-transform: uppercase; color: #55555f\">{{ col.title }}<\/div>\n            <div style=\"display: flex; flex-direction: column; gap: 12px; margin-top: 18px\">\n              <sc-for list=\"{{ col.links }}\" as=\"link\" hint-placeholder-count=\"4\">\n                <a href=\"#top\" style=\"font-size: 14.5px; color: #9b9ba5; transition: color .25s ease\" style-hover=\"color:#fff\">{{ link }}<\/a>\n              <\/sc-for>\n            <\/div>\n          <\/div>\n        <\/sc-for>\n      <\/div>\n      <div style=\"display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 18px; margin-top: 56px; padding-top: 26px; border-top: 1px solid rgba(255,255,255,.06)\">\n        <span style=\"font-family: 'IBM Plex Mono', monospace; font-size: 11.5px; color: #55555f\">\u00a9 2026 okalura. All rights reserved.<\/span>\n        <div style=\"display: flex; gap: 10px\">\n          <sc-for list=\"{{ socials }}\" as=\"s\" hint-placeholder-count=\"4\">\n            <a href=\"#top\" style=\"display: flex; align-items: center; justify-content: center; width: 40px; height: 40px; border-radius: 12px; border: 1px solid rgba(255,255,255,.08); background: rgba(255,255,255,.028); font-family: 'IBM Plex Mono', monospace; font-size: 11.5px; color: #85858f; transition: all .3s ease\" style-hover=\"color:#fff;border-color:rgba(255,255,255,.24);transform:translateY(-2px)\">{{ s }}<\/a>\n          <\/sc-for>\n        <\/div>\n      <\/div>\n    <\/div>\n  <\/footer>\n\n  <sc-if value=\"{{ showSticky }}\" hint-placeholder-val=\"{{ false }}\">\n    <div style=\"position: fixed; left: 14px; right: 14px; bottom: 14px; z-index: 50; display: flex; align-items: center; gap: 10px; padding: 10px 10px 10px 18px; border-radius: 999px; border: 1px solid rgba(255,255,255,.12); background: rgba(10,10,13,.82); backdrop-filter: blur(22px); box-shadow: 0 20px 50px -12px rgba(0,0,0,.9); transform: translateY({{ stickyY }}); opacity: {{ stickyO }}; transition: transform .45s cubic-bezier(.22,1,.36,1), opacity .35s ease\">\n      <div style=\"flex: 1; min-width: 0\">\n        <div style=\"font-size: 14px; font-weight: 650; letter-spacing: -0.01em\">Free sample frame<\/div>\n        <div style=\"font-family: 'IBM Plex Mono', monospace; font-size: 10.5px; letter-spacing: .08em; text-transform: uppercase; color: #6f6f7a\">24h \u00b7 no commitment<\/div>\n      <\/div>\n      <a href=\"#cta\" onClick=\"{{ openModal }}\" style=\"display: inline-flex; align-items: center; justify-content: center; min-height: 48px; padding: 0 22px; border-radius: 999px; font-size: 14.5px; font-weight: 650; color: #08080a; background: linear-gradient(180deg, #ffffff, #d6d6df); white-space: nowrap\">Start Your Project<\/a>\n    <\/div>\n  <\/sc-if>\n\n  <!-- LEAD CAPTURE MODAL -->\n  <div onClick=\"{{ closeModal }}\" role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"lead-title\" style=\"position: fixed; inset: 0; z-index: 90; display: flex; align-items: {{ overlayAlign }}; justify-content: center; padding: {{ overlayPad }}; background: rgba(4,4,6,.62); backdrop-filter: {{ overlayBlur }}; -webkit-backdrop-filter: {{ overlayBlur }}; opacity: {{ overlayOpacity }}; visibility: {{ overlayVis }}; transition: opacity .35s cubic-bezier(.22,1,.36,1), visibility .35s linear, backdrop-filter .35s ease\">\n    <div ref=\"{{ panelRef }}\" onClick=\"{{ stopClick }}\" style=\"position: relative; width: {{ panelW }}; max-width: 650px; max-height: {{ panelMaxH }}; overflow-y: auto; overflow-x: hidden; border-radius: {{ panelRadius }}; border: 1px solid rgba(255,255,255,.12); background: linear-gradient(172deg, rgba(19,19,25,.96), rgba(9,9,12,.98)); box-shadow: 0 60px 140px -40px rgba(0,0,0,.95), inset 0 1px 0 rgba(255,255,255,.07); transform: {{ panelTransform }}; opacity: {{ overlayOpacity }}; transition: transform .35s cubic-bezier(.22,1,.36,1), opacity .35s ease\">\n      <div style=\"position: absolute; top: -120px; left: 50%; width: 460px; height: 300px; margin-left: -230px; border-radius: 50%; filter: blur(80px); background: oklch(0.55 0.17 275 \/ 0.42); pointer-events: none\"><\/div>\n\n      <div style=\"position: relative; padding: {{ panelPad }}\">\n        <sc-if value=\"{{ isMobile }}\" hint-placeholder-val=\"{{ false }}\">\n          <div style=\"display: flex; justify-content: center; margin: -8px 0 16px\"><span style=\"width: 42px; height: 4px; border-radius: 999px; background: rgba(255,255,255,.16)\"><\/span><\/div>\n        <\/sc-if>\n\n        <div style=\"display: flex; align-items: flex-start; justify-content: space-between; gap: 16px\">\n          <div>\n            <div style=\"display: inline-flex; align-items: center; gap: 8px; padding: 6px 12px; border-radius: 999px; border: 1px solid rgba(255,255,255,.1); background: rgba(255,255,255,.04); font-family: 'IBM Plex Mono', monospace; font-size: 10.5px; letter-spacing: .14em; text-transform: uppercase; color: #b6b6c0\">\n              <span style=\"width: 5px; height: 5px; border-radius: 50%; background: oklch(0.78 0.13 255); animation: pulseDot 2.4s ease-in-out infinite\"><\/span>\n              Project request\n            <\/div>\n            <h2 id=\"lead-title\" style=\"margin: 18px 0 0; font-size: {{ modalTitleSize }}; line-height: 1.08; letter-spacing: -0.035em; font-weight: 700\">Let's Start Your Project<\/h2>\n          <\/div>\n          <button onClick=\"{{ closeModal }}\" aria-label=\"Close\" style=\"appearance: none; cursor: pointer; flex: 0 0 auto; display: flex; align-items: center; justify-content: center; width: 36px; height: 36px; border-radius: 50%; border: 1px solid rgba(255,255,255,.12); background: rgba(255,255,255,.04); color: #b6b6c0; font-size: 15px; transition: all .3s ease\" style-hover=\"background:rgba(255,255,255,.1);color:#fff\">\u2715<\/button>\n        <\/div>\n        <p style=\"margin: 14px 0 0; max-width: 480px; font-size: 15px; line-height: 1.6; color: #8f8f99; text-wrap: pretty\">Complete the short form below and our creative team will contact you within 24 hours to discuss your project.<\/p>\n\n        <form onSubmit=\"{{ submit }}\" style=\"margin-top: 28px\">\n          <div style=\"display: grid; grid-template-columns: {{ fieldCols }}; gap: 16px\">\n            <sc-for list=\"{{ fields }}\" as=\"f\" hint-placeholder-count=\"4\">\n              <div style=\"animation: {{ f.shake }}\">\n                <label for=\"lead-{{ f.k }}\" style=\"display: block; font-family: 'IBM Plex Mono', monospace; font-size: 10.5px; letter-spacing: .14em; text-transform: uppercase; color: #7c7c88\">{{ f.label }} <span style=\"color: oklch(0.78 0.13 255)\">*<\/span><\/label>\n                <input id=\"lead-{{ f.k }}\" ref=\"{{ f.ref }}\" type=\"{{ f.type }}\" autoComplete=\"{{ f.auto }}\" placeholder=\"{{ f.ph }}\" value=\"{{ f.value }}\" onChange=\"{{ f.onInput }}\" aria-invalid=\"{{ f.invalid }}\" style=\"width: 100%; min-height: 52px; margin-top: 9px; padding: 0 16px; border-radius: 14px; border: 1px solid {{ f.border }}; background: rgba(255,255,255,.035); color: #f4f4f5; font-family: inherit; font-size: 15px; outline: none; transition: border-color .3s ease, box-shadow .3s ease, background .3s ease\" style-focus=\"border-color:oklch(0.78 0.13 255);box-shadow:0 0 0 4px oklch(0.62 0.16 268 \/ 0.18);background:rgba(255,255,255,.06)\" \/>\n                <sc-if value=\"{{ f.hasErr }}\" hint-placeholder-val=\"{{ false }}\">\n                  <div style=\"margin-top: 8px; font-size: 12.5px; color: oklch(0.76 0.16 25)\">{{ f.err }}<\/div>\n                <\/sc-if>\n              <\/div>\n            <\/sc-for>\n          <\/div>\n\n          <div style=\"margin-top: 32px; padding-top: 26px; border-top: 1px solid rgba(255,255,255,.08)\">\n            <div style=\"display: flex; align-items: baseline; justify-content: space-between; gap: 14px\">\n              <h3 style=\"margin: 0; font-size: 17px; font-weight: 650; letter-spacing: -0.02em\">Upload Your Product Photos<\/h3>\n              <span style=\"font-family: 'IBM Plex Mono', monospace; font-size: 10.5px; letter-spacing: .1em; text-transform: uppercase; color: #55555f\">optional<\/span>\n            <\/div>\n            <p style=\"margin: 8px 0 0; font-size: 13.5px; line-height: 1.55; color: #7c7c88\">You can upload up to 2 product images \u2014 JPG, PNG or WEBP, max 10 MB each.<\/p>\n\n            <div style=\"display: grid; grid-template-columns: {{ uploadCols }}; gap: 14px; margin-top: 18px\">\n              <sc-for list=\"{{ slots }}\" as=\"s\" hint-placeholder-count=\"2\">\n                <div onDragOver=\"{{ s.onDragOver }}\" onDragLeave=\"{{ s.onDragLeave }}\" onDrop=\"{{ s.onDrop }}\" style=\"position: relative; overflow: hidden; border-radius: 20px; border: 1.5px {{ s.dash }} {{ s.border }}; background: {{ s.bg }}; box-shadow: {{ s.glow }}; transition: border-color .3s ease, background .3s ease, box-shadow .3s ease\" style-hover=\"background:rgba(255,255,255,.06);border-color:rgba(255,255,255,.3)\">\n                  <sc-if value=\"{{ s.isEmpty }}\" hint-placeholder-val=\"{{ true }}\">\n                    <label style=\"display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; min-height: 178px; padding: 22px 18px; cursor: pointer; text-align: center\">\n                      <span style=\"display: flex; align-items: center; justify-content: center; width: 46px; height: 46px; border-radius: 15px; border: 1px solid rgba(255,255,255,.12); background: rgba(255,255,255,.05)\">\n                        <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\"><path d=\"M12 16V4m0 0L7.5 8.5M12 4l4.5 4.5\" stroke=\"oklch(0.84 0.1 258)\" stroke-width=\"1.7\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><\/path><path d=\"M4 15v3.5A1.5 1.5 0 0 0 5.5 20h13a1.5 1.5 0 0 0 1.5-1.5V15\" stroke=\"oklch(0.84 0.1 258)\" stroke-width=\"1.7\" stroke-linecap=\"round\"><\/path><\/svg>\n                      <\/span>\n                      <span style=\"font-size: 13.5px; font-weight: 600; color: #e4e4ea\">Drag &amp; drop {{ s.label }}<\/span>\n                      <span style=\"font-family: 'IBM Plex Mono', monospace; font-size: 10.5px; letter-spacing: .1em; text-transform: uppercase; color: #5d5d67\">or<\/span>\n                      <span style=\"display: inline-flex; align-items: center; min-height: 40px; padding: 0 18px; border-radius: 999px; border: 1px solid rgba(255,255,255,.14); background: rgba(255,255,255,.05); font-size: 13.5px; font-weight: 600; color: #f0f0f4\">Browse Files<\/span>\n                      <input type=\"file\" accept=\"image\/jpeg,image\/png,image\/webp\" onChange=\"{{ s.onChange }}\" style=\"position: absolute; width: 1px; height: 1px; opacity: 0\" \/>\n                      <sc-if value=\"{{ s.msg }}\" hint-placeholder-val=\"{{ false }}\">\n                        <span style=\"font-size: 12px; color: oklch(0.76 0.16 25)\">{{ s.msg }}<\/span>\n                      <\/sc-if>\n                    <\/label>\n                  <\/sc-if>\n\n                  <sc-if value=\"{{ s.isUploading }}\" hint-placeholder-val=\"{{ false }}\">\n                    <div style=\"display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px; min-height: 178px; padding: 22px\">\n                      <span style=\"width: 26px; height: 26px; border-radius: 50%; border: 2px solid rgba(255,255,255,.14); border-top-color: oklch(0.82 0.11 258); animation: spin .8s linear infinite\"><\/span>\n                      <span style=\"font-family: 'IBM Plex Mono', monospace; font-size: 11px; letter-spacing: .12em; text-transform: uppercase; color: #8f8f99\">uploading {{ s.progressLabel }}<\/span>\n                      <span style=\"width: 78%; height: 4px; border-radius: 999px; background: rgba(255,255,255,.1); overflow: hidden\">\n                        <span style=\"display: block; width: {{ s.progress }}; height: 100%; border-radius: 999px; background: linear-gradient(90deg, oklch(0.78 0.13 255), oklch(0.62 0.16 312)); transition: width .18s linear\"><\/span>\n                      <\/span>\n                    <\/div>\n                  <\/sc-if>\n\n                  <sc-if value=\"{{ s.isDone }}\" hint-placeholder-val=\"{{ false }}\">\n                    <div style=\"animation: popIn .45s cubic-bezier(.22,1,.36,1) both\">\n                      <div style=\"position: relative; height: 128px; overflow: hidden; background: #0a0a0d\">\n                        <img decoding=\"async\" src=\"{{ s.url }}\" alt=\"{{ s.name }}\" loading=\"lazy\" style=\"width: 100%; height: 100%; object-fit: cover; display: block\" \/>\n                        <button onClick=\"{{ s.remove }}\" aria-label=\"Remove image\" style=\"appearance: none; cursor: pointer; position: absolute; top: 10px; right: 10px; display: flex; align-items: center; justify-content: center; width: 30px; height: 30px; border-radius: 50%; border: 1px solid rgba(255,255,255,.16); background: rgba(8,8,11,.72); backdrop-filter: blur(10px); color: #e4e4ea; font-size: 12px; transition: all .3s ease\" style-hover=\"background:oklch(0.5 0.18 25 \/ 0.7);border-color:transparent\">\u2715<\/button>\n                      <\/div>\n                      <div style=\"display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 12px 14px\">\n                        <div style=\"min-width: 0\">\n                          <div style=\"font-size: 12.5px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis\">{{ s.name }}<\/div>\n                          <div style=\"font-family: 'IBM Plex Mono', monospace; font-size: 10.5px; color: #6f6f7a\">{{ s.dims }}<\/div>\n                        <\/div>\n                        <label style=\"cursor: pointer; flex: 0 0 auto; font-family: 'IBM Plex Mono', monospace; font-size: 10.5px; letter-spacing: .1em; text-transform: uppercase; color: oklch(0.82 0.11 258)\">\n                          replace\n                          <input type=\"file\" accept=\"image\/jpeg,image\/png,image\/webp\" onChange=\"{{ s.onChange }}\" style=\"position: absolute; width: 1px; height: 1px; opacity: 0\" \/>\n                        <\/label>\n                      <\/div>\n                    <\/div>\n                  <\/sc-if>\n                <\/div>\n              <\/sc-for>\n            <\/div>\n          <\/div>\n\n          <div style=\"position: sticky; bottom: 0; margin: 26px -2px -2px; padding: 18px 2px 2px; background: linear-gradient(180deg, rgba(11,11,15,0), rgba(11,11,15,.96) 42%)\">\n            <button type=\"submit\" disabled=\"{{ submitting }}\" style=\"appearance: none; cursor: {{ submitCursor }}; display: flex; align-items: center; justify-content: center; gap: 10px; width: 100%; min-height: 56px; border: 0; border-radius: 999px; font-family: inherit; font-size: 16px; font-weight: 650; color: #08080a; background: linear-gradient(180deg, #ffffff, #d6d6df); opacity: {{ submitOpacity }}; box-shadow: 0 14px 40px rgba(255,255,255,.14); transition: transform .3s cubic-bezier(.22,1,.36,1), box-shadow .3s ease, opacity .3s ease\" style-hover=\"transform:translateY(-2px);box-shadow:0 20px 54px rgba(255,255,255,.26)\">\n              <sc-if value=\"{{ submitting }}\" hint-placeholder-val=\"{{ false }}\">\n                <span style=\"width: 17px; height: 17px; border-radius: 50%; border: 2px solid rgba(0,0,0,.2); border-top-color: #08080a; animation: spin .7s linear infinite\"><\/span>\n              <\/sc-if>\n              {{ submitLabel }}\n            <\/button>\n            <div style=\"margin-top: 12px; text-align: center; font-family: 'IBM Plex Mono', monospace; font-size: 10.5px; letter-spacing: .1em; text-transform: uppercase; color: #55555f\">No commitment \u00b7 reply within 24h<\/div>\n          <\/div>\n        <\/form>\n      <\/div>\n    <\/div>\n  <\/div>\n\n  <!-- THANK YOU -->\n  <div role=\"status\" aria-live=\"polite\" style=\"position: fixed; inset: 0; z-index: 95; overflow-y: auto; display: flex; align-items: flex-start; justify-content: center; padding: {{ thanksPad }}; background: radial-gradient(110% 70% at 50% -6%, oklch(0.32 0.1 268 \/ 0.55), transparent 60%), #050506; opacity: {{ thanksOpacity }}; visibility: {{ thanksVis }}; transform: {{ thanksTransform }}; transition: opacity .5s cubic-bezier(.22,1,.36,1), visibility .5s linear, transform .5s cubic-bezier(.22,1,.36,1)\">\n    <sc-if value=\"{{ isThanks }}\" hint-placeholder-val=\"{{ false }}\">\n      <div style=\"width: 100%; max-width: 640px; text-align: center\">\n        <div style=\"position: relative; display: flex; align-items: center; justify-content: center; width: 132px; height: 132px; margin: 0 auto\">\n          <div style=\"position: absolute; inset: 0; border-radius: 50%; filter: blur(30px); background: oklch(0.62 0.15 155 \/ 0.35)\"><\/div>\n          <svg width=\"108\" height=\"108\" viewBox=\"0 0 96 96\" fill=\"none\" aria-hidden=\"true\" style=\"position: relative\">\n            <circle cx=\"48\" cy=\"48\" r=\"44\" stroke=\"oklch(0.72 0.14 155 \/ 0.28)\" stroke-width=\"1\"><\/circle>\n            <circle cx=\"48\" cy=\"48\" r=\"44\" stroke=\"oklch(0.78 0.16 155)\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-dasharray=\"276\" style=\"animation: drawRing 1.1s cubic-bezier(.22,1,.36,1) both; transform: rotate(-90deg); transform-origin: 48px 48px\"><\/circle>\n            <path d=\"M31 49.5 43 61l22-25\" stroke=\"#ffffff\" stroke-width=\"4.4\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-dasharray=\"62\" style=\"animation: drawCheck .55s cubic-bezier(.22,1,.36,1) .55s both\"><\/path>\n          <\/svg>\n          <span style=\"position: absolute; top: 14px; left: 8px; width: 5px; height: 5px; border-radius: 50%; background: oklch(0.82 0.16 155); --dx: -26px; --dy: -22px; animation: spark 1.4s ease-out .8s infinite\"><\/span>\n          <span style=\"position: absolute; top: 20px; right: 10px; width: 4px; height: 4px; border-radius: 50%; background: oklch(0.86 0.1 200); --dx: 28px; --dy: -18px; animation: spark 1.6s ease-out 1s infinite\"><\/span>\n          <span style=\"position: absolute; bottom: 16px; left: 22px; width: 4px; height: 4px; border-radius: 50%; background: oklch(0.84 0.12 262); --dx: -22px; --dy: 24px; animation: spark 1.8s ease-out 1.2s infinite\"><\/span>\n          <span style=\"position: absolute; bottom: 12px; right: 20px; width: 5px; height: 5px; border-radius: 50%; background: oklch(0.82 0.16 155); --dx: 24px; --dy: 22px; animation: spark 1.5s ease-out 1.35s infinite\"><\/span>\n        <\/div>\n\n        <h1 style=\"margin: 34px 0 0; font-size: {{ thanksTitle }}; line-height: 1.02; letter-spacing: -0.045em; font-weight: 700; animation: fadeUp .7s cubic-bezier(.22,1,.36,1) .25s both\">Thank You!<\/h1>\n        <p style=\"margin: 22px auto 0; max-width: 500px; font-size: {{ pSize }}; line-height: 1.6; color: #a0a0aa; text-wrap: pretty; animation: fadeUp .7s cubic-bezier(.22,1,.36,1) .35s both\">Your request has been successfully submitted. Our creative team will review your project and contact you within the next 24 hours using the email address or phone number you provided.<\/p>\n        <p style=\"margin: 16px auto 0; max-width: 470px; font-size: {{ pSmall }}; line-height: 1.6; color: #6f6f7a; text-wrap: pretty; animation: fadeUp .7s cubic-bezier(.22,1,.36,1) .45s both\">In the meantime, feel free to prepare additional product references or inspiration images if you'd like to share more details.<\/p>\n\n        <div style=\"margin: 38px auto 0; border-radius: 24px; padding: {{ cardPad }}; text-align: left; border: 1px solid rgba(255,255,255,.09); background: linear-gradient(168deg, rgba(255,255,255,.055), rgba(255,255,255,.014)); backdrop-filter: blur(14px); animation: fadeUp .7s cubic-bezier(.22,1,.36,1) .55s both\">\n          <div style=\"display: flex; align-items: center; justify-content: space-between; gap: 14px\">\n            <span style=\"font-family: 'IBM Plex Mono', monospace; font-size: 10.5px; letter-spacing: .16em; text-transform: uppercase; color: #63636d\">Submission summary<\/span>\n            <span style=\"display: inline-flex; align-items: center; gap: 7px; padding: 6px 12px; border-radius: 999px; border: 1px solid oklch(0.72 0.14 155 \/ 0.4); background: oklch(0.55 0.14 155 \/ 0.16); font-family: 'IBM Plex Mono', monospace; font-size: 10.5px; letter-spacing: .1em; text-transform: uppercase; color: #b7ecc8\">\n              <span style=\"width: 5px; height: 5px; border-radius: 50%; background: oklch(0.82 0.16 155)\"><\/span>\n              Request received\n            <\/span>\n          <\/div>\n          <div style=\"display: flex; flex-direction: column; gap: 12px; margin-top: 20px\">\n            <sc-for list=\"{{ summary }}\" as=\"row\" hint-placeholder-count=\"4\">\n              <div style=\"display: flex; align-items: center; justify-content: space-between; gap: 16px; padding-bottom: 12px; border-bottom: 1px solid rgba(255,255,255,.06)\">\n                <span style=\"font-size: 13.5px; color: #6f6f7a\">{{ row.k }}<\/span>\n                <span style=\"font-size: 14px; font-weight: 600; text-align: right; word-break: break-word\">{{ row.v }}<\/span>\n              <\/div>\n            <\/sc-for>\n          <\/div>\n        <\/div>\n\n        <div style=\"display: flex; flex-wrap: wrap; justify-content: center; gap: 12px; margin-top: 34px; animation: fadeUp .7s cubic-bezier(.22,1,.36,1) .65s both\">\n          <a href=\"#top\" onClick=\"{{ backHome }}\" style=\"display: inline-flex; align-items: center; justify-content: center; gap: 10px; min-height: 54px; padding: 0 28px; border-radius: 999px; font-size: 15.5px; font-weight: 650; color: #08080a; background: linear-gradient(180deg, #ffffff, #d6d6df); box-shadow: 0 14px 40px rgba(255,255,255,.16); transition: transform .3s cubic-bezier(.22,1,.36,1)\" style-hover=\"transform:translateY(-2px)\">Back to Homepage<\/a>\n          <a href=\"#top\" style=\"display: inline-flex; align-items: center; justify-content: center; gap: 10px; min-height: 54px; padding: 0 26px; border-radius: 999px; font-size: 15.5px; font-weight: 600; color: #eaf6ee; border: 1px solid oklch(0.72 0.14 155 \/ 0.4); background: oklch(0.55 0.14 155 \/ 0.16); transition: background .3s ease, transform .3s cubic-bezier(.22,1,.36,1)\" style-hover=\"background:oklch(0.55 0.14 155 \/ 0.26);transform:translateY(-2px)\">\n            <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\"><path d=\"M4 20l1.3-4A8 8 0 1 1 8 18.7L4 20z\" stroke=\"oklch(0.82 0.16 155)\" stroke-width=\"1.6\" stroke-linejoin=\"round\"><\/path><circle cx=\"9.5\" cy=\"12\" r=\"1\" fill=\"oklch(0.82 0.16 155)\"><\/circle><circle cx=\"12.5\" cy=\"12\" r=\"1\" fill=\"oklch(0.82 0.16 155)\"><\/circle><circle cx=\"15.5\" cy=\"12\" r=\"1\" fill=\"oklch(0.82 0.16 155)\"><\/circle><\/svg>\n            Chat on WhatsApp\n          <\/a>\n        <\/div>\n      <\/div>\n    <\/sc-if>\n  <\/div>\n<\/div>\n<\/x-dc>\n<script type=\"text\/x-dc\" data-dc-script data-props=\"{&quot;showStats&quot;:{&quot;editor&quot;:&quot;boolean&quot;,&quot;default&quot;:true,&quot;tsType&quot;:&quot;boolean&quot;,&quot;section&quot;:&quot;Content&quot;},&quot;stickyCta&quot;:{&quot;editor&quot;:&quot;boolean&quot;,&quot;default&quot;:true,&quot;tsType&quot;:&quot;boolean&quot;,&quot;section&quot;:&quot;Behavior&quot;},&quot;calmMotion&quot;:{&quot;editor&quot;:&quot;boolean&quot;,&quot;default&quot;:false,&quot;tsType&quot;:&quot;boolean&quot;,&quot;section&quot;:&quot;Behavior&quot;},&quot;forceBreakpoint&quot;:{&quot;editor&quot;:&quot;enum&quot;,&quot;options&quot;:[&quot;auto&quot;,&quot;mobile&quot;,&quot;tablet&quot;,&quot;desktop&quot;],&quot;default&quot;:&quot;auto&quot;,&quot;tsType&quot;:&quot;string&quot;,&quot;section&quot;:&quot;Behavior&quot;}}\">\nclass Component extends DCLogic {\n  state = {\n    w: typeof window !== 'undefined' ? window.innerWidth : 1440,\n    split: 46, caseIdx: 0, open: 0, mx: 0, my: 0, scrolled: false, past: false,\n    modalOpen: false, view: 'landing', submitting: false, submitCount: 0,\n    form: { first: '', last: '', phone: '', email: '' }, errors: {},\n    slots: [\n      { status: 'empty', progress: 0, name: '', dims: '', url: '', msg: '', drag: false },\n      { status: 'empty', progress: 0, name: '', dims: '', url: '', msg: '', drag: false }\n    ]\n  };\n\n  _setFirst = (el) => { this._firstInput = el; };\n  _noRef = () => {};\n\n  openModal = (e) => {\n    if (e) e.preventDefault();\n    document.body.style.overflow = 'hidden';\n    this.setState({ modalOpen: true });\n    setTimeout(() => { if (this._firstInput) this._firstInput.focus(); }, 380);\n  };\n\n  closeModal = (e) => {\n    if (e) e.preventDefault();\n    if (this.state.submitting) return;\n    document.body.style.overflow = '';\n    this.setState({ modalOpen: false });\n  };\n\n  setField(k, v) {\n    this.setState((s) => {\n      const errors = { ...s.errors };\n      delete errors[k];\n      return { form: { ...s.form, [k]: v }, errors };\n    });\n  }\n\n  setSlot(i, patch) {\n    this.setState((s) => {\n      const slots = s.slots.slice();\n      slots[i] = { ...slots[i], ...patch };\n      return { slots };\n    });\n  }\n\n  handleFiles(idx, list) {\n    const file = list && list[0];\n    this.setSlot(idx, { drag: false });\n    if (!file) return;\n    if (!['image\/jpeg', 'image\/jpg', 'image\/png', 'image\/webp'].includes(file.type)) {\n      this.setSlot(idx, { status: 'empty', msg: 'JPG, PNG or WEBP only.' });\n      return;\n    }\n    if (file.size > 10 * 1024 * 1024) {\n      this.setSlot(idx, { status: 'empty', msg: 'Maximum size is 10 MB.' });\n      return;\n    }\n    const url = URL.createObjectURL(file);\n    this._timers = this._timers || {};\n    clearInterval(this._timers[idx]);\n    this.setSlot(idx, { status: 'uploading', progress: 6, name: file.name, url, dims: '', msg: '' });\n    this._timers[idx] = setInterval(() => {\n      const s = this.state.slots[idx];\n      if (!s || s.status !== 'uploading') { clearInterval(this._timers[idx]); return; }\n      const p = s.progress + 9 + Math.random() * 20;\n      if (p >= 100) { clearInterval(this._timers[idx]); this.setSlot(idx, { progress: 100, status: 'done' }); }\n      else this.setSlot(idx, { progress: p });\n    }, 150);\n    const img = new Image();\n    img.onload = () => this.setSlot(idx, { dims: img.naturalWidth + ' \u00d7 ' + img.naturalHeight + ' px' });\n    img.src = url;\n  }\n\n  clearSlot(idx) {\n    this._timers = this._timers || {};\n    clearInterval(this._timers[idx]);\n    this.setSlot(idx, { status: 'empty', progress: 0, name: '', dims: '', url: '', msg: '', drag: false });\n  }\n\n  validate() {\n    const f = this.state.form, e = {};\n    if (!f.first.trim()) e.first = 'Please add your first name.';\n    if (!f.last.trim()) e.last = 'Please add your last name.';\n    const digits = f.phone.replace(\/[^\\d]\/g, '');\n    if (!f.phone.trim()) e.phone = 'Please add a phone number.';\n    else if (digits.length < 8 || digits.length > 16) e.phone = 'That phone number looks incomplete.';\n    if (!f.email.trim()) e.email = 'Please add your email address.';\n    else if (!\/^[^\\s@]+@[^\\s@]+\\.[a-z]{2,}$\/i.test(f.email.trim())) e.email = 'Please check the email format.';\n    return e;\n  }\n\n  submit = (e) => {\n    if (e) e.preventDefault();\n    if (this.state.submitting) return;\n    const errors = this.validate();\n    this.setState((s) => ({ errors, submitCount: s.submitCount + 1 }));\n    if (Object.keys(errors).length) return;\n    this.setState({ submitting: true });\n    setTimeout(() => {\n      this.setState({ submitting: false, modalOpen: false });\n      setTimeout(() => {\n        this.setState({ view: 'thanks' });\n        document.body.style.overflow = 'hidden';\n        window.scrollTo(0, 0);\n      }, 260);\n    }, 1600);\n  };\n\n  backHome = (e) => {\n    if (e) e.preventDefault();\n    document.body.style.overflow = '';\n    this.setState({\n      view: 'landing', errors: {}, submitCount: 0,\n      form: { first: '', last: '', phone: '', email: '' },\n      slots: [\n        { status: 'empty', progress: 0, name: '', dims: '', url: '', msg: '', drag: false },\n        { status: 'empty', progress: 0, name: '', dims: '', url: '', msg: '', drag: false }\n      ]\n    });\n  };\n\n  componentDidMount() {\n    this._onResize = () => this.setState({ w: window.innerWidth });\n    window.addEventListener('resize', this._onResize);\n    let raf = 0;\n    this._onScroll = () => {\n      if (raf) return;\n      raf = requestAnimationFrame(() => {\n        raf = 0;\n        const y = window.scrollY;\n        const s = y > 24, p = y > 620;\n        if (s !== this.state.scrolled || p !== this.state.past) this.setState({ scrolled: s, past: p });\n      });\n    };\n    window.addEventListener('scroll', this._onScroll, { passive: true });\n    let mraf = 0;\n    this._onMove = (e) => {\n      if (this.bp() !== 'desktop' || mraf) return;\n      mraf = requestAnimationFrame(() => { mraf = 0; this.setState({ mx: e.clientX, my: e.clientY }); });\n    };\n    window.addEventListener('pointermove', this._onMove);\n    this._onDrag = (e) => {\n      if (!this._dragging || !this._el) return;\n      const r = this._el.getBoundingClientRect();\n      const pct = Math.max(2, Math.min(98, ((e.clientX - r.left) \/ r.width) * 100));\n      this.setState({ split: pct });\n    };\n    this._onUp = () => { this._dragging = false; };\n    window.addEventListener('pointermove', this._onDrag);\n    window.addEventListener('pointerup', this._onUp);\n    this._onKey = (e) => {\n      if (e.key === 'Escape' && this.state.modalOpen) this.closeModal();\n      if (e.key === 'Tab' && this.state.modalOpen && this._panel) {\n        const f = this._panel.querySelectorAll('input, button, a[href], [tabindex]:not([tabindex=\"-1\"])');\n        if (!f.length) return;\n        const first = f[0], last = f[f.length - 1];\n        if (e.shiftKey && document.activeElement === first) { e.preventDefault(); last.focus(); }\n        else if (!e.shiftKey && document.activeElement === last) { e.preventDefault(); first.focus(); }\n      }\n    };\n    window.addEventListener('keydown', this._onKey);\n  }\n\n  componentWillUnmount() {\n    window.removeEventListener('resize', this._onResize);\n    window.removeEventListener('scroll', this._onScroll);\n    window.removeEventListener('pointermove', this._onMove);\n    window.removeEventListener('pointermove', this._onDrag);\n    window.removeEventListener('pointerup', this._onUp);\n    window.removeEventListener('keydown', this._onKey);\n    document.body.style.overflow = '';\n  }\n\n  bp() {\n    const f = this.props.forceBreakpoint;\n    if (f && f !== 'auto') return f;\n    const w = this.state.w;\n    return w < 768 ? 'mobile' : w < 1200 ? 'tablet' : 'desktop';\n  }\n\n  renderVals() {\n    const bp = this.bp();\n    const isMobile = bp === 'mobile', isTablet = bp === 'tablet', isDesktop = bp === 'desktop';\n    const pick = (m, t, d) => (isMobile ? m : isTablet ? t : d);\n    const showStats = this.props.showStats ?? true;\n    const calm = this.props.calmMotion ?? false;\n\n    const cases = [\n      { label: 'Accessories', before: 'https:\/\/okalura.com\/wp-content\/uploads\/2026\/07\/set-3-before.avif', after: 'https:\/\/okalura.com\/wp-content\/uploads\/2026\/07\/set-3-after.avif' },\n      { label: 'Knitwear', before: 'https:\/\/okalura.com\/wp-content\/uploads\/2026\/07\/set-1-before.avif', after: 'https:\/\/okalura.com\/wp-content\/uploads\/2026\/07\/set-1-after.avif' },\n      { label: 'Sneakers', before: '', after: 'https:\/\/okalura.com\/wp-content\/uploads\/2026\/07\/shoe-2.avif' },\n      { label: 'Jewelry', before: 'https:\/\/okalura.com\/wp-content\/uploads\/2026\/07\/jewelery-1-before.avif', after: 'https:\/\/okalura.com\/wp-content\/uploads\/2026\/07\/jewelery-1-after.avif' }\n    ];\n    const active = cases[this.state.caseIdx] || cases[0];\n    const gutter = pick('0 20px', '0 32px', '0 40px');\n\n    return {\n      isMobile, isTablet, isDesktop, showStats,\n      maxW: pick('100%', '960px', '1400px'),\n      gutterPad: gutter,\n      navPad: pick('12px 20px', '14px 32px', '18px 40px'),\n      navBg: this.state.scrolled ? 'rgba(6,6,9,.72)' : 'transparent',\n      navBorder: this.state.scrolled ? 'rgba(255,255,255,.08)' : 'transparent',\n      navBlur: this.state.scrolled ? 'blur(20px) saturate(160%)' : 'blur(0px)',\n\n      heroPad: pick('112px 0 24px', '132px 0 40px', '176px 0 60px'),\n      heroCols: isDesktop ? '1.02fr .98fr' : '1fr',\n      heroGap: pick('44px', '52px', '72px'),\n      logoPad: pick('56px 0', '80px 0', '96px 0'),\n      secPad: pick('80px 0', '120px 0', '160px 0'),\n      cardPad: pick('24px', '28px', '32px'),\n      gridGap: pick('16px', '20px', '24px'),\n      h1Size: pick('clamp(42px, 12vw, 48px)', '56px', 'clamp(64px, 5vw, 80px)'),\n      h1Small: pick('34px', '46px', '64px'),\n      h2Size: pick('30px', '40px', '48px'),\n      h3Size: pick('18px', '19px', '20px'),\n      pSize: pick('16px', '18px', '20px'),\n      pSmall: pick('15px', '16px', '17px'),\n      quoteSize: pick('18px', '19px', '21px'),\n      statSize: pick('24px', '30px', '34px'),\n      btnH: isMobile ? '54px' : '52px',\n      statCols: 'repeat(3, 1fr)',\n      statGap: pick('14px', '24px', '32px'),\n      headCols: isDesktop ? '1.4fr 1fr' : '1fr',\n      featureCols: pick('1fr', 'repeat(2, 1fr)', 'repeat(3, 1fr)'),\n      processCols: isDesktop ? '.85fr 1.15fr' : '1fr',\n      processGap: pick('40px', '48px', '96px'),\n      stepGap: pick('26px', '30px', '38px'),\n      faqCols: isDesktop ? '1.35fr .65fr' : '1fr',\n      faqPadX: pick('20px', '24px', '28px'),\n      faqQSize: pick('16px', '17px', '18px'),\n      platformCols: pick('repeat(2, 1fr)', 'repeat(4, 1fr)', 'repeat(6, 1fr)'),\n      platformGap: pick('12px', '16px', '18px'),\n      ctaPad: pick('52px 24px', '72px 40px', '104px 64px'),\n      footPad: pick('56px 0 100px', '72px 0', '88px 0'),\n      footMargin: pick('60px', '80px', '120px'),\n      footCols: pick('1fr', 'repeat(2, 1fr)', '1.4fr repeat(4, 1fr)'),\n      footGap: pick('40px', '40px', '48px'),\n      compareRatio: pick('4 \/ 5', '16 \/ 11', '16 \/ 9'),\n      compareW: isMobile ? '92vw' : isTablet ? '860px' : '1300px',\n      splitPct: this.state.split.toFixed(1) + '%',\n      tiltY: isDesktop && !calm ? ((this.state.mx \/ Math.max(1, window.innerWidth)) - 0.5) * -7 : 0,\n      tiltX: isDesktop && !calm ? ((this.state.my \/ Math.max(1, window.innerHeight)) - 0.5) * 5 : 0,\n      mx: this.state.mx, my: this.state.my,\n      showSticky: (this.props.stickyCta ?? true) && !isDesktop,\n      stickyY: this.state.past ? '0px' : '130%',\n      stickyO: this.state.past ? 1 : 0,\n      sliderRef: (el) => { this._el = el; },\n      onDragStart: (e) => {\n        this._dragging = true;\n        const r = e.currentTarget.getBoundingClientRect();\n        this.setState({ split: Math.max(2, Math.min(98, ((e.clientX - r.left) \/ r.width) * 100)) });\n      },\n\n      stats: [\n        { v: '48h', k: 'avg first concepts' },\n        { v: '2.4k+', k: 'images delivered' },\n        { v: '96%', k: 'client retention' }\n      ],\n      logos: ['MAISON R\u00caVE', 'ATELIER NORD', 'VELOUR', 'SOLE&CO', 'KIN STUDIO', 'ORIA', 'MAISON R\u00caVE', 'ATELIER NORD', 'VELOUR', 'SOLE&CO', 'KIN STUDIO', 'ORIA'],\n      activeCase: active.label,\n      activeBefore: active.before,\n      activeAfter: active.after,\n      hasBefore: !!active.before,\n      hasAfter: !!active.after,\n      noBefore: !active.before,\n      noAfter: !active.after,\n      clipRight: (100 - this.state.split).toFixed(1) + '%',\n      cases: cases.map((c, i) => ({\n        label: c.label,\n        select: () => this.setState({ caseIdx: i, split: 46 }),\n        border: i === this.state.caseIdx ? 'rgba(255,255,255,.28)' : 'rgba(255,255,255,.1)',\n        bg: i === this.state.caseIdx ? 'rgba(255,255,255,.09)' : 'transparent',\n        color: i === this.state.caseIdx ? '#f4f4f5' : '#7c7c88',\n        dot: i === this.state.caseIdx ? 'oklch(0.82 0.11 258)' : 'rgba(255,255,255,.14)'\n      })),\n      features: [\n        { glyph: '$', title: 'Lower Cost', body: 'Save thousands compared to traditional photography \u2014 no studio, crew, model or location fees.' },\n        { glyph: '\u226b', title: 'Lightning Fast', body: 'Receive your visuals within days instead of weeks. First concepts usually land in 48 hours.' },\n        { glyph: '\u221e', title: 'Unlimited Creative Freedom', body: 'Change clothing, colors, backgrounds, lighting or models without expensive reshoots.' },\n        { glyph: '\u25c7', title: 'Human Quality', body: 'Every project is reviewed by real creative professionals before it reaches you.' },\n        { glyph: '\u25a3', title: 'Marketing Ready', body: 'Delivered in the exact crops and formats your website, ads and social channels need.' },\n        { glyph: '\u2318', title: 'Scalable', body: 'Need 10 images or 1000? Our pipeline handles catalogue-scale volume without quality drift.' }\n      ],\n      steps: [\n        { n: '01', title: 'Send your product photos', body: 'A clear smartphone shot is enough. Upload a folder and we take it from there.' },\n        { n: '02', title: 'Tell us your vision', body: 'Share your preferred model, background, lighting and style \u2014 or send references and let us direct it.' },\n        { n: '03', title: 'Receive first concepts', body: 'Review the generated images in a shared board and comment directly on the frames.' },\n        { n: '04', title: 'Unlimited refinements', body: \"We'll continue improving until you're satisfied. No revision counters, no extra invoices.\" },\n        { n: '05', title: 'Download and use everywhere', body: 'Final files arrive in web, social and print resolutions with full commercial rights.' }\n      ],\n      priceDisplay: isMobile ? 'flex' : 'grid',\n      priceCols: isTablet ? 'repeat(2, 1fr)' : 'repeat(4, 1fr)',\n      priceOverflow: isMobile ? 'auto' : 'visible',\n      priceAlign: isDesktop ? 'center' : 'stretch',\n      plans: [\n        { name: 'Starter', volume: '10 Images', price: '$249', per: '', items: ['10 finished images', 'Up to 2 concepts', 'Web + social formats', 'Unlimited refinements'], cta: 'Start Now' },\n        { name: 'Professional', volume: '50 Images', price: '$890', per: '', featured: true, items: ['50 finished images', 'Up to 6 concepts', 'Model & scene direction', 'Priority 48h turnaround', 'Dedicated creative lead'], cta: 'Start Now' },\n        { name: 'Business', volume: '100 Images', price: '$1490', per: '', items: ['100 finished images', 'Full catalogue consistency', 'Ad-ready crop variants', 'Priority queue'], cta: 'Start Now' },\n        { name: 'Enterprise', volume: 'Custom volume', price: 'Custom', per: 'quote', items: ['1000+ images \/ month', 'Brand style guide build', 'Dedicated production team', 'SLA & invoicing'], cta: 'Talk to Us' }\n      ].map((p) => ({\n        ...p,\n        flex: isMobile ? '0 0 auto' : '1 1 0',\n        minW: isMobile ? '80vw' : '0',\n        pad: p.featured && isDesktop ? '40px 34px' : pick('24px', '28px', '32px'),\n        priceSize: p.featured ? pick('38px', '42px', '48px') : pick('32px', '34px', '38px'),\n        scale: p.featured && isDesktop ? 'scale(1.045)' : 'none',\n        border: p.featured ? 'oklch(0.72 0.13 262 \/ 0.42)' : 'rgba(255,255,255,.08)',\n        bg: p.featured ? 'linear-gradient(170deg, oklch(0.38 0.13 272 \/ 0.55), rgba(255,255,255,.02))' : 'linear-gradient(165deg, rgba(255,255,255,.045), rgba(255,255,255,.012))',\n        shadow: p.featured ? '0 50px 120px -50px oklch(0.55 0.17 275 \/ 0.95)' : 'none',\n        ctaBg: p.featured ? 'linear-gradient(180deg, #ffffff, #d6d6df)' : 'rgba(255,255,255,.05)',\n        ctaColor: p.featured ? '#08080a' : '#f0f0f4',\n        ctaBorder: p.featured ? 'transparent' : 'rgba(255,255,255,.14)'\n      })),\n      platforms: [\n        { n: 'Shopify', g: 'S' }, { n: 'Amazon', g: 'A' }, { n: 'Instagram', g: '\u25ce' }, { n: 'Facebook', g: 'f' },\n        { n: 'TikTok', g: '\u266a' }, { n: 'Pinterest', g: 'P' }, { n: 'Google Shopping', g: 'G' }, { n: 'Website', g: '\u2317' },\n        { n: 'Email Campaigns', g: '\u2709' }, { n: 'Ads', g: '\u25c8' }, { n: 'Catalogs', g: '\u25a4' }, { n: 'Print', g: '\u2399' }\n      ],\n      testDisplay: isMobile ? 'flex' : 'grid',\n      testCols: isTablet ? 'repeat(2, 1fr)' : 'repeat(3, 1fr)',\n      testOverflow: isMobile ? 'auto' : 'visible',\n      testMinW: isMobile ? '78vw' : '0',\n      testimonials: [\n        { quote: 'Our sales page instantly looked premium.', name: 'Emma', role: 'Fashion brand owner', offset: '0px' },\n        { quote: 'We replaced expensive photoshoots completely.', name: 'Daniel', role: 'Footwear store', offset: isDesktop ? '32px' : '0px' },\n        { quote: 'The images looked incredibly realistic.', name: 'Sophia', role: 'Jewelry brand', offset: isDesktop ? '12px' : '0px' },\n        { quote: 'Our ROAS improved because the creatives looked much more premium.', name: 'James', role: 'Performance marketer', offset: isDesktop ? '44px' : '0px' }\n      ],\n      faqs: [\n        { q: 'Can I request revisions?', a: \"Yes. We'll continue refining until you're happy \u2014 revisions are included in every package.\" },\n        { q: 'How long does delivery take?', a: 'Usually within a few business days depending on project size. First concepts typically arrive in 48 hours.' },\n        { q: 'Do I need professional product photos?', a: 'No. A clear smartphone image is often enough \u2014 good light and a clean angle are all we need.' },\n        { q: 'Can you match our brand style?', a: 'Absolutely. We can follow your references, colors and visual identity, and build a reusable style guide.' },\n        { q: 'Where can I use these images?', a: 'Anywhere, including websites, Shopify, Amazon, Instagram, Facebook, TikTok, ads, catalogs and email campaigns.' }\n      ].map((f, i) => ({\n        ...f,\n        toggle: () => this.setState((s) => ({ open: s.open === i ? -1 : i })),\n        rows: this.state.open === i ? '1fr' : '0fr',\n        rot: this.state.open === i ? 45 : 0,\n        border: this.state.open === i ? 'rgba(255,255,255,.2)' : 'rgba(255,255,255,.08)',\n        bg: this.state.open === i ? 'rgba(255,255,255,.05)' : 'rgba(255,255,255,.02)'\n      })),\n      footerCols: [\n        { title: 'Services', links: ['Lifestyle imagery', 'On-model apparel', 'Product retouch', 'Ad creatives'] },\n        { title: 'Company', links: ['About', 'Portfolio', 'Careers', 'Press'] },\n        { title: 'Resources', links: ['Pricing', 'FAQ', 'Style guides', 'Delivery formats'] },\n        { title: 'Contact', links: ['Start a project', 'WhatsApp', 'hello@okalura.com', 'Book a call'] }\n      ],\n      socials: ['IG', 'IN', 'X', 'BE'],\n\n      openModal: this.openModal,\n      closeModal: this.closeModal,\n      stopClick: (e) => e.stopPropagation(),\n      submit: this.submit,\n      backHome: this.backHome,\n      modalOpen: this.state.modalOpen,\n      overlayOpacity: this.state.modalOpen ? 1 : 0,\n      overlayVis: this.state.modalOpen ? 'visible' : 'hidden',\n      overlayBlur: this.state.modalOpen ? 'blur(16px) saturate(120%)' : 'blur(0px)',\n      overlayAlign: isMobile ? 'flex-end' : 'center',\n      overlayPad: isMobile ? '0' : pick('0', '24px', '32px'),\n      panelW: pick('100%', '90%', '650px'),\n      panelRadius: isMobile ? '30px 30px 0 0' : '28px',\n      panelPad: pick('26px 20px 20px', '34px', '38px'),\n      panelTransform: this.state.modalOpen ? 'translateY(0) scale(1)' : (isMobile ? 'translateY(6%) scale(1)' : 'translateY(8px) scale(.96)'),\n      panelMaxH: isMobile ? '92vh' : '88vh',\n      panelRef: (el) => { this._panel = el; },\n      firstRef: (el) => { this._firstInput = el; },\n      modalTitleSize: pick('26px', '30px', '32px'),\n      fieldCols: isMobile ? '1fr' : 'repeat(2, 1fr)',\n      uploadCols: isMobile ? '1fr' : 'repeat(2, 1fr)',\n      submitting: this.state.submitting,\n      submitLabel: this.state.submitting ? 'Submitting\u2026' : 'Submit Request',\n      submitOpacity: this.state.submitting ? 0.72 : 1,\n      submitCursor: this.state.submitting ? 'wait' : 'pointer',\n\n      fields: [\n        { k: 'first', label: 'First Name', ph: 'Emma', type: 'text', auto: 'given-name', first: true },\n        { k: 'last', label: 'Last Name', ph: 'Larsen', type: 'text', auto: 'family-name' },\n        { k: 'phone', label: 'Phone Number', ph: '+1 555 018 2299', type: 'tel', auto: 'tel' },\n        { k: 'email', label: 'Email Address', ph: 'emma@brand.com', type: 'email', auto: 'email' }\n      ].map((f) => {\n        const err = this.state.errors[f.k] || '';\n        return {\n          ...f,\n          value: this.state.form[f.k],\n          onInput: (e) => this.setField(f.k, e.target.value),\n          err,\n          hasErr: !!err,\n          ref: f.first ? this._setFirst : this._noRef,\n          border: err ? 'oklch(0.68 0.19 22 \/ 0.75)' : 'rgba(255,255,255,.12)',\n          shake: err ? (this.state.submitCount % 2 ? 'shake .42s cubic-bezier(.36,.07,.19,.97)' : 'shakeAlt .42s cubic-bezier(.36,.07,.19,.97)') : 'none',\n          invalid: err ? 'true' : 'false'\n        };\n      }),\n\n      slots: this.state.slots.map((s, i) => ({\n        idx: i,\n        label: i === 0 ? 'Image 01' : 'Image 02',\n        status: s.status,\n        isEmpty: s.status === 'empty',\n        isUploading: s.status === 'uploading',\n        isDone: s.status === 'done',\n        name: s.name,\n        dims: s.dims || 'reading dimensions\u2026',\n        url: s.url,\n        msg: s.msg,\n        progress: Math.round(s.progress) + '%',\n        progressLabel: Math.round(s.progress) + '%',\n        border: s.drag ? 'oklch(0.78 0.13 255)' : s.status === 'done' ? 'rgba(255,255,255,.16)' : 'rgba(255,255,255,.14)',\n        bg: s.drag ? 'oklch(0.62 0.16 268 \/ 0.16)' : 'rgba(255,255,255,.026)',\n        glow: s.drag ? '0 0 0 4px oklch(0.62 0.16 268 \/ 0.18), 0 20px 50px -30px oklch(0.62 0.16 268 \/ 0.9)' : 'none',\n        dash: s.status === 'done' ? 'solid' : 'dashed',\n        onDragOver: (e) => { e.preventDefault(); if (!this.state.slots[i].drag) this.setSlot(i, { drag: true }); },\n        onDragLeave: (e) => { e.preventDefault(); this.setSlot(i, { drag: false }); },\n        onDrop: (e) => { e.preventDefault(); this.handleFiles(i, e.dataTransfer.files); },\n        onChange: (e) => this.handleFiles(i, e.target.files),\n        remove: (e) => { e.preventDefault(); this.clearSlot(i); }\n      })),\n\n      isThanks: this.state.view === 'thanks',\n      thanksOpacity: this.state.view === 'thanks' ? 1 : 0,\n      thanksVis: this.state.view === 'thanks' ? 'visible' : 'hidden',\n      thanksTransform: this.state.view === 'thanks' ? 'translateY(0)' : 'translateY(18px)',\n      thanksPad: pick('96px 20px 60px', '110px 32px 70px', '120px 40px 80px'),\n      thanksTitle: pick('38px', '52px', '64px'),\n      summary: [\n        { k: 'Name', v: (this.state.form.first + ' ' + this.state.form.last).trim() || '\u2014' },\n        { k: 'Email', v: this.state.form.email || '\u2014' },\n        { k: 'Uploaded images', v: String(this.state.slots.filter((s) => s.status === 'done').length) },\n        { k: 'Reference', v: 'AS-' + String(2600 + this.state.submitCount * 7) }\n      ]\n    };\n  }\n}\n<\/script>\n\n<script>\n\/\/ GENERATED from dc-runtime\/src\/*.ts \u2014 do not edit. Rebuild with `cd dc-runtime && bun run build`.\n\"use strict\";\n(() => {\n  var __defProp = Object.defineProperty;\n  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;\n  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== \"symbol\" ? key + \"\" : key, value);\n\n  \/\/ src\/react.ts\n  function getReact() {\n    const R = window.React;\n    if (!R) throw new Error(\"dc-runtime: window.React is not available yet\");\n    return R;\n  }\n  function getReactDOM() {\n    const RD = window.ReactDOM;\n    if (!RD) throw new Error(\"dc-runtime: window.ReactDOM is not available yet\");\n    return RD;\n  }\n  var h = ((...args) => getReact().createElement(\n    ...args\n  ));\n\n  \/\/ src\/parse.ts\n  function parseDcDocument(doc) {\n    const dc = doc.querySelector(\"x-dc\");\n    if (!dc) return null;\n    const scriptEl = doc.querySelector(\"script[data-dc-script]\");\n    const { props, preview } = parseDataProps(\n      scriptEl?.getAttribute(\"data-props\") ?? null\n    );\n    return {\n      template: dc.innerHTML,\n      js: scriptEl ? scriptEl.textContent || \"\" : \"\",\n      props,\n      preview\n    };\n  }\n  function parseDcText(src) {\n    const openMatch = \/<x-dc(?:\\s[^>]*)?>\/.exec(src);\n    if (!openMatch) return null;\n    const close = src.lastIndexOf(\"<\/x-dc>\");\n    if (close === -1 || close < openMatch.index) return null;\n    const template = src.slice(openMatch.index + openMatch[0].length, close);\n    const doc = new DOMParser().parseFromString(src, \"text\/html\");\n    const scriptEl = doc.querySelector(\"script[data-dc-script]\");\n    const { props, preview } = parseDataProps(\n      scriptEl?.getAttribute(\"data-props\") ?? null\n    );\n    return {\n      template,\n      js: scriptEl ? scriptEl.textContent || \"\" : \"\",\n      props,\n      preview\n    };\n  }\n  function parseDataProps(raw) {\n    if (!raw) return { props: null, preview: null };\n    let parsed;\n    try {\n      parsed = JSON.parse(raw);\n    } catch {\n      return { props: null, preview: null };\n    }\n    if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n      return { props: null, preview: null };\n    }\n    const obj = parsed;\n    const preview = obj.$preview && typeof obj.$preview === \"object\" ? obj.$preview : null;\n    const rest = {};\n    for (const k of Object.keys(obj)) {\n      if (k[0] !== \"$\") rest[k] = obj[k];\n    }\n    return { props: Object.keys(rest).length ? rest : null, preview };\n  }\n  function dcNameFromPath(pathname) {\n    let p = pathname || \"\";\n    try {\n      p = decodeURIComponent(p);\n    } catch {\n    }\n    const base = p.split(\"\/\").pop() || \"Root\";\n    return base.replace(\/\\.dc\\.html$\/, \"\").replace(\/\\.html?$\/, \"\") || \"Root\";\n  }\n\n  \/\/ src\/boot.ts\n  var BASE_CSS = `\n    .sc-placeholder{background:color-mix(in srgb,currentColor 8%,transparent);\n      border:1px solid color-mix(in srgb,currentColor 50%,transparent);\n      border-radius:2px;box-sizing:border-box;overflow:hidden}\n    @keyframes sc-shine{0%{background-position:100% 50%}100%{background-position:0% 50%}}\n    html.sc-dc-streaming .sc-placeholder,\n    html.sc-dc-streaming .sc-interp.sc-missing{position:relative;\n      background:color-mix(in srgb,currentColor 5%,transparent);\n      border-color:transparent}\n    html.sc-dc-streaming .sc-placeholder::before,\n    html.sc-dc-streaming .sc-interp.sc-missing::before{content:'';\n      position:absolute;inset:0;pointer-events:none;\n      background:linear-gradient(90deg,rgba(217,119,87,0) 25%,rgba(247,225,211,.95) 37%,rgba(217,119,87,0) 63%);\n      background-size:400% 100%;animation:sc-shine 1.4s ease infinite}\n    html.sc-dc-streaming .sc-placeholder:nth-child(n+9 of .sc-placeholder)::before,\n    html.sc-dc-streaming .sc-interp.sc-missing:nth-child(n+9 of .sc-interp.sc-missing)::before{animation:none;\n      background:color-mix(in srgb,currentColor 8%,transparent)}\n    .sc-placeholder-error{padding:4px 8px;font:11px\/1.4 ui-monospace,monospace;\n      color:color-mix(in srgb,currentColor 70%,transparent);word-break:break-word}\n    .sc-interp.sc-missing{display:inline-block;width:2em;height:1em;overflow:hidden;\n      vertical-align:text-bottom;background:rgba(255,255,255,.3);border:1px solid rgba(0,0,0,.5);\n      border-radius:2px;box-sizing:border-box;color:transparent;\n      user-select:none}\n    .sc-interp.sc-unresolved{font-family:ui-monospace,monospace;font-size:.85em;\n      color:color-mix(in srgb,currentColor 50%,transparent);\n      background:color-mix(in srgb,currentColor 10%,transparent);border-radius:3px;\n      padding:0 3px}\n    .sc-host.sc-has-error{position:relative}\n    .sc-logic-error{position:absolute;top:8px;left:8px;z-index:2147483647;max-width:60ch;\n      padding:6px 10px;background:#b00020;color:#fff;font:12px\/1.4 ui-monospace,monospace;\n      border-radius:4px;white-space:pre-wrap;pointer-events:none}\n    \/* Mirrors PRINT_BASELINE_CSS in apps\/web deck-stage-export.ts \\u2014 keep both\n       in sync until dc-runtime regains a build step. *\/\n    @media print {\n      @page { margin: 0.5cm; }\n      figure, table { break-inside: avoid; }\n      #dc-root, #dc-root > .sc-host { height: auto; }\n      *, *::before, *::after {\n        print-color-adjust: exact; -webkit-print-color-adjust: exact;\n        backdrop-filter: none !important; -webkit-backdrop-filter: none !important;\n        animation-delay: -99s !important; animation-duration: .001s !important;\n        animation-iteration-count: 1 !important; animation-fill-mode: both !important;\n        animation-play-state: running !important; transition-duration: 0s !important;\n      }\n    }\n  `;\n  var FULL_PAGE_CSS = \"html,body{height:100%;margin:0}#dc-root,#dc-root>.sc-host{height:100%}\";\n  function rootNameForDocument(doc, loc) {\n    let bootPath = loc.pathname || \"\";\n    if (!\/\\.dc\\.html?$\/i.test(safeDecode(bootPath))) {\n      try {\n        bootPath = new URL(doc.baseURI || \"\/\").pathname;\n      } catch {\n      }\n    }\n    return dcNameFromPath(bootPath);\n  }\n  function safeDecode(s) {\n    try {\n      return decodeURIComponent(s);\n    } catch {\n      return s;\n    }\n  }\n  function boot(runtime, doc = document) {\n    const parsed = parseDcDocument(doc);\n    if (!parsed) return null;\n    const React = getReact();\n    const rootName = rootNameForDocument(doc, location);\n    runtime.markFetched(rootName);\n    runtime.setRootName(rootName);\n    runtime.adoptParsed(rootName, parsed);\n    if (!window.__resources) {\n      fetch(location.href).then((res) => res.ok ? res.text() : \"\").then((t) => {\n        const raw = t ? parseDcText(t) : null;\n        if (raw?.template) runtime.updateHtml(rootName, raw.template);\n      }).catch(() => {\n      });\n    }\n    const dc = doc.querySelector(\"x-dc\");\n    const hostEl = doc.createElement(\"div\");\n    hostEl.id = \"dc-root\";\n    dc.replaceWith(hostEl);\n    if (!parsed.preview) {\n      const s = doc.createElement(\"style\");\n      s.textContent = FULL_PAGE_CSS;\n      doc.head.appendChild(s);\n    }\n    const Root = runtime.getDC(rootName);\n    const entry = runtime.registry.get(rootName);\n    function StandaloneRoot() {\n      const [, setTick] = React.useState(0);\n      React.useEffect(() => {\n        const sub = () => setTick((n) => n + 1);\n        entry.subs.add(sub);\n        return () => {\n          entry.subs.delete(sub);\n        };\n      }, []);\n      const defaults = React.useMemo(() => {\n        const d = {};\n        for (const k in entry.propsMeta || {}) {\n          const v = entry.propsMeta?.[k]?.default;\n          if (v !== void 0) d[k] = v;\n        }\n        return d;\n      }, [entry.propsMeta]);\n      return h(Root, { ...defaults, ...entry.propOverrides || {} });\n    }\n    const ReactDOM = getReactDOM();\n    if (ReactDOM.createRoot)\n      ReactDOM.createRoot(hostEl).render(h(StandaloneRoot));\n    else ReactDOM.render(h(StandaloneRoot), hostEl);\n    return rootName;\n  }\n\n  \/\/ src\/expr.ts\n  var IDENT_RE = \/^[A-Za-z_$][A-Za-z0-9_$]*\/;\n  var NUMBER_RE = \/^-?\\d+(\\.\\d+)?$\/;\n  function resolve(vals, src) {\n    const expr = String(src).trim();\n    if (!expr) return void 0;\n    if (expr[0] === \"(\" && expr[expr.length - 1] === \")\" && parensWrapWhole(expr)) {\n      return resolve(vals, expr.slice(1, -1));\n    }\n    const eq = findTopLevelEquality(expr);\n    if (eq) {\n      const lv = resolve(vals, expr.slice(0, eq.index));\n      const rv = resolve(vals, expr.slice(eq.index + eq.op.length));\n      switch (eq.op) {\n        case \"===\":\n          return lv === rv;\n        case \"!==\":\n          return lv !== rv;\n        case \"==\":\n          return lv == rv;\n        default:\n          return lv != rv;\n      }\n    }\n    if (expr[0] === \"!\") return !resolve(vals, expr.slice(1));\n    if (expr === \"true\") return true;\n    if (expr === \"false\") return false;\n    if (expr === \"null\") return null;\n    if (expr === \"undefined\") return void 0;\n    if (NUMBER_RE.test(expr)) return Number(expr);\n    if (expr.length >= 2 && (expr[0] === '\"' || expr[0] === \"'\") && expr[expr.length - 1] === expr[0]) {\n      return expr.slice(1, -1);\n    }\n    return resolvePath(vals, expr);\n  }\n  function parensWrapWhole(expr) {\n    let depth = 0;\n    for (let i = 0; i < expr.length - 1; i++) {\n      if (expr[i] === \"(\") depth++;\n      else if (expr[i] === \")\") {\n        depth--;\n        if (depth === 0) return false;\n      }\n    }\n    return true;\n  }\n  function findTopLevelEquality(expr) {\n    let depth = 0;\n    for (let i = 0; i < expr.length; i++) {\n      const c = expr[i];\n      if (c === \"[\" || c === \"(\") depth++;\n      else if (c === \"]\" || c === \")\") depth--;\n      else if (depth === 0 && (c === \"=\" || c === \"!\") && expr[i + 1] === \"=\") {\n        if (i > 0 && (expr[i - 1] === \"=\" || expr[i - 1] === \"!\")) continue;\n        if (!expr.slice(0, i).trim()) continue;\n        const op = expr[i + 2] === \"=\" ? c + \"==\" : c + \"=\";\n        return { index: i, op };\n      }\n    }\n    return null;\n  }\n  function resolvePath(vals, expr) {\n    const head = expr.match(IDENT_RE);\n    if (!head) return void 0;\n    let cur = vals == null ? void 0 : vals[head[0]];\n    let i = head[0].length;\n    while (i < expr.length) {\n      if (expr[i] === \".\") {\n        const m = expr.slice(i + 1).match(IDENT_RE) || expr.slice(i + 1).match(\/^\\d+\/);\n        if (!m) return void 0;\n        cur = cur == null ? void 0 : cur[m[0]];\n        i += 1 + m[0].length;\n      } else if (expr[i] === \"[\") {\n        let depth = 1;\n        let j = i + 1;\n        while (j < expr.length && depth > 0) {\n          if (expr[j] === \"[\") depth++;\n          else if (expr[j] === \"]\") {\n            depth--;\n            if (depth === 0) break;\n          }\n          j++;\n        }\n        if (depth !== 0) return void 0;\n        const key = resolve(vals, expr.slice(i + 1, j));\n        cur = cur == null ? void 0 : cur[key];\n        i = j + 1;\n      } else {\n        return void 0;\n      }\n    }\n    return cur;\n  }\n\n  \/\/ src\/encode.ts\n  var CAMEL_ATTR = \"sc-camel-\";\n  var INLINE_TEXT_TAGS = new Set(\n    \"a abbr b bdi bdo br cite code del dfn em i ins kbd mark q s samp small span strike strong sub sup u var wbr\".split(\n      \" \"\n    )\n  );\n  var RAW_WRAP = {\n    select: \"sc-raw-select\",\n    table: \"sc-raw-table\",\n    tbody: \"sc-raw-tbody\",\n    thead: \"sc-raw-thead\",\n    tfoot: \"sc-raw-tfoot\",\n    tr: \"sc-raw-tr\",\n    td: \"sc-raw-td\",\n    th: \"sc-raw-th\",\n    caption: \"sc-raw-caption\"\n  };\n  var RAW_UNWRAP = Object.fromEntries(\n    Object.entries(RAW_WRAP).map(([k, v]) => [v, k])\n  );\n  var EVENT_MAP = {\n    onclick: \"onClick\",\n    onchange: \"onChange\",\n    oninput: \"onInput\",\n    onsubmit: \"onSubmit\",\n    onkeydown: \"onKeyDown\",\n    onkeyup: \"onKeyUp\",\n    onkeypress: \"onKeyPress\",\n    onmousedown: \"onMouseDown\",\n    onmouseup: \"onMouseUp\",\n    onmouseenter: \"onMouseEnter\",\n    onmouseleave: \"onMouseLeave\",\n    onfocus: \"onFocus\",\n    onblur: \"onBlur\",\n    ondoubleclick: \"onDoubleClick\",\n    oncontextmenu: \"onContextMenu\",\n    onmousemove: \"onMouseMove\",\n    onmouseover: \"onMouseOver\",\n    onmouseout: \"onMouseOut\",\n    onpointerdown: \"onPointerDown\",\n    onpointerup: \"onPointerUp\",\n    onpointermove: \"onPointerMove\",\n    onpointerenter: \"onPointerEnter\",\n    onpointerleave: \"onPointerLeave\",\n    onpointercancel: \"onPointerCancel\",\n    onpointerover: \"onPointerOver\",\n    onpointerout: \"onPointerOut\",\n    ongotpointercapture: \"onGotPointerCapture\",\n    onlostpointercapture: \"onLostPointerCapture\",\n    ontouchstart: \"onTouchStart\",\n    ontouchend: \"onTouchEnd\",\n    ontouchmove: \"onTouchMove\",\n    ontouchcancel: \"onTouchCancel\",\n    ondragstart: \"onDragStart\",\n    ondragend: \"onDragEnd\",\n    ondragenter: \"onDragEnter\",\n    ondragleave: \"onDragLeave\",\n    ondragover: \"onDragOver\",\n    onanimationstart: \"onAnimationStart\",\n    onanimationend: \"onAnimationEnd\",\n    onanimationiteration: \"onAnimationIteration\",\n    ontransitionend: \"onTransitionEnd\"\n  };\n  var ATTRS = `(?:[^>\"']|\"[^\"]*\"|'[^']*')*`;\n  var IMPORT_SELF_CLOSE_RE = new RegExp(\n    \"<(x-import|dc-import)(\" + ATTRS + \")\/>\",\n    \"gi\"\n  );\n  var CAMEL_ATTR_RE = \/(\\s)([a-z]+[A-Z][A-Za-z0-9]*)(\\s*=)\/g;\n  function encodeCamelAttrs(html) {\n    return html.replace(\n      CAMEL_ATTR_RE,\n      (_, sp, name, eq) => sp + CAMEL_ATTR + name.replace(\/[A-Z]\/g, (c) => \"-\" + c.toLowerCase()) + eq\n    );\n  }\n  function encodeCase(html) {\n    html = html.replace(\n      IMPORT_SELF_CLOSE_RE,\n      (_, t, a) => \"<\" + t + a + \"><\/\" + t + \">\"\n    );\n    html = html.replace(\/<helmet(\\s|>)\/gi, \"<sc-helmet$1\");\n    html = html.replace(\/<\\\/helmet\\s*>\/gi, \"<\/sc-helmet>\");\n    html = encodeCamelAttrs(html);\n    for (const [real, alias] of Object.entries(RAW_WRAP)) {\n      html = html.replace(\n        new RegExp(\"(<\/?)\" + real + \"(?=[\\\\s>])\", \"gi\"),\n        \"$1\" + alias\n      );\n    }\n    return html;\n  }\n  function kebabToCamel(s) {\n    return s.replace(\/-([a-z])\/g, (_, c) => c.toUpperCase());\n  }\n  function cssToObj(css) {\n    const o = {};\n    for (const decl of css.split(\";\")) {\n      const i = decl.indexOf(\":\");\n      if (i < 0) continue;\n      const prop = decl.slice(0, i).trim();\n      o[prop.startsWith(\"--\") ? prop : kebabToCamel(prop)] = decl.slice(i + 1).trim();\n    }\n    return o;\n  }\n  function compileAttr(raw) {\n    const whole = raw.match(\/^\\s*\\{\\{([\\s\\S]+?)\\}\\}\\s*$\/);\n    if (whole) {\n      const path = whole[1];\n      return (vals) => resolve(vals, path);\n    }\n    if (raw.includes(\"{{\")) {\n      const parts = raw.split(\/\\{\\{([\\s\\S]+?)\\}\\}\/g);\n      return (vals) => parts.map((s, i) => i & 1 ? resolve(vals, s) ?? \"\" : s).join(\"\");\n    }\n    return () => raw;\n  }\n\n  \/\/ src\/compile.ts\n  function collectProps(node, kind, host) {\n    const propGetters = [];\n    const pseudoClasses = [];\n    let hintSize = null;\n    for (const { name, value } of [...node.attributes]) {\n      if (name === \"sc-name\" || name === \"data-dc-tpl\") continue;\n      let key = name;\n      if (key.startsWith(CAMEL_ATTR))\n        key = kebabToCamel(key.slice(CAMEL_ATTR.length));\n      if (key === \"hint-size\") {\n        hintSize = value;\n        continue;\n      }\n      if (key.startsWith(\"style-\")) {\n        pseudoClasses.push(host.pseudoClass(key.slice(6), value));\n        continue;\n      }\n      if (kind !== \"dom\") {\n        if (key.includes(\"-\") && !(kind === \"x-import\" && (key.startsWith(\"aria-\") || key.startsWith(\"data-\"))))\n          key = kebabToCamel(key);\n      } else {\n        if (key === \"class\") key = \"className\";\n        else if (key === \"for\") key = \"htmlFor\";\n        else if (key.startsWith(\"on\"))\n          key = EVENT_MAP[key] || \"on\" + key[2].toUpperCase() + key.slice(3);\n      }\n      propGetters.push([key, compileAttr(value)]);\n    }\n    return { propGetters, pseudoClasses, hintSize };\n  }\n  var HOST_STYLE_PROPS = \/* @__PURE__ *\/ new Set([\n    \"position\",\n    \"left\",\n    \"right\",\n    \"top\",\n    \"bottom\",\n    \"inset\",\n    \"width\",\n    \"height\",\n    \"z-index\",\n    \"transform\"\n  ]);\n  function hostPositionStyle(style) {\n    const all = typeof style === \"string\" ? cssToObj(style) : style != null && typeof style === \"object\" ? style : null;\n    if (!all) return void 0;\n    const out = {};\n    for (const [k, v] of Object.entries(all)) {\n      const kebab = k.replace(\/[A-Z]\/g, (c) => \"-\" + c.toLowerCase());\n      if (HOST_STYLE_PROPS.has(kebab)) out[k] = v;\n    }\n    return Object.keys(out).length ? out : void 0;\n  }\n  function compileTemplate(html, host) {\n    const tpl = document.createElement(\"template\");\n    \/\/! nosemgrep: direct-inner-html-assignment\n    tpl.innerHTML = encodeCase(html);\n    let tplN = 0;\n    (function stamp(node) {\n      if (node.nodeType === Node.ELEMENT_NODE) {\n        node.setAttribute(\"data-dc-tpl\", String(tplN++));\n      }\n      for (const c of node.childNodes) stamp(c);\n    })(tpl.content);\n    const builders = walkChildren(tpl.content, host);\n    const render = ((vals, ctx) => builders.map((b, i) => b(vals || {}, ctx, i)));\n    render.__annotated = tpl.innerHTML;\n    return render;\n  }\n  function walkChildren(node, host) {\n    return [...node.childNodes].map((c) => walk(c, host)).filter((b) => b != null);\n  }\n  var SLIDE_ID_VALUE_RE = \/^[0-9a-f]{8}$\/;\n  var DECK_CONTROL_FLOW_RE = \/^(sc-if|sc-for|sc-else|dc-import|x-import)$\/;\n  var DECK_AUX_RE = \/^(template|script|style|sc-helmet|helmet)$\/;\n  function isDeckMountTag(el) {\n    if (el.localName === \"deck-stage\") return true;\n    return el.localName === \"x-import\" && (el.getAttribute(\"component-from-global-scope\") || \"\") === \"deck-stage\";\n  }\n  function walkDeckChildren(el, host) {\n    const pairs = [...el.childNodes].map((c) => ({ c, b: walk(c, host) })).filter((p) => p.b !== null);\n    const kids = pairs.map((p) => p.b);\n    const seen = \/* @__PURE__ *\/ new Set();\n    const wsSeen = \/* @__PURE__ *\/ new Map();\n    const keys = [];\n    const nextSlideId = new Array(pairs.length);\n    {\n      let upcoming = null;\n      for (let j = pairs.length - 1; j >= 0; j--) {\n        const n = pairs[j].c;\n        if (n.nodeType === Node.ELEMENT_NODE) {\n          const t = n.localName;\n          upcoming = !DECK_AUX_RE.test(t) && !DECK_CONTROL_FLOW_RE.test(t) ? n.getAttribute(\"data-om-slide-id\") : null;\n        }\n        nextSlideId[j] = upcoming;\n      }\n    }\n    for (let j = 0; j < pairs.length; j++) {\n      const { c } = pairs[j];\n      if (c.nodeType === Node.TEXT_NODE) {\n        if ((c.nodeValue ?? \"\").trim() === \"\") {\n          const base = nextSlideId[j] ? \"omid-ws:\" + nextSlideId[j] : \"omid-ws:aux\";\n          const n = wsSeen.get(base) ?? 0;\n          wsSeen.set(base, n + 1);\n          keys.push(n === 0 ? base : base + \":\" + n);\n          continue;\n        }\n        return { kids, keys: null };\n      }\n      if (c.nodeType !== Node.ELEMENT_NODE) {\n        keys.push(j);\n        continue;\n      }\n      const child = c;\n      const tag = child.localName;\n      if (DECK_AUX_RE.test(tag)) {\n        keys.push(j);\n        continue;\n      }\n      if (DECK_CONTROL_FLOW_RE.test(tag)) return { kids, keys: null };\n      const v = child.getAttribute(\"data-om-slide-id\");\n      if (!v || !SLIDE_ID_VALUE_RE.test(v) || seen.has(v)) {\n        return { kids, keys: null };\n      }\n      seen.add(v);\n      keys.push(\"omid:\" + v);\n    }\n    return { kids, keys };\n  }\n  function renderDeckKids(kids, kidKeys, vals, ctx) {\n    return kids.map((b, j) => {\n      const k = kidKeys ? kidKeys[j] : j;\n      const out = b(vals, ctx, k);\n      return kidKeys != null && typeof out === \"string\" ? h(getReact().Fragment, { key: k }, out) : out;\n    });\n  }\n  function walk(node, host) {\n    if (node.nodeType === Node.TEXT_NODE) return walkText(node);\n    if (node.nodeType !== Node.ELEMENT_NODE) return null;\n    const el = node;\n    const tag = el.tagName.toLowerCase();\n    if (tag === \"sc-for\") return walkFor(el, host);\n    if (tag === \"sc-if\") return walkIf(el, host);\n    if (tag === \"x-import\") return walkXImport(el, host);\n    if (tag === \"sc-helmet\") return host.helmet(el);\n    if (tag === \"dc-import\") return walkComponent(el, host);\n    return walkElement(el, host);\n  }\n  var warnedHoles = \/* @__PURE__ *\/ new Set();\n  function warnUnresolved(ctx, what) {\n    const key = (ctx?.__name || \"?\") + \"\\0\" + what;\n    if (warnedHoles.has(key)) return;\n    warnedHoles.add(key);\n    console.warn(\"[dc-runtime] \" + (ctx?.__name || \"template\") + \": \" + what);\n  }\n  function walkText(node) {\n    const txt = node.nodeValue ?? \"\";\n    if (!txt.includes(\"{{\")) {\n      if (!txt.trim() && !txt.includes(\" \")) return null;\n      return () => txt;\n    }\n    const parts = txt.split(\/\\{\\{([\\s\\S]+?)\\}\\}\/g);\n    return (vals, ctx, key) => h(\n      getReact().Fragment,\n      { key },\n      ...parts.map((p, i) => {\n        if (!(i & 1)) return p;\n        const v = resolve(vals, p);\n        if (v === void 0) {\n          if (!ctx?.__streamingNow) {\n            if (document.body?.hasAttribute(\"data-dc-editor-on\")) {\n              return h(\n                \"span\",\n                { key: i, className: \"sc-interp sc-unresolved\" },\n                \"{{ \" + p.trim() + \" }}\"\n              );\n            }\n            warnUnresolved(\n              ctx,\n              \"{{ \" + p.trim() + \" }} never resolved \\u2014 rendered as empty\"\n            );\n            return null;\n          }\n          return h(\n            \"span\",\n            { key: i, className: \"sc-interp sc-missing\" },\n            p.trim()\n          );\n        }\n        if (getReact().isValidElement(v) || Array.isArray(v)) {\n          return h(getReact().Fragment, { key: i }, v);\n        }\n        if (v === null || typeof v === \"boolean\") return null;\n        return h(\"span\", { key: i, className: \"sc-interp\" }, String(v));\n      })\n    );\n  }\n  function walkFor(el, host) {\n    const listGet = compileAttr(el.getAttribute(\"list\") || \"\");\n    const asName = el.getAttribute(\"as\") || \"item\";\n    const hintN = parseInt(el.getAttribute(\"hint-placeholder-count\") || \"0\", 10);\n    const kids = walkChildren(el, host);\n    const listSrc = el.getAttribute(\"list\") || \"\";\n    return (vals, ctx, key) => {\n      let list = listGet(vals);\n      if (!Array.isArray(list)) {\n        if (!ctx?.__streamingNow) {\n          if (list !== void 0 && list !== null) {\n            warnUnresolved(\n              ctx,\n              'sc-for list=\"' + listSrc + '\" is not an array (' + typeof list + \")\"\n            );\n          }\n          list = [];\n        } else {\n          list = hintN > 0 ? Array(hintN).fill(void 0) : [];\n        }\n      }\n      return h(\n        getReact().Fragment,\n        { key },\n        list.map((item, i) => {\n          const sub = { ...vals, [asName]: item, $index: i };\n          return h(\n            getReact().Fragment,\n            { key: i },\n            kids.map((b, j) => b(sub, ctx, j))\n          );\n        })\n      );\n    };\n  }\n  function walkIf(el, host) {\n    const valGet = compileAttr(el.getAttribute(\"value\") || \"\");\n    const hintRaw = el.getAttribute(\"hint-placeholder-val\");\n    const hintGet = hintRaw != null ? compileAttr(hintRaw) : null;\n    const kids = walkChildren(el, host);\n    return (vals, ctx, key) => {\n      let v = valGet(vals);\n      if (v === void 0 && hintGet && ctx?.__streamingNow) v = hintGet(vals);\n      return v ? h(\n        getReact().Fragment,\n        { key },\n        kids.map((b, j) => b(vals, ctx, j))\n      ) : null;\n    };\n  }\n  function walkComponent(el, host) {\n    const name = el.getAttribute(\"name\") || el.getAttribute(\"component\") || \"\";\n    el.removeAttribute(\"name\");\n    el.removeAttribute(\"component\");\n    const tplId = el.getAttribute(\"data-dc-tpl\");\n    const styleRaw = el.getAttribute(\"style\");\n    el.removeAttribute(\"style\");\n    const styleGet = styleRaw != null ? compileAttr(styleRaw) : null;\n    const { propGetters, hintSize } = collectProps(el, \"dc-import\", host);\n    const kids = walkChildren(el, host);\n    return (vals, ctx, key) => {\n      const props = {\n        key,\n        __hintSize: hintSize,\n        __tplId: tplId,\n        __hostStyle: styleGet ? hostPositionStyle(styleGet(vals)) : void 0\n      };\n      for (const [k, g] of propGetters) {\n        const v = g(vals);\n        if (k === \"dcProps\") {\n          if (v && typeof v === \"object\") Object.assign(props, v);\n          continue;\n        }\n        props[k] = v;\n      }\n      if (kids.length) props.children = kids.map((b, j) => b(vals, ctx, j));\n      return h(host.component(name), props);\n    };\n  }\n  function walkXImport(el, host) {\n    const globalNameGet = compileAttr(\n      el.getAttribute(\"component-from-global-scope\") || \"\"\n    );\n    const exportNameGet = compileAttr(\n      el.getAttribute(\"component\") || el.getAttribute(\"name\") || \"\"\n    );\n    const fromRaw = el.getAttribute(\"from\") || (el.getAttribute(\"component-from-global-scope\") ? \"\" : el.getAttribute(\"src\") || el.getAttribute(\"import\") || \"\");\n    const urls = fromRaw.trim() ? fromRaw.trim().split(\/\\s+\/) : [];\n    const url = urls.length ? urls[urls.length - 1] : \"\";\n    const kindOf = (u) => \/\\.(jsx|tsx)(\\?|#|$)\/i.test(u) ? \"jsx\" : \"js\";\n    const tplId = el.getAttribute(\"data-dc-tpl\");\n    const styleRaw = el.getAttribute(\"style\");\n    el.removeAttribute(\"style\");\n    const styleGet = styleRaw != null ? compileAttr(styleRaw) : null;\n    const wrap = tplId != null || styleGet != null;\n    const { propGetters, hintSize } = collectProps(el, \"x-import\", host);\n    const hasContent = el.children.length > 0 || !!(el.textContent || \"\").trim();\n    const deckKeyed = hasContent && isDeckMountTag(el) ? walkDeckChildren(el, host) : null;\n    const kids = deckKeyed ? deckKeyed.kids : hasContent ? walkChildren(el, host) : [];\n    const kidKeys = deckKeyed?.keys ?? null;\n    const urlBindable = fromRaw.includes(\"{{\");\n    if (urls.length && !urlBindable) {\n      let prev;\n      for (const u of urls) prev = host.loadExternal(kindOf(u), u, prev);\n    }\n    const evalName = (g, vals) => {\n      const v = g(vals);\n      const s = v == null ? \"\" : String(v);\n      return s.includes(\"{{\") ? \"\" : s;\n    };\n    return (vals, ctx, key) => {\n      const globalName = evalName(globalNameGet, vals);\n      const name = globalName || evalName(exportNameGet, vals);\n      const C = !name || urlBindable ? null : globalName ? host.resolveExternalGlobal(url, globalName) : host.resolveExternal(url, name);\n      const hostStyle = styleGet ? hostPositionStyle(styleGet(vals)) : void 0;\n      const wrapper = wrap ? {\n        key,\n        className: \"sc-host-x\",\n        \"data-dc-tpl\": tplId,\n        style: hostStyle || { display: \"contents\" }\n      } : null;\n      if (!C) {\n        const error = urlBindable ? \"x-import `from` cannot contain {{ \\u2026 }} \\u2014 module URLs are resolved at parse time; use a literal URL\" : host.resolveExternalError(url, name);\n        const ph = host.placeholder({\n          key: wrapper ? void 0 : key,\n          name,\n          hintSize,\n          error\n        });\n        return wrapper ? h(\"div\", wrapper, ph) : ph;\n      }\n      const props = wrapper ? {} : { key };\n      let unresolvedHole = false;\n      for (const [k, g] of propGetters) {\n        if (k === \"component\" || k === \"componentFromGlobalScope\" || k === \"from\") {\n          continue;\n        }\n        const v = g(vals);\n        if (v === void 0) unresolvedHole = true;\n        if (k === \"dcProps\") {\n          if (v && typeof v === \"object\") Object.assign(props, v);\n          continue;\n        }\n        props[k] = v;\n      }\n      if (unresolvedHole && ctx?.__htmlStreamingNow) {\n        const ph = host.placeholder({\n          key: wrapper ? void 0 : key,\n          name,\n          hintSize,\n          error: null\n        });\n        return wrapper ? h(\"div\", wrapper, ph) : ph;\n      }\n      if (kids.length) {\n        props.children = renderDeckKids(kids, kidKeys, vals, ctx);\n      }\n      return wrapper ? h(\"div\", wrapper, h(C, props)) : h(C, props);\n    };\n  }\n  function contentKey(el) {\n    const clone = el.cloneNode(true);\n    for (const d of clone.querySelectorAll(\"*\")) {\n      while (d.attributes.length) d.removeAttribute(d.attributes[0].name);\n    }\n    const s = clone.innerHTML;\n    let h2 = 5381;\n    for (let i = 0; i < s.length; i++) h2 = (h2 << 5) + h2 + s.charCodeAt(i) | 0;\n    return s.length + \".\" + (h2 >>> 0).toString(36);\n  }\n  var NEVER_CONTENT_KEYED = new Set(\n    \"script style textarea option title select canvas iframe video audio\".split(\n      \" \"\n    )\n  );\n  var NOT_INLINE_SELECTOR = \":not(\" + [...INLINE_TEXT_TAGS].join(\",\") + \")\";\n  function walkElement(el, host) {\n    const realTag = RAW_UNWRAP[el.localName] || el.localName;\n    const tplId = el.getAttribute(\"data-dc-tpl\");\n    const inlineOnly = el.childNodes.length > 0 && !NEVER_CONTENT_KEYED.has(realTag) && el.querySelector(NOT_INLINE_SELECTOR) === null;\n    const keySuffix = inlineOnly ? \"|\" + contentKey(el) : \"\";\n    const { propGetters, pseudoClasses } = collectProps(el, \"dom\", host);\n    const deckKeyed = isDeckMountTag(el) ? walkDeckChildren(el, host) : null;\n    const kids = deckKeyed ? deckKeyed.kids : walkChildren(el, host);\n    const kidKeys = deckKeyed?.keys ?? null;\n    return (vals, ctx, key) => {\n      const props = {\n        key: key + keySuffix,\n        \"data-dc-tpl\": tplId\n      };\n      for (const [k, g] of propGetters) {\n        let v = g(vals);\n        if (k === \"style\" && typeof v === \"string\") v = cssToObj(v);\n        if ((k === \"value\" || k === \"checked\") && v === void 0) {\n          v = k === \"checked\" ? false : \"\";\n        }\n        props[k] = v;\n      }\n      if (pseudoClasses.length) {\n        props.className = [props.className, ...pseudoClasses].filter(Boolean).join(\" \");\n      }\n      return h(realTag, props, ...renderDeckKids(kids, kidKeys, vals, ctx));\n    };\n  }\n\n  \/\/ src\/logic.ts\n  var StreamableLogic = class {\n    constructor(props) {\n      __publicField(this, \"props\");\n      __publicField(this, \"state\", {});\n      \/** Back-pointer to the wrapper component, installed after construction. *\/\n      __publicField(this, \"__host\");\n      this.props = props || {};\n    }\n    setState(update, cb) {\n      this.__host && this.__host.__setLogicState(update, cb);\n    }\n    forceUpdate() {\n      this.__host && this.__host.forceUpdate();\n    }\n    componentDidMount() {\n    }\n    componentDidUpdate(_prevProps) {\n    }\n    componentWillUnmount() {\n    }\n    \/** The flat object the template renders against (merged over props). *\/\n    renderVals() {\n      return {};\n    }\n  };\n  function evalDcLogic(src) {\n    \/\/! nosemgrep: eval-and-function-constructor\n    const fn = new Function(\n      \"DCLogic\",\n      \"StreamableLogic\",\n      \"React\",\n      src + '\\n;return (typeof Component!==\"undefined\"&&Component)||undefined;'\n    );\n    return fn(StreamableLogic, StreamableLogic, getReact());\n  }\n\n  \/\/ src\/component.ts\n  function shallowEqual(a, b) {\n    if (!b) return false;\n    const ak = Object.keys(a).filter((k) => k !== \"children\");\n    const bk = Object.keys(b).filter((k) => k !== \"children\");\n    if (ak.length !== bk.length) return false;\n    for (const k of ak) if (a[k] !== b[k]) return false;\n    return true;\n  }\n  function Placeholder({\n    name,\n    hintSize,\n    streaming,\n    error\n  }) {\n    const [w, hgt] = (hintSize || \"100%,60px\").split(\",\");\n    return h(\n      \"div\",\n      {\n        className: \"sc-placeholder\" + (streaming ? \" sc-streaming\" : \"\"),\n        style: { width: w.trim(), height: hgt && hgt.trim() },\n        title: name\n      },\n      error ? h(\n        \"div\",\n        { className: \"sc-placeholder-error\" },\n        (name ? name + \": \" : \"\") + error\n      ) : null\n    );\n  }\n  function hintToMin(hint) {\n    if (!hint) return void 0;\n    const [w, hgt] = hint.split(\",\");\n    return { minWidth: w.trim(), minHeight: hgt && hgt.trim() };\n  }\n  function createComponentFactory(registry, ensureFetched) {\n    const React = getReact();\n    const AncestorContext = React.createContext([]);\n    class StreamableComponent extends React.Component {\n      constructor(props) {\n        super(props);\n        __publicField(this, \"__name\");\n        __publicField(this, \"__sub\");\n        __publicField(this, \"__needsDidMount\", false);\n        \/** Snapshot of the registry's streaming flags taken at render time \u2014\n         *  builders read it off the RenderCtx (this) to pick placeholder vs\n         *  render-nothing for unresolved values. *\/\n        __publicField(this, \"__streamingNow\", false);\n        __publicField(this, \"__htmlStreamingNow\", false);\n        \/** When a construct throws, remember the (class, registry.ver, props)\n         *  triple so render-time reconcile doesn't re-attempt it on every parent\n         *  re-render. A registry bump (new class, template, external module\n         *  resolving via bumpAll) changes `ver` and breaks the memo so an\n         *  env-dependent constructor can self-heal. *\/\n        __publicField(this, \"__failedLogic\", null);\n        __publicField(this, \"__failedUserProps\", null);\n        __publicField(this, \"__failedVer\", -1);\n        \/** Per-instance constructor error \u2014 kept here (not on the registry entry)\n         *  so one instance's successful construct can't hide a sibling's failure,\n         *  and a construct can never wipe an eval error `updateJs` recorded on\n         *  `r.logicError`. *\/\n        __publicField(this, \"__ctorError\", null);\n        __publicField(this, \"logic\");\n        this.__name = props.__name;\n        this.state = { __v: 0, __err: null };\n        this.__sub = () => {\n          if (this.state.__err) this.setState({ __err: null });\n          this.forceUpdate();\n        };\n        this.__makeLogic(registry.get(this.__name).Logic, null);\n        ensureFetched(this.__name);\n      }\n      \/** Error-boundary hook: a render crash anywhere in this DC's subtree\n       *  (its own template, an x-import'd component, a child DC without its\n       *  own deeper boundary) lands here instead of unmounting the page. *\/\n      static getDerivedStateFromError(e) {\n        return { __err: e instanceof Error && e.message ? e.message : String(e) };\n      }\n      componentDidCatch(e, info) {\n        console.error(\n          \"[dc-runtime] render error in <\" + this.__name + \">:\",\n          e,\n          info?.componentStack || \"\"\n        );\n      }\n      \/** Instantiate the logic class (or the no-op base) and adopt `prevState`\n       *  over its initial state \u2014 used both at mount and on hot-swap. *\/\n      __makeLogic(Logic, prevState) {\n        const L = Logic || StreamableLogic;\n        try {\n          this.logic = new L(this.__userProps());\n          this.__failedLogic = null;\n          this.__failedUserProps = null;\n          this.__ctorError = null;\n        } catch (e) {\n          console.error(e);\n          this.__failedLogic = Logic;\n          this.__failedUserProps = this.__userProps();\n          this.__failedVer = registry.get(this.__name).ver;\n          this.__ctorError = this.__name + \": \" + (e instanceof Error && e.message ? e.message : String(e));\n          this.logic = new StreamableLogic(\n            this.__userProps()\n          );\n        }\n        this.logic.__host = this;\n        if (prevState)\n          this.logic.state = { ...this.logic.state || {}, ...prevState };\n      }\n      \/** The props the author's logic + template see \u2014 internal __-prefixed\n       *  wiring stripped. *\/\n      __userProps() {\n        const { __name, __hintSize, __tplId, __hostStyle, ...rest } = this.props;\n        return rest;\n      }\n      __setLogicState(update, cb) {\n        const prev = this.logic.state;\n        const patch = typeof update === \"function\" ? update(prev) : update;\n        this.logic.state = { ...prev, ...patch };\n        this.setState((s) => ({ __v: s.__v + 1 }), cb);\n      }\n      \/** Swap the logic instance when the registry's Logic class changed\n       *  (streaming completion, hot reload). State carries over; didMount\n       *  re-fires after the swap commits so refs exist. *\/\n      __reconcileLogic() {\n        const r = registry.get(this.__name);\n        const Next = r.Logic;\n        const Cur = this.logic.constructor;\n        if (Next === Cur || !Next && Cur === StreamableLogic || Next === this.__failedLogic && r.ver === this.__failedVer && shallowEqual(this.__userProps(), this.__failedUserProps)) {\n          return;\n        }\n        if (!this.__needsDidMount) {\n          try {\n            this.logic.componentWillUnmount();\n          } catch (e) {\n            console.error(e);\n          }\n        }\n        this.__makeLogic(Next, this.logic.state);\n        this.__needsDidMount = true;\n      }\n      componentDidMount() {\n        registry.get(this.__name).subs.add(this.__sub);\n        try {\n          this.logic.componentDidMount();\n        } catch (e) {\n          console.error(e);\n        }\n      }\n      componentDidUpdate(prevProps) {\n        this.logic.props = this.__userProps();\n        if (this.__needsDidMount) {\n          if (this.state.__err || !registry.get(this.__name).tpl) return;\n          this.__needsDidMount = false;\n          try {\n            this.logic.componentDidMount();\n          } catch (e) {\n            console.error(e);\n          }\n        } else {\n          try {\n            this.logic.componentDidUpdate(prevProps);\n          } catch (e) {\n            console.error(e);\n          }\n        }\n      }\n      componentWillUnmount() {\n        registry.get(this.__name).subs.delete(this.__sub);\n        if (!this.__needsDidMount) {\n          try {\n            this.logic.componentWillUnmount();\n          } catch (e) {\n            console.error(e);\n          }\n        }\n      }\n      render() {\n        const r = registry.get(this.__name);\n        const cls = \"sc-host\" + (r.htmlStreaming ? \" sc-streaming-html\" : \"\") + (r.jsStreaming ? \" sc-streaming-js\" : \"\");\n        const hintStyle = r.htmlStreaming ? hintToMin(this.props.__hintSize) : void 0;\n        const hostStyle = this.props.__hostStyle || hintStyle ? { ...hintStyle || {}, ...this.props.__hostStyle || {} } : void 0;\n        const hostBase = {\n          className: cls,\n          style: hostStyle,\n          \"data-sc-name\": this.__name,\n          \"data-dc-tpl\": this.props.__tplId\n        };\n        const chain = Array.isArray(this.context) ? this.context : [];\n        if (chain.includes(this.__name)) {\n          const cycle = [\n            ...chain.slice(chain.indexOf(this.__name)),\n            this.__name\n          ].join(\" \\u2192 \");\n          return h(\n            \"div\",\n            { ...hostBase, className: cls + \" sc-has-error\" },\n            h(Placeholder, {\n              name: this.__name,\n              hintSize: this.props.__hintSize,\n              error: \"circular import: \" + cycle\n            })\n          );\n        }\n        if (this.state.__err) {\n          return h(\n            \"div\",\n            { ...hostBase, className: cls + \" sc-has-error\" },\n            h(\n              \"div\",\n              { className: \"sc-logic-error\", \"data-omelette-chrome\": \"\" },\n              this.__name + \": \" + this.state.__err\n            ),\n            h(Placeholder, {\n              name: this.__name,\n              hintSize: this.props.__hintSize,\n              error: this.state.__err\n            })\n          );\n        }\n        this.__reconcileLogic();\n        if (!r.tpl) {\n          return h(\n            \"div\",\n            hostBase,\n            h(Placeholder, { name: this.__name, hintSize: this.props.__hintSize })\n          );\n        }\n        const userProps = this.__userProps();\n        this.logic.props = userProps;\n        let vals = userProps;\n        let renderErr = r.logicError || this.__ctorError;\n        try {\n          vals = { ...userProps, ...this.logic.renderVals() || {} };\n        } catch (e) {\n          console.error(e);\n          renderErr = this.__name + \".renderVals(): \" + (e instanceof Error && e.message ? e.message : String(e));\n        }\n        this.__streamingNow = !!(r.htmlStreaming || r.jsStreaming);\n        this.__htmlStreamingNow = !!r.htmlStreaming;\n        return h(\n          \"div\",\n          { ...hostBase, className: cls + (renderErr ? \" sc-has-error\" : \"\") },\n          renderErr && h(\n            \"div\",\n            { className: \"sc-logic-error\", \"data-omelette-chrome\": \"\" },\n            renderErr\n          ),\n          h(\n            AncestorContext.Provider,\n            { value: [...chain, this.__name] },\n            r.tpl(vals, this)\n          )\n        );\n      }\n    }\n    __publicField(StreamableComponent, \"contextType\", AncestorContext);\n    const named = \/* @__PURE__ *\/ new Map();\n    function getDC(name) {\n      const hit = named.get(name);\n      if (hit) return hit;\n      function Dispatcher(p) {\n        const [, setTick] = React.useState(0);\n        React.useEffect(() => {\n          const sub = () => setTick((n) => n + 1);\n          registry.get(name).subs.add(sub);\n          return () => {\n            registry.get(name).subs.delete(sub);\n          };\n        }, []);\n        ensureFetched(name);\n        return h(StreamableComponent, { ...p, __name: name });\n      }\n      Dispatcher.displayName = name;\n      named.set(name, Dispatcher);\n      return Dispatcher;\n    }\n    return {\n      getDC,\n      StreamableComponent\n    };\n  }\n\n  \/\/ src\/bundled.ts\n  function bundledBlob(url) {\n    const blobs = window.__resourceBlobs;\n    const b = blobs ? blobs[url.split(\"#\")[0]] : void 0;\n    return b instanceof Blob ? b : null;\n  }\n\n  \/\/ src\/cdn.ts\n  var REACT_URL = \"https:\/\/unpkg.com\/react@18.3.1\/umd\/react.production.min.js\";\n  var REACT_SRI = \"sha384-DGyLxAyjq0f9SPpVevD6IgztCFlnMF6oW\/XQGmfe+IsZ8TqEiDrcHkMLKI6fiB\/Z\";\n  var REACT_DOM_URL = \"https:\/\/unpkg.com\/react-dom@18.3.1\/umd\/react-dom.production.min.js\";\n  var REACT_DOM_SRI = \"sha384-gTGxhz21lVGYNMcdJOyq01Edg0jhn\/c22nsx0kyqP0TxaV5WVdsSH1fSDUf5YJj1\";\n  var BABEL_URL = \"https:\/\/unpkg.com\/@babel\/standalone@7.29.0\/babel.min.js\";\n  var BABEL_SRI = \"sha384-m08KidiNqLdpJqLq95G\/LEi8Qvjl\/xUYll3QILypMoQ65QorJ9Lvtp2RXYGBFj1y\";\n  function cdnScriptFor(url, sri) {\n    const res = window.__resources;\n    const v = res ? res[url] : void 0;\n    return typeof v === \"string\" && v ? { src: v } : { src: url, integrity: sri };\n  }\n\n  \/\/ src\/external.ts\n  var isCustomElementName = (n) => !n.includes(\".\") && n.includes(\"-\");\n  function isRenderableType(g) {\n    if (typeof g === \"function\") return !isElementClass(g);\n    return typeof g === \"object\" && g !== null && typeof g.$$typeof === \"symbol\";\n  }\n  function resolveDottedPath(root, name) {\n    let cur = root;\n    for (const seg of name.split(\".\")) {\n      if (cur == null) return void 0;\n      cur = cur[seg];\n    }\n    return cur;\n  }\n  var GLOBAL_POLL_INTERVAL_MS = 50;\n  var GLOBAL_POLL_TIMEOUT_MS = 3e4;\n  function createExternalModules(onResolved) {\n    const cache = \/* @__PURE__ *\/ new Map();\n    let babelLoading = null;\n    const reportedMissing = \/* @__PURE__ *\/ new Map();\n    const polling = \/* @__PURE__ *\/ new Set();\n    function ensureBabel() {\n      if (window.Babel) return Promise.resolve();\n      if (babelLoading) return babelLoading;\n      const babel = cdnScriptFor(BABEL_URL, BABEL_SRI);\n      babelLoading = new Promise((res, rej) => {\n        const s = document.createElement(\"script\");\n        s.src = babel.src;\n        if (babel.integrity) {\n          s.integrity = babel.integrity;\n          s.crossOrigin = \"anonymous\";\n        }\n        s.onload = () => res();\n        s.onerror = rej;\n        document.head.appendChild(s);\n      });\n      return babelLoading;\n    }\n    const pending = \/* @__PURE__ *\/ new Map();\n    function load(kind, url, after) {\n      const existing = pending.get(url);\n      if (existing) return existing;\n      cache.set(url, null);\n      console.info(\"[dc-runtime] x-import: loading\", url, \"(\" + kind + \")\");\n      const ready = Promise.all([\n        kind === \"jsx\" ? ensureBabel() : Promise.resolve(),\n        after ?? Promise.resolve()\n      ]);\n      const p = ready.then(() => {\n        const pre = bundledBlob(url);\n        if (pre) return pre.text();\n        return fetch(url).then((r) => {\n          if (!r.ok) throw new Error(\"HTTP \" + r.status);\n          return r.text();\n        });\n      }).then((src) => {\n        const code = kind === \"jsx\" ? window.Babel.transform(src, {\n          filename: url,\n          presets: [\"react\", \"typescript\"]\n        }).code : src;\n        const module = { exports: {} };\n        const before = new Set(Object.keys(window));\n        \/\/! nosemgrep: eval-and-function-constructor\n        new Function(\"React\", \"module\", \"exports\", \"require\", code)(\n          getReact(),\n          module,\n          module.exports,\n          () => ({})\n        );\n        const globals = {};\n        for (const k of Object.keys(window)) {\n          if (!before.has(k) && typeof window[k] === \"function\") {\n            globals[k] = window[k];\n          }\n        }\n        cache.set(url, { mod: module.exports, globals });\n        console.info(\n          \"[dc-runtime] x-import: loaded\",\n          url,\n          \"\\u2014 exports:\",\n          Object.keys(module.exports),\n          \"window globals:\",\n          Object.keys(globals)\n        );\n        onResolved();\n      }).catch((e) => {\n        cache.set(url, {\n          mod: {},\n          globals: {},\n          error: \"failed to load: \" + (e instanceof Error && e.message ? e.message : String(e))\n        });\n        console.error(\n          \"[dc-runtime] x-import: FAILED to load\",\n          url,\n          \"(\" + kind + \")\",\n          e\n        );\n        onResolved();\n      });\n      pending.set(url, p);\n      return p;\n    }\n    function resolve2(url, name) {\n      const entry = cache.get(url);\n      if (!entry) return null;\n      const { mod, globals } = entry;\n      const C = mod && mod[name] || globals && globals[name] || typeof window !== \"undefined\" && window[name] || mod && mod.default;\n      if (typeof C === \"function\") return C;\n      const key = url + \"\\0\" + name;\n      if (!reportedMissing.has(key)) {\n        reportedMissing.set(\n          key,\n          entry.error || 'no export named \"' + name + '\" (has: ' + Object.keys(mod).join(\", \") + \")\"\n        );\n        console.error(\n          \"[dc-runtime] x-import: module\",\n          url,\n          \"loaded but has no component named\",\n          JSON.stringify(name),\n          \"\\u2014 available exports:\",\n          Object.keys(mod),\n          \"window globals:\",\n          Object.keys(globals),\n          \". The module must `module.exports = {\" + name + \"}` or set `window.\" + name + \"`.\"\n        );\n      }\n      return null;\n    }\n    function waitForGlobal(name) {\n      if (polling.has(name)) return;\n      polling.add(name);\n      const started = Date.now();\n      const isCE = isCustomElementName(name);\n      const tick = () => {\n        const found = isCE ? customElements.get(name) : isRenderableType(resolveDottedPath(window, name));\n        if (found) {\n          polling.delete(name);\n          onResolved();\n          return;\n        }\n        if (Date.now() - started >= GLOBAL_POLL_TIMEOUT_MS) {\n          console.warn(\n            \"[dc-runtime] x-import: global\",\n            JSON.stringify(name),\n            \"never appeared on window after \" + GLOBAL_POLL_TIMEOUT_MS + \"ms\"\n          );\n          return;\n        }\n        setTimeout(tick, GLOBAL_POLL_INTERVAL_MS);\n      };\n      setTimeout(tick, GLOBAL_POLL_INTERVAL_MS);\n    }\n    function resolveGlobal(url, name) {\n      const isCE = isCustomElementName(name);\n      if (!url) {\n        if (isCE) {\n          if (customElements.get(name)) return name;\n          waitForGlobal(name);\n          return null;\n        }\n        const g2 = resolveDottedPath(window, name);\n        if (isRenderableType(g2)) return g2;\n        waitForGlobal(name);\n        return null;\n      }\n      const entry = cache.get(url);\n      if (!entry) return null;\n      if (isCE && customElements.get(name)) return name;\n      const g = entry.globals[name] ?? resolveDottedPath(window, name);\n      if (isRenderableType(g)) return g;\n      if (name.includes(\".\")) return null;\n      const key = url + \"\\0global\\0\" + name;\n      if (!reportedMissing.has(key)) {\n        reportedMissing.set(key, null);\n        if (isCE && !customElements.get(name)) {\n          console.warn(\n            \"[dc-runtime] x-import:\",\n            url,\n            \"loaded but no custom element\",\n            JSON.stringify(name),\n            \"is registered and window.\" + name + \" is not a function \\u2014 rendering <\" + name + \"> as an unknown element.\"\n          );\n        }\n      }\n      return name;\n    }\n    function getError(url, name) {\n      const entry = cache.get(url);\n      if (entry?.error) return entry.error;\n      return reportedMissing.get(url + \"\\0\" + name) || null;\n    }\n    return { load, resolve: resolve2, resolveGlobal, getError };\n  }\n  function isElementClass(g) {\n    try {\n      return typeof g === \"function\" && typeof HTMLElement !== \"undefined\" && g.prototype instanceof HTMLElement;\n    } catch {\n      return false;\n    }\n  }\n\n  \/\/ src\/atomics.ts\n  var ATOMIC_CSS = (\n    \/\/ layout\n    \".fx{display:flex}.col{display:flex;flex-direction:column}.grid{display:grid}.ac{align-items:center}.jc{justify-content:center}.jb{justify-content:space-between}.f1{flex:1}.noshrink{flex-shrink:0}.wrap{flex-wrap:wrap}.fw5{font-weight:500}.fw6{font-weight:600}.fw7{font-weight:700}.fw8{font-weight:800}.fs11{font-size:11px}.fs12{font-size:12px}.fs13{font-size:13px}.fs14{font-size:14px}.fs15{font-size:15px}.fs16{font-size:16px}.fs20{font-size:20px}.fs22{font-size:22px}.upper{text-transform:uppercase}.tc{text-align:center}.nowrap{white-space:nowrap}.gap8{gap:8px}.gap10{gap:10px}.gap12{gap:12px}.gap16{gap:16px}.gap24{gap:24px}.m0{margin:0}.mt8{margin-top:8px}.mt12{margin-top:12px}.mt16{margin-top:16px}.mb8{margin-bottom:8px}.mb12{margin-bottom:12px}.mb16{margin-bottom:16px}.posrel{position:relative}.posabs{position:absolute}.round{border-radius:50%}.ohide{overflow:hidden}.bbox{box-sizing:border-box}.pointer{cursor:pointer}.w100{width:100%}.b0{border:none}\"\n  );\n\n  \/\/ src\/helmet.ts\n  var DESIGN_DOC_MODE_RE = \/<meta\\b[^>]*\\bname\\s*=\\s*[\"']design_doc_mode[\"'][^>]*\\b(?:content|value)\\s*=\\s*[\"'](\\w+)[\"']\/i;\n  var CANVAS_BG_LIGHT = \"#f0eee6\";\n  var CANVAS_BG_DARK = \"#2e2c26\";\n  function createHelmetManager(doc, isStreaming) {\n    const mounted = \/* @__PURE__ *\/ new Set();\n    const live = \/* @__PURE__ *\/ new Map();\n    let designDocMode = null;\n    let canvasStyleEl = null;\n    let appTheme = \"light\";\n    try {\n      const ds = doc.documentElement.dataset.theme;\n      appTheme = ds === \"dark\" || ds === \"light\" ? ds : new URLSearchParams(doc.defaultView?.location.search ?? \"\").get(\n        \"theme\"\n      ) === \"dark\" ? \"dark\" : \"light\";\n    } catch {\n    }\n    function applyCanvasBg() {\n      if (!canvasStyleEl) return;\n      const bg = appTheme === \"dark\" ? CANVAS_BG_DARK : CANVAS_BG_LIGHT;\n      canvasStyleEl.textContent = `html,body{background:${bg}}#dc-root>.sc-host{position:relative}`;\n    }\n    function postDesignMode(mode) {\n      if (window.parent === window) return;\n      try {\n        window.parent.postMessage({ type: \"__dc_design_mode\", mode }, \"*\");\n      } catch {\n      }\n    }\n    function setDesignDocMode(mode) {\n      if (mode === designDocMode) return;\n      designDocMode = mode;\n      postDesignMode(mode);\n      if (mode === \"canvas\") {\n        doc.documentElement.setAttribute(\"data-dc-canvas\", \"\");\n        canvasStyleEl = doc.createElement(\"style\");\n        canvasStyleEl.setAttribute(\"data-dc-canvas\", \"\");\n        applyCanvasBg();\n        doc.head.appendChild(canvasStyleEl);\n      } else {\n        doc.documentElement.removeAttribute(\"data-dc-canvas\");\n        canvasStyleEl?.remove();\n        canvasStyleEl = null;\n      }\n    }\n    window.addEventListener(\"message\", (e) => {\n      const type = e.data && e.data.type;\n      if (type === \"__dc_theme\") {\n        const t = e.data.theme;\n        if (t === \"light\" || t === \"dark\") {\n          appTheme = t;\n          applyCanvasBg();\n        }\n        return;\n      }\n      if (!designDocMode || type !== \"__dc_probe\") return;\n      postDesignMode(designDocMode);\n    });\n    function compile(node) {\n      const raw = [...node.children];\n      const helmetClosed = node.nextSibling != null || node.parentNode?.nextSibling != null;\n      if (node.hasAttribute(\"data-dc-atomics\") && !mounted.has(\"__dc-atomics\")) {\n        mounted.add(\"__dc-atomics\");\n        const el = doc.createElement(\"style\");\n        el.id = \"__dc-atomics\";\n        el.textContent = ATOMIC_CSS;\n        doc.head.appendChild(el);\n      }\n      return (_vals, ctx) => {\n        const name = ctx && ctx.__name || \"\";\n        const streaming = !!(name && isStreaming(name));\n        for (let i = 0; i < raw.length; i++) {\n          const child = raw[i];\n          const tag = child.tagName;\n          const mayBePartial = streaming && !helmetClosed && i === raw.length - 1;\n          if (tag === \"SCRIPT\") {\n            if (mayBePartial) continue;\n            const key = \"SCRIPT|\" + (child.getAttribute(\"src\") || child.textContent || \"\");\n            if (mounted.has(key)) continue;\n            mounted.add(key);\n            const el = doc.createElement(\"script\");\n            for (const { name: an, value } of [...child.attributes])\n              el.setAttribute(an, value);\n            if (child.textContent) el.textContent = child.textContent;\n            doc.head.appendChild(el);\n          } else if (tag === \"LINK\" || tag === \"META\") {\n            if (mayBePartial) continue;\n            const key = tag + \"|\" + (child.getAttribute(\"href\") || child.getAttribute(\"src\") || child.outerHTML);\n            if (mounted.has(key)) continue;\n            mounted.add(key);\n            if (tag === \"LINK\") {\n              const rel = (child.getAttribute(\"rel\") || \"\").toLowerCase().split(\/\\s+\/);\n              const href = (child.getAttribute(\"href\") || \"\").trim();\n              const res = window.__resources;\n              const pre = res && rel.includes(\"stylesheet\") && !rel.includes(\"alternate\") ? res[href] : void 0;\n              const blob = typeof pre === \"string\" && pre ? bundledBlob(pre) : null;\n              if (blob) {\n                const el = doc.createElement(\"style\");\n                if (child.hasAttribute(\"disabled\")) {\n                  el.setAttribute(\"media\", \"not all\");\n                } else if (child.getAttribute(\"media\")) {\n                  el.setAttribute(\"media\", child.getAttribute(\"media\"));\n                }\n                if (child.getAttribute(\"title\"))\n                  el.setAttribute(\"title\", child.getAttribute(\"title\"));\n                void blob.text().then((css) => {\n                  el.textContent = css;\n                });\n                doc.head.appendChild(el);\n                continue;\n              }\n            }\n            doc.head.appendChild(child.cloneNode(true));\n          } else {\n            const key = name + \"|\" + i;\n            let el = live.get(key);\n            if (!el || el.tagName !== tag) {\n              if (el) el.remove();\n              el = doc.createElement(tag.toLowerCase());\n              live.set(key, el);\n              doc.head.appendChild(el);\n            }\n            for (const { name: an, value } of [...child.attributes]) {\n              if (el.getAttribute(an) !== value) el.setAttribute(an, value);\n            }\n            if (el.textContent !== child.textContent)\n              el.textContent = child.textContent;\n          }\n        }\n        return null;\n      };\n    }\n    return { compile, setDesignDocMode };\n  }\n\n  \/\/ src\/pseudo.ts\n  function scanUnquotedUrl(css, i) {\n    if (css[i] !== \"u\" && css[i] !== \"U\" || css.slice(i, i + 4).toLowerCase() !== \"url(\" || \/[a-z0-9_-]\/i.test(css[i - 1] ?? \"\")) {\n      return -1;\n    }\n    let j = i + 4;\n    while (j < css.length && \/\\s\/.test(css[j])) j++;\n    if (css[j] === '\"' || css[j] === \"'\") return -1;\n    while (j < css.length && css[j] !== \")\") {\n      if (css[j] === \"\\\\\") j++;\n      j++;\n    }\n    return j < css.length ? j + 1 : css.length;\n  }\n  function stripComments(css) {\n    let out = \"\";\n    let quote = \"\";\n    for (let i = 0; i < css.length; i++) {\n      const c = css[i];\n      if (quote) {\n        if (c === \"\\\\\") {\n          out += c + (css[i + 1] ?? \"\");\n          i++;\n          continue;\n        }\n        if (c === quote) quote = \"\";\n        out += c;\n      } else if (c === \"'\" || c === '\"') {\n        quote = c;\n        out += c;\n      } else if (c === \"\/\" && css[i + 1] === \"*\") {\n        const end = css.indexOf(\"*\/\", i + 2);\n        i = end === -1 ? css.length : end + 1;\n        out += \" \";\n      } else {\n        const end = scanUnquotedUrl(css, i);\n        if (end === -1) out += c;\n        else {\n          out += css.slice(i, end);\n          i = end - 1;\n        }\n      }\n    }\n    return out;\n  }\n  function importantify(css) {\n    css = stripComments(css);\n    const decls = [];\n    let start = 0;\n    let depth = 0;\n    let quote = \"\";\n    for (let i = 0; i < css.length; i++) {\n      const c = css[i];\n      if (quote) {\n        if (c === \"\\\\\") i++;\n        else if (c === quote) quote = \"\";\n      } else if (c === \"'\" || c === '\"') quote = c;\n      else if (c === \"(\") depth++;\n      else if (c === \")\") depth = Math.max(0, depth - 1);\n      else if (c === \";\" && depth === 0) {\n        decls.push(css.slice(start, i));\n        start = i + 1;\n      } else {\n        const end = scanUnquotedUrl(css, i);\n        if (end !== -1) i = end - 1;\n      }\n    }\n    decls.push(css.slice(start));\n    return decls.map((d) => d.trim()).filter(Boolean).map((d) => \/!\\s*important$\/i.test(d) ? d : d + \" !important\").join(\";\");\n  }\n  function createPseudoSheet(doc) {\n    let el = null;\n    const cache = \/* @__PURE__ *\/ new Map();\n    let n = 0;\n    return (pseudo, css) => {\n      const k = pseudo + \"|\" + css;\n      const hit = cache.get(k);\n      if (hit) return hit;\n      if (!el) {\n        el = doc.createElement(\"style\");\n        doc.head.appendChild(el);\n      }\n      const cls = \"scp\" + (n++).toString(36);\n      const isPseudoElement = pseudo === \"before\" || pseudo === \"after\";\n      const sel = isPseudoElement ? \".\" + cls + \"::\" + pseudo : \".\" + cls + \":\" + pseudo;\n      el.sheet.insertRule(\n        sel + \"{\" + (isPseudoElement ? css : importantify(css)) + \"}\",\n        el.sheet.cssRules.length\n      );\n      cache.set(k, cls);\n      return cls;\n    };\n  }\n\n  \/\/ src\/registry.ts\n  function createRegistry() {\n    const entries = \/* @__PURE__ *\/ Object.create(null);\n    function get(name) {\n      return entries[name] || (entries[name] = {\n        html: \"\",\n        tpl: null,\n        Logic: null,\n        jsStreaming: false,\n        htmlStreaming: false,\n        ver: 0,\n        subs: \/* @__PURE__ *\/ new Set(),\n        fetched: false\n      });\n    }\n    function bump(name) {\n      const r = get(name);\n      r.ver++;\n      for (const fn of r.subs) fn();\n    }\n    return {\n      entries,\n      get,\n      bump,\n      bumpAll() {\n        for (const n in entries) bump(n);\n      }\n    };\n  }\n\n  \/\/ src\/runtime.ts\n  var COMPONENT_DIR = \".\";\n  function createRuntime(doc = document) {\n    const registry = createRegistry();\n    const pseudoClass = createPseudoSheet(doc);\n    const helmet = createHelmetManager(\n      doc,\n      (name) => registry.get(name).htmlStreaming\n    );\n    const external = createExternalModules(() => registry.bumpAll());\n    const factory = createComponentFactory(registry, ensureFetched);\n    const host = {\n      component: (name) => factory.getDC(name),\n      placeholder: (props) => h(Placeholder, props),\n      helmet: (node) => helmet.compile(node),\n      loadExternal: (kind, url, after) => external.load(kind, url, after),\n      resolveExternal: (url, name) => external.resolve(url, name),\n      resolveExternalGlobal: (url, name) => external.resolveGlobal(url, name),\n      resolveExternalError: (url, name) => external.getError(url, name),\n      pseudoClass\n    };\n    function ensureFetched(name) {\n      const r = registry.get(name);\n      if (r.fetched) return;\n      r.fetched = true;\n      const url = COMPONENT_DIR + \"\/\" + encodeURIComponent(name) + \".dc.html\";\n      const res = window.__resources;\n      const pre = res ? res[url] : void 0;\n      const target = typeof pre === \"string\" && pre ? pre : url;\n      const blob = bundledBlob(target);\n      (blob ? blob.text() : fetch(target).then((res2) => {\n        if (!res2.ok) {\n          console.error(\n            '[dc-runtime] sibling fetch for \"' + name + '\" failed:',\n            url,\n            \"returned\",\n            res2.status,\n            \"\\u2014 the reference renders as an empty placeholder.\"\n          );\n          return \"\";\n        }\n        return res2.text();\n      })).then((t) => {\n        if (!t) return;\n        const parsed = parseDcText(t);\n        if (!parsed) {\n          console.error(\n            '[dc-runtime] sibling fetch for \"' + name + '\":',\n            url,\n            \"has no <x-dc> block \\u2014 not a Design Component.\"\n          );\n          return;\n        }\n        if (parsed.props) r.propsMeta = parsed.props;\n        if (parsed.preview) r.preview = parsed.preview;\n        if (parsed.template && !r.html) updateHtml(name, parsed.template);\n        if (parsed.js && !r.Logic) updateJs(name, parsed.js);\n      }).catch(\n        (e) => console.error(\n          '[dc-runtime] sibling fetch for \"' + name + '\" threw:',\n          url,\n          e\n        )\n      );\n    }\n    let rootName = null;\n    function updateHtml(name, html) {\n      const r = registry.get(name);\n      r.html = html;\n      if (name === rootName) {\n        const mode = DESIGN_DOC_MODE_RE.exec(html)?.[1] ?? null;\n        if (mode || !r.htmlStreaming) helmet.setDesignDocMode(mode);\n      }\n      try {\n        r.tpl = compileTemplate(html, host);\n      } catch (e) {\n        console.error(\"[dc-runtime] template compile FAILED for\", name, e);\n      }\n      registry.bump(name);\n    }\n    function updateJs(name, src) {\n      const r = registry.get(name);\n      const seq = r.jsSeq = (r.jsSeq || 0) + 1;\n      try {\n        const Cls = evalDcLogic(src);\n        if (r.jsSeq !== seq) return;\n        if (typeof Cls !== \"function\") {\n          r.logicError = name + \".dc.html: <script data-dc-script> must define `class Component extends DCLogic`\";\n        } else {\n          r.logicError = null;\n          r.Logic = Cls;\n        }\n      } catch (e) {\n        if (r.jsSeq !== seq) return;\n        console.error(\n          \"[dc-runtime] logic class eval FAILED for\",\n          name,\n          \"\\u2014 the template renders with props only.\",\n          e\n        );\n        r.logicError = name + \": \" + (e instanceof Error && e.message ? e.message : String(e));\n      }\n      registry.bump(name);\n    }\n    function setStreaming(name, kind, on) {\n      const r = registry.get(name);\n      if (kind === \"html\") r.htmlStreaming = !!on;\n      else r.jsStreaming = !!on;\n      let any = false;\n      for (const n in registry.entries) {\n        const e = registry.entries[n];\n        if (e && (e.htmlStreaming || e.jsStreaming)) {\n          any = true;\n          break;\n        }\n      }\n      doc.documentElement.classList.toggle(\"sc-dc-streaming\", any);\n      registry.bump(name);\n    }\n    function dcUpdate(name, kind, content, streaming) {\n      if (streaming) registry.get(name).fetched = true;\n      if (kind === \"html\") {\n        setStreaming(name, \"html\", !!streaming);\n        updateHtml(name, content);\n      } else if (kind === \"js\") {\n        setStreaming(name, \"js\", !!streaming);\n        if (!streaming) updateJs(name, content);\n      } else if (kind === \"props\") {\n        const { props, preview } = parseDataProps(content);\n        const r = registry.get(name);\n        r.propsMeta = props ?? void 0;\n        r.preview = preview;\n        registry.bump(name);\n      }\n    }\n    function setProps(name, overrides) {\n      registry.get(name).propOverrides = overrides && typeof overrides === \"object\" ? { ...overrides } : null;\n      registry.bump(name);\n    }\n    function adoptParsed(name, parsed) {\n      if (!parsed) return;\n      const r = registry.get(name);\n      if (parsed.props) r.propsMeta = parsed.props;\n      if (parsed.preview) r.preview = parsed.preview;\n      if (parsed.template) updateHtml(name, parsed.template);\n      if (parsed.js) updateJs(name, parsed.js);\n    }\n    return {\n      registry,\n      getDC: factory.getDC,\n      updateHtml,\n      updateJs,\n      dcUpdate,\n      setProps,\n      adoptParsed,\n      setRootName: (name) => {\n        rootName = name;\n      },\n      markFetched: (name) => {\n        registry.get(name).fetched = true;\n      },\n      annotatedTemplate: (name) => {\n        const r = registry.get(name);\n        return r.tpl && r.tpl.__annotated || null;\n      },\n      templateSource: (name) => registry.get(name).html || null,\n      StreamableLogic\n    };\n  }\n\n  \/\/ src\/stream-state.ts\n  function createStreamTracker(staleMs = 6e4, now = Date.now) {\n    const since = \/* @__PURE__ *\/ new Map();\n    const liveOne = (n) => {\n      const t = since.get(n);\n      if (t === void 0) return false;\n      if (now() - t > staleMs) {\n        since.delete(n);\n        return false;\n      }\n      return true;\n    };\n    return {\n      push(name, streaming, viewportKey) {\n        if (viewportKey === \"dc-model\") return;\n        if (streaming) since.set(name, now());\n        else since.delete(name);\n      },\n      live(name) {\n        if (name !== void 0) return liveOne(name);\n        for (const n of [...since.keys()]) if (liveOne(n)) return true;\n        return false;\n      }\n    };\n  }\n\n  \/\/ src\/index.ts\n  function hideRawTemplate() {\n    const s = document.createElement(\"style\");\n    s.textContent = \"x-dc{display:none!important}\";\n    document.head.appendChild(s);\n  }\n  function loadScript(src, integrity) {\n    return new Promise((resolve2, reject) => {\n      \/\/! nosemgrep: create-script-element\n      const s = document.createElement(\"script\");\n      s.src = src;\n      if (integrity) {\n        s.integrity = integrity;\n        s.crossOrigin = \"anonymous\";\n      }\n      s.async = false;\n      s.onload = () => resolve2();\n      s.onerror = () => reject(new Error(`failed to load ${src}`));\n      document.head.appendChild(s);\n    });\n  }\n  function loadReactUmd() {\n    const w = window;\n    if (w.React && w.ReactDOM) return Promise.resolve();\n    const react = cdnScriptFor(REACT_URL, REACT_SRI);\n    const reactDom = cdnScriptFor(REACT_DOM_URL, REACT_DOM_SRI);\n    return Promise.all([\n      loadScript(react.src, react.integrity),\n      loadScript(reactDom.src, reactDom.integrity)\n    ]).then(() => void 0);\n  }\n  function init() {\n    const runtime = createRuntime(document);\n    let rootName = \"Root\";\n    const baseCss = document.createElement(\"style\");\n    baseCss.textContent = BASE_CSS;\n    document.head.prepend(baseCss);\n    const notifyHost = () => {\n      if (window.parent === window) return;\n      const r = runtime.registry.entries[rootName];\n      try {\n        window.parent.postMessage(\n          {\n            type: \"__dc_booted\",\n            rootName,\n            propsMeta: r && r.propsMeta || null,\n            preview: r && r.preview || null\n          },\n          \"*\"\n        );\n      } catch {\n      }\n    };\n    const streams = createStreamTracker();\n    const api = {\n      __dcUpdate: (name, kind, content, streaming, viewportKey) => {\n        streams.push(name, streaming, viewportKey);\n        runtime.dcUpdate(name, kind, content, streaming);\n        if (name === rootName && !streaming && kind === \"props\") notifyHost();\n      },\n      __dcStreaming: (name) => streams.live(name),\n      __dcSetProps: (name, overrides) => runtime.setProps(name, overrides),\n      \/** Name of the component currently mounted as the page root \u2014 DC tools\n       *  push their template-stream here when targeting \"the open page\". *\/\n      __dcRootName: () => rootName,\n      \/** Editor bridge \u2014 the encoded, `data-dc-tpl`-annotated template source.\n       *  The host editor parses this into its own template DOM so it can map a\n       *  rendered node (carrying the same `data-dc-tpl`) back to the source\n       *  node that emitted it. Returns the encoded form (`sc-camel-*` attrs,\n       *  `<sc-raw-*>`\/`<sc-helmet>` tags); the editor decodes on serialize. *\/\n      __dcAnnotatedTemplate: (name) => runtime.annotatedTemplate(name),\n      \/** Editor bridge \u2014 the *original* (decoded) template source. *\/\n      __dcTemplateSource: (name) => runtime.templateSource(name),\n      __dcBoot: () => {\n        rootName = boot(runtime, document) ?? rootName;\n        notifyHost();\n      },\n      __dcRegistry: runtime.registry.entries,\n      getDC: (name) => runtime.getDC(name),\n      \/\/ `DCLogic` is the documented base class name; `StreamableLogic` is the\n      \/\/ implementation alias kept for any project that already references it.\n      DCLogic: runtime.StreamableLogic,\n      StreamableLogic: runtime.StreamableLogic\n    };\n    Object.assign(window, api);\n    window.__dcContentKeyed = true;\n    if (document.readyState !== \"loading\") api.__dcBoot();\n    else document.addEventListener(\"DOMContentLoaded\", () => api.__dcBoot());\n  }\n  hideRawTemplate();\n  loadReactUmd().then(init).catch((err) => {\n    console.error(\"[dc] failed to load React or boot:\", err);\n    throw err;\n  });\n})();\n\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>okalura Work Why us Process Pricing FAQ See our work Start your project Creative production studio Your Products. Styled to Sell. We are a creative production team that transforms your product photos into premium lifestyle images using AI-assisted workflows. From fashion and footwear to accessories and ecommerce products, we create realistic visuals ready for your [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_canvas","meta":{"footnotes":""},"class_list":["post-10","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/okalura.com\/index.php?rest_route=\/wp\/v2\/pages\/10","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/okalura.com\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/okalura.com\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/okalura.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/okalura.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=10"}],"version-history":[{"count":16,"href":"https:\/\/okalura.com\/index.php?rest_route=\/wp\/v2\/pages\/10\/revisions"}],"predecessor-version":[{"id":57,"href":"https:\/\/okalura.com\/index.php?rest_route=\/wp\/v2\/pages\/10\/revisions\/57"}],"wp:attachment":[{"href":"https:\/\/okalura.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=10"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}