changes since conversation categories and layout fixes andshop

This commit is contained in:
Dorian
2026-04-24 13:05:03 +01:00
parent 7a6f84cb25
commit 2707036b61
93 changed files with 1109 additions and 333 deletions

View File

@@ -1 +0,0 @@
import{C as e,T as t,c as n,j as r,l as i,lt as a,p as o,r as s,s as c,st as l,u}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as d}from"./_plugin-vue_export-helper-BOai-rQB.js";import{t as f}from"./Badge-DcvgVKep.js";var p={id:`about`,class:`bg-cream text-ink`},m={class:`mx-auto w-full max-w-6xl px-6 py-16 sm:px-8 sm:py-20 md:px-12 md:py-24 lg:px-16 lg:py-28`},h={class:`flex flex-col items-center text-center gap-4 max-w-3xl mx-auto`},g={key:1,class:`font-display font-normal leading-[1.05] tracking-tight text-ink`,style:{"font-size":`clamp(2.25rem, 5vw, 3.75rem)`}},_={key:2,class:`text-lg leading-relaxed text-muted max-w-2xl`},v={key:0,class:`timeline-track hidden md:grid md:grid-cols-3 mt-16`,"aria-hidden":`true`},y={key:1,class:`timeline-list mt-6 md:mt-8 grid gap-0 md:gap-6 md:grid-cols-3`},b={class:`timeline-mobile-marker`},x=d({__name:`About`,props:{eyebrow:{type:String,default:``},headline:{type:String,default:``},sub:{type:String,default:``},milestones:{type:Array,default:()=>[],validator:e=>e.every(e=>e&&typeof e==`object`&&typeof e.year==`string`&&typeof e.title==`string`&&typeof e.text==`string`)}},setup(d){let x=[{card:`bg-cream border-line`,title:`text-ink`,body:`text-muted`,pill:`pill-paper`},{card:`bg-paper border-line`,title:`text-ink`,body:`text-muted`,pill:`pill-brand-soft`},{card:`bg-brand border-transparent`,title:`text-cream`,body:`text-cream/80`,pill:`pill-accent`}];return(S,C)=>(e(),u(`section`,p,[c(`div`,m,[c(`div`,h,[d.eyebrow?(e(),n(f,{key:0,variant:`brand`},{default:r(()=>[o(a(d.eyebrow),1)]),_:1})):i(``,!0),d.headline?(e(),u(`h2`,g,a(d.headline),1)):i(``,!0),d.sub?(e(),u(`p`,_,a(d.sub),1)):i(``,!0)]),d.milestones.length?(e(),u(`div`,v,[(e(!0),u(s,null,t(d.milestones.slice(0,3),(t,n)=>(e(),u(`div`,{key:`track-`+n,class:`timeline-cell`},[c(`span`,{class:l([`timeline-pill`,x[n].pill])},a(t.year),3)]))),128))])):i(``,!0),d.milestones.length?(e(),u(`ol`,y,[(e(!0),u(s,null,t(d.milestones.slice(0,3),(t,n)=>(e(),u(`li`,{key:t.year+t.title,class:`timeline-item flex flex-col`},[c(`div`,b,[c(`span`,{class:l([`timeline-pill`,x[n].pill])},a(t.year),3)]),c(`div`,{class:l([`flex flex-col gap-3 rounded-md border p-6 md:p-7`,x[n].card])},[c(`h3`,{class:l([`font-display text-2xl font-normal leading-tight`,x[n].title])},a(t.title),3),c(`p`,{class:l([`text-sm leading-relaxed`,x[n].body])},a(t.text),3)],2)]))),128))])):i(``,!0)])]))}},[[`__scopeId`,`data-v-39877af8`]]);export{x as t};

View File

@@ -1 +1 @@
.timeline-pill[data-v-39877af8]{border-radius:var(--radius-pill);font-family:var(--font-sans);letter-spacing:var(--tracking-eyebrow);text-transform:uppercase;white-space:nowrap;z-index:1;border:1px solid #0000;justify-content:center;align-items:center;padding:.375rem .875rem;font-size:.75rem;font-weight:700;display:inline-flex;position:relative}.pill-paper[data-v-39877af8]{background:var(--color-paper);color:var(--color-brand);border-color:var(--color-line-strong)}.pill-brand-soft[data-v-39877af8]{background:color-mix(in srgb, var(--color-brand) 14%, var(--color-cream));color:var(--color-brand);border-color:color-mix(in srgb, var(--color-brand) 28%, transparent)}.pill-accent[data-v-39877af8]{background:var(--color-accent);color:var(--color-brand);border-color:color-mix(in srgb, var(--color-accent) 70%, var(--color-brand))}.timeline-track[data-v-39877af8]{align-items:center;margin-bottom:.5rem;position:relative}.timeline-track[data-v-39877af8]:before{content:"";background:var(--color-line-strong);height:1px;position:absolute;top:50%;left:16.6667%;right:16.6667%;transform:translateY(-.5px)}.timeline-cell[data-v-39877af8]{justify-content:center;display:flex}@media (width<=767px){.timeline-mobile-marker[data-v-39877af8]{justify-content:center;align-items:center;padding:1.75rem 0;display:flex;position:relative}.timeline-mobile-marker[data-v-39877af8]:before{content:"";background:var(--color-line-strong);width:1px;position:absolute;top:0;bottom:50%;left:50%;transform:translate(-.5px)}.timeline-mobile-marker[data-v-39877af8]:after{content:"";background:var(--color-line-strong);width:1px;position:absolute;top:50%;bottom:0;left:50%;transform:translate(-.5px)}.timeline-item:first-child .timeline-mobile-marker[data-v-39877af8]:before{display:none}}@media (width>=768px){.timeline-mobile-marker[data-v-39877af8]{display:none}}
.timeline-pill[data-v-7d574710]{border-radius:var(--radius-pill);font-family:var(--font-sans);letter-spacing:var(--tracking-eyebrow);text-transform:uppercase;white-space:nowrap;z-index:1;border:1px solid #0000;justify-content:center;align-items:center;padding:.375rem .875rem;font-size:.75rem;font-weight:700;display:inline-flex;position:relative}.pill-paper[data-v-7d574710]{background:var(--color-paper);color:var(--color-brand);border-color:var(--color-line-strong)}.pill-brand-soft[data-v-7d574710]{background:color-mix(in srgb, var(--color-brand) 14%, var(--color-cream));color:var(--color-brand);border-color:color-mix(in srgb, var(--color-brand) 28%, transparent)}.pill-accent[data-v-7d574710]{background:var(--color-accent);color:var(--color-brand);border-color:color-mix(in srgb, var(--color-accent) 70%, var(--color-brand))}.timeline-track[data-v-7d574710]{align-items:center;margin-bottom:.5rem;position:relative}.timeline-track[data-v-7d574710]:before{content:"";background:var(--color-line-strong);height:1px;position:absolute;top:50%;left:16.6667%;right:16.6667%;transform:translateY(-.5px)}.timeline-cell[data-v-7d574710]{justify-content:center;display:flex}@media (width<=767px){.timeline-mobile-marker[data-v-7d574710]{justify-content:center;align-items:center;padding:1.75rem 0;display:flex;position:relative}.timeline-mobile-marker[data-v-7d574710]:before{content:"";background:var(--color-line-strong);width:1px;position:absolute;top:0;bottom:50%;left:50%;transform:translate(-.5px)}.timeline-mobile-marker[data-v-7d574710]:after{content:"";background:var(--color-line-strong);width:1px;position:absolute;top:50%;bottom:0;left:50%;transform:translate(-.5px)}.timeline-item:first-child .timeline-mobile-marker[data-v-7d574710]:before{display:none}}@media (width>=768px){.timeline-mobile-marker[data-v-7d574710]{display:none}}

1
dist/assets/About-rqnuePZN.js vendored Normal file
View File

@@ -0,0 +1 @@
import{C as e,T as t,c as n,j as r,l as i,lt as a,p as o,r as s,s as c,st as l,u}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as d}from"./_plugin-vue_export-helper-BOai-rQB.js";import{t as f}from"./Badge-DcvgVKep.js";var p={id:`about`,class:`bg-cream text-ink`},m={class:`mx-auto w-full max-w-6xl px-6 py-16 sm:px-8 sm:py-20 md:px-12 md:py-24 lg:px-16 lg:py-28`},h={class:`flex flex-col items-center text-center gap-4 max-w-3xl mx-auto`},g={key:1,class:`font-display font-normal leading-[1.05] tracking-tight text-ink text-headline-lg`},_={key:2,class:`text-lg leading-relaxed text-muted max-w-2xl`},v={key:0,class:`timeline-track hidden md:grid md:grid-cols-3 mt-16`,"aria-hidden":`true`},y={key:1,class:`timeline-list mt-6 md:mt-8 grid gap-0 md:gap-6 md:grid-cols-3`},b={class:`timeline-mobile-marker`},x=d({__name:`About`,props:{eyebrow:{type:String,default:``},headline:{type:String,default:``},sub:{type:String,default:``},milestones:{type:Array,default:()=>[],validator:e=>e.every(e=>e&&typeof e==`object`&&typeof e.year==`string`&&typeof e.title==`string`&&typeof e.text==`string`)}},setup(d){let x=[{card:`bg-cream border-line`,title:`text-ink`,body:`text-muted`,pill:`pill-paper`},{card:`bg-paper border-line`,title:`text-ink`,body:`text-muted`,pill:`pill-brand-soft`},{card:`bg-brand border-transparent`,title:`text-cream`,body:`text-cream/80`,pill:`pill-accent`}];return(S,C)=>(e(),u(`section`,p,[c(`div`,m,[c(`div`,h,[d.eyebrow?(e(),n(f,{key:0,variant:`brand`},{default:r(()=>[o(a(d.eyebrow),1)]),_:1})):i(``,!0),d.headline?(e(),u(`h2`,g,a(d.headline),1)):i(``,!0),d.sub?(e(),u(`p`,_,a(d.sub),1)):i(``,!0)]),d.milestones.length?(e(),u(`div`,v,[(e(!0),u(s,null,t(d.milestones.slice(0,3),(t,n)=>(e(),u(`div`,{key:`track-`+n,class:`timeline-cell`},[c(`span`,{class:l([`timeline-pill`,x[n].pill])},a(t.year),3)]))),128))])):i(``,!0),d.milestones.length?(e(),u(`ol`,y,[(e(!0),u(s,null,t(d.milestones.slice(0,3),(t,n)=>(e(),u(`li`,{key:t.year+t.title,class:`timeline-item flex flex-col md:h-full`},[c(`div`,b,[c(`span`,{class:l([`timeline-pill`,x[n].pill])},a(t.year),3)]),c(`div`,{class:l([`flex flex-col gap-3 rounded-md border p-6 md:p-7 md:flex-1 md:h-full`,x[n].card])},[c(`h3`,{class:l([`font-display text-2xl font-normal leading-tight`,x[n].title])},a(t.title),3),c(`p`,{class:l([`text-sm leading-relaxed`,x[n].body])},a(t.text),3)],2)]))),128))])):i(``,!0)])]))}},[[`__scopeId`,`data-v-7d574710`]]);export{x as t};

View File

@@ -1 +1 @@
import{C as e,G as t,m as n,o as r,u as i}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as a}from"./i18n-DrTQks20.js";import{t as o}from"./About--uXlb06p.js";var s={class:`min-h-screen bg-cream`},c={__name:`AboutPreview`,setup(c){let{t:l}=a(),u=r(()=>[1,2,3].map(e=>({year:l(`about.milestone.${e}.year`),title:l(`about.milestone.${e}.title`),text:l(`about.milestone.${e}.text`)})));return(r,a)=>(e(),i(`div`,s,[n(o,{eyebrow:t(l)(`about.eyebrow`),headline:t(l)(`about.headline`),sub:t(l)(`about.sub`),milestones:u.value},null,8,[`eyebrow`,`headline`,`sub`,`milestones`])]))}};export{c as default};
import{C as e,G as t,m as n,o as r,u as i}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as a}from"./i18n-CJQl3WLC.js";import{t as o}from"./About-rqnuePZN.js";var s={class:`min-h-screen bg-cream`},c={__name:`AboutPreview`,setup(c){let{t:l}=a(),u=r(()=>[1,2,3].map(e=>({year:l(`about.milestone.${e}.year`),title:l(`about.milestone.${e}.title`),text:l(`about.milestone.${e}.text`)})));return(r,a)=>(e(),i(`div`,s,[n(o,{eyebrow:t(l)(`about.eyebrow`),headline:t(l)(`about.headline`),sub:t(l)(`about.sub`),milestones:u.value},null,8,[`eyebrow`,`headline`,`sub`,`milestones`])]))}};export{c as default};

View File

@@ -1,4 +1,4 @@
import{C as e,G as t,c as n,j as r,lt as i,m as a,p as o,s}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as c}from"./i18n-DrTQks20.js";import{t as l}from"./SectionShell-BEISUYi8.js";import{t as u}from"./DevicePreview-DvIWByfU.js";var d={class:`eyebrow mb-5`},f=`/design/preview/about`,p={__name:`AboutSection`,setup(p){let{t:m}=c();return(c,p)=>(e(),n(l,{eyebrow:t(m)(`ds.eyebrow.components`),title:t(m)(`ds.about.title`),description:t(m)(`ds.about.description`),wide:``},{default:r(()=>[s(`section`,null,[a(u,{src:f,initial:`desktop`,height:820})]),s(`section`,null,[s(`h2`,d,i(t(m)(`ds.heading.usage`)),1),p[0]||=s(`div`,{class:`rounded-md border border-line bg-paper p-6 font-mono text-[12px] text-ink`},[s(`pre`,{class:`whitespace-pre-wrap`},`<About
import{C as e,G as t,c as n,j as r,lt as i,m as a,p as o,s}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as c}from"./i18n-CJQl3WLC.js";import{t as l}from"./SectionShell-Cd_Fu3uI.js";import{t as u}from"./DevicePreview-Dx8DzWeH.js";var d={class:`eyebrow mb-5`},f=`/design/preview/about`,p={__name:`AboutSection`,setup(p){let{t:m}=c();return(c,p)=>(e(),n(l,{eyebrow:t(m)(`ds.eyebrow.components`),title:t(m)(`ds.about.title`),description:t(m)(`ds.about.description`),wide:``},{default:r(()=>[s(`section`,null,[a(u,{src:f,initial:`desktop`,height:820})]),s(`section`,null,[s(`h2`,d,i(t(m)(`ds.heading.usage`)),1),p[0]||=s(`div`,{class:`rounded-md border border-line bg-paper p-6 font-mono text-[12px] text-ink`},[s(`pre`,{class:`whitespace-pre-wrap`},`<About
:eyebrow="t('about.eyebrow')"
:headline="t('about.headline')"
:sub="t('about.sub')"

View File

@@ -1 +1 @@
import{C as e,G as t,c as n,j as r,lt as i,m as a,p as o,s}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as c}from"./i18n-DrTQks20.js";import{t as l}from"./Badge-DcvgVKep.js";import{t as u}from"./SectionShell-BEISUYi8.js";import{t as d}from"./Card-DM27vc3f.js";var f={class:`eyebrow mb-5`},p={class:`flex flex-wrap gap-3`},m={class:`eyebrow mb-5`},h={class:`flex flex-wrap gap-3`},g={__name:`BadgesSection`,setup(g){let{t:_}=c();return(c,g)=>(e(),n(u,{eyebrow:t(_)(`ds.eyebrow.components`),title:t(_)(`ds.badges.title`),description:t(_)(`ds.badges.description`)},{default:r(()=>[s(`section`,null,[s(`h2`,f,i(t(_)(`ds.heading.variants`)),1),a(d,{tone:`paper`},{default:r(()=>[s(`div`,p,[a(l,{variant:`neutral`},{default:r(()=>[o(i(t(_)(`ds.badges.neutral`)),1)]),_:1}),a(l,{variant:`brand`},{default:r(()=>[o(i(t(_)(`ds.badges.brand`)),1)]),_:1}),a(l,{variant:`accent`},{default:r(()=>[o(i(t(_)(`ds.badges.accent`)),1)]),_:1}),a(l,{variant:`subtle`},{default:r(()=>[o(i(t(_)(`ds.badges.subtle`)),1)]),_:1}),a(l,{variant:`success`},{default:r(()=>[o(i(t(_)(`ds.badges.success`)),1)]),_:1}),a(l,{variant:`warning`},{default:r(()=>[o(i(t(_)(`ds.badges.warning`)),1)]),_:1}),a(l,{variant:`danger`},{default:r(()=>[o(i(t(_)(`ds.badges.danger`)),1)]),_:1})])]),_:1})]),s(`section`,null,[s(`h2`,m,i(t(_)(`ds.heading.nonUppercase`)),1),a(d,{tone:`paper`},{default:r(()=>[s(`div`,h,[a(l,{variant:`brand`,uppercase:!1},{default:r(()=>[o(i(t(_)(`ds.badges.newRelease`)),1)]),_:1}),a(l,{variant:`accent`,uppercase:!1},{default:r(()=>[o(i(t(_)(`ds.badges.featured`)),1)]),_:1}),a(l,{variant:`subtle`,uppercase:!1},{default:r(()=>[...g[0]||=[o(`v2.1.0`,-1)]]),_:1})])]),_:1})])]),_:1},8,[`eyebrow`,`title`,`description`]))}};export{g as default};
import{C as e,G as t,c as n,j as r,lt as i,m as a,p as o,s}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as c}from"./i18n-CJQl3WLC.js";import{t as l}from"./Badge-DcvgVKep.js";import{t as u}from"./SectionShell-Cd_Fu3uI.js";import{t as d}from"./Card-pgd8VnYH.js";var f={class:`eyebrow mb-5`},p={class:`flex flex-wrap gap-3`},m={class:`eyebrow mb-5`},h={class:`flex flex-wrap gap-3`},g={__name:`BadgesSection`,setup(g){let{t:_}=c();return(c,g)=>(e(),n(u,{eyebrow:t(_)(`ds.eyebrow.components`),title:t(_)(`ds.badges.title`),description:t(_)(`ds.badges.description`)},{default:r(()=>[s(`section`,null,[s(`h2`,f,i(t(_)(`ds.heading.variants`)),1),a(d,{tone:`paper`},{default:r(()=>[s(`div`,p,[a(l,{variant:`neutral`},{default:r(()=>[o(i(t(_)(`ds.badges.neutral`)),1)]),_:1}),a(l,{variant:`brand`},{default:r(()=>[o(i(t(_)(`ds.badges.brand`)),1)]),_:1}),a(l,{variant:`accent`},{default:r(()=>[o(i(t(_)(`ds.badges.accent`)),1)]),_:1}),a(l,{variant:`subtle`},{default:r(()=>[o(i(t(_)(`ds.badges.subtle`)),1)]),_:1}),a(l,{variant:`success`},{default:r(()=>[o(i(t(_)(`ds.badges.success`)),1)]),_:1}),a(l,{variant:`warning`},{default:r(()=>[o(i(t(_)(`ds.badges.warning`)),1)]),_:1}),a(l,{variant:`danger`},{default:r(()=>[o(i(t(_)(`ds.badges.danger`)),1)]),_:1})])]),_:1})]),s(`section`,null,[s(`h2`,m,i(t(_)(`ds.heading.nonUppercase`)),1),a(d,{tone:`paper`},{default:r(()=>[s(`div`,h,[a(l,{variant:`brand`,uppercase:!1},{default:r(()=>[o(i(t(_)(`ds.badges.newRelease`)),1)]),_:1}),a(l,{variant:`accent`,uppercase:!1},{default:r(()=>[o(i(t(_)(`ds.badges.featured`)),1)]),_:1}),a(l,{variant:`subtle`,uppercase:!1},{default:r(()=>[...g[0]||=[o(`v2.1.0`,-1)]]),_:1})])]),_:1})])]),_:1},8,[`eyebrow`,`title`,`description`]))}};export{g as default};

View File

@@ -1 +1 @@
import{C as e,G as t,O as n,T as r,c as i,j as a,l as o,lt as s,m as c,o as l,p as u,r as d,s as f,st as p,u as m}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as h}from"./Icon-BCRRMV3J.js";import{t as g}from"./i18n-DrTQks20.js";import{t as _}from"./Badge-DcvgVKep.js";import{t as v}from"./Button-DkdaDkuf.js";var y=[`src`,`alt`],b={class:`flex flex-col gap-1.5`},x={key:0,class:`text-xs font-semibold tracking-label text-muted uppercase`},S={class:`flex flex-col gap-1.5`},C={key:0,class:`text-sm text-muted tracking-label`},w={class:`flex flex-col gap-0.5`},T={class:`text-xs tracking-label text-muted uppercase`},E={class:`font-display text-2xl font-normal text-brand leading-none`},D={key:0,class:`text-xs text-muted mt-1`},O={key:1,class:`text-xs font-semibold tracking-label uppercase text-danger mt-1`},k=3,A={__name:`BundleCard`,props:{name:{type:String,required:!0},items:{type:Array,required:!0},price:{type:Number,required:!0},memberPrice:{type:Number,default:null},usage:{type:String,default:``},image:{type:String,required:!0},imageAlt:{type:String,default:``},badge:{type:String,default:``},badgeVariant:{type:String,default:`accent`,validator:e=>[`neutral`,`brand`,`accent`,`subtle`,`success`,`warning`,`danger`].includes(e)},tone:{type:String,default:`paper`,validator:e=>[`paper`,`cream`].includes(e)},layout:{type:String,default:`vertical`,validator:e=>[`vertical`,`horizontal`].includes(e)},inStock:{type:Boolean,default:!0},currency:{type:String,default:``},href:{type:String,default:``}},emits:[`add`],setup(A){let j=A,{t:M}=g(),N={paper:{surface:`bg-paper`,media:`bg-cream`,border:`border-line`},cream:{surface:`bg-cream`,media:`bg-paper`,border:`border-line`}},P=l(()=>N[j.tone]);function F(e){return`${j.currency} ${e.toFixed(2).replace(`.`,`,`)}`}let I=l(()=>F(j.price)),L=l(()=>j.memberPrice==null?``:F(j.memberPrice)),R=l(()=>j.items.slice(0,k)),z=l(()=>Math.max(0,j.items.length-k));return(l,g)=>(e(),m(`article`,{class:p([`group flex overflow-hidden rounded-md border transition-all duration-base ease-out`,A.layout===`horizontal`?`flex-col md:flex-row`:`flex-col`,P.value.surface,P.value.border,`hover:-translate-y-1 hover:shadow-md hover:border-brand-soft`])},[(e(),i(n(A.href?`a`:`div`),{href:A.href||null,class:p([`relative block overflow-hidden`,A.layout===`horizontal`?`aspect-[4/3] md:aspect-auto md:w-[38%] md:shrink-0 md:min-h-[300px]`:`aspect-[4/3]`,P.value.media])},{default:a(()=>[A.badge?(e(),i(_,{key:0,variant:A.badgeVariant,class:`absolute top-4 left-4 z-[1]`},{default:a(()=>[u(s(A.badge),1)]),_:1},8,[`variant`])):o(``,!0),f(`img`,{src:A.image,alt:A.imageAlt||A.name,loading:`lazy`,decoding:`async`,class:p([`absolute inset-0 w-full h-full object-contain transition-transform duration-slow ease-out group-hover:scale-105`,A.layout===`horizontal`?`p-6 md:p-5`:`p-8`])},null,10,y)]),_:1},8,[`href`,`class`])),f(`div`,{class:p([`flex flex-col gap-4 p-6`,A.layout===`horizontal`?`md:p-6 md:flex-1`:``])},[f(`div`,b,[A.usage?(e(),m(`span`,x,s(A.usage),1)):o(``,!0),(e(),i(n(A.href?`a`:`h3`),{href:A.href||null,class:p([`font-display text-xl font-normal leading-tight text-ink`,A.href?`hover:text-brand transition-colors duration-base`:``])},{default:a(()=>[u(s(A.name),1)]),_:1},8,[`href`,`class`]))]),f(`ul`,S,[(e(!0),m(d,null,r(R.value,t=>(e(),m(`li`,{key:t,class:`text-sm text-ink/80 leading-relaxed`},s(t),1))),128)),z.value>0?(e(),m(`li`,C,`+ `+s(z.value)+` `+s(t(M)(`bundles.card.moreItems`)),1)):o(``,!0)]),f(`div`,{class:p([`mt-auto pt-4 border-t border-line flex gap-3`,A.layout===`horizontal`?`flex-col sm:flex-row sm:items-end sm:justify-between`:`flex-col`])},[f(`div`,w,[f(`span`,T,s(t(M)(`bundles.card.priceLabel`)),1),f(`span`,E,s(I.value),1),L.value?(e(),m(`span`,D,s(t(M)(`bundles.card.memberPrefix`))+` `+s(L.value),1)):o(``,!0),A.inStock?o(``,!0):(e(),m(`span`,O,s(t(M)(`ds.product.outOfStock`)),1))]),c(v,{variant:`primary`,size:`md`,block:A.layout===`vertical`,disabled:!A.inStock,onClick:g[0]||=e=>l.$emit(`add`)},{before:a(()=>[c(h,{name:`plus`,size:16})]),default:a(()=>[u(` `+s(t(M)(`ds.buttons.addToCart`)),1)]),_:1},8,[`block`,`disabled`])],2)],2)],2))}};export{A as t};
import{C as e,G as t,O as n,T as r,c as i,j as a,l as o,lt as s,m as c,o as l,p as u,r as d,s as f,st as p,u as m}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as h}from"./Icon-BCRRMV3J.js";import{t as g}from"./i18n-CJQl3WLC.js";import{t as _}from"./Badge-DcvgVKep.js";import{t as v}from"./Button-DkdaDkuf.js";var y=[`src`,`alt`],b={class:`flex flex-col gap-1.5`},x={key:0,class:`text-xs font-semibold tracking-label text-muted uppercase`},S={class:`flex flex-col gap-1.5`},C={key:0,class:`text-sm text-muted tracking-label`},w={class:`flex flex-col gap-0.5`},T={class:`text-xs tracking-label text-muted uppercase`},E={class:`font-display text-2xl font-normal text-brand leading-none`},D={key:0,class:`text-xs text-muted mt-1`},O={key:1,class:`text-xs font-semibold tracking-label uppercase text-danger mt-1`},k=3,A={__name:`BundleCard`,props:{name:{type:String,required:!0},items:{type:Array,required:!0},price:{type:Number,required:!0},memberPrice:{type:Number,default:null},usage:{type:String,default:``},image:{type:String,required:!0},imageAlt:{type:String,default:``},badge:{type:String,default:``},badgeVariant:{type:String,default:`accent`,validator:e=>[`neutral`,`brand`,`accent`,`subtle`,`success`,`warning`,`danger`].includes(e)},tone:{type:String,default:`paper`,validator:e=>[`paper`,`cream`].includes(e)},layout:{type:String,default:`vertical`,validator:e=>[`vertical`,`horizontal`].includes(e)},inStock:{type:Boolean,default:!0},currency:{type:String,default:``},href:{type:String,default:``}},emits:[`add`],setup(A){let j=A,{t:M}=g(),N={paper:{surface:`bg-paper`,media:`bg-cream`,border:`border-line`},cream:{surface:`bg-cream`,media:`bg-paper`,border:`border-line`}},P=l(()=>N[j.tone]);function F(e){return`${j.currency} ${e.toFixed(2).replace(`.`,`,`)}`}let I=l(()=>F(j.price)),L=l(()=>j.memberPrice==null?``:F(j.memberPrice)),R=l(()=>j.items.slice(0,k)),z=l(()=>Math.max(0,j.items.length-k));return(l,g)=>(e(),m(`article`,{class:p([`group flex overflow-hidden rounded-md border transition-all duration-base ease-out`,A.layout===`horizontal`?`flex-col md:flex-row`:`flex-col`,P.value.surface,P.value.border,`hover:-translate-y-1 hover:shadow-md hover:border-brand-soft`])},[(e(),i(n(A.href?`a`:`div`),{href:A.href||null,class:p([`relative block overflow-hidden`,A.layout===`horizontal`?`aspect-[4/3] md:aspect-auto md:w-[38%] md:shrink-0 md:min-h-[300px]`:`aspect-[4/3]`,P.value.media])},{default:a(()=>[A.badge?(e(),i(_,{key:0,variant:A.badgeVariant,class:`absolute top-4 left-4 z-[1]`},{default:a(()=>[u(s(A.badge),1)]),_:1},8,[`variant`])):o(``,!0),f(`img`,{src:A.image,alt:A.imageAlt||A.name,loading:`lazy`,decoding:`async`,class:p([`absolute inset-0 w-full h-full object-contain transition-transform duration-slow ease-out group-hover:scale-105`,A.layout===`horizontal`?`p-6 md:p-5`:`p-8`])},null,10,y)]),_:1},8,[`href`,`class`])),f(`div`,{class:p([`flex flex-col gap-4 p-6`,A.layout===`horizontal`?`md:p-6 md:flex-1`:``])},[f(`div`,b,[A.usage?(e(),m(`span`,x,s(A.usage),1)):o(``,!0),(e(),i(n(A.href?`a`:`h3`),{href:A.href||null,class:p([`font-display text-xl font-normal leading-tight text-ink`,A.href?`hover:text-brand transition-colors duration-base`:``])},{default:a(()=>[u(s(A.name),1)]),_:1},8,[`href`,`class`]))]),f(`ul`,S,[(e(!0),m(d,null,r(R.value,t=>(e(),m(`li`,{key:t,class:`text-sm text-ink/80 leading-relaxed`},s(t),1))),128)),z.value>0?(e(),m(`li`,C,`+ `+s(z.value)+` `+s(t(M)(`bundles.card.moreItems`)),1)):o(``,!0)]),f(`div`,{class:p([`mt-auto pt-4 border-t border-line flex gap-3`,A.layout===`horizontal`?`flex-col sm:flex-row sm:items-end sm:justify-between`:`flex-col`])},[f(`div`,w,[f(`span`,T,s(t(M)(`bundles.card.priceLabel`)),1),f(`span`,E,s(I.value),1),L.value?(e(),m(`span`,D,s(t(M)(`bundles.card.memberPrefix`))+` `+s(L.value),1)):o(``,!0),A.inStock?o(``,!0):(e(),m(`span`,O,s(t(M)(`ds.product.outOfStock`)),1))]),c(v,{variant:`primary`,size:`md`,block:A.layout===`vertical`,disabled:!A.inStock,onClick:g[0]||=e=>l.$emit(`add`)},{before:a(()=>[c(h,{name:`plus`,size:16})]),default:a(()=>[u(` `+s(t(M)(`ds.buttons.addToCart`)),1)]),_:1},8,[`block`,`disabled`])],2)],2)],2))}};export{A as t};

View File

@@ -1,4 +1,4 @@
import{B as e,C as t,G as n,c as r,j as i,l as a,lt as o,m as s,p as c,s as l,u,y as d}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as f}from"./i18n-DrTQks20.js";import{t as p}from"./BundleCard-Dzd67GYz.js";import{t as m}from"./SectionShell-BEISUYi8.js";var h={class:`eyebrow mb-5`},g={class:`grid sm:grid-cols-2 lg:grid-cols-3 gap-6`},_={key:0,class:`mt-5 text-sm text-muted`},v={class:`font-mono text-[12px]`},y={class:`grid gap-6`},b={class:`eyebrow mb-5`},x={class:`grid sm:grid-cols-2 gap-6`},S={class:`eyebrow mb-5`},C=`/products/cutouts/kaiser-natron-pulver-250-g-grosspackung-removebg-preview-1.png`,w={__name:`BundleCardSection`,setup(w){let{t:T}=f(),E=e(``);function D(e){E.value=e,setTimeout(()=>{E.value===e&&(E.value=``)},2e3)}let O={name:`Haushalts-Bundle`,usage:`23× pro Quartal empfohlen`,items:[`1× Kaiser-Natron Pulver 250 g`,`1× Allzweck-Spray 500 ml`,`1× Spülmittel 500 ml`],price:24.9,memberPrice:21.17,image:C,imageAlt:`Haushalts-Bundle`},k={...O,items:[...O.items,`1× Holste Wasch-Soda 500 g`,`1× Allzweckreiniger 750 ml`]};return(e,f)=>(t(),r(m,{eyebrow:n(T)(`ds.eyebrow.components`),title:n(T)(`ds.bundleCard.title`),description:n(T)(`ds.bundleCard.description`)},{default:i(()=>[l(`section`,null,[l(`h2`,h,o(n(T)(`ds.heading.default`)),1),l(`div`,g,[s(p,d(O,{onAdd:f[0]||=e=>D(`default`)}),null,16),s(p,d(O,{badge:`Bestseller`,"badge-variant":`accent`,onAdd:f[1]||=e=>D(`bestseller`)}),null,16),s(p,d(O,{tone:`cream`,onAdd:f[2]||=e=>D(`cream`)}),null,16)]),E.value?(t(),u(`p`,_,[c(o(n(T)(`ds.product.added`))+`: `,1),l(`code`,v,o(E.value),1)])):a(``,!0)]),l(`section`,null,[f[5]||=l(`h2`,{class:`eyebrow mb-5`},`Horizontal layout`,-1),f[6]||=l(`p`,{class:`text-sm text-muted mb-5 max-w-2xl`},[c(` Passed as `),l(`code`,{class:`font-mono text-[12px]`},`layout="horizontal"`),c(`. From `),l(`code`,{class:`font-mono text-[12px]`},`md`),c(` up the media takes ~38% of the row and the body fills the rest, with the CTA inlined next to the price block. Below `),l(`code`,{class:`font-mono text-[12px]`},`md`),c(` it collapses back to vertical. `)],-1),l(`div`,y,[s(p,d(O,{layout:`horizontal`,badge:`Bestseller`,"badge-variant":`accent`,onAdd:f[3]||=e=>D(`horizontal`)}),null,16)])]),l(`section`,null,[l(`h2`,b,o(n(T)(`ds.heading.states`)),1),f[7]||=l(`p`,{class:`text-sm text-muted mb-5 max-w-2xl`},` Same bundle across both cards — only the state being demonstrated changes. `,-1),l(`div`,x,[s(p,d(O,{"in-stock":!1}),null,16),s(p,d(k,{onAdd:f[4]||=e=>D(`overflow`)}),null,16)]),f[8]||=l(`p`,{class:`mt-3 text-sm text-muted max-w-2xl`},[c(` More than three items collapse the tail into a `),l(`code`,{class:`font-mono text-[12px]`},`+ N weitere`),c(` line so the card stays scannable. `)],-1)]),l(`section`,null,[l(`h2`,S,o(n(T)(`ds.heading.usage`)),1),f[9]||=l(`div`,{class:`rounded-md border border-line bg-paper p-6 font-mono text-[12px] text-ink`},[l(`pre`,{class:`whitespace-pre-wrap`},`<BundleCard
import{B as e,C as t,G as n,c as r,j as i,l as a,lt as o,m as s,p as c,s as l,u,y as d}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as f}from"./i18n-CJQl3WLC.js";import{t as p}from"./BundleCard-BNbtPMJE.js";import{t as m}from"./SectionShell-Cd_Fu3uI.js";var h={class:`eyebrow mb-5`},g={class:`grid sm:grid-cols-2 lg:grid-cols-3 gap-6`},_={key:0,class:`mt-5 text-sm text-muted`},v={class:`font-mono text-[12px]`},y={class:`grid gap-6`},b={class:`eyebrow mb-5`},x={class:`grid sm:grid-cols-2 gap-6`},S={class:`eyebrow mb-5`},C=`/products/cutouts/kaiser-natron-pulver-250-g-grosspackung-removebg-preview-1.png`,w={__name:`BundleCardSection`,setup(w){let{t:T}=f(),E=e(``);function D(e){E.value=e,setTimeout(()=>{E.value===e&&(E.value=``)},2e3)}let O={name:`Haushalts-Bundle`,usage:`23× pro Quartal empfohlen`,items:[`1× Kaiser-Natron Pulver 250 g`,`1× Allzweck-Spray 500 ml`,`1× Spülmittel 500 ml`],price:24.9,memberPrice:21.17,image:C,imageAlt:`Haushalts-Bundle`},k={...O,items:[...O.items,`1× Holste Wasch-Soda 500 g`,`1× Allzweckreiniger 750 ml`]};return(e,f)=>(t(),r(m,{eyebrow:n(T)(`ds.eyebrow.components`),title:n(T)(`ds.bundleCard.title`),description:n(T)(`ds.bundleCard.description`)},{default:i(()=>[l(`section`,null,[l(`h2`,h,o(n(T)(`ds.heading.default`)),1),l(`div`,g,[s(p,d(O,{onAdd:f[0]||=e=>D(`default`)}),null,16),s(p,d(O,{badge:`Bestseller`,"badge-variant":`accent`,onAdd:f[1]||=e=>D(`bestseller`)}),null,16),s(p,d(O,{tone:`cream`,onAdd:f[2]||=e=>D(`cream`)}),null,16)]),E.value?(t(),u(`p`,_,[c(o(n(T)(`ds.product.added`))+`: `,1),l(`code`,v,o(E.value),1)])):a(``,!0)]),l(`section`,null,[f[5]||=l(`h2`,{class:`eyebrow mb-5`},`Horizontal layout`,-1),f[6]||=l(`p`,{class:`text-sm text-muted mb-5 max-w-2xl`},[c(` Passed as `),l(`code`,{class:`font-mono text-[12px]`},`layout="horizontal"`),c(`. From `),l(`code`,{class:`font-mono text-[12px]`},`md`),c(` up the media takes ~38% of the row and the body fills the rest, with the CTA inlined next to the price block. Below `),l(`code`,{class:`font-mono text-[12px]`},`md`),c(` it collapses back to vertical. `)],-1),l(`div`,y,[s(p,d(O,{layout:`horizontal`,badge:`Bestseller`,"badge-variant":`accent`,onAdd:f[3]||=e=>D(`horizontal`)}),null,16)])]),l(`section`,null,[l(`h2`,b,o(n(T)(`ds.heading.states`)),1),f[7]||=l(`p`,{class:`text-sm text-muted mb-5 max-w-2xl`},` Same bundle across both cards — only the state being demonstrated changes. `,-1),l(`div`,x,[s(p,d(O,{"in-stock":!1}),null,16),s(p,d(k,{onAdd:f[4]||=e=>D(`overflow`)}),null,16)]),f[8]||=l(`p`,{class:`mt-3 text-sm text-muted max-w-2xl`},[c(` More than three items collapse the tail into a `),l(`code`,{class:`font-mono text-[12px]`},`+ N weitere`),c(` line so the card stays scannable. `)],-1)]),l(`section`,null,[l(`h2`,S,o(n(T)(`ds.heading.usage`)),1),f[9]||=l(`div`,{class:`rounded-md border border-line bg-paper p-6 font-mono text-[12px] text-ink`},[l(`pre`,{class:`whitespace-pre-wrap`},`<BundleCard
name="Haushalts-Bundle"
usage="23× pro Quartal empfohlen"
:items="[

1
dist/assets/Bundles-BUFH-aMm.js vendored Normal file

File diff suppressed because one or more lines are too long

1
dist/assets/Bundles-Bv4Zw5GG.css vendored Normal file
View File

@@ -0,0 +1 @@
.no-scrollbar[data-v-2edf5d69]::-webkit-scrollbar{display:none}.no-scrollbar[data-v-2edf5d69]{scrollbar-width:none;-ms-overflow-style:none}

View File

@@ -1 +0,0 @@
.no-scrollbar[data-v-d1080e83]::-webkit-scrollbar{display:none}.no-scrollbar[data-v-d1080e83]{scrollbar-width:none;-ms-overflow-style:none}

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
import{C as e,G as t,m as n,o as r,u as i}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as a}from"./i18n-DrTQks20.js";import{t as o}from"./Bundles-ak0UwRx6.js";var s={class:`min-h-screen bg-surface`},c={__name:`BundlesPreview`,setup(c){let{t:l}=a(),u=[{id:`haushalt`,name:`Haushalts-Bundle`,usage:`23× pro Quartal empfohlen`,items:[`1× Kaiser-Natron Pulver 250 g`,`1× Allzweck-Spray 500 ml`,`1× Spülmittel 500 ml`],price:24.9,memberPrice:21.17,image:`/products/cutouts/kaiser-natron-pulver-250-g-grosspackung-removebg-preview-1.png`,imageAlt:`Haushalts-Bundle mit Kaiser-Natron`,badge:`Bestseller`,badgeVariant:`accent`},{id:`waesche`,name:`Wäsche & Pflege`,usage:`12× pro Quartal`,items:[`1× Holste Wasch-Soda 500 g`,`1× Gazelle Wäschestärke 1 l`,`1× Linda Fleckenweg 200 ml`],price:22.9,memberPrice:19.47,image:`/products/holste-wasch-soda-500-g-beutel.jpg`,imageAlt:`Wäsche & Pflege Bundle`},{id:`wohlfuehl`,name:`Wohlfühl-Bundle`,usage:`1× pro Quartal`,items:[`1× Kaiser-Natron Tabletten 100 g`,`1× Kaiser-Natron Bad 500 g`,`1× Kaiser-Natron Fußbad 500 g`],price:29.9,memberPrice:25.42,image:`/products/kaiser-natron-bad-500-g.jpg`,imageAlt:`Wohlfühl-Bundle`}],d=r(()=>[l(`bundles.benefit.1.title`),l(`bundles.benefit.2.title`),l(`bundles.benefit.3.title`)]);return(r,a)=>(e(),i(`div`,s,[n(o,{bundles:u,headline:t(l)(`bundles.headline.a`),"headline-em":t(l)(`bundles.headline.em`),sub:t(l)(`bundles.sub`),benefits:d.value,"join-cta":t(l)(`bundles.joinCta`)},null,8,[`headline`,`headline-em`,`sub`,`benefits`,`join-cta`])]))}};export{c as default};

View File

@@ -0,0 +1 @@
import{C as e,G as t,m as n,o as r,u as i}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{a}from"./vue-router-QRVDVSxc.js";import{t as o}from"./i18n-CJQl3WLC.js";import{t as s}from"./Bundles-BUFH-aMm.js";var c={class:`min-h-screen bg-surface`},l={__name:`BundlesPreview`,setup(l){let{t:u}=o(),d=a(),f=r(()=>d.query.layout===`stacked`?`stacked`:`sidebar`),p=[{id:`haushalt`,name:`Haushalts-Bundle`,usage:`23× pro Quartal empfohlen`,items:[`1× Kaiser-Natron Pulver 250 g`,`1× Allzweck-Spray 500 ml`,`1× Spülmittel 500 ml`],price:24.9,memberPrice:21.17,image:`/products/cutouts/kaiser-natron-pulver-250-g-grosspackung-removebg-preview-1.png`,imageAlt:`Haushalts-Bundle mit Kaiser-Natron`,badge:`Bestseller`,badgeVariant:`accent`},{id:`waesche`,name:`Wäsche & Pflege`,usage:`12× pro Quartal`,items:[`1× Holste Wasch-Soda 500 g`,`1× Gazelle Wäschestärke 1 l`,`1× Linda Fleckenweg 200 ml`],price:22.9,memberPrice:19.47,image:`/products/holste-wasch-soda-500-g-beutel.jpg`,imageAlt:`Wäsche & Pflege Bundle`},{id:`wohlfuehl`,name:`Wohlfühl-Bundle`,usage:`1× pro Quartal`,items:[`1× Kaiser-Natron Tabletten 100 g`,`1× Kaiser-Natron Bad 500 g`,`1× Kaiser-Natron Fußbad 500 g`],price:29.9,memberPrice:25.42,image:`/products/kaiser-natron-bad-500-g.jpg`,imageAlt:`Wohlfühl-Bundle`}],m=r(()=>[u(`bundles.benefit.1.title`),u(`bundles.benefit.2.title`),u(`bundles.benefit.3.title`)]);return(r,a)=>(e(),i(`div`,c,[n(s,{layout:f.value,bundles:p,headline:t(u)(`bundles.headline.a`),"headline-em":t(u)(`bundles.headline.em`),sub:t(u)(`bundles.sub`),benefits:m.value,"join-cta":t(u)(`bundles.joinCta`)},null,8,[`layout`,`headline`,`headline-em`,`sub`,`benefits`,`join-cta`])]))}};export{l as default};

14
dist/assets/BundlesSection-Bw3L83wT.js vendored Normal file
View File

@@ -0,0 +1,14 @@
import{B as e,C as t,G as n,T as r,c as i,j as a,lt as o,m as s,o as c,p as l,r as u,s as d,st as f,u as p}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as m}from"./i18n-CJQl3WLC.js";import{t as h}from"./SectionShell-Cd_Fu3uI.js";import{t as g}from"./DevicePreview-Dx8DzWeH.js";var _={role:`tablist`,"aria-label":`Layout variant`,class:`inline-flex items-center p-1 gap-0.5 rounded-pill border border-line bg-paper`},v=[`aria-selected`,`onClick`],y={class:`eyebrow mb-5`},b={__name:`BundlesSection`,setup(b){let{t:x}=m(),S=[{id:`sidebar`,label:`Option 1`},{id:`stacked`,label:`Option 2`}],C=e(`sidebar`),w=c(()=>`/design/preview/bundles?layout=${C.value}`);return(e,c)=>(t(),i(h,{eyebrow:n(x)(`ds.eyebrow.components`),title:n(x)(`ds.bundles.title`),description:n(x)(`ds.bundles.description`),wide:``},{default:a(()=>[d(`section`,null,[s(g,{src:w.value,initial:`desktop`,height:1080},{controls:a(()=>[d(`div`,_,[(t(),p(u,null,r(S,e=>d(`button`,{key:e.id,type:`button`,role:`tab`,"aria-selected":C.value===e.id,class:f([`inline-flex items-center gap-2 px-3 py-1.5 text-[12px] font-semibold tracking-label rounded-pill transition-colors duration-base`,C.value===e.id?`bg-brand text-accent`:`text-muted hover:text-brand`]),onClick:t=>C.value=e.id},o(e.label),11,v)),64))])]),_:1},8,[`src`])]),d(`section`,null,[d(`h2`,y,o(n(x)(`ds.heading.usage`)),1),c[0]||=d(`div`,{class:`rounded-md border border-line bg-paper p-6 font-mono text-[12px] text-ink`},[d(`pre`,{class:`whitespace-pre-wrap`},`<Bundles
:bundles="bundles"
:headline="t('bundles.headline.a')"
:headline-em="t('bundles.headline.em')"
:sub="t('bundles.sub')"
:benefits="[
t('bundles.benefit.1.title'),
t('bundles.benefit.2.title'),
t('bundles.benefit.3.title'),
]"
:join-cta="t('bundles.joinCta')"
@add="addBundle(bundleId)"
@join="openSignup()"
/>`)],-1)]),c[1]||=d(`section`,null,[d(`h2`,{class:`eyebrow mb-5`},`Props`),d(`div`,{class:`rounded-md border border-line bg-paper overflow-x-auto`},[d(`table`,{class:`w-full text-left text-[13px]`},[d(`thead`,{class:`bg-surface border-b border-line`},[d(`tr`,null,[d(`th`,{class:`px-5 py-3 font-semibold tracking-label text-muted uppercase text-[11px]`},`Prop`),d(`th`,{class:`px-5 py-3 font-semibold tracking-label text-muted uppercase text-[11px]`},`Type`),d(`th`,{class:`px-5 py-3 font-semibold tracking-label text-muted uppercase text-[11px]`},`Purpose`)])]),d(`tbody`,{class:`divide-y divide-line`},[d(`tr`,null,[d(`td`,{class:`px-5 py-3 font-mono text-[12px]`},`bundles`),d(`td`,{class:`px-5 py-3 text-muted`},`Array`),d(`td`,{class:`px-5 py-3`},`Required. Array of bundle records rendered by BundleCard.`)]),d(`tr`,null,[d(`td`,{class:`px-5 py-3 font-mono text-[12px]`},`headline / headlineEm / sub`),d(`td`,{class:`px-5 py-3 text-muted`},`String`),d(`td`,{class:`px-5 py-3`},[l(`Sidebar copy; `),d(`code`,{class:`font-mono text-[12px]`},`headlineEm`),l(` is the italicised highlight.`)])]),d(`tr`,null,[d(`td`,{class:`px-5 py-3 font-mono text-[12px]`},`benefits`),d(`td`,{class:`px-5 py-3 text-muted`},`String[]`),d(`td`,{class:`px-5 py-3`},`Sidebar benefit bullets. First three are shown.`)]),d(`tr`,null,[d(`td`,{class:`px-5 py-3 font-mono text-[12px]`},`joinCta`),d(`td`,{class:`px-5 py-3 text-muted`},`String`),d(`td`,{class:`px-5 py-3`},[l(`Label for the sidebar's primary button. Emits `),d(`code`,{class:`font-mono text-[12px]`},`join`),l(`.`)])]),d(`tr`,null,[d(`td`,{class:`px-5 py-3 font-mono text-[12px]`},`carousel*Label`),d(`td`,{class:`px-5 py-3 text-muted`},`String`),d(`td`,{class:`px-5 py-3`},`Override the default carousel a11y labels (prev / next / goToSlide / region label).`)])])])])],-1)]),_:1},8,[`eyebrow`,`title`,`description`]))}};export{b as default};

View File

@@ -1,14 +0,0 @@
import{C as e,G as t,c as n,j as r,lt as i,m as a,p as o,s}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as c}from"./i18n-DrTQks20.js";import{t as l}from"./SectionShell-BEISUYi8.js";import{t as u}from"./DevicePreview-DvIWByfU.js";var d={class:`eyebrow mb-5`},f=`/design/preview/bundles`,p={__name:`BundlesSection`,setup(p){let{t:m}=c();return(c,p)=>(e(),n(l,{eyebrow:t(m)(`ds.eyebrow.components`),title:t(m)(`ds.bundles.title`),description:t(m)(`ds.bundles.description`),wide:``},{default:r(()=>[s(`section`,null,[a(u,{src:f,initial:`desktop`,height:1080})]),s(`section`,null,[s(`h2`,d,i(t(m)(`ds.heading.usage`)),1),p[0]||=s(`div`,{class:`rounded-md border border-line bg-paper p-6 font-mono text-[12px] text-ink`},[s(`pre`,{class:`whitespace-pre-wrap`},`<Bundles
:bundles="bundles"
:headline="t('bundles.headline.a')"
:headline-em="t('bundles.headline.em')"
:sub="t('bundles.sub')"
:benefits="[
t('bundles.benefit.1.title'),
t('bundles.benefit.2.title'),
t('bundles.benefit.3.title'),
]"
:join-cta="t('bundles.joinCta')"
@add="addBundle(bundleId)"
@join="openSignup()"
/>`)],-1)]),p[1]||=s(`section`,null,[s(`h2`,{class:`eyebrow mb-5`},`Props`),s(`div`,{class:`rounded-md border border-line bg-paper overflow-x-auto`},[s(`table`,{class:`w-full text-left text-[13px]`},[s(`thead`,{class:`bg-surface border-b border-line`},[s(`tr`,null,[s(`th`,{class:`px-5 py-3 font-semibold tracking-label text-muted uppercase text-[11px]`},`Prop`),s(`th`,{class:`px-5 py-3 font-semibold tracking-label text-muted uppercase text-[11px]`},`Type`),s(`th`,{class:`px-5 py-3 font-semibold tracking-label text-muted uppercase text-[11px]`},`Purpose`)])]),s(`tbody`,{class:`divide-y divide-line`},[s(`tr`,null,[s(`td`,{class:`px-5 py-3 font-mono text-[12px]`},`bundles`),s(`td`,{class:`px-5 py-3 text-muted`},`Array`),s(`td`,{class:`px-5 py-3`},`Required. Array of bundle records rendered by BundleCard.`)]),s(`tr`,null,[s(`td`,{class:`px-5 py-3 font-mono text-[12px]`},`headline / headlineEm / sub`),s(`td`,{class:`px-5 py-3 text-muted`},`String`),s(`td`,{class:`px-5 py-3`},[o(`Sidebar copy; `),s(`code`,{class:`font-mono text-[12px]`},`headlineEm`),o(` is the italicised highlight.`)])]),s(`tr`,null,[s(`td`,{class:`px-5 py-3 font-mono text-[12px]`},`benefits`),s(`td`,{class:`px-5 py-3 text-muted`},`String[]`),s(`td`,{class:`px-5 py-3`},`Sidebar benefit bullets. First three are shown.`)]),s(`tr`,null,[s(`td`,{class:`px-5 py-3 font-mono text-[12px]`},`joinCta`),s(`td`,{class:`px-5 py-3 text-muted`},`String`),s(`td`,{class:`px-5 py-3`},[o(`Label for the sidebar's primary button. Emits `),s(`code`,{class:`font-mono text-[12px]`},`join`),o(`.`)])]),s(`tr`,null,[s(`td`,{class:`px-5 py-3 font-mono text-[12px]`},`carousel*Label`),s(`td`,{class:`px-5 py-3 text-muted`},`String`),s(`td`,{class:`px-5 py-3`},`Override the default carousel a11y labels (prev / next / goToSlide / region label).`)])])])])],-1)]),_:1},8,[`eyebrow`,`title`,`description`]))}};export{p as default};

View File

@@ -1,4 +1,4 @@
import{C as e,G as t,c as n,j as r,lt as i,m as a,p as o,s}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as c}from"./Icon-BCRRMV3J.js";import{t as l}from"./i18n-DrTQks20.js";import{t as u}from"./Button-DkdaDkuf.js";import{t as d}from"./SectionShell-BEISUYi8.js";import{t as f}from"./Card-DM27vc3f.js";var p={class:`eyebrow mb-5`},m={class:`flex flex-wrap gap-3`},h={class:`eyebrow mb-5`},g={class:`grid md:grid-cols-3 gap-4`},_={class:`eyebrow mb-4`},v={class:`flex flex-wrap gap-3`},y={class:`eyebrow mb-4`},b={class:`flex flex-wrap gap-3`},x={class:`eyebrow mb-4 !text-cream opacity-80`},S={class:`flex flex-wrap gap-3`},C={class:`eyebrow mb-5`},w={class:`flex flex-wrap items-center gap-3`},T={class:`eyebrow mb-5`},E={class:`flex flex-wrap items-center gap-3`},D={class:`eyebrow mb-5`},O={class:`flex flex-wrap gap-3 items-center`},k={class:`eyebrow mb-5`},A={class:`max-w-md space-y-3`},j={class:`eyebrow mb-5`},M={class:`rounded-md border border-line bg-paper p-6 font-mono text-[12px] text-ink`},N={class:`whitespace-pre-wrap`},P={__name:`ButtonsSection`,setup(P){let{t:F}=l();return(l,P)=>(e(),n(d,{eyebrow:t(F)(`ds.eyebrow.components`),title:t(F)(`ds.buttons.title`),description:t(F)(`ds.buttons.description`)},{default:r(()=>[s(`section`,null,[s(`h2`,p,i(t(F)(`ds.heading.variants`)),1),a(f,{tone:`paper`},{default:r(()=>[s(`div`,m,[a(u,{variant:`primary`},{default:r(()=>[o(i(t(F)(`ds.buttons.primary`)),1)]),_:1}),a(u,{variant:`accent`},{default:r(()=>[o(i(t(F)(`ds.buttons.accent`)),1)]),_:1}),a(u,{variant:`secondary`},{default:r(()=>[o(i(t(F)(`ds.buttons.secondary`)),1)]),_:1}),a(u,{variant:`ghost`},{default:r(()=>[o(i(t(F)(`ds.buttons.ghost`)),1)]),_:1}),a(u,{variant:`danger`},{default:r(()=>[o(i(t(F)(`ds.buttons.danger`)),1)]),_:1})])]),_:1})]),s(`section`,null,[s(`h2`,h,i(t(F)(`ds.heading.onDifferentSurfaces`)),1),s(`div`,g,[a(f,{tone:`paper`},{default:r(()=>[s(`p`,_,i(t(F)(`ds.cards.paper`)),1),s(`div`,v,[a(u,{variant:`primary`},{before:r(()=>[a(c,{name:`cart`,size:18})]),default:r(()=>[o(` `+i(t(F)(`ds.buttons.addToCart`)),1)]),_:1}),a(u,{variant:`ghost`},{default:r(()=>[o(i(t(F)(`ds.buttons.learnMore`)),1)]),_:1})])]),_:1}),a(f,{tone:`cream`},{default:r(()=>[s(`p`,y,i(t(F)(`ds.cards.cream`)),1),s(`div`,b,[a(u,{variant:`primary`},{before:r(()=>[a(c,{name:`cart`,size:18})]),default:r(()=>[o(` `+i(t(F)(`ds.buttons.addToCart`)),1)]),_:1}),a(u,{variant:`ghost`},{default:r(()=>[o(i(t(F)(`ds.buttons.learnMore`)),1)]),_:1})])]),_:1}),a(f,{tone:`brand`},{default:r(()=>[s(`p`,x,i(t(F)(`ds.cards.brand`)),1),s(`div`,S,[a(u,{variant:`accent`},{before:r(()=>[a(c,{name:`cart`,size:18})]),default:r(()=>[o(` `+i(t(F)(`ds.buttons.addToCart`)),1)]),_:1}),a(u,{variant:`ghost`,class:`!text-cream hover:!bg-cream-wash`},{default:r(()=>[o(i(t(F)(`ds.buttons.learnMore`)),1)]),_:1})])]),_:1})])]),s(`section`,null,[s(`h2`,C,i(t(F)(`ds.heading.sizes`)),1),a(f,{tone:`paper`},{default:r(()=>[s(`div`,w,[a(u,{size:`sm`},{default:r(()=>[o(i(t(F)(`ds.buttons.small`)),1)]),_:1}),a(u,{size:`md`},{default:r(()=>[o(i(t(F)(`ds.buttons.medium`)),1)]),_:1}),a(u,{size:`lg`},{default:r(()=>[o(i(t(F)(`ds.buttons.large`)),1)]),_:1})])]),_:1})]),s(`section`,null,[s(`h2`,T,i(t(F)(`ds.heading.withIcons`)),1),a(f,{tone:`paper`},{default:r(()=>[s(`div`,E,[a(u,{variant:`primary`},{before:r(()=>[a(c,{name:`cart`,size:18})]),default:r(()=>[o(` `+i(t(F)(`ds.buttons.addToCart`)),1)]),_:1}),a(u,{variant:`secondary`},{after:r(()=>[a(c,{name:`arrow-right`,size:18})]),default:r(()=>[o(i(t(F)(`ds.buttons.learnMore`))+` `,1)]),_:1}),a(u,{variant:`ghost`},{before:r(()=>[a(c,{name:`heart`,size:18})]),default:r(()=>[o(` `+i(t(F)(`ds.buttons.save`)),1)]),_:1}),a(u,{variant:`accent`,size:`sm`},{before:r(()=>[a(c,{name:`check`,size:16})]),default:r(()=>[o(` `+i(t(F)(`ds.buttons.confirm`)),1)]),_:1})])]),_:1})]),s(`section`,null,[s(`h2`,D,i(t(F)(`ds.heading.states`)),1),a(f,{tone:`paper`},{default:r(()=>[s(`div`,O,[a(u,null,{default:r(()=>[o(i(t(F)(`ds.heading.default`)),1)]),_:1}),a(u,{disabled:``},{default:r(()=>[o(i(t(F)(`ds.buttons.disabled`)),1)]),_:1}),a(u,{loading:``},{default:r(()=>[o(i(t(F)(`ds.buttons.loading`)),1)]),_:1})])]),_:1})]),s(`section`,null,[s(`h2`,k,i(t(F)(`ds.heading.block`)),1),a(f,{tone:`paper`},{default:r(()=>[s(`div`,A,[a(u,{block:``,variant:`primary`},{before:r(()=>[a(c,{name:`cart`,size:18})]),default:r(()=>[o(` `+i(t(F)(`ds.buttons.addToCart`)),1)]),_:1}),a(u,{block:``,variant:`secondary`},{default:r(()=>[o(i(t(F)(`ds.buttons.continueShopping`)),1)]),_:1})])]),_:1})]),s(`section`,null,[s(`h2`,j,i(t(F)(`ds.heading.usage`)),1),s(`div`,M,[s(`pre`,N,`<Button variant="primary" size="md">
import{C as e,G as t,c as n,j as r,lt as i,m as a,p as o,s}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as c}from"./Icon-BCRRMV3J.js";import{t as l}from"./i18n-CJQl3WLC.js";import{t as u}from"./Button-DkdaDkuf.js";import{t as d}from"./SectionShell-Cd_Fu3uI.js";import{t as f}from"./Card-pgd8VnYH.js";var p={class:`eyebrow mb-5`},m={class:`flex flex-wrap gap-3`},h={class:`eyebrow mb-5`},g={class:`grid md:grid-cols-3 gap-4`},_={class:`eyebrow mb-4`},v={class:`flex flex-wrap gap-3`},y={class:`eyebrow mb-4`},b={class:`flex flex-wrap gap-3`},x={class:`eyebrow mb-4 !text-cream opacity-80`},S={class:`flex flex-wrap gap-3`},C={class:`eyebrow mb-5`},w={class:`flex flex-wrap items-center gap-3`},T={class:`eyebrow mb-5`},E={class:`flex flex-wrap items-center gap-3`},D={class:`eyebrow mb-5`},O={class:`flex flex-wrap gap-3 items-center`},k={class:`eyebrow mb-5`},A={class:`max-w-md space-y-3`},j={class:`eyebrow mb-5`},M={class:`rounded-md border border-line bg-paper p-6 font-mono text-[12px] text-ink`},N={class:`whitespace-pre-wrap`},P={__name:`ButtonsSection`,setup(P){let{t:F}=l();return(l,P)=>(e(),n(d,{eyebrow:t(F)(`ds.eyebrow.components`),title:t(F)(`ds.buttons.title`),description:t(F)(`ds.buttons.description`)},{default:r(()=>[s(`section`,null,[s(`h2`,p,i(t(F)(`ds.heading.variants`)),1),a(f,{tone:`paper`},{default:r(()=>[s(`div`,m,[a(u,{variant:`primary`},{default:r(()=>[o(i(t(F)(`ds.buttons.primary`)),1)]),_:1}),a(u,{variant:`accent`},{default:r(()=>[o(i(t(F)(`ds.buttons.accent`)),1)]),_:1}),a(u,{variant:`secondary`},{default:r(()=>[o(i(t(F)(`ds.buttons.secondary`)),1)]),_:1}),a(u,{variant:`ghost`},{default:r(()=>[o(i(t(F)(`ds.buttons.ghost`)),1)]),_:1}),a(u,{variant:`danger`},{default:r(()=>[o(i(t(F)(`ds.buttons.danger`)),1)]),_:1})])]),_:1})]),s(`section`,null,[s(`h2`,h,i(t(F)(`ds.heading.onDifferentSurfaces`)),1),s(`div`,g,[a(f,{tone:`paper`},{default:r(()=>[s(`p`,_,i(t(F)(`ds.cards.paper`)),1),s(`div`,v,[a(u,{variant:`primary`},{before:r(()=>[a(c,{name:`cart`,size:18})]),default:r(()=>[o(` `+i(t(F)(`ds.buttons.addToCart`)),1)]),_:1}),a(u,{variant:`ghost`},{default:r(()=>[o(i(t(F)(`ds.buttons.learnMore`)),1)]),_:1})])]),_:1}),a(f,{tone:`cream`},{default:r(()=>[s(`p`,y,i(t(F)(`ds.cards.cream`)),1),s(`div`,b,[a(u,{variant:`primary`},{before:r(()=>[a(c,{name:`cart`,size:18})]),default:r(()=>[o(` `+i(t(F)(`ds.buttons.addToCart`)),1)]),_:1}),a(u,{variant:`ghost`},{default:r(()=>[o(i(t(F)(`ds.buttons.learnMore`)),1)]),_:1})])]),_:1}),a(f,{tone:`brand`},{default:r(()=>[s(`p`,x,i(t(F)(`ds.cards.brand`)),1),s(`div`,S,[a(u,{variant:`accent`},{before:r(()=>[a(c,{name:`cart`,size:18})]),default:r(()=>[o(` `+i(t(F)(`ds.buttons.addToCart`)),1)]),_:1}),a(u,{variant:`ghost`,class:`!text-cream hover:!bg-cream-wash`},{default:r(()=>[o(i(t(F)(`ds.buttons.learnMore`)),1)]),_:1})])]),_:1})])]),s(`section`,null,[s(`h2`,C,i(t(F)(`ds.heading.sizes`)),1),a(f,{tone:`paper`},{default:r(()=>[s(`div`,w,[a(u,{size:`sm`},{default:r(()=>[o(i(t(F)(`ds.buttons.small`)),1)]),_:1}),a(u,{size:`md`},{default:r(()=>[o(i(t(F)(`ds.buttons.medium`)),1)]),_:1}),a(u,{size:`lg`},{default:r(()=>[o(i(t(F)(`ds.buttons.large`)),1)]),_:1})])]),_:1})]),s(`section`,null,[s(`h2`,T,i(t(F)(`ds.heading.withIcons`)),1),a(f,{tone:`paper`},{default:r(()=>[s(`div`,E,[a(u,{variant:`primary`},{before:r(()=>[a(c,{name:`cart`,size:18})]),default:r(()=>[o(` `+i(t(F)(`ds.buttons.addToCart`)),1)]),_:1}),a(u,{variant:`secondary`},{after:r(()=>[a(c,{name:`arrow-right`,size:18})]),default:r(()=>[o(i(t(F)(`ds.buttons.learnMore`))+` `,1)]),_:1}),a(u,{variant:`ghost`},{before:r(()=>[a(c,{name:`heart`,size:18})]),default:r(()=>[o(` `+i(t(F)(`ds.buttons.save`)),1)]),_:1}),a(u,{variant:`accent`,size:`sm`},{before:r(()=>[a(c,{name:`check`,size:16})]),default:r(()=>[o(` `+i(t(F)(`ds.buttons.confirm`)),1)]),_:1})])]),_:1})]),s(`section`,null,[s(`h2`,D,i(t(F)(`ds.heading.states`)),1),a(f,{tone:`paper`},{default:r(()=>[s(`div`,O,[a(u,null,{default:r(()=>[o(i(t(F)(`ds.heading.default`)),1)]),_:1}),a(u,{disabled:``},{default:r(()=>[o(i(t(F)(`ds.buttons.disabled`)),1)]),_:1}),a(u,{loading:``},{default:r(()=>[o(i(t(F)(`ds.buttons.loading`)),1)]),_:1})])]),_:1})]),s(`section`,null,[s(`h2`,k,i(t(F)(`ds.heading.block`)),1),a(f,{tone:`paper`},{default:r(()=>[s(`div`,A,[a(u,{block:``,variant:`primary`},{before:r(()=>[a(c,{name:`cart`,size:18})]),default:r(()=>[o(` `+i(t(F)(`ds.buttons.addToCart`)),1)]),_:1}),a(u,{block:``,variant:`secondary`},{default:r(()=>[o(i(t(F)(`ds.buttons.continueShopping`)),1)]),_:1})])]),_:1})]),s(`section`,null,[s(`h2`,j,i(t(F)(`ds.heading.usage`)),1),s(`div`,M,[s(`pre`,N,`<Button variant="primary" size="md">
<template #before><Icon name="cart" :size="18" /></template>
`+i(t(F)(`ds.buttons.addToCart`))+`
</Button>`,1)])])]),_:1},8,[`eyebrow`,`title`,`description`]))}};export{P as default};

View File

@@ -1 +1 @@
import{C as e,G as t,c as n,j as r,lt as i,m as a,p as o,s}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as c}from"./i18n-DrTQks20.js";import{t as l}from"./Badge-DcvgVKep.js";import{t as u}from"./SectionShell-BEISUYi8.js";import{t as d}from"./Card-DM27vc3f.js";var f={class:`eyebrow mb-5`},p={class:`grid md:grid-cols-3 gap-6`},m={class:`font-display text-2xl font-normal mb-2`},h={class:`text-[14px] text-muted leading-relaxed`},g={class:`font-display text-2xl font-normal mb-2`},_={class:`text-[14px] text-muted leading-relaxed`},v={class:`font-display text-2xl font-normal mb-2`},y={class:`text-[14px] opacity-80 leading-relaxed`},b={class:`eyebrow mb-5`},x={class:`grid md:grid-cols-2 gap-6`},S={class:`font-display text-2xl font-normal mb-2`},C={class:`text-[14px] text-muted leading-relaxed`},w={class:`font-display text-2xl font-normal mb-2`},T={class:`text-[14px] text-muted leading-relaxed`},E={class:`eyebrow mb-5`},D={class:`p-7`},O={class:`font-display text-2xl font-normal mb-2`},k={class:`text-[14px] text-muted leading-relaxed`},A={__name:`CardsSection`,setup(A){let{t:j}=c();return(c,A)=>(e(),n(u,{eyebrow:t(j)(`ds.eyebrow.components`),title:t(j)(`ds.cards.title`),description:t(j)(`ds.cards.description`)},{default:r(()=>[s(`section`,null,[s(`h2`,f,i(t(j)(`ds.heading.tones`)),1),s(`div`,p,[a(d,{tone:`paper`},{default:r(()=>[a(l,{variant:`subtle`,class:`mb-4`},{default:r(()=>[o(i(t(j)(`ds.cards.paper`)),1)]),_:1}),s(`h3`,m,i(t(j)(`ds.cards.paperTitle`)),1),s(`p`,h,i(t(j)(`ds.cards.paperBody`)),1)]),_:1}),a(d,{tone:`cream`},{default:r(()=>[a(l,{variant:`subtle`,class:`mb-4`},{default:r(()=>[o(i(t(j)(`ds.cards.cream`)),1)]),_:1}),s(`h3`,g,i(t(j)(`ds.cards.creamTitle`)),1),s(`p`,_,i(t(j)(`ds.cards.creamBody`)),1)]),_:1}),a(d,{tone:`brand`},{default:r(()=>[a(l,{variant:`accent`,class:`mb-4`},{default:r(()=>[o(i(t(j)(`ds.cards.brand`)),1)]),_:1}),s(`h3`,v,i(t(j)(`ds.cards.brandTitle`)),1),s(`p`,y,i(t(j)(`ds.cards.brandBody`)),1)]),_:1})])]),s(`section`,null,[s(`h2`,b,i(t(j)(`ds.heading.interactive`)),1),s(`div`,x,[a(d,{tone:`paper`,interactive:``},{default:r(()=>[s(`h3`,S,i(t(j)(`ds.cards.hoverMe`)),1),s(`p`,C,i(t(j)(`ds.cards.hoverBody`)),1)]),_:1}),a(d,{tone:`cream`,interactive:``},{default:r(()=>[s(`h3`,w,i(t(j)(`ds.cards.hoverMeToo`)),1),s(`p`,T,i(t(j)(`ds.cards.hoverBodyAlt`)),1)]),_:1})])]),s(`section`,null,[s(`h2`,E,i(t(j)(`ds.heading.withoutPadding`)),1),a(d,{tone:`paper`,padded:!1},{default:r(()=>[A[2]||=s(`div`,{class:`h-40 bg-cream rounded-t-md`},null,-1),s(`div`,D,[s(`h3`,O,i(t(j)(`ds.cards.mediaTitle`)),1),s(`p`,k,[o(i(t(j)(`ds.cards.mediaBody`))+` `,1),A[0]||=s(`code`,{class:`font-mono text-[12px]`},`:padded="false"`,-1),A[1]||=o(`. `,-1)])])]),_:1})])]),_:1},8,[`eyebrow`,`title`,`description`]))}};export{A as default};
import{C as e,G as t,c as n,j as r,lt as i,m as a,p as o,s}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as c}from"./i18n-CJQl3WLC.js";import{t as l}from"./Badge-DcvgVKep.js";import{t as u}from"./SectionShell-Cd_Fu3uI.js";import{t as d}from"./Card-pgd8VnYH.js";var f={class:`eyebrow mb-5`},p={class:`grid md:grid-cols-3 gap-6`},m={class:`font-display text-2xl font-normal mb-2`},h={class:`text-[14px] text-muted leading-relaxed`},g={class:`font-display text-2xl font-normal mb-2`},_={class:`text-[14px] text-muted leading-relaxed`},v={class:`font-display text-2xl font-normal mb-2`},y={class:`text-[14px] opacity-80 leading-relaxed`},b={class:`eyebrow mb-5`},x={class:`grid md:grid-cols-2 gap-6`},S={class:`font-display text-2xl font-normal mb-2`},C={class:`text-[14px] text-muted leading-relaxed`},w={class:`font-display text-2xl font-normal mb-2`},T={class:`text-[14px] text-muted leading-relaxed`},E={class:`eyebrow mb-5`},D={class:`p-7`},O={class:`font-display text-2xl font-normal mb-2`},k={class:`text-[14px] text-muted leading-relaxed`},A={__name:`CardsSection`,setup(A){let{t:j}=c();return(c,A)=>(e(),n(u,{eyebrow:t(j)(`ds.eyebrow.components`),title:t(j)(`ds.cards.title`),description:t(j)(`ds.cards.description`)},{default:r(()=>[s(`section`,null,[s(`h2`,f,i(t(j)(`ds.heading.tones`)),1),s(`div`,p,[a(d,{tone:`paper`},{default:r(()=>[a(l,{variant:`subtle`,class:`mb-4`},{default:r(()=>[o(i(t(j)(`ds.cards.paper`)),1)]),_:1}),s(`h3`,m,i(t(j)(`ds.cards.paperTitle`)),1),s(`p`,h,i(t(j)(`ds.cards.paperBody`)),1)]),_:1}),a(d,{tone:`cream`},{default:r(()=>[a(l,{variant:`subtle`,class:`mb-4`},{default:r(()=>[o(i(t(j)(`ds.cards.cream`)),1)]),_:1}),s(`h3`,g,i(t(j)(`ds.cards.creamTitle`)),1),s(`p`,_,i(t(j)(`ds.cards.creamBody`)),1)]),_:1}),a(d,{tone:`brand`},{default:r(()=>[a(l,{variant:`accent`,class:`mb-4`},{default:r(()=>[o(i(t(j)(`ds.cards.brand`)),1)]),_:1}),s(`h3`,v,i(t(j)(`ds.cards.brandTitle`)),1),s(`p`,y,i(t(j)(`ds.cards.brandBody`)),1)]),_:1})])]),s(`section`,null,[s(`h2`,b,i(t(j)(`ds.heading.interactive`)),1),s(`div`,x,[a(d,{tone:`paper`,interactive:``},{default:r(()=>[s(`h3`,S,i(t(j)(`ds.cards.hoverMe`)),1),s(`p`,C,i(t(j)(`ds.cards.hoverBody`)),1)]),_:1}),a(d,{tone:`cream`,interactive:``},{default:r(()=>[s(`h3`,w,i(t(j)(`ds.cards.hoverMeToo`)),1),s(`p`,T,i(t(j)(`ds.cards.hoverBodyAlt`)),1)]),_:1})])]),s(`section`,null,[s(`h2`,E,i(t(j)(`ds.heading.withoutPadding`)),1),a(d,{tone:`paper`,padded:!1},{default:r(()=>[A[2]||=s(`div`,{class:`h-40 bg-cream rounded-t-md`},null,-1),s(`div`,D,[s(`h3`,O,i(t(j)(`ds.cards.mediaTitle`)),1),s(`p`,k,[o(i(t(j)(`ds.cards.mediaBody`))+` `,1),A[0]||=s(`code`,{class:`font-mono text-[12px]`},`:padded="false"`,-1),A[1]||=o(`. `,-1)])])]),_:1})])]),_:1},8,[`eyebrow`,`title`,`description`]))}};export{A as default};

File diff suppressed because one or more lines are too long

View File

@@ -1,4 +1,4 @@
import{B as e,C as t,G as n,S as r,c as i,j as a,lt as o,m as s,p as c,s as l}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as u}from"./Icon-BCRRMV3J.js";import{t as d}from"./i18n-DrTQks20.js";import{a as f,i as p,n as m,o as h,r as g,t as _}from"./api-S-LVXOcC.js";import{t as v}from"./Button-DkdaDkuf.js";import{t as y}from"./CartDrawer-B4LbpROl.js";import{t as b}from"./SectionShell-BEISUYi8.js";var x={class:`eyebrow mb-5`},S={class:`rounded-md border border-line bg-paper p-6 flex flex-col sm:flex-row sm:items-center gap-4`},C={class:`text-[13px] text-muted`},w={class:`eyebrow mb-5`},T={class:`text-[15px] text-muted leading-relaxed mb-4 max-w-2xl`},E={class:`eyebrow mb-5`},D={__name:`CartDrawerSection`,setup(D){let{t:O}=d(),k=h(),A=e(!1);async function j(){await m(),await _(`kaiser-natron-pulver-250-g-grosspackung`,2),await _(`kaiser-natron-bad-500-g`,1),A.value=!0}async function M({productId:e,quantity:t}){await f(e,t)}async function N(e){await p(e)}return r(()=>{g()}),(e,r)=>(t(),i(b,{eyebrow:n(O)(`ds.eyebrow.components`),title:n(O)(`ds.cartDrawer.title`),description:n(O)(`ds.cartDrawer.description`)},{default:a(()=>[l(`section`,null,[l(`h2`,x,o(n(O)(`ds.heading.default`)),1),l(`div`,S,[s(v,{variant:`primary`,onClick:j},{before:a(()=>[s(u,{name:`cart`,size:18})]),default:a(()=>[c(` `+o(n(O)(`ds.cartDrawer.demoLabel`)),1)]),_:1}),l(`p`,C,o(n(O)(`ds.cartDrawer.demoHint`)),1)])]),l(`section`,null,[l(`h2`,w,o(n(O)(`ds.cartDrawer.integrationTitle`)),1),l(`p`,T,o(n(O)(`ds.cartDrawer.integrationBody`)),1),r[2]||=l(`div`,{class:`rounded-md border border-line bg-paper p-6 font-mono text-[12px] text-ink`},[l(`pre`,{class:`whitespace-pre-wrap`},`import {
import{B as e,C as t,G as n,S as r,c as i,j as a,lt as o,m as s,p as c,s as l}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as u}from"./Icon-BCRRMV3J.js";import{t as d}from"./i18n-CJQl3WLC.js";import{a as f,i as p,n as m,o as h,r as g,t as _}from"./api-tyvtUCGz.js";import{t as v}from"./Button-DkdaDkuf.js";import{t as y}from"./CartDrawer-GmlNs2mL.js";import{t as b}from"./SectionShell-Cd_Fu3uI.js";var x={class:`eyebrow mb-5`},S={class:`rounded-md border border-line bg-paper p-6 flex flex-col sm:flex-row sm:items-center gap-4`},C={class:`text-[13px] text-muted`},w={class:`eyebrow mb-5`},T={class:`text-[15px] text-muted leading-relaxed mb-4 max-w-2xl`},E={class:`eyebrow mb-5`},D={__name:`CartDrawerSection`,setup(D){let{t:O}=d(),k=h(),A=e(!1);async function j(){await m(),await _(`kaiser-natron-pulver-250-g-grosspackung`,2),await _(`kaiser-natron-bad-500-g`,1),A.value=!0}async function M({productId:e,quantity:t}){await f(e,t)}async function N(e){await p(e)}return r(()=>{g()}),(e,r)=>(t(),i(b,{eyebrow:n(O)(`ds.eyebrow.components`),title:n(O)(`ds.cartDrawer.title`),description:n(O)(`ds.cartDrawer.description`)},{default:a(()=>[l(`section`,null,[l(`h2`,x,o(n(O)(`ds.heading.default`)),1),l(`div`,S,[s(v,{variant:`primary`,onClick:j},{before:a(()=>[s(u,{name:`cart`,size:18})]),default:a(()=>[c(` `+o(n(O)(`ds.cartDrawer.demoLabel`)),1)]),_:1}),l(`p`,C,o(n(O)(`ds.cartDrawer.demoHint`)),1)])]),l(`section`,null,[l(`h2`,w,o(n(O)(`ds.cartDrawer.integrationTitle`)),1),l(`p`,T,o(n(O)(`ds.cartDrawer.integrationBody`)),1),r[2]||=l(`div`,{class:`rounded-md border border-line bg-paper p-6 font-mono text-[12px] text-ink`},[l(`pre`,{class:`whitespace-pre-wrap`},`import {
fetchCart,
addToCart,
updateCartItem,

View File

@@ -1 +1 @@
import{C as e,G as t,T as n,c as r,ct as i,j as a,lt as o,o as s,r as c,s as l,u}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as d}from"./i18n-DrTQks20.js";import{t as f}from"./SectionShell-BEISUYi8.js";var p={class:`eyebrow mb-5`},m={class:`grid grid-cols-2 sm:grid-cols-3 gap-4`},h={class:`px-4 py-3`},g={class:`font-mono text-[12px] text-ink block`},_={__name:`ColorsSection`,setup(_){let{t:v}=d(),y=s(()=>[{title:v(`ds.colors.group.brand`),names:[`brand`,`brand-hover`,`brand-soft`]},{title:v(`ds.colors.group.accent`),names:[`accent`,`accent-soft`,`accent-ink`]},{title:v(`ds.colors.group.surface`),names:[`surface`,`paper`,`cream`]},{title:v(`ds.colors.group.ink`),names:[`ink`,`muted`]},{title:v(`ds.colors.group.line`),names:[`line`,`line-strong`]},{title:v(`ds.colors.group.semantic`),names:[`success`,`warning`,`danger`]}]);return(s,d)=>(e(),r(f,{eyebrow:t(v)(`ds.eyebrow.tokens`),title:t(v)(`ds.colors.title`),description:t(v)(`ds.colors.description`)},{default:a(()=>[(e(!0),u(c,null,n(y.value,t=>(e(),u(`section`,{key:t.title},[l(`h2`,p,o(t.title),1),l(`div`,m,[(e(!0),u(c,null,n(t.names,t=>(e(),u(`div`,{key:t,class:`rounded-md border border-line overflow-hidden bg-paper`},[l(`div`,{class:`h-28 border-b border-line`,style:i({background:`var(--color-${t})`})},null,4),l(`div`,h,[l(`code`,g,`--color-`+o(t),1)])]))),128))])]))),128))]),_:1},8,[`eyebrow`,`title`,`description`]))}};export{_ as default};
import{C as e,G as t,T as n,c as r,ct as i,j as a,lt as o,o as s,r as c,s as l,u}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as d}from"./i18n-CJQl3WLC.js";import{t as f}from"./SectionShell-Cd_Fu3uI.js";var p={class:`eyebrow mb-5`},m={class:`grid grid-cols-2 sm:grid-cols-3 gap-4`},h={class:`px-4 py-3`},g={class:`font-mono text-[12px] text-ink block`},_={__name:`ColorsSection`,setup(_){let{t:v}=d(),y=s(()=>[{title:v(`ds.colors.group.brand`),names:[`brand`,`brand-hover`,`brand-soft`]},{title:v(`ds.colors.group.accent`),names:[`accent`,`accent-soft`,`accent-ink`]},{title:v(`ds.colors.group.surface`),names:[`surface`,`paper`,`cream`]},{title:v(`ds.colors.group.ink`),names:[`ink`,`muted`]},{title:v(`ds.colors.group.line`),names:[`line`,`line-strong`]},{title:v(`ds.colors.group.semantic`),names:[`success`,`warning`,`danger`]}]);return(s,d)=>(e(),r(f,{eyebrow:t(v)(`ds.eyebrow.tokens`),title:t(v)(`ds.colors.title`),description:t(v)(`ds.colors.description`)},{default:a(()=>[(e(!0),u(c,null,n(y.value,t=>(e(),u(`section`,{key:t.title},[l(`h2`,p,o(t.title),1),l(`div`,m,[(e(!0),u(c,null,n(t.names,t=>(e(),u(`div`,{key:t,class:`rounded-md border border-line overflow-hidden bg-paper`},[l(`div`,{class:`h-28 border-b border-line`,style:i({background:`var(--color-${t})`})},null,4),l(`div`,h,[l(`code`,g,`--color-`+o(t),1)])]))),128))])]))),128))]),_:1},8,[`eyebrow`,`title`,`description`]))}};export{_ as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

1
dist/assets/Hero-CBIJn5YV.js vendored Normal file

File diff suppressed because one or more lines are too long

1
dist/assets/Hero-CNFv3JDa.css vendored Normal file
View File

@@ -0,0 +1 @@
.hero-section[data-v-1e8eafc0]{overflow-clip-margin:1rem}.hero-headline[data-v-1e8eafc0]{overflow-wrap:anywhere;word-break:normal}

View File

@@ -1 +1 @@
import{C as e,G as t,j as n,lt as r,m as i,o as a,p as o,r as s,s as c,st as l,u}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{a as d}from"./vue-router-QRVDVSxc.js";import{t as f}from"./i18n-DrTQks20.js";import{t as p}from"./Navbar-DTKm8Xku.js";import{t as m}from"./Hero-B6Qkpe_4.js";var h={class:`italic font-light text-brand-soft`},g={class:`italic font-light text-brand-soft`},_=`/products/cutouts/kaiser-natron-pulver-250-g-grosspackung-removebg-preview-3.png`,v=`/products/kaiser-natron-bad-500-g.jpg`,y={__name:`HeroPreview`,setup(y){let b=d(),{t:x}=f(),S=a(()=>[`split`,`centered`].includes(b.query.variant)?b.query.variant:`split`),C=a(()=>[`cream`,`paper`,`brand`].includes(b.query.tone)?b.query.tone:`cream`),w=a(()=>b.query.reverse===`1`),T=a(()=>C.value===`brand`?`brand`:C.value),E=a(()=>w.value?v:_),D=a(()=>w.value?`Kaiser-Natron Bad 500 g`:`Kaiser-Natron Pulver 250 g Großpackung`);return(a,d)=>(e(),u(`div`,{class:l([`min-h-screen`,C.value===`brand`?`bg-brand`:`bg-surface`])},[i(p,{variant:T.value,"cart-count":0},null,8,[`variant`]),i(m,{variant:S.value,tone:C.value,reverse:w.value,eyebrow:w.value?t(x)(`home.banner.eyebrow`):t(x)(`ds.hero.eyebrow`),subheadline:w.value?t(x)(`home.banner.sub`):t(x)(`ds.hero.sub`),image:E.value,"image-alt":D.value,badge:w.value?``:t(x)(`ds.badges.featured`),"cta-label":t(x)(`ds.buttons.addToCart`),"secondary-label":t(x)(`ds.buttons.learnMore`)},{headline:n(()=>[w.value?(e(),u(s,{key:0},[o(r(t(x)(`home.banner.headline.a`))+` `,1),c(`em`,h,r(t(x)(`home.banner.headline.em`)),1),o(` `+r(t(x)(`home.banner.headline.b`)),1)],64)):(e(),u(s,{key:1},[o(r(t(x)(`ds.hero.headline.a`))+` `,1),c(`em`,g,r(t(x)(`ds.hero.headline.em`)),1),o(` `+r(t(x)(`ds.hero.headline.b`)),1)],64))]),_:1},8,[`variant`,`tone`,`reverse`,`eyebrow`,`subheadline`,`image`,`image-alt`,`badge`,`cta-label`,`secondary-label`])],2))}};export{y as default};
import{C as e,G as t,j as n,lt as r,m as i,o as a,p as o,r as s,s as c,st as l,u}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{a as d}from"./vue-router-QRVDVSxc.js";import{t as f}from"./i18n-CJQl3WLC.js";import{t as p}from"./Navbar-DRsVuXxb.js";import{t as m}from"./Hero-CBIJn5YV.js";var h={class:`italic font-light text-brand-soft`},g={class:`italic font-light text-brand-soft`},_=`/products/cutouts/kaiser-natron-pulver-250-g-grosspackung-removebg-preview-3.png`,v=`/products/kaiser-natron-bad-500-g.jpg`,y={__name:`HeroPreview`,setup(y){let b=d(),{t:x}=f(),S=a(()=>[`split`,`centered`].includes(b.query.variant)?b.query.variant:`split`),C=a(()=>[`cream`,`paper`,`brand`].includes(b.query.tone)?b.query.tone:`cream`),w=a(()=>b.query.reverse===`1`),T=a(()=>C.value===`brand`?`brand`:C.value),E=a(()=>w.value?v:_),D=a(()=>w.value?`Kaiser-Natron Bad 500 g`:`Kaiser-Natron Pulver 250 g Großpackung`);return(a,d)=>(e(),u(`div`,{class:l([`min-h-screen`,C.value===`brand`?`bg-brand`:`bg-surface`])},[i(p,{variant:T.value,"cart-count":0},null,8,[`variant`]),i(m,{variant:S.value,tone:C.value,reverse:w.value,eyebrow:w.value?t(x)(`home.banner.eyebrow`):t(x)(`ds.hero.eyebrow`),subheadline:w.value?t(x)(`home.banner.sub`):t(x)(`ds.hero.sub`),image:E.value,"image-alt":D.value,badge:w.value?``:t(x)(`ds.badges.featured`),"cta-label":t(x)(`ds.buttons.addToCart`),"secondary-label":t(x)(`ds.buttons.learnMore`)},{headline:n(()=>[w.value?(e(),u(s,{key:0},[o(r(t(x)(`home.banner.headline.a`))+` `,1),c(`em`,h,r(t(x)(`home.banner.headline.em`)),1),o(` `+r(t(x)(`home.banner.headline.b`)),1)],64)):(e(),u(s,{key:1},[o(r(t(x)(`ds.hero.headline.a`))+` `,1),c(`em`,g,r(t(x)(`ds.hero.headline.em`)),1),o(` `+r(t(x)(`ds.hero.headline.b`)),1)],64))]),_:1},8,[`variant`,`tone`,`reverse`,`eyebrow`,`subheadline`,`image`,`image-alt`,`badge`,`cta-label`,`secondary-label`])],2))}};export{y as default};

View File

@@ -1,4 +1,4 @@
import{B as e,C as t,G as n,T as r,c as i,ct as a,j as o,lt as s,m as c,o as l,p as u,r as d,s as f,st as p,u as m}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as h}from"./i18n-DrTQks20.js";import{t as g}from"./SectionShell-BEISUYi8.js";import{t as _}from"./DevicePreview-DvIWByfU.js";var v=[`aria-label`],y=[`aria-selected`,`onClick`],b=[`aria-label`],x=[`aria-selected`,`onClick`],S={class:`eyebrow mb-5`},C={__name:`HeroSection`,setup(C){let{t:w}=h(),T=l(()=>[{id:`split`,label:w(`ds.hero.variant.split`)},{id:`centered`,label:w(`ds.hero.variant.centered`)}]),E=l(()=>[{id:`cream`,label:w(`ds.navbar.tone.cream`),swatch:`var(--color-cream)`},{id:`paper`,label:w(`ds.navbar.tone.paper`),swatch:`#ffffff`},{id:`brand`,label:w(`ds.navbar.tone.brand`),swatch:`var(--color-brand)`}]),D=e(`split`),O=e(`cream`),k=l(()=>`/design/preview/hero?variant=${D.value}&tone=${O.value}`);return(e,l)=>(t(),i(g,{eyebrow:n(w)(`ds.eyebrow.components`),title:n(w)(`ds.hero.title`),description:n(w)(`ds.hero.description`),wide:``},{default:o(()=>[f(`section`,null,[c(_,{src:k.value,initial:`desktop`,height:760},{controls:o(()=>[f(`div`,{role:`tablist`,"aria-label":n(w)(`ds.hero.variant.label`),class:`inline-flex items-center p-1 gap-0.5 rounded-pill border border-line bg-paper`},[(t(!0),m(d,null,r(T.value,e=>(t(),m(`button`,{key:e.id,type:`button`,role:`tab`,"aria-selected":D.value===e.id,class:p([`px-3 py-1.5 text-[12px] font-semibold tracking-label rounded-pill transition-colors duration-base`,D.value===e.id?`bg-brand text-accent`:`text-muted hover:text-brand`]),onClick:t=>D.value=e.id},s(e.label),11,y))),128))],8,v),f(`div`,{role:`tablist`,"aria-label":n(w)(`ds.navbar.tone`),class:`inline-flex items-center p-1 gap-0.5 rounded-pill border border-line bg-paper`},[(t(!0),m(d,null,r(E.value,e=>(t(),m(`button`,{key:e.id,type:`button`,role:`tab`,"aria-selected":O.value===e.id,class:p([`inline-flex items-center gap-2 px-3 py-1.5 text-[12px] font-semibold tracking-label rounded-pill transition-colors duration-base`,O.value===e.id?`bg-brand text-accent`:`text-muted hover:text-brand`]),onClick:t=>O.value=e.id},[f(`span`,{class:`w-2.5 h-2.5 rounded-full border border-line-strong`,style:a({backgroundColor:e.swatch})},null,4),u(` `+s(e.label),1)],10,x))),128))],8,b)]),_:1},8,[`src`])]),f(`section`,null,[f(`h2`,S,s(n(w)(`ds.heading.usage`)),1),l[0]||=f(`div`,{class:`rounded-md border border-line bg-paper p-6 font-mono text-[12px] text-ink`},[f(`pre`,{class:`whitespace-pre-wrap`},`<Hero
import{B as e,C as t,G as n,T as r,c as i,ct as a,j as o,lt as s,m as c,o as l,p as u,r as d,s as f,st as p,u as m}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as h}from"./i18n-CJQl3WLC.js";import{t as g}from"./SectionShell-Cd_Fu3uI.js";import{t as _}from"./DevicePreview-Dx8DzWeH.js";var v=[`aria-label`],y=[`aria-selected`,`onClick`],b=[`aria-label`],x=[`aria-selected`,`onClick`],S={class:`eyebrow mb-5`},C={__name:`HeroSection`,setup(C){let{t:w}=h(),T=l(()=>[{id:`split`,label:w(`ds.hero.variant.split`)},{id:`centered`,label:w(`ds.hero.variant.centered`)}]),E=l(()=>[{id:`cream`,label:w(`ds.navbar.tone.cream`),swatch:`var(--color-cream)`},{id:`paper`,label:w(`ds.navbar.tone.paper`),swatch:`#ffffff`},{id:`brand`,label:w(`ds.navbar.tone.brand`),swatch:`var(--color-brand)`}]),D=e(`split`),O=e(`cream`),k=l(()=>`/design/preview/hero?variant=${D.value}&tone=${O.value}`);return(e,l)=>(t(),i(g,{eyebrow:n(w)(`ds.eyebrow.components`),title:n(w)(`ds.hero.title`),description:n(w)(`ds.hero.description`),wide:``},{default:o(()=>[f(`section`,null,[c(_,{src:k.value,initial:`desktop`,height:760},{controls:o(()=>[f(`div`,{role:`tablist`,"aria-label":n(w)(`ds.hero.variant.label`),class:`inline-flex items-center p-1 gap-0.5 rounded-pill border border-line bg-paper`},[(t(!0),m(d,null,r(T.value,e=>(t(),m(`button`,{key:e.id,type:`button`,role:`tab`,"aria-selected":D.value===e.id,class:p([`px-3 py-1.5 text-[12px] font-semibold tracking-label rounded-pill transition-colors duration-base`,D.value===e.id?`bg-brand text-accent`:`text-muted hover:text-brand`]),onClick:t=>D.value=e.id},s(e.label),11,y))),128))],8,v),f(`div`,{role:`tablist`,"aria-label":n(w)(`ds.navbar.tone`),class:`inline-flex items-center p-1 gap-0.5 rounded-pill border border-line bg-paper`},[(t(!0),m(d,null,r(E.value,e=>(t(),m(`button`,{key:e.id,type:`button`,role:`tab`,"aria-selected":O.value===e.id,class:p([`inline-flex items-center gap-2 px-3 py-1.5 text-[12px] font-semibold tracking-label rounded-pill transition-colors duration-base`,O.value===e.id?`bg-brand text-accent`:`text-muted hover:text-brand`]),onClick:t=>O.value=e.id},[f(`span`,{class:`w-2.5 h-2.5 rounded-full border border-line-strong`,style:a({backgroundColor:e.swatch})},null,4),u(` `+s(e.label),1)],10,x))),128))],8,b)]),_:1},8,[`src`])]),f(`section`,null,[f(`h2`,S,s(n(w)(`ds.heading.usage`)),1),l[0]||=f(`div`,{class:`rounded-md border border-line bg-paper p-6 font-mono text-[12px] text-ink`},[f(`pre`,{class:`whitespace-pre-wrap`},`<Hero
variant="split"
tone="cream"
eyebrow="Neu"

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
@media (width>=1024px){.banner-shrink-desktop[data-v-697d5bea] img{max-height:48svh}.banner-shrink-desktop[data-v-697d5bea] .relative.mx-auto.w-full.max-w-6xl>div:last-child>div.relative{max-width:460px}}

1
dist/assets/HomePage-CvQwUlGw.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -1,2 +1,2 @@
import{B as e,C as t,G as n,M as r,T as i,c as a,j as o,l as s,lt as c,m as l,o as u,r as d,s as f,u as p}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{r as m}from"./runtime-dom.esm-bundler-CcSFQHoC.js";import{n as h,t as g}from"./Icon-BCRRMV3J.js";import{t as _}from"./i18n-DrTQks20.js";import{t as v}from"./SectionShell-BEISUYi8.js";var y={class:`mb-5 flex items-center gap-3 flex-wrap`},b={class:`relative inline-flex items-center`},x={class:`absolute left-3 text-muted pointer-events-none`},S=[`placeholder`],C={class:`text-[12px] text-muted`},w={key:0,class:`text-[14px] text-muted`},T={class:`eyebrow mb-4`},E={class:`grid grid-cols-[repeat(auto-fill,minmax(120px,1fr))] gap-3`},D=[`onClick`],O={class:`w-10 h-10 rounded-sm bg-cream text-brand flex items-center justify-center`},k={class:`font-mono text-[11px] text-muted group-hover:text-brand transition-colors`},A={class:`eyebrow mb-5`},j={class:`grid md:grid-cols-3 gap-4`},M={class:`rounded-md border border-line bg-paper text-brand p-8 flex items-center justify-center gap-6`},N={class:`rounded-md border border-line bg-cream text-brand p-8 flex items-center justify-center gap-6`},P={class:`rounded-md bg-brand text-accent p-8 flex items-center justify-center gap-6`},F={class:`eyebrow mb-5`},I={class:`rounded-md border border-line bg-paper p-8 flex items-end gap-8 text-brand`},L={class:`flex flex-col items-center gap-3`},R={class:`flex flex-col items-center gap-3`},z={class:`font-mono text-[11px] text-muted`},B={class:`flex flex-col items-center gap-3`},V={class:`flex flex-col items-center gap-3`},H={class:`flex flex-col items-center gap-3`},U={class:`eyebrow mb-5`},W={__name:`IconsSection`,setup(W){let{t:G}=_(),K=u(()=>[{title:G(`ds.icons.group.commerce`),names:[`cart`,`bag`,`heart`,`user`,`search`]},{title:G(`ds.icons.group.navigation`),names:[`menu`,`close`,`chevron-left`,`chevron-right`,`chevron-down`,`chevron-up`,`arrow-left`,`arrow-right`]},{title:G(`ds.icons.group.actions`),names:[`plus`,`minus`,`check`]},{title:G(`ds.icons.group.contact`),names:[`mail`,`phone`,`map-pin`,`external-link`]},{title:G(`ds.icons.group.feedback`),names:[`info`,`star`]},{title:G(`ds.icons.group.devices`),names:[`mobile`,`tablet`,`desktop`]}]),q=e(``),J=u(()=>{let e=q.value.trim().toLowerCase();return e?K.value.map(t=>({...t,names:t.names.filter(t=>t.includes(e)||(h[t]?.label||``).toLowerCase().includes(e))})).filter(e=>e.names.length>0):K.value}),Y=e(``);async function X(e){let t=`<Icon name="${e}" />`;try{await navigator.clipboard.writeText(t),Y.value=e,setTimeout(()=>{Y.value===e&&(Y.value=``)},1200)}catch{}}return(e,u)=>(t(),a(v,{eyebrow:n(G)(`ds.eyebrow.components`),title:n(G)(`ds.icons.title`),description:n(G)(`ds.icons.description`)},{default:o(()=>[f(`section`,null,[f(`div`,y,[f(`label`,b,[f(`span`,x,[l(g,{name:`search`,size:16})]),r(f(`input`,{"onUpdate:modelValue":u[0]||=e=>q.value=e,type:`search`,placeholder:n(G)(`ds.icons.search`),class:`pl-9 pr-4 py-2 rounded-pill border border-line bg-paper text-[14px] text-ink placeholder:text-muted focus:outline-none focus:border-brand w-[260px]`},null,8,S),[[m,q.value]])]),f(`span`,C,c(n(G)(`ds.icons.copyHint`)),1)]),J.value.length===0?(t(),p(`div`,w,c(n(G)(`ds.icons.noMatch`))+` "`+c(q.value)+`". `,1)):s(``,!0),(t(!0),p(d,null,i(J.value,e=>(t(),p(`div`,{key:e.title,class:`mb-10 last:mb-0`},[f(`h2`,T,c(e.title),1),f(`div`,E,[(t(!0),p(d,null,i(e.names,e=>(t(),p(`button`,{key:e,type:`button`,class:`group flex flex-col items-center justify-center gap-2 p-4 rounded-md border border-line bg-paper text-ink hover:border-brand-soft hover:-translate-y-0.5 hover:shadow-sm transition-all duration-base ease-out`,onClick:t=>X(e)},[f(`span`,O,[l(g,{name:e,size:22},null,8,[`name`])]),f(`span`,k,c(Y.value===e?n(G)(`ds.icons.copied`):e),1)],8,D))),128))])]))),128))]),f(`section`,null,[f(`h2`,A,c(n(G)(`ds.heading.onDifferentSurfaces`)),1),f(`div`,j,[f(`div`,M,[l(g,{name:`cart`,size:28}),l(g,{name:`heart`,size:28}),l(g,{name:`user`,size:28})]),f(`div`,N,[l(g,{name:`cart`,size:28}),l(g,{name:`heart`,size:28}),l(g,{name:`user`,size:28})]),f(`div`,P,[l(g,{name:`cart`,size:28}),l(g,{name:`heart`,size:28}),l(g,{name:`user`,size:28})])])]),f(`section`,null,[f(`h2`,F,c(n(G)(`ds.heading.sizes`)),1),f(`div`,I,[f(`div`,L,[l(g,{name:`cart`,size:16}),u[1]||=f(`code`,{class:`font-mono text-[11px] text-muted`},`16`,-1)]),f(`div`,R,[l(g,{name:`cart`,size:20}),f(`code`,z,c(n(G)(`ds.icons.sizeDefault`)),1)]),f(`div`,B,[l(g,{name:`cart`,size:24}),u[2]||=f(`code`,{class:`font-mono text-[11px] text-muted`},`24`,-1)]),f(`div`,V,[l(g,{name:`cart`,size:32}),u[3]||=f(`code`,{class:`font-mono text-[11px] text-muted`},`32`,-1)]),f(`div`,H,[l(g,{name:`cart`,size:48}),u[4]||=f(`code`,{class:`font-mono text-[11px] text-muted`},`48`,-1)])])]),f(`section`,null,[f(`h2`,U,c(n(G)(`ds.heading.usage`)),1),u[5]||=f(`div`,{class:`rounded-md border border-line bg-paper p-6 font-mono text-[12px] text-ink`},[f(`pre`,{class:`whitespace-pre-wrap`},`<Icon name="cart" :size="20" />
import{B as e,C as t,G as n,M as r,T as i,c as a,j as o,l as s,lt as c,m as l,o as u,r as d,s as f,u as p}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{r as m}from"./runtime-dom.esm-bundler-CcSFQHoC.js";import{n as h,t as g}from"./Icon-BCRRMV3J.js";import{t as _}from"./i18n-CJQl3WLC.js";import{t as v}from"./SectionShell-Cd_Fu3uI.js";var y={class:`mb-5 flex items-center gap-3 flex-wrap`},b={class:`relative inline-flex items-center`},x={class:`absolute left-3 text-muted pointer-events-none`},S=[`placeholder`],C={class:`text-[12px] text-muted`},w={key:0,class:`text-[14px] text-muted`},T={class:`eyebrow mb-4`},E={class:`grid grid-cols-[repeat(auto-fill,minmax(120px,1fr))] gap-3`},D=[`onClick`],O={class:`w-10 h-10 rounded-sm bg-cream text-brand flex items-center justify-center`},k={class:`font-mono text-[11px] text-muted group-hover:text-brand transition-colors`},A={class:`eyebrow mb-5`},j={class:`grid md:grid-cols-3 gap-4`},M={class:`rounded-md border border-line bg-paper text-brand p-8 flex items-center justify-center gap-6`},N={class:`rounded-md border border-line bg-cream text-brand p-8 flex items-center justify-center gap-6`},P={class:`rounded-md bg-brand text-accent p-8 flex items-center justify-center gap-6`},F={class:`eyebrow mb-5`},I={class:`rounded-md border border-line bg-paper p-8 flex items-end gap-8 text-brand`},L={class:`flex flex-col items-center gap-3`},R={class:`flex flex-col items-center gap-3`},z={class:`font-mono text-[11px] text-muted`},B={class:`flex flex-col items-center gap-3`},V={class:`flex flex-col items-center gap-3`},H={class:`flex flex-col items-center gap-3`},U={class:`eyebrow mb-5`},W={__name:`IconsSection`,setup(W){let{t:G}=_(),K=u(()=>[{title:G(`ds.icons.group.commerce`),names:[`cart`,`bag`,`heart`,`user`,`search`]},{title:G(`ds.icons.group.navigation`),names:[`menu`,`close`,`chevron-left`,`chevron-right`,`chevron-down`,`chevron-up`,`arrow-left`,`arrow-right`]},{title:G(`ds.icons.group.actions`),names:[`plus`,`minus`,`check`]},{title:G(`ds.icons.group.contact`),names:[`mail`,`phone`,`map-pin`,`external-link`]},{title:G(`ds.icons.group.feedback`),names:[`info`,`star`]},{title:G(`ds.icons.group.devices`),names:[`mobile`,`tablet`,`desktop`]}]),q=e(``),J=u(()=>{let e=q.value.trim().toLowerCase();return e?K.value.map(t=>({...t,names:t.names.filter(t=>t.includes(e)||(h[t]?.label||``).toLowerCase().includes(e))})).filter(e=>e.names.length>0):K.value}),Y=e(``);async function X(e){let t=`<Icon name="${e}" />`;try{await navigator.clipboard.writeText(t),Y.value=e,setTimeout(()=>{Y.value===e&&(Y.value=``)},1200)}catch{}}return(e,u)=>(t(),a(v,{eyebrow:n(G)(`ds.eyebrow.components`),title:n(G)(`ds.icons.title`),description:n(G)(`ds.icons.description`)},{default:o(()=>[f(`section`,null,[f(`div`,y,[f(`label`,b,[f(`span`,x,[l(g,{name:`search`,size:16})]),r(f(`input`,{"onUpdate:modelValue":u[0]||=e=>q.value=e,type:`search`,placeholder:n(G)(`ds.icons.search`),class:`pl-9 pr-4 py-2 rounded-pill border border-line bg-paper text-[14px] text-ink placeholder:text-muted focus:outline-none focus:border-brand w-[260px]`},null,8,S),[[m,q.value]])]),f(`span`,C,c(n(G)(`ds.icons.copyHint`)),1)]),J.value.length===0?(t(),p(`div`,w,c(n(G)(`ds.icons.noMatch`))+` "`+c(q.value)+`". `,1)):s(``,!0),(t(!0),p(d,null,i(J.value,e=>(t(),p(`div`,{key:e.title,class:`mb-10 last:mb-0`},[f(`h2`,T,c(e.title),1),f(`div`,E,[(t(!0),p(d,null,i(e.names,e=>(t(),p(`button`,{key:e,type:`button`,class:`group flex flex-col items-center justify-center gap-2 p-4 rounded-md border border-line bg-paper text-ink hover:border-brand-soft hover:-translate-y-0.5 hover:shadow-sm transition-all duration-base ease-out`,onClick:t=>X(e)},[f(`span`,O,[l(g,{name:e,size:22},null,8,[`name`])]),f(`span`,k,c(Y.value===e?n(G)(`ds.icons.copied`):e),1)],8,D))),128))])]))),128))]),f(`section`,null,[f(`h2`,A,c(n(G)(`ds.heading.onDifferentSurfaces`)),1),f(`div`,j,[f(`div`,M,[l(g,{name:`cart`,size:28}),l(g,{name:`heart`,size:28}),l(g,{name:`user`,size:28})]),f(`div`,N,[l(g,{name:`cart`,size:28}),l(g,{name:`heart`,size:28}),l(g,{name:`user`,size:28})]),f(`div`,P,[l(g,{name:`cart`,size:28}),l(g,{name:`heart`,size:28}),l(g,{name:`user`,size:28})])])]),f(`section`,null,[f(`h2`,F,c(n(G)(`ds.heading.sizes`)),1),f(`div`,I,[f(`div`,L,[l(g,{name:`cart`,size:16}),u[1]||=f(`code`,{class:`font-mono text-[11px] text-muted`},`16`,-1)]),f(`div`,R,[l(g,{name:`cart`,size:20}),f(`code`,z,c(n(G)(`ds.icons.sizeDefault`)),1)]),f(`div`,B,[l(g,{name:`cart`,size:24}),u[2]||=f(`code`,{class:`font-mono text-[11px] text-muted`},`24`,-1)]),f(`div`,V,[l(g,{name:`cart`,size:32}),u[3]||=f(`code`,{class:`font-mono text-[11px] text-muted`},`32`,-1)]),f(`div`,H,[l(g,{name:`cart`,size:48}),u[4]||=f(`code`,{class:`font-mono text-[11px] text-muted`},`48`,-1)])])]),f(`section`,null,[f(`h2`,U,c(n(G)(`ds.heading.usage`)),1),u[5]||=f(`div`,{class:`rounded-md border border-line bg-paper p-6 font-mono text-[12px] text-ink`},[f(`pre`,{class:`whitespace-pre-wrap`},`<Icon name="cart" :size="20" />
<Icon name="arrow-right" :size="16" label="Next slide" />`)],-1)])]),_:1},8,[`eyebrow`,`title`,`description`]))}};export{W as default};

View File

@@ -1 +1 @@
import{B as e,C as t,G as n,c as r,j as i,k as a,l as o,lt as s,m as c,o as l,p as u,s as d,st as f,u as p}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as m}from"./i18n-DrTQks20.js";import{t as h}from"./SectionShell-BEISUYi8.js";import{t as g}from"./Card-DM27vc3f.js";var _={class:`flex flex-col gap-2`},v=[`for`],y={key:0,class:`text-danger`},b=[`id`,`type`,`value`,`placeholder`,`disabled`,`required`,`aria-invalid`,`aria-describedby`],x=[`id`],S=[`id`],C={__name:`Input`,props:{modelValue:{type:[String,Number],default:``},label:{type:String,default:``},hint:{type:String,default:``},error:{type:String,default:``},type:{type:String,default:`text`},placeholder:{type:String,default:``},disabled:{type:Boolean,default:!1},required:{type:Boolean,default:!1}},emits:[`update:modelValue`],setup(e){let n=e,r=a(),i=l(()=>`in-${r}`),c=l(()=>n.hint?`hint-${r}`:void 0),m=l(()=>n.error?`err-${r}`:void 0),h=l(()=>[c.value,m.value].filter(Boolean).join(` `)||void 0);return(n,r)=>(t(),p(`div`,_,[e.label?(t(),p(`label`,{key:0,for:i.value,class:`text-[11px] font-bold uppercase tracking-eyebrow text-muted`},[u(s(e.label),1),e.required?(t(),p(`span`,y,` *`)):o(``,!0)],8,v)):o(``,!0),d(`input`,{id:i.value,type:e.type,value:e.modelValue,placeholder:e.placeholder,disabled:e.disabled,required:e.required,"aria-invalid":!!e.error,"aria-describedby":h.value,class:f([`w-full rounded-sm border bg-paper px-4 py-3 text-[15px] text-ink placeholder:text-ink-placeholder transition-colors duration-base focus:outline-none focus:border-brand disabled:opacity-50 disabled:cursor-not-allowed`,e.error?`border-danger`:`border-line`]),onInput:r[0]||=e=>n.$emit(`update:modelValue`,e.target.value)},null,42,b),e.hint&&!e.error?(t(),p(`p`,{key:1,id:c.value,class:`text-[13px] text-muted`},s(e.hint),9,x)):o(``,!0),e.error?(t(),p(`p`,{key:2,id:m.value,class:`text-[13px] text-danger`},s(e.error),9,S)):o(``,!0)]))}},w={class:`eyebrow mb-5`},T={class:`grid md:grid-cols-2 gap-6 max-w-3xl`},E={class:`eyebrow mb-5`},D={class:`grid md:grid-cols-2 gap-6 max-w-3xl`},O={__name:`InputsSection`,setup(a){let{t:o}=m(),l=e(``),u=e(``),f=e(``);return(e,a)=>(t(),r(h,{eyebrow:n(o)(`ds.eyebrow.components`),title:n(o)(`ds.inputs.title`),description:n(o)(`ds.inputs.description`)},{default:i(()=>[d(`section`,null,[d(`h2`,w,s(n(o)(`ds.heading.default`)),1),c(g,{tone:`paper`},{default:i(()=>[d(`div`,T,[c(C,{modelValue:l.value,"onUpdate:modelValue":a[0]||=e=>l.value=e,label:n(o)(`ds.inputs.email`),type:`email`,placeholder:`you@example.com`,hint:n(o)(`ds.inputs.emailHint`)},null,8,[`modelValue`,`label`,`hint`]),c(C,{modelValue:u.value,"onUpdate:modelValue":a[1]||=e=>u.value=e,label:n(o)(`ds.inputs.password`),type:`password`,placeholder:`••••••••`},null,8,[`modelValue`,`label`])])]),_:1})]),d(`section`,null,[d(`h2`,E,s(n(o)(`ds.heading.states`)),1),c(g,{tone:`paper`},{default:i(()=>[d(`div`,D,[c(C,{modelValue:f.value,"onUpdate:modelValue":a[2]||=e=>f.value=e,label:n(o)(`ds.inputs.required`),required:``,error:n(o)(`ds.inputs.requiredError`)},null,8,[`modelValue`,`label`,`error`]),c(C,{label:n(o)(`ds.inputs.disabled`),placeholder:n(o)(`ds.inputs.disabledPlaceholder`),disabled:``},null,8,[`label`,`placeholder`])])]),_:1})])]),_:1},8,[`eyebrow`,`title`,`description`]))}};export{O as default};
import{B as e,C as t,G as n,c as r,j as i,k as a,l as o,lt as s,m as c,o as l,p as u,s as d,st as f,u as p}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as m}from"./i18n-CJQl3WLC.js";import{t as h}from"./SectionShell-Cd_Fu3uI.js";import{t as g}from"./Card-pgd8VnYH.js";var _={class:`flex flex-col gap-2`},v=[`for`],y={key:0,class:`text-danger`},b=[`id`,`type`,`value`,`placeholder`,`disabled`,`required`,`aria-invalid`,`aria-describedby`],x=[`id`],S=[`id`],C={__name:`Input`,props:{modelValue:{type:[String,Number],default:``},label:{type:String,default:``},hint:{type:String,default:``},error:{type:String,default:``},type:{type:String,default:`text`},placeholder:{type:String,default:``},disabled:{type:Boolean,default:!1},required:{type:Boolean,default:!1}},emits:[`update:modelValue`],setup(e){let n=e,r=a(),i=l(()=>`in-${r}`),c=l(()=>n.hint?`hint-${r}`:void 0),m=l(()=>n.error?`err-${r}`:void 0),h=l(()=>[c.value,m.value].filter(Boolean).join(` `)||void 0);return(n,r)=>(t(),p(`div`,_,[e.label?(t(),p(`label`,{key:0,for:i.value,class:`text-[11px] font-bold uppercase tracking-eyebrow text-muted`},[u(s(e.label),1),e.required?(t(),p(`span`,y,` *`)):o(``,!0)],8,v)):o(``,!0),d(`input`,{id:i.value,type:e.type,value:e.modelValue,placeholder:e.placeholder,disabled:e.disabled,required:e.required,"aria-invalid":!!e.error,"aria-describedby":h.value,class:f([`w-full rounded-sm border bg-paper px-4 py-3 text-[15px] text-ink placeholder:text-ink-placeholder transition-colors duration-base focus:outline-none focus:border-brand disabled:opacity-50 disabled:cursor-not-allowed`,e.error?`border-danger`:`border-line`]),onInput:r[0]||=e=>n.$emit(`update:modelValue`,e.target.value)},null,42,b),e.hint&&!e.error?(t(),p(`p`,{key:1,id:c.value,class:`text-[13px] text-muted`},s(e.hint),9,x)):o(``,!0),e.error?(t(),p(`p`,{key:2,id:m.value,class:`text-[13px] text-danger`},s(e.error),9,S)):o(``,!0)]))}},w={class:`eyebrow mb-5`},T={class:`grid md:grid-cols-2 gap-6 max-w-3xl`},E={class:`eyebrow mb-5`},D={class:`grid md:grid-cols-2 gap-6 max-w-3xl`},O={__name:`InputsSection`,setup(a){let{t:o}=m(),l=e(``),u=e(``),f=e(``);return(e,a)=>(t(),r(h,{eyebrow:n(o)(`ds.eyebrow.components`),title:n(o)(`ds.inputs.title`),description:n(o)(`ds.inputs.description`)},{default:i(()=>[d(`section`,null,[d(`h2`,w,s(n(o)(`ds.heading.default`)),1),c(g,{tone:`paper`},{default:i(()=>[d(`div`,T,[c(C,{modelValue:l.value,"onUpdate:modelValue":a[0]||=e=>l.value=e,label:n(o)(`ds.inputs.email`),type:`email`,placeholder:`you@example.com`,hint:n(o)(`ds.inputs.emailHint`)},null,8,[`modelValue`,`label`,`hint`]),c(C,{modelValue:u.value,"onUpdate:modelValue":a[1]||=e=>u.value=e,label:n(o)(`ds.inputs.password`),type:`password`,placeholder:`••••••••`},null,8,[`modelValue`,`label`])])]),_:1})]),d(`section`,null,[d(`h2`,E,s(n(o)(`ds.heading.states`)),1),c(g,{tone:`paper`},{default:i(()=>[d(`div`,D,[c(C,{modelValue:f.value,"onUpdate:modelValue":a[2]||=e=>f.value=e,label:n(o)(`ds.inputs.required`),required:``,error:n(o)(`ds.inputs.requiredError`)},null,8,[`modelValue`,`label`,`error`]),c(C,{label:n(o)(`ds.inputs.disabled`),placeholder:n(o)(`ds.inputs.disabledPlaceholder`),disabled:``},null,8,[`label`,`placeholder`])])]),_:1})])]),_:1},8,[`eyebrow`,`title`,`description`]))}};export{O as default};

View File

@@ -1 +1 @@
import{C as e,G as t,T as n,lt as r,o as i,r as a,st as o,u as s}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as c}from"./i18n-DrTQks20.js";var l=[`aria-label`,`aria-pressed`,`onClick`],u={__name:`LanguageSwitcher`,props:{floating:{type:Boolean,default:!1},tone:{type:String,default:`paper`,validator:e=>[`paper`,`cream`,`brand`].includes(e)}},setup(u){let d=u,{locale:f,setLocale:p,availableLocales:m}=c(),h={paper:{container:`border border-line bg-paper`,active:`bg-brand text-accent`,inactive:`text-muted hover:text-brand`},cream:{container:`border border-line-strong bg-paper`,active:`bg-brand text-accent`,inactive:`text-muted hover:text-brand`},brand:{container:`border border-cream-line bg-cream-wash`,active:`bg-accent text-brand`,inactive:`text-cream hover:text-accent`}},g=i(()=>h[d.tone]);return(i,c)=>(e(),s(`div`,{role:`group`,"aria-label":`Language`,class:o([`inline-flex items-center h-10 px-2 gap-0.5 rounded-pill font-sans`,g.value.container,u.floating?`fixed top-6 right-6 z-[60] shadow-sm`:``])},[(e(!0),s(a,null,n(t(m),n=>(e(),s(`button`,{key:n.code,type:`button`,"aria-label":n.name,"aria-pressed":t(f)===n.code,class:o([`px-2.5 py-1 text-[11px] font-bold tracking-eyebrow rounded-pill transition-colors duration-base`,t(f)===n.code?g.value.active:g.value.inactive]),onClick:e=>t(p)(n.code)},r(n.label),11,l))),128))],2))}};export{u as t};
import{C as e,G as t,T as n,lt as r,o as i,r as a,st as o,u as s}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as c}from"./i18n-CJQl3WLC.js";var l=[`aria-label`,`aria-pressed`,`onClick`],u={__name:`LanguageSwitcher`,props:{floating:{type:Boolean,default:!1},tone:{type:String,default:`paper`,validator:e=>[`paper`,`cream`,`brand`].includes(e)}},setup(u){let d=u,{locale:f,setLocale:p,availableLocales:m}=c(),h={paper:{container:`border border-line bg-paper`,active:`bg-brand text-accent`,inactive:`text-muted hover:text-brand`},cream:{container:`border border-line-strong bg-paper`,active:`bg-brand text-accent`,inactive:`text-muted hover:text-brand`},brand:{container:`border border-cream-line bg-cream-wash`,active:`bg-accent text-brand`,inactive:`text-cream hover:text-accent`}},g=i(()=>h[d.tone]);return(i,c)=>(e(),s(`div`,{role:`group`,"aria-label":`Language`,class:o([`inline-flex items-center h-10 px-2 gap-0.5 rounded-pill font-sans`,g.value.container,u.floating?`fixed top-6 right-6 z-[60] shadow-sm`:``])},[(e(!0),s(a,null,n(t(m),n=>(e(),s(`button`,{key:n.code,type:`button`,"aria-label":n.name,"aria-pressed":t(f)===n.code,class:o([`px-2.5 py-1 text-[11px] font-bold tracking-eyebrow rounded-pill transition-colors duration-base`,t(f)===n.code?g.value.active:g.value.inactive]),onClick:e=>t(p)(n.code)},r(n.label),11,l))),128))],2))}};export{u as t};

View File

@@ -1,3 +1,3 @@
import{C as e,G as t,c as n,j as r,lt as i,m as a,s as o}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as s}from"./i18n-DrTQks20.js";import{t as c}from"./LanguageSwitcher-sWIzrbUO.js";import{t as l}from"./SectionShell-BEISUYi8.js";import{t as u}from"./Card-DM27vc3f.js";var d={class:`eyebrow mb-5`},f={class:`grid md:grid-cols-3 gap-4`},p={class:`eyebrow mb-4`},m={class:`text-[13px] text-muted mt-4 leading-relaxed`},h={class:`eyebrow mb-4`},g={class:`text-[13px] text-muted mt-4 leading-relaxed`},_={class:`eyebrow mb-4`},v={class:`text-[13px] opacity-80 mt-4 leading-relaxed`},y={class:`eyebrow mb-5`},b={class:`text-[13px] text-muted max-w-2xl leading-relaxed`},x={class:`eyebrow mb-5`},S={__name:`LanguageSwitcherSection`,setup(S){let{t:C}=s();return(s,S)=>(e(),n(l,{eyebrow:t(C)(`ds.eyebrow.components`),title:t(C)(`ds.language.title`),description:t(C)(`ds.language.description`)},{default:r(()=>[o(`section`,null,[o(`h2`,d,i(t(C)(`ds.heading.onDifferentSurfaces`)),1),o(`div`,f,[a(u,{tone:`paper`},{default:r(()=>[o(`p`,p,i(t(C)(`ds.cards.paper`)),1),a(c,{tone:`paper`}),o(`p`,m,i(t(C)(`ds.language.paperNote`)),1)]),_:1}),a(u,{tone:`cream`},{default:r(()=>[o(`p`,h,i(t(C)(`ds.cards.cream`)),1),a(c,{tone:`cream`}),o(`p`,g,i(t(C)(`ds.language.creamNote`)),1)]),_:1}),a(u,{tone:`brand`},{default:r(()=>[o(`p`,_,i(t(C)(`ds.cards.brand`)),1),a(c,{tone:`brand`}),o(`p`,v,i(t(C)(`ds.language.brandNote`)),1)]),_:1})])]),o(`section`,null,[o(`h2`,y,i(t(C)(`ds.language.floating`)),1),a(u,{tone:`paper`},{default:r(()=>[o(`p`,b,i(t(C)(`ds.language.floatingNote`)),1)]),_:1})]),o(`section`,null,[o(`h2`,x,i(t(C)(`ds.heading.usage`)),1),S[0]||=o(`div`,{class:`rounded-md border border-line bg-paper p-6 font-mono text-[12px] text-ink`},[o(`pre`,{class:`whitespace-pre-wrap`},`<LanguageSwitcher />
import{C as e,G as t,c as n,j as r,lt as i,m as a,s as o}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as s}from"./i18n-CJQl3WLC.js";import{t as c}from"./LanguageSwitcher-D0mrMmyq.js";import{t as l}from"./SectionShell-Cd_Fu3uI.js";import{t as u}from"./Card-pgd8VnYH.js";var d={class:`eyebrow mb-5`},f={class:`grid md:grid-cols-3 gap-4`},p={class:`eyebrow mb-4`},m={class:`text-[13px] text-muted mt-4 leading-relaxed`},h={class:`eyebrow mb-4`},g={class:`text-[13px] text-muted mt-4 leading-relaxed`},_={class:`eyebrow mb-4`},v={class:`text-[13px] opacity-80 mt-4 leading-relaxed`},y={class:`eyebrow mb-5`},b={class:`text-[13px] text-muted max-w-2xl leading-relaxed`},x={class:`eyebrow mb-5`},S={__name:`LanguageSwitcherSection`,setup(S){let{t:C}=s();return(s,S)=>(e(),n(l,{eyebrow:t(C)(`ds.eyebrow.components`),title:t(C)(`ds.language.title`),description:t(C)(`ds.language.description`)},{default:r(()=>[o(`section`,null,[o(`h2`,d,i(t(C)(`ds.heading.onDifferentSurfaces`)),1),o(`div`,f,[a(u,{tone:`paper`},{default:r(()=>[o(`p`,p,i(t(C)(`ds.cards.paper`)),1),a(c,{tone:`paper`}),o(`p`,m,i(t(C)(`ds.language.paperNote`)),1)]),_:1}),a(u,{tone:`cream`},{default:r(()=>[o(`p`,h,i(t(C)(`ds.cards.cream`)),1),a(c,{tone:`cream`}),o(`p`,g,i(t(C)(`ds.language.creamNote`)),1)]),_:1}),a(u,{tone:`brand`},{default:r(()=>[o(`p`,_,i(t(C)(`ds.cards.brand`)),1),a(c,{tone:`brand`}),o(`p`,v,i(t(C)(`ds.language.brandNote`)),1)]),_:1})])]),o(`section`,null,[o(`h2`,y,i(t(C)(`ds.language.floating`)),1),a(u,{tone:`paper`},{default:r(()=>[o(`p`,b,i(t(C)(`ds.language.floatingNote`)),1)]),_:1})]),o(`section`,null,[o(`h2`,x,i(t(C)(`ds.heading.usage`)),1),S[0]||=o(`div`,{class:`rounded-md border border-line bg-paper p-6 font-mono text-[12px] text-ink`},[o(`pre`,{class:`whitespace-pre-wrap`},`<LanguageSwitcher />
<LanguageSwitcher tone="brand" />
<LanguageSwitcher floating />`)],-1)])]),_:1},8,[`eyebrow`,`title`,`description`]))}};export{S as default};

View File

@@ -1 +1 @@
import{C as e,G as t,c as n,j as r,lt as i,m as a,s as o}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as s}from"./Logo-FFBeOKwm.js";import{t as c}from"./i18n-DrTQks20.js";import{t as l}from"./SectionShell-BEISUYi8.js";var u={class:`eyebrow mb-5`},d={class:`grid md:grid-cols-3 gap-4`},f={class:`rounded-md border border-line bg-paper p-10 flex flex-col items-center gap-4`},p={class:`font-mono text-[11px] text-muted`},m={class:`rounded-md border border-line bg-cream p-10 flex flex-col items-center gap-4`},h={class:`font-mono text-[11px] text-muted`},g={class:`rounded-md bg-brand p-10 flex flex-col items-center gap-4`},_={class:`font-mono text-[11px] text-cream opacity-70`},v={class:`eyebrow mb-5`},y={class:`rounded-md border border-line bg-paper p-10 flex items-end gap-10 flex-wrap`},b={class:`flex flex-col items-center gap-3`},x={class:`flex flex-col items-center gap-3`},S={class:`flex flex-col items-center gap-3`},C={class:`eyebrow mb-5`},w={class:`rounded-md border border-line bg-paper p-6 font-mono text-[12px] text-ink`},T={class:`mb-2 text-muted`},E={__name:`LogoSection`,setup(E){let{t:D}=c();return(c,E)=>(e(),n(l,{eyebrow:t(D)(`ds.eyebrow.brand`),title:t(D)(`ds.logo.title`),description:t(D)(`ds.logo.description`)},{default:r(()=>[o(`section`,null,[o(`h2`,u,i(t(D)(`ds.heading.onDifferentSurfaces`)),1),o(`div`,d,[o(`div`,f,[a(s,{class:`w-40 h-auto text-brand`}),o(`code`,p,i(t(D)(`ds.cards.paper`)),1)]),o(`div`,m,[a(s,{class:`w-40 h-auto text-brand`}),o(`code`,h,i(t(D)(`ds.cards.cream`)),1)]),o(`div`,g,[a(s,{class:`w-40 h-auto text-paper`}),o(`code`,_,i(t(D)(`ds.cards.brand`)),1)])])]),o(`section`,null,[o(`h2`,v,i(t(D)(`ds.heading.sizes`)),1),o(`div`,y,[o(`div`,b,[a(s,{class:`w-16 h-auto text-brand`}),E[0]||=o(`code`,{class:`font-mono text-[11px] text-muted`},`w-16`,-1)]),o(`div`,x,[a(s,{class:`w-32 h-auto text-brand`}),E[1]||=o(`code`,{class:`font-mono text-[11px] text-muted`},`w-32`,-1)]),o(`div`,S,[a(s,{class:`w-60 h-auto text-brand`}),E[2]||=o(`code`,{class:`font-mono text-[11px] text-muted`},`w-60`,-1)])])]),o(`section`,null,[o(`h2`,C,i(t(D)(`ds.heading.usage`)),1),o(`div`,w,[o(`p`,T,i(t(D)(`ds.logo.usageIntro`)),1),E[3]||=o(`pre`,{class:`whitespace-pre-wrap`},`<Logo class="w-60 h-auto text-brand" />`,-1)])])]),_:1},8,[`eyebrow`,`title`,`description`]))}};export{E as default};
import{C as e,G as t,c as n,j as r,lt as i,m as a,s as o}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as s}from"./Logo-FFBeOKwm.js";import{t as c}from"./i18n-CJQl3WLC.js";import{t as l}from"./SectionShell-Cd_Fu3uI.js";var u={class:`eyebrow mb-5`},d={class:`grid md:grid-cols-3 gap-4`},f={class:`rounded-md border border-line bg-paper p-10 flex flex-col items-center gap-4`},p={class:`font-mono text-[11px] text-muted`},m={class:`rounded-md border border-line bg-cream p-10 flex flex-col items-center gap-4`},h={class:`font-mono text-[11px] text-muted`},g={class:`rounded-md bg-brand p-10 flex flex-col items-center gap-4`},_={class:`font-mono text-[11px] text-cream opacity-70`},v={class:`eyebrow mb-5`},y={class:`rounded-md border border-line bg-paper p-10 flex items-end gap-10 flex-wrap`},b={class:`flex flex-col items-center gap-3`},x={class:`flex flex-col items-center gap-3`},S={class:`flex flex-col items-center gap-3`},C={class:`eyebrow mb-5`},w={class:`rounded-md border border-line bg-paper p-6 font-mono text-[12px] text-ink`},T={class:`mb-2 text-muted`},E={__name:`LogoSection`,setup(E){let{t:D}=c();return(c,E)=>(e(),n(l,{eyebrow:t(D)(`ds.eyebrow.brand`),title:t(D)(`ds.logo.title`),description:t(D)(`ds.logo.description`)},{default:r(()=>[o(`section`,null,[o(`h2`,u,i(t(D)(`ds.heading.onDifferentSurfaces`)),1),o(`div`,d,[o(`div`,f,[a(s,{class:`w-40 h-auto text-brand`}),o(`code`,p,i(t(D)(`ds.cards.paper`)),1)]),o(`div`,m,[a(s,{class:`w-40 h-auto text-brand`}),o(`code`,h,i(t(D)(`ds.cards.cream`)),1)]),o(`div`,g,[a(s,{class:`w-40 h-auto text-paper`}),o(`code`,_,i(t(D)(`ds.cards.brand`)),1)])])]),o(`section`,null,[o(`h2`,v,i(t(D)(`ds.heading.sizes`)),1),o(`div`,y,[o(`div`,b,[a(s,{class:`w-16 h-auto text-brand`}),E[0]||=o(`code`,{class:`font-mono text-[11px] text-muted`},`w-16`,-1)]),o(`div`,x,[a(s,{class:`w-32 h-auto text-brand`}),E[1]||=o(`code`,{class:`font-mono text-[11px] text-muted`},`w-32`,-1)]),o(`div`,S,[a(s,{class:`w-60 h-auto text-brand`}),E[2]||=o(`code`,{class:`font-mono text-[11px] text-muted`},`w-60`,-1)])])]),o(`section`,null,[o(`h2`,C,i(t(D)(`ds.heading.usage`)),1),o(`div`,w,[o(`p`,T,i(t(D)(`ds.logo.usageIntro`)),1),E[3]||=o(`pre`,{class:`whitespace-pre-wrap`},`<Logo class="w-60 h-auto text-brand" />`,-1)])])]),_:1},8,[`eyebrow`,`title`,`description`]))}};export{E as default};

File diff suppressed because one or more lines are too long

1
dist/assets/Navbar-DRsVuXxb.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
import{C as e,T as t,ct as n,m as r,o as i,r as a,s as o,u as s}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{a as c}from"./vue-router-QRVDVSxc.js";import{t as l}from"./Navbar-DTKm8Xku.js";var u={class:`min-h-screen bg-surface`},d={class:`max-w-5xl mx-auto px-6 py-16 space-y-6`},f={__name:`NavbarPreview`,setup(f){let p=c(),m=i(()=>{let e=p.query.variant;return[`paper`,`cream`,`brand`].includes(e)?e:`paper`}),h=i(()=>p.query.layout===`floating`?`floating`:`standard`);return(i,c)=>(e(),s(`div`,u,[r(l,{variant:m.value,layout:h.value,"cart-count":2},null,8,[`variant`,`layout`]),o(`div`,d,[(e(),s(a,null,t([40,28,40,32,40,28,36,40],e=>o(`div`,{key:e,class:`rounded-md border border-line bg-paper`,style:n({height:e*4+`px`})},null,4)),64))])]))}};export{f as default};
import{C as e,T as t,ct as n,m as r,o as i,r as a,s as o,u as s}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{a as c}from"./vue-router-QRVDVSxc.js";import{t as l}from"./Navbar-DRsVuXxb.js";var u={class:`min-h-screen bg-surface`},d={class:`max-w-5xl mx-auto px-6 py-16 space-y-6`},f={__name:`NavbarPreview`,setup(f){let p=c(),m=i(()=>{let e=p.query.variant;return[`paper`,`cream`,`brand`].includes(e)?e:`paper`}),h=i(()=>p.query.layout===`floating`?`floating`:`standard`);return(i,c)=>(e(),s(`div`,u,[r(l,{variant:m.value,layout:h.value,"cart-count":2},null,8,[`variant`,`layout`]),o(`div`,d,[(e(),s(a,null,t([40,28,40,32,40,28,36,40],e=>o(`div`,{key:e,class:`rounded-md border border-line bg-paper`,style:n({height:e*4+`px`})},null,4)),64))])]))}};export{f as default};

View File

@@ -1,4 +1,4 @@
import{B as e,C as t,G as n,T as r,c as i,ct as a,j as o,lt as s,m as c,o as l,p as u,r as d,s as f,st as p,u as m}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as h}from"./i18n-DrTQks20.js";import{t as g}from"./SectionShell-BEISUYi8.js";import{t as _}from"./DevicePreview-DvIWByfU.js";var v=[`aria-label`],y=[`aria-selected`,`onClick`],b=[`aria-label`],x=[`aria-selected`,`onClick`],S={class:`eyebrow mb-5`},C={__name:`NavbarSection`,setup(C){let{t:w}=h(),T=l(()=>[{id:`paper`,label:w(`ds.navbar.tone.paper`),swatch:`#ffffff`},{id:`cream`,label:w(`ds.navbar.tone.cream`),swatch:`var(--color-cream)`},{id:`brand`,label:w(`ds.navbar.tone.brand`),swatch:`var(--color-brand)`}]),E=l(()=>[{id:`standard`,label:w(`ds.navbar.layout.standard`)},{id:`floating`,label:w(`ds.navbar.layout.floating`)}]),D=e(`paper`),O=e(`standard`),k=l(()=>`/design/preview/navbar?variant=${D.value}&layout=${O.value}`);return(e,l)=>(t(),i(g,{eyebrow:n(w)(`ds.eyebrow.components`),title:n(w)(`ds.navbar.title`),description:n(w)(`ds.navbar.description`),wide:``},{default:o(()=>[f(`section`,null,[c(_,{src:k.value,initial:`mobile`,height:720},{controls:o(()=>[f(`div`,{role:`tablist`,"aria-label":n(w)(`ds.navbar.layout`),class:`inline-flex items-center p-1 gap-0.5 rounded-pill border border-line bg-paper`},[(t(!0),m(d,null,r(E.value,e=>(t(),m(`button`,{key:e.id,type:`button`,role:`tab`,"aria-selected":O.value===e.id,class:p([`px-3 py-1.5 text-[12px] font-semibold tracking-label rounded-pill transition-colors duration-base`,O.value===e.id?`bg-brand text-accent`:`text-muted hover:text-brand`]),onClick:t=>O.value=e.id},s(e.label),11,y))),128))],8,v),f(`div`,{role:`tablist`,"aria-label":n(w)(`ds.navbar.tone`),class:`inline-flex items-center p-1 gap-0.5 rounded-pill border border-line bg-paper`},[(t(!0),m(d,null,r(T.value,e=>(t(),m(`button`,{key:e.id,type:`button`,role:`tab`,"aria-selected":D.value===e.id,class:p([`inline-flex items-center gap-2 px-3 py-1.5 text-[12px] font-semibold tracking-label rounded-pill transition-colors duration-base`,D.value===e.id?`bg-brand text-accent`:`text-muted hover:text-brand`]),onClick:t=>D.value=e.id},[f(`span`,{class:`w-2.5 h-2.5 rounded-full border border-line-strong`,style:a({backgroundColor:e.swatch})},null,4),u(` `+s(e.label),1)],10,x))),128))],8,b)]),_:1},8,[`src`])]),f(`section`,null,[f(`h2`,S,s(n(w)(`ds.heading.usage`)),1),l[0]||=f(`div`,{class:`rounded-md border border-line bg-paper p-6 font-mono text-[12px] text-ink`},[f(`pre`,{class:`whitespace-pre-wrap`},`<Navbar
import{B as e,C as t,G as n,T as r,c as i,ct as a,j as o,lt as s,m as c,o as l,p as u,r as d,s as f,st as p,u as m}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as h}from"./i18n-CJQl3WLC.js";import{t as g}from"./SectionShell-Cd_Fu3uI.js";import{t as _}from"./DevicePreview-Dx8DzWeH.js";var v=[`aria-label`],y=[`aria-selected`,`onClick`],b=[`aria-label`],x=[`aria-selected`,`onClick`],S={class:`eyebrow mb-5`},C={__name:`NavbarSection`,setup(C){let{t:w}=h(),T=l(()=>[{id:`paper`,label:w(`ds.navbar.tone.paper`),swatch:`#ffffff`},{id:`cream`,label:w(`ds.navbar.tone.cream`),swatch:`var(--color-cream)`},{id:`brand`,label:w(`ds.navbar.tone.brand`),swatch:`var(--color-brand)`}]),E=l(()=>[{id:`standard`,label:w(`ds.navbar.layout.standard`)},{id:`floating`,label:w(`ds.navbar.layout.floating`)}]),D=e(`paper`),O=e(`standard`),k=l(()=>`/design/preview/navbar?variant=${D.value}&layout=${O.value}`);return(e,l)=>(t(),i(g,{eyebrow:n(w)(`ds.eyebrow.components`),title:n(w)(`ds.navbar.title`),description:n(w)(`ds.navbar.description`),wide:``},{default:o(()=>[f(`section`,null,[c(_,{src:k.value,initial:`mobile`,height:720},{controls:o(()=>[f(`div`,{role:`tablist`,"aria-label":n(w)(`ds.navbar.layout`),class:`inline-flex items-center p-1 gap-0.5 rounded-pill border border-line bg-paper`},[(t(!0),m(d,null,r(E.value,e=>(t(),m(`button`,{key:e.id,type:`button`,role:`tab`,"aria-selected":O.value===e.id,class:p([`px-3 py-1.5 text-[12px] font-semibold tracking-label rounded-pill transition-colors duration-base`,O.value===e.id?`bg-brand text-accent`:`text-muted hover:text-brand`]),onClick:t=>O.value=e.id},s(e.label),11,y))),128))],8,v),f(`div`,{role:`tablist`,"aria-label":n(w)(`ds.navbar.tone`),class:`inline-flex items-center p-1 gap-0.5 rounded-pill border border-line bg-paper`},[(t(!0),m(d,null,r(T.value,e=>(t(),m(`button`,{key:e.id,type:`button`,role:`tab`,"aria-selected":D.value===e.id,class:p([`inline-flex items-center gap-2 px-3 py-1.5 text-[12px] font-semibold tracking-label rounded-pill transition-colors duration-base`,D.value===e.id?`bg-brand text-accent`:`text-muted hover:text-brand`]),onClick:t=>D.value=e.id},[f(`span`,{class:`w-2.5 h-2.5 rounded-full border border-line-strong`,style:a({backgroundColor:e.swatch})},null,4),u(` `+s(e.label),1)],10,x))),128))],8,b)]),_:1},8,[`src`])]),f(`section`,null,[f(`h2`,S,s(n(w)(`ds.heading.usage`)),1),l[0]||=f(`div`,{class:`rounded-md border border-line bg-paper p-6 font-mono text-[12px] text-ink`},[f(`pre`,{class:`whitespace-pre-wrap`},`<Navbar
variant="paper"
layout="floating"
:items="[{ key: 'nav.shop', href: '/shop' }]"

1
dist/assets/ProductCard-Cxy5I4vQ.js vendored Normal file
View File

@@ -0,0 +1 @@
import{C as e,G as t,O as n,c as r,j as i,l as a,lt as o,m as s,o as c,p as l,s as u,st as d,u as f}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as p}from"./Icon-BCRRMV3J.js";import{t as m}from"./i18n-CJQl3WLC.js";import{t as h}from"./Badge-DcvgVKep.js";import{t as g}from"./Button-DkdaDkuf.js";var _=[`src`,`alt`],v={class:`flex flex-col gap-3 p-6`},y={class:`flex flex-col gap-1`},b={key:0,class:`text-sm text-muted tracking-label`},x={class:`mt-auto flex items-center justify-between gap-3 pt-2`},S={class:`font-display text-2xl font-normal text-brand`},C={key:0,class:`text-xs font-semibold tracking-label uppercase text-danger`},w={__name:`ProductCard`,props:{title:{type:String,required:!0},size:{type:String,default:``},price:{type:[String,Number],required:!0},currency:{type:String,default:``},image:{type:String,required:!0},imageAlt:{type:String,default:``},badge:{type:String,default:``},badgeVariant:{type:String,default:`accent`,validator:e=>[`neutral`,`brand`,`accent`,`subtle`,`success`,`warning`,`danger`].includes(e)},tone:{type:String,default:`paper`,validator:e=>[`paper`,`cream`].includes(e)},inStock:{type:Boolean,default:!0},href:{type:String,default:``}},emits:[`add`],setup(w){let T=w,{t:E}=m(),D={paper:{surface:`bg-paper`,media:`bg-cream`,border:`border-line`},cream:{surface:`bg-cream`,media:`bg-paper`,border:`border-line`}},O=c(()=>D[T.tone]),k=c(()=>typeof T.price==`number`?`${T.currency} ${T.price.toFixed(2).replace(`.`,`,`)}`:`${T.currency} ${T.price}`);return(c,m)=>(e(),f(`article`,{class:d([`group flex flex-col overflow-hidden rounded-md border transition-all duration-base ease-out`,O.value.surface,O.value.border,`hover:-translate-y-1 hover:shadow-md hover:border-brand-soft`])},[(e(),r(n(w.href?`a`:`div`),{href:w.href||null,class:d([`relative block aspect-[4/5] overflow-hidden`,O.value.media])},{default:i(()=>[w.badge?(e(),r(h,{key:0,variant:w.badgeVariant,class:`absolute top-4 left-4 z-[1]`},{default:i(()=>[l(o(w.badge),1)]),_:1},8,[`variant`])):a(``,!0),u(`img`,{src:w.image,alt:w.imageAlt||w.title,loading:`lazy`,decoding:`async`,class:`absolute inset-0 w-full h-full object-contain p-8 transition-transform duration-slow ease-out group-hover:scale-105`},null,8,_)]),_:1},8,[`href`,`class`])),u(`div`,v,[u(`div`,y,[(e(),r(n(w.href?`a`:`h3`),{href:w.href||null,class:d([`font-display text-xl font-normal leading-tight text-ink`,w.href?`hover:text-brand transition-colors duration-base`:``])},{default:i(()=>[l(o(w.title),1)]),_:1},8,[`href`,`class`])),w.size?(e(),f(`p`,b,o(w.size),1)):a(``,!0)]),u(`div`,x,[u(`span`,S,o(k.value),1),w.inStock?a(``,!0):(e(),f(`span`,C,o(t(E)(`ds.product.outOfStock`)),1))]),s(g,{variant:`primary`,size:`md`,block:``,disabled:!w.inStock,onClick:m[0]||=e=>c.$emit(`add`)},{before:i(()=>[s(p,{name:`plus`,size:16})]),default:i(()=>[l(` `+o(t(E)(`ds.buttons.addToCart`)),1)]),_:1},8,[`disabled`])])],2))}};export{w as t};

View File

@@ -1,11 +0,0 @@
import{B as e,C as t,G as n,O as r,c as i,j as a,l as o,lt as s,m as c,o as l,p as u,s as d,st as f,u as p}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as m}from"./Icon-BCRRMV3J.js";import{t as h}from"./i18n-DrTQks20.js";import{t as g}from"./Badge-DcvgVKep.js";import{t as _}from"./Button-DkdaDkuf.js";import{t as v}from"./SectionShell-BEISUYi8.js";var y=[`src`,`alt`],b={class:`flex flex-col gap-3 p-6`},x={class:`flex flex-col gap-1`},S={key:0,class:`text-sm text-muted tracking-label`},C={class:`mt-auto flex items-center justify-between gap-3 pt-2`},w={class:`font-display text-2xl font-normal text-brand`},T={key:0,class:`text-xs font-semibold tracking-label uppercase text-danger`},E={__name:`ProductCard`,props:{title:{type:String,required:!0},size:{type:String,default:``},price:{type:[String,Number],required:!0},currency:{type:String,default:``},image:{type:String,required:!0},imageAlt:{type:String,default:``},badge:{type:String,default:``},badgeVariant:{type:String,default:`accent`,validator:e=>[`neutral`,`brand`,`accent`,`subtle`,`success`,`warning`,`danger`].includes(e)},tone:{type:String,default:`paper`,validator:e=>[`paper`,`cream`].includes(e)},inStock:{type:Boolean,default:!0},href:{type:String,default:``}},emits:[`add`],setup(e){let v=e,{t:E}=h(),D={paper:{surface:`bg-paper`,media:`bg-cream`,border:`border-line`},cream:{surface:`bg-cream`,media:`bg-paper`,border:`border-line`}},O=l(()=>D[v.tone]),k=l(()=>typeof v.price==`number`?`${v.currency} ${v.price.toFixed(2).replace(`.`,`,`)}`:`${v.currency} ${v.price}`);return(l,h)=>(t(),p(`article`,{class:f([`group flex flex-col overflow-hidden rounded-md border transition-all duration-base ease-out`,O.value.surface,O.value.border,`hover:-translate-y-1 hover:shadow-md hover:border-brand-soft`])},[(t(),i(r(e.href?`a`:`div`),{href:e.href||null,class:f([`relative block aspect-[4/5] overflow-hidden`,O.value.media])},{default:a(()=>[e.badge?(t(),i(g,{key:0,variant:e.badgeVariant,class:`absolute top-4 left-4 z-[1]`},{default:a(()=>[u(s(e.badge),1)]),_:1},8,[`variant`])):o(``,!0),d(`img`,{src:e.image,alt:e.imageAlt||e.title,loading:`lazy`,decoding:`async`,class:`absolute inset-0 w-full h-full object-contain p-8 transition-transform duration-slow ease-out group-hover:scale-105`},null,8,y)]),_:1},8,[`href`,`class`])),d(`div`,b,[d(`div`,x,[(t(),i(r(e.href?`a`:`h3`),{href:e.href||null,class:f([`font-display text-xl font-normal leading-tight text-ink`,e.href?`hover:text-brand transition-colors duration-base`:``])},{default:a(()=>[u(s(e.title),1)]),_:1},8,[`href`,`class`])),e.size?(t(),p(`p`,S,s(e.size),1)):o(``,!0)]),d(`div`,C,[d(`span`,w,s(k.value),1),e.inStock?o(``,!0):(t(),p(`span`,T,s(n(E)(`ds.product.outOfStock`)),1))]),c(_,{variant:`primary`,size:`md`,block:``,disabled:!e.inStock,onClick:h[0]||=e=>l.$emit(`add`)},{before:a(()=>[c(m,{name:`plus`,size:16})]),default:a(()=>[u(` `+s(n(E)(`ds.buttons.addToCart`)),1)]),_:1},8,[`disabled`])])],2))}},D={class:`eyebrow mb-5`},O={class:`grid sm:grid-cols-2 lg:grid-cols-3 gap-6`},k={key:0,class:`mt-5 text-sm text-muted`},A={class:`font-mono text-[12px]`},j={class:`eyebrow mb-5`},M={class:`grid sm:grid-cols-2 lg:grid-cols-3 gap-6`},N={class:`eyebrow mb-5`},P=`/products/cutouts/kaiser-natron-pulver-250-g-grosspackung-removebg-preview-1.png`,F={__name:`ProductsSection`,setup(r){let{t:l}=h(),f=e(``);function m(e){f.value=e,setTimeout(()=>{f.value===e&&(f.value=``)},2e3)}return(e,r)=>(t(),i(v,{eyebrow:n(l)(`ds.eyebrow.components`),title:n(l)(`ds.product.title`),description:n(l)(`ds.product.description`)},{default:a(()=>[d(`section`,null,[d(`h2`,D,s(n(l)(`ds.heading.default`)),1),d(`div`,O,[c(E,{title:`Kaiser-Natron® Pulver`,size:`250 g Großpackung`,price:4.49,image:P,"image-alt":`Kaiser-Natron Pulver 250 g Großpackung`,href:`#`,onAdd:r[0]||=e=>m(`pulver-250`)}),c(E,{title:`Kaiser-Natron® Pulver`,size:`250 g Großpackung`,price:4.49,image:P,badge:n(l)(`ds.badges.featured`),"badge-variant":`accent`,href:`#`,onAdd:r[1]||=e=>m(`pulver-250-featured`)},null,8,[`badge`]),c(E,{title:`Kaiser-Natron® Pulver`,size:`250 g Großpackung`,price:4.49,image:P,tone:`cream`,href:`#`,onAdd:r[2]||=e=>m(`pulver-250-cream`)})]),f.value?(t(),p(`p`,k,[u(s(n(l)(`ds.product.added`))+`: `,1),d(`code`,A,s(f.value),1)])):o(``,!0)]),d(`section`,null,[d(`h2`,j,s(n(l)(`ds.heading.states`)),1),d(`div`,M,[c(E,{title:`Kaiser-Natron® Pulver`,size:`250 g Großpackung`,price:4.49,image:P,"in-stock":!1}),c(E,{title:`Kaiser-Natron® Pulver`,size:`250 g Großpackung`,price:4.49,image:P,badge:n(l)(`ds.badges.newRelease`),"badge-variant":`brand`,href:`#`},null,8,[`badge`])])]),d(`section`,null,[d(`h2`,N,s(n(l)(`ds.heading.usage`)),1),r[3]||=d(`div`,{class:`rounded-md border border-line bg-paper p-6 font-mono text-[12px] text-ink`},[d(`pre`,{class:`whitespace-pre-wrap`},`<ProductCard
title="Kaiser-Natron® Pulver"
size="250 g Großpackung"
:price="4.49"
image="/products/cutouts/…-removebg-preview.png"
badge="Bestseller"
badge-variant="accent"
tone="paper"
href="/kaiser-natron-pulver-250-g-grosspackung"
@add="addToCart(sku)"
/>`)],-1)])]),_:1},8,[`eyebrow`,`title`,`description`]))}};export{F as default};

11
dist/assets/ProductsSection-qRzVWVuD.js vendored Normal file
View File

@@ -0,0 +1,11 @@
import{B as e,C as t,G as n,c as r,j as i,l as a,lt as o,m as s,p as c,s as l,u}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as d}from"./i18n-CJQl3WLC.js";import{t as f}from"./ProductCard-Cxy5I4vQ.js";import{t as p}from"./SectionShell-Cd_Fu3uI.js";var m={class:`eyebrow mb-5`},h={class:`grid sm:grid-cols-2 lg:grid-cols-3 gap-6`},g={key:0,class:`mt-5 text-sm text-muted`},_={class:`font-mono text-[12px]`},v={class:`eyebrow mb-5`},y={class:`grid sm:grid-cols-2 lg:grid-cols-3 gap-6`},b={class:`eyebrow mb-5`},x=`/products/cutouts/kaiser-natron-pulver-250-g-grosspackung-removebg-preview-1.png`,S={__name:`ProductsSection`,setup(S){let{t:C}=d(),w=e(``);function T(e){w.value=e,setTimeout(()=>{w.value===e&&(w.value=``)},2e3)}return(e,d)=>(t(),r(p,{eyebrow:n(C)(`ds.eyebrow.components`),title:n(C)(`ds.product.title`),description:n(C)(`ds.product.description`)},{default:i(()=>[l(`section`,null,[l(`h2`,m,o(n(C)(`ds.heading.default`)),1),l(`div`,h,[s(f,{title:`Kaiser-Natron® Pulver`,size:`250 g Großpackung`,price:4.49,image:x,"image-alt":`Kaiser-Natron Pulver 250 g Großpackung`,href:`#`,onAdd:d[0]||=e=>T(`pulver-250`)}),s(f,{title:`Kaiser-Natron® Pulver`,size:`250 g Großpackung`,price:4.49,image:x,badge:n(C)(`ds.badges.featured`),"badge-variant":`accent`,href:`#`,onAdd:d[1]||=e=>T(`pulver-250-featured`)},null,8,[`badge`]),s(f,{title:`Kaiser-Natron® Pulver`,size:`250 g Großpackung`,price:4.49,image:x,tone:`cream`,href:`#`,onAdd:d[2]||=e=>T(`pulver-250-cream`)})]),w.value?(t(),u(`p`,g,[c(o(n(C)(`ds.product.added`))+`: `,1),l(`code`,_,o(w.value),1)])):a(``,!0)]),l(`section`,null,[l(`h2`,v,o(n(C)(`ds.heading.states`)),1),l(`div`,y,[s(f,{title:`Kaiser-Natron® Pulver`,size:`250 g Großpackung`,price:4.49,image:x,"in-stock":!1}),s(f,{title:`Kaiser-Natron® Pulver`,size:`250 g Großpackung`,price:4.49,image:x,badge:n(C)(`ds.badges.newRelease`),"badge-variant":`brand`,href:`#`},null,8,[`badge`])])]),l(`section`,null,[l(`h2`,b,o(n(C)(`ds.heading.usage`)),1),d[3]||=l(`div`,{class:`rounded-md border border-line bg-paper p-6 font-mono text-[12px] text-ink`},[l(`pre`,{class:`whitespace-pre-wrap`},`<ProductCard
title="Kaiser-Natron® Pulver"
size="250 g Großpackung"
:price="4.49"
image="/products/cutouts/…-removebg-preview.png"
badge="Bestseller"
badge-variant="accent"
tone="paper"
href="/kaiser-natron-pulver-250-g-grosspackung"
@add="addToCart(sku)"
/>`)],-1)])]),_:1},8,[`eyebrow`,`title`,`description`]))}};export{S as default};

View File

@@ -1,4 +1,4 @@
import{B as e,C as t,G as n,c as r,j as i,lt as a,m as o,s}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as c}from"./i18n-DrTQks20.js";import{t as l}from"./QuantityStepper-Bjh3X3wE.js";import{t as u}from"./SectionShell-BEISUYi8.js";var d={class:`eyebrow mb-5`},f={class:`flex flex-wrap items-center gap-6`},p={class:`eyebrow mb-5`},m={class:`flex flex-wrap items-center gap-6`},h={class:`flex flex-col gap-2`},g={class:`eyebrow`},_={class:`flex flex-col gap-2`},v={class:`eyebrow`},y={class:`flex flex-col gap-2`},b={class:`eyebrow`},x={class:`eyebrow mb-5`},S={__name:`QuantityStepperSection`,setup(S){let{t:C}=c(),w=e(1),T=e(3),E=e(5),D=e(2);return(e,c)=>(t(),r(u,{eyebrow:n(C)(`ds.eyebrow.components`),title:n(C)(`ds.qtyStepper.title`),description:n(C)(`ds.qtyStepper.description`)},{default:i(()=>[s(`section`,null,[s(`h2`,d,a(n(C)(`ds.heading.sizes`)),1),s(`div`,f,[o(l,{modelValue:w.value,"onUpdate:modelValue":c[0]||=e=>w.value=e,size:`sm`,"decrease-label":n(C)(`cart.qty.decrease`),"increase-label":n(C)(`cart.qty.increase`)},null,8,[`modelValue`,`decrease-label`,`increase-label`]),o(l,{modelValue:T.value,"onUpdate:modelValue":c[1]||=e=>T.value=e,size:`md`,"decrease-label":n(C)(`cart.qty.decrease`),"increase-label":n(C)(`cart.qty.increase`)},null,8,[`modelValue`,`decrease-label`,`increase-label`])])]),s(`section`,null,[s(`h2`,p,a(n(C)(`ds.heading.states`)),1),s(`div`,m,[s(`div`,h,[s(`span`,g,a(n(C)(`ds.qtyStepper.minBoundary`)),1),o(l,{"model-value":0,min:0,"decrease-label":n(C)(`cart.qty.decrease`),"increase-label":n(C)(`cart.qty.increase`)},null,8,[`decrease-label`,`increase-label`])]),s(`div`,_,[s(`span`,v,a(n(C)(`ds.qtyStepper.maxBoundary`)),1),o(l,{modelValue:E.value,"onUpdate:modelValue":c[2]||=e=>E.value=e,max:5,"decrease-label":n(C)(`cart.qty.decrease`),"increase-label":n(C)(`cart.qty.increase`)},null,8,[`modelValue`,`decrease-label`,`increase-label`])]),s(`div`,y,[s(`span`,b,a(n(C)(`ds.buttons.disabled`)),1),o(l,{modelValue:D.value,"onUpdate:modelValue":c[3]||=e=>D.value=e,disabled:``,"decrease-label":n(C)(`cart.qty.decrease`),"increase-label":n(C)(`cart.qty.increase`)},null,8,[`modelValue`,`decrease-label`,`increase-label`])])])]),s(`section`,null,[s(`h2`,x,a(n(C)(`ds.heading.usage`)),1),c[4]||=s(`div`,{class:`rounded-md border border-line bg-paper p-6 font-mono text-[12px] text-ink`},[s(`pre`,{class:`whitespace-pre-wrap`},`<QuantityStepper
import{B as e,C as t,G as n,c as r,j as i,lt as a,m as o,s}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as c}from"./i18n-CJQl3WLC.js";import{t as l}from"./QuantityStepper-Bjh3X3wE.js";import{t as u}from"./SectionShell-Cd_Fu3uI.js";var d={class:`eyebrow mb-5`},f={class:`flex flex-wrap items-center gap-6`},p={class:`eyebrow mb-5`},m={class:`flex flex-wrap items-center gap-6`},h={class:`flex flex-col gap-2`},g={class:`eyebrow`},_={class:`flex flex-col gap-2`},v={class:`eyebrow`},y={class:`flex flex-col gap-2`},b={class:`eyebrow`},x={class:`eyebrow mb-5`},S={__name:`QuantityStepperSection`,setup(S){let{t:C}=c(),w=e(1),T=e(3),E=e(5),D=e(2);return(e,c)=>(t(),r(u,{eyebrow:n(C)(`ds.eyebrow.components`),title:n(C)(`ds.qtyStepper.title`),description:n(C)(`ds.qtyStepper.description`)},{default:i(()=>[s(`section`,null,[s(`h2`,d,a(n(C)(`ds.heading.sizes`)),1),s(`div`,f,[o(l,{modelValue:w.value,"onUpdate:modelValue":c[0]||=e=>w.value=e,size:`sm`,"decrease-label":n(C)(`cart.qty.decrease`),"increase-label":n(C)(`cart.qty.increase`)},null,8,[`modelValue`,`decrease-label`,`increase-label`]),o(l,{modelValue:T.value,"onUpdate:modelValue":c[1]||=e=>T.value=e,size:`md`,"decrease-label":n(C)(`cart.qty.decrease`),"increase-label":n(C)(`cart.qty.increase`)},null,8,[`modelValue`,`decrease-label`,`increase-label`])])]),s(`section`,null,[s(`h2`,p,a(n(C)(`ds.heading.states`)),1),s(`div`,m,[s(`div`,h,[s(`span`,g,a(n(C)(`ds.qtyStepper.minBoundary`)),1),o(l,{"model-value":0,min:0,"decrease-label":n(C)(`cart.qty.decrease`),"increase-label":n(C)(`cart.qty.increase`)},null,8,[`decrease-label`,`increase-label`])]),s(`div`,_,[s(`span`,v,a(n(C)(`ds.qtyStepper.maxBoundary`)),1),o(l,{modelValue:E.value,"onUpdate:modelValue":c[2]||=e=>E.value=e,max:5,"decrease-label":n(C)(`cart.qty.decrease`),"increase-label":n(C)(`cart.qty.increase`)},null,8,[`modelValue`,`decrease-label`,`increase-label`])]),s(`div`,y,[s(`span`,b,a(n(C)(`ds.buttons.disabled`)),1),o(l,{modelValue:D.value,"onUpdate:modelValue":c[3]||=e=>D.value=e,disabled:``,"decrease-label":n(C)(`cart.qty.decrease`),"increase-label":n(C)(`cart.qty.increase`)},null,8,[`modelValue`,`decrease-label`,`increase-label`])])])]),s(`section`,null,[s(`h2`,x,a(n(C)(`ds.heading.usage`)),1),c[4]||=s(`div`,{class:`rounded-md border border-line bg-paper p-6 font-mono text-[12px] text-ink`},[s(`pre`,{class:`whitespace-pre-wrap`},`<QuantityStepper
v-model="quantity"
:min="0"
:max="10"

View File

@@ -1 +1 @@
import{C as e,G as t,T as n,c as r,ct as i,j as a,lt as o,r as s,s as c,u as l}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as u}from"./i18n-DrTQks20.js";import{t as d}from"./SectionShell-BEISUYi8.js";var f={class:`grid grid-cols-2 sm:grid-cols-3 gap-6`},p={class:`font-mono text-[12px] text-ink block`},m={class:`text-[12px] text-muted mt-1`},h={__name:`RadiiSection`,setup(h){let{t:g}=u(),_=[{name:`xs`,value:`6px`},{name:`sm`,value:`10px`},{name:`md`,value:`16px`},{name:`lg`,value:`20px`},{name:`xl`,value:`28px`},{name:`pill`,value:`100px`}];return(u,h)=>(e(),r(d,{eyebrow:t(g)(`ds.eyebrow.tokens`),title:t(g)(`ds.radii.title`),description:t(g)(`ds.radii.description`)},{default:a(()=>[c(`div`,f,[(e(),l(s,null,n(_,e=>c(`div`,{key:e.name,class:`flex flex-col items-center`},[c(`div`,{class:`h-32 w-full bg-paper border border-line mb-4 shadow-sm`,style:i({borderRadius:`var(--radius-${e.name})`})},null,4),c(`code`,p,`--radius-`+o(e.name),1),c(`span`,m,o(e.value),1)])),64))])]),_:1},8,[`eyebrow`,`title`,`description`]))}};export{h as default};
import{C as e,G as t,T as n,c as r,ct as i,j as a,lt as o,r as s,s as c,u as l}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as u}from"./i18n-CJQl3WLC.js";import{t as d}from"./SectionShell-Cd_Fu3uI.js";var f={class:`grid grid-cols-2 sm:grid-cols-3 gap-6`},p={class:`font-mono text-[12px] text-ink block`},m={class:`text-[12px] text-muted mt-1`},h={__name:`RadiiSection`,setup(h){let{t:g}=u(),_=[{name:`xs`,value:`6px`},{name:`sm`,value:`10px`},{name:`md`,value:`16px`},{name:`lg`,value:`20px`},{name:`xl`,value:`28px`},{name:`pill`,value:`100px`}];return(u,h)=>(e(),r(d,{eyebrow:t(g)(`ds.eyebrow.tokens`),title:t(g)(`ds.radii.title`),description:t(g)(`ds.radii.description`)},{default:a(()=>[c(`div`,f,[(e(),l(s,null,n(_,e=>c(`div`,{key:e.name,class:`flex flex-col items-center`},[c(`div`,{class:`h-32 w-full bg-paper border border-line mb-4 shadow-sm`,style:i({borderRadius:`var(--radius-${e.name})`})},null,4),c(`code`,p,`--radius-`+o(e.name),1),c(`span`,m,o(e.value),1)])),64))])]),_:1},8,[`eyebrow`,`title`,`description`]))}};export{h as default};

View File

@@ -0,0 +1 @@
.rv-orbit[data-v-04135cd6]{width:var(--size-orbit);height:var(--size-orbit);justify-content:center;align-items:center;display:inline-flex;position:relative}.rv-orbit-ring[data-v-04135cd6]{border:1px solid color-mix(in oklab, var(--color-accent) 60%, transparent);background:color-mix(in oklab, var(--color-accent) 6%, transparent);animation:var(--animate-orbit);border-radius:9999px;position:absolute;inset:0}.rv-orbit-dot[data-v-04135cd6]{background:var(--color-accent);width:6px;height:6px;box-shadow:0 0 8px color-mix(in oklab, var(--color-accent) 55%, transparent);border-radius:9999px;margin-left:-3px;position:absolute;top:-3px;left:50%}.rv-orbit-center[data-v-04135cd6]{filter:drop-shadow(0 1px 2px #00000040);font-size:22px;line-height:1}

View File

@@ -0,0 +1 @@
import{C as e,T as t,c as n,ct as r,j as i,l as a,lt as o,m as s,p as c,r as l,s as u,u as d}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as f}from"./_plugin-vue_export-helper-BOai-rQB.js";import{t as p}from"./Badge-DcvgVKep.js";import{t as m}from"./Button-DkdaDkuf.js";var h={id:`revitalize`,class:`bg-brand text-cream`},g={class:`mx-auto w-full max-w-6xl px-6 py-16 sm:px-8 sm:py-20 md:px-12 md:py-24 lg:px-16 lg:py-28`},_={class:`flex flex-col items-center text-center gap-6 max-w-3xl mx-auto`},v={key:1,class:`font-display font-normal leading-[1.04] tracking-tight text-headline-lg`},y={key:0,class:`italic font-light text-accent-soft`},b={key:2,class:`text-lg leading-relaxed text-cream/80 max-w-2xl`},x={key:0,class:`mt-10 md:mt-14 grid gap-6 sm:grid-cols-3 sm:gap-8 max-w-4xl mx-auto`},S={"aria-hidden":`true`,class:`rv-orbit`},C={key:0,class:`rv-orbit-center`},w={class:`font-sans text-base font-semibold text-cream leading-snug`},T={key:1,class:`mt-10 md:mt-14 flex justify-center`},E=f({__name:`Revitalization`,props:{eyebrow:{type:String,default:``},headline:{type:String,default:``},headlineEm:{type:String,default:``},sub:{type:String,default:``},features:{type:Array,default:()=>[],validator:e=>e.every(e=>typeof e==`string`||e&&typeof e==`object`&&typeof e.title==`string`)},notifyCta:{type:String,default:``}},emits:[`notify`],setup(f){return(E,D)=>(e(),d(`section`,h,[u(`div`,g,[u(`div`,_,[f.eyebrow?(e(),n(p,{key:0,variant:`accent`},{default:i(()=>[c(o(f.eyebrow),1)]),_:1})):a(``,!0),f.headline||f.headlineEm?(e(),d(`h2`,v,[c(o(f.headline)+` `,1),f.headlineEm?(e(),d(`em`,y,o(f.headlineEm),1)):a(``,!0)])):a(``,!0),f.sub?(e(),d(`p`,b,o(f.sub),1)):a(``,!0)]),f.features.length?(e(),d(`ul`,x,[(e(!0),d(l,null,t(f.features.slice(0,3),(t,n)=>(e(),d(`li`,{key:typeof t==`string`?t:t.title,class:`flex flex-col items-center gap-4 text-center`},[u(`span`,S,[u(`span`,{class:`rv-orbit-ring`,style:r({animationDelay:`${n*-5}s`})},[...D[1]||=[u(`span`,{class:`rv-orbit-dot`},null,-1)]],4),typeof t==`object`&&t.icon?(e(),d(`span`,C,o(t.icon),1)):a(``,!0)]),u(`span`,w,o(typeof t==`string`?t:t.title),1)]))),128))])):a(``,!0),f.notifyCta?(e(),d(`div`,T,[s(m,{variant:`accent`,size:`lg`,onClick:D[0]||=e=>E.$emit(`notify`)},{default:i(()=>[c(o(f.notifyCta),1)]),_:1})])):a(``,!0)])]))}},[[`__scopeId`,`data-v-04135cd6`]]);export{E as t};

View File

@@ -1 +0,0 @@
import{C as e,T as t,c as n,ct as r,j as i,l as a,lt as o,m as s,p as c,r as l,s as u,u as d}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as f}from"./_plugin-vue_export-helper-BOai-rQB.js";import{t as p}from"./Badge-DcvgVKep.js";import{t as m}from"./Button-DkdaDkuf.js";var h={id:`revitalize`,class:`bg-brand text-cream`},g={class:`mx-auto w-full max-w-6xl px-6 py-16 sm:px-8 sm:py-20 md:px-12 md:py-24 lg:px-16 lg:py-28`},_={class:`flex flex-col items-center text-center gap-6 max-w-3xl mx-auto`},v={key:1,class:`font-display font-normal leading-[1.04] tracking-tight`,style:{"font-size":`clamp(2.25rem, 5vw, 3.75rem)`}},y={key:0,class:`italic font-light text-accent-soft`},b={key:2,class:`text-lg leading-relaxed text-cream/80 max-w-2xl`},x={key:0,class:`mt-10 md:mt-14 grid gap-6 sm:grid-cols-3 sm:gap-8 max-w-4xl mx-auto`},S={"aria-hidden":`true`,class:`rv-orbit`},C={key:0,class:`rv-orbit-center`},w={class:`font-sans text-base font-semibold text-cream leading-snug`},T={key:1,class:`mt-10 md:mt-14 flex justify-center`},E=f({__name:`Revitalization`,props:{eyebrow:{type:String,default:``},headline:{type:String,default:``},headlineEm:{type:String,default:``},sub:{type:String,default:``},features:{type:Array,default:()=>[],validator:e=>e.every(e=>typeof e==`string`||e&&typeof e==`object`&&typeof e.title==`string`)},notifyCta:{type:String,default:``}},emits:[`notify`],setup(f){return(E,D)=>(e(),d(`section`,h,[u(`div`,g,[u(`div`,_,[f.eyebrow?(e(),n(p,{key:0,variant:`accent`},{default:i(()=>[c(o(f.eyebrow),1)]),_:1})):a(``,!0),f.headline||f.headlineEm?(e(),d(`h2`,v,[c(o(f.headline)+` `,1),f.headlineEm?(e(),d(`em`,y,o(f.headlineEm),1)):a(``,!0)])):a(``,!0),f.sub?(e(),d(`p`,b,o(f.sub),1)):a(``,!0)]),f.features.length?(e(),d(`ul`,x,[(e(!0),d(l,null,t(f.features.slice(0,3),(t,n)=>(e(),d(`li`,{key:typeof t==`string`?t:t.title,class:`flex flex-col items-center gap-4 text-center`},[u(`span`,S,[u(`span`,{class:`rv-orbit-ring`,style:r({animationDelay:`${n*-5}s`})},[...D[1]||=[u(`span`,{class:`rv-orbit-dot`},null,-1)]],4),typeof t==`object`&&t.icon?(e(),d(`span`,C,o(t.icon),1)):a(``,!0)]),u(`span`,w,o(typeof t==`string`?t:t.title),1)]))),128))])):a(``,!0),f.notifyCta?(e(),d(`div`,T,[s(m,{variant:`accent`,size:`lg`,onClick:D[0]||=e=>E.$emit(`notify`)},{default:i(()=>[c(o(f.notifyCta),1)]),_:1})])):a(``,!0)])]))}},[[`__scopeId`,`data-v-ec4233b0`]]);export{E as t};

View File

@@ -1 +0,0 @@
.rv-orbit[data-v-ec4233b0]{justify-content:center;align-items:center;width:72px;height:72px;display:inline-flex;position:relative}.rv-orbit-ring[data-v-ec4233b0]{border:1px solid color-mix(in oklab, var(--color-accent) 60%, transparent);background:color-mix(in oklab, var(--color-accent) 6%, transparent);animation:var(--animate-orbit);border-radius:9999px;position:absolute;inset:0}.rv-orbit-dot[data-v-ec4233b0]{background:var(--color-accent);width:6px;height:6px;box-shadow:0 0 8px color-mix(in oklab, var(--color-accent) 55%, transparent);border-radius:9999px;margin-left:-3px;position:absolute;top:-3px;left:50%}.rv-orbit-center[data-v-ec4233b0]{filter:drop-shadow(0 1px 2px #00000040);font-size:22px;line-height:1}

View File

@@ -1 +1 @@
import{C as e,G as t,m as n,o as r,u as i}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as a}from"./i18n-DrTQks20.js";import{t as o}from"./Revitalization-Dbf9J8TA.js";var s={class:`min-h-screen bg-brand`},c={__name:`RevitalizationPreview`,setup(c){let{t:l}=a(),u=r(()=>[{title:l(`revit.feature.1.title`),icon:`⚗️`},{title:l(`revit.feature.2.title`),icon:`💊`},{title:l(`revit.feature.3.title`),icon:`🌿`}]);return(r,a)=>(e(),i(`div`,s,[n(o,{eyebrow:t(l)(`revit.eyebrow`),headline:t(l)(`revit.headline.a`),"headline-em":t(l)(`revit.headline.em`),sub:t(l)(`revit.sub`),features:u.value,"notify-cta":t(l)(`revit.notifyCta`)},null,8,[`eyebrow`,`headline`,`headline-em`,`sub`,`features`,`notify-cta`])]))}};export{c as default};
import{C as e,G as t,m as n,o as r,u as i}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as a}from"./i18n-CJQl3WLC.js";import{t as o}from"./Revitalization-D6Ehuu8K.js";var s={class:`min-h-screen bg-brand`},c={__name:`RevitalizationPreview`,setup(c){let{t:l}=a(),u=r(()=>[{title:l(`revit.feature.1.title`),icon:`⚗️`},{title:l(`revit.feature.2.title`),icon:`💊`},{title:l(`revit.feature.3.title`),icon:`🌿`}]);return(r,a)=>(e(),i(`div`,s,[n(o,{eyebrow:t(l)(`revit.eyebrow`),headline:t(l)(`revit.headline.a`),"headline-em":t(l)(`revit.headline.em`),sub:t(l)(`revit.sub`),features:u.value,"notify-cta":t(l)(`revit.notifyCta`)},null,8,[`eyebrow`,`headline`,`headline-em`,`sub`,`features`,`notify-cta`])]))}};export{c as default};

View File

@@ -1,4 +1,4 @@
import{C as e,G as t,c as n,j as r,lt as i,m as a,s as o}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as s}from"./i18n-DrTQks20.js";import{t as c}from"./SectionShell-BEISUYi8.js";import{t as l}from"./DevicePreview-DvIWByfU.js";var u={class:`eyebrow mb-5`},d=`/design/preview/revitalization`,f={__name:`RevitalizationSection`,setup(f){let{t:p}=s();return(s,f)=>(e(),n(c,{eyebrow:t(p)(`ds.eyebrow.components`),title:t(p)(`ds.revitalization.title`),description:t(p)(`ds.revitalization.description`),wide:``},{default:r(()=>[o(`section`,null,[a(l,{src:d,initial:`desktop`,height:720})]),o(`section`,null,[o(`h2`,u,i(t(p)(`ds.heading.usage`)),1),f[0]||=o(`div`,{class:`rounded-md border border-line bg-paper p-6 font-mono text-[12px] text-ink`},[o(`pre`,{class:`whitespace-pre-wrap`},`<Revitalization
import{C as e,G as t,c as n,j as r,lt as i,m as a,s as o}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as s}from"./i18n-CJQl3WLC.js";import{t as c}from"./SectionShell-Cd_Fu3uI.js";import{t as l}from"./DevicePreview-Dx8DzWeH.js";var u={class:`eyebrow mb-5`},d=`/design/preview/revitalization`,f={__name:`RevitalizationSection`,setup(f){let{t:p}=s();return(s,f)=>(e(),n(c,{eyebrow:t(p)(`ds.eyebrow.components`),title:t(p)(`ds.revitalization.title`),description:t(p)(`ds.revitalization.description`),wide:``},{default:r(()=>[o(`section`,null,[a(l,{src:d,initial:`desktop`,height:720})]),o(`section`,null,[o(`h2`,u,i(t(p)(`ds.heading.usage`)),1),f[0]||=o(`div`,{class:`rounded-md border border-line bg-paper p-6 font-mono text-[12px] text-ink`},[o(`pre`,{class:`whitespace-pre-wrap`},`<Revitalization
:eyebrow="t('revit.eyebrow')"
:headline="t('revit.headline.a')"
:headline-em="t('revit.headline.em')"

File diff suppressed because one or more lines are too long

1
dist/assets/Search-BYh1LNrJ.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
.search-input[data-v-3782d7e2]::-webkit-search-cancel-button{appearance:none}.search-input[data-v-3782d7e2]::-webkit-search-decoration{appearance:none}

1
dist/assets/Search-dtR7osTa.css vendored Normal file
View File

@@ -0,0 +1 @@
.search-input[data-v-5b95e6b1]::-webkit-search-cancel-button{appearance:none}.search-input[data-v-5b95e6b1]::-webkit-search-decoration{appearance:none}

View File

@@ -1,4 +1,4 @@
import{B as e,C as t,G as n,T as r,c as i,j as a,lt as o,m as s,p as c,r as l,s as u,u as d}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as f}from"./Icon-BCRRMV3J.js";import{t as p}from"./i18n-DrTQks20.js";import{t as m}from"./Search-5Gw6O_vh.js";import{n as h,r as g}from"./products-GEWPSJSp.js";import{t as _}from"./Button-DkdaDkuf.js";import{t as v}from"./SectionShell-BEISUYi8.js";var y={class:`eyebrow mb-5`},b={class:`rounded-md border border-line bg-paper p-6 flex flex-col sm:flex-row sm:items-center gap-4`},x={class:`text-[13px] text-muted`},S={class:`eyebrow mb-5`},C={class:`rounded-md border border-line bg-paper divide-y divide-line overflow-hidden`},w=[`src`,`alt`],T={class:`min-w-0 flex-1`},E={class:`text-[14px] font-semibold text-ink truncate`},D={class:`text-[12px] text-muted truncate`},O={class:`shrink-0 text-[13px] font-semibold text-brand`},k={class:`eyebrow mb-5`},A=`natron pulver`,j={__name:`SearchSection`,setup(j){let{t:M}=p(),N=e(!1),P=g(A,h,4);return(e,p)=>(t(),i(v,{eyebrow:n(M)(`ds.eyebrow.components`),title:n(M)(`ds.search.title`),description:n(M)(`ds.search.description`)},{default:a(()=>[u(`section`,null,[u(`h2`,y,o(n(M)(`ds.heading.default`)),1),u(`div`,b,[s(_,{variant:`primary`,onClick:p[0]||=e=>N.value=!0},{before:a(()=>[s(f,{name:`search`,size:18})]),default:a(()=>[c(` `+o(n(M)(`ds.search.demo.label`)),1)]),_:1}),u(`p`,x,o(n(M)(`ds.search.demo.hint`)),1)])]),u(`section`,null,[u(`h2`,S,o(n(M)(`ds.heading.variants`))+` — "`+o(A)+`"`,1),u(`ul`,C,[(t(!0),d(l,null,r(n(P),e=>(t(),d(`li`,{key:e.id,class:`flex items-center gap-4 px-4 py-3`},[u(`img`,{src:e.image,alt:e.title,loading:`lazy`,decoding:`async`,class:`shrink-0 w-12 h-12 rounded-sm object-cover bg-cream`},null,8,w),u(`div`,T,[u(`p`,E,o(e.title),1),u(`p`,D,o(e.size)+` · `+o(e.category),1)]),u(`span`,O,``+o(e.price.toFixed(2).replace(`.`,`,`)),1)]))),128))])]),u(`section`,null,[u(`h2`,k,o(n(M)(`ds.heading.usage`)),1),p[2]||=u(`div`,{class:`rounded-md border border-line bg-paper p-6 font-mono text-[12px] text-ink`},[u(`pre`,{class:`whitespace-pre-wrap`},`import { products } from '@/api/products.js'
import{B as e,C as t,G as n,T as r,c as i,j as a,lt as o,m as s,p as c,r as l,s as u,u as d}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as f}from"./Icon-BCRRMV3J.js";import{t as p}from"./i18n-CJQl3WLC.js";import{t as m}from"./Search-BYh1LNrJ.js";import{a as h,r as g}from"./products-Dhgp5EjC.js";import{t as _}from"./Button-DkdaDkuf.js";import{t as v}from"./SectionShell-Cd_Fu3uI.js";var y={class:`eyebrow mb-5`},b={class:`rounded-md border border-line bg-paper p-6 flex flex-col sm:flex-row sm:items-center gap-4`},x={class:`text-[13px] text-muted`},S={class:`eyebrow mb-5`},C={class:`rounded-md border border-line bg-paper divide-y divide-line overflow-hidden`},w=[`src`,`alt`],T={class:`min-w-0 flex-1`},E={class:`text-[14px] font-semibold text-ink truncate`},D={class:`text-[12px] text-muted truncate`},O={class:`shrink-0 text-[13px] font-semibold text-brand`},k={class:`eyebrow mb-5`},A=`natron pulver`,j={__name:`SearchSection`,setup(j){let{t:M}=p(),N=e(!1),P=h(A,g,4);return(e,p)=>(t(),i(v,{eyebrow:n(M)(`ds.eyebrow.components`),title:n(M)(`ds.search.title`),description:n(M)(`ds.search.description`)},{default:a(()=>[u(`section`,null,[u(`h2`,y,o(n(M)(`ds.heading.default`)),1),u(`div`,b,[s(_,{variant:`primary`,onClick:p[0]||=e=>N.value=!0},{before:a(()=>[s(f,{name:`search`,size:18})]),default:a(()=>[c(` `+o(n(M)(`ds.search.demo.label`)),1)]),_:1}),u(`p`,x,o(n(M)(`ds.search.demo.hint`)),1)])]),u(`section`,null,[u(`h2`,S,o(n(M)(`ds.heading.variants`))+` — "`+o(A)+`"`,1),u(`ul`,C,[(t(!0),d(l,null,r(n(P),e=>(t(),d(`li`,{key:e.id,class:`flex items-center gap-4 px-4 py-3`},[u(`img`,{src:e.image,alt:e.title,loading:`lazy`,decoding:`async`,class:`shrink-0 w-12 h-12 rounded-sm object-cover bg-cream`},null,8,w),u(`div`,T,[u(`p`,E,o(e.title),1),u(`p`,D,o(e.size)+` · `+o(e.category),1)]),u(`span`,O,``+o(e.price.toFixed(2).replace(`.`,`,`)),1)]))),128))])]),u(`section`,null,[u(`h2`,k,o(n(M)(`ds.heading.usage`)),1),p[2]||=u(`div`,{class:`rounded-md border border-line bg-paper p-6 font-mono text-[12px] text-ink`},[u(`pre`,{class:`whitespace-pre-wrap`},`import { products } from '@/api/products.js'
import Search from '@/design-system/components/Search.vue'
const open = ref(false)
@@ -8,4 +8,4 @@ const open = ref(false)
// Navbar already renders its own Search overlay, so most callers
// just pass the catalogue in:
<Navbar :products="products" />`)],-1)]),s(m,{open:N.value,"onUpdate:open":p[1]||=e=>N.value=e,products:n(h)},null,8,[`open`,`products`])]),_:1},8,[`eyebrow`,`title`,`description`]))}};export{j as default};
<Navbar :products="products" />`)],-1)]),s(m,{open:N.value,"onUpdate:open":p[1]||=e=>N.value=e,products:n(g)},null,8,[`open`,`products`])]),_:1},8,[`eyebrow`,`title`,`description`]))}};export{j as default};

View File

@@ -1 +1 @@
import{C as e,G as t,T as n,c as r,ct as i,j as a,lt as o,o as s,r as c,s as l,u}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as d}from"./i18n-DrTQks20.js";import{t as f}from"./SectionShell-BEISUYi8.js";var p={class:`grid sm:grid-cols-3 gap-8`},m={class:`font-mono text-[12px] text-ink block`},h={class:`text-[13px] text-muted mt-1`},g={__name:`ShadowsSection`,setup(g){let{t:_}=d(),v=s(()=>[{name:`sm`,css:`var(--shadow-sm)`,note:_(`ds.shadows.sm.note`)},{name:`md`,css:`var(--shadow-md)`,note:_(`ds.shadows.md.note`)},{name:`lg`,css:`var(--shadow-lg)`,note:_(`ds.shadows.lg.note`)}]);return(s,d)=>(e(),r(f,{eyebrow:t(_)(`ds.eyebrow.tokens`),title:t(_)(`ds.shadows.title`),description:t(_)(`ds.shadows.description`)},{default:a(()=>[l(`div`,p,[(e(!0),u(c,null,n(v.value,t=>(e(),u(`div`,{key:t.name,class:`space-y-4`},[l(`div`,{class:`h-36 rounded-md bg-paper`,style:i({boxShadow:t.css})},null,4),l(`div`,null,[l(`code`,m,`--shadow-`+o(t.name),1),l(`p`,h,o(t.note),1)])]))),128))])]),_:1},8,[`eyebrow`,`title`,`description`]))}};export{g as default};
import{C as e,G as t,T as n,c as r,ct as i,j as a,lt as o,o as s,r as c,s as l,u}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as d}from"./i18n-CJQl3WLC.js";import{t as f}from"./SectionShell-Cd_Fu3uI.js";var p={class:`grid sm:grid-cols-3 gap-8`},m={class:`font-mono text-[12px] text-ink block`},h={class:`text-[13px] text-muted mt-1`},g={__name:`ShadowsSection`,setup(g){let{t:_}=d(),v=s(()=>[{name:`sm`,css:`var(--shadow-sm)`,note:_(`ds.shadows.sm.note`)},{name:`md`,css:`var(--shadow-md)`,note:_(`ds.shadows.md.note`)},{name:`lg`,css:`var(--shadow-lg)`,note:_(`ds.shadows.lg.note`)}]);return(s,d)=>(e(),r(f,{eyebrow:t(_)(`ds.eyebrow.tokens`),title:t(_)(`ds.shadows.title`),description:t(_)(`ds.shadows.description`)},{default:a(()=>[l(`div`,p,[(e(!0),u(c,null,n(v.value,t=>(e(),u(`div`,{key:t.name,class:`space-y-4`},[l(`div`,{class:`h-36 rounded-md bg-paper`,style:i({boxShadow:t.css})},null,4),l(`div`,null,[l(`code`,m,`--shadow-`+o(t.name),1),l(`p`,h,o(t.note),1)])]))),128))])]),_:1},8,[`eyebrow`,`title`,`description`]))}};export{g as default};

1
dist/assets/ShopPage-BDztc4FL.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
import{C as e,G as t,T as n,c as r,j as i,lt as a,m as o,r as s,s as c,st as l,u}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as d}from"./i18n-DrTQks20.js";import{t as f}from"./SectionShell-BEISUYi8.js";import{t as p}from"./Card-DM27vc3f.js";var m={class:`grid md:grid-cols-2 gap-6`},h={class:`eyebrow mb-3`},g={class:`text-[14px] text-muted leading-relaxed`},_={class:`eyebrow mb-3`},v={class:`text-[14px] text-muted leading-relaxed`},y={class:`eyebrow mb-6`},b={class:`divide-y divide-line rounded-md border border-line bg-paper px-6`},x={class:`font-mono text-[11px] text-muted w-24 shrink-0`},S={__name:`TypographySection`,setup(S){let{t:C}=d(),w=[`xs`,`sm`,`base`,`lg`,`xl`,`2xl`,`3xl`,`4xl`,`5xl`];return(d,S)=>(e(),r(f,{eyebrow:t(C)(`ds.eyebrow.tokens`),title:t(C)(`ds.typography.title`),description:t(C)(`ds.typography.description`)},{default:i(()=>[c(`section`,m,[o(p,{tone:`paper`},{default:i(()=>[c(`p`,h,a(t(C)(`ds.heading.display`)),1),S[0]||=c(`p`,{class:`font-display text-5xl font-normal leading-[1.05] mb-3`},`Fraunces`,-1),c(`p`,g,a(t(C)(`ds.typography.serifDesc`)),1),S[1]||=c(`code`,{class:`font-mono text-[11px] text-muted block mt-5`},`var(--font-serif)`,-1)]),_:1}),o(p,{tone:`paper`},{default:i(()=>[c(`p`,_,a(t(C)(`ds.heading.body`)),1),S[2]||=c(`p`,{class:`font-sans text-5xl font-medium leading-[1.05] mb-3`},`DM Sans`,-1),c(`p`,v,a(t(C)(`ds.typography.sansDesc`)),1),S[3]||=c(`code`,{class:`font-mono text-[11px] text-muted block mt-5`},`var(--font-sans)`,-1)]),_:1})]),c(`section`,null,[c(`h2`,y,a(t(C)(`ds.heading.scale`)),1),c(`div`,b,[(e(),u(s,null,n(w,e=>c(`div`,{key:e,class:`flex items-baseline gap-8 py-4`},[c(`code`,x,`text-`+a(e),1),c(`span`,{class:l(`text-${e}`)},a(t(C)(`ds.typography.sample`)),3)])),64))])])]),_:1},8,[`eyebrow`,`title`,`description`]))}};export{S as default};
import{C as e,G as t,T as n,c as r,j as i,lt as a,m as o,r as s,s as c,st as l,u}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as d}from"./i18n-CJQl3WLC.js";import{t as f}from"./SectionShell-Cd_Fu3uI.js";import{t as p}from"./Card-pgd8VnYH.js";var m={class:`grid md:grid-cols-2 gap-6`},h={class:`eyebrow mb-3`},g={class:`text-[14px] text-muted leading-relaxed`},_={class:`eyebrow mb-3`},v={class:`text-[14px] text-muted leading-relaxed`},y={class:`eyebrow mb-6`},b={class:`divide-y divide-line rounded-md border border-line bg-paper px-6`},x={class:`font-mono text-[11px] text-muted w-24 shrink-0`},S={__name:`TypographySection`,setup(S){let{t:C}=d(),w=[`xs`,`sm`,`base`,`lg`,`xl`,`2xl`,`3xl`,`4xl`,`5xl`];return(d,S)=>(e(),r(f,{eyebrow:t(C)(`ds.eyebrow.tokens`),title:t(C)(`ds.typography.title`),description:t(C)(`ds.typography.description`)},{default:i(()=>[c(`section`,m,[o(p,{tone:`paper`},{default:i(()=>[c(`p`,h,a(t(C)(`ds.heading.display`)),1),S[0]||=c(`p`,{class:`font-display text-5xl font-normal leading-[1.05] mb-3`},`Fraunces`,-1),c(`p`,g,a(t(C)(`ds.typography.serifDesc`)),1),S[1]||=c(`code`,{class:`font-mono text-[11px] text-muted block mt-5`},`var(--font-serif)`,-1)]),_:1}),o(p,{tone:`paper`},{default:i(()=>[c(`p`,_,a(t(C)(`ds.heading.body`)),1),S[2]||=c(`p`,{class:`font-sans text-5xl font-medium leading-[1.05] mb-3`},`DM Sans`,-1),c(`p`,v,a(t(C)(`ds.typography.sansDesc`)),1),S[3]||=c(`code`,{class:`font-mono text-[11px] text-muted block mt-5`},`var(--font-sans)`,-1)]),_:1})]),c(`section`,null,[c(`h2`,y,a(t(C)(`ds.heading.scale`)),1),c(`div`,b,[(e(),u(s,null,n(w,e=>c(`div`,{key:e,class:`flex items-baseline gap-8 py-4`},[c(`code`,x,`text-`+a(e),1),c(`span`,{class:l(`text-${e}`)},a(t(C)(`ds.typography.sample`)),3)])),64))])])]),_:1},8,[`eyebrow`,`title`,`description`]))}};export{S as default};

View File

@@ -1 +1 @@
import{n as e}from"./pinia-DQoUg3qR.js";import{n as t}from"./products-GEWPSJSp.js";var n=`kn-cart-v1`;function r(){if(typeof localStorage>`u`)return[];try{let e=localStorage.getItem(n);if(!e)return[];let t=JSON.parse(e);return Array.isArray(t)?t.filter(e=>e&&typeof e.productId==`string`&&Number.isInteger(e.quantity)&&e.quantity>0):[]}catch{return[]}}function i(e){if(!(typeof localStorage>`u`))try{localStorage.setItem(n,JSON.stringify(e))}catch{}}function a(e){let n=t.find(t=>t.id===e.productId);return n?{productId:e.productId,quantity:e.quantity,unitPrice:n.price,lineTotal:+(n.price*e.quantity).toFixed(2),product:{id:n.id,title:n.title,brand:n.brand,size:n.size,image:n.image,href:n.href}}:null}var o=e(`cart`,{state:()=>({lines:r()}),getters:{items:e=>e.lines.map(a).filter(Boolean),count:e=>e.lines.reduce((e,t)=>e+t.quantity,0),subtotal(){return+this.items.reduce((e,t)=>e+t.lineTotal,0).toFixed(2)},isEmpty:e=>e.lines.length===0},actions:{add(e,t=1){let n=this.lines.find(t=>t.productId===e);n?n.quantity+=t:this.lines.push({productId:e,quantity:t}),i(this.lines)},update(e,t){if(Number.isInteger(t)){if(t<=0)this.lines=this.lines.filter(t=>t.productId!==e);else{let n=this.lines.find(t=>t.productId===e);n&&(n.quantity=t)}i(this.lines)}},remove(e){this.lines=this.lines.filter(t=>t.productId!==e),i(this.lines)},clear(){this.lines=[],i(this.lines)}}});function s(e){return{items:e.items,count:e.count,subtotal:e.subtotal,updatedAt:new Date().toISOString()}}async function c(){return s(o())}async function l(e,t=1){if(typeof e!=`string`||!e)throw Error(`cart.productIdRequired`);let n=Number.isInteger(t)?t:1;if(n<1)throw Error(`cart.quantityInvalid`);let r=o();return r.add(e,n),s(r)}async function u(e,t){let n=o();return n.update(e,Number.isInteger(t)?t:0),s(n)}async function d(e){let t=o();return t.remove(e),s(t)}async function f(){let e=o();return e.clear(),s(e)}export{u as a,d as i,f as n,o,c as r,l as t};
import{n as e}from"./pinia-DQoUg3qR.js";import{r as t}from"./products-Dhgp5EjC.js";var n=`kn-cart-v1`;function r(){if(typeof localStorage>`u`)return[];try{let e=localStorage.getItem(n);if(!e)return[];let t=JSON.parse(e);return Array.isArray(t)?t.filter(e=>e&&typeof e.productId==`string`&&Number.isInteger(e.quantity)&&e.quantity>0):[]}catch{return[]}}function i(e){if(!(typeof localStorage>`u`))try{localStorage.setItem(n,JSON.stringify(e))}catch{}}function a(e){let n=t.find(t=>t.id===e.productId);return n?{productId:e.productId,quantity:e.quantity,unitPrice:n.price,lineTotal:+(n.price*e.quantity).toFixed(2),product:{id:n.id,title:n.title,brand:n.brand,size:n.size,image:n.image,href:n.href}}:null}var o=e(`cart`,{state:()=>({lines:r()}),getters:{items:e=>e.lines.map(a).filter(Boolean),count:e=>e.lines.reduce((e,t)=>e+t.quantity,0),subtotal(){return+this.items.reduce((e,t)=>e+t.lineTotal,0).toFixed(2)},isEmpty:e=>e.lines.length===0},actions:{add(e,t=1){let n=this.lines.find(t=>t.productId===e);n?n.quantity+=t:this.lines.push({productId:e,quantity:t}),i(this.lines)},update(e,t){if(Number.isInteger(t)){if(t<=0)this.lines=this.lines.filter(t=>t.productId!==e);else{let n=this.lines.find(t=>t.productId===e);n&&(n.quantity=t)}i(this.lines)}},remove(e){this.lines=this.lines.filter(t=>t.productId!==e),i(this.lines)},clear(){this.lines=[],i(this.lines)}}});function s(e){return{items:e.items,count:e.count,subtotal:e.subtotal,updatedAt:new Date().toISOString()}}async function c(){return s(o())}async function l(e,t=1){if(typeof e!=`string`||!e)throw Error(`cart.productIdRequired`);let n=Number.isInteger(t)?t:1;if(n<1)throw Error(`cart.quantityInvalid`);let r=o();return r.add(e,n),s(r)}async function u(e,t){let n=o();return n.update(e,Number.isInteger(t)?t:0),s(n)}async function d(e){let t=o();return t.remove(e),s(t)}async function f(){let e=o();return e.clear(),s(e)}export{u as a,d as i,f as n,o,c as r,l as t};

1
dist/assets/i18n-CJQl3WLC.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dist/assets/index-GHK8PbUQ.js vendored Normal file

File diff suppressed because one or more lines are too long

1
dist/assets/index-j7lHVelw.css vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

4
dist/index.html vendored
View File

@@ -12,13 +12,13 @@
href="https://fonts.googleapis.com/css2?family=Fraunces:ital,opsz,wght@0,9..144,200;0,9..144,400;0,9..144,600;0,9..144,700;1,9..144,200;1,9..144,400;1,9..144,600&family=DM+Sans:ital,wght@0,300;0,400;0,500;0,600;0,700;1,300;1,400&display=swap"
rel="stylesheet"
/>
<script type="module" crossorigin src="/assets/index-D8xPTD_C.js"></script>
<script type="module" crossorigin src="/assets/index-GHK8PbUQ.js"></script>
<link rel="modulepreload" crossorigin href="/assets/_plugin-vue_export-helper-BOai-rQB.js">
<link rel="modulepreload" crossorigin href="/assets/runtime-core.esm-bundler-BD0e4RlP.js">
<link rel="modulepreload" crossorigin href="/assets/runtime-dom.esm-bundler-CcSFQHoC.js">
<link rel="modulepreload" crossorigin href="/assets/pinia-DQoUg3qR.js">
<link rel="modulepreload" crossorigin href="/assets/vue-router-QRVDVSxc.js">
<link rel="stylesheet" crossorigin href="/assets/index-Dqiix-Zn.css">
<link rel="stylesheet" crossorigin href="/assets/index-j7lHVelw.css">
</head>
<body>
<div id="app"></div>

View File

@@ -1,11 +1,9 @@
<script setup>
import { computed, ref, defineAsyncComponent } from 'vue'
import { useRoute } from 'vue-router'
import DefaultLayout from './layouts/DefaultLayout.vue'
import SplashIntro from './components/SplashIntro.vue'
const route = useRoute()
const useDefaultLayout = computed(() => route.meta.layout !== 'none')
const isPreview = computed(() => route.meta.preview === true)
const isDesignRoute = computed(() => route.path.startsWith('/design'))
const inIframe = typeof window !== 'undefined' && window.self !== window.top
@@ -31,9 +29,13 @@ const A11yToolbar = isDev
<template>
<SplashIntro v-if="showSplash" @finished="onSplashFinished" />
<DefaultLayout v-if="useDefaultLayout">
<router-view />
</DefaultLayout>
<router-view v-else />
<!-- Single router outlet. Each page (Home, Shop, /design/*) owns its
own layout chrome no app-level wrapper, so there's no frame
where an intermediate layout can flash before the route
resolves. (Previously a conditional DefaultLayout was rendered
whenever `route.meta.layout !== 'none'`, but during initial
load `route.meta` is `{}`, so the condition was truthy and the
dev sidebar showed under every page for one frame.) -->
<router-view />
<A11yToolbar v-if="isDev && isDesignRoute && !isPreview && !inIframe" />
</template>

View File

@@ -1,7 +1,14 @@
// Barrel for the API boundary. Swap these imports for real backend calls
// when the PHP / MySQL side lands — callers keep the same import path.
export { products, searchProducts, formatPrice } from './products.js'
export {
products,
searchProducts,
formatPrice,
USE_CASES,
useCaseFor,
productsByUseCase,
} from './products.js'
export {
fetchCart,
addToCart,

View File

@@ -338,3 +338,38 @@ export function formatPrice(amount, currency = '€') {
if (!Number.isFinite(num)) return ''
return `${currency} ${num.toFixed(2).replace('.', ',')}`
}
/**
* Shop use-cases — the three top-level bands on the Shop page and in
* the desktop nav (Cook / Clean / Care). Product-level `category`
* strings are fine-grained (Pulver, Reinigung, Wäsche, Körperpflege,
* Sport, Tabletten); this table rolls them up into the three shop-
* facing groups so the mapping is declared in one place.
*
* cook — kitchen & digestion (baking, gastro)
* clean — household cleaning & laundry
* care — bath, body and sport
*/
export const USE_CASES = ['cook', 'clean', 'care']
const USE_CASE_BY_CATEGORY = {
Pulver: 'cook',
Tabletten: 'cook',
Reinigung: 'clean',
Wäsche: 'clean',
Körperpflege: 'care',
Sport: 'care',
}
export function useCaseFor(product) {
return USE_CASE_BY_CATEGORY[product.category] || 'clean'
}
export function productsByUseCase(list = products) {
return list.reduce(
(acc, p) => {
acc[useCaseFor(p)].push(p)
return acc
},
{ cook: [], clean: [], care: [] },
)
}

View File

@@ -5,6 +5,13 @@
html {
scroll-behavior: smooth;
font-size: 17px;
/* Runtime-measured navbar height. Default matches the standard
Navbar variant at lg (py-5 + logo + border) so the home-page
first-fold wrapper can use `calc(100svh - var(--nav-h))` from
first paint. HomePage still refines this at mount via a
ResizeObserver for pixel-exact fit, but the default prevents a
~nav-height layout shift between first paint and hydration. */
--nav-h: 68px;
}
body {

View File

@@ -71,6 +71,11 @@ const props = defineProps({
// fill finishes at 2.70s). We give it a 100ms breath then start the
// fade so the splash doesn't linger past its own climax.
duration: { type: Number, default: 2800 },
// Portrait/mobile animation is tightened to ~1.0s total: slides
// resolve at ~670ms, wordmark + mound land at ~1.0s. Dismiss at
// 1150ms gives a ~150ms breath past the climax — matches the snap
// of the desktop dismiss (desktop climax 2.70s → dismiss 2.80s).
durationPortrait: { type: Number, default: 1150 },
dismissOnTap: { type: Boolean, default: true },
respectReducedMotion: { type: Boolean, default: true },
portraitQuery: { type: String, default: '(max-width: 768px), (orientation: portrait) and (max-width: 900px)' }
@@ -97,7 +102,9 @@ onMounted(() => {
props.respectReducedMotion &&
typeof window !== 'undefined' &&
window.matchMedia('(prefers-reduced-motion: reduce)').matches
const totalMs = reduced ? 1200 : props.duration
const totalMs = reduced
? 1200
: (isPortrait.value ? props.durationPortrait : props.duration)
timer = window.setTimeout(() => { visible.value = false }, totalMs)
})
onBeforeUnmount(() => {
@@ -164,24 +171,34 @@ const dPortMound = `M 501.491 1116.015 C 501.156 1116.557, 499.810 1117, 498.50
transition-delay: 1.30s; }
.splash-root.go .wordmark { opacity: 1; }
/* Mobile slide-ins */
.left-m { fill: #b5d8b6; opacity: 0; transform: translateX(-14%); transition-delay: 260ms; }
.right-m { fill: #b5d8b6; opacity: 0; transform: translateX( 14%); transition-delay: 260ms; }
/* Mobile slide-ins — tightened to ~550ms so the whole portrait
choreography lands in ~1.1s total (was ~1.6s). Uses the same
cubic-bezier as the default .layer rule but overrides the
duration/delay so the .layer 900ms/260ms transition doesn't
slow things down. */
.left-m { fill: #b5d8b6; opacity: 0; transform: translateX(-14%);
transition: transform 550ms cubic-bezier(.22,.61,.36,1) 120ms,
opacity 450ms ease 120ms; }
.right-m { fill: #b5d8b6; opacity: 0; transform: translateX( 14%);
transition: transform 550ms cubic-bezier(.22,.61,.36,1) 120ms,
opacity 450ms ease 120ms; }
.splash-root.go .left-m,
.splash-root.go .right-m { opacity: 1; transform: none; }
/* Mobile wordmark — slides from top + fades in (no stroke draw) */
/* Mobile wordmark — slides from top + fades in (no stroke draw).
Starts as the slides are landing (~500ms) and resolves by ~1.0s
so the splash can auto-dismiss shortly after. */
.top-m { fill: #ffffff; opacity: 0; transform: translateY(-14%);
transition-property: opacity, transform;
transition-duration: 700ms;
transition-duration: 500ms;
transition-timing-function: ease;
transition-delay: 900ms; }
transition-delay: 500ms; }
.splash-root.go .top-m { opacity: 1; transform: none; }
/* Mobile handful-of-natron — matches the wordmark fade timing */
.mound-m { fill: #ffffff; opacity: 0;
transition: opacity 700ms ease;
transition-delay: 900ms; }
transition: opacity 500ms ease;
transition-delay: 500ms; }
.splash-root.go .mound-m { opacity: 1; }
/* Desktop climax: natron droplets */

View File

@@ -77,8 +77,7 @@ const CARD_TONES = [
<h2
v-if="headline"
class="font-display font-normal leading-[1.05] tracking-tight text-ink"
style="font-size: clamp(2.25rem, 5vw, 3.75rem);"
class="font-display font-normal leading-[1.05] tracking-tight text-ink text-headline-lg"
>{{ headline }}</h2>
<p v-if="sub" class="text-lg leading-relaxed text-muted max-w-2xl">
@@ -117,14 +116,19 @@ const CARD_TONES = [
<li
v-for="(milestone, i) in milestones.slice(0, 3)"
:key="milestone.year + milestone.title"
class="timeline-item flex flex-col"
class="timeline-item flex flex-col md:h-full"
>
<div class="timeline-mobile-marker">
<span :class="['timeline-pill', CARD_TONES[i].pill]">{{ milestone.year }}</span>
</div>
<!-- md:flex-1 + md:h-full: the `<li>` stretches to the row's
natural tallest height via CSS-grid's default
align-items: stretch; the card then fills that li so
every card in the row reads as the same height on
desktop. Mobile stays auto-height (no grid row). -->
<div
:class="[
'flex flex-col gap-3 rounded-md border p-6 md:p-7',
'flex flex-col gap-3 rounded-md border p-6 md:p-7 md:flex-1 md:h-full',
CARD_TONES[i].card,
]"
>

View File

@@ -4,6 +4,8 @@ import Button from './Button.vue'
import Icon from './Icon.vue'
import IconButton from './IconButton.vue'
import BundleCard from './BundleCard.vue'
import BundlesHeader from './internal/BundlesHeader.vue'
import BundlesBenefits from './internal/BundlesBenefits.vue'
import { useI18n } from '@/i18n/index.js'
/**
@@ -15,6 +17,19 @@ import { useI18n } from '@/i18n/index.js'
* can be overridden per-instance via the *Label / *A11y props.
*/
const props = defineProps({
// Layout variant.
// - 'sidebar' (default): left column holds headline/sub/benefits/CTA,
// right column holds a one-at-a-time scroll-snap carousel.
// - 'stacked': desktop puts the sidebar content in a full-width row
// on top, then renders the bundles as a 3-up grid below — no
// carousel, no pagination (since all three fit in view).
// Mobile (<md) is identical for both: a vertical stack of cards.
layout: {
type: String,
default: 'sidebar',
validator: (v) => ['sidebar', 'stacked'].includes(v),
},
// Section headline. `headline` renders in the display serif; `headlineEm`
// is the italicised highlight, styled consistently with Hero.
headline: { type: String, default: '' },
@@ -124,37 +139,48 @@ onBeforeUnmount(() => {
<!-- Matches the Hero banner container same max-w-6xl so the section
aligns with the banner above rather than breaking full-bleed. -->
<div
class="mx-auto w-full max-w-6xl px-6 py-16 sm:px-8 sm:py-20 md:px-12 md:py-20 lg:px-16 lg:py-24"
class="mx-auto w-full max-w-6xl px-6 py-16 sm:px-8 sm:py-20 md:px-12 md:py-24 lg:px-16 lg:py-28"
>
<div class="grid gap-10 md:gap-12 lg:gap-16 lg:grid-cols-[340px_1fr] lg:items-center">
<!-- Sidebar: heading + sub + up-to-3 benefits + CTA. -->
<aside class="flex flex-col gap-8">
<div v-if="headline || sub" class="flex flex-col gap-4">
<h2
v-if="headline || headlineEm"
class="font-display font-normal leading-[1.05] tracking-tight text-ink"
style="font-size: clamp(2rem, 4vw, 3rem);"
>
{{ headline }}
<em
v-if="headlineEm"
class="italic font-light text-brand"
>{{ headlineEm }}</em>
</h2>
<p v-if="sub" class="text-base leading-relaxed text-muted max-w-md">
{{ sub }}
</p>
</div>
<!-- STACKED layout (option 2).
Row 1: headline + sub (single column, full width).
Row 2: benefits as a horizontal chip row inside a paper
container sits between the pitch and the products
as a "why join" summary strip.
Row 3: mobile stack / md+ 3-up grid of bundle cards.
Row 4: "become a member" CTA centred below the products. -->
<div v-if="layout === 'stacked'" class="flex flex-col gap-10 md:gap-12 lg:gap-14">
<!-- Row 1: headline + sub. Full width so the pitch reads as a
section opener rather than a split banner. -->
<BundlesHeader
:headline="headline"
:headline-em="headlineEm"
:sub="sub"
sub-max-width="max-w-2xl"
/>
<ul v-if="benefits.length" class="flex flex-col gap-4">
<!-- Row 2: benefits strip. Cream-on-surface container, the
cream-surface analogue of the LanguageSwitcher's `brand`
tone (cream-wash-on-brand). The warm fill + strong line
border lifts the chips off the section's surface ground
without competing with the bundle cards below.
`rounded-md` reads as "card" at this larger scale
reserving the pill shape for true chip rows (nav, tabs,
language switcher) where the container is the control.
Flex-wrap lets long benefit copy reflow to two lines on
narrow viewports instead of overflowing horizontally. -->
<div
v-if="benefits.length"
class="rounded-md border border-cream-dark bg-cream px-5 py-4 sm:px-6 sm:py-5"
>
<ul class="flex flex-col gap-4 sm:flex-row sm:flex-wrap sm:items-center sm:justify-between sm:gap-x-8 sm:gap-y-3">
<li
v-for="benefit in benefits.slice(0, 3)"
:key="benefit"
class="flex items-start gap-3"
class="flex items-center gap-3"
>
<span
aria-hidden="true"
class="mt-0.5 inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-brand-wash text-brand"
class="inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-brand-wash text-brand"
>
<Icon name="check" :size="14" :stroke-width="2.2" />
</span>
@@ -163,20 +189,89 @@ onBeforeUnmount(() => {
</span>
</li>
</ul>
</div>
<!-- Products row. Mobile: vertical stack (same as sidebar
layout). md+: 3-up grid, vertical cards. -->
<div class="min-w-0">
<div class="md:hidden grid gap-5">
<BundleCard
v-for="bundle in bundles"
:key="bundle.id"
layout="vertical"
:name="bundle.name"
:items="bundle.items"
:price="bundle.price"
:member-price="bundle.memberPrice"
:usage="bundle.usage"
:image="bundle.image"
:image-alt="bundle.imageAlt"
:badge="bundle.badge"
:badge-variant="bundle.badgeVariant || 'accent'"
tone="paper"
@add="$emit('add', bundle.id)"
/>
</div>
<div class="hidden md:grid md:gap-6 md:grid-cols-3">
<BundleCard
v-for="bundle in bundles.slice(0, 3)"
:key="bundle.id"
layout="vertical"
:name="bundle.name"
:items="bundle.items"
:price="bundle.price"
:member-price="bundle.memberPrice"
:usage="bundle.usage"
:image="bundle.image"
:image-alt="bundle.imageAlt"
:badge="bundle.badge"
:badge-variant="bundle.badgeVariant || 'accent'"
tone="paper"
@add="$emit('add', bundle.id)"
/>
</div>
</div>
<!-- Bottom CTA centred below the products so the eye lands
on it last, after the member pitch has been made above
and the products have been scanned. -->
<div v-if="joinCta" class="flex justify-center">
<Button
variant="primary"
size="lg"
@click="$emit('join')"
>{{ joinCta }}</Button>
</div>
</div>
<!-- SIDEBAR layout (option 1, original).
Left aside + right carousel on lg+. -->
<div
v-else
class="grid gap-10 md:gap-12 lg:gap-16 lg:grid-cols-[340px_1fr] lg:items-center"
>
<aside class="flex flex-col gap-8">
<BundlesHeader
:headline="headline"
:headline-em="headlineEm"
:sub="sub"
sub-max-width="max-w-md"
/>
<BundlesBenefits :benefits="benefits" />
<Button
v-if="joinCta"
variant="primary"
size="md"
class="self-start"
@click="$emit('join')"
>{{ joinCta }}</Button>
</aside>
<!-- Bundles. `min-w-0` is load-bearing: a grid `1fr` column
defaults to `min-width: auto`, letting its children's
intrinsic width push the column past its allocation.
Without this, the carousel's fixed-width slides drag the
right column past the section's max-width during resizes. -->
<!-- `min-w-0` is load-bearing: a grid `1fr` column defaults to
`min-width: auto`, letting children push the column past
its allocation. Without this, the carousel's fixed-width
slides drag the right column past the section's max-width
during resizes. -->
<div class="min-w-0">
<!-- Mobile: vertical stack. -->
<div class="md:hidden grid gap-5">
@@ -198,9 +293,7 @@ onBeforeUnmount(() => {
/>
</div>
<!-- md+ : one-at-a-time scroll-snap carousel with horizontal cards.
Swipe, keyboard arrow keys, and the prev/next buttons all
drive the same scrollLeft — no animation state needed. -->
<!-- md+ : one-at-a-time scroll-snap carousel. -->
<div class="hidden md:flex md:flex-col md:gap-6 relative">
<!-- Padding + matching negative margins reserve room inside the
scroll container for the hover lift and shadow-md without

View File

@@ -34,6 +34,12 @@ const props = defineProps({
* and copy on the right from `lg` up. Mobile order is unchanged (image
* on top, copy below) to preserve reading order. */
reverse: { type: Boolean, default: false },
/** Compact hero: smaller image cap + narrower media column from `lg` up.
* Used for secondary/supporting heroes (e.g. the cream "hundert
* Anwendungen" second-fold banner) so they read as companion content
* to the primary first-fold hero rather than a second centre-stage
* block. Mobile sizing is unchanged. */
compact: { type: Boolean, default: false },
})
defineEmits(['cta', 'secondary'])
@@ -73,7 +79,7 @@ const layout = computed(() => {
copy: 'max-w-2xl mx-auto items-center text-center',
actions: 'justify-center',
media: 'mt-4 md:mt-6',
mediaSize: 'w-[287px] sm:w-[354px] md:w-[442px] lg:w-[530px]',
mediaSize: 'w-full max-w-[287px] sm:max-w-[354px] md:max-w-[442px] lg:max-w-[530px]',
}
}
// Split: image on top on mobile/tablet, text-left/image-right on desktop.
@@ -82,37 +88,97 @@ const layout = computed(() => {
// the copy column so its headline/CTA block sits at the image's vertical midpoint.
// `reverse` swaps the desktop columns so the image sits on the left.
return {
// `grid-cols-1` is load-bearing at mobile. Without it, the grid
// has no column template below `lg`, so `grid-auto-columns: auto`
// sizes the implicit column to max-content of its widest child —
// which is the image column's declared width. That max-content
// column then forces the copy column to the same width, overflowing
// narrow viewports and clipping the headline against the section
// edge. `grid-cols-1` emits `minmax(0, 1fr)`, constraining the
// column to available width and letting children actually shrink.
root: props.reverse
? 'grid gap-10 md:gap-14 lg:grid-cols-[1fr_1.05fr]'
: 'grid gap-10 md:gap-14 lg:grid-cols-[1.05fr_1fr]',
? 'grid grid-cols-1 gap-10 md:gap-14 lg:grid-cols-[1fr_1.05fr]'
: 'grid grid-cols-1 gap-10 md:gap-14 lg:grid-cols-[1.05fr_1fr]',
copy: [
'order-2 max-w-xl mx-auto lg:mx-0 items-center text-center lg:justify-center',
props.reverse ? 'lg:order-2 lg:items-start lg:text-left' : 'lg:order-1 lg:items-start lg:text-left',
].join(' '),
actions: 'justify-center lg:justify-start',
media: props.reverse ? 'order-1 lg:order-1' : 'order-1 lg:order-2',
mediaSize: 'w-[373px] sm:w-[489px] md:w-[603px] lg:w-full lg:max-w-[748px]',
// Media cell: use max-width rather than fixed width below `lg` so
// the column can shrink below the image's preferred size on narrow
// phones. A fixed `w-[373px]` forced the single-column mobile grid
// to 373px, which overflowed a 375px viewport minus section padding
// and pushed the headline text past the section edge (clipped).
// Compact heroes cap the desktop media width tighter so the image
// doesn't dominate; mobile/tablet sizing is identical.
mediaSize: props.compact
? 'w-full max-w-[373px] sm:max-w-[489px] md:max-w-[603px] lg:max-w-[460px] mx-auto'
: 'w-full max-w-[373px] sm:max-w-[489px] md:max-w-[603px] lg:max-w-[748px] mx-auto',
}
})
// Max image height per viewport step. Compact drops the desktop cap
// from 78svh → 48svh so the secondary hero reads as a companion,
// not a second main stage. Mobile/tablet caps are shared because
// phone screens shouldn't scale content down below its legible size.
// Image max-height steps. At lg the default cap is deliberately
// conservative (52svh) because anything larger makes the Hero
// exceed the home page's `min-h-[calc(100svh - var(--nav-h))] +
// pb-[var(--nav-h)]` content box on typical laptop viewports
// (svh ≈ 800900), which forces the wrapper to grow and pins the
// Hero to the top — losing vertical centering. 52svh keeps the
// total Hero height below the content box at svh ≥ 700 so
// centering holds across all common desktop breakpoints. Compact
// variant is lower still for the secondary banner.
const imageHeightClass = computed(() =>
props.compact
? 'max-h-[44svh] md:max-h-[61svh] lg:max-h-[48svh]'
: 'max-h-[44svh] md:max-h-[61svh] lg:max-h-[52svh]',
)
</script>
<template>
<!-- overflow-clip (not overflow-hidden) contains the media halo/disc
decor WITHOUT establishing a new scrollport so the headline's
italic-overhang can't be clipped against the section edge at
narrow widths. Historically this was `overflow-hidden`, which
made the section a scrolling ancestor and sheared the last
italic letter off the hero h1 at phone-sim widths.
The `hero-section` scoped class carries the overflow-clip-margin
value up to 1rem of content (including italic overhang) is
allowed past the section edge before clipping kicks in. -->
<section
:class="[
'relative overflow-hidden',
'hero-section relative overflow-clip',
'px-6 py-10 sm:px-8 sm:py-12 md:px-12 md:py-16 lg:px-16 lg:py-20',
tone.surface,
tone.text,
]"
>
<div :class="['relative mx-auto w-full max-w-6xl', layout.root]">
<!-- Copy -->
<div :class="['relative z-[1] flex flex-col gap-6', layout.copy]">
<!-- Copy.
`min-w-0` is load-bearing: the copy column is a flex/grid
child whose default `min-width: auto` resolves to its
longest word's intrinsic width, which lets the headline
push the column wider than the viewport. Overriding to 0
lets the headline actually respect its own max width so
the font-size clamp and wrapping can take effect. -->
<div :class="['relative z-[1] flex flex-col gap-6 min-w-0', layout.copy]">
<p v-if="eyebrow" class="eyebrow">{{ eyebrow }}</p>
<!-- Headline sizing uses responsive Tailwind arbitrary values
so each breakpoint compiles to a plain media-query
`font-size` rule — no scoped-CSS hash, no HMR edge
cases. Italic Fraunces at ≥2.25rem overhangs the
line-box at ≤400px and gets clipped by the section's
`overflow-hidden` (needed for the halo/disc decor);
capping at 1.625rem on phones keeps the whole phrase
inside the content width. `break-words` + the inline
`overflow-wrap` is belt-and-braces for any long word
(e.g. German compounds) that still can't fit. -->
<h1
class="font-display font-normal leading-[1.04] tracking-tight"
style="font-size: clamp(2.5rem, 6vw, 4.5rem);"
class="hero-headline font-display font-normal leading-[1.04] tracking-tight hyphens-auto break-words text-[1.625rem] sm:text-[2.25rem] lg:text-[3rem] xl:text-[3.75rem] 2xl:text-[4.5rem]"
>
<slot name="headline">{{ headline }}</slot>
</h1>
@@ -207,11 +273,42 @@ const layout = computed(() => {
:alt="imageAlt || headline"
loading="eager"
decoding="async"
class="relative mx-auto w-auto max-w-full max-h-[44svh] md:max-h-[61svh] lg:max-h-[78svh] object-contain drop-shadow-[0_20px_40px_rgba(28,58,40,0.18)]"
:class="[
'relative mx-auto w-auto max-w-full object-contain drop-shadow-[0_20px_40px_rgba(28,58,40,0.18)]',
imageHeightClass,
]"
/>
</slot>
<!-- Page-level extension point for mobile category shortcuts
etc. Sits under the image within the media column so it
tracks the hero's vertical rhythm. Empty by default. -->
<slot name="afterMedia" />
</div>
</div>
</div>
</section>
</template>
<style scoped>
/* overflow-clip (vs overflow-hidden) contains the decorative halo and
disc behind the product image WITHOUT establishing a new scrollport.
The margin lets up to 1rem of content — including Fraunces italic
overhang — extend past the section edge before being clipped. No
Tailwind utility covers this pair, so it lives here rather than as
inline CSS on every call site. */
.hero-section {
overflow-clip-margin: 1rem;
}
/* Headline wrap rules. `overflow-wrap: anywhere` is stronger than
`break-words` — the latter only breaks between words, the former
will break inside a word if it can't otherwise fit the line-box.
Paired with `word-break: normal` so regular CJK / soft-hyphen
behaviour isn't altered. Together these guarantee a long German
compound can never overflow the column. */
.hero-headline {
overflow-wrap: anywhere;
word-break: normal;
}
</style>

View File

@@ -24,6 +24,11 @@ const props = defineProps({
default: 'standard',
validator: (v) => ['standard', 'floating'].includes(v),
},
/**
* Primary nav items — render in the left cluster, next to the logo.
* On the shop/home these are the top-level shop destinations
* (Shop, Cook, Clean, Care).
*/
items: {
type: Array,
default: () => [
@@ -33,6 +38,18 @@ const props = defineProps({
{ key: 'nav.contact', href: '#' },
],
},
/**
* Secondary nav items — render in the right cluster, immediately to
* the LEFT of the search trigger. Intended for supporting pages
* (Bundles, Revitalisation, About) that sit above the purchasing
* flow but below the category browse in importance. Empty by
* default so callers that don't use the split leave the right
* cluster unchanged.
*/
secondaryItems: {
type: Array,
default: () => [],
},
cartCount: { type: Number, default: 0 },
floatOnMobile: { type: Boolean, default: true },
/**
@@ -133,8 +150,24 @@ onBeforeUnmount(() => {
</nav>
</div>
<!-- Right: search + language + cart (desktop only) -->
<!-- Right: secondary nav + search + language + cart (desktop only) -->
<div class="hidden md:flex items-center gap-4">
<!-- Secondary nav supporting pages tucked to the left of
search so the primary category nav on the left stays the
focal point. Shares the same visual treatment as the
primary items for consistency. -->
<nav
v-if="secondaryItems.length"
class="flex items-center gap-6 mr-2"
>
<a
v-for="item in secondaryItems"
:key="item.key || item.label"
:href="item.href || '#'"
:class="[tone.link, 'text-[14px] font-medium tracking-label transition-colors duration-base']"
@click="$emit('nav', item)"
>{{ itemLabel(item) }}</a>
</nav>
<button
type="button"
:class="[
@@ -223,9 +256,13 @@ onBeforeUnmount(() => {
<Logo class="w-12 h-auto text-cream" />
</div>
<!-- Mobile menu shows primary + secondary nav as one stack.
Desktop splits them left/right of the search; on mobile
the menu is the only nav surface so they read as one
list, primary first. -->
<nav class="flex-1 flex flex-col justify-center px-8 gap-3 overflow-y-auto">
<a
v-for="item in items"
v-for="item in [...items, ...secondaryItems]"
:key="item.key || item.label"
:href="item.href || '#'"
class="font-serif font-normal text-[clamp(2.25rem,9vw,3.5rem)] tracking-tight leading-[1.05] text-cream hover:text-accent transition-colors duration-base"

View File

@@ -46,8 +46,7 @@ defineEmits(['notify'])
<h2
v-if="headline || headlineEm"
class="font-display font-normal leading-[1.04] tracking-tight"
style="font-size: clamp(2.25rem, 5vw, 3.75rem);"
class="font-display font-normal leading-[1.04] tracking-tight text-headline-lg"
>
{{ headline }}
<em
@@ -106,8 +105,8 @@ defineEmits(['notify'])
display: inline-flex;
align-items: center;
justify-content: center;
width: 72px;
height: 72px;
width: var(--size-orbit);
height: var(--size-orbit);
}
.rv-orbit-ring {
position: absolute;

View File

@@ -215,9 +215,20 @@ function priceLabel(p) {
return p.price ? `${p.price}` : ''
}
// Real anchors still navigate; prevent the '#' fallback from hash-jumping.
// Always suppress the browser's native anchor navigation. The row's
// `href` is retained so middle-click / right-click "open in new tab"
// keeps working semantically, but a primary-click is a *selection*:
// we emit `select` and let the parent decide what happens (add to
// cart, route to the PDP, close a drawer, etc.). Previously an
// unprevented primary-click also followed the href, which on the
// homepage caused a full-page navigation to `/shop/<slug>` — a
// route that doesn't exist — leaving the SPA in an inconsistent
// state behind the intended "add to cart" flow.
function onRowClick(i, item, e) {
if (!item.href) e.preventDefault()
// Respect modifier-click intent (open in new tab / window): let the
// browser handle those natively without also firing `select`.
if (e.metaKey || e.ctrlKey || e.shiftKey || e.button === 1) return
e.preventDefault()
selectAt(i)
}
</script>

View File

@@ -0,0 +1,73 @@
<script setup>
/**
* WaveDivider — the home page's signature soft-wave transition
* between two full-bleed coloured sections. Extracted from
* HomePage.vue so the shop page (and any future sections page) can
* reuse the same visual grammar instead of duplicating the SVG.
*
* The SVG is fully opaque by design: a `to` rect fills the whole
* viewBox so the bottom row is solid destination colour (matches
* the section below → no seam), and a `from` path paints the wavy
* top portion (matches the section above → no seam). Leaving the
* top half transparent caused browsers to anti-alias the path's
* top/bottom edges against the parent and produce hairline
* artefacts.
*
* Tone names (`brand`, `cream`, `surface`, `paper`) mirror the
* surface tokens used across Hero / About / Bundles etc. so calls
* read as "from X to Y" without the caller knowing the underlying
* CSS-variable names.
*/
import { computed } from 'vue'
const props = defineProps({
/** Colour of the section above the wave — painted on the wavy top. */
from: {
type: String,
default: 'brand',
validator: (v) => ['brand', 'cream', 'surface', 'paper'].includes(v),
},
/** Colour of the section below the wave — fills the solid bottom. */
to: {
type: String,
default: 'cream',
validator: (v) => ['brand', 'cream', 'surface', 'paper'].includes(v),
},
})
const toneVar = {
brand: 'var(--color-brand)',
cream: 'var(--color-cream)',
surface: 'var(--color-surface)',
paper: 'var(--color-paper)',
}
const toneBg = {
brand: 'bg-brand',
cream: 'bg-cream',
surface: 'bg-surface',
paper: 'bg-paper',
}
// The wrapping bg-* class paints any 1-device-pixel gap that could
// otherwise show up between the SVG's bottom and the next section
// during subpixel rounding — matches the `from` tone so the wave
// rests flush on the section above.
const wrapperClass = computed(() => toneBg[props.from])
const fromFill = computed(() => toneVar[props.from])
const toFill = computed(() => toneVar[props.to])
</script>
<template>
<svg
aria-hidden="true"
:class="['block w-full h-12 md:h-16 shrink-0 -mb-px', wrapperClass]"
viewBox="0 0 1440 64"
preserveAspectRatio="none"
>
<rect width="1440" height="64" :fill="toFill" />
<path
d="M0,0 L0,40 C320,4 520,60 720,32 C920,4 1120,60 1440,24 L1440,0 Z"
:fill="fromFill"
/>
</svg>
</template>

View File

@@ -0,0 +1,44 @@
<script setup>
/**
* BundlesBenefits — the checklist rendered alongside both Bundles
* layouts. Accepts a positioning hint so the caller can align the
* list flush-left in a grid cell (stacked layout) without the
* subcomponent needing to know anything about grid context.
*/
import Icon from '../Icon.vue'
defineProps({
benefits: {
type: Array,
required: true,
validator: (arr) => arr.every((v) => typeof v === 'string'),
},
/** Applied to the root `<ul>`. Stacked layout uses
* `lg:justify-self-start lg:max-w-sm` so the list sits at the
* left of its grid column; sidebar layout passes nothing. */
listClass: { type: String, default: '' },
})
</script>
<template>
<ul
v-if="benefits.length"
:class="['flex flex-col gap-4', listClass]"
>
<li
v-for="benefit in benefits.slice(0, 3)"
:key="benefit"
class="flex items-start gap-3"
>
<span
aria-hidden="true"
class="mt-0.5 inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-brand-wash text-brand"
>
<Icon name="check" :size="14" :stroke-width="2.2" />
</span>
<span class="font-sans text-sm font-semibold text-ink leading-snug">
{{ benefit }}
</span>
</li>
</ul>
</template>

View File

@@ -0,0 +1,39 @@
<script setup>
/**
* BundlesHeader — shared headline + sub block rendered by both
* Bundles layouts (sidebar and stacked). Kept local to
* `design-system/components/internal/` so the top-level index stays
* focused on publicly-composed primitives (Bundles, BundleCard, etc.)
* and this stays plainly "an implementation detail of Bundles".
*/
defineProps({
headline: { type: String, default: '' },
headlineEm: { type: String, default: '' },
sub: { type: String, default: '' },
/** Tailwind max-width utility applied to the sub paragraph. Callers
* pass whichever fits their column rhythm — `max-w-md` for the
* narrow sidebar, `max-w-2xl` for a full-width banner, etc. Kept
* as a string rather than an enum so we don't have to maintain an
* allow-list in two places. */
subMaxWidth: { type: String, default: 'max-w-md' },
})
</script>
<template>
<div v-if="headline || headlineEm || sub" class="flex flex-col gap-4">
<h2
v-if="headline || headlineEm"
class="font-display font-normal leading-[1.05] tracking-tight text-ink text-headline-md"
>
{{ headline }}
<em
v-if="headlineEm"
class="italic font-light text-brand"
>{{ headlineEm }}</em>
</h2>
<p
v-if="sub"
:class="['text-base leading-relaxed text-muted', subMaxWidth]"
>{{ sub }}</p>
</div>
</template>

View File

@@ -29,6 +29,12 @@
--color-line: color-mix(in srgb, var(--color-brand) 11%, transparent);
--color-line-strong: color-mix(in srgb, var(--color-brand) 22%, transparent);
--color-cream: #f4efe4;
/* Darker cream — brand-tinted so it stays in the warm-green palette
rather than drifting toward muddy taupe. Used as a visible border
or rule where plain `--color-cream` would disappear against the
surface ground, and `--color-line-strong` (brand-tinted hairline)
would read as "technical line" rather than "paper edge". */
--color-cream-dark: color-mix(in oklab, var(--color-cream), var(--color-brand) 18%);
--color-surface: #faf7f1;
--color-paper: #ffffff;
@@ -61,13 +67,31 @@
--text-3xl: 1.875rem;
--text-4xl: 2.25rem;
--text-5xl: 3rem;
/* Section-headline scale — fluid clamps shared by full-bleed
sections (Hero, About, Revitalization, Bundles). Centralised so
the home page reads as one typographic rhythm rather than a set
of individually-tuned clamps. `display` is the first-fold hero
statement; `headline-lg` is the standard second-tier section
heading; `headline-md` is a quieter band (Bundles). Tailwind v4
auto-generates `text-display` / `text-headline-lg` / `text-
headline-md` utilities from these custom properties. */
--text-display: clamp(3.25rem, 5.2vw, 5.125rem);
--text-headline-lg: clamp(2.25rem, 5vw, 3.75rem);
--text-headline-md: clamp(2rem, 4vw, 3rem);
--tracking-eyebrow: 0.08em;
--tracking-label: 0.04em;
--tracking-wide: 0.12em;
--tracking-tight: -0.025em;
/* ——— Iconography sizing —————————————————————————————————— */
/* Orbit is the decorative dot-on-a-ring glyph used in
Revitalization's feature cluster. Kept as a token so any
future "pillar / feature / science-beat" block can match
without re-deriving the geometry. */
--size-orbit: 72px;
/* ——— Radius ———————————————————————————————————————————————— */
--radius-xs: 6px;
--radius-sm: 10px;

View File

@@ -5,11 +5,32 @@
const de = {
// Navbar (also used by the Navbar preview)
'nav.shop': 'Shop',
'nav.cook': 'Kochen',
'nav.clean': 'Reinigen',
'nav.care': 'Pflege',
'nav.applications': 'Anwendungen',
'nav.bundles': 'Bundles',
'nav.revitalization': 'Revitalisierung',
'nav.about': 'Über uns',
'nav.contact': 'Kontakt',
// Shop page — section headlines for the three use-case groups.
'shop.eyebrow': 'Unser Sortiment',
'shop.headline': 'Kaiser-Natron',
'shop.headline.em': 'für jeden Bereich',
'shop.sub': 'Vom Kochen über das Reinigen bis zur Pflege: drei Sammlungen, ein Rohstoff.',
'shop.section.cook.headline': 'Backen, kochen,',
'shop.section.cook.headline.em': 'gesund verdauen.',
'shop.section.cook.sub': 'Pulver und Tabletten — die Basis für Teig, Gerichte und guten Geschmack.',
'shop.section.clean.headline': 'Schrubben, waschen,',
'shop.section.clean.headline.em': 'alles sauber.',
'shop.section.clean.sub': 'Natron-basierte Reiniger und Waschhelfer, die auch bei hartnäckigem Schmutz überzeugen.',
'shop.section.care.headline': 'Baden, pflegen,',
'shop.section.care.headline.em': 'durchatmen.',
'shop.section.care.sub': 'Bade- und Pflegeprodukte, abgestimmt auf den Alltag und den Sport.',
'shop.feature.cook': 'Für die Küche',
'shop.feature.clean': 'Für den Haushalt',
'shop.feature.care': 'Für Körper & Pflege',
'shop.feature.cta': 'Zur Kategorie',
'cart.open': 'Warenkorb öffnen',
'cart.label': 'Warenkorb',
'cart.subtotal': 'Zwischensumme',
@@ -272,6 +293,11 @@ const de = {
'home.banner.headline.b': 'im Haushalt.',
'home.banner.sub': 'Vom Kuchen über das Bad bis zur Wäsche Kaiser-Natron leistet überall still und zuverlässig seine Arbeit.',
// Home page mobile-only hero category shortcuts (Clean / Cook / Care).
'home.categories.clean': 'Putzen',
'home.categories.cook': 'Kochen',
'home.categories.care': 'Pflege',
// Bundles section — copy for the sidebar, card chrome, and carousel.
'bundles.headline.a': 'Bundles &',
'bundles.headline.em': 'Vorteile',
@@ -392,11 +418,32 @@ const atOverrides = {
const en = {
'nav.shop': 'Shop',
'nav.cook': 'Cook',
'nav.clean': 'Clean',
'nav.care': 'Care',
'nav.applications': 'Uses',
'nav.bundles': 'Bundles',
'nav.revitalization': 'Revitalisation',
'nav.about': 'About',
'nav.contact': 'Contact',
// Shop page — section headlines for the three use-case groups.
'shop.eyebrow': 'Our range',
'shop.headline': 'Kaiser Natron',
'shop.headline.em': 'for every corner',
'shop.sub': 'From cooking to cleaning to care — three collections, one ingredient.',
'shop.section.cook.headline': 'Bake, cook,',
'shop.section.cook.headline.em': 'digest well.',
'shop.section.cook.sub': 'Powders and tablets — the quiet foundation under bread, cakes and good digestion.',
'shop.section.clean.headline': 'Scrub, wash,',
'shop.section.clean.headline.em': 'all clean.',
'shop.section.clean.sub': 'Natron-based cleaners and laundry helpers that hold up against stubborn grime.',
'shop.section.care.headline': 'Bathe, soften,',
'shop.section.care.headline.em': 'breathe easy.',
'shop.section.care.sub': 'Bath and care products tuned for daily life and sport.',
'shop.feature.cook': 'For the kitchen',
'shop.feature.clean': 'For the home',
'shop.feature.care': 'For body & care',
'shop.feature.cta': 'Shop category',
'cart.open': 'Open cart',
'cart.label': 'Cart',
'cart.subtotal': 'Subtotal',
@@ -643,6 +690,11 @@ const en = {
'home.banner.headline.b': 'around the home.',
'home.banner.sub': 'From baking to bathing to laundry — Kaiser Natron quietly does its work wherever you need it.',
// Home page mobile-only hero category shortcuts.
'home.categories.clean': 'Clean',
'home.categories.cook': 'Cook',
'home.categories.care': 'Care',
// Bundles section
'bundles.headline.a': 'Bundles &',
'bundles.headline.em': 'Benefits',

View File

@@ -1,87 +0,0 @@
<script setup>
import { computed } from 'vue'
import { RouterLink, useRoute } from 'vue-router'
const route = useRoute()
const isDesign = computed(() => route.name === 'design')
const designSections = [
{ id: 'colors', label: 'Colors' },
{ id: 'typography', label: 'Typography' },
{ id: 'radii', label: 'Radii' },
{ id: 'shadows', label: 'Shadows' },
{ id: 'buttons', label: 'Buttons' },
{ id: 'badges', label: 'Badges' },
{ id: 'inputs', label: 'Inputs' },
{ id: 'cards', label: 'Cards' },
]
</script>
<template>
<div class="min-h-screen flex">
<!-- Sidebar -->
<aside
class="fixed inset-y-0 left-0 w-[260px] border-r border-[var(--color-line)] bg-[var(--color-surface)] flex flex-col z-40"
>
<!-- Logo -->
<div class="h-[78px] shrink-0 flex items-center px-6 border-b border-[var(--color-line)]">
<RouterLink
to="/"
class="font-display text-[20px] font-normal tracking-[-0.01em] text-[var(--color-ink)]"
>
Kaiser<span class="italic font-light text-[var(--color-brand-soft)]"> Natron</span>
</RouterLink>
</div>
<!-- Primary nav -->
<nav class="flex-1 overflow-y-auto p-4 space-y-1">
<RouterLink
to="/"
class="flex items-center gap-3 px-3 py-2 rounded-[var(--radius-sm)] text-[14px] font-medium text-[var(--color-muted)] hover:text-[var(--color-brand)] hover:bg-[rgba(28,58,40,0.06)] transition-colors"
active-class="!text-[var(--color-brand)] !bg-[rgba(28,58,40,0.08)]"
>
<span class="inline-block w-1.5 h-1.5 rounded-full bg-current opacity-60" />
Home
</RouterLink>
<div>
<RouterLink
to="/design"
class="flex items-center gap-3 px-3 py-2 rounded-[var(--radius-sm)] text-[14px] font-medium text-[var(--color-muted)] hover:text-[var(--color-brand)] hover:bg-[rgba(28,58,40,0.06)] transition-colors"
active-class="!text-[var(--color-brand)] !bg-[rgba(28,58,40,0.08)]"
>
<span class="inline-block w-1.5 h-1.5 rounded-full bg-current opacity-60" />
Design system
</RouterLink>
<!-- Nested sub-sections, visible only on /design -->
<div
v-if="isDesign"
class="mt-1 ml-[18px] pl-3 border-l border-[var(--color-line)] flex flex-col"
>
<a
v-for="s in designSections"
:key="s.id"
:href="`#${s.id}`"
class="px-3 py-1.5 rounded-[var(--radius-sm)] text-[13px] font-medium text-[var(--color-muted)] hover:text-[var(--color-brand)] hover:bg-[rgba(28,58,40,0.05)] transition-colors"
>
{{ s.label }}
</a>
</div>
</div>
</nav>
<!-- Sidebar footer -->
<div class="shrink-0 p-4 border-t border-[var(--color-line)]">
<p class="text-[11px] font-bold uppercase tracking-[var(--tracking-eyebrow)] text-[var(--color-muted)]">
Kaiser Natron · v0.1
</p>
</div>
</aside>
<!-- Main content (offset by sidebar width) -->
<main class="flex-1 ml-[260px] min-w-0">
<slot />
</main>
</div>
</template>

View File

@@ -32,13 +32,35 @@ const bannerProductId = 'kaiser-natron-pulver-250-g-grosspackung'
// Homepage top-level nav items — overrides the Navbar default so the
// homepage reads as the shop entry point (Shop / Bundles / Revitalisierung
// / Über uns) instead of the generic catalogue chrome.
// Primary nav — the top-level shop destinations, rendered on the left
// of the Navbar. Cook / Clean / Care deep-link into the Shop page's
// use-case sections so users land on the right band immediately.
const navItems = [
{ key: 'nav.shop', href: '#' },
{ key: 'nav.shop', href: '/shop' },
{ key: 'nav.cook', href: '/shop#cook' },
{ key: 'nav.clean', href: '/shop#clean' },
{ key: 'nav.care', href: '/shop#care' },
]
// Secondary nav — supporting pages. Rendered on the right, tucked to
// the left of the search trigger. Same visual treatment as primary so
// the split reads as "categories | pages" rather than two navs.
const navSecondaryItems = [
{ key: 'nav.bundles', href: '#bundles' },
{ key: 'nav.revitalization', href: '#revitalize' },
{ key: 'nav.about', href: '#about' },
]
// Mobile-only category shortcuts rendered under the hero image. Three
// pills that point at the shop's top-level use-cases. Labels are
// translated through the page i18n so the German/English splits stay
// in sync with the rest of the site copy.
const heroCategories = computed(() => [
{ label: t('home.categories.clean'), href: '#clean' },
{ label: t('home.categories.cook'), href: '#cook' },
{ label: t('home.categories.care'), href: '#care' },
])
// Bundles sidebar copy resolves through the page's own i18n namespace so
// component internals stay decoupled from any particular key tree.
const bundlesCopy = computed(() => ({
@@ -92,8 +114,7 @@ const bundles = [
],
price: 24.9,
memberPrice: 21.17,
image:
'/products/cutouts/kaiser-natron-pulver-250-g-grosspackung-removebg-preview-1.png',
image: '/products/ai/kaiser-natron-pulver-250-g-grosspackung.png',
imageAlt: 'Haushalts-Bundle mit Kaiser-Natron',
badge: 'Bestseller',
badgeVariant: 'accent',
@@ -105,7 +126,7 @@ const bundles = [
items: ['1× Holste Wasch-Soda 500 g', '1× Gazelle Wäschestärke 1 l', '1× Linda Fleckenweg 200 ml'],
price: 22.9,
memberPrice: 19.47,
image: '/products/cutouts/holste-wasch-soda-500-g-beutel-Photoroom.png',
image: '/products/ai/kaiser-natron-pulver-250-g-grosspackung.png',
imageAlt: 'Wäsche & Pflege Bundle',
badge: '',
badgeVariant: 'accent',
@@ -117,8 +138,7 @@ const bundles = [
items: ['1× Kaiser-Natron Tabletten 100 g', '1× Kaiser-Natron Bad 500 g', '1× Kaiser-Natron Fußbad 500 g'],
price: 29.9,
memberPrice: 25.42,
image:
'/products/cutouts/kaiser-natron-pulver-250-g-grosspackung-removebg-preview-3.png',
image: '/products/ai/kaiser-natron-bad-500-g.png',
imageAlt: 'Wohlfühl-Bundle mit Kaiser-Natron Bad',
badge: '',
badgeVariant: 'accent',
@@ -179,45 +199,27 @@ async function onSearchSelect(product) {
cartOpen.value = true
}
// Hydrate from the API on mount — today this reads the local store, later
// it will hit `GET /api/cart`. Either way the drawer has data to show.
// First-fold vertical centering: the sticky navbar sits above the green
// hero container and occupies layout space. If the green container is a
// full 100svh tall, the hero centers inside that block, which sits *below*
// the navbar — so the hero's visual center ends up ~navH/2 below the
// viewport's visual center (between nav bottom and viewport bottom).
// First-fold vertical centering. The sticky navbar takes flow space
// above the green wrapper; if the wrapper is a full 100svh tall, the
// hero centers inside that block (which starts BELOW the nav) and
// its visual center lands ~navH/2 below the viewport's true center.
//
// Fix: set the green container's min-height to `100svh - navH`, so the
// flex-centering wrapper inside centers the hero exactly within the
// available viewport area below the sticky nav.
// The wrapper's height is driven by CSS: `100svh - var(--nav-h)`,
// with `--nav-h` defaulted in global styles so first paint is correct.
// This ResizeObserver refines `--nav-h` at runtime so the wrapper
// tracks real Navbar height changes (logo swaps, language changes,
// responsive breakpoints) without a layout shift.
const navRef = ref(null)
const navHeight = ref(0)
const isMdUp = ref(false)
let navResizeObserver = null
let mdQuery = null
function syncNavHeight() {
const el = navRef.value
const node = el && (el.$el || el)
if (!node || typeof window === 'undefined') return
navHeight.value = Math.round(node.getBoundingClientRect().height)
document.documentElement.style.setProperty('--nav-h', `${navHeight.value}px`)
const h = Math.round(node.getBoundingClientRect().height)
document.documentElement.style.setProperty('--nav-h', `${h}px`)
}
const heroFoldStyle = computed(() => {
const h = navHeight.value
if (!h || !isMdUp.value) return {}
// Override Tailwind's `md:min-h-svh` with a nav-aware value. Inline
// styles win over classes, so this reliably shrinks the centering
// block to the viewport area actually visible below the sticky nav.
return { minHeight: `calc(100svh - ${h}px)` }
})
onMounted(() => {
fetchCart()
// Match Tailwind's `md` breakpoint (768px).
if (typeof window !== 'undefined' && window.matchMedia) {
mdQuery = window.matchMedia('(min-width: 768px)')
isMdUp.value = mdQuery.matches
mdQuery.addEventListener('change', onMdChange)
}
syncNavHeight()
if (typeof ResizeObserver !== 'undefined' && navRef.value) {
const node = navRef.value.$el || navRef.value
@@ -226,12 +228,8 @@ onMounted(() => {
}
window.addEventListener('resize', syncNavHeight)
})
function onMdChange(e) {
isMdUp.value = e.matches
}
onBeforeUnmount(() => {
if (navResizeObserver) navResizeObserver.disconnect()
if (mdQuery) mdQuery.removeEventListener('change', onMdChange)
if (typeof window !== 'undefined') window.removeEventListener('resize', syncNavHeight)
})
</script>
@@ -250,67 +248,90 @@ onBeforeUnmount(() => {
variant="brand"
layout="standard"
:items="navItems"
:secondary-items="navSecondaryItems"
:cart-count="cart.count"
:products="products"
@cart="cartOpen = true"
@search="onSearchSelect"
/>
<!-- First-fold wrapper full viewport height, pulled up under the
sticky nav via a negative margin equal to `--nav-h`. The nav
and the wrapper share the brand green, so the overlap reads as
a single continuous surface, and the hero centers at the TRUE
viewport vertical midpoint (50svh) rather than the midpoint of
the nav-offset space below it. The wave divider sits OUTSIDE
this wrapper so it never eats vertical space from the centering
calculation. `--nav-h` is defaulted in global CSS so first
paint is correct; a ResizeObserver refines it on mount. -->
<div
class="flex flex-col bg-brand md:min-h-svh"
:style="heroFoldStyle"
class="flex flex-col bg-brand md:min-h-[calc(100svh-var(--nav-h))] md:justify-center"
>
<div class="md:flex-1 md:flex md:items-center">
<Hero
class="w-full"
variant="split"
tone="brand"
:eyebrow="t('ds.hero.eyebrow')"
:subheadline="t('ds.hero.sub')"
:image="imgPulver250"
image-alt="Kaiser-Natron Pulver 250 g Großpackung"
:cta-label="t('ds.buttons.addToCart')"
:secondary-label="t('ds.buttons.learnMore')"
secondary-href="/anwendungen"
@cta="onHeroAdd"
>
<template #headline>
{{ t('ds.hero.headline.a') }}
<em class="italic font-light text-accent-soft">{{ t('ds.hero.headline.em') }}</em>
{{ t('ds.hero.headline.b') }}
</template>
</Hero>
</div>
<!-- Wave divider from brand-green cream. The SVG is fully opaque:
a cream rect fills the whole viewBox so the SVG's bottom row is
solid cream (matches the banner below → no seam), and a green
path paints the top portion (matches the bg-brand parent above
→ no seam). The earlier version left the top half transparent,
which caused browsers to anti-alias the path's top/bottom
edges against the parent and produce hairline artifacts. -->
<svg
aria-hidden="true"
class="block w-full h-12 md:h-16 shrink-0 -mb-px"
viewBox="0 0 1440 64"
preserveAspectRatio="none"
<Hero
class="w-full"
variant="split"
tone="brand"
:eyebrow="t('ds.hero.eyebrow')"
:subheadline="t('ds.hero.sub')"
:image="imgPulver250"
image-alt="Kaiser-Natron Pulver 250 g Großpackung"
:cta-label="t('ds.buttons.addToCart')"
:secondary-label="t('ds.buttons.learnMore')"
secondary-href="/anwendungen"
@cta="onHeroAdd"
>
<rect width="1440" height="64" fill="var(--color-cream)" />
<path
d="M0,0 L0,40 C320,4 520,60 720,32 C920,4 1120,60 1440,24 L1440,0 Z"
fill="var(--color-brand)"
/>
</svg>
<template #headline>
{{ t('ds.hero.headline.a') }}
<em class="italic font-light text-accent-soft">{{ t('ds.hero.headline.em') }}</em>
{{ t('ds.hero.headline.b') }}
</template>
<!-- Mobile-only category shortcuts. Three pills sit directly
under the hero jar so the phone user can jump straight to
a use-case context without scrolling past the whole fold.
Hidden on md+ because desktop already has full nav chrome. -->
<template #afterMedia>
<div class="md:hidden mt-6 flex items-center justify-center gap-2">
<a
v-for="cat in heroCategories"
:key="cat.href"
:href="cat.href"
class="inline-flex items-center justify-center rounded-pill border border-cream/50 px-5 py-2.5 text-sm font-semibold tracking-label text-cream transition-colors duration-base hover:border-cream hover:bg-cream-wash-strong"
>{{ cat.label }}</a>
</div>
</template>
</Hero>
</div>
<!-- Wave divider from brand-green cream. Sits OUTSIDE the fold
wrapper so it doesn't steal vertical space from the hero's
centering. The SVG is fully opaque: a cream rect fills the
whole viewBox so the SVG's bottom row is solid cream (matches
the banner below → no seam), and a green path paints the top
portion (matches the bg-brand fold above → no seam). -->
<svg
aria-hidden="true"
class="block w-full h-12 md:h-16 shrink-0 -mb-px bg-brand"
viewBox="0 0 1440 64"
preserveAspectRatio="none"
>
<rect width="1440" height="64" fill="var(--color-cream)" />
<path
d="M0,0 L0,40 C320,4 520,60 720,32 C920,4 1120,60 1440,24 L1440,0 Z"
fill="var(--color-brand)"
/>
</svg>
<!-- Second-fold product banner — same Hero component, cream surface,
split layout reversed so the product sits on the left. The -mt-px
pairs with the wave's -mb-px to overlap the two sections by 1 CSS
split layout reversed so the product sits on the left. `compact`
tightens the desktop media sizing so this section reads as a
companion band, not a second full hero stage. The -mt-px pairs
with the wave's -mb-px to overlap the two sections by 1 CSS
pixel and hide any device-pixel seam. -->
<Hero
class="banner-shrink-desktop -mt-px"
class="-mt-px"
variant="split"
tone="cream"
reverse
compact
:eyebrow="t('home.banner.eyebrow')"
:subheadline="t('home.banner.sub')"
:image="imgBanner"
@@ -351,6 +372,7 @@ onBeforeUnmount(() => {
md+ flips to a one-at-a-time scroll-snap carousel. -->
<Bundles
class="-mt-px"
layout="stacked"
:bundles="bundles"
:headline="bundlesCopy.headline"
:headline-em="bundlesCopy.headlineEm"
@@ -435,18 +457,3 @@ onBeforeUnmount(() => {
/>
</template>
<style scoped>
/* Banner (second-fold Hero) desktop sizing override.
Hero was globally scaled +30%. On desktop we want the banner to read
~20% smaller than ORIGINAL size (0.8 × 575px ≈ 460px max width, and
0.8 × 60svh = 48svh max height). Mobile/tablet keep the enlarged
sizing from Hero.vue. */
@media (min-width: 1024px) {
.banner-shrink-desktop :deep(img) {
max-height: 48svh;
}
.banner-shrink-desktop :deep(.relative.mx-auto.w-full.max-w-6xl > div:last-child > div.relative) {
max-width: 460px;
}
}
</style>

252
src/pages/ShopPage.vue Normal file
View File

@@ -0,0 +1,252 @@
<script setup>
import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
import Navbar from '@/design-system/components/Navbar.vue'
import ProductCard from '@/design-system/components/ProductCard.vue'
import WaveDivider from '@/design-system/components/WaveDivider.vue'
import CartDrawer from '@/design-system/components/CartDrawer.vue'
import {
products,
productsByUseCase,
USE_CASES,
fetchCart,
addToCart,
updateCartItem,
removeFromCart,
} from '@/api/index.js'
import { useCartStore } from '@/stores/cart.js'
import { useI18n } from '@/i18n/index.js'
const { t } = useI18n()
const cart = useCartStore()
const cartOpen = ref(false)
// Site-wide nav split mirrors HomePage so the header reads as one
// piece of chrome across both routes. On /shop the category links
// point at in-page anchors (`#cook`, `#clean`, `#care`) so they
// scroll within the page rather than re-route.
const navItems = [
{ key: 'nav.shop', href: '/shop' },
{ key: 'nav.cook', href: '#cook' },
{ key: 'nav.clean', href: '#clean' },
{ key: 'nav.care', href: '#care' },
]
const navSecondaryItems = [
{ key: 'nav.bundles', href: '/#bundles' },
{ key: 'nav.revitalization', href: '/#revitalize' },
{ key: 'nav.about', href: '/#about' },
]
// Group products by use-case once; iterate a stable config below.
// The featured tiles in the top banner each pick the FIRST product
// in their group — a representative face for that band. The
// sections themselves display every product in the group.
const grouped = computed(() => productsByUseCase(products))
const featuredTiles = computed(() =>
USE_CASES.map((id) => ({
id,
label: t(`shop.feature.${id}`),
product: grouped.value[id][0],
})),
)
const sections = computed(() =>
USE_CASES.map((id, i) => ({
id,
headline: t(`shop.section.${id}.headline`),
headlineEm: t(`shop.section.${id}.headline.em`),
sub: t(`shop.section.${id}.sub`),
products: grouped.value[id],
// Alternate tones so neighbouring sections read as distinct
// surfaces without a hard rule. Cook/Care land on cream;
// Clean sits on surface between them for contrast.
tone: i % 2 === 0 ? 'cream' : 'surface',
})),
)
async function onAdd(product) {
await addToCart(product.id, 1)
cartOpen.value = true
}
async function onSearchSelect(product) {
await addToCart(product.id, 1)
cartOpen.value = true
}
async function onQty({ productId, quantity }) {
await updateCartItem(productId, quantity)
}
async function onRemove(productId) {
await removeFromCart(productId)
}
// `--nav-h` is defaulted in global styles; this ResizeObserver refines
// it so deep-link anchor targets (e.g. `/shop#care`) land just below
// the sticky nav via each section's `scroll-mt` offset.
const navRef = ref(null)
let navResizeObserver = null
function syncNavHeight() {
const el = navRef.value
const node = el && (el.$el || el)
if (!node || typeof window === 'undefined') return
const h = Math.round(node.getBoundingClientRect().height)
document.documentElement.style.setProperty('--nav-h', `${h}px`)
}
onMounted(() => {
fetchCart()
syncNavHeight()
if (typeof ResizeObserver !== 'undefined' && navRef.value) {
const node = navRef.value.$el || navRef.value
navResizeObserver = new ResizeObserver(syncNavHeight)
navResizeObserver.observe(node)
}
window.addEventListener('resize', syncNavHeight)
})
onBeforeUnmount(() => {
if (navResizeObserver) navResizeObserver.disconnect()
if (typeof window !== 'undefined') window.removeEventListener('resize', syncNavHeight)
})
</script>
<template>
<Navbar
ref="navRef"
variant="brand"
layout="standard"
:items="navItems"
:secondary-items="navSecondaryItems"
:cart-count="cart.count"
:products="products"
@cart="cartOpen = true"
@search="onSearchSelect"
/>
<!-- First-fold green banner full viewport height, pulled up under
the sticky nav so the hero content centers at the TRUE viewport
midpoint (matches the home page's first fold). The content is a
page-title band + three featured product tiles, one per use-case
section, with anchor links into the sections below. -->
<div
class="flex flex-col bg-brand text-cream md:min-h-[calc(100svh-var(--nav-h))] md:justify-center"
>
<div class="mx-auto w-full max-w-6xl px-6 py-12 sm:px-8 sm:py-16 md:px-12 md:py-12 lg:px-16 lg:py-16">
<!-- Title band. Mixed-font banner treatment (Hero-style): normal
display weight + italic light for the emphasis phrase. -->
<div class="flex flex-col items-center text-center gap-4 max-w-3xl mx-auto">
<h1 class="font-display font-normal leading-[1.05] tracking-tight text-cream text-headline-lg">
{{ t('shop.headline') }}
<em class="italic font-light text-accent-soft">{{ t('shop.headline.em') }}</em>
</h1>
<p class="text-base md:text-lg leading-relaxed text-cream/80 max-w-2xl">
{{ t('shop.sub') }}
</p>
</div>
<!-- Three featured tiles — rule of 3. One representative product
per use-case, each tile is an anchor into its section. Uses
the cream-wash-on-brand container pattern from the
LanguageSwitcher's `brand` tone so tiles read as lifted off
the green ground without another heavy surface.
Image uses aspect-[4/3] (not aspect-square) with a svh-
relative height cap so the whole fold title + sub + three
tiles + padding stays inside 100svh at desktop heights
from ~720px up. Mobile stacks the tiles; the fold can
overflow below there because phones scroll naturally. -->
<ul class="mt-8 md:mt-10 grid gap-4 sm:gap-5 md:gap-6 grid-cols-1 sm:grid-cols-3">
<li v-for="tile in featuredTiles" :key="tile.id">
<a
:href="`#${tile.id}`"
class="group flex h-full flex-col items-center gap-4 p-4 md:p-5 rounded-md border border-cream-line bg-cream-wash hover:bg-cream-wash-strong transition-colors duration-base"
>
<div class="w-full aspect-[4/3] max-h-[30svh] md:max-h-[26svh] lg:max-h-[28svh] rounded-md bg-cream overflow-hidden flex items-center justify-center">
<img
:src="tile.product.image"
:alt="tile.product.title"
loading="lazy"
decoding="async"
class="w-full h-full object-contain p-4 md:p-5"
/>
</div>
<div class="flex flex-col items-center text-center gap-1">
<p class="eyebrow text-accent">{{ tile.label }}</p>
<h3 class="font-display text-lg md:text-xl font-normal leading-tight text-cream">
{{ tile.product.title }}
</h3>
</div>
<span
class="mt-auto inline-flex items-center gap-1.5 text-sm font-semibold tracking-label text-cream/80 group-hover:text-accent transition-colors duration-base"
>
{{ t('shop.feature.cta') }}
<span aria-hidden="true" class="transition-transform duration-base group-hover:translate-x-1"></span>
</span>
</a>
</li>
</ul>
</div>
</div>
<!-- Three use-case sections. Each has its own banner-style mixed-font
heading (no eyebrow pill), a 3-up product grid capped at the
rule of 3 per row, and wave dividers on either side so the
page reads with the same rhythm as the home page. -->
<template v-for="(section, i) in sections" :key="section.id">
<!-- Wave into the section. Previous surface is `brand` for the
first divider (coming out of the green fold), then alternates
between cream/surface to match the previous section's tone. -->
<WaveDivider :from="i === 0 ? 'brand' : sections[i - 1].tone" :to="section.tone" />
<section
:id="section.id"
:class="[
'-mt-px scroll-mt-[calc(var(--nav-h)+1rem)]',
section.tone === 'cream' ? 'bg-cream text-ink' : 'bg-surface text-ink',
]"
>
<div class="mx-auto w-full max-w-6xl px-6 py-16 sm:px-8 sm:py-20 md:px-12 md:py-24 lg:px-16 lg:py-28">
<div class="flex flex-col gap-4 max-w-3xl">
<h2 class="font-display font-normal leading-[1.05] tracking-tight text-ink text-headline-lg">
{{ section.headline }}
<em class="italic font-light text-brand">{{ section.headlineEm }}</em>
</h2>
<p class="text-lg leading-relaxed text-muted max-w-2xl">
{{ section.sub }}
</p>
</div>
<div
v-if="section.products.length"
class="mt-12 md:mt-14 grid gap-5 md:gap-7 grid-cols-1 sm:grid-cols-2 md:grid-cols-3"
>
<ProductCard
v-for="product in section.products"
:key="product.id"
:title="product.title"
:size="product.size"
:price="product.price"
:image="product.image"
:image-alt="product.title"
:href="product.href"
:tone="section.tone === 'cream' ? 'paper' : 'cream'"
:in-stock="product.inStock"
@add="onAdd(product)"
/>
</div>
</div>
</section>
</template>
<!-- Bottom clearance for the mobile floating cluster (search / cart /
menu), same pattern as HomePage so both pages align visually. -->
<div
aria-hidden="true"
class="md:hidden"
style="height: calc(100px + env(safe-area-inset-bottom));"
/>
<CartDrawer
v-model="cartOpen"
:items="cart.items"
:subtotal="cart.subtotal"
:count="cart.count"
@update-quantity="onQty"
@remove="onRemove"
@checkout="cartOpen = false"
/>
</template>

View File

@@ -1,4 +1,5 @@
<script setup>
import { computed, ref } from 'vue'
import SectionShell from './SectionShell.vue'
import DevicePreview from '@/design-system/components/DevicePreview.vue'
import { useI18n } from '@/i18n/index.js'
@@ -9,7 +10,17 @@ const { t } = useI18n()
// md up — iframe it through DevicePreview so we can demo mobile / tablet /
// desktop breakpoints side by side rather than squeezing into the docs
// column at a single width.
const src = '/design/preview/bundles'
//
// Layout variant travels to the preview route via `?layout=` so the
// iframe can re-render in the selected shape. Index-based labelling
// ('Option 1', 'Option 2', …) keeps the UI generic so the same
// switcher pattern works for any future component variant set.
const variants = [
{ id: 'sidebar', label: 'Option 1' },
{ id: 'stacked', label: 'Option 2' },
]
const variant = ref('sidebar')
const src = computed(() => `/design/preview/bundles?layout=${variant.value}`)
</script>
<template>
@@ -20,7 +31,31 @@ const src = '/design/preview/bundles'
wide
>
<section>
<DevicePreview :src="src" initial="desktop" :height="1080" />
<DevicePreview :src="src" initial="desktop" :height="1080">
<template #controls>
<!-- Variant switcher. Same pill treatment as the device
switcher on the right, aligned left so the two sit at
opposite ends of the preview's control bar. -->
<div
role="tablist"
aria-label="Layout variant"
class="inline-flex items-center p-1 gap-0.5 rounded-pill border border-line bg-paper"
>
<button
v-for="v in variants"
:key="v.id"
type="button"
role="tab"
:aria-selected="variant === v.id"
:class="[
'inline-flex items-center gap-2 px-3 py-1.5 text-[12px] font-semibold tracking-label rounded-pill transition-colors duration-base',
variant === v.id ? 'bg-brand text-accent' : 'text-muted hover:text-brand',
]"
@click="variant = v.id"
>{{ v.label }}</button>
</div>
</template>
</DevicePreview>
</section>
<section>

View File

@@ -1,9 +1,20 @@
<script setup>
import { computed } from 'vue'
import { useRoute } from 'vue-router'
import Bundles from '@/design-system/components/Bundles.vue'
import { useI18n } from '@/i18n/index.js'
const { t } = useI18n()
const route = useRoute()
// Variant selection travels in as a URL query param so the section
// page's iframe can switch layouts without reloading the component
// registry. Falls back to the default 'sidebar' layout if the param
// is missing or not one of the component's recognised variants.
const layout = computed(() => {
const q = route.query.layout
return q === 'stacked' ? 'stacked' : 'sidebar'
})
// Demo fixtures — mirrors HomePage's real content so the preview is
// representative rather than lorem-ipsum. Kept inline because preview
@@ -66,6 +77,7 @@ const benefits = computed(() => [
<template>
<div class="min-h-screen bg-surface">
<Bundles
:layout="layout"
:bundles="bundles"
:headline="t('bundles.headline.a')"
:headline-em="t('bundles.headline.em')"

View File

@@ -7,6 +7,12 @@ const routes = [
component: () => import('@/pages/HomePage.vue'),
meta: { layout: 'none' },
},
{
path: '/shop',
name: 'shop',
component: () => import('@/pages/ShopPage.vue'),
meta: { layout: 'none' },
},
{
path: '/design/preview/navbar',
name: 'ds-preview-navbar',
@@ -72,7 +78,15 @@ const routes = [
const router = createRouter({
history: createWebHistory(),
routes,
scrollBehavior: () => ({ top: 0 }),
// Anchor-aware scroll: navigating to `/shop#care` scrolls to the
// #care section rather than resetting to top. `el: ...` lets the
// router run the browser's own findElementBySelector, so the
// ShopPage sections' `scroll-mt-[calc(var(--nav-h)+1rem)]` offset
// handles the sticky-nav clearance declaratively.
scrollBehavior(to) {
if (to.hash) return { el: to.hash, behavior: 'smooth' }
return { top: 0 }
},
})
export default router