1import{c as Xe,b as Ke,r as w,s as k,u as x,j as e,l as et}from"./index-DmBrIuMr.js";import{D as tt,a as st,b as ot,c as pe,d as at}from"./dropdown-menu-DOx7VjSH.js";import{E as Ge}from"./jspdf.es.min-QP5ynwro.js";import{B as F}from"./button-BVgaPNYd.js";import{D as nt,a as it,b as rt,c as lt,d as ct}from"./dialog-D3JEJsPU.js";import{A as dt}from"./arrow-right-D6kuqmE-.js";import{E as pt}from"./external-link-BDzjTqCP.js";import{C as Te}from"./circle-check-big-BuDXyV8n.js";import{G as Qe}from"./globe-DPgUrQ5O.js";import{F as We}from"./file-image-QXgjySDd.js";import{L as he}from"./loader-circle-BgFsXzCb.js";import{U as ht}from"./upload-CglqxmSA.js";import{A as mt}from"./arrow-left-CzyOJBz-.js";import{R as ut}from"./refresh-cw-CFMYbA4X.js";import{D as Le}from"./download-C5OTLHBb.js";import{C as gt}from"./chevron-down-BuzlTV0R.js";import{F as Ce}from"./file-text-BUtOihor.js";import{D as qe}from"./dna-PP0I9YbM.js";import{P as Ze}from"./palette-DM6ZdyWE.js";import{W as ft}from"./wand-sparkles-DCx-vvW5.js";import{C as Ve}from"./copy-M8CVK2vH.js";import{T as yt}from"./type-C50H1-S8.js";import{P as bt}from"./panels-top-left-mGRm0YVF.js";import{I as vt}from"./image-ChWzI2UK.js";import{S as _t}from"./sparkles-BrrgE7yr.js";import"./index-Bf1vIFkb.js";import"./Combination-B-vZEg9O.js";import"./index-DMAls7C9.js";import"./chevron-right-Bm11si2L.js";import"./check-Bd6GKLth.js";import"./circle-Bu3JpZwb.js";import"./index-BtoCHN1J.js";/** 2 * @license lucide-react v0.462.0 - ISC 3 * 4 * This source code is licensed under the ISC license. 5 * See the LICENSE file in the root directory of this source tree. 6 */const Ye=Xe("ClipboardCopy",[["rect",{width:"8",height:"4",x:"8",y:"2",rx:"1",ry:"1",key:"tgr4d6"}],["path",{d:"M8 4H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2",key:"4jdomd"}],["path",{d:"M16 4h2a2 2 0 0 1 2 2v4",key:"3hqy98"}],["path",{d:"M21 14H11",key:"1bme5i"}],["path",{d:"m15 10-4 4 4 4",key:"5dvupr"}]]);/** 7 * @license lucide-react v0.462.0 - ISC 8 * 9 * This source code is licensed under the ISC license. 10 * See the LICENSE file in the root directory of this source tree. 11 */const De=Xe("Code",[["polyline",{points:"16 18 22 12 16 6",key:"z7tu5w"}],["polyline",{points:"8 6 2 12 8 18",key:"1eg1df"}]]),Je=[{id:"native",name:"Arcbase Native",description:"Build directly in the OS, section by section",url:null,icon:"â¨",native:!0},{id:"claude",name:"Claude",description:"Build with Claude AI â paste the brief and iterate",url:"https://claude.ai/new",icon:"ð¤"},{id:"vercel",name:"Vercel / v0",description:"Launch on Vercel with v0.dev for rapid prototyping",url:"https://v0.dev",icon:"â²"},{id:"lovable",name:"Lovable",description:"Build with Lovable's AI-powered editor",url:"https://lovable.dev",icon:"ð"},{id:"other",name:"Other",description:"Manual build or another platform",url:null,icon:"ð§"}];function xt({clientId:y,clientName:se}){var fe;const H=Ke(),[Q,m]=w.useState(!1),[C,T]=w.useState({build_platform:"",html_code:"",figma_link:"",homepage_file_path:"",homepage_file_type:"",status:"draft",notes:""}),[oe,J]=w.useState(!1),[ae,me]=w.useState(!1),[Z,ne]=w.useState(null),[X,z]=w.useState(null);w.useEffect(()=>{ue()},[y]);const ue=async()=>{const{data:f}=await k.from("website_builds").select("*").eq("client_id",y).single();if(f){const u=f;if(ne(u.id),T({build_platform:u.build_platform||"",html_code:u.html_code||"",figma_link:u.figma_link||"",homepage_file_path:u.homepage_file_path||"",homepage_file_type:u.homepage_file_type||"",status:u.status||"draft",notes:u.notes||""}),u.homepage_file_path){const{data:D}=await k.storage.from("client-media").createSignedUrl(u.homepage_file_path,3600);D!=null&&D.signedUrl&&z(D.signedUrl)}}},ie=w.useCallback(async f=>{J(!0);try{if(Z)await k.from("website_builds").update({...f,updated_at:new Date().toISOString()}).eq("id",Z);else{const{data:u}=await k.from("website_builds").insert({client_id:y,...f}).select().single();u&&ne(u.id)}x.success("Build info saved")}catch{x.error("Failed to save")}finally{J(!1)}},[y,Z]),je=f=>{const u=Je.find(t=>t.id===f),D={...C,build_platform:f};if(T(D),u!=null&&u.native){ie(D),H(`/website-builder/${y}`);return}u!=null&&u.url&&window.open(u.url,"_blank","noopener,noreferrer"),m(!0)},Ae=async f=>{var t;const u=(t=f.target.files)==null?void 0:t[0];if(!u)return;if(!["image/png","image/jpeg","image/webp","application/pdf"].includes(u.type)){x.error("Please upload a PNG, JPEG, WebP, or PDF file");return}me(!0);try{const i=u.name.split(".").pop(),l=`${y}/homepage-build/homepage.${i}`;await k.storage.from("client-media").upload(l,u,{upsert:!0});const n={...C,homepage_file_path:l,homepage_file_type:u.type};T(n);const{data:r}=await k.storage.from("client-media").createSignedUrl(l,3600);r!=null&&r.signedUrl&&z(r.signedUrl),x.success("Homepage uploaded")}catch{x.error("Upload failed")}finally{me(!1)}},$e=()=>ie(C),ge=C.html_code||C.figma_link||C.homepage_file_path;return e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"mt-8 rounded-xl border-2 border-dashed border-primary/30 bg-primary/5 p-6",children:[e.jsxs("div",{className:"flex items-center gap-3 mb-4",children:[e.jsx("div",{className:"w-10 h-10 rounded-full bg-primary/10 flex items-center justify-center",children:e.jsx(dt,{className:"w-5 h-5 text-primary"})}),e.jsxs("div",{children:[e.jsx("h3",{className:"text-base font-semibold",children:"Ready to Build?"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Launch your website with the brief above, then come back to link your deliverables"})]})]}
11),e.jsx("div",{className:"grid grid-cols-2 md:grid-cols-5 gap-3 mb-4",children:Je.map(f=>e.jsxs("button",{onClick:()=>je(f.id),className:`flex flex-col items-center gap-2 p-4 rounded-lg border text-center transition-all hover:border-primary hover:shadow-sm ${C.build_platform===f.id?"border-primary bg-primary/5 shadow-sm":"border-border bg-card"}`,children:[e.jsx("span",{className:"text-2xl",children:f.icon}),e.jsx("span",{className:"text-sm font-medium",children:f.name}),e.jsx("span",{className:"text-[10px] text-muted-foreground leading-tight",children:f.description}),f.url&&e.jsx(pt,{className:"w-3 h-3 text-muted-foreground"})]},f.id))}),ge&&e.jsxs("div",{className:"flex items-center gap-2 text-xs text-muted-foreground mb-3",children:[e.jsx(Te,{className:"w-3.5 h-3.5 text-green-600"}),"Build artifacts saved",e.jsx(F,{variant:"link",size:"sm",className:"h-auto p-0 text-xs",onClick:()=>m(!0),children:"View / Edit"})]}),!ge&&e.jsxs(F,{variant:"outline",size:"sm",onClick:()=>m(!0),className:"w-full",children:[e.jsx(De,{className:"w-4 h-4 mr-2"})," Paste HTML, Link Figma, or Upload Homepage"]})]}),e.jsx(nt,{open:Q,onOpenChange:m,children:e.jsxs(it,{className:"max-w-2xl max-h-[85vh] overflow-y-auto",children:[e.jsxs(rt,{children:[e.jsxs(lt,{children:["Website Build â ",se]}),e.jsx(ct,{children:"Paste your HTML code, link your Figma design, or upload the homepage screenshot."})]}),e.jsxs("div",{className:"space-y-6 mt-4",children:[e.jsxs("div",{children:[e.jsxs("label",{className:"flex items-center gap-2 text-sm font-medium mb-2",children:[e.jsx(De,{className:"w-4 h-4"})," HTML Code"]}),e.jsx("textarea",{className:"w-full h-40 rounded-md border bg-muted/30 p-3 text-sm font-mono resize-y focus:outline-none focus:ring-2 focus:ring-ring",placeholder:"Paste your HTML code here...",value:C.html_code,onChange:f=>T({...C,html_code:f.target.value})})]}),e.jsxs("div",{children:[e.jsxs("label",{className:"flex items-center gap-2 text-sm font-medium mb-2",children:[e.jsx(Qe,{className:"w-4 h-4"})," Figma Design Link"]}),e.jsx("input",{type:"url",className:"w-full rounded-md border bg-muted/30 px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring",placeholder:"https://www.figma.com/file/...",value:C.figma_link,onChange:f=>T({...C,figma_link:f.target.value})})]}),e.jsxs("div",{children:[e.jsxs("label",{className:"flex items-center gap-2 text-sm font-medium mb-2",children:[e.jsx(We,{className:"w-4 h-4"})," Upload Homepage (PDF, PNG, JPEG)"]}),X&&((fe=C.homepage_file_type)!=null&&fe.startsWith("image/"))?e.jsx("div",{className:"mb-3 rounded-lg border overflow-hidden",children:e.jsx("img",{src:X,alt:"Homepage preview",className:"w-full max-h-60 object-contain bg-muted/20"})}):X?e.jsxs("div",{className:"mb-3 p-3 rounded-lg border bg-muted/20 flex items-center gap-2",children:[e.jsx(We,{className:"w-5 h-5 text-muted-foreground"}),e.jsx("span",{className:"text-sm text-muted-foreground",children:"PDF uploaded"}),e.jsx("a",{href:X,target:"_blank",rel:"noreferrer",className:"text-xs text-primary underline ml-auto",children:"View"})]}):null,e.jsxs("label",{className:"flex items-center justify-center gap-2 p-4 rounded-lg border-2 border-dashed border-border hover:border-primary/50 cursor-pointer transition-colors",children:[ae?e.jsx(he,{className:"w-4 h-4 animate-spin"}):e.jsx(ht,{className:"w-4 h-4 text-muted-foreground"}),e.jsx("span",{className:"text-sm text-muted-foreground",children:ae?"Uploading...":"Click to upload or replace"}),e.jsx("input",{type:"file",className:"hidden",accept:".pdf,.png,.jpg,.jpeg,.webp",onChange:Ae,disabled:ae})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"text-sm font-medium mb-2 block",children:"Notes"}),e.jsx("textarea",{className:"w-full h-20 rounded-md border bg-muted/30 p-3 text-sm resize-y focus:outline-none focus:ring-2 focus:ring-ring",placeholder:"Any notes about the build...",value:C.notes,onChange:f=>T({...C,notes:f.target.value})})]}),e.jsxs("div",{className:"flex justify-end gap-2",children:[e.jsx(F,{variant:"outline",onClick:()=>m(!1),children:"Cancel"}),e.jsxs(F,{onClick:$e,disabled:oe,children:[oe?e.jsx(he,{className:"w-4 h-4 mr-1 animate-spin"}):e.jsx(Te,{className:"w-4 h-4 mr-1"}),"Save Build Info"]})]})]})]})})]})}
11const K=[{key:"voice-tone",title:"Brand Identity, Voice & Messaging",icon:yt},{key:"hero-concept",title:"â Hero & Homepage Concept",icon:Qe},{key:"layout-components",title:"Layout & Component Guidelines",icon:bt},{key:"homepage-copy",title:"Homepage Copy (Exact Text)",icon:Ce},{key:"design-system",title:"Design System & Visual Foundation",icon:Ze},{key:"imagery-graphics",title:"Imagery, Graphics & Visual Content",icon:vt},{key:"design-references",title:"Design Inspirations & References",icon:_t},{key:"technical-spec",title:"Technical Implementation Specs",icon:De}];function wt({filePath:y,fileName:se}){const[H,Q]=w.useState(null);return w.useEffect(()=>{k.storage.from("client-media").createSignedUrl(y,3600).then(({data:m})=>{m!=null&&m.signedUrl&&Q(m.signedUrl)})},[y]),H?e.jsx("img",{src:H,alt:se,className:"aspect-square object-cover w-full"}):e.jsx("div",{className:"aspect-square bg-muted animate-pulse"})}function ts(){const{clientId:y}=et(),se=Ke(),[H,Q]=w.useState(!0),[m,C]=w.useState(null),[T,oe]=w.useState("voice-tone"),[J,ae]=w.useState([]),[me,Z]=w.useState(null);w.useState(!1);const[ne,X]=w.useState(!1),[z,ue]=w.useState({});w.useEffect(()=>{y&&ie()},[y]);const ie=async()=>{var t,i,l,n,r,c,d,g,v,S,$,_,O;Q(!0);try{const[j,P,G,R,U]=await Promise.all([k.from("clients").select("*").eq("id",y).single(),k.from("brand_dna").select("*").eq("client_id",y).single(),k.from("homepage_copy").select("*").eq("client_id",y).single(),k.from("client_sitemaps").select("*").eq("client_id",y).single(),k.from("client_media_requests").select("id").eq("client_id",y)]),W=j.data,A=((t=P.data)==null?void 0:t.profile_data)||{},ye=((i=G.data)==null?void 0:i.sections)||[],q=R.data,re=(U.data||[]).map(b=>b.id);if(re.length>0){const{data:b}=await k.from("client_media_uploads").select("*").in("media_request_id",re);ae(b||[])}const M=A.visualBrandKit||{},L=A.designParameters||{},be={};(((l=M.colorSystem)==null?void 0:l.palette)||L.colors||[]).forEach((b,N)=>{be[`color${N}`]={name:b.name||`Color ${N+1}`,hex:b.hex,role:b.role||b.usage||"accent"}});const V=M.typography||{},Ee=L.displayFont||L.headerFont||"",Y=L.bodyFont||"",Ie=Ee||((n=V.display)==null?void 0:n.fontFamily)||"Sans-serif",ve=Y||((r=V.body)==null?void 0:r.fontFamily)||"Sans-serif",Pe=L.displayFontSource||((c=V.display)==null?void 0:c.source)||"google",Oe=L.bodyFontSource||((d=V.body)==null?void 0:d.source)||"google",E=A.visualDirection||{},ee=E.moodKeywords||((g=E.moodAndAtmosphere)==null?void 0:g.split(",").map(b=>b.trim()))||A.brandPersonality||[],B=A.brandVoiceTone||{},_e=B.characteristics||B.voiceAttributes||[],xe=B.doSay||B.samplePhrases||[],s=B.dontSay||B.avoidPhrases||[],o=[];if(M.designInspirations){const b=M.designInspirations;b.tasteGamePicks&&b.tasteGamePicks.forEach(N=>o.push(N.label||N.chosenLabel||"")),b.websiteStylePicks&&b.websiteStylePicks.forEach(N=>o.push(N.url||N.label||"")),b.moodboardAssets&&b.moodboardAssets.forEach(N=>o.push(N.label||N.url||""))}E.aesthetic&&o.push(`Visual aesthetic: ${E.aesthetic}`),E.imageryStyle&&o.push(`Imagery style: ${E.imageryStyle}`);const a=[];q!=null&&q.sitemap_data&&(Array.isArray(q.sitemap_data)?q.sitemap_data:[]).forEach(N=>{var de;(de=N.data)!=null&&de.label&&a.push({label:N.data.label,href:`/${N.data.label.toLowerCase().replace(/\s+/g,"-")}`})});const p=((v=M.logoGuidelines)==null?void 0:v.approvedDirection)||L.logoDirection||"",te=L.logoUrls||[],le=A.narrativeIdentity||{},we=le.brandEssence||le.positioning||((S=A.purpose)==null?void 0:S.statement)||"",Se=E.aesthetic||(($=M.colorSystem)==null?void 0:$.story)||"",Ne=E.imageryStyle||E.photographyDirection||"",ke=E.layoutApproach||"Structured space with generous negative space. Built on a strong, clear grid.",ce={clientName:(W==null?void 0:W.name)||"Client",brandEssence:we,visualConcept:Se,colors:be,typography:{display:{name:Ie,usage:((_=V.display)==null?void 0:_.usage)||"Primary headlines (H1), large pull quotes"},body:{name:ve,usage:((O=V.body)==null?void 0:O.usage)||"All body copy, sub-headlines, UI text"}},mood:Array.isArray(ee)?ee:[ee],voiceTone:{characteristics:_e,doSay:xe,dontSay:s}
11,designReferences:o.filter(Boolean),imageryDirection:Ne,layoutPhilosophy:ke,navbar:a,homepageSections:ye,logoDirection:p,logoUrls:te,rawDna:A};C(ce),je(ce)}catch(j){console.error("Failed to load data:",j),x.error("Failed to load client data")}Q(!1)},je=t=>{var ve,Pe,Oe,E,ee,B,_e,xe;const i=Object.values(t.colors),l=i.map((s,o)=>`- ${s.name} (${s.hex}) â Role: ${s.role}`).join(` 12`),n=t.rawDna||{},r={},c=()=>{var ke,ce,b,N,de,Ue,Fe,Me,Be,He,ze;const s=[],o=n.visualBrandKit||{},a=n.designParameters||{},p=n.visualDirection||{};(ce=(ke=o.designInspirations)==null?void 0:ke.tasteGamePicks)!=null&&ce.length&&(s.push("## Taste Game Results (Client's Visual Preferences)"),s.push("These are REAL brand systems the client was shown side-by-side and CHOSE as aligned with their taste:"),o.designInspirations.tasteGamePicks.forEach(h=>{const I=[`**${h.label||h.chosenLabel||"Selected Brand"}**`];h.category&&I.push(`Category: ${h.category}`),h.description&&I.push(`Description: ${h.description}`),h.reason&&I.push(`Why chosen: ${h.reason}`),s.push(`- ${I.join(" | ")}`)}),s.push("")),(N=(b=o.designInspirations)==null?void 0:b.websiteStylePicks)!=null&&N.length&&(s.push("## Website Style Preferences"),s.push("Specific website styles the client identified as aspirational:"),o.designInspirations.websiteStylePicks.forEach(h=>{const I=[h.label||h.category||"Style"];h.url&&I.push(`â Visit: ${h.url}`),h.notes&&I.push(`Client notes: "${h.notes}"`),h.screenshotUrl&&I.push(`Screenshot: ${h.screenshotUrl}`),s.push(`- ${I.join(" | ")}`)}),s.push("")),(Ue=(de=o.designInspirations)==null?void 0:de.moodboardAssets)!=null&&Ue.length&&(s.push("## Moodboard References"),s.push("Curated visual references assembled during brand exploration:"),o.designInspirations.moodboardAssets.forEach(h=>{const I=[h.label||h.url||"Reference"];h.source&&I.push(`Source: ${h.source}`),h.url&&I.push(`URL: ${h.url}`),s.push(`- ${I.join(" | ")}`)}),s.push("")),p.aesthetic&&s.push(`## Visual Aesthetic Direction 13${p.aesthetic} 14`),p.imageryStyle&&s.push(`## Imagery Style 15${p.imageryStyle} 16`),p.moodAndAtmosphere&&s.push(`## Mood & Atmosphere 17${p.moodAndAtmosphere} 18`),p.layoutApproach&&s.push(`## Layout Approach 19${p.layoutApproach} 20`);const te=a.logoPreferences||n.logoPreferences||{};(Fe=te.selectedTypes)!=null&&Fe.length&&s.push(`## Logo Type Preferences 21Client selected: ${te.selectedTypes.join(", ")}`),(Me=te.inspirations)!=null&&Me.length&&s.push(`Logo inspirations: ${te.inspirations.map(h=>h.name||h).join(", ")} 22`);const le=a.fontPreferences||n.fontPreferences||{};(Be=le.selectedStyles)!=null&&Be.length&&s.push(`## Typography Style Preferences 23Client gravitated toward: ${le.selectedStyles.join(", ")} 24`);const we=a.colorPreferences||n.colorPreferences||{};(He=we.selectedColors)!=null&&He.length&&s.push(`## Color Preferences from Discovery 25${we.selectedColors.map(h=>`${h.name||h.hex||h}: ${h.meaning||""}`).join(", ")} 26`);const Se=n.brandAdjectives||a.brandAdjectives||[];Se.length&&s.push(`## Brand Adjectives (Client-Selected) 27${Se.join(", ")} 28`);const Ne=((ze=t.rawDna)==null?void 0:ze.clientWebsite)||"";return Ne&&s.push(`## Client's Current Website 29${Ne} 30`),s},d=t.typography.display.name,g=t.typography.body.name,v=d!=="Sans-serif"&&d!=="Serif",S=g!=="Sans-serif"&&g!=="Serif";r["design-system"]=`# DESIGN SYSTEM & VISUAL FOUNDATION 31 32â ï¸ CRITICAL â READ BEFORE DESIGNING ANYTHING â ï¸ 33 34## Typography System â EXACT SPECIFICATIONS 35 36### DISPLAY / HEADLINE FONT: "${d}" 37${v?`- Google Fonts: https://fonts.google.com/specimen/${d.replace(/\s+/g,"+")} 38- Import: <link href="https://fonts.googleapis.com/css2?family=${d.replace(/\s+/g,"+")}:wght@400;500;600;700&display=swap" rel="stylesheet">`:"- This is a system/foundry font. Ensure it is properly loaded."} 39- CSS: font-family: '${d}', serif; 40- Usage: ${t.typography.display.usage} 41- THIS IS THE HEADER FONT. Use it for ALL H1, H2, and pull quotes. Do NOT substitute with a different font. 42 43### BODY / UI FONT: "${g}" 44${S?`- Google Fonts: https://fonts.google.com/specimen/${g.replace(/\s+/g,"+")} 45- Import: <link href="https://fonts.googleapis.com/css2?family=${g.replace(/\s+/g,"+")}:wght@300;400;500;600;700&display=swap" rel="stylesheet">`:"- This is a system/foundry font. Ensure it is properly loaded."} 46- CSS: font-family: '${g}', sans-serif; 47- Usage: ${t.typography.body.usage} 48 49### TYPOGRAPHIC HIERARCHY (Exact sizes) 50| Element | Font | Size (Desktop) | Size (Mobile) | Weight | Line-Height | Letter-Spacing | 51|---------|------|-----------------|---------------|--------|-------------|----------------| 52| H1 | ${d} | 56-72px | 36-44px | 600-700 | 1.1 | -0.02em | 53| H2 | ${d} | 36-48px | 28-32px | 600 | 1.2 | -0.01em | 54| H3 | ${d} | 24-32px | 20-24px | 500-600 | 1.3 | 0 | 55| Subtitle | ${g} | 20-24px | 18-20px | 400 | 1.4 | 0.01em | 56| Body | ${g} | 16-18px | 16px | 400 | 1.7 | 0 | 57| Small/Caption | ${g} | 13-14px | 13px | 400 | 1.5 | 0.02em | 58| Button | ${g}
58 | 15-16px | 15px | 500-600 | 1 | 0.05em | 59| Nav Link | ${g} | 15px | 15px | 500 | 1 | 0.03em | 60 61## Brand Concept 62Visual Concept: "${t.visualConcept}" 63Brand Essence: ${t.brandEssence} 64 65## Color Palette â EXACT HEX VALUES 66${l} 67 68COLOR APPLICATION RULES: 69⢠Primary color: hero backgrounds, CTA buttons, key accents 70⢠Secondary/Neutral: body text, section backgrounds, cards 71⢠Accent: hover states, highlights, small decorative elements 72⢠NEVER use pure black (#000000) â use the darkest brand color or a warm/cool near-black 73⢠Accent colors max 15% of any composition 74⢠All interactive elements (buttons, links, hover states) MUST use the primary accent 75⢠Backgrounds should alternate between white and the lightest brand neutral 76 77## Mood & Atmosphere Keywords 78${t.mood.join(", ")} 79These keywords should be FELT in every design decision â spacing, image selection, animation speed, and color balance. 80 81${t.logoDirection?`## Logo Direction 82${t.logoDirection}`:""} 83${t.logoUrls.length>0?` 84## Logo Assets (Use these exact files) 85${t.logoUrls.map(s=>`- ${s}`).join(` 86`)}`:""}`,r["layout-components"]=`# LAYOUT & COMPONENT GUIDELINES 87 88## HTML Structure Contract (Arcbound theme) 89This site MUST be built inside our Arcbound WordPress theme shell. The visual 90design is yours â but the markup must follow this pattern so each block can be 91lifted into a shortcode partial: 92 93\`\`\` 94#main 95 header.masthead > .inner-masthead (logo + .main-menu nav) 96 #main-content 97 section.section-padding.home-banner > .content-width 98 section.section-padding.home-about > .content-width 99 section.section-padding.home-services > .content-width 100 section.section-padding.home-{slug} > .content-width 101 footer.site-footer.section-padding > .content-width 102\`\`\` 103 104- One \`<section class="section-padding {slug}">\` per homepage block. 105- Every section wraps content in \`<div class="content-width">\`. 106- Use CSS variables \`--color-1/2/3\`, \`--xl/lg/md/sm\`, \`--heading-font\`, 107 \`--default-font\` (see Technical Implementation Specs for full contract). 108- Buttons use \`class="button"\`. Scroll reveals use \`fade-from-left|right|bottom\`. 109 110## Layout Philosophy 111"${t.layoutPhilosophy}" 112 113## CRITICAL VISUAL RULE 114Every section of the website MUST contain at least ONE visual element beyond text: 115- Hero: Full-bleed image, video background, or animated graphic 116- About/Story sections: Portrait photo, brand photography, or illustrated timeline 117- Services/Offerings: Icon grid, illustrated cards, or process diagram 118- Testimonials: Client photos, logo wall, or trust badges 119- Stats/Impact: Animated counters with infographic styling, charts, or data visualization 120- CTA sections: Background imagery or decorative brand patterns 121 122DO NOT create text-only sections. Every section needs visual weight. 123 124## Grid System 125- 12-column grid, gutters: 24-32px 126- Max content width: 1200px text-heavy, 1440px full layouts 127- Asymmetric layouts encouraged â offset images, staggered grids 128- Minimum 64px vertical section padding (96-128px preferred) 129 130## Navigation Bar 131- Fixed/sticky, height 80-96px 132- Logo left, nav right-aligned 133- Nav items: ${t.navbar.map(s=>s.label).join(", ")||"TBD from sitemap"} 134- Mobile: hamburger â full-screen overlay with brand-colored background 135- Font: ${g}, 15px, weight 500, letter-spacing 0.03em 136 137## Component Specifications 138 139### Hero Section 140- Full viewport height (100vh) or minimum 80vh 141- Large impactful imagery or video background 142- Headline: ${d}, 56-72px, positioned with dramatic negative space 143- CTA button: Solid fill primary color, 16px vertical / 40px horizontal padding, bold 144- Consider: parallax scroll, subtle animation on load, or gradient overlay 145 146### Section Dividers 147- Use alternating background colors (white â lightest brand neutral) 148- Thin accent-colored line, or brand pattern strip between sections 149- Decorative elements: geometric shapes, thin rules, or brand motifs 150 151### Cards/Modules 152- Clean with subtle border OR soft shadow (not both) 153- Border-radius: 4-8px 154- Internal padding: 32-48px 155- Each card should have an icon, illustration, or image â never just text 156 157### Buttons 158PRIMARY: Solid fill primary accent, 4px radius, hover: darken 10% 159SECONDARY: Outlined with primary color border, transparent bg 160GHOST: Text-only with underline on hover 161Font: ${g}, 15-16px, weight 600, letter-spacing 0.05em 162 163## Responsive Breakpoints 164640px (mobile) | 768px (tablet) | 1024px (desktop) | 1280px (large) 165- Headlines reduce 35-40% on mobile 166- Stack all multi-column layouts to single column 167- Touch targets minimum 44x44px`,r["imagery-graphics"]=`# IMAGERY, GRAPHICS & VISUAL CONTENT DIRECTION 168 169## CRITICAL RULE: No Section Without Visuals 170Every single section of the homepage MUST include at least one of: 171â¡ Photography (hero, team, process, behind-the-scenes) 172â¡ Custom illustration or icon set 173â¡ Diagram, flowchart, or infographic 174â¡ Data visualization (charts, animated counters) 175â¡ Decorative brand graphics (patterns, geometric shapes, gradients) 176â¡ Video or animated element 177 178## Photography Style 179${t.imageryDirection||"Professional, authentic, editorial quality. Documentary or photojournalistic style â never stock."} 180 181PHOTO SPECIFICATIONS: 182- Style: Candid, editorial, cinematic â NOT posed stock photography 183- Color treatment: Warm or cool-toned to match brand palette, slight desaturation for sophistication 184- Composition: Rule of thirds, strong leading lines, shallow depth of field 185- Subjects: Real people in authentic moments, workspaces, details, textures
186- â AVOID: Generic stock photos, posed corporate headshots, cheesy handshakes, busy cluttered backgrounds 187 188## Section-by-Section Visual Assignments 189${t.homepageSections.map((s,o)=>{const a=s.heading.toLowerCase();let p="";return a.includes("hero")?p="â VISUAL: Full-bleed cinematic hero image OR video background. Overlay with brand gradient (60-70% opacity). Bold headline with dramatic scale contrast.":a.includes("about")||a.includes("story")||a.includes("who")?p="â VISUAL: Side-by-side layout with editorial portrait or brand photography. Consider a timeline graphic or illustrated origin story.":a.includes("service")||a.includes("offer")||a.includes("what")||a.includes("how")?p="â VISUAL: Icon cards with custom illustrations (not generic). OR a process flow diagram showing steps. Each offering needs its own visual icon.":a.includes("testimonial")||a.includes("client")||a.includes("result")||a.includes("impact")?p="â VISUAL: Client photos, company logos, or trust badges. Animated stat counters. Consider a quote card with portrait + decorative quotation mark.":a.includes("cta")||a.includes("contact")||a.includes("start")||a.includes("next")?p="â VISUAL: Full-width background image with color overlay, or brand pattern/gradient. Large bold CTA button with ample padding.":a.includes("feature")||a.includes("benefit")||a.includes("why")?p="â VISUAL: Feature grid with icons/illustrations per item. OR a comparison infographic. Consider before/after or side-by-side visual.":a.includes("process")||a.includes("approach")||a.includes("method")?p="â VISUAL: Numbered step diagram, flowchart, or illustrated process timeline. Horizontal on desktop, vertical on mobile.":a.includes("faq")||a.includes("question")?p="â VISUAL: Accordion with brand-colored expand icons. Decorative illustration or geometric pattern in sidebar.":p="â VISUAL: Include relevant imagery, illustration, or infographic. Never leave this section as text-only.",`### Section ${o+1}: "${s.heading}" 190${p}`}).join(` 191 192`)} 193 194## Iconography System 195- Style: ${t.mood.includes("bold")||t.mood.includes("modern")?"Solid fill with rounded corners":"Outline style, 1.5-2px stroke weight"} 196- Color: Primary brand accent for active, muted neutral for inactive 197- Size: 24-32px for inline UI, 48-64px for feature highlights, 80px+ for section heroes 198- Consistency: All icons from the same set/style â do not mix outline and fill 199 200## Diagrams & Infographics 201- Clean, 2D flat design (no 3D, no skeuomorphism) 202- Use ONLY brand color palette 203- Typography: ${g} for all labels and data 204- Generous whitespace between data points 205- Animate on scroll into view where possible 206 207## Decorative Elements 208- Subtle geometric patterns using brand colors at 5-10% opacity 209- Thin accent lines as section dividers 210- Abstract shapes (circles, arcs) as background decorations 211- These should enhance, never compete with content`;const $=t.homepageSections.map((s,o)=>{const a=s.heading.toLowerCase();let p="ð¼ï¸ This section MUST include a visual element â image, icon, illustration, or diagram. See Imagery section for specifics.";return a.includes("hero")?p="ð¼ï¸ HERO IMAGE REQUIRED: Full-bleed cinematic image or video background behind this text. Use gradient overlay for text readability.":a.includes("service")||a.includes("offer")?p="ð¼ï¸ ICONS/ILLUSTRATIONS REQUIRED: Each service/offering needs its own visual icon or illustration card.":(a.includes("testimonial")||a.includes("result"))&&(p="ð¼ï¸ SOCIAL PROOF VISUALS: Include client photos, company logos, or stat counters alongside this text."),`--- 212 213## SECTION ${o+1}: ${s.heading} 214 215${p} 216 217${s.copy} 218 219${s.notes?`ADMIN NOTES: ${s.notes}`:""}`}).join(` 220 221`);r["homepage-copy"]=`# HOMEPAGE COPY â EXACT TEXT TO USE 222 223â ï¸ USE THIS COPY VERBATIM. Do not rewrite, summarize, or improvise. This is approved client copy. 224 225## Navigation Bar 226Logo: "${t.clientName}" â use the provided logo asset, not text 227Nav Items: ${t.navbar.map(s=>`"${s.label}"`).join(" | ")||"TBD"} 228CTA Button: Use the primary CTA from the hero section 229 230## IMPORTANT: Every Section Needs Visuals 231Do NOT render any section as text-only. Each section below should be paired with imagery, icons, diagrams, or decorative elements as specified in the Imagery & Graphics section. 232 233${$||"No homepage copy generated yet. Generate it from the Homepage Copy step first."} 234 235## Footer 236- Brand logo (not just text name) 237- Navigation links repeated in columns 238- Contact info, social media icons 239- Newsletter signup (if applicable) 240- Legal: © ${new Date().getFullYear()} ${t.clientName}. All rights reserved. 241- Footer should have subtle brand pattern or accent color background`;const _=n.narrativeIdentity||{},O=n.purpose||{},j=n.coreOfferings||{},P=n.targetDemographic||{},G=n.differentiators||n.competitivePosition||{},R=n.keyMessages||n.messagingPillars||{},U=n.brandPersonality||[],W=[_.positioning?`POSITIONING: ${_.positioning}`:"",_.brandEssence?`BRAND ESSENCE: ${_.brandEssence}`:"",_.tagline?`TAGLINE: "${_.tagline}"`:"",_.elevatorPitch?`ELEVATOR PITCH: ${_.elevatorPitch}`:"",_.originStory?`ORIGIN STORY: ${_.originStory}
241`:""].filter(Boolean).join(` 242 243`),A=[O.statement?`PURPOSE: ${O.statement}`:"",O.vision?`VISION: ${O.vision}`:"",O.mission?`MISSION: ${O.mission}`:""].filter(Boolean).join(` 244`),ye=typeof j=="object"&&!Array.isArray(j)?Object.entries(j).map(([s,o])=>typeof o=="string"?`- ${s}: ${o}`:typeof o=="object"&&o?`- ${o.name||s}: ${o.description||JSON.stringify(o)}`:"").filter(Boolean).join(` 245`):Array.isArray(j)?j.map(s=>`- ${s.name||s.title||s}: ${s.description||""}`).join(` 246`):String(j),q=typeof P=="object"?Object.entries(P).map(([s,o])=>{const a=s.replace(/([A-Z])/g," $1").replace(/^./,p=>p.toUpperCase());return typeof o=="string"?`${a}: ${o}`:Array.isArray(o)?`${a}: ${o.join(", ")}`:typeof o=="object"&&o?`${a}: ${JSON.stringify(o)}`:""}).filter(Boolean).join(` 247`):String(P),re=typeof G=="object"?Object.entries(G).map(([s,o])=>{const a=s.replace(/([A-Z])/g," $1").replace(/^./,p=>p.toUpperCase());return typeof o=="string"?`- ${a}: ${o}`:Array.isArray(o)?`- ${a}: ${o.join(", ")}`:""}).filter(Boolean).join(` 248`):String(G),M=typeof R=="object"?Array.isArray(R)?R.map((s,o)=>`${o+1}. ${typeof s=="string"?s:s.headline||s.message||JSON.stringify(s)}`).join(` 249`):Object.entries(R).map(([s,o])=>`- ${s.replace(/([A-Z])/g," $1").replace(/^./,p=>p.toUpperCase())}: ${typeof o=="string"?o:JSON.stringify(o)}`).join(` 250`):String(R);r["voice-tone"]=`# BRAND IDENTITY, VOICE & MESSAGING 251## READ THIS SECTION FIRST â It establishes who ${t.clientName} is, what they do, and how they communicate. 252 253## Who Is ${t.clientName}? 254${t.brandEssence||"See narrative identity below."} 255 256${W?`## Narrative Identity 257${W}`:""} 258 259${A?`## Purpose, Vision & Mission 260${A}`:""} 261 262${U.length>0?`## Brand Personality 263${Array.isArray(U)?U.join(", "):U}`:""} 264 265${ye?`## Core Offerings 266${ye}`:""} 267 268${q?`## Target Audience 269${q}`:""} 270 271${re?`## Differentiators & Competitive Position 272${re}`:""} 273 274${M?`## Key Messages & Messaging Pillars 275${M}`:""} 276 277## Voice Characteristics 278${t.voiceTone.characteristics.join(", ")||"Authoritative, Precise, Clear"} 279 280The brand voice should permeate every headline, subhead, body paragraph, button label, and micro-copy on the site. 281 282## DO Say (Use These Phrases/Patterns): 283${t.voiceTone.doSay.map(s=>`⢠"${s}"`).join(` 284`)||"⢠[From brand strategy messaging pillars]"} 285 286## DON'T Say (Avoid These): 287${t.voiceTone.dontSay.map(s=>`⢠${s}`).join(` 288`)||"⢠Generic marketing clichés"} 289 290## Writing Style Rules 291- Clear, direct sentences with varied rhythm 292- Active voice predominantly 293- 2-4 sentences per paragraph for web 294- Strategic questions to engage 295- Every CTA: action-oriented, specific, no urgency tactics`;const L=c();r["design-references"]=`# DESIGN INSPIRATIONS & VISUAL REFERENCES 296 297â ï¸ THIS SECTION IS CRITICAL. Study these references deeply before designing. 298These are not generic suggestions â they come directly from the client's brand discovery sessions, taste exercises, and strategic conversations. 299 300${L.length>0?L.join(` 301`):"No specific references captured yet."} 302 303${t.designReferences.length>0?`## Additional References 304${t.designReferences.map((s,o)=>`${o+1}. ${s}`).join(` 305`)}`:""} 306 307## How to Use These References 3081. **Visit every linked website** and study: layout structure, typography scale, whitespace usage, image treatment, color application, animation/motion, and overall feeling 3092. **Identify the common threads** across all references â what visual patterns keep repeating? That's the client's natural taste 3103. **Synthesize, don't copy** â extract the feeling, sophistication level, and design approach, then apply with this client's unique brand palette & typography 3114. **Match the energy level** â if references are calm/refined, don't add flashy animations; if they're bold/dynamic, don't make it too quiet 312 313## Design Principles (Derived from Client Taste) 3141. **${t.mood[0]||"Sophisticated"} over generic** â Every design choice must reinforce the brand personality 3152. **Visual richness** â Every section needs imagery, graphics, or visual elements. NO text-only sections 3163. **Typography as art** â Headlines using ${d} should be a key design element with dramatic scale 3174. **Intentional whitespace** â Breathing room signals quality and confidence 3185. **Brand-aligned imagery** â Every photo, icon, and graphic should feel like it belongs to this specific brand 319 320## Anti-References (AVOID AT ALL COSTS) 321â Generic template sites with stock photography 322â Coaching/consulting sites with aggressive countdown timers 323â Dense text walls with no visual hierarchy or imagery 324â Corporate templates that feel institutional or cold 325â Overly busy designs with competing visual elements 326â Sites that use system fonts or mismatched typography`;const be=((ve=i[0])==null?void 0:ve.hex)||"#111111",Re=((Pe=i[1])==null?void 0:Pe.hex)||((Oe=i[0])==null?void 0:Oe.hex)||"#333333",V=((E=i[2])==null?void 0:E.hex)||((ee=i[1])==null?void 0:ee.hex)||((B=i[0])==null?void 0:B.hex)||"#cccccc",Ee=i.map((s,o)=>` /* --color-${o+1}: ${s.hex} (${s.name} â ${s.role}) */`).join(` 327`);r["technical-spec"]=`# TECHNICAL IMPLEMENTATION SPECIFICATIONS 328 329â ï¸ CRITICAL: The output HTML MUST follow the **Arcbound WordPress theme** structure. 330The visual design is up to you â but the markup, class names, and CSS variable 331names below are NON-NEGOTIABLE so the result drops cleanly into our WordPress 332theme as shortcode partials. 333 334--- 335 336## 1. Page Skeleton (mirror header.php â main â footer) 337 338\`\`\`html 339<!doctype html> 340<html lang="en"> 341<head> 342 <meta charset="UTF-8" /> 343 <meta name="viewport" content="width=device-width, initial-scale=1" /> 344 <title>${t.clientName}</title>
345 <link rel="preconnect" href="https://fonts.googleapis.com"> 346 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> 347 <link href="https://fonts.googleapis.com/css2?family=${d.replace(/\s+/g,"+")}:wght@400;500;600;700&family=${g.replace(/\s+/g,"+")}:wght@300;400;500;600;700&display=swap" rel="stylesheet"> 348 <!-- inline <style> block goes here (see section 3) --> 349</head> 350<body> 351 <div id="main"> 352 <a class="skip-menu" href="#main-content">Skip to Main Content</a> 353 354 <header class="masthead"> 355 <div class="inner-masthead"> 356 <a class="logo-container" href="/"><img src="LOGO_URL" width="400" height="64" alt="${t.clientName} logo"></a> 357 <div class="menu-container"> 358 <label for="mobile-input">â°</label> 359 <input type="checkbox" id="mobile-input"> 360 <nav> 361 <ul class="main-menu"> 362 ${(t.navbar.length?t.navbar:[{label:"Home",href:"/"}]).map(s=>`<li><a href="${s.href}">${s.label}</a></li>`).join(` 363 `)} 364 </ul> 365 </nav> 366 </div> 367 </div> 368 </header> 369 370 <div id="main-content"> 371 372 <!-- Each homepage block = its own <section>. 373 One section per shortcode partial (home-banner, home-services, etc.) --> 374 375 <section class="section-padding home-banner"> 376 <div class="content-width"> 377 <!-- hero content --> 378 </div> 379 </section> 380 381 <!-- ...additional <section class="section-padding xxx"> blocks... --> 382 383 </div><!-- /#main-content --> 384 385 <footer class="site-footer section-padding"> 386 <div class="content-width"> 387 <!-- footer content --> 388 </div> 389 </footer> 390 </div><!-- /#main --> 391</body> 392</html> 393\`\`\` 394 395--- 396 397## 2. Section / Shortcode Naming Convention 398 399Every homepage block becomes one \`<section class="section-padding {slug}">\` 400where {slug} matches an Arcbound shortcode partial. Use these slugs (one per 401section) so the markup can be split into \`template-parts/sections/home/{slug}.php\`: 402 403- \`home-banner\` â hero 404- \`home-about\` â about / story 405- \`home-services\` â offerings / services 406- \`home-mission\` â purpose / mission 407- \`home-results\` â stats / impact 408- \`home-team\` â team 409- \`home-testimonials\`â testimonials / social proof 410- \`home-awards\` â press / awards 411- \`home-news\` â blog / news 412- \`home-social\` â social feed 413- \`home-cta\` â call-to-action 414- \`home-contact\` â contact form 415 416Inside every section: \`<div class="content-width">â¦</div>\` is required. 417 418--- 419 420## 3. CSS Variables (Arcbound contract â use these EXACT names) 421 422\`\`\`css 423:root{ 424 /* site colors â positional, not name-based */ 425 --color-1: ${be}; 426 --color-2: ${Re}; 427 --color-3: ${V}; 428${Ee} 429 430 /* font sizes */ 431 --xl: 55px; 432 --lg: 40px; 433 --md: 30px; 434 --sm: 20px; 435 --default: 16px; 436 437 /* font families */ 438 --heading-font: "${d}", serif; 439 --default-font: "${g}", sans-serif; 440 --accent-font: "${g}", sans-serif; 441} 442@media(max-width: 1000px){ 443 :root{ --xl: 40px; --lg: 30px; --md: 20px; --sm: 18px; } 444} 445@media(max-width: 750px){ 446 :root{ --xl: 35px; --lg: 25px; --md: 20px; --sm: 18px; } 447} 448 449/* Theme defaults â DO NOT rename these classes */ 450html, body{ scroll-behavior: smooth; font-size: var(--default); } 451body{ margin:0; -webkit-font-smoothing: antialiased; } 452*{ box-sizing: border-box; } 453img, svg{ max-width: 100%; height: auto; } 454a{ text-decoration: none; color: var(--color-2); } 455 456h1, h2, h3, h4, h5, h6{ font-family: var(--heading-font); line-height: 1.25em; } 457body, p, ul, ol, li{ font-family: var(--default-font); line-height: 1.25em; } 458h1{ font-size: var(--xl); } 459h2{ font-size: var(--lg); } 460h3{ font-size: var(--md); } 461h4{ font-size: var(--sm); } 462 463#main{ overflow-x: hidden; } 464.section-padding{ padding: min(150px, max(5%, 50px)) 0; } 465.content-width{ width: 1230px; max-width: 100%; padding: 0 15px; margin: 0 auto; } 466.has-text-align-right{ text-align: right; } 467.has-text-align-center, .aligncenter{ text-align: center; } 468 469.absolute-cover{ position: absolute; left: 0; top: 0; width: 100%; height: 100%; object-fit: cover; object-position: center; } 470 471/* Buttons */ 472.button, 473.button-container a{ 474 background: var(--color-1); color: white; font-size: 16px; 475 padding: 10px 40px; font-weight: bold; border-radius: 5px; 476 transition: background .25s; display: inline-block; 477} 478.button:hover, 479.button-container a:hover{ background: var(--color-2); } 480 481/* Masthead â keep these class names */
482.inner-masthead{ display: flex; justify-content: space-between; align-items: center; position: relative; padding: 0 25px; } 483.inner-masthead .logo-container{ width: 300px; } 484.inner-masthead .main-menu{ display: flex; align-items: center; padding: 0; margin: 0; list-style: none; } 485.inner-masthead .main-menu > li > a{ padding: 30px 15px; display: inline-block; } 486.menu-container label, .menu-container #mobile-input{ display: none; } 487@media(max-width: 1000px){ 488 .menu-container label{ display: block; font-size: 25px; cursor: pointer; } 489 .menu-container nav{ position: absolute; left: 0; top: 100%; width: 100%; background: #222; height: 0; overflow: hidden; } 490 .menu-container input:checked + nav{ height: auto; padding: 15px 0; } 491 .inner-masthead .main-menu{ flex-direction: column; align-items: flex-start; } 492 .inner-masthead .main-menu > li a{ color: #ddd; padding: 15px; } 493} 494 495/* Animations (theme contract) */ 496.fade-from-left{ opacity: 0; transform: translateX(-25px); transition: opacity 1s, transform 1s; } 497.fade-from-left.active{ opacity: 1; transform: translateX(0); } 498.fade-from-right{ opacity: 0; transform: translateX(25px); transition: opacity 1s, transform 1s; } 499.fade-from-right.active{ opacity: 1; transform: translateX(0); } 500.fade-from-bottom{ opacity: 0; transform: translateY(25px); transition: opacity 1s, transform 1s; } 501.fade-from-bottom.active{ opacity: 1; transform: translateY(0); } 502@media(max-width: 750px){ 503 .fade-from-left, .fade-from-right, .fade-from-bottom{ opacity: 1; transform: none; } 504} 505\`\`\` 506 507Add any extra section-specific CSS *scoped* to that section's slug 508(e.g. \`.home-services .card{â¦}\`). Never rename \`--color-1/2/3\`, 509\`--xl/lg/md/sm\`, \`--heading-font\`, \`--default-font\`, 510\`.section-padding\`, \`.content-width\`, \`.button\`, \`.masthead\`, 511or \`.absolute-cover\` â those are the theme contract. 512 513--- 514 515## 4. Animations 516- Add \`fade-from-left | fade-from-right | fade-from-bottom\` to any element 517 that should reveal on scroll. A small IntersectionObserver script adds 518 \`.active\` when the element enters the viewport. 519- Stat counters: animate 0 â final value over 1.5s. 520 521\`\`\`html 522<script> 523 const io = new IntersectionObserver((entries) => { 524 entries.forEach(e => { if (e.isIntersecting) e.target.classList.add('active'); }); 525 }, { threshold: 0.15 }); 526 document.querySelectorAll('.fade-from-left,.fade-from-right,.fade-from-bottom') 527 .forEach(el => io.observe(el)); 528<\/script> 529\`\`\` 530 531--- 532 533## 5. Responsive Breakpoints (theme-aligned) 534\`750px\` · \`1000px\` · \`1230px\` (max content width). 535 536## 6. Accessibility 537- Single \`<h1>\` per page (inside \`.home-banner\`). 538- Keep the \`<a class="skip-menu">\` link. 539- All images get meaningful \`alt\`. Decorative imagery â \`alt=""\`. 540- Color contrast ⥠4.5:1. 541 542## 7. SEO 543- \`<title>\` ⤠60 chars with primary keyword. 544- \`<meta name="description">\` ⤠160 chars. 545- Lazy-load below-fold images (see section 10). 546- JSON-LD Organization block in \`<head>\`. 547 548--- 549 550## 8. Interior Page Shortcodes 551 552Every NON-homepage page is composed from these interior shortcode partials. 553Use the exact \`<section class="â¦">\` wrappers below so each block maps 1:1 to 554\`template-parts/sections/internal/{slug}.php\`. 555 556### \`[internal_banner]\` â page header strip 557\`\`\`html 558<section class="internal-banner"> 559 <div class="content-width"><h1>{Page Title}</h1></div> 560</section> 561\`\`\` 562Used on archive, search, 404 and the top of every interior page. 563 564### \`[internal_content]\` â long-form / rich text body 565\`\`\`html 566<section class="internal-content section-padding"> 567 <div class="content-width"> 568 <!-- prose: h2/h3, paragraphs, lists, blockquotes, inline images --> 569 </div> 570</section> 571\`\`\` 572 573### \`[internal_services]\` â feature / offerings grid 574\`\`\`html 575<section class="internal-services section-padding"> 576 <div class="content-width"> 577 <h2>{Section Heading}</h2> 578 <div class="service-grid"> 579 <article class="service-card"><h3>â¦</h3><p>â¦</p></article> 580 </div> 581 </div> 582</section> 583\`\`\` 584 585### \`[internal_fullwidth]\` â edge-to-edge image / video / quote band 586\`\`\`html 587<section class="internal-fullwidth"> 588 <!-- NO .content-width â this block bleeds to viewport edges --> 589 <img class="absolute-cover" src="â¦" alt="â¦"> 590 <div class="overlay"><h2>â¦</h2></div> 591</section> 592\`\`\` 593 594### \`[internal_cta]\` â closing call-to-action band 595\`\`\`html 596<section class="internal-cta section-padding"> 597 <div class="content-width has-text-align-center"> 598 <h2>{CTA Headline}</h2> 599 <p>{Supporting line}</p> 600 <div class="button-container"><a href="â¦">{Button Label}</a></div> 601 </div> 602</section> 603\`\`\` 604 605Typical interior stack: \`internal_banner\` â \`internal_content\` â 606(optional \`internal_services\` or \`internal_fullwidth\`) â \`internal_cta\`. 607 608--- 609 610## 9. Scoped Section Styles 611 612Every section's extra CSS must be **scoped to its own class** so partials 613stay portable. In WordPress this is wrapped in an \`apply_{slug}_styles\` 614function hooked to \`wp_footer\`; in the generated HTML, emit a matching 615\`<style>\` block immediately AFTER the section â never let one section's CSS
616leak into another. 617 618\`\`\`html 619<section class="home-services">â¦</section> 620<style> 621 .home-services{ background: var(--color-3); } 622 .home-services .card{ padding: 32px; } 623 @media(max-width: 750px){ .home-services .card{ padding: 20px; } } 624</style> 625\`\`\` 626 627--- 628 629## 10. Lazy-loading Convention (theme-changes.php contract) 630 631For below-fold media, use the theme's data-attribute lazy loader â NOT 632\`loading="lazy"\`: 633 634- \`<img data-url="/path/image.jpg" alt="â¦">\` â swaps to \`src\` on intersect 635- \`<iframe data-url="https://â¦">\` â same, for embeds 636- \`<div data-bg-img="/path/image.jpg" class="hero"></div>\` â sets \`background-image\` 637- Add \`class="lazyload"\` to any extra element you want the observer to watch. 638 639Include this script once at the bottom of \`<body>\` (mirrors theme-changes.php): 640 641\`\`\`html 642<script> 643 window.addEventListener("load", () => { 644 const items = document.querySelectorAll('img[data-url], iframe[data-url], .lazyload[data-url], [data-bg-img]'); 645 const io = new IntersectionObserver((entries, obs) => { 646 entries.forEach(e => { 647 if (!e.isIntersecting) return; 648 const el = e.target; 649 if (el.hasAttribute('data-url')) { el.setAttribute('src', el.getAttribute('data-url')); el.removeAttribute('data-url'); } 650 else if (el.hasAttribute('data-bg-img')) { el.style.backgroundImage = "url('" + el.getAttribute('data-bg-img') + "')"; el.removeAttribute('data-bg-img'); } 651 obs.unobserve(el); 652 }); 653 }, { rootMargin: '150px 0px', threshold: 0.01 }); 654 items.forEach(i => io.observe(i)); 655 }); 656<\/script> 657\`\`\` 658 659--- 660 661## 11. Blog / Archive / Search / Single / 404 Templates 662 663Class names below are hard-coded in \`blog-styles.php\` and must not be renamed. 664 665### Blog index, Category archive, Search results 666\`\`\`html 667<section class="internal-banner"><div class="content-width"><h1>Blog</h1></div></section> 668 669<section class="section-padding"> 670 <div class="content-width"> 671 <div class="posts-container has-blogs"> 672 <div class="indiv-post"> 673 <a href="/post-slug" class="img-container"> 674 <img src="/featured.jpg" alt=""> 675 <!-- if no thumb: <span class="empty-thumb-container"></span> --> 676 </a> 677 <div class="post-info"> 678 <p class="date"> 679 <span class="day">07</span> 680 <span class="y-m-container"> 681 <span class="year">2026</span> 682 <span class="month">June</span> 683 </span> 684 </p> 685 <h2 class="title">{Post Title}</h2> 686 <p>{Excerpt}</p> 687 <a class="button" href="/post-slug">Read More</a> 688 </div> 689 </div> 690 <!-- repeat .indiv-post --> 691 </div> 692 693 <div class="nav-links"> 694 <a class="prev page-numbers" href="#"><span><</span></a> 695 <span class="page-numbers current">1</span> 696 <a class="page-numbers" href="#">2</a> 697 <a class="next page-numbers" href="#"><span>></span></a> 698 </div> 699 </div> 700</section> 701\`\`\` 702Grid: 3 cols desktop â 2 cols @ 900px â 1 col @ 700px. 703Empty state uses \`<div class="posts-container no-blogs">\`. 704Search page banner: \`[internal_banner title="You searched for: {term}"]\` and 705prepend \`<h2>The following is a list of results for your search term:</h2>\` 706inside the section before \`.posts-container\`. 707 708### Single post 709\`\`\`html 710<section class="section-padding single-post"> 711 <div class="content-width"> 712 <h1>{Post Title}</h1> 713 <div class="author-date"><strong>{Author}</strong> | {Date}</div> 714 <div class="img-container"><img src="/featured.jpg" alt=""></div> 715 <div class="blog-content"> 716 <!-- the_content() output --> 717 </div> 718 </div> 719</section> 720\`\`\` 721Scoped CSS (single-blog-styles.php): 722\`.single-post .blog-content{ width:750px; max-width:100%; margin:0 auto; }\` 723\`.single-post h1{ text-align:center; margin:0; }\` 724\`.single-post .img-container{ width:1000px; max-width:100%; margin:1em auto; text-align:center; }\` 725\`.single-post .author-date{ text-align:center; }\` 726 727### 404 728\`\`\`html 729<section class="internal-banner"><div class="content-width"><h1>
729That's a 404</h1></div></section> 730<section class="section-padding"> 731 <div class="content-width" style="text-align: center;"> 732 The URL you entered doesn't exist on our site. Perhaps try navigating from 733 <a href="/">our homepage</a>? 734 </div> 735</section> 736\`\`\` 737 738--- 739 740## 12. Footer Markup (footer.php contract) 741 742\`\`\`html 743<footer class="site-footer section-padding"> 744 <div class="content-width"> 745 <!-- columns: logo, nav, contact/social, newsletter --> 746 </div> 747</footer> 748<!-- footer.php then closes #main-content and #main --> 749\`\`\` 750 751--- 752 753## 13. Theme Class Whitelist (DO NOT rename) 754 755\`#main\` · \`#main-content\` · \`.masthead\` · \`.inner-masthead\` · 756\`.logo-container\` · \`.menu-container\` · \`.main-menu\` · \`.sub-menu\` · 757\`.skip-menu\` · \`.section-padding\` · \`.content-width\` · \`.absolute-cover\` · 758\`.button\` · \`.button-container\` · \`.has-text-align-center\` · 759\`.has-text-align-right\` · \`.aligncenter\` · 760\`.fade-from-left\` · \`.fade-from-right\` · \`.fade-from-bottom\` · 761\`.internal-banner\` · \`.internal-content\` · \`.internal-services\` · 762\`.internal-fullwidth\` · \`.internal-cta\` · 763\`.posts-container\` · \`.has-blogs\` · \`.no-blogs\` · \`.indiv-post\` · 764\`.img-container\` · \`.empty-thumb-container\` · \`.post-info\` · \`.date\` · 765\`.day\` · \`.month\` · \`.year\` · \`.y-m-container\` · \`.title\` · 766\`.nav-links\` · \`.page-numbers\` · \`.current\` · \`.prev\` · \`.next\` · 767\`.single-post\` · \`.blog-content\` · \`.author-date\` · \`.site-footer\`. 768 769Any new visual treatment must be ADDITIVE â new modifier classes scoped 770under the section slug, never edits to the names above. 771 772--- 773 774## 14. Section Scaffold Templates (drop-in PHP partials) 775 776Every \`<section>\` in this brief maps 1:1 to a WordPress shortcode partial in 777\`template-parts/sections/home/{slug}.php\` (or \`internal/{slug}.php\`). The 778generated HTML must mirror the EXACT scaffold below so we can lift each 779\`<section>â¦</section>\` block straight into its partial. The \`shortcode_atts\` 780array enumerates the dynamic props the section accepts; the 781\`apply_{slug}_styles\` wp_footer hook is where that section's CSS lives. 782 783> Rule: emit one \`<section class="{slug}">\` PER scaffold below. Put that 784> section's CSS in a single \`<style>\` block that follows the section (it will 785> become the body of \`apply_{slug}_styles\` in WordPress). Do NOT merge two 786> sections into one partial. 787 788### \`internal-banner.php\` â top of every interior page 789\`\`\`php 790<?php $atts = shortcode_atts(array( 791 'title' => '', 792), $atts); ?> 793 794<style type="text/css"></style> 795 796<section class="internal-banner section-padding"> 797 <h1><?= $atts['title']; ?></h1> 798</section> 799\`\`\` 800 801### \`home-services.php\` 802\`\`\`php 803<?php $atts = shortcode_atts(array( 804 '' => '', 805), $atts); ?> 806 807<section class="home-services"> 808</section> 809 810<?php if(!function_exists('apply_home_services_styles')){ 811 function apply_home_services_styles(){ ?> 812 <style>/* .home-services { ⦠} */</style> 813 <?php } 814 add_action('wp_footer', 'apply_home_services_styles'); 815} ?> 816\`\`\` 817 818### \`home-mission.php\` 819\`\`\`php 820<section class="home-mission"></section> 821<?php if(!function_exists('apply_home_mission_styles')){ 822 function apply_home_mission_styles(){ ?><style>/* .home-mission { ⦠} */</style><?php } 823 add_action('wp_footer', 'apply_home_mission_styles'); 824} ?> 825\`\`\` 826 827### \`home-results.php\` 828\`\`\`php 829<section class="home-results"></section> 830<?php if(!function_exists('apply_home_results_styles')){ 831 function apply_home_results_styles(){ ?><style>/* .home-results { ⦠} */</style><?php } 832 add_action('wp_footer', 'apply_home_results_styles'); 833} ?> 834\`\`\` 835 836### \`home-team.php\` 837\`\`\`php 838<section class="home-team"></section> 839<?php if(!function_exists('apply_home_team_styles')){ 840 function apply_home_team_styles(){ ?><style>/* .home-team { ⦠} */</style><?php } 841 add_action('wp_footer', 'apply_home_team_styles'); 842} ?> 843\`\`\` 844 845### \`home-testimonials.php\` 846\`\`\`php 847<section class="home-testimonials"></section> 848<?php if(!function_exists('apply_home_testimonials_styles')){ 849 function apply_home_testimonials_styles(){ ?><style>/* .home-testimonials { ⦠} */</style><?php } 850 add_action('wp_footer', 'apply_home_testimonials_styles'); 851} ?> 852\`\`\` 853 854### \`home-portfolio.php\` 855\`\`\`php 856<section class="home-portfolio"></section> 857<?php if(!function_exists('apply_home_portfolio_styles')){ 858 function apply_home_portfolio_styles(){ ?><style>/* .home-portfolio { ⦠} */</style><?php } 859 add_action('wp_footer', 'apply_home_portfolio_styles'); 860} ?> 861\`\`\` 862 863### \`home-news.php\` 864\`\`\`php 865<section class="home-news"></section> 866<?php if(!function_exists('apply_home_news_styles')){ 867 function apply_home_news_styles(){ ?><style>/* .home-news { ⦠} */</style><?php } 868 add_action('wp_footer', 'apply_home_news_styles'); 869} ?> 870\`\`\` 871 872### \`home-social.php\` 873\`\`\`php 874<section class="home-social"></section> 875<?php if(!function_exists('apply_home_social_styles')){ 876 function apply_home_social_styles(){ ?><style>/* .home-social { ⦠} */</style><?php } 877 add_action('wp_footer', 'apply_home_social_styles'); 878} ?> 879\`\`\` 880 881### \`home-cta.php\` 882\`\`\`php 883<section class="home-cta"></section> 884<?php if(!function_exists('apply_home_cta_styles')){ 885 function apply_home_cta_styles(){ ?><style>/* .home-cta { ⦠} */</style><?php } 886 add_action('wp_footer', 'apply_home_cta_styles'); 887} ?> 888\`\`\` 889 890### \`home-banner.php\` â homepage hero (note: uses inline \`<style>\`, NOT wp_footer) 891\`\`\`php 892<?php $atts = shortcode_atts(array( 893 '' => '',
894), $atts); ?> 895 896<style> 897/* .home-banner { ⦠} â banner styles live INLINE because the hero is the 898 first thing painted; it must not wait for wp_footer to inject CSS. */ 899</style> 900 901<section class="home-banner section-padding"> 902 <div class="content-width"> 903 <!-- single <h1> for the entire page lives here --> 904 </div> 905</section> 906\`\`\` 907 908### \`home-about.php\` 909\`\`\`php 910<?php $atts = shortcode_atts(array( 911 '' => '', 912), $atts); ?> 913 914<section class="home-about"></section> 915 916<?php if(!function_exists('apply_home_about_styles')){ 917 function apply_home_about_styles(){ ?><style>/* .home-about { ⦠} */</style><?php } 918 add_action('wp_footer', 'apply_home_about_styles'); 919} ?> 920\`\`\` 921 922### \`home-awards.php\` 923\`\`\`php 924<?php $atts = shortcode_atts(array( 925 '' => '', 926), $atts); ?> 927 928<section class="home-awards"></section> 929 930<?php if(!function_exists('apply_home_awards_styles')){ 931 function apply_home_awards_styles(){ ?><style>/* .home-awards { ⦠} */</style><?php } 932 add_action('wp_footer', 'apply_home_awards_styles'); 933} ?> 934\`\`\` 935 936### \`home-contact.php\` 937\`\`\`php 938<?php $atts = shortcode_atts(array( 939 '' => '', 940), $atts); ?> 941 942<section class="home-contact"></section> 943 944<?php if(!function_exists('apply_home_contact_styles')){ 945 function apply_home_contact_styles(){ ?><style>/* .home-contact { ⦠} */</style><?php } 946 add_action('wp_footer', 'apply_home_contact_styles'); 947} ?> 948\`\`\` 949 950> All other home-* sections (any new one you introduce) follow the SAME pattern: 951> \`shortcode_atts\` â \`<section class="{slug}">\` â \`apply_{slug}_styles\` 952> hooked to \`wp_footer\`. Only \`home-banner\` uses an inline \`<style>\` block 953> because the hero must render without waiting for the footer. 954 955--- 956 957## 16. Shortcode Registry â \`inc/shortcodes.php\` 958 959Every section partial in §14 MUST be registered as a WordPress shortcode in 960\`inc/shortcodes.php\` so it can be dropped into the page editor as 961\`[home_banner]\`, \`[home_services]\`, etc. Use this exact pattern â one 962function per partial, name matches the slug with underscores: 963 964\`\`\`php 965<?php 966/****** HOME SHORTCODES *******/ 967function home_banner($atts, $content=null){ 968 ob_start(); 969 include(locate_template('template-parts/sections/home/home-banner.php')); 970 return ob_get_clean(); 971} 972add_shortcode('home_banner', 'home_banner'); 973 974function home_services($atts, $content=null){ 975 ob_start(); 976 include(locate_template('template-parts/sections/home/home-services.php')); 977 return ob_get_clean(); 978} 979add_shortcode('home_services', 'home_services'); 980 981// ...repeat for: home_about, home_team, home_cta, home_results, 982// home_testimonials, home_social, home_news, home_contact, home_mission, 983// home_awards, home_portfolio 984 985/****** INTERNAL SHORTCODES *******/ 986function internal_banner($atts, $content=null){ 987 ob_start(); 988 include(locate_template('template-parts/sections/internal/internal-banner.php')); 989 return ob_get_clean(); 990} 991add_shortcode('internal_banner', 'internal_banner'); 992 993// ...repeat for: internal_content, internal_services, internal_fullwidth, 994// internal_cta 995\`\`\` 996 997> Rule: if you create a new \`{slug}.php\` partial, you MUST add a matching 998> shortcode function + \`add_shortcode()\` call in this file. Missing 999> registrations = broken page editor. 1000 1001--- 1002 1003## 17. WordPress Template Files (theme root) 1004 1005These templates live at the THEME ROOT (not in \`template-parts/\`) and are 1006required for WordPress to render non-homepage routes. Generate them exactly 1007as shown â only the styling layer (\`single-blog-styles.php\`, 1008\`blog-styles.php\`) is brand-customizable. 1009 1010### \`page.php\` â generic page wrapper (uses Gutenberg / shortcode content) 1011\`\`\`php 1012<?php 1013/** 1014 * The template for displaying all standard pages 1015 */ 1016 1017get_header(); 1018 1019/* Start the Loop */ 1020while ( have_posts() ) : 1021 the_post(); 1022 the_content(); 1023endwhile; 1024 1025get_footer(); 1026\`\`\` 1027 1028### \`single.php\` â single blog post layout 1029\`\`\`php 1030<?php 1031/** 1032 * The template for displaying all single posts 1033 */ 1034 1035function add_single_blog_styles(){ 1036 include(locate_template('single-blog-styles.php')); 1037} 1038add_action('wp_head', 'add_single_blog_styles'); 1039 1040get_header(); 1041?> 1042 1043<?php while ( have_posts() ) : the_post(); ?> 1044 <section class="section-padding single-post"> 1045 <div class="content-width"> 1046 <h1><?= get_the_title(); ?></h1> 1047 <div class="author-date"> 1048 <strong><?= get_the_author(); ?></strong> | <?= get_the_date(); ?> 1049 </div> 1050 1051 <?php if(has_post_thumbnail()){ ?> 1052 <div class="img-container"> 1053 <img src="<?= get_the_post_thumbnail_url(); ?>"> 1054 </div> 1055 <?php } ?> 1056 1057 <div class="blog-content"> 1058 <?php the_content(); ?> 1059 </div> 1060 </div> 1061 </section> 1062<?php endwhile; ?> 1063 1064<?php get_footer(); ?> 1065\`\`\` 1066 1067### \`single-blog-styles.php\` â scoped styles for \`single.php\` 1068\`\`\`php 1069<style type="text/css"> 1070 .single-post .blog-content { width: 750px; max-width: 100%; margin: 0 auto; } 1071 .single-post h1 { text-align: center; margin: 0; } 1072 .single-post .img-container { width: 1000px; max-width: 100%; margin: 1em auto; text-align: center; } 1073 .single-post .img-container img { display: block; margin: 0 auto; } 1074 .single-post .author-date { text-align: center; } 1075</style> 1076\`\`\` 1077 1078### \`search.php\` â search results page (reuses \`[internal_banner]\` + \`blog-styles.php\`) 1079\`\`\`php 1080<?php 1081/** 1082 * The template for displaying search results pages 1083 */ 1084 1085function add_blog_styles(){ 1086 include(locate_template('blog-styles.php')); 1087} 1088add_action('wp_head', 'add_blog_styles'); 1089 1090get_header(); 1091$term = get_search_query(); 1092$banner = '[internal_banner title="You searched for: '. $term . '"]'; 1093?> 1094 1095<?= apply_shortcodes($banner); ?> 1096 1097<section class="section-padding"> 1098 <div class="content-width"> 1099 <h2>The following is a list of results for your search term:</h2> 1100 1101 <?php if ( have_posts() ) { ?> 1102 <div class="posts-container has-blogs"> 1103 <?php while ( have_posts() ) { the_post(); ?> 1104 <div class="indiv-post"> 1105 <a href="<?= get_the_permalink(); ?>" class="img-container"> 1106 <?php if(has_post_thumbnail()){ ?> 1107 <img src="<?= get_the_post_thumbnail_url(); ?>"> 1108 <?php } else { ?>
1109 <span class="empty-thumb-container"></span> 1110 <?php } ?> 1111 </a> 1112 <div class="post-info"> 1113 <p class="date"> 1114 <span class="day"><?= get_the_date('d'); ?></span> 1115 <span class="y-m-container"> 1116 <span class="year"><?= get_the_date('Y'); ?></span> 1117 <span class="month"><?= get_the_date('F'); ?></span> 1118 </span> 1119 </p> 1120 <h2 class="title"><?= get_the_title(); ?></h2> 1121 <p><?= get_the_excerpt(); ?></p> 1122 <a class="button" href="<?= get_the_permalink(); ?>">Read More</a> 1123 </div> 1124 </div> 1125 <?php } ?> 1126 </div> 1127 1128 <div class="nav-links"> 1129 <?php echo paginate_links(array( 1130 'prev_text' => '<span><</span>', 1131 'next_text' => '<span>></span>', 1132 )); ?> 1133 </div> 1134 <?php } else { ?> 1135 <div class="posts-container no-blogs"> 1136 There are no posts with that category name. 1137 <a style="width:100%;" href="/">Return to our homepage.</a> 1138 </div> 1139 <?php } ?> 1140 </div> 1141</section> 1142 1143<?php get_footer(); ?> 1144\`\`\` 1145 1146> Rule: \`search.php\` and any archive/index template ALWAYS load styles via 1147> a brand-specific \`blog-styles.php\` partial hooked into \`wp_head\` â never 1148> inline. Classes used (\`posts-container\`, \`indiv-post\`, \`img-container\`, 1149> \`post-info\`, \`date\`, \`day\`, \`y-m-container\`, \`year\`, \`month\`, 1150> \`title\`, \`nav-links\`, \`no-blogs\`, \`has-blogs\`, \`empty-thumb-container\`) 1151> are part of the theme class whitelist in §13 and MUST NOT be renamed. 1152 1153--- 1154 1155## 18. Theme Header â \`style.css\` 1156 1157WordPress requires the theme's \`style.css\` to start with a metadata 1158docblock. Visual styles do NOT live here â they live in 1159\`theme-style.css\` (loaded via \`functions.php\` \`wp_enqueue_style\`). 1160 1161\`\`\`css 1162/* 1163Theme Name: {Client} Custom 1164Theme URI: https://{client-domain}/ 1165Author: Arcbound Team 1166Description: Custom theme generated from the Arcbound brand kit. 1167Requires PHP: 5.6+ 1168Version: 1.0 1169*/ 1170 1171/* STYLES FOR THEME CAN BE FOUND IN THEME-STYLE.CSS */ 1172\`\`\` 1173 1174> Do not put real CSS in \`style.css\` â only the WordPress theme header. All 1175> compiled styles ship from \`theme-style.css\` so cache-busting and 1176> conditional loading can be controlled from \`functions.php\`. 1177 1178--- 1179 1180## 15. Section-by-Section Build Workflow (MANDATORY) 1181 1182â ï¸ DO NOT generate the entire homepage in one pass. The builder MUST work 1183section-by-section, using full reasoning capacity on each section before 1184moving on. This brief is the blueprint; each section is its own contained 1185deliverable. 1186 1187For EACH section listed in §2 (\`home-banner\` â \`home-contact\`), execute 1188this 7-step loop in order before starting the next section: 1189 1190**Step 1 â Read brief context** 1191Re-read: Brand DNA (voice/tone, messaging pillars, audience), Design 1192References, this section's copy from "Homepage Copy", and any uploaded 1193visual references for this section. 1194 1195**Step 2 â Decide the section's job** 1196State in one sentence: what this section must communicate, what scroll 1197moment it owns, and what the user should feel/do leaving it. 1198 1199**Step 3 â Choose the layout pattern** 1200Pick a specific layout (split hero, asymmetric grid, full-bleed image with 1201overlay, marquee, etc.) justified by the design references â not generic 1202"3-column card grid" defaults. Sketch the grid in a comment. 1203 1204**Step 4 â Write the markup** 1205Emit the section using its §14 scaffold: 1206\`<section class="{slug}">â¦</section>\`. Include real copy from the 1207Homepage Copy spec, real image URLs (or labeled placeholders matching the 1208brief's image direction), \`data-url\`/\`data-bg-img\` for below-fold media, 1209and \`fade-from-*\` classes on reveal elements. Single \`<h1>\` only in 1210\`home-banner\`; \`<h2>\` for every other section's primary heading. 1211 1212**Step 5 â Write the scoped CSS** 1213Immediately after the section, emit one \`<style>\` block where EVERY 1214selector starts with \`.{slug}\` (this becomes \`apply_{slug}_styles\` in 1215PHP). Use \`var(--color-1/2/3)\`, \`var(--xl/lg/md/sm)\`, \`var(--heading-font)\`, 1216\`var(--default-font)\`. Include the 1000px and 750px breakpoint overrides. 1217 1218**Step 6 â Self-QA the section** 1219Confirm: (a) markup uses only whitelisted theme classes + new modifiers 1220scoped under \`.{slug}\`; (b) all CSS is scoped to \`.{slug}\`; (c) copy 1221matches the Homepage Copy spec verbatim â no paraphrasing; (d) imagery 1222direction matches design references; (e) no \`loading="lazy"\` (use 1223\`data-url\`); (f) contrast ⥠4.5:1 against background; (g) reveals use 1224\`fade-from-*\` not custom animation names. 1225 1226**Step 7 â Commit the section, then move on** 1227Output the finished \`<section>\` + scoped \`<style>\` as a self-contained 1228block. Do not touch a previously-completed section while building a new 1229one â its styles are already isolated by §9. 1230 1231After ALL home-* sections are complete, assemble the page skeleton from §1, 1232drop the sections into \`#main-content\` in the order listed in §2, append 1233the footer (§12) and the lazy-load + IntersectionObserver scripts (§4, §10). 1234Run a final pass to confirm zero cross-section CSS leakage and that every 1235section maps cleanly to a \`template-parts/sections/home/{slug}.php\` partial 1236using the §14 scaffolds. 1237 1238For interior pages, repeat the same 7-step loop using the 1239\`internal-banner\` / \`internal-content\` / \`internal-services\` / 1240\`internal-fullwidth\` / \`internal-cta\` scaffolds from §8 and §14. 1241 1242--- 1243 1244## 19. \`functions.php\` Contract (theme bootstrap) 1245 1246Every generated WordPress theme MUST ship a \`functions.php\` that mirrors 1247the Arcbound boilerplate exactly. This is what wires \`theme-styles.php\` 1248into \`wp_head\`, registers the shortcode registry from §16, and strips 1249WordPress default cruft (emojis, block-library CSS) that fights the brand. 1250 1251\`\`\`php 1252<?php 1253// 1. Load theme styles partial into <head> 1254function add_theme_styles(){ 1255 include(locate_template('theme-styles.php')); 1256} 1257add_action( 'wp_head', 'add_theme_styles' ); 1258 1259// 2. Register all section shortcodes (see §16) 1260include(locate_template('shortcodes.php')); 1261 1262// 3. Kill WordPress emoji scripts (perf + visual cleanliness) 1263function disable_emojis() { 1264 remove_action( 'wp_head', 'print_emoji_detection_script', 7 ); 1265 remove_action( 'admin_print_scripts', 'print_emoji_detection_script' ); 1266 remove_action( 'wp_print_styles', 'print_emoji_styles' ); 1267 remove_action( 'admin_print_styles', 'print_emoji_styles' ); 1268 remove_filter( 'the_content_feed', 'wp_staticize_emoji' ); 1269 remove_filter( 'comment_text_rss', 'wp_staticize_emoji' ); 1270 remove_filter( 'wp_mail', 'wp_staticize_emoji_for_email' ); 1271 add_filter( 'tiny_mce_plugins', 'disable_emojis_tinymce' ); 1272 add_filter( 'wp_resource_hints', 'disable_emojis_remove_dns_prefetch', 10, 2 ); 1273} 1274add_action( 'init', 'disable_emojis' ); 1275 1276function disable_emojis_tinymce( $plugins ) { 1277 return is_array( $plugins ) ? array_diff( $plugins, array( 'wpemoji' ) ) : array(); 1278} 1279function disable_emojis_remove_dns_prefetch( $urls, $relation_type ) { 1280 if ( 'dns-prefetch' == $relation_type ) { 1281 $emoji_svg_url = apply_filters( 'emoji_svg_url', 'https://s.w.org/images/core/emoji/2/svg/' ); 1282 $urls = array_diff( $urls, array( $emoji_svg_url ) ); 1283 } 1284 return $urls; 1285} 1286 1287// 4. Drop Gutenberg block-library + WooCommerce block CSS (we ship our own) 1288function smartwp_remove_wp_block_library_css(){ 1289 wp_dequeue_style( 'wp-block-library' ); 1290 wp_dequeue_style( 'wp-block-library-theme' ); 1291 wp_dequeue_style( 'wc-blocks-style' ); 1292} 1293add_action( 'wp_enqueue_scripts', 'smartwp_remove_wp_block_library_css', 100 ); 1294 1295// 5. Theme support 1296add_action( 'after_setup_theme', 'add_theming_support' ); 1297function add_theming_support(){ 1298 add_theme_support( 'automatic-feed-links' ); 1299 add_theme_support( 'title-tag' ); 1300 add_theme_support( 'post-formats', array( 'aside','image','video','quote','link' ) ); 1301 add_theme_support( 'post-thumbnails' ); 1302 add_theme_support( 'html5', array( 'search-form','comment-form','comment-list','gallery','caption','script','style' ) ); 1303 register_nav_menus( array( 'main-menu' => 'Main Menu', 'footer-menu' => 'Footer Menu' ) ); 1304} 1305\`\`\` 1306 1307> Rules: \`functions.php\` NEVER contains markup or visual CSS. It only 1308> wires hooks. Any new section partial added in §14 MUST also be registered 1309>
1309 as a shortcode in \`shortcodes.php\` (§16) â \`functions.php\` includes 1310> that file once. 1311 1312--- 1313 1314## 20. \`theme-styles.php\` Contract (global base styles partial) 1315 1316\`theme-styles.php\` is the partial \`functions.php\` injects into 1317\`wp_head\`. It contains ONLY global base styles: CSS variables, reset, 1318typography, navbar, footer, and the utility classes from §13. Section 1319styles NEVER live here â they live in their own scoped \`apply_{slug}_styles\` 1320block (§9 / §14). 1321 1322\`\`\`php 1323<style type="text/css"> 1324 :root{ 1325 --color-1: {hex}; /* primary */ 1326 --color-2: {hex}; /* secondary */ 1327 --color-3: {hex}; /* accent */ 1328 --color-4: {hex}; /* neutral */ 1329 --heading-font: '{display}', serif; 1330 --default-font: '{body}', sans-serif; 1331 --xl: clamp(56px, 6vw, 88px); 1332 --lg: clamp(36px, 4vw, 56px); 1333 --md: clamp(22px, 2.5vw, 32px); 1334 --sm: 16px; 1335 } 1336 /* reset, body, masthead, inner-masthead, main-menu, mobile menu, 1337 .section-padding, .content-width, .absolute-cover, .button, 1338 .site-footer, fade-from-* keyframes â see §13 whitelist */ 1339</style> 1340\`\`\` 1341 1342> Rule: the AI builder writes one \`theme-styles.php\` per brand, populated 1343> from the Visual Brand Kit. It MUST NOT contain any \`.home-*\` or 1344> \`.internal-*\` selectors. 1345 1346--- 1347 1348## 21. \`header.php\` Contract (WordPress) 1349 1350\`header.php\` is the only template that emits the opening \`<html>\`, 1351\`<head>\`, and the masthead. It MUST follow this exact contract â the 1352class names are whitelisted (§13) and the WordPress hooks are required. 1353 1354\`\`\`php 1355<?php /** The header. */ ?> 1356<!doctype html> 1357<html <?php language_attributes(); ?>> 1358<head> 1359 <meta charset="<?php bloginfo( 'charset' ); ?>" /> 1360 <meta name="viewport" content="width=device-width, initial-scale=1" /> 1361 <?php wp_head(); ?> 1362</head> 1363<body <?php body_class(); ?>> 1364<?php wp_body_open(); ?> 1365<div id="main"> 1366 <a class="skip-menu" href="#main-content">Skip to Main Content</a> 1367 <header class="masthead"> 1368 <div class="inner-masthead"> 1369 <a class="logo-container" href="<?= get_home_url(); ?>/"> 1370 <img src="<?= wp_get_attachment_url(LOGO_ATTACHMENT_ID); ?>" width="400" height="64" alt="logo for <?php bloginfo('name'); ?>"> 1371 </a> 1372 <div class="menu-container"> 1373 <label for="mobile-input">â°</label> 1374 <input type="checkbox" id="mobile-input"> 1375 <nav> 1376 <?php wp_nav_menu(array('menu' => 'Main Menu', 'menu_class' => 'main-menu')); ?> 1377 </nav> 1378 </div> 1379 </div> 1380 </header> 1381 <div id="main-content"> 1382\`\`\` 1383 1384> Rules: never hard-code the logo \`<img src>\` â always 1385> \`wp_get_attachment_url()\`. \`wp_head()\`, \`wp_body_open()\`, and the 1386> matching \`wp_footer()\` in \`footer.php\` are non-negotiable. The 1387> mobile menu uses the CSS checkbox-toggle pattern in §13 â no JS. 1388 1389--- 1390 1391## 22. \`index.php\` / \`archive.php\` / \`404.php\` Contracts 1392 1393These three WordPress templates share the \`blog-styles.php\` partial 1394(§11) and the \`[internal_banner]\` shortcode (§8) so brand styling stays 1395centralised. Builder must emit all three verbatim, varying only the 1396banner title source. 1397 1398### \`index.php\` â blog index (post archive fallback) 1399\`\`\`php 1400<?php 1401function add_blog_styles(){ include(locate_template('blog-styles.php')); } 1402add_action('wp_head', 'add_blog_styles'); 1403get_header(); 1404$banner = '[internal_banner title="Blog"]'; 1405?> 1406<?= apply_shortcodes($banner); ?> 1407<section class="section-padding"> 1408 <div class="content-width"> 1409 <?php if ( have_posts() ) { ?> 1410 <div class="posts-container has-blogs"> 1411 <?php while ( have_posts() ) { the_post(); ?> 1412 <div class="indiv-post"> 1413 <a href="<?= get_the_permalink(); ?>" class="img-container"> 1414 <?php if(has_post_thumbnail()){ ?> 1415 <img src="<?= get_the_post_thumbnail_url(); ?>"> 1416 <?php }else{ ?> 1417 <span class="empty-thumb-container"></span> 1418 <?php } ?> 1419 </a> 1420 <div class="post-info"> 1421 <p class="date"> 1422 <span class="day"><?= get_the_date('d'); ?></span> 1423 <span class="y-m-container">
1424 <span class="year"><?= get_the_date('Y'); ?></span> 1425 <span class="month"><?= get_the_date('F'); ?></span> 1426 </span> 1427 </p> 1428 <h2 class="title"><?= get_the_title(); ?></h2> 1429 <p><?= get_the_excerpt(); ?></p> 1430 <a class="button" href="<?= get_the_permalink(); ?>">Read More</a> 1431 </div> 1432 </div> 1433 <?php } ?> 1434 </div> 1435 <div class="nav-links"> 1436 <?php echo paginate_links(array('prev_text'=>'<span><</span>','next_text'=>'<span>></span>')); ?> 1437 </div> 1438 <?php } else { ?> 1439 <div class="posts-container has-blogs">no content</div> 1440 <?php } ?> 1441 </div> 1442</section> 1443<?php get_footer(); ?> 1444\`\`\` 1445 1446### \`archive.php\` â taxonomy / category archives 1447Identical loop to \`index.php\` except the banner title pulls from the 1448queried term and the empty state copy changes: 1449\`\`\`php 1450<?php 1451function add_blog_styles(){ include(locate_template('blog-styles.php')); } 1452add_action('wp_head', 'add_blog_styles'); 1453get_header(); 1454$term = get_queried_object(); 1455$banner = '[internal_banner title="'. $term->name .'"]'; 1456?> 1457<?= apply_shortcodes($banner); ?> 1458<!-- â¦same loop as index.php⦠--> 1459<!-- Empty-state variant: --> 1460<div class="posts-container no-blogs"> 1461 There are no posts with that category name. 1462 <a style="width:100%;" href="/">Return to our homepage.</a> 1463</div> 1464\`\`\` 1465 1466### \`404.php\` â not found 1467\`\`\`php 1468<?php get_header(); ?> 1469<?= apply_shortcodes('[internal_banner title="That\\'s a 404"]'); ?> 1470<section class="section-padding"> 1471 <div class="content-width" style="text-align: center;"> 1472 The URL you entered doesn't exist on our site. Perhaps try navigating from <a href="/">our homepage</a>? 1473 </div> 1474</section> 1475<?php get_footer(); ?> 1476\`\`\` 1477 1478> Rules: (a) \`index.php\` and \`archive.php\` ALWAYS load 1479> \`blog-styles.php\` via the \`add_blog_styles\` hook â never inline. (b) 1480> The banner is ALWAYS \`[internal_banner]\` so it inherits the brand's 1481> interior-banner styling. (c) Loop markup (\`posts-container\`, 1482> \`indiv-post\`, \`img-container\`, \`empty-thumb-container\`, \`post-info\`, 1483> \`date\`/\`day\`/\`y-m-container\`/\`year\`/\`month\`, \`title\`, 1484> \`nav-links\`) is part of the §13 whitelist and MUST NOT be renamed â 1485> \`blog-styles.php\` selectors depend on these exact class names. 1486 1487--- 1488 1489## 23. Arcbound Theme File Structure (CANONICAL â WordPress-ready) 1490 1491Every generated build MUST map 1:1 to this file tree so it can be dropped 1492into the Arcbound WordPress boilerplate without restructuring. Do NOT 1493invent alternative folder layouts. 1494 1495\`\`\` 1496{theme-root}/ 1497âââ style.css (§18 â registration only, no real CSS) 1498âââ functions.php (§19 â bootstrap, enqueues, shortcode + hook wiring) 1499âââ theme-styles.php (§20 â global :root vars, reset, nav, footer, utilities) 1500âââ header.php (§21 â <html>, <head>, <body>, .masthead, mobile nav) 1501âââ footer.php (§12 â closes #main-content/#main, wp_footer) 1502âââ page.php (§17 â generic page wrapper, the_content()) 1503âââ single.php (§17 â single post; loads single-blog-styles.php) 1504âââ single-blog-styles.php (§17 â scoped post styles) 1505âââ index.php (§22 â blog index, loads blog-styles.php) 1506âââ archive.php (§22 â taxonomy archive, loads blog-styles.php) 1507âââ search.php (§17 â reuses [internal_banner] + blog-styles.php) 1508âââ 404.php (§22 â uses [internal_banner]) 1509âââ blog-styles.php (§11 â shared archive/search loop styles) 1510âââ includes/ 1511â âââ shortcodes.php (§16 â home_* + internal_* registry) 1512â âââ theme-changes.php (§10 â wp_footer: IntersectionObserver lazy load + scroll-in animations) 1513âââ template-parts/ 1514 âââ sections/ 1515 âââ home/ 1516 â âââ home-banner.php (§14 â inline <style>, NOT wp_footer) 1517 â âââ home-services.php 1518 â âââ home-about.php 1519 â âââ home-team.php 1520 â âââ home-cta.php 1521 â âââ home-results.php 1522 â âââ home-testimonials.php 1523 â âââ home-social.php 1524 â âââ home-news.php 1525 â âââ home-contact.php 1526 â âââ home-mission.php 1527 â âââ home-awards.php 1528 â âââ home-portfolio.php 1529 âââ internal/ 1530 âââ internal-banner.php 1531 âââ internal-content.php 1532 âââ internal-fullwidth.php 1533 âââ internal-cta.php 1534 âââ internal-contact.php 1535 âââ internal-services.php 1536\`\`\` 1537 1538> Generation contract: when the AI emits the build payload it MUST return a 1539> map keyed by these exact relative paths. Any partial that does not have a 1540> matching shortcode registration in \`includes/shortcodes.php\` is a build 1541> failure â re-run the §15 workflow for that section. 1542 1543--- 1544 1545## 24. \`includes/theme-changes.php\` Contract (lazy load + scroll animations) 1546 1547Single source of truth for the two runtime behaviours referenced in §4 and 1548§10. Output ONLY via the \`wp_footer\` hook â never inline in templates. 1549 1550\`\`\`php 1551<?php 1552add_action('wp_footer', 'arcbound_footer_scripts'); 1553function arcbound_footer_scripts() { ?> 1554<script> 1555// 1. Lazy load: swap data-url -> src as elements enter viewport 1556(function () { 1557 var imgs = document.querySelectorAll('img[data-url]'); 1558 if (!('IntersectionObserver' in window)) {
1559 imgs.forEach(function (i) { i.src = i.getAttribute('data-url'); }); 1560 return; 1561 } 1562 var io = new IntersectionObserver(function (entries, obs) { 1563 entries.forEach(function (e) { 1564 if (!e.isIntersecting) return; 1565 var el = e.target; 1566 el.src = el.getAttribute('data-url'); 1567 el.removeAttribute('data-url'); 1568 obs.unobserve(el); 1569 }); 1570 }, { rootMargin: '200px 0px' }); 1571 imgs.forEach(function (i) { io.observe(i); }); 1572})(); 1573 1574// 2. Scroll-in animations: activate .fade-from-* once visible (disabled <=750px) 1575window.addEventListener('load', function () { 1576 if (window.innerWidth <= 750) return; 1577 var els = document.querySelectorAll('.fade-from-left, .fade-from-right, .fade-from-bottom'); 1578 var io = new IntersectionObserver(function (entries, obs) { 1579 entries.forEach(function (e) { 1580 if (!e.isIntersecting) return; 1581 e.target.classList.add('is-visible'); 1582 obs.unobserve(e.target); 1583 }); 1584 }, { threshold: 0.15 }); 1585 els.forEach(function (el) { io.observe(el); }); 1586}); 1587<\/script> 1588<?php } 1589\`\`\` 1590 1591> Rules: (a) Every \`<img>\` in every section partial MUST use \`data-url\` 1592> instead of \`src\` (except the LCP image inside \`home-banner.php\`, which 1593> stays as \`src\` for performance). (b) The \`.fade-from-*\` classes 1594> declared in §13 are inert until the observer adds \`.is-visible\` â 1595> \`theme-styles.php\` MUST define both the resting and \`.is-visible\` state. 1596> (c) Do not enqueue any other lazy-load plugin; \`functions.php\` (§19) 1597> explicitly disables native WP lazy loading and \`wp_calculate_image_srcset\`. 1598 1599--- 1600 1601## 25. \`functions.php\` â Required Disables (additive to §19) 1602 1603The Arcbound boilerplate intentionally disables WordPress features that 1604conflict with the custom lazy loader and scoped section styles. Include 1605ALL of the following in \`functions.php\`: 1606 1607\`\`\`php 1608// Disable native lazy loading (custom IntersectionObserver used instead â §24) 1609add_filter('wp_lazy_loading_enabled', '__return_false'); 1610 1611// Disable responsive srcset (custom data-url swap handles delivery) 1612add_filter('wp_calculate_image_srcset_meta', '__return_null'); 1613add_filter('wp_calculate_image_srcset', '__return_false'); 1614 1615// Strip emoji scripts/styles (see §19 disable_emojis) 1616remove_action('wp_head', 'print_emoji_detection_script', 7); 1617remove_action('wp_print_styles', 'print_emoji_styles'); 1618 1619// Dequeue block library + global styles (theme is fully custom) 1620add_action('wp_enqueue_scripts', function () { 1621 wp_dequeue_style('wp-block-library'); 1622 wp_dequeue_style('wp-block-library-theme'); 1623 wp_dequeue_style('global-styles'); 1624}, 100); 1625\`\`\` 1626 1627--- 1628 1629## 26. Per-Section Asset Conventions (image markup) 1630 1631To keep §24's lazy loader working everywhere, every section partial MUST 1632follow this image markup contract: 1633 1634\`\`\`php 1635<!-- Below-the-fold image (default) --> 1636<img data-url="<?= esc_url($img) ?>" 1637 alt="<?= esc_attr($alt) ?>" 1638 width="<?= (int) $w ?>" 1639 height="<?= (int) $h ?>" 1640 decoding="async"> 1641 1642<!-- LCP / above-the-fold (home-banner.php only) --> 1643<img src="<?= esc_url($img) ?>" 1644 alt="<?= esc_attr($alt) ?>" 1645 width="<?= (int) $w ?>" 1646 height="<?= (int) $h ?>" 1647 fetchpriority="high" 1648 decoding="async"> 1649\`\`\` 1650 1651Rules: (a) Always emit explicit \`width\` + \`height\` to prevent CLS. 1652(b) Never use \`loading="lazy"\` â the observer handles it. 1653(c) Background images go in the scoped \`apply_{slug}_styles\` block, not inline \`style="..."\`. 1654 1655--- 1656 1657## 27. Launch-Readiness Generation Contract (SOP Phases 3â5) 1658 1659The generator MUST emit, in addition to the theme files, a sibling 1660\`LAUNCH-CHECKLIST.md\` per build that mirrors the Arcbound SOP so QA can 1661tick items without re-deriving them: 1662 1663- Phase 3.1 Updates & Plugins â Yoast SEO, Forms plugin, Redirection listed as required 1664- Phase 3.2 Forms â every \`[internal_contact]\` / form shortcode must declare its recipient + thank-you URL in the build payload 1665- Phase 3.3 SEO â every \`page.php\` / section pair must ship a \`<title>\` + meta description + single \`<h1>\` (enforced by §11/§17 templates) 1666- Phase 3.3 Yoast â archives (\`archive.php\`, author/category/tag) MUST be flagged \`noindex\` in the generated Yoast import file 1667- Phase 3.4 Performance â \`home-banner.php\` is the ONLY section allowed to inline its \`<style>\` and use \`fetchpriority="high"\` (§14, §26) 1668- Phase 3.5 Cleanup â \`404.php\` (§22) is mandatory;
1668 build fails if absent 1669- Phase 5.1 Post-launch â Post SMTP + HTTPS notes included in the checklist; not generated as code 1670 1671> The checklist is a deliverable, not a suggestion. A build payload that 1672> omits \`LAUNCH-CHECKLIST.md\` is incomplete and MUST be regenerated. 1673 1674--- 1675 1676## 28. AI Component Generation System Prompt (MANDATORY â html components only) 1677 1678When the generator is asked to produce ONE section/component (not a full 1679page), it MUST operate under the following system prompt verbatim. This is 1680the source of truth for the Arcbound WordPress theme boilerplate; deviating 1681from any rule is a build failure. 1682 1683> You are generating PHP template section files for a custom WordPress theme 1684> called the Arcbound boilerplate. Every section you create must follow all 1685> of the rules below exactly. Do not deviate from these patterns even if a 1686> different approach seems cleaner or more conventional. 1687 1688### 28.1 â 1:1:1 Naming Contract 1689 1690The section slug is the single source of truth. It drives the file name, 1691the root CSS class, AND the shortcode name. 1692 1693| Element | Pattern | Example | 1694|---|---|---| 1695| File name | \`{slug}.php\` | \`home-banner.php\` | 1696| Root CSS class | \`.{slug}\` | \`.home-banner\` | 1697| Shortcode name | \`{slug}\` with \`-\` â \`_\` | \`home_banner\` | 1698 1699Location: \`template-parts/sections/home/{slug}.php\` (home) or 1700\`template-parts/sections/internal/{slug}.php\` (internal). 1701The shortcode is registered in \`includes/shortcodes.php\` â NEVER inside 1702the template file: 1703 1704\`\`\`php 1705function home_banner($atts, $content = null) { 1706 ob_start(); 1707 include(locate_template('template-parts/sections/home/home-banner.php')); 1708 return ob_get_clean(); 1709} 1710add_shortcode('home_banner', 'home_banner'); 1711\`\`\` 1712 1713### 28.2 â Template File Top-to-Bottom Order (STRICT) 1714 1715Every section file MUST contain these four blocks in this exact order and 1716nothing else: 1717 17181. PHP attribute block (\`shortcode_atts()\`) 17192. \`<style>\` block (scoped to root class) 17203. HTML markup 17214. PHP JS function (registered to \`wp_footer\`) â OMIT entirely if no JS 1722 1723Forbidden in the file: \`wp_enqueue_style\`, \`wp_enqueue_script\`, external 1724\`<link>\` or \`<script src>\`, inline \`style="..."\` on HTML elements, 1725section markup in \`header.php\`/\`footer.php\`. 1726 1727### 28.3 â PHP Attribute Block (always first) 1728 1729\`\`\`php 1730<?php $atts = shortcode_atts(array( 1731 'title' => '', 1732 'content' => '', 1733), $atts); ?> 1734\`\`\` 1735 1736If the section has no attributes yet, use a placeholder so it remains 1737extensible without restructuring: 1738 1739\`\`\`php 1740<?php $atts = shortcode_atts(array('' => ''), $atts); ?> 1741\`\`\` 1742 1743### 28.4 â The \`<style>\` Block (scoped CSS only) 1744 1745Rules: 1746- EVERY selector starts with \`.{slug}\`. No bare tag selectors. No global 1747 class without the slug prefix. 1748- Use the theme's CSS custom properties for ALL colors, sizes, and fonts. 1749 Hardcoded hex/px values are a build failure. 1750- Include responsive overrides at \`max-width: 1000px\` AND \`max-width: 750px\`. 1751- Reuse global utilities in the HTML, do NOT re-declare them: \`.section-padding\`, 1752 \`.content-width\`, \`.absolute-cover\`, \`.fade-from-left/-right/-bottom\`. 1753 1754Available CSS custom properties (theme contract): 1755 1756\`\`\`css 1757/* Colors */ var(--color-1) var(--color-2) var(--color-3) 1758/* Font sizes */ var(--xl) /* h1: 55â40â35 */ 1759 var(--lg) /* h2: 40â30â25 */ 1760 var(--md) /* h3: 30â20â20 */ 1761 var(--sm) /* h4: 20â18â18 */ 1762 var(--default) /* body 16 */ 1763/* Font families */ var(--heading-font) var(--default-font) var(--accent-font) 1764\`\`\` 1765 1766### 28.5 â HTML Markup Rules 1767 1768- Outermost element is ALWAYS \`<section class="{slug} section-padding">\`. 1769- Wrap content in \`<div class="content-width">\`. 1770- Sub-classes use BEM scoped to the slug: \`.home-banner__title\`, 1771 \`.home-banner__grid\`, \`.home-banner__item\`. 1772- Full-bleed backgrounds: \`<img class="absolute-cover" ...>\` inside the 1773 section + \`position: relative; overflow: hidden;\` on \`.{slug}\` in 1774 \`<style>\`. 1775- Lazy-loaded images use \`data-url=\` instead of \`src=\` (see §24).
1776- Above-the-fold LCP image (home-banner only) uses \`src=\` + \`fetchpriority="high"\`. 1777- Animation classes: \`.fade-from-left\`, \`.fade-from-right\`, \`.fade-from-bottom\` 1778 on any element â the theme observer adds \`.active\` (and disables on 1779 mobile automatically). 1780- Output attribute values with the short echo tag: \`<?= $atts['key']; ?>\`. 1781- ACF/custom field access is allowed: \`the_field()\`, \`get_field()\`, 1782 \`get_post_meta()\`. 1783 1784### 28.6 â JavaScript Block (last; omit if none) 1785 1786\`\`\`php 1787<?php if(!function_exists('apply_home_banner_styles')) { 1788 function apply_home_banner_styles() { ?> 1789 <script> 1790 window.addEventListener('load', function() { 1791 const banner = document.querySelector('.home-banner'); 1792 if (!banner) return; 1793 // scoped logic here 1794 }); 1795 <\/script> 1796 <?php } 1797 add_action('wp_footer', 'apply_home_banner_styles'); 1798} ?> 1799\`\`\` 1800 1801Rules: 1802- Function name = \`apply_{slug_with_underscores}_styles\`. 1803- ALWAYS guard with \`if(!function_exists(...))\` â shortcodes may render multiple times per page. 1804- Register via \`add_action('wp_footer', ...)\`. 1805- Use \`window.addEventListener('load', ...)\` â never \`document.ready\`. 1806- Query only by \`.{slug}\` or selectors unique to this section. 1807- No inline library imports. Assume libraries (if any) are globally enqueued. 1808- If the section needs no JS, OMIT this block entirely. Do NOT ship an empty function. 1809 1810### 28.7 â Canonical Empty Starter 1811 1812\`\`\`php 1813<?php $atts = shortcode_atts(array( 1814 'title' => '', 1815 'content' => '', 1816), $atts); ?> 1817 1818<style type="text/css"> 1819 .{slug} {} 1820 .{slug} h1 { font-family: var(--heading-font); font-size: var(--xl); } 1821 @media(max-width: 1000px) { .{slug} {} } 1822 @media(max-width: 750px) { .{slug} {} } 1823</style> 1824 1825<section class="{slug} section-padding"> 1826 <div class="content-width"> 1827 <!-- markup --> 1828 </div> 1829</section> 1830 1831<?php if(!function_exists('apply_{slug_us}_styles')) { 1832 function apply_{slug_us}_styles() { ?> 1833 <script>window.addEventListener('load', function(){ /* ... */ });<\/script> 1834 <?php } 1835 add_action('wp_footer', 'apply_{slug_us}_styles'); 1836} ?> 1837\`\`\` 1838 1839### 28.8 â Pre-Built Slug Registry (do NOT recreate) 1840 1841If a design calls for one of these, EXTEND the existing file. Do not generate a duplicate under a different slug. 1842 1843Homepage (\`template-parts/sections/home/\`): 1844\`home-banner\`, \`home-services\`, \`home-about\`, \`home-team\`, \`home-cta\`, 1845\`home-results\`, \`home-testimonials\`, \`home-social\`, \`home-news\`, 1846\`home-contact\`, \`home-mission\`, \`home-awards\`, \`home-portfolio\`. 1847 1848Internal (\`template-parts/sections/internal/\`): 1849\`internal-banner\`, \`internal-content\`, \`internal-fullwidth\`, 1850\`internal-cta\`, \`internal-contact\`, \`internal-services\`. 1851 1852### 28.9 â Global File Boundaries 1853 1854\`header.php\` â \`<!doctype>\`, \`<html>\`, \`<head>\`, \`wp_head()\`, 1855opens \`<body>\` + \`wp_body_open()\`, renders \`.masthead\` (logo + nav), 1856opens \`#main\` and \`#main-content\`, includes \`.skip-menu\`. NO section 1857markup, NO inline styles, NO inline scripts. 1858 1859\`footer.php\` â closes \`#main-content\` and \`#main\`, calls \`wp_footer()\` 1860(this is what triggers every section's \`apply_{slug}_styles\` registration), 1861closes \`</body>\` and \`</html>\`. NO section markup. 1862 1863\`theme-styles.php\` â global ONLY: \`:root\` custom properties, reset, 1864typography defaults, navigation, buttons, animation keyframes. NO selectors 1865beginning with \`.home-\` or \`.internal-\`. When a client's brand colors or 1866fonts change, ONLY the \`:root\` block changes. 1867 1868### 28.10 â Per-Section Self-QA Checklist (run before emitting) 1869 1870Every generated section file must pass ALL of: 1871 1872- [ ] File name matches slug exactly (\`{slug}.php\`). 1873- [ ] Root \`<section>\` class matches slug exactly. 1874- [ ] Shortcode function name matches slug exactly (\`-\` â \`_\`). 1875- [ ] Shortcode registered in \`includes/shortcodes.php\`, NOT in template. 1876- [ ] Every CSS selector scoped to \`.{slug}\`. 1877- [ ] No hardcoded colors â \`var(--color-*)\` only. 1878- [ ] No hardcoded font sizes â \`var(--xl|lg|md|sm|default)\` only.
1879- [ ] Responsive overrides at 1000px AND 750px. 1880- [ ] Lazy images use \`data-url=\` (except LCP in \`home-banner\`). 1881- [ ] Animations use \`.fade-from-*\` classes â no inline keyframes. 1882- [ ] JS wrapped in \`apply_{slug}_styles()\` + \`function_exists\` guard. 1883- [ ] JS uses \`window.addEventListener('load', ...)\`. 1884- [ ] If section has no JS, the JS block is OMITTED (no empty function). 1885- [ ] No \`wp_enqueue_*\`, no external \`<link>\`/\`<script src>\` in the file. 1886 1887> Generator behaviour: when asked to produce a single component, output 1888> ONLY the contents of \`{slug}.php\` per §28.7, plus the matching 1889> \`add_shortcode\` registration that belongs in \`includes/shortcodes.php\` 1890> (clearly labelled as a separate snippet). Do not emit page-level wrappers, 1891> \`header.php\`, or \`footer.php\` for single-component requests. 1892 1893### 28.11 â Theme Token Bridge (compat with §13/§20) 1894 1895The Arcbound boilerplate uses the SHORT tokens in §28.4 (\`--xl\`, \`--lg\`, 1896\`--heading-font\`, etc.). Earlier sections of this brief reference longer 1897tokens (\`--font-display\`, \`--color-1\`). \`theme-styles.php\` (§20) MUST 1898declare both spellings in \`:root\` so generated sections under either 1899contract resolve correctly: 1900 1901\`\`\`css 1902:root { 1903 /* canonical (§28) */ 1904 --color-1: <hex>; --color-2: <hex>; --color-3: <hex>; 1905 --xl: 55px; --lg: 40px; --md: 30px; --sm: 20px; --default: 16px; 1906 --heading-font: '<Display>', serif; 1907 --default-font: '<Body>', sans-serif; 1908 --accent-font: '<Accent>', sans-serif; 1909 1910 /* aliases for earlier sections of this brief */ 1911 --font-display: var(--heading-font); 1912 --font-body: var(--default-font); 1913} 1914@media(max-width: 1000px) { :root { --xl: 40px; --lg: 30px; --md: 20px; --sm: 18px; } } 1915@media(max-width: 750px) { :root { --xl: 35px; --lg: 25px; --md: 20px; --sm: 18px; } } 1916\`\`\``;const Y=t.homepageSections.find(s=>{var o,a;return((o=s.heading)==null?void 0:o.toLowerCase().includes("hero"))||((a=s.heading)==null?void 0:a.toLowerCase().includes("header"))}),Ie=(Y==null?void 0:Y.copy)||((_e=t.homepageSections[0])==null?void 0:_e.copy)||"";r["hero-concept"]=`# â HERO & FULL HOMEPAGE DESIGN CONCEPT 1917 1918## â¡ Click "Generate Hero Concept" to create an AI-powered design concept 1919This will: 19201. Scrape award-winning designs from Godly.website, Awwwards, and OnePageLove 19212. Extract hero HTML/CSS patterns from featured sites 19223. Generate a bespoke hero concept with production-ready code 19234. Include parallax, custom cursor, reactive elements, and scroll animations 19245. Create section-by-section visual direction for the entire homepage 1925 1926## Current Hero Copy (from Homepage Copy section) 1927**Heading:** ${(Y==null?void 0:Y.heading)||((xe=t.homepageSections[0])==null?void 0:xe.heading)||"TBD"} 1928 1929${Ie} 1930 1931## Design Parameters That Will Be Applied 1932- Display Font: **${d}** 1933- Body Font: **${g}** 1934- Colors: ${l} 1935- Mood: ${t.mood.join(", ")} 1936 1937## Interactive Elements to Include 1938- ⦠Custom cursor (subtle dot/ring that reacts to hoverable elements) 1939- ⦠Parallax scrolling on hero background layers 1940- ⦠Mouse-tracking gradient orbs or light effects 1941- ⦠Magnetic buttons that subtly pull toward cursor 1942- ⦠Scroll-triggered animations (stagger reveal, parallax sections) 1943- ⦠Animated counters for statistics/impact numbers 1944- ⦠Smooth page transitions between sections 1945- ⦠Reactive floating elements that respond to scroll position 1946- ⦠Infographics and diagrams with brand colors 1947- ⦠Icon system with consistent visual language 1948 1949> Click the **"Generate Hero Concept"** button above to create a full design concept with code.`,ue(r)},Ae=t=>{const i=z[t];i&&(navigator.clipboard.writeText(i),Z(t),x.success("Copied to clipboard!"),setTimeout(()=>Z(null),2e3))},$e=()=>{if(!m)return;const t=K.map(r=>`${r.title} 1950${"=".repeat(r.title.length)} 1951 1952${z[r.key]||""} 1953 1954 1955`).join(""),i=new Blob([t],{type:"text/plain"}),l=URL.createObjectURL(i),n=document.createElement("a");n.href=l,n.download=`${m.clientName.replace(/\s+/g,"-")}-Website-Brief.txt`,n.click(),URL.revokeObjectURL(l)},ge=()=>{if(!m)return;const t=K.map(i=>`${i.title} 1956${"=".repeat(i.title.length)} 1957 1958${z[i.key]||""} 1959 1960 1961`).join("");navigator.clipboard.writeText(t),x.success("All brief sections copied to clipboard!")},fe=()=>{if(!m)return;const t=new Ge({orientation:"p",unit:"mm",format:"a4"}),i=210,l=15,n=i-l*2;let r=l;
1961const c=(d,g,v=!1)=>{t.setFontSize(g),v?t.setFont("helvetica","bold"):t.setFont("helvetica","normal");const S=t.splitTextToSize(d,n),$=g*.45;for(const _ of S)r+$>282&&(t.addPage(),r=l),t.text(_,l,r),r+=$};t.setFontSize(24),t.setFont("helvetica","bold"),t.text("Website Design Brief",l,40),t.setFontSize(14),t.setFont("helvetica","normal"),t.text(m.clientName,l,52),t.setFontSize(10),t.text(new Date().toLocaleDateString(),l,60),t.addPage(),r=l,K.forEach((d,g)=>{g>0&&(t.addPage(),r=l),c(d.title,16,!0),r+=4,(z[d.key]||"").split(` 1962`).forEach(S=>{S.startsWith("# ")?(c(S.slice(2),14,!0),r+=2):S.startsWith("## ")?(c(S.slice(3),12,!0),r+=1):S.startsWith("### ")?c(S.slice(4),11,!0):S.trim()===""?r+=3:c(S,9)})}),t.save(`${m.clientName.replace(/\s+/g,"-")}-Website-Brief.pdf`),x.success("Brief exported as PDF!")},f=async t=>{var i;if(y){x.loading("Loading Brand DNA...",{id:"dna-export"});try{const{data:l}=await k.from("brand_dna").select("profile_data").eq("client_id",y).single(),n=l==null?void 0:l.profile_data;if(!n){x.error("No Brand DNA found",{id:"dna-export"});return}const r=JSON.stringify(n,null,2);if(t==="clipboard"){await navigator.clipboard.writeText(r),x.success("Brand DNA copied to clipboard!",{id:"dna-export"});return}const c=new Ge({orientation:"p",unit:"mm",format:"a4"}),d=15,g=180;let v=d;c.setFontSize(20),c.setFont("helvetica","bold"),c.text("Brand DNA Profile",d,v+10),c.setFontSize(11),c.setFont("helvetica","normal"),c.text((m==null?void 0:m.clientName)||"",d,v+18),c.text(new Date().toLocaleDateString(),d,v+24),v=d+34;const S=($,_=0)=>{if(!$||typeof $!="object")return;const O=Array.isArray($)?$.map((j,P)=>[String(P),j]):Object.entries($);for(const[j,P]of O){v>280&&(c.addPage(),v=d);const G=d+_*4;if(P&&typeof P=="object"){c.setFont("helvetica","bold"),c.setFontSize(_===0?12:10);const R=j.replace(/([A-Z])/g," $1").replace(/^./,U=>U.toUpperCase());c.text(R,G,v),v+=5,c.setFont("helvetica","normal"),S(P,_+1)}else{c.setFont("helvetica","normal"),c.setFontSize(9);const U=`${j.replace(/([A-Z])/g," $1").replace(/^./,A=>A.toUpperCase())}: ${String(P??"")}`,W=c.splitTextToSize(U,g-_*4);for(const A of W)v>280&&(c.addPage(),v=d),c.text(A,G,v),v+=4}}};S(n),c.save(`${((i=m==null?void 0:m.clientName)==null?void 0:i.replace(/\s+/g,"-"))||"Client"}-Brand-DNA.pdf`),x.success("Brand DNA exported as PDF!",{id:"dna-export"})}catch(l){x.error("Export failed: "+(l.message||"Unknown error"),{id:"dna-export"})}}},u=async()=>{var t;if(y){X(!0),oe("hero-concept"),x.loading("Scraping award-winning designs & generating hero concept... This takes 30-60 seconds.",{id:"hero-gen"});try{const{data:i,error:l}=await k.functions.invoke("generate-hero-concept",{body:{clientId:y}});if(l)throw l;if(i!=null&&i.error)throw new Error(i.error);const n=i.data,r=`# â HERO & FULL HOMEPAGE DESIGN CONCEPT 1963## Generated from Award-Winning Design Analysis 1964 1965> This concept was generated by analyzing ${n.heroCodeExamplesCount} award-winning hero sections from sites featured on Godly.website, Awwwards, and OnePageLove. The design has been tailored to your exact brand fonts, colors, and messaging. 1966 1967## Inspiration Sources Analyzed 1968${((t=n.gallerySources)==null?void 0:t.map(c=>{var d;return`### ${c.source} 1969Featured sites studied: ${((d=c.featuredLinks)==null?void 0:d.join(", "))||"N/A"}`}).join(` 1970 1971`))||"N/A"} 1972 1973--- 1974 1975${n.heroConcept} 1976 1977--- 1978 1979## How to Use This Concept 19801. **Copy the entire concept** and paste it into Claude, v0, or Lovable as your primary design brief 19812. **The HTML/CSS/JS code is production-ready** â paste it directly into your builder 19823. **The design direction covers every section** â use it as your visual North Star 19834. **Customize the copy** â replace placeholder text with the exact copy from the "Homepage Copy" section 19845. **Maintain the interactive elements** â parallax, custom cursor, and reactive elements are what make it award-worthy`;ue(c=>({...c,"hero-concept":r})),x.success("Hero concept generated! ð¨",{id:"hero-gen"})}catch(i){console.error("Hero gen error:",i),x.error(i.message||"Failed to generate hero concept",{id:"hero-gen"})}X(!1)}};if(H)return e.jsx("div",{className:"min-h-screen flex items-center justify-center bg-background",children:e.jsx(he,{className:"w-6 h-6 animate-spin text-muted-foreground"})});if(!m)return e.jsx("div",{className:"min-h-screen flex items-center justify-center bg-background",children:e.jsx("p",{className:"text-muted-foreground",children:"No brand data found. Complete earlier steps first."})});const D=K.find(t=>t.key===T).icon;return e.jsxs("div",{className:"min-h-screen bg-background text-foreground",children:[e.jsx("div",{className:"border-b bg-card",children:e.jsx("div",{className:"max-w-7xl mx-auto px-6 py-4",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsxs(F,{variant:"ghost",size:"sm",onClick:()=>se(`/admin/client/${y}`),children:[e.jsx(mt,{className:"w-4 h-4 mr-1"})," Back"]}),e.jsxs("div",{children:[e.jsx("h1",{className:"text-lg font-semibold",children:"Website Design Brief"}),e.jsxs("p",{className:"text-sm text-muted-foreground",children:["AI prompts for ",m.clientName]})]})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(F,{variant:"outline",size:"sm",onClick:()=>ie(),disabled:H,children:[H?e.jsx(he,{className:"w-4 h-4 mr-1 animate-spin"}):e.jsx(ut,{className:"w-4 h-4 mr-1"}),"Reload"]}),e.jsxs(tt,{children:[e.jsx(st,{asChild:!0,children:e.jsxs(F,{variant:"outline",size:"sm",children:[e.jsx(Le,{className:"w-4 h-4 mr-1"})," Export ",e.jsx(gt,{className:"w-3 h-3 ml-1"})]})}
1984),e.jsxs(ot,{align:"end",className:"w-56",children:[e.jsxs(pe,{onClick:ge,children:[e.jsx(Ye,{className:"w-4 h-4 mr-2"})," Copy All Brief to Clipboard"]}),e.jsxs(pe,{onClick:$e,children:[e.jsx(Le,{className:"w-4 h-4 mr-2"})," Download Brief as TXT"]}),e.jsxs(pe,{onClick:fe,children:[e.jsx(Ce,{className:"w-4 h-4 mr-2"})," Export Brief as PDF"]}),e.jsx(at,{}),e.jsxs(pe,{onClick:()=>f("clipboard"),children:[e.jsx(qe,{className:"w-4 h-4 mr-2"})," Copy Brand DNA to Clipboard"]}),e.jsxs(pe,{onClick:()=>f("pdf"),children:[e.jsx(qe,{className:"w-4 h-4 mr-2"})," Export Brand DNA as PDF"]})]})]})]})]})})}),e.jsx("div",{className:"max-w-7xl mx-auto px-6 py-6",children:e.jsxs("div",{className:"flex gap-6",children:[e.jsx("div",{className:"w-64 shrink-0",children:e.jsxs("div",{className:"sticky top-6 space-y-1",children:[e.jsx("p",{className:"text-xs font-medium text-muted-foreground uppercase tracking-wider mb-3",children:"Brief Sections"}),K.map(t=>{const i=t.icon;return e.jsxs("button",{onClick:()=>oe(t.key),className:`w-full flex items-center gap-2.5 px-3 py-2 rounded-md text-left text-sm transition-colors ${T===t.key?"bg-primary text-primary-foreground":"text-muted-foreground hover:bg-muted hover:text-foreground"}`,children:[e.jsx(i,{className:"w-4 h-4 shrink-0"}),e.jsx("span",{className:"truncate",children:t.title})]},t.key)}),e.jsxs("div",{className:"mt-6 p-3 rounded-md bg-muted/50 text-xs space-y-1.5",children:[e.jsxs("div",{className:"flex items-center gap-1.5 text-muted-foreground",children:[e.jsx(Te,{className:"w-3.5 h-3.5"}),K.length," detailed sections"]}),e.jsxs("div",{className:"flex items-center gap-1.5 text-muted-foreground",children:[e.jsx(Ze,{className:"w-3.5 h-3.5"}),Object.keys(m.colors).length," brand colors"]}),e.jsxs("div",{className:"flex items-center gap-1.5 text-muted-foreground",children:[e.jsx(Ce,{className:"w-3.5 h-3.5"}),m.homepageSections.length," copy sections"]})]})]})}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center justify-between mb-4",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"w-10 h-10 rounded-md bg-primary/10 flex items-center justify-center",children:e.jsx(D,{className:"w-5 h-5 text-primary"})}),e.jsxs("div",{children:[e.jsx("h2",{className:"text-base font-semibold",children:K.find(t=>t.key===T).title}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Copy this prompt to guide website generation"})]})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[T==="hero-concept"&&e.jsx(F,{size:"sm",onClick:u,disabled:ne,className:"bg-gradient-to-r from-primary to-primary/80",children:ne?e.jsxs(e.Fragment,{children:[e.jsx(he,{className:"w-4 h-4 mr-1 animate-spin"})," Generating..."]}):e.jsxs(e.Fragment,{children:[e.jsx(ft,{className:"w-4 h-4 mr-1"})," Generate Hero Concept"]})}),e.jsx(F,{variant:"outline",size:"sm",onClick:()=>Ae(T),children:me===T?e.jsxs(e.Fragment,{children:[e.jsx(Te,{className:"w-4 h-4 mr-1 text-green-600"})," Copied!"]}):e.jsxs(e.Fragment,{children:[e.jsx(Ve,{className:"w-4 h-4 mr-1"})," Copy Section"]})})]})]}),e.jsx("div",{className:"rounded-lg border bg-card overflow-hidden",children:e.jsx("pre",{className:"p-6 text-sm leading-relaxed whitespace-pre-wrap font-mono text-foreground/90 max-h-[70vh] overflow-y-auto",children:z[T]||"Loading..."})}),T==="design-system"&&Object.keys(m.colors).length>0&&e.jsxs("div",{className:"mt-4 p-4 rounded-lg border bg-card",children:[e.jsx("p",{className:"text-xs font-medium text-muted-foreground uppercase tracking-wider mb-3",children:"Color Preview"}),e.jsx("div",{className:"flex gap-3 flex-wrap",children:Object.values(m.colors).map((t,i)=>e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("div",{className:"w-8 h-8 rounded-md border",style:{backgroundColor:t.hex}}),e.jsxs("div",{children:[e.jsx("p",{className:"text-xs font-medium",children:t.name}),e.jsx("p",{className:"text-[10px] text-muted-foreground",children:t.hex})]})]},i))})]}),T==="imagery-graphics"&&J.length>0&&e.jsxs("div",{className:"mt-4 p-4 rounded-lg border bg-card",children:[e.jsxs("div",{className:"flex items-center justify-between mb-3",children:[e.jsxs("p",{className:"text-xs font-medium text-muted-foreground uppercase tracking-wider",children:["Client Media Assets (",J.length,")"]}),e.jsxs(F,{variant:"outline",size:"sm",onClick:async()=>{const t=await Promise.all(J.map(async i=>{const{data:l}=await k.storage.from("client-media").createSignedUrl(i.file_path,3600);return(l==null?void 0:l.signedUrl)||""}));await navigator.clipboard.writeText(t.filter(Boolean).join(` 1985`)),x.success("All media URLs copied to clipboard!")},children:[e.jsx(Ye,{className:"w-3.5 h-3.5 mr-1"})," Copy All URLs"]})]}),e.jsx("div",{className:"grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-3",children:J.map(t=>{var l;const i=(l=t.file_type)==null?void 0:l.startsWith("image/");return e.jsxs("div",{className:"group relative rounded-md border bg-muted/30 overflow-hidden",children:[i?e.jsx(wt,{filePath:t.file_path,fileName:t.file_name}):e.jsx("div",{className:"aspect-square flex items-center justify-center",children:e.jsx(Ce,{className:"w-8 h-8 text-muted-foreground"})}),e.jsxs("div",{className:"p-2",children:[e.jsx("p",{className:"text-[10px] text-muted-foreground truncate",children:t.file_name}),t.category&&e.jsx("p",{className:"text-[9px] text-muted-foreground
1985/60",children:t.category})]}),e.jsxs("div",{className:"absolute top-1 right-1 flex gap-1 opacity-0 group-hover:opacity-100 transition-opacity",children:[e.jsx("button",{className:"p-1 rounded bg-background/80 hover:bg-background shadow-sm",title:"Copy URL",onClick:async()=>{const{data:n}=await k.storage.from("client-media").createSignedUrl(t.file_path,3600);n!=null&&n.signedUrl&&(await navigator.clipboard.writeText(n.signedUrl),x.success("URL copied!"))},children:e.jsx(Ve,{className:"w-3 h-3"})}),e.jsx("button",{className:"p-1 rounded bg-background/80 hover:bg-background shadow-sm",title:"Download",onClick:async()=>{const{data:n}=await k.storage.from("client-media").createSignedUrl(t.file_path,3600);if(n!=null&&n.signedUrl){const r=document.createElement("a");r.href=n.signedUrl,r.download=t.file_name,r.click()}},children:e.jsx(Le,{className:"w-3 h-3"})})]})]},t.id)})})]}),e.jsx(xt,{clientId:y,clientName:m.clientName}),e.jsxs("div",{className:"mt-4 p-4 rounded-lg border bg-muted/30",children:[e.jsx("p",{className:"text-xs font-medium mb-2",children:"How to use"}),e.jsxs("ul",{className:"text-xs text-muted-foreground space-y-1 list-disc list-inside",children:[e.jsx("li",{children:"Copy each section and feed to your AI website builder (Claude, GPT, v0.dev, Lovable)"}),e.jsx("li",{children:'Start with "Brand Identity" to ground the AI in who the client is'}),e.jsx("li",{children:'Use "Homepage Copy" for exact text â no improvisation needed'}),e.jsx("li",{children:'Download client media from "Imagery" section for real assets'}),e.jsx("li",{children:"Iterate section by section for best results"})]})]})]})]})})]})}export{ts as default};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.