{
  "id": "studio-agency",
  "name": "Studio agency",
  "description": "A complete editorial agency homepage with an oversized serif hero, selected case studies, a service ledger, studio story, approved testimonial and host-owned contact action.",
  "category": "Marketing",
  "blockIds": [],
  "style": "clean-saas",
  "registryId": "recipe-studio-agency",
  "componentName": "StudioAgencyRecipe",
  "componentSource": "content/recipe-components/studio-agency.tsx",
  "featured": true,
  "searchCategories": [
    "marketing"
  ],
  "tags": [
    "agency",
    "studio",
    "portfolio",
    "creative agency",
    "services",
    "complete landing page",
    "工作室",
    "设计机构",
    "作品集",
    "服务介绍",
    "完整页面"
  ],
  "source": {
    "name": "Foundry",
    "url": "https://github.com/tailthemes/foundry",
    "author": "WISE IT LLC",
    "license": "MIT",
    "revision": "cfdc5a64ab378122124d8e2ffc039f60109de3e4",
    "files": [
      "src/app/home.tsx",
      "src/components/site-header.tsx",
      "src/components/hero.tsx",
      "src/components/client-band.tsx",
      "src/components/selected-work.tsx",
      "src/components/services-ledger.tsx",
      "src/components/manifesto.tsx",
      "src/components/testimonial.tsx",
      "src/components/cta.tsx",
      "src/components/site-footer.tsx",
      "src/fixtures/foundry.ts",
      "src/theme.css",
      "src/assets/README.md",
      "src/components/ui/container.tsx",
      "src/components/ui/badge.tsx",
      "src/components/ui/plate.tsx",
      "src/components/ui/icons.tsx",
      "src/components/ui/button.tsx",
      "src/components/ui/section-heading.tsx",
      "src/assets/case-halcyon.jpg",
      "src/assets/case-marlow.jpg",
      "src/assets/case-verity.jpg",
      "src/assets/case-northbank.jpg"
    ],
    "licenseFile": "licenses/third-party/foundry-MIT.txt",
    "modifications": [
      "Adapted the complete homepage composition and original section order to portable React with typed host content, controlled empty defaults and explicitly labelled fictional demo fixtures.",
      "Replaced next/font and StaticImageData with system serif/sans/mono fonts and native images. Scoped palette/type styles to the recipe root and retained optional local theme controls.",
      "Embedded four original MIT-generated JPEG case plates as unchanged data URIs in a local TypeScript module; actual projects use host images or a layout-preserving placeholder. No fonts are redistributed.",
      "Replaced upstream application routes, mailto/phone/legal claims and simulated contact behaviour with valid local section anchors, optional host URLs and a host callback requiring explicit status:\"sent\" confirmation. Business contact actions are disabled in demo mode while local section anchors and native case disclosures remain usable."
    ]
  },
  "installUsage": "import StudioAgencyRecipe from \"@/components/uiblocks/recipe-studio-agency/recipe-studio-agency\";\n\nexport default function StudioPage() {\n  return (\n    <StudioAgencyRecipe\n      brand=\"Your studio\"\n      hero={{ title: \"Your studio positioning\", description: \"Your actual services and approach.\" }}\n      work={[]}\n      services={[]}\n      contact={{ title: \"Start a conversation\", href: \"/contact\", actionLabel: \"Contact our studio\" }}\n    />\n  );\n}",
  "demoUsage": "import StudioAgencyRecipe from \"@/components/uiblocks/recipe-studio-agency/recipe-studio-agency\";\n\nexport default function StudioDemo() {\n  return <StudioAgencyRecipe mode=\"demo\" />;\n}",
  "propsContract": [
    {
      "name": "mode, brand, brandMark, brandHref, availability, navigation",
      "description": "Controlled by default: no sample projects, claims or testimonials. The host owns real brand and destinations. Local default navigation targets existing section IDs; explicit mode=\"demo\" opts into labelled fictional Foundry content."
    },
    {
      "name": "hero, primaryAction, secondaryAction, facts, clientIntro, clients",
      "description": "Supply the actual positioning, primary links, facts and approved client names. Pass null to either hero action to hide it. Empty arrays stay empty in demo mode."
    },
    {
      "name": "workHeading, work, servicesHeading, services, servicesNote",
      "description": "Real projects support an optional host href, a local native detail disclosure, image {src,alt,width,height}, disciplines/year/outcome. Missing images preserve a visible placeholder; no customer picture is fabricated. Services support verified prices/durations/deliverables and optional approved proof."
    },
    {
      "name": "studioHeading, studioParagraphs, studioFacts, testimonialEyebrow, testimonial",
      "description": "Host-owned studio story, verified figures and approved quote. Set testimonial=null to suppress the fictional demo quote."
    },
    {
      "name": "contact, contactDetails, onContact",
      "description": "Controlled mode only: set contact.href to a real host destination, or provide onContact. The handler may return a promise and must explicitly return {status:\"sent\",message?}; pending, rejection, missing confirmation and retry are represented. No handler/href leaves the action disabled. Demo mode always disables the contact business action, labels it as local/no-send and never invokes onContact, even if supplied; section anchors and case disclosures remain available."
    },
    {
      "name": "footerDescription, footerColumns, legalText, legalLink, theme, className",
      "description": "Set footer content and genuine legal/host links. Theme inherits the host dark class by default; its optional local toggle changes only the recipe wrapper. Explicit light/dark props lock the recipe theme. Scoped CSS and system fonts do not change the host theme or stylesheet."
    }
  ],
  "contentGuidelines": [
    "Retain the oversized serif hero, cool paper canvas, coral accent, 1152px measure, thin rules and full section order when adapting the layout.",
    "Replace all fictional Foundry clients, figures, prices, booking availability and testimonials with verified host content before publication. Controlled mode starts with empty collections.",
    "Original case JPEG bytes are embedded in a local TypeScript demo module under the upstream MIT grant, and each demo image is labelled as AI-generated. Supply your own image props for real projects; missing controlled images display placeholders.",
    "System serif, sans and monospace replace the original Fraunces/Archivo/IBM Plex Mono webfonts. No upstream fonts are redistributed, and no Next or router runtime is required.",
    "In controlled mode, connect contact.href or an authenticated onContact host action. A promise resolution without {status:\"sent\"} is unconfirmed, and rejected requests can be retried. Demo contact actions are disabled and never call business handlers.",
    "Native project disclosures, menu Escape/focus return, theme controls and long Chinese copy must be checked at desktop and 390px mobile widths."
  ],
  "prompt": "Build an agency or studio website using UIBlocks studio-agency, adapted from the MIT Foundry complete homepage. Inspect get_recipe and get_preview, install recipe-studio-agency once, and import StudioAgencyRecipe through the host components alias. Preserve the editorial serif hierarchy, cool blue paper, coral accent, selected-work ledger, services, studio story, testimonial and closing contact section. Default to controlled mode with actual brand, copy, verified work/services/facts, approved testimonials, host image URLs and real navigation. Set contact.href or provide onContact that explicitly returns {status:\"sent\"} only after the authenticated host service confirms success. Keep empty, pending, rejected, unconfirmed and retry states honest. Explicit mode=\"demo\" shows labelled fictional fixtures and MIT AI-generated case plates. Preserve upstream MIT notice, host routes and aliases; check keyboard, reduced motion, long Chinese copy and mobile layout.",
  "origin": "external",
  "preview": "/preview/recipes/studio-agency",
  "screenshot": "/previews/recipe-studio-agency.png",
  "screenshotMetadata": {
    "renderer": "Chromium",
    "id": "recipe-studio-agency",
    "image": "recipe-studio-agency.png",
    "sourceFiles": [
      "app/globals.css",
      "components/brand.tsx",
      "components/copy-button.tsx",
      "components/footer.tsx",
      "components/header.tsx",
      "components/recipes/recipe-preview.tsx",
      "components/registry-setup.tsx",
      "components/seo-jsonld.tsx",
      "components/theme-toggle.tsx",
      "components/ui/button.tsx",
      "components/ui/chart.tsx",
      "components/ui/dialog.tsx",
      "components/ui/dropdown-menu.tsx",
      "components/ui/input-group.tsx",
      "components/ui/input.tsx",
      "components/ui/separator.tsx",
      "components/ui/sheet.tsx",
      "components/ui/sidebar.tsx",
      "components/ui/skeleton.tsx",
      "components/ui/sonner.tsx",
      "components/ui/table.tsx",
      "components/ui/textarea.tsx",
      "components/ui/tooltip.tsx",
      "config.ts",
      "content/blocks-metadata.ts",
      "content/catalog.ts",
      "content/community-blocks.ts",
      "content/components/dashboard/dashboard-01/customers-table.tsx",
      "content/components/dashboard/dashboard-01/dashboard-charts.tsx",
      "content/components/marketing/faq-01.tsx",
      "content/components/marketing/features-01.tsx",
      "content/components/marketing/footer-01.tsx",
      "content/components/marketing/hero-01.tsx",
      "content/components/marketing/logo-cloud-01.tsx",
      "content/components/marketing/navigation-01.tsx",
      "content/components/marketing/pricing-01.tsx",
      "content/components/workspace/results-gallery-01.tsx",
      "content/components/workspace/task-queue-01.tsx",
      "content/components/workspace/upload-workflow-01.tsx",
      "content/components/workspace/usage-panel-01.tsx",
      "content/components/workspace/workspace-header-01.tsx",
      "content/declarations.ts",
      "content/product-launch-recipe.ts",
      "content/recipe-components/product-launch-art.tsx",
      "content/recipe-components/product-launch.tsx",
      "content/recipe-components/saas-dashboard.tsx",
      "content/recipe-components/studio-agency.tsx",
      "content/recipe-components/studio-agency/demo-assets.ts",
      "content/recipe-components/studio-agency/demo.ts",
      "content/recipe-components/studio-agency/styles.ts",
      "content/recipe-components/studio-agency/types.ts",
      "content/recipe-components/team-inbox.tsx",
      "content/recipe-components/tool-landing.tsx",
      "content/recipe-components/tool-workspace.tsx",
      "content/recipes.ts",
      "content/studio-agency-recipe.ts",
      "content/template-recipes.ts",
      "hooks/use-mobile.ts",
      "hooks/use-registry-origin.ts",
      "lib/google-analytics.ts",
      "lib/utils.ts",
      "package-lock.json",
      "package.json",
      "postcss.config.mjs",
      "public/icon.svg",
      "public/opengraph-image.png",
      "scripts/capture-previews.mjs",
      "scripts/preview-provenance.mjs",
      "src/lib/head.ts",
      "src/routes/__root.tsx",
      "src/routes/preview.recipes.$recipeId.tsx",
      "vite.config.ts"
    ],
    "sourceHash": "dc70e606353c852d8a960ab8430bcd474e219cbfe5494466123598393e7604ba",
    "imageHash": "4f5e73de40a35118017b61592f638f7b6ac53324ada9e0ed8d04d7fb279996f5",
    "capturedAt": "2026-10-30T09:46:24.928Z",
    "viewport": {
      "width": 1200,
      "height": 800
    },
    "dimensions": {
      "width": 1200,
      "height": 7981
    },
    "state": "demo"
  },
  "url": "/recipes/studio-agency",
  "registry": "/r/recipe-studio-agency.json",
  "install": {
    "direct": "npx shadcn@latest add https://uiblocks.org/r/recipe-studio-agency.json",
    "namespaced": "npx shadcn@latest add @uiblocks/recipe-studio-agency",
    "registryConfig": {
      "registries": {
        "@uiblocks": "https://uiblocks.org/r/{name}.json"
      }
    },
    "entry": "@components/uiblocks/recipe-studio-agency/recipe-studio-agency.tsx",
    "exportName": "default",
    "dependencies": [
      "lucide-react@0.577.0"
    ],
    "requirements": {
      "react": ">=19",
      "tailwind": ">=4"
    },
    "setup": [
      {
        "id": "project",
        "title": "Open your existing React project",
        "description": "Use React 19+, TypeScript/TSX, and a working Tailwind CSS 4 build. Keep the project's existing router, dependencies, and global stylesheet."
      },
      {
        "id": "shadcn",
        "title": "Check components.json before installing",
        "description": "Reuse an existing components.json. Its aliases.components must resolve in TypeScript and the bundler, and tailwind.css must point to the stylesheet your app loads. Do not reinitialize an already configured project.",
        "command": "npx shadcn@latest init",
        "when": "Only if components.json is missing; run inside the existing app and follow its framework setup."
      },
      {
        "id": "styles",
        "title": "Include the installed sources in Tailwind",
        "description": "Keep the host's standard shadcn theme variables, Tailwind @theme mappings, and base border styles loaded (background, foreground, border, sidebar, and chart tokens). Ensure Tailwind scans the actual installed components directory. Restricted source(none), ignored paths, and monorepos may need an @source path relative to the stylesheet. For theme='dark', use a class-based dark variant in the host CSS."
      },
      {
        "id": "import",
        "title": "Import through your configured components alias",
        "description": "The @components/ entry is a registry target placeholder, not a JavaScript import. Replace the example's @/components prefix with components.json aliases.components, verify the file printed by the CLI, and mount it in an existing host route."
      }
    ],
    "usage": "import StudioAgencyRecipe from \"@/components/uiblocks/recipe-studio-agency/recipe-studio-agency\";\n\nexport default function StudioPage() {\n  return (\n    <StudioAgencyRecipe\n      brand=\"Your studio\"\n      hero={{ title: \"Your studio positioning\", description: \"Your actual services and approach.\" }}\n      work={[]}\n      services={[]}\n      contact={{ title: \"Start a conversation\", href: \"/contact\", actionLabel: \"Contact our studio\" }}\n    />\n  );\n}",
    "demoUsage": "import StudioAgencyRecipe from \"@/components/uiblocks/recipe-studio-agency/recipe-studio-agency\";\n\nexport default function StudioDemo() {\n  return <StudioAgencyRecipe mode=\"demo\" />;\n}"
  },
  "compositionSource": {
    "language": "tsx",
    "componentName": "StudioAgencyRecipe",
    "referenceOnly": false,
    "installedEntry": "@components/uiblocks/recipe-studio-agency/recipe-studio-agency.tsx",
    "content": "\"use client\";\n\n/**\n * Studio Agency: adapted from the complete Foundry homepage by TailThemes.\n * Copyright (c) 2026 WISE IT LLC. MIT License; see foundry-MIT.txt in the bundle.\n * Upstream: https://github.com/tailthemes/foundry/blob/cfdc5a64ab378122124d8e2ffc039f60109de3e4/src/app/home.tsx\n * Sections: src/components/{site-header,hero,client-band,selected-work,\n * services-ledger,manifesto,testimonial,cta,site-footer}.tsx at the same revision.\n * Adaptations: portable React/native elements and scoped theme; system serif,\n * sans and mono instead of next/font and bundled OFL fonts; host-owned content,\n * links and explicit contact confirmation; fictional fixtures only in demo mode;\n * original MIT-generated case plates embedded as data URIs for registry portability.\n */\nimport { ArrowRight, ArrowUpRight, Menu, Moon, Sun, X } from \"lucide-react\";\nimport { useEffect, useId, useRef, useState } from \"react\";\nimport {\n  demoClients,\n  demoContactDetails,\n  demoFacts,\n  demoServices,\n  demoStudioFacts,\n  demoStudioParagraphs,\n  demoTestimonial,\n  demoWork,\n} from \"./shared/content/recipe-components/studio-agency/demo\";\nimport { studioAgencyStyles } from \"./shared/content/recipe-components/studio-agency/styles\";\nimport type {\n  StudioAgencyContactResult,\n  StudioAgencyFact,\n  StudioAgencyHeading,\n  StudioAgencyLink,\n  StudioAgencyRecipeProps,\n  StudioAgencyTestimonial,\n} from \"./shared/content/recipe-components/studio-agency/types\";\n\nexport type * from \"./shared/content/recipe-components/studio-agency/types\";\n\nconst container = \"mx-auto w-full max-w-6xl px-5 sm:px-8 lg:px-10\";\nconst sectionSpace = \"py-20 sm:py-28 lg:py-32\";\nconst emptyStyle =\n  \"sa-rule sa-muted-text border border-dashed p-8 text-sm leading-7\";\n\n/** A successful contact UI requires an explicit result from the host service. */\nexport async function confirmStudioAgencyContact(\n  onContact: NonNullable<StudioAgencyRecipeProps[\"onContact\"]>\n): Promise<StudioAgencyContactResult> {\n  const result = await onContact();\n  if (result?.status !== \"sent\")\n    throw new Error(\"The host did not confirm the contact request. Try again.\");\n  return result;\n}\n\nfunction Action({\n  link,\n  secondary = false,\n}: {\n  link: StudioAgencyLink;\n  secondary?: boolean;\n}) {\n  return (\n    <a\n      className={`sa-button ${secondary ? \"sa-button-secondary\" : \"\"}`}\n      href={link.href}\n    >\n      {link.label}\n      {!secondary && (\n        <ArrowRight\n          aria-hidden=\"true\"\n          className=\"size-4 shrink-0\"\n          strokeWidth={1.5}\n        />\n      )}\n    </a>\n  );\n}\n\nfunction BrandMark() {\n  return (\n    <svg\n      aria-hidden=\"true\"\n      className=\"size-6 shrink-0\"\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      stroke=\"currentColor\"\n      strokeWidth=\"1.5\"\n    >\n      <path d=\"M5 4h14v16H5zM5 9h10M5 14h6\" />\n    </svg>\n  );\n}\n\nfunction Heading({ heading }: { heading: StudioAgencyHeading }) {\n  return (\n    <div className=\"flex flex-col gap-6 lg:flex-row lg:items-end lg:justify-between lg:gap-12\">\n      <div className=\"min-w-0 max-w-3xl\">\n        {heading.eyebrow && (\n          <p className=\"sa-label sa-eyebrow\">{heading.eyebrow}</p>\n        )}\n        <h2 className=\"sa-display sa-h2 mt-5\">{heading.title}</h2>\n        {heading.description && (\n          <p className=\"sa-lead sa-muted-text mt-6 max-w-2xl\">\n            {heading.description}\n          </p>\n        )}\n      </div>\n      {heading.action && (\n        <a\n          className=\"sa-link sa-small inline-flex min-h-11 min-w-0 items-center gap-2 self-start lg:max-w-60 lg:self-end\"\n          href={heading.action.href}\n        >\n          {heading.action.label}\n          <ArrowRight\n            aria-hidden=\"true\"\n            className=\"size-4 shrink-0\"\n            strokeWidth={1.5}\n          />\n        </a>\n      )}\n    </div>\n  );\n}\n\nfunction Facts({\n  facts,\n  compact = false,\n}: {\n  facts: readonly StudioAgencyFact[];\n  compact?: boolean;\n}) {\n  if (!facts.length) return null;\n  return (\n    <dl\n      className={`sa-rule grid grid-cols-1 border-y sm:grid-cols-2 lg:grid-cols-4 ${compact ? \"mt-12\" : \"mt-16\"}`}\n    >\n      {facts.map((fact, index) => (\n        <div\n          className={`sa-rule min-w-0 border-b py-7 last:border-b-0 sm:px-5 ${index ? \"sm:border-l\" : \"\"}`}\n          key={`${fact.label}-${index}`}\n        >\n          <dt className=\"sa-label sa-muted-text\">{fact.label}</dt>\n          <dd\n            className={`sa-display mt-4 tabular-nums ${compact ? \"sa-h3\" : \"sa-figure\"}`}\n          >\n            {fact.value}\n          </dd>\n          {fact.note && (\n            <dd className=\"sa-small sa-muted-text mt-2\">{fact.note}</dd>\n          )}\n        </div>\n      ))}\n    </dl>\n  );\n}\n\nfunction Proof({\n  proof,\n  large = false,\n}: {\n  proof: StudioAgencyTestimonial;\n  large?: boolean;\n}) {\n  return (\n    <figure>\n      <blockquote className={large ? \"sa-display sa-h2\" : \"leading-7\"}>\n        <p>“{proof.quote}”</p>\n      </blockquote>\n      <figcaption\n        className={`flex min-w-0 items-center gap-4 ${large ? \"mt-10\" : \"mt-4\"}`}\n      >\n        {large && (\n          <span\n            aria-hidden=\"true\"\n            className=\"sa-accent sa-ink sa-label grid size-12 shrink-0 place-items-center border border-[var(--sa-border)]\"\n          >\n            {proof.name\n              .split(/\\s+/)\n              .filter(Boolean)\n              .slice(0, 2)\n              .map((word) => word[0])\n              .join(\"\")}\n          </span>\n        )}\n        <span className=\"sa-small min-w-0\">\n          <span className=\"block font-medium\">{proof.name}</span>\n          {proof.role && (\n            <span className=\"sa-muted-text block\">{proof.role}</span>\n          )}\n        </span>\n      </figcaption>\n    </figure>\n  );\n}\n\nexport default function StudioAgencyRecipe({\n  mode = \"controlled\",\n  brand,\n  brandMark,\n  brandHref,\n  availability,\n  navigation,\n  hero,\n  primaryAction,\n  secondaryAction,\n  facts,\n  clientIntro,\n  clients,\n  workHeading,\n  work,\n  servicesHeading,\n  services,\n  servicesNote,\n  studioHeading,\n  studioParagraphs,\n  studioFacts,\n  testimonialEyebrow = \"In their words\",\n  testimonial,\n  contact,\n  contactDetails,\n  onContact,\n  footerDescription,\n  footerColumns,\n  legalText,\n  legalLink,\n  theme = \"inherit\",\n  className,\n}: StudioAgencyRecipeProps) {\n  const demo = mode === \"demo\";\n  const prefix = `studio-${useId().replaceAll(\":\", \"\")}`;\n  const id = (section: string) => `${prefix}-${section}`;\n  const anchor = (section: string) => `#${id(section)}`;\n  const root = useRef<HTMLDivElement>(null);\n  const menu = useRef<HTMLDetailsElement>(null);\n  const menuButton = useRef<HTMLElement>(null);\n  const [localTheme, setLocalTheme] = useState<\"inherit\" | \"light\" | \"dark\">(\n    \"inherit\"\n  );\n  const [dark, setDark] = useState(false);\n  const [contactState, setContactState] = useState<\n    \"idle\" | \"pending\" | \"sent\" | \"error\"\n  >(\"idle\");\n  const [contactMessage, setContactMessage] = useState(\"\");\n  const activeTheme = theme === \"inherit\" ? localTheme : theme;\n  useEffect(() => {\n    const update = () => {\n      if (root.current)\n        setDark(\n          getComputedStyle(root.current)\n            .getPropertyValue(\"--sa-scheme\")\n            .trim() === \"dark\"\n        );\n    };\n    update();\n    const observer = new MutationObserver(update);\n    observer.observe(document.documentElement, {\n      attributes: true,\n      attributeFilter: [\"class\"],\n    });\n    return () => observer.disconnect();\n  }, [activeTheme]);\n\n  const studioBrand = brand ?? (demo ? \"Foundry\" : \"Your studio\");\n  const heroCopy =\n    hero ??\n    (demo\n      ? {\n          eyebrow: \"Brand & digital studio\",\n          title: \"Brands that\",\n          accent: \"carry weight.\",\n          description:\n            \"We make identities, design systems and websites for companies that have outgrown the logo a founder drew in a hurry.\",\n        }\n      : {\n          eyebrow: \"Independent studio\",\n          title: \"Your studio,\",\n          accent: \"clearly presented.\",\n          description:\n            \"Supply your studio's positioning, selected work and services through the page props.\",\n        });\n  const shownFacts = facts ?? (demo ? demoFacts : []);\n  const shownClients = clients ?? (demo ? demoClients : []);\n  const shownWork = work ?? (demo ? demoWork : []);\n  const shownServices = services ?? (demo ? demoServices : []);\n  const paragraphs = studioParagraphs ?? (demo ? demoStudioParagraphs : []);\n  const shownStudioFacts = studioFacts ?? (demo ? demoStudioFacts : []);\n  const quote =\n    testimonial === undefined ? (demo ? demoTestimonial : null) : testimonial;\n  const shownContactDetails =\n    contactDetails ?? (demo ? demoContactDetails : []);\n  const workCopy = workHeading ?? {\n    eyebrow: \"Selected work\",\n    title: demo\n      ? \"Four projects that explain the studio.\"\n      : \"Your selected work.\",\n    description: demo\n      ? \"Every case names the client, the year, and the number the work moved.\"\n      : \"Present approved project summaries and the outcomes your team can verify.\",\n  };\n  const servicesCopy = servicesHeading ?? {\n    eyebrow: \"Services\",\n    title: demo\n      ? \"Six things we do, and what they cost.\"\n      : \"Your services, clearly set out.\",\n    description: demo\n      ? \"Illustrative starting prices, fixed after a paid discovery.\"\n      : \"Describe scope, deliverables and verified pricing in your own words.\",\n  };\n  const studioCopy = studioHeading ?? {\n    eyebrow: \"The studio\",\n    title: demo\n      ? \"We sell the twenty minutes after the reveal.\"\n      : \"The people and principles behind the work.\",\n  };\n  const contactCopy = contact ?? {\n    eyebrow: \"New business\",\n    title: \"Tell us what you're building.\",\n    description: demo\n      ? \"Bring the messy version — the half-finished deck, the name you are not sure about, the site you have stopped showing people. We will tell you honestly whether we are the right studio for it.\"\n      : \"Provide your contact destination or connect an explicit host action to start a conversation.\",\n  };\n  const nav = navigation ?? [\n    { label: \"Work\", href: anchor(\"work\") },\n    { label: \"Services\", href: anchor(\"services\") },\n    { label: \"Studio\", href: anchor(\"studio\") },\n    { label: \"Contact\", href: anchor(\"contact\") },\n  ];\n  const primary =\n    primaryAction === undefined\n      ? { label: \"Start a project\", href: anchor(\"contact\") }\n      : primaryAction;\n  const secondary =\n    secondaryAction === undefined\n      ? { label: \"See the ledger\", href: anchor(\"services\") }\n      : secondaryAction;\n  const columns = footerColumns ?? [\n    { title: \"Studio\", links: nav },\n    {\n      title: \"Services\",\n      links: shownServices.map((service) => ({\n        label: service.name,\n        href: anchor(`service-${service.id}`),\n      })),\n    },\n    {\n      title: \"Contact\",\n      links: contactCopy.href\n        ? [\n            {\n              label: contactCopy.actionLabel ?? \"Contact the studio\",\n              href: contactCopy.href,\n            },\n          ]\n        : [{ label: \"Project enquiries\", href: anchor(\"contact\") }],\n    },\n  ];\n  async function requestContact() {\n    if (demo || !onContact || contactState === \"pending\") return;\n    setContactState(\"pending\");\n    setContactMessage(\"\");\n    try {\n      const result = await confirmStudioAgencyContact(onContact);\n      setContactState(\"sent\");\n      setContactMessage(\n        result.message ?? \"The host confirmed your contact request.\"\n      );\n    } catch (failure) {\n      setContactState(\"error\");\n      setContactMessage(\n        failure instanceof Error\n          ? failure.message\n          : \"The contact request could not be completed. Try again.\"\n      );\n    }\n  }\n  function closeMenu() {\n    if (menu.current) menu.current.open = false;\n  }\n  const closeWithEscape = (event: {\n    key: string;\n    preventDefault: () => void;\n  }) => {\n    if (event.key === \"Escape\" && menu.current?.open) {\n      event.preventDefault();\n      closeMenu();\n      menuButton.current?.focus();\n    }\n  };\n\n  return (\n    <div\n      ref={root}\n      id={id(\"top\")}\n      className={`studio-agency ${className ?? \"\"}`}\n      data-studio-agency-mode={mode}\n      data-studio-theme={activeTheme}\n    >\n      <style>{studioAgencyStyles}</style>\n      <a\n        href={anchor(\"main\")}\n        className=\"sr-only focus:not-sr-only focus:absolute focus:left-4 focus:top-4 focus:z-50 focus:rounded focus:bg-[var(--sa-card)] focus:p-3\"\n      >\n        Skip to studio content\n      </a>\n      <header className=\"sa-rule sticky top-0 z-20 border-b bg-[var(--sa-bg)]/95 backdrop-blur-md\">\n        <div\n          className={`${container} relative flex min-h-16 items-center justify-between gap-3 py-3 sm:min-h-20 sm:gap-6`}\n        >\n          <a\n            href={brandHref ?? anchor(\"top\")}\n            className=\"sa-display sa-figure flex min-w-0 items-center gap-2.5\"\n          >\n            <span className=\"sa-ink shrink-0\">\n              {brandMark ?? <BrandMark />}\n            </span>\n            <span className=\"min-w-0\">{studioBrand}</span>\n          </a>\n          <nav\n            aria-label=\"Studio navigation\"\n            className=\"hidden min-w-0 lg:block\"\n          >\n            <ul className=\"flex flex-wrap items-center justify-center gap-1\">\n              {nav.map((link, index) => (\n                <li key={`${link.label}-${index}`}>\n                  <a\n                    className=\"sa-small sa-muted-text inline-flex min-h-10 items-center px-3 hover:underline\"\n                    href={link.href}\n                  >\n                    {link.label}\n                  </a>\n                </li>\n              ))}\n            </ul>\n          </nav>\n          <div className=\"flex shrink-0 items-center gap-2 sm:gap-3\">\n            {(availability ?? (demo ? \"Booking from November\" : \"\")) && (\n              <p className=\"sa-label sa-muted-text hidden max-w-44 items-center gap-2 xl:flex\">\n                <span\n                  aria-hidden=\"true\"\n                  className=\"size-1.5 shrink-0 rounded-full bg-[var(--sa-primary)]\"\n                />\n                {availability ?? \"Booking from November\"}\n              </p>\n            )}\n            {theme === \"inherit\" && (\n              <button\n                type=\"button\"\n                className=\"sa-rule grid size-10 shrink-0 place-items-center rounded border\"\n                aria-label=\"Toggle studio color theme\"\n                aria-pressed={dark}\n                onClick={() => setLocalTheme(dark ? \"light\" : \"dark\")}\n              >\n                {dark ? (\n                  <Sun\n                    aria-hidden=\"true\"\n                    className=\"size-5\"\n                    strokeWidth={1.5}\n                  />\n                ) : (\n                  <Moon\n                    aria-hidden=\"true\"\n                    className=\"size-5\"\n                    strokeWidth={1.5}\n                  />\n                )}\n              </button>\n            )}\n            {primary && (\n              <div className=\"hidden md:block\">\n                <Action link={primary} />\n              </div>\n            )}\n            <details\n              ref={menu}\n              className=\"sa-menu lg:hidden\"\n              onKeyDown={closeWithEscape}\n            >\n              <summary\n                ref={menuButton}\n                aria-label=\"Studio menu\"\n                className=\"sa-rule grid size-10 cursor-pointer place-items-center rounded border\"\n              >\n                <Menu aria-hidden=\"true\" className=\"sa-menu-closed size-5\" />\n                <X aria-hidden=\"true\" className=\"sa-menu-open size-5\" />\n              </summary>\n              <nav\n                aria-label=\"Studio mobile navigation\"\n                className=\"sa-rule sa-card absolute inset-x-0 top-full max-h-[70vh] overflow-auto border p-5 shadow-lg\"\n              >\n                <ul className=\"space-y-1\">\n                  {nav.map((link, index) => (\n                    <li key={`${link.label}-${index}`}>\n                      <a\n                        className=\"sa-small flex min-h-11 items-center py-2\"\n                        href={link.href}\n                        onClick={closeMenu}\n                      >\n                        {link.label}\n                      </a>\n                    </li>\n                  ))}\n                </ul>\n                {primary && (\n                  <a\n                    className=\"sa-button mt-4 w-full\"\n                    href={primary.href}\n                    onClick={closeMenu}\n                  >\n                    {primary.label}\n                    <ArrowRight aria-hidden=\"true\" className=\"size-4\" />\n                  </a>\n                )}\n              </nav>\n            </details>\n          </div>\n        </div>\n      </header>\n      {demo && (\n        <p className={`${container} sa-label sa-ink py-3`}>\n          Demo content · Fictional studio, clients, prices, outcomes and\n          testimonials. Case artwork is AI-generated.\n        </p>\n      )}\n      <main id={id(\"main\")}>\n        <section\n          aria-labelledby={id(\"hero-title\")}\n          className=\"sa-rule border-b\"\n        >\n          <div\n            className={`${container} pb-16 pt-12 sm:pb-24 sm:pt-16 lg:pb-28 lg:pt-20`}\n          >\n            {heroCopy.eyebrow && (\n              <p className=\"sa-label sa-eyebrow\">{heroCopy.eyebrow}</p>\n            )}\n            <h1 id={id(\"hero-title\")} className=\"sa-display sa-h1 mt-10\">\n              {heroCopy.title}\n              {heroCopy.accent && (\n                <>\n                  {\" \"}\n                  <span className=\"text-[var(--sa-primary)]\">\n                    {heroCopy.accent}\n                  </span>\n                </>\n              )}\n            </h1>\n            <div className=\"sa-rule mt-12 grid gap-8 border-t pt-10 lg:grid-cols-[7fr_5fr] lg:items-start lg:gap-16\">\n              <p className=\"sa-lead sa-muted-text max-w-2xl\">\n                {heroCopy.description}\n              </p>\n              <div className=\"flex min-w-0 flex-col gap-3 sm:flex-row lg:justify-end\">\n                {primary && <Action link={primary} />}\n                {secondary && <Action link={secondary} secondary />}\n              </div>\n            </div>\n            <Facts facts={shownFacts} />\n          </div>\n        </section>\n        <section\n          aria-label=\"Studio clients\"\n          className=\"sa-rule sa-muted border-b\"\n        >\n          <div className=\"mx-auto w-full max-w-7xl px-5 py-14 sm:px-8 sm:py-16 lg:px-10\">\n            <div className=\"flex flex-col gap-8 lg:flex-row lg:items-center lg:gap-14\">\n              <p className=\"sa-label sa-muted-text max-w-xs\">\n                {clientIntro ??\n                  (demo\n                    ? \"Thirty-one companies since 2016, eight of them twice\"\n                    : \"Host-approved clients and collaborators\")}\n              </p>\n              {shownClients.length ? (\n                <ul className=\"grid min-w-0 grow grid-cols-2 gap-x-8 gap-y-5 sm:grid-cols-3 lg:grid-cols-4\">\n                  {shownClients.map((client, index) => (\n                    <li\n                      className=\"sa-display sa-figure min-w-0\"\n                      key={`${client}-${index}`}\n                    >\n                      {client}\n                    </li>\n                  ))}\n                </ul>\n              ) : (\n                <p className=\"sa-small sa-muted-text\">\n                  No client names supplied.\n                </p>\n              )}\n            </div>\n          </div>\n        </section>\n        <section\n          id={id(\"work\")}\n          aria-label=\"Selected work\"\n          className=\"sa-rule scroll-mt-24 border-b\"\n        >\n          <div className={`${container} ${sectionSpace}`}>\n            <Heading heading={workCopy} />\n            {shownWork.length ? (\n              <ol className=\"sa-rule mt-14 border-t\">\n                {shownWork.map((project, index) => (\n                  <li key={project.id} className=\"sa-rule border-b\">\n                    <article className=\"grid gap-6 py-9 lg:grid-cols-[4rem_1fr_20rem] lg:gap-10 lg:px-4\">\n                      <span className=\"sa-label sa-ink text-lg\">\n                        {String(index + 1).padStart(2, \"0\")}\n                      </span>\n                      <div className=\"min-w-0\">\n                        <h3 className=\"sa-display sa-h3\">\n                          {project.href ? (\n                            <a className=\"hover:underline\" href={project.href}>\n                              {project.title}\n                            </a>\n                          ) : (\n                            project.title\n                          )}\n                        </h3>\n                        <p className=\"sa-muted-text mt-5 max-w-2xl leading-7\">\n                          {project.summary}\n                        </p>\n                        {!!project.disciplines?.length && (\n                          <ul className=\"mt-6 flex flex-wrap gap-2\">\n                            {project.disciplines.map((discipline, tag) => (\n                              <li\n                                className=\"sa-label sa-tag px-2.5 py-1\"\n                                key={`${discipline}-${tag}`}\n                              >\n                                {discipline}\n                              </li>\n                            ))}\n                          </ul>\n                        )}\n                        {!project.href && project.detail && (\n                          <details className=\"mt-6\">\n                            <summary className=\"sa-link sa-small cursor-pointer py-2\">\n                              {project.actionLabel ?? \"Read the case\"}\n                            </summary>\n                            <p className=\"sa-rule sa-muted-text mt-3 border-l pl-4 text-sm leading-7\">\n                              {project.detail}\n                            </p>\n                          </details>\n                        )}\n                      </div>\n                      <div className=\"min-w-0 lg:pt-2 lg:text-right\">\n                        {project.image ? (\n                          <div className=\"sa-rule sa-card mb-5 overflow-hidden rounded border p-1\">\n                            <img\n                              src={project.image.src}\n                              alt={project.image.alt}\n                              width={project.image.width ?? 1200}\n                              height={project.image.height ?? 800}\n                              loading=\"lazy\"\n                              decoding=\"async\"\n                              className=\"aspect-3/2 w-full object-cover\"\n                            />\n                          </div>\n                        ) : (\n                          <div className=\"sa-rule sa-muted sa-label sa-muted-text mb-5 grid aspect-3/2 w-full place-items-center rounded border p-6 text-center\">\n                            Host project image\n                          </div>\n                        )}\n                        {project.year && (\n                          <p className=\"sa-label sa-muted-text\">\n                            {project.year}\n                          </p>\n                        )}\n                        {project.outcome && (\n                          <p className=\"sa-small mt-3\">{project.outcome}</p>\n                        )}\n                        {project.href && (\n                          <a\n                            className=\"sa-link sa-small mt-4 inline-flex min-h-11 items-center gap-2\"\n                            href={project.href}\n                          >\n                            {project.actionLabel ?? \"Read the case\"}\n                            <ArrowUpRight\n                              aria-hidden=\"true\"\n                              className=\"size-4 shrink-0\"\n                              strokeWidth={1.5}\n                            />\n                          </a>\n                        )}\n                      </div>\n                    </article>\n                  </li>\n                ))}\n              </ol>\n            ) : (\n              <p className={`${emptyStyle} mt-14`}>\n                No projects supplied. Add approved work and images through the\n                work prop.\n              </p>\n            )}\n          </div>\n        </section>\n        <section\n          id={id(\"services\")}\n          aria-label=\"Studio services\"\n          className={`sa-rule sa-muted scroll-mt-24 border-b ${sectionSpace}`}\n        >\n          <div className={`${container} mb-14`}>\n            <Heading heading={servicesCopy} />\n          </div>\n          {shownServices.length ? (\n            <ol>\n              {shownServices.map((service, index) => (\n                <li\n                  id={id(`service-${service.id}`)}\n                  key={service.id}\n                  className={`scroll-mt-24 ${service.featured ? \"sa-accent\" : \"\"}`}\n                >\n                  <div\n                    className={`${container} sa-rule grid gap-5 border-b py-8 sm:py-10 lg:grid-cols-[3.5rem_1fr_16rem] lg:items-baseline lg:gap-10 ${index === 0 ? \"border-t\" : \"\"}`}\n                  >\n                    <span className=\"sa-label sa-ink text-lg\">\n                      {String(index + 1).padStart(2, \"0\")}\n                    </span>\n                    <div className=\"min-w-0\">\n                      <div className=\"flex flex-wrap items-baseline gap-x-4 gap-y-2\">\n                        <h3 className=\"sa-display sa-h3\">{service.name}</h3>\n                        {service.featured && (\n                          <span className=\"sa-label rounded bg-[var(--sa-primary)] px-2.5 py-1 text-[var(--sa-primary-fg)]\">\n                            {service.featuredLabel ?? \"Featured service\"}\n                          </span>\n                        )}\n                      </div>\n                      <p className=\"sa-muted-text mt-4 max-w-xl leading-7\">\n                        {service.summary}\n                      </p>\n                      {!!service.deliverables?.length && (\n                        <ul className=\"sa-label sa-muted-text mt-5 flex flex-wrap gap-x-5 gap-y-2\">\n                          {service.deliverables.map((deliverable, tag) => (\n                            <li key={`${deliverable}-${tag}`}>{deliverable}</li>\n                          ))}\n                        </ul>\n                      )}\n                      {service.proof && (\n                        <div className=\"sa-rule mt-6 max-w-xl border-t pt-5\">\n                          <Proof proof={service.proof} />\n                        </div>\n                      )}\n                    </div>\n                    <div className=\"flex min-w-0 flex-wrap items-baseline justify-between gap-4 lg:flex-col lg:items-end lg:gap-2\">\n                      {service.price && (\n                        <p className=\"sa-display sa-h3 tabular-nums\">\n                          {service.price}\n                        </p>\n                      )}\n                      {service.duration && (\n                        <p className=\"sa-label sa-muted-text\">\n                          {service.duration}\n                        </p>\n                      )}\n                    </div>\n                  </div>\n                </li>\n              ))}\n            </ol>\n          ) : (\n            <div className={container}>\n              <p className={emptyStyle}>\n                No services supplied. Add your scope, deliverables and verified\n                prices.\n              </p>\n            </div>\n          )}\n          {(servicesNote ??\n            (demo\n              ? \"Illustrative prices exclude taxes, print and third-party licences. Replace the example amounts and policies with your verified terms.\"\n              : \"\")) && (\n            <div className={container}>\n              <p className=\"sa-small sa-muted-text mt-8 max-w-2xl\">\n                {servicesNote ??\n                  \"Illustrative prices exclude taxes, print and third-party licences. Replace the example amounts and policies with your verified terms.\"}\n              </p>\n            </div>\n          )}\n        </section>\n        <section\n          id={id(\"studio\")}\n          aria-label=\"About the studio\"\n          className=\"sa-rule scroll-mt-24 border-b\"\n        >\n          <div className={`${container} py-16 sm:py-20 lg:py-24`}>\n            <div className=\"grid gap-12 lg:grid-cols-[5fr_7fr] lg:gap-20\">\n              <div className=\"lg:sticky lg:top-28 lg:self-start\">\n                {studioCopy.eyebrow && (\n                  <p className=\"sa-label sa-eyebrow\">{studioCopy.eyebrow}</p>\n                )}\n                <h2 className=\"sa-display sa-h2 mt-5\">{studioCopy.title}</h2>\n                {studioCopy.description && (\n                  <p className=\"sa-muted-text mt-6 leading-7\">\n                    {studioCopy.description}\n                  </p>\n                )}\n              </div>\n              <div className=\"min-w-0 max-w-2xl\">\n                {paragraphs.length ? (\n                  paragraphs.map((paragraph, index) => (\n                    <p\n                      className={`${index ? \"sa-muted-text mt-6 leading-7\" : \"sa-lead\"}`}\n                      key={index}\n                    >\n                      {paragraph}\n                    </p>\n                  ))\n                ) : (\n                  <p className={emptyStyle}>\n                    No studio story supplied. Describe your team and working\n                    principles.\n                  </p>\n                )}\n                <Facts facts={shownStudioFacts} compact />\n              </div>\n            </div>\n          </div>\n        </section>\n        <section\n          aria-label=\"Studio testimonial\"\n          className=\"sa-rule sa-muted border-b\"\n        >\n          <div className={`${container} ${sectionSpace}`}>\n            <p className=\"sa-label sa-eyebrow mb-6\">{testimonialEyebrow}</p>\n            {quote ? (\n              <div className=\"max-w-4xl\">\n                <Proof proof={quote} large />\n              </div>\n            ) : (\n              <p className={emptyStyle}>\n                No testimonial supplied. Add a quote approved for publication.\n              </p>\n            )}\n          </div>\n        </section>\n        <section\n          id={id(\"contact\")}\n          aria-label=\"Contact the studio\"\n          className=\"sa-rule scroll-mt-24 border-b\"\n        >\n          <div className={`${container} ${sectionSpace}`}>\n            <div className=\"sa-rule sa-accent rounded border p-8 sm:p-12 lg:p-16\">\n              <div className=\"grid gap-10 lg:grid-cols-[7fr_5fr] lg:items-end lg:gap-16\">\n                <div className=\"min-w-0 max-w-2xl\">\n                  {contactCopy.eyebrow && (\n                    <p className=\"sa-label sa-eyebrow\">{contactCopy.eyebrow}</p>\n                  )}\n                  <h2 className=\"sa-display sa-h2 mt-5\">{contactCopy.title}</h2>\n                  {contactCopy.description && (\n                    <p className=\"sa-lead sa-muted-text mt-6\">\n                      {contactCopy.description}\n                    </p>\n                  )}\n                  <div className=\"mt-9 flex flex-col gap-3 sm:flex-row\">\n                    {demo ? (\n                      <button\n                        className=\"sa-button\"\n                        type=\"button\"\n                        disabled\n                        title=\"Local demo only. No contact request is sent.\"\n                      >\n                        Demo contact · Not sent\n                        <ArrowRight\n                          aria-hidden=\"true\"\n                          className=\"size-4 shrink-0\"\n                        />\n                      </button>\n                    ) : onContact ? (\n                      <button\n                        className=\"sa-button\"\n                        type=\"button\"\n                        aria-busy={contactState === \"pending\"}\n                        disabled={contactState === \"pending\"}\n                        onClick={() => {\n                          void requestContact();\n                        }}\n                      >\n                        {contactState === \"pending\"\n                          ? \"Awaiting host confirmation…\"\n                          : (contactCopy.actionLabel ??\n                            \"Request a conversation\")}\n                        <ArrowRight\n                          aria-hidden=\"true\"\n                          className=\"size-4 shrink-0\"\n                        />\n                      </button>\n                    ) : contactCopy.href ? (\n                      <Action\n                        link={{\n                          label:\n                            contactCopy.actionLabel ?? \"Contact the studio\",\n                          href: contactCopy.href,\n                        }}\n                      />\n                    ) : (\n                      <button\n                        type=\"button\"\n                        className=\"sa-button\"\n                        disabled\n                        title=\"Supply contact.href or an onContact handler\"\n                      >\n                        {contactCopy.actionLabel ?? \"Contact the studio\"}\n                        <ArrowRight\n                          aria-hidden=\"true\"\n                          className=\"size-4 shrink-0\"\n                        />\n                      </button>\n                    )}\n                    <Action\n                      link={\n                        contactCopy.secondaryAction ?? {\n                          label: \"Read the ledger first\",\n                          href: anchor(\"services\"),\n                        }\n                      }\n                      secondary\n                    />\n                  </div>\n                  {demo && (\n                    <p className=\"sa-small sa-muted-text mt-4\">\n                      Local demo only. This page does not send contact requests.\n                    </p>\n                  )}\n                  {!demo && contactState === \"error\" && (\n                    <p\n                      role=\"alert\"\n                      className=\"mt-5 rounded border border-red-600/30 bg-red-50 p-4 text-sm leading-6 text-red-900\"\n                    >\n                      {contactMessage}\n                    </p>\n                  )}\n                  {!demo && contactState === \"sent\" && (\n                    <p\n                      role=\"status\"\n                      className=\"sa-rule sa-card mt-5 rounded border p-4 text-sm leading-6\"\n                    >\n                      {contactMessage}\n                    </p>\n                  )}\n                </div>\n                {shownContactDetails.length > 0 && (\n                  <dl className=\"sa-rule flex min-w-0 flex-col gap-5 border-t pt-8 lg:border-l lg:border-t-0 lg:pl-12 lg:pt-0\">\n                    {shownContactDetails.map((detail, index) => (\n                      <div key={`${detail.label}-${index}`}>\n                        <dt className=\"sa-label sa-muted-text\">\n                          {detail.label}\n                        </dt>\n                        <dd className=\"mt-2\">{detail.value}</dd>\n                        {detail.note && (\n                          <dd className=\"sa-small sa-muted-text mt-1\">\n                            {detail.note}\n                          </dd>\n                        )}\n                      </div>\n                    ))}\n                  </dl>\n                )}\n              </div>\n            </div>\n          </div>\n        </section>\n      </main>\n      <footer className=\"sa-rule sa-muted border-t\">\n        <div className={`${container} py-16 sm:py-20`}>\n          <div className=\"grid gap-12 lg:grid-cols-[1.2fr_2fr]\">\n            <div className=\"min-w-0 max-w-sm\">\n              <a\n                href={brandHref ?? anchor(\"top\")}\n                className=\"sa-display sa-figure inline-flex min-w-0 items-center gap-2.5\"\n              >\n                <span className=\"sa-ink shrink-0\">\n                  {brandMark ?? <BrandMark />}\n                </span>\n                <span className=\"min-w-0\">{studioBrand}</span>\n              </a>\n              <p className=\"sa-small sa-muted-text mt-5\">\n                {footerDescription ??\n                  (demo\n                    ? \"A twelve-person brand and digital studio in a railway arch. Identities, design systems and the websites that carry them. Four projects at a time, since 2016.\"\n                    : \"Supply your studio's introduction, legal details and links through the page props.\")}\n              </p>\n              {availability && (\n                <p className=\"sa-label sa-muted-text mt-6\">{availability}</p>\n              )}\n            </div>\n            <div className=\"grid min-w-0 gap-10 sm:grid-cols-3\">\n              {columns.map((column, index) => (\n                <nav\n                  aria-label={`Studio footer: ${column.title}`}\n                  key={`${column.title}-${index}`}\n                >\n                  <h2 className=\"sa-label\">{column.title}</h2>\n                  <ul className=\"mt-5 space-y-3\">\n                    {column.links.map((link, position) => (\n                      <li key={`${link.label}-${position}`}>\n                        <a\n                          className=\"sa-small sa-muted-text underline-offset-4 hover:underline\"\n                          href={link.href}\n                        >\n                          {link.label}\n                        </a>\n                      </li>\n                    ))}\n                  </ul>\n                </nav>\n              ))}\n            </div>\n          </div>\n          <div className=\"sa-rule sa-label sa-muted-text mt-14 flex flex-wrap items-center justify-between gap-4 border-t pt-8\">\n            <p>\n              {legalText ??\n                (demo\n                  ? \"© 2026 Foundry · Fictional studio demonstration.\"\n                  : \"Add your legal and copyright details.\")}\n            </p>\n            {legalLink && (\n              <a className=\"sa-link\" href={legalLink.href}>\n                {legalLink.label}\n              </a>\n            )}\n          </div>\n        </div>\n      </footer>\n    </div>\n  );\n}\n",
    "guidance": "Install this complete recipe with its single shadcn command, then import the component using your configured components alias and meta.entry. Matching blocks, helpers, and MIT notices are bundled. Pass your own copy, navigation, data, and callbacks through the published props. Recipes with meta.demoUsage require explicit demo mode for sample data or simulation; controlled mode delegates service work to your application."
  }
}
