{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "hero-magazine",
  "type": "registry:block",
  "title": "Editorial magazine hero",
  "description": "Issue-style masthead, cover story with image and headline, and a numbered contents column of linked stories.",
  "author": "StoreKit <hello@storekit.dev>",
  "categories": [
    "hero",
    "any"
  ],
  "dependencies": [
    "motion",
    "lucide-react"
  ],
  "registryDependencies": [
    "https://storekit-eight.vercel.app/r/cn.json",
    "https://storekit-eight.vercel.app/r/sk-analytics.json"
  ],
  "files": [
    {
      "path": "hero/hero-magazine.tsx",
      "content": "\"use client\"\n\nimport { motion, useReducedMotion } from \"motion/react\"\nimport { ArrowRight } from \"lucide-react\"\nimport { cn } from \"@/components/storekit/lib/cn\"\nimport { useSkBlock } from \"@/components/storekit/lib/sk-analytics\"\n\n/* Editorial magazine hero. Reads like the cover of an issue: a masthead\n   rule with the issue number and season, a cover story with a big image and\n   headline, and a contents column of shorter stories with kicker, title and\n   read time. Every story is one link. The contents column numbers its items\n   like a table of contents. On mobile the cover leads and the contents list\n   follows as a ruled list. */\n\nconst EASE = [0.23, 1, 0.32, 1] as const\n\nexport type Story = { kicker?: string; title: string; dek?: string; href: string; image?: string; readTime?: string; focus?: string }\n\nconst COVER: Story = {\n  kicker: \"Cover story\",\n  title: \"The slow morning, and why it beats a perfect routine\",\n  dek: \"Three dietitians on the small habits that actually stick, and the ones you can drop.\",\n  href: \"#\",\n  image: \"/placeholder.webp\",\n  readTime: \"8 min read\",\n}\n\nconst SAMPLE: Story[] = [\n  { kicker: \"Ingredients\", title: \"What 28 greens in one scoop really means\", href: \"#\", readTime: \"5 min\", image: \"/placeholder.webp\" },\n  { kicker: \"Sleep\", title: \"Magnesium, explained without the hype\", href: \"#\", readTime: \"4 min\", image: \"/placeholder.webp\" },\n  { kicker: \"Field notes\", title: \"Inside a third-party lab test\", href: \"#\", readTime: \"6 min\", image: \"/placeholder.webp\" },\n]\n\nexport function HeroMagazine({\n  masthead = \"The Journal\",\n  issue = \"Issue 07\",\n  season = \"Autumn 2026\",\n  cover = COVER,\n  stories = SAMPLE,\n  allHref = \"#\",\n  className,\n}: {\n  masthead?: string\n  issue?: string\n  season?: string\n  cover?: Story\n  stories?: Story[]\n  allHref?: string\n  className?: string\n}) {\n  const reduce = useReducedMotion()\n  const sk = useSkBlock(\"hero\", \"hero-magazine\")\n  const rise = (i: number) => ({\n    initial: { opacity: 0, y: reduce ? 0 : 10 },\n    animate: { opacity: 1, y: 0 },\n    transition: { duration: 0.55, ease: EASE, delay: reduce ? 0 : i * 0.07 },\n  })\n\n  return (\n    <section ref={sk.ref} {...sk.attrs} className={cn(\"bg-sk-paper text-sk-ink\", className)}>\n      <div className=\"mx-auto w-full max-w-6xl px-4 py-8 sm:px-8 sm:py-12\">\n        <motion.header {...rise(0)} className=\"flex items-baseline justify-between gap-4 border-b-2 border-sk-ink pb-3\">\n          <p className=\"font-sk-display text-[22px] font-semibold leading-none tracking-[-0.02em] sm:text-[28px]\">{masthead}</p>\n          <p className=\"flex gap-3 font-sk-mono text-[11px] uppercase tracking-[0.14em] text-sk-muted\">\n            <span>{issue}</span>\n            <span aria-hidden>/</span>\n            <span>{season}</span>\n          </p>\n        </motion.header>\n\n        <div className=\"mt-6 grid gap-8 lg:grid-cols-[1.55fr_1fr] lg:gap-10\">\n          <motion.a\n            {...rise(1)}\n            href={cover.href}\n            onClick={() => sk.emit(\"interact\", \"cover\")}\n            className=\"group block rounded-sk-card outline-none focus-visible:ring-2 focus-visible:ring-sk-accent focus-visible:ring-offset-4 focus-visible:ring-offset-sk-paper\"\n          >\n            {cover.image ? (\n              <div className=\"relative aspect-[4/3] overflow-hidden rounded-sk-card bg-sk-surface sm:aspect-[16/10]\">\n                <img src={cover.image} alt=\"\" className=\"absolute inset-0 h-full w-full object-cover transition-transform duration-[900ms] ease-sk-out group-hover:scale-[1.025]\" style={{ objectPosition: cover.focus }} />\n              </div>\n            ) : null}\n            {cover.kicker ? <p className=\"mt-5 font-sk-mono text-[11px] uppercase tracking-[0.14em] text-sk-accent\">{cover.kicker}</p> : null}\n            <h1 className=\"mt-2 text-balance font-sk-display font-semibold leading-[1.04] tracking-[-0.025em]\" style={{ fontSize: \"clamp(2rem, 4.4vw, 3.5rem)\" }}>\n              <span className=\"bg-[linear-gradient(currentColor,currentColor)] bg-[length:0%_2px] bg-left-bottom bg-no-repeat transition-[background-size] duration-500 ease-sk-out group-hover:bg-[length:100%_2px]\">\n                {cover.title}\n              </span>\n            </h1>\n            {cover.dek ? <p className=\"mt-3 max-w-xl text-[16px] leading-[1.5] text-sk-muted\">{cover.dek}</p> : null}\n            {cover.readTime ? <p className=\"mt-3 font-sk-mono text-[11px] uppercase tracking-[0.14em] text-sk-muted\">{cover.readTime}</p> : null}\n          </motion.a>\n\n          <motion.nav {...rise(2)} aria-label=\"In this issue\">\n            <p className=\"font-sk-mono text-[11px] uppercase tracking-[0.14em] text-sk-muted\">In this issue</p>\n            <ol className=\"mt-3 divide-y divide-sk-line border-y border-sk-line\">\n              {stories.map((s, i) => (\n                <li key={s.title}>\n                  <a\n                    href={s.href}\n                    onClick={() => sk.emit(\"interact\", \"story\", i)}\n                    className=\"group flex items-start gap-4 py-4 outline-none focus-visible:bg-sk-surface\"\n                  >\n                    <span className=\"w-6 shrink-0 pt-0.5 font-sk-mono text-[12px] tabular-nums text-sk-muted\">{String(i + 2).padStart(2, \"0\")}</span>\n                    <span className=\"min-w-0 flex-1\">\n                      {s.kicker ? <span className=\"block font-sk-mono text-[10px] uppercase tracking-[0.14em] text-sk-muted\">{s.kicker}</span> : null}\n                      <span className=\"mt-1 block text-balance font-sk-display text-[18px] font-semibold leading-[1.2] tracking-[-0.01em] underline decoration-transparent underline-offset-4 transition-[text-decoration-color] duration-200 group-hover:decoration-sk-ink/40\">\n                        {s.title}\n                      </span>\n                      {s.readTime ? <span className=\"mt-1.5 block text-[12px] text-sk-muted\">{s.readTime}</span> : null}\n                    </span>\n                    {s.image ? <img src={s.image} alt=\"\" className=\"h-16 w-16 shrink-0 rounded-sk-chip bg-sk-surface object-cover sm:h-20 sm:w-20\" style={{ objectPosition: s.focus }} /> : null}\n                  </a>\n                </li>\n              ))}\n            </ol>\n            <a\n              href={allHref}\n              onClick={() => sk.emit(\"interact\", \"all_stories\")}\n              className=\"group mt-4 inline-flex min-h-11 items-center gap-1.5 text-sm font-medium outline-none focus-visible:underline\"\n            >\n              Read the full issue\n              <ArrowRight size={15} aria-hidden className=\"transition-transform duration-300 ease-sk-out group-hover:translate-x-0.5\" />\n            </a>\n          </motion.nav>\n        </div>\n      </div>\n    </section>\n  )\n}\n",
      "type": "registry:block",
      "target": "components/storekit/hero/hero-magazine.tsx"
    }
  ],
  "meta": {
    "section": "hero",
    "variant": "magazine",
    "niche": [
      "any"
    ],
    "commerce": [
      "content"
    ],
    "previewHeight": 680
  }
}