diff --git a/README.md b/README.md index ef47aa1..55250c8 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Pin the immutable GitHub release: ```json { "dependencies": { - "@hraness/design-kit": "github:hraness/design-kit#v0.3.1", + "@hraness/design-kit": "github:hraness/design-kit#v0.4.0", "@hraness/ui": "github:hraness/ui#v0.4.7" } } @@ -48,52 +48,96 @@ Import narrower layers when the application does not need the full presentation ## Explain a technical product `product-marketing.css` is an opt-in narrative grammar for technical product -sites. It supplies outcome-led hero, ordered workflow, fact strip, install, -proof frame, narrative section, interface, trust-boundary, native question, and -call-to-action roles. The classes own responsive structure and semantics-facing -presentation. Products bind the `--hraness-marketing-*` roles to their own -palette, type, content, evidence, and action. +sites. It gives every Hraness product one typeface, one measured type scale, +sentence-case labels, hairline chrome, soft radii, and one accent color, so the +portfolio reads as one studio's work. The roles are a sticky site header, an +outcome-led hero with an optional product frame, three pillars, an install +panel, an ordered flow, fact and stat strips, narrative sections, numbered +primitives, interface and trust cards, attributed quotes, pricing, native +questions, a maker section, and a closing call to action. The classes own +responsive structure and semantics-facing presentation. Products bind the +`--hraness-marketing-*` roles to their own content and set one accent: + +```css +@import "@hraness/design-kit/styles.css"; + +.hraness-marketing-page { + --hraness-site-accent: oklch(0.55 0.21 262); + --hraness-site-accent-ink: #ffffff; +} +``` Static sites may render the documented classes directly. React sites can use the server-safe compositions from either React entry: ```tsx import { - MarketingFlow, + MarketingCallToAction, + MarketingPage, + MarketingPillars, + MarketingProofFrame, + MarketingSiteHeader, ProductHero, } from "@hraness/design-kit/react/server"; - - ), - }} - summary="The same owned job can be initialized, run, and inspected from a human or agent surface." -/> + + + + Relay printing one receipt in a terminal + + )} + heading="Move one job across every interface" + headingId="relay-title" + name="Relay" + summary="Relay runs the same job from a terminal, typed code, or a coding agent, and hands back one receipt you can read." + /> + + + ``` +`tone="accent"` on the hero or the call to action paints that role edge to +edge in the product accent. `layout="split"` or `"split-reverse"` on a +section places its heading group beside its body. `MarketingQuoteGrid` and +`MarketingPillars` render nothing for an empty list, so a site adds quotes +only when it has real, attributed ones. + +Homepage copy on this grammar follows a few rules on top of `STYLE.md`. The +headline is the reader's outcome in eight words or fewer, sentence case, no +period. The summary says what the product is, who it is for, and the one thing +it does differently in 40 words or fewer, in the second person. The `example` +is a concrete request a reader could make. Section headings are sentences with +periods. Limits stay, written the way a person would say them, and release +caveats move to the questions list. Words such as "bounded", "exact", +"authority", "custody", "immutable", and "inspectable" stay out of the hero and +leads. Every number has a date or a source, and no quote appears without an +attributed author who agreed to it. + Import only the grammar when a site owns its reset and tokens: ```css @@ -101,8 +145,9 @@ Import only the grammar when a site owns its reset and tokens: ``` The components render complete server HTML and add no clipboard, animation, or -analytics runtime. A product may enhance a command with its own accessible copy -control while keeping selectable text as the fallback. +analytics runtime. A +product may enhance a command with its own accessible copy control while +keeping selectable text as the fallback. ## Use application compositions diff --git a/dist/chunk-qaq1t8y3.js b/dist/chunk-5ggeyw1q.js similarity index 72% rename from dist/chunk-qaq1t8y3.js rename to dist/chunk-5ggeyw1q.js index d008c9e..af77d38 100644 --- a/dist/chunk-qaq1t8y3.js +++ b/dist/chunk-5ggeyw1q.js @@ -312,11 +312,14 @@ function Heading({ function childHeadingLevel(level) { return Math.min(level + 1, 6); } -function MarketingActions({ actions }) { +function MarketingActions({ + actions, + className +}) { if (actions.length === 0) return null; return /* @__PURE__ */ jsx2("div", { - className: "hraness-marketing-hero__actions", + className, children: actions.map((action, index) => /* @__PURE__ */ jsx2("a", { className: "hraness-marketing-action", "data-emphasis": action.emphasis ?? (index === 0 ? "primary" : "secondary"), @@ -325,6 +328,66 @@ function MarketingActions({ actions }) { }, `${action.href}-${action.label}`)) }); } +function MarketingPage({ + children, + className, + id +}) { + return /* @__PURE__ */ jsx2("div", { + className: classNames("hraness-marketing-page", className), + "data-hraness-marketing": "page", + id, + children + }); +} +function MarketingSiteHeader({ + action, + ariaLabel = "Site", + brand, + brandHref = "/", + brandLabel, + className, + links, + trailing +}) { + const brandProperties = brandLabel === undefined ? {} : { "aria-label": brandLabel }; + return /* @__PURE__ */ jsx2("header", { + className: classNames("hraness-marketing-header", className), + "data-hraness-marketing": "header", + children: /* @__PURE__ */ jsxs2("div", { + className: "hraness-marketing-header__inner", + children: [ + /* @__PURE__ */ jsx2("a", { + className: "hraness-marketing-header__brand", + href: brandHref, + ...brandProperties, + children: brand + }), + /* @__PURE__ */ jsx2("nav", { + "aria-label": ariaLabel, + className: "hraness-marketing-header__nav", + children: links.map((link) => /* @__PURE__ */ jsx2("a", { + "aria-current": link.current === true ? "page" : undefined, + href: link.href, + children: link.label + }, `${link.href}-${link.label}`)) + }), + action === undefined && trailing === undefined ? null : /* @__PURE__ */ jsxs2("div", { + className: "hraness-marketing-header__actions", + children: [ + action === undefined ? null : /* @__PURE__ */ jsx2("a", { + className: "hraness-marketing-action", + "data-emphasis": action.emphasis ?? "primary", + href: action.href, + children: action.label + }), + trailing + ] + }) + ] + }) + }); +} function MarketingFlow({ ariaLabel, className, @@ -372,6 +435,7 @@ function MarketingFacts({ return /* @__PURE__ */ jsx2("dl", { className: classNames("hraness-marketing-facts", className), "data-hraness-marketing": "facts", + style: { "--hraness-marketing-fact-columns": String(facts.length) }, children: facts.map((fact) => /* @__PURE__ */ jsxs2("div", { children: [ /* @__PURE__ */ jsx2("dt", { @@ -393,21 +457,27 @@ function MarketingFacts({ } function ProductHero({ actions = [], + align = "center", boundary, className, + example, eyebrow, facts = [], + frame, heading, headingId, headingLevel = 1, name, proof, - summary + summary, + tone = "paper" }) { return /* @__PURE__ */ jsxs2("header", { "aria-labelledby": headingId, className: classNames("hraness-marketing-hero", className), + "data-align": align, "data-hraness-marketing": "hero", + "data-tone": tone, children: [ /* @__PURE__ */ jsxs2("div", { className: "hraness-marketing-hero__copy", @@ -430,8 +500,13 @@ function ProductHero({ className: "hraness-marketing-hero__summary", children: summary }), + example === undefined ? null : /* @__PURE__ */ jsx2("p", { + className: "hraness-marketing-hero__example", + children: example + }), /* @__PURE__ */ jsx2(MarketingActions, { - actions + actions, + className: "hraness-marketing-hero__actions" }), boundary === undefined ? null : /* @__PURE__ */ jsx2("p", { className: "hraness-marketing-hero__boundary", @@ -439,6 +514,10 @@ function ProductHero({ }) ] }), + frame === undefined ? null : /* @__PURE__ */ jsx2("div", { + className: "hraness-marketing-hero__frame", + children: frame + }), proof === undefined ? null : /* @__PURE__ */ jsxs2("aside", { className: "hraness-marketing-proof", "aria-labelledby": `${headingId}-proof`, @@ -462,6 +541,30 @@ function ProductHero({ ] }); } +function MarketingPillars({ + ariaLabel, + className, + pillars +}) { + if (pillars.length === 0) + return null; + return /* @__PURE__ */ jsx2("dl", { + "aria-label": ariaLabel, + className: classNames("hraness-marketing-pillars", className), + "data-hraness-marketing": "pillars", + style: { "--hraness-marketing-pillar-columns": String(pillars.length) }, + children: pillars.map((pillar) => /* @__PURE__ */ jsxs2("div", { + children: [ + /* @__PURE__ */ jsx2("dt", { + children: pillar.label + }), + /* @__PURE__ */ jsx2("dd", { + children: pillar.summary + }) + ] + }, pillar.label)) + }); +} function MarketingInstallPanel({ children, className, @@ -503,20 +606,39 @@ function MarketingProofFrame({ caption, children, className, - credit + credit, + title }) { return /* @__PURE__ */ jsxs2("figure", { className: classNames("hraness-marketing-proof-frame", className), "data-hraness-marketing": "proof-frame", children: [ + title === undefined ? null : /* @__PURE__ */ jsxs2("div", { + "aria-hidden": "true", + className: "hraness-marketing-proof-frame__chrome", + children: [ + /* @__PURE__ */ jsxs2("span", { + className: "hraness-marketing-proof-frame__lights", + children: [ + /* @__PURE__ */ jsx2("span", {}), + /* @__PURE__ */ jsx2("span", {}), + /* @__PURE__ */ jsx2("span", {}) + ] + }), + /* @__PURE__ */ jsx2("span", { + className: "hraness-marketing-proof-frame__title", + children: title + }) + ] + }), /* @__PURE__ */ jsx2("div", { className: "hraness-marketing-proof-frame__content", children }), - /* @__PURE__ */ jsxs2("figcaption", { + caption === undefined && credit === undefined ? null : /* @__PURE__ */ jsxs2("figcaption", { className: "hraness-marketing-proof-frame__caption", children: [ - /* @__PURE__ */ jsx2("span", { + caption === undefined ? null : /* @__PURE__ */ jsx2("span", { children: caption }), credit === undefined ? null : /* @__PURE__ */ jsx2("small", { @@ -534,12 +656,15 @@ function MarketingSection({ headingId, headingLevel = 2, id, - label + label, + layout = "stack", + summary }) { return /* @__PURE__ */ jsxs2("section", { "aria-labelledby": headingId, className: classNames("hraness-marketing-section", className), "data-hraness-marketing": "section", + "data-layout": layout, id, children: [ /* @__PURE__ */ jsxs2("div", { @@ -554,6 +679,10 @@ function MarketingSection({ id: headingId, level: headingLevel, children: heading + }), + summary === undefined ? null : /* @__PURE__ */ jsx2("p", { + className: "hraness-marketing-section__summary", + children: summary }) ] }), @@ -591,6 +720,92 @@ function MarketingCollectionHeader({ ] }); } +function MarketingPrimitives({ + className, + heading, + headingId, + headingLevel = 2, + id, + items, + label, + summary +}) { + return /* @__PURE__ */ jsxs2("section", { + "aria-labelledby": headingId, + className: classNames("hraness-marketing-primitives", className), + "data-hraness-marketing": "primitives", + id, + children: [ + /* @__PURE__ */ jsx2(MarketingCollectionHeader, { + ...{ heading, headingId, headingLevel, label, summary }, + prefix: "primitives" + }), + /* @__PURE__ */ jsx2("ol", { + className: "hraness-marketing-primitives__list", + children: items.map((item, index) => /* @__PURE__ */ jsxs2("li", { + className: "hraness-marketing-primitive", + children: [ + /* @__PURE__ */ jsx2("span", { + "aria-hidden": "true", + className: "hraness-marketing-primitive__number", + children: String(index + 1).padStart(2, "0") + }), + /* @__PURE__ */ jsx2(Heading, { + className: "hraness-marketing-primitive__heading", + level: childHeadingLevel(headingLevel), + children: item.label + }), + /* @__PURE__ */ jsx2("p", { + children: item.summary + }), + item.example + ] + }, item.label)) + }) + ] + }); +} +function MarketingStatStrip({ + ariaLabel, + className, + source, + stats +}) { + if (stats.length === 0) + return null; + return /* @__PURE__ */ jsxs2("section", { + "aria-label": ariaLabel, + className: classNames("hraness-marketing-stats", className), + "data-hraness-marketing": "stats", + children: [ + /* @__PURE__ */ jsx2("dl", { + className: "hraness-marketing-stats__list", + style: { "--hraness-marketing-fact-columns": String(stats.length) }, + children: stats.map((stat) => /* @__PURE__ */ jsxs2("div", { + children: [ + /* @__PURE__ */ jsx2("dt", { + children: stat.label + }), + /* @__PURE__ */ jsxs2("dd", { + children: [ + /* @__PURE__ */ jsx2("strong", { + children: stat.value + }), + stat.detail === undefined ? null : /* @__PURE__ */ jsx2("span", { + children: stat.detail + }) + ] + }) + ] + }, `${stat.label}-${stat.value}`)) + }), + source === undefined ? null : /* @__PURE__ */ jsx2("p", { + className: "hraness-marketing-stats__source", + children: source + }) + ] + }); +} function MarketingInterfaceGrid({ className, heading, @@ -668,6 +883,127 @@ function MarketingTrustBoundary({ ] }); } +function MarketingQuoteGrid({ + className, + heading, + headingId, + headingLevel = 2, + id, + label, + quotes, + summary +}) { + if (quotes.length === 0) + return null; + return /* @__PURE__ */ jsxs2("section", { + "aria-labelledby": headingId, + className: classNames("hraness-marketing-quotes", className), + "data-hraness-marketing": "quotes", + id, + children: [ + /* @__PURE__ */ jsx2(MarketingCollectionHeader, { + ...{ heading, headingId, headingLevel, label, summary }, + prefix: "quotes" + }), + /* @__PURE__ */ jsx2("ul", { + className: "hraness-marketing-quote-grid", + children: quotes.map((entry) => /* @__PURE__ */ jsx2("li", { + children: /* @__PURE__ */ jsxs2("figure", { + className: "hraness-marketing-quote", + children: [ + /* @__PURE__ */ jsx2("blockquote", { + children: /* @__PURE__ */ jsx2("p", { + children: entry.quote + }) + }), + /* @__PURE__ */ jsxs2("figcaption", { + children: [ + /* @__PURE__ */ jsx2("strong", { + children: entry.name + }), + entry.role === undefined ? null : entry.href === undefined ? /* @__PURE__ */ jsx2("span", { + children: entry.role + }) : /* @__PURE__ */ jsx2("a", { + href: entry.href, + children: entry.role + }) + ] + }) + ] + }) + }, `${entry.name}-${entry.quote.slice(0, 24)}`)) + }) + ] + }); +} +function MarketingPricing({ + className, + heading, + headingId, + headingLevel = 2, + id, + label, + plans, + summary +}) { + return /* @__PURE__ */ jsxs2("section", { + "aria-labelledby": headingId, + className: classNames("hraness-marketing-pricing", className), + "data-hraness-marketing": "pricing", + id, + children: [ + /* @__PURE__ */ jsx2(MarketingCollectionHeader, { + ...{ heading, headingId, headingLevel, label, summary }, + prefix: "pricing" + }), + /* @__PURE__ */ jsx2("ul", { + className: "hraness-marketing-plan-grid", + children: plans.map((plan) => /* @__PURE__ */ jsxs2("li", { + className: "hraness-marketing-plan", + "data-emphasis": plan.emphasis ?? "secondary", + children: [ + /* @__PURE__ */ jsx2(Heading, { + className: "hraness-marketing-plan__name", + level: childHeadingLevel(headingLevel), + children: plan.name + }), + /* @__PURE__ */ jsxs2("p", { + className: "hraness-marketing-plan__price", + children: [ + /* @__PURE__ */ jsx2("strong", { + children: plan.price + }), + plan.period === undefined ? null : /* @__PURE__ */ jsx2("span", { + children: plan.period + }) + ] + }), + plan.summary === undefined ? null : /* @__PURE__ */ jsx2("p", { + className: "hraness-marketing-plan__summary", + children: plan.summary + }), + plan.features.length === 0 ? null : /* @__PURE__ */ jsx2("ul", { + className: "hraness-marketing-plan__features", + children: plan.features.map((feature) => /* @__PURE__ */ jsx2("li", { + children: feature + }, feature)) + }), + plan.action === undefined ? null : /* @__PURE__ */ jsx2("a", { + className: "hraness-marketing-action", + "data-emphasis": plan.action.emphasis ?? plan.emphasis ?? "secondary", + href: plan.action.href, + children: plan.action.label + }), + plan.note === undefined ? null : /* @__PURE__ */ jsx2("p", { + className: "hraness-marketing-plan__note", + children: plan.note + }) + ] + }, plan.name)) + }) + ] + }); +} function MarketingQuestionList({ className, heading, @@ -706,23 +1042,80 @@ function MarketingQuestionList({ ] }); } +function MarketingMaker({ + children, + className, + heading, + headingId, + headingLevel = 2, + id, + label, + links = [], + portrait +}) { + return /* @__PURE__ */ jsxs2("section", { + "aria-labelledby": headingId, + className: classNames("hraness-marketing-maker", className), + "data-hraness-marketing": "maker", + id, + children: [ + /* @__PURE__ */ jsxs2("header", { + className: "hraness-marketing-maker__header", + children: [ + portrait === undefined ? null : /* @__PURE__ */ jsx2("div", { + className: "hraness-marketing-maker__portrait", + children: portrait + }), + /* @__PURE__ */ jsx2("p", { + className: "hraness-marketing-maker__label", + children: label + }), + /* @__PURE__ */ jsx2(Heading, { + className: "hraness-marketing-maker__heading", + id: headingId, + level: headingLevel, + children: heading + }) + ] + }), + /* @__PURE__ */ jsxs2("div", { + className: "hraness-marketing-maker__body", + children: [ + children, + links.length === 0 ? null : /* @__PURE__ */ jsx2("ul", { + className: "hraness-marketing-maker__links", + children: links.map((link) => /* @__PURE__ */ jsx2("li", { + children: /* @__PURE__ */ jsx2("a", { + href: link.href, + children: link.label + }) + }, `${link.href}-${link.label}`)) + }) + ] + }) + ] + }); +} function MarketingCallToAction({ actions, className, eyebrow, + footnote, heading, headingId, headingLevel = 2, id, - summary + summary, + tone = "paper" }) { return /* @__PURE__ */ jsxs2("section", { "aria-labelledby": headingId, className: classNames("hraness-marketing-cta", className), "data-hraness-marketing": "cta", + "data-tone": tone, id, children: [ - /* @__PURE__ */ jsx2("p", { + eyebrow === undefined ? null : /* @__PURE__ */ jsx2("p", { className: "hraness-marketing-cta__eyebrow", children: eyebrow }), @@ -736,14 +1129,13 @@ function MarketingCallToAction({ className: "hraness-marketing-cta__summary", children: summary }), - /* @__PURE__ */ jsx2("div", { - className: "hraness-marketing-cta__actions", - children: actions.map((action, index) => /* @__PURE__ */ jsx2("a", { - className: "hraness-marketing-action", - "data-emphasis": action.emphasis ?? (index === 0 ? "primary" : "secondary"), - href: action.href, - children: action.label - }, `${action.href}-${action.label}`)) + /* @__PURE__ */ jsx2(MarketingActions, { + actions, + className: "hraness-marketing-cta__actions" + }), + footnote === undefined ? null : /* @__PURE__ */ jsx2("p", { + className: "hraness-marketing-cta__footnote", + children: footnote }) ] }); @@ -1154,4 +1546,4 @@ function ParticleHalo({ }); } -export { proceduralBackdropVariants, proceduralRecipeVersion, createProceduralBackdropRecipe, createParticleHaloRecipe, ProceduralBackdrop, MarketingFlow, MarketingFacts, ProductHero, MarketingInstallPanel, MarketingProofFrame, MarketingSection, MarketingInterfaceGrid, MarketingTrustBoundary, MarketingQuestionList, MarketingCallToAction, DitherSurface, TopBar, BottomBar, PageCanvas, DockedFooter, SyntaxCode, ParticleHalo }; +export { proceduralBackdropVariants, proceduralRecipeVersion, createProceduralBackdropRecipe, createParticleHaloRecipe, ProceduralBackdrop, MarketingPage, MarketingSiteHeader, MarketingFlow, MarketingFacts, ProductHero, MarketingPillars, MarketingInstallPanel, MarketingProofFrame, MarketingSection, MarketingPrimitives, MarketingStatStrip, MarketingInterfaceGrid, MarketingTrustBoundary, MarketingQuoteGrid, MarketingPricing, MarketingQuestionList, MarketingMaker, MarketingCallToAction, DitherSurface, TopBar, BottomBar, PageCanvas, DockedFooter, SyntaxCode, ParticleHalo }; diff --git a/dist/react/index.js b/dist/react/index.js index 17e3f72..36ca1b6 100644 --- a/dist/react/index.js +++ b/dist/react/index.js @@ -18,9 +18,17 @@ import { MarketingFlow, MarketingInstallPanel, MarketingInterfaceGrid, + MarketingMaker, + MarketingPage, + MarketingPillars, + MarketingPricing, + MarketingPrimitives, MarketingProofFrame, MarketingQuestionList, + MarketingQuoteGrid, MarketingSection, + MarketingSiteHeader, + MarketingStatStrip, MarketingTrustBoundary, PageCanvas, ParticleHalo, @@ -32,7 +40,7 @@ import { createProceduralBackdropRecipe, proceduralBackdropVariants, proceduralRecipeVersion -} from "../chunk-qaq1t8y3.js"; +} from "../chunk-5ggeyw1q.js"; import"../chunk-djxa5bgc.js"; import { __require @@ -2987,51 +2995,165 @@ function DesignSystemGallery({ children: "Product-marketing grammar" }), /* @__PURE__ */ jsxs11("div", { - className: "design-gallery__marketing", + className: "design-gallery__marketing hraness-marketing-page", children: [ + /* @__PURE__ */ jsx13(MarketingSiteHeader, { + action: { href: "#gallery-install", label: "Install Relay" }, + brand: "Relay", + links: [ + { current: true, href: "#marketing", label: "How it works" }, + { href: "#gallery-install", label: "Install" }, + { href: "#shells", label: "Docs" } + ] + }), /* @__PURE__ */ jsx13(ProductHero, { actions: [ { href: "#gallery-install", label: "Install Relay" }, { href: "#shells", label: "See the workspace" } ], - boundary: "Local CLI · version 1.2.3 · sync optional", + boundary: "Free for local use on macOS and Linux · version 1.2.3", className: "design-gallery__marketing-hero", - eyebrow: "Reference developer tool", + example: "Ask your agent to run the nightly job and show you the receipt.", + eyebrow: "A reference developer tool", facts: [ { detail: "One exact source.", label: "Input", value: "Repository" }, { detail: "One inspectable result.", label: "Output", value: "Receipt" }, { detail: "Terminal and typed code.", label: "Interfaces", value: "CLI + SDK" } ], - heading: "Move one exact job across every interface.", + frame: /* @__PURE__ */ jsx13(MarketingProofFrame, { + caption: "Receipt produced by the checked example.", + credit: "Captured 5 September 2026", + title: "relay run job-01", + children: /* @__PURE__ */ jsx13("pre", { + className: "design-gallery__marketing-command", + children: /* @__PURE__ */ jsx13("code", { + children: '{"status":"complete","job":"job-01","durationMs":412}' + }) + }) + }), + heading: "Move one job across every interface", headingId: "design-gallery-marketing-title", headingLevel: 3, name: "Relay", - proof: { - content: /* @__PURE__ */ jsx13(MarketingFlow, { - ariaLabel: "First Relay job", - steps: [ - { code: "relay init", detail: "Create one exact workspace.", label: "Initialize" }, - { code: "relay run job-01", detail: "Run the named job.", label: "Execute" }, - { code: "relay inspect job-01", detail: "Read the resulting receipt.", label: "Inspect" } - ] - }), - heading: "One job, three observable transitions", - kicker: "Working model" - }, - summary: "The same owned job can be initialized, run, and inspected from a human or agent surface." + summary: "Relay runs the same job from a terminal, typed code, or a coding agent, and hands back one receipt you can read." + }), + /* @__PURE__ */ jsx13(MarketingPillars, { + ariaLabel: "Relay in three points", + pillars: [ + { label: "Fast", summary: "Runs locally with no service in the loop." }, + { label: "Legible", summary: "Every run leaves a receipt you can open." }, + { label: "Yours", summary: "Source files and credentials stay on your machine." } + ] }), - /* @__PURE__ */ jsx13(MarketingInstallPanel, { + /* @__PURE__ */ jsxs11(MarketingInstallPanel, { eyebrow: "Local release", heading: "Install the verified tool.", headingId: "design-gallery-install-title", headingLevel: 3, id: "gallery-install", - children: /* @__PURE__ */ jsx13("pre", { - className: "design-gallery__marketing-command", - children: /* @__PURE__ */ jsx13("code", { - children: "bun add --global relay@1.2.3" + children: [ + /* @__PURE__ */ jsx13("pre", { + className: "design-gallery__marketing-command", + children: /* @__PURE__ */ jsx13("code", { + children: "bun add --global relay@1.2.3" + }) + }), + /* @__PURE__ */ jsx13(MarketingFlow, { + ariaLabel: "First Relay job", + steps: [ + { code: "relay init", detail: "Create one workspace.", label: "Initialize" }, + { code: "relay run job-01", detail: "Run the named job.", label: "Execute" }, + { code: "relay inspect job-01", detail: "Read the resulting receipt.", label: "Inspect" } + ] }) + ] + }), + /* @__PURE__ */ jsx13(MarketingPrimitives, { + heading: "Small building blocks for serious workflows.", + headingId: "design-gallery-primitives-title", + headingLevel: 3, + items: [ + { label: "Jobs", summary: "A named unit of work with declared inputs and outputs." }, + { label: "Receipts", summary: "The durable record of one run, readable by people and agents." }, + { label: "Schedules", summary: "Run a job on a cadence without another daemon." } + ], + label: "Primitives", + summary: "Relay gives agents a few durable objects to compose around the work in front of them." + }), + /* @__PURE__ */ jsx13(MarketingStatStrip, { + ariaLabel: "Relay usage", + source: "Counted from the public example repository on 5 September 2026.", + stats: [ + { label: "Example jobs", value: "12" }, + { label: "Interfaces", detail: "CLI, SDK, Agent Skill", value: "3" }, + { label: "Accounts required", value: "0" } + ] + }), + /* @__PURE__ */ jsx13(MarketingQuoteGrid, { + heading: "From the people building with it.", + headingId: "design-gallery-quotes-title", + headingLevel: 3, + label: "Quotes", + quotes: [ + { name: "A. Example", quote: "A placeholder quote for the gallery only. Product sites render real, attributed quotes or none.", role: "@example" } + ] + }), + /* @__PURE__ */ jsx13(MarketingPricing, { + heading: "Free for local use.", + headingId: "design-gallery-pricing-title", + headingLevel: 3, + label: "Pricing", + plans: [ + { + action: { href: "#gallery-install", label: "Install Relay" }, + emphasis: "primary", + features: ["Every feature", "Unlimited local jobs", "All future updates"], + name: "Local", + period: "forever", + price: "$0", + summary: "Full-featured, with no trial or expiration." + }, + { + action: { href: "#shells", label: "Read about sync" }, + features: ["Everything in Local", "Encrypted sync", "Priority email support"], + name: "Sync", + note: "Cancel any time.", + period: "per year", + price: "$49", + summary: "Keep receipts in step across your machines." + } + ] + }), + /* @__PURE__ */ jsx13(MarketingQuestionList, { + heading: "Questions before installing.", + headingId: "design-gallery-questions-title", + headingLevel: 3, + label: "Questions", + questions: [ + { answer: /* @__PURE__ */ jsx13("p", { + children: "No. The local workflow works without one." + }), question: "Does it require an account?" }, + { answer: /* @__PURE__ */ jsx13("p", { + children: "Nothing leaves your machine unless you turn on sync." + }), question: "Does it phone home?" } + ] + }), + /* @__PURE__ */ jsx13(MarketingMaker, { + heading: "Built by a reference maker.", + headingId: "design-gallery-maker-title", + headingLevel: 3, + label: "Built by", + links: [{ href: "#marketing", label: "Personal site" }], + children: /* @__PURE__ */ jsx13("p", { + children: "A short, plain-words bio: who made it, what they did before, where they are, and why this product exists." }) + }), + /* @__PURE__ */ jsx13(MarketingCallToAction, { + actions: [{ href: "#gallery-install", label: "Install Relay" }], + footnote: "Free for local use on macOS and Linux.", + heading: "Give every job the same room to run in.", + headingId: "design-gallery-cta-title", + headingLevel: 3 }) ] }) @@ -4262,9 +4384,17 @@ export { PageCanvas, NavigationRail, MarketingTrustBoundary, + MarketingStatStrip, + MarketingSiteHeader, MarketingSection, + MarketingQuoteGrid, MarketingQuestionList, MarketingProofFrame, + MarketingPrimitives, + MarketingPricing, + MarketingPillars, + MarketingPage, + MarketingMaker, MarketingInterfaceGrid, MarketingInstallPanel, MarketingFlow, diff --git a/dist/react/server.js b/dist/react/server.js index edea158..ea35d51 100644 --- a/dist/react/server.js +++ b/dist/react/server.js @@ -7,9 +7,17 @@ import { MarketingFlow, MarketingInstallPanel, MarketingInterfaceGrid, + MarketingMaker, + MarketingPage, + MarketingPillars, + MarketingPricing, + MarketingPrimitives, MarketingProofFrame, MarketingQuestionList, + MarketingQuoteGrid, MarketingSection, + MarketingSiteHeader, + MarketingStatStrip, MarketingTrustBoundary, PageCanvas, ParticleHalo, @@ -21,7 +29,7 @@ import { createProceduralBackdropRecipe, proceduralBackdropVariants, proceduralRecipeVersion -} from "../chunk-qaq1t8y3.js"; +} from "../chunk-5ggeyw1q.js"; import"../chunk-djxa5bgc.js"; import"../chunk-5gtx3pza.js"; export { @@ -36,9 +44,17 @@ export { ParticleHalo, PageCanvas, MarketingTrustBoundary, + MarketingStatStrip, + MarketingSiteHeader, MarketingSection, + MarketingQuoteGrid, MarketingQuestionList, MarketingProofFrame, + MarketingPrimitives, + MarketingPricing, + MarketingPillars, + MarketingPage, + MarketingMaker, MarketingInterfaceGrid, MarketingInstallPanel, MarketingFlow, diff --git a/package.json b/package.json index 7fbf1cc..532f7ee 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hraness/design-kit", - "version": "0.3.1", + "version": "0.4.0", "description": "Opinionated application compositions, charts, effects, and syntax presentation built on @hraness/ui.", "license": "MIT", "type": "module", diff --git a/portfolio-inventory.json b/portfolio-inventory.json index 2201b2e..d3e073a 100644 --- a/portfolio-inventory.json +++ b/portfolio-inventory.json @@ -6,7 +6,7 @@ "name": "@hraness/design-kit", "path": ".", "visibility": "public", - "version": "0.3.1" + "version": "0.4.0" } ], "contract": "hraness.portfolio-inventory/v1", diff --git a/src/design-gallery.css b/src/design-gallery.css index c83603a..d92493c 100644 --- a/src/design-gallery.css +++ b/src/design-gallery.css @@ -85,20 +85,21 @@ } .design-gallery__marketing { - display: grid; - gap: var(--space-8); - padding: clamp(var(--space-4), 3vw, var(--space-8)); + display: block; + overflow: clip; border: 1px solid var(--line); + border-radius: 0.875rem; background: var(--background); } +.design-gallery__marketing > .hraness-marketing-header { + position: static; +} + .design-gallery__marketing-command { max-inline-size: 100%; margin: 0; - padding: var(--space-4); overflow: auto; - background: var(--inverse); - color: var(--inverse-foreground); } .design-gallery__shell-preview { diff --git a/src/product-marketing.css b/src/product-marketing.css index 2b1b69e..c7c9c4c 100644 --- a/src/product-marketing.css +++ b/src/product-marketing.css @@ -1,96 +1,239 @@ @layer components.hraness-design-kit.legacy { +/** + * Product-marketing grammar + * + * An opt-in narrative grammar for technical product sites. One typeface, one + * measured type scale, sentence-case labels, hairline chrome, soft radii, and + * one accent per product. Roles: site header, hero with optional product + * frame, pillars, install, ordered flow, fact and stat strips, narrative + * section, primitives, interfaces, trust boundary, quotes, pricing, native + * questions, maker, and closing call to action. + * + * Products bind the `--hraness-marketing-*` custom properties on the marketing + * root (`.hraness-marketing-page`) or on any role element. Every role reads + * the same properties, so a site sets its accent once. + */ + :where( + .hraness-marketing-page, + .hraness-marketing-header, .hraness-marketing-hero, + .hraness-marketing-pillars, .hraness-marketing-install, .hraness-marketing-section, + .hraness-marketing-primitives, + .hraness-marketing-stats, .hraness-marketing-interfaces, .hraness-marketing-trust, + .hraness-marketing-quotes, + .hraness-marketing-pricing, .hraness-marketing-questions, - .hraness-marketing-cta + .hraness-marketing-maker, + .hraness-marketing-cta, + .hraness-marketing-proof-frame ) { --hraness-marketing-ink: var(--foreground, CanvasText); --hraness-marketing-muted: var(--muted, GrayText); - --hraness-marketing-line: var(--line, currentColor); + --hraness-marketing-background: var(--background, Canvas); --hraness-marketing-surface: var(--surface, Canvas); + --hraness-marketing-line: color-mix(in oklch, var(--hraness-marketing-ink) 12%, transparent); + --hraness-marketing-line-strong: color-mix(in oklch, var(--hraness-marketing-ink) 22%, transparent); --hraness-marketing-inverse: var(--inverse, CanvasText); --hraness-marketing-inverse-ink: var(--inverse-foreground, Canvas); - --hraness-marketing-accent: var(--primary, currentColor); + --hraness-marketing-accent: var(--hraness-site-accent, oklch(0.55 0.21 262)); + --hraness-marketing-accent-ink: var(--hraness-site-accent-ink, white); + --hraness-marketing-accent-soft: color-mix(in oklch, var(--hraness-marketing-accent) 10%, transparent); --hraness-marketing-text-font: var(--font-text, ui-sans-serif, system-ui, sans-serif); --hraness-marketing-heading-font: var(--font-heading, var(--hraness-marketing-text-font)); --hraness-marketing-mono-font: var(--font-mono, ui-monospace, monospace); - --hraness-marketing-measure: 74rem; - --hraness-marketing-copy-measure: 68ch; + --hraness-marketing-measure: 72rem; + --hraness-marketing-copy-measure: 40rem; + --hraness-marketing-prose-measure: 62ch; + --hraness-marketing-gutter: clamp(1.25rem, 4vw, 3rem); + --hraness-marketing-radius: 0.625rem; + --hraness-marketing-frame-radius: 0.875rem; --hraness-marketing-rule: 1px solid var(--hraness-marketing-line); + --hraness-marketing-shadow: + 0 1px 2px oklch(0 0 0 / 0.06), + 0 24px 48px -24px oklch(0 0 0 / 0.28); + --hraness-marketing-section-space: clamp(4rem, 9vw, 7.5rem); + --hraness-marketing-heading-weight: 500; + --hraness-marketing-heading-tracking: -0.022em; + --hraness-marketing-action-height: 2.75rem; color: var(--hraness-marketing-ink); + font-family: var(--hraness-marketing-text-font); } -.hraness-marketing-hero { - display: grid; - inline-size: min(100%, var(--hraness-marketing-measure)); - min-inline-size: 0; - margin-inline: auto; - gap: clamp(2rem, 5vw, 4.5rem); - grid-template-columns: minmax(0, 1.04fr) minmax(min(100%, 22rem), 0.96fr); +.hraness-marketing-page { + background: var(--hraness-marketing-background); + color: var(--hraness-marketing-ink); + font-size: 1rem; + line-height: 1.55; + overflow-x: clip; + -webkit-font-smoothing: antialiased; } -.hraness-marketing-hero__copy { - min-inline-size: 0; - align-self: center; - padding-block: clamp(1rem, 5vw, 4rem); +.hraness-marketing-page :where(p, li, dd) { + text-wrap: pretty; +} + +.hraness-marketing-page :where(a) { + color: inherit; + text-decoration-thickness: 1px; + text-underline-offset: 0.16em; } +.hraness-marketing-page :where(code, kbd, pre) { + font-family: var(--hraness-marketing-mono-font); +} + +.hraness-marketing-page :where(pre) { + max-inline-size: 100%; + margin: 0; + padding: 1rem 1.15rem; + overflow: auto; + border-radius: var(--hraness-marketing-radius); + background: var(--hraness-marketing-inverse); + color: var(--hraness-marketing-inverse-ink); + font-size: 0.85rem; + line-height: 1.6; + tab-size: 2; +} + +.hraness-marketing-page :where(:not(pre) > code) { + padding: 0.08em 0.38em; + border-radius: 0.3em; + background: color-mix(in oklch, var(--hraness-marketing-ink) 7%, transparent); + font-size: 0.9em; +} + +/* Labels: sentence case in the text face. Monospace stays with code. */ :where( .hraness-marketing-hero__eyebrow, .hraness-marketing-hero__name, - .hraness-marketing-hero__boundary, .hraness-marketing-proof__kicker, .hraness-marketing-install__eyebrow, .hraness-marketing-facts dt, + .hraness-marketing-stats dt, .hraness-marketing-section__label, + .hraness-marketing-primitives__label, .hraness-marketing-interfaces__label, .hraness-marketing-trust__label, + .hraness-marketing-quotes__label, + .hraness-marketing-pricing__label, .hraness-marketing-questions__label, + .hraness-marketing-maker__label, .hraness-marketing-cta__eyebrow ) { - font-family: var(--hraness-marketing-mono-font); - font-size: 0.72rem; - font-weight: 700; - letter-spacing: 0.1em; + margin: 0; + color: var(--hraness-marketing-muted); + font-family: var(--hraness-marketing-text-font); + font-size: 0.875rem; + font-weight: 500; + letter-spacing: 0; line-height: 1.4; - text-transform: uppercase; -} - -.hraness-marketing-hero__eyebrow { - margin: 0 0 clamp(2rem, 5vw, 4rem); - color: var(--hraness-marketing-accent); -} - -.hraness-marketing-hero__name { - margin: 0 0 0.65rem; + text-transform: none; } -.hraness-marketing-hero__heading { - max-inline-size: 11ch; +/* Shared heading recipe. */ +:where( + .hraness-marketing-hero__heading, + .hraness-marketing-proof__heading, + .hraness-marketing-install__heading, + .hraness-marketing-section__heading, + .hraness-marketing-primitives__heading, + .hraness-marketing-interfaces__heading, + .hraness-marketing-trust__heading, + .hraness-marketing-quotes__heading, + .hraness-marketing-pricing__heading, + .hraness-marketing-questions__heading, + .hraness-marketing-maker__heading, + .hraness-marketing-cta__heading +) { margin: 0; + color: var(--hraness-marketing-ink); font-family: var(--hraness-marketing-heading-font); - font-size: clamp(3.25rem, 7.6vw, 6.6rem); - font-weight: 700; - letter-spacing: -0.065em; - line-height: 0.92; + font-weight: var(--hraness-marketing-heading-weight); + letter-spacing: -0.012em; + line-height: 1.15; text-wrap: balance; } -.hraness-marketing-hero__summary { - max-inline-size: 38rem; - margin: 1.75rem 0 0; +:where( + .hraness-marketing-section__heading, + .hraness-marketing-primitives__heading, + .hraness-marketing-interfaces__heading, + .hraness-marketing-trust__heading, + .hraness-marketing-quotes__heading, + .hraness-marketing-pricing__heading, + .hraness-marketing-questions__heading, + .hraness-marketing-maker__heading +) { + font-size: clamp(1.75rem, 3vw, 2.5rem); +} + +/* Lead and summary paragraphs under a heading. */ +:where( + .hraness-marketing-hero__summary, + .hraness-marketing-hero__example, + .hraness-marketing-section__summary, + .hraness-marketing-primitives__header > p:last-child, + .hraness-marketing-interfaces__header > p:last-child, + .hraness-marketing-trust__header > p:last-child, + .hraness-marketing-quotes__header > p:last-child, + .hraness-marketing-pricing__header > p:last-child, + .hraness-marketing-questions__header > p:last-child, + .hraness-marketing-cta__summary +) { + margin: 0; color: var(--hraness-marketing-muted); font-family: var(--hraness-marketing-text-font); - font-size: clamp(1.1rem, 2.25vw, 1.55rem); - line-height: 1.4; - text-wrap: pretty; + font-size: 1.125rem; + line-height: 1.5; +} + +/* Container rhythm shared by every full-width role. */ +:where( + .hraness-marketing-hero, + .hraness-marketing-pillars, + .hraness-marketing-install, + .hraness-marketing-section, + .hraness-marketing-primitives, + .hraness-marketing-stats, + .hraness-marketing-interfaces, + .hraness-marketing-trust, + .hraness-marketing-quotes, + .hraness-marketing-pricing, + .hraness-marketing-questions, + .hraness-marketing-maker, + .hraness-marketing-cta +) { + inline-size: min(100%, var(--hraness-marketing-measure)); + min-inline-size: 0; + margin-inline: auto; +} + +.hraness-marketing-page > :where( + .hraness-marketing-hero, + .hraness-marketing-pillars, + .hraness-marketing-install, + .hraness-marketing-section, + .hraness-marketing-primitives, + .hraness-marketing-stats, + .hraness-marketing-interfaces, + .hraness-marketing-trust, + .hraness-marketing-quotes, + .hraness-marketing-pricing, + .hraness-marketing-questions, + .hraness-marketing-maker, + .hraness-marketing-cta +) { + padding-inline: var(--hraness-marketing-gutter); } +/* Actions */ + .hraness-marketing-hero__actions, .hraness-marketing-cta__actions { display: flex; @@ -99,73 +242,264 @@ gap: 0.65rem; } -.hraness-marketing-hero__actions { - margin-block-start: clamp(1.5rem, 3vw, 2.25rem); -} - .hraness-marketing-action { display: inline-flex; - min-block-size: 2.75rem; + min-block-size: var(--hraness-marketing-action-height); align-items: center; justify-content: center; - padding: 0.7rem 1rem; - border: var(--hraness-marketing-rule); - border-radius: var(--hraness-marketing-action-radius, 0); + gap: 0.45rem; + padding: 0.6rem 1.1rem; + border: 1px solid var(--hraness-marketing-line-strong); + border-radius: var(--hraness-marketing-radius); + background: var(--hraness-marketing-surface); color: var(--hraness-marketing-ink); font-family: var(--hraness-marketing-text-font); - font-size: 0.9rem; - font-weight: 700; + font-size: 0.95rem; + font-weight: 500; + line-height: 1.2; text-decoration: none; } .hraness-marketing-action:hover { - background: color-mix(in oklch, var(--hraness-marketing-ink) 8%, transparent); + background: color-mix(in oklch, var(--hraness-marketing-ink) 6%, var(--hraness-marketing-surface)); text-decoration: none; } +.hraness-marketing-action:focus-visible { + outline: 2px solid var(--hraness-marketing-accent); + outline-offset: 2px; +} + .hraness-marketing-action[data-emphasis="primary"] { - background: var(--hraness-marketing-ink); - color: var(--hraness-marketing-surface); + border-color: var(--hraness-marketing-accent); + background: var(--hraness-marketing-accent); + color: var(--hraness-marketing-accent-ink); } .hraness-marketing-action[data-emphasis="primary"]:hover { - background: color-mix(in oklch, var(--hraness-marketing-ink) 88%, var(--hraness-marketing-surface)); + border-color: color-mix(in oklch, var(--hraness-marketing-accent) 84%, black); + background: color-mix(in oklch, var(--hraness-marketing-accent) 84%, black); +} + +/* Site header */ + +.hraness-marketing-header { + position: sticky; + inset-block-start: 0; + z-index: 40; + border-block-end: var(--hraness-marketing-rule); + background: color-mix(in oklch, var(--hraness-marketing-background) 82%, transparent); + backdrop-filter: blur(14px) saturate(1.4); + -webkit-backdrop-filter: blur(14px) saturate(1.4); +} + +.hraness-marketing-header__inner { + display: flex; + inline-size: min(100%, var(--hraness-marketing-measure)); + min-block-size: 3.5rem; + align-items: center; + gap: 0.75rem 1.5rem; + margin-inline: auto; + padding-inline: var(--hraness-marketing-gutter); +} + +.hraness-marketing-header__brand { + display: inline-flex; + align-items: center; + gap: 0.5rem; + color: var(--hraness-marketing-ink); + font-size: 1rem; + font-weight: 600; + letter-spacing: -0.01em; + text-decoration: none; +} + +.hraness-marketing-header__brand :where(img, svg) { + block-size: 1.375rem; + inline-size: auto; +} + +.hraness-marketing-header__nav { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 0.15rem 1.35rem; + margin-inline-start: auto; +} + +.hraness-marketing-header__nav a { + color: var(--hraness-marketing-muted); + font-size: 0.92rem; + font-weight: 500; + text-decoration: none; +} + +.hraness-marketing-header__nav a:hover, +.hraness-marketing-header__nav a[aria-current="page"] { + color: var(--hraness-marketing-ink); +} + +.hraness-marketing-header__actions { + display: flex; + align-items: center; + gap: 0.5rem; +} + +.hraness-marketing-header .hraness-marketing-action { + min-block-size: 2.25rem; + padding-block: 0.4rem; + padding-inline: 0.9rem; + font-size: 0.9rem; +} + +/* Hero */ + +.hraness-marketing-hero { + display: grid; + gap: clamp(2rem, 5vw, 3.5rem); + padding-block: clamp(3.5rem, 9vw, 7rem) clamp(2.5rem, 6vw, 4.5rem); +} + +.hraness-marketing-hero__copy { + display: grid; + min-inline-size: 0; + justify-items: center; + gap: 1.25rem; + text-align: center; +} + +.hraness-marketing-hero[data-align="start"] .hraness-marketing-hero__copy { + justify-items: start; + text-align: start; +} + +.hraness-marketing-hero__eyebrow { + display: inline-flex; + align-items: center; + gap: 0.45rem; + padding: 0.3rem 0.8rem; + border: 1px solid color-mix(in oklch, var(--hraness-marketing-accent) 32%, transparent); + border-radius: 999px; + background: var(--hraness-marketing-accent-soft); + color: var(--hraness-marketing-accent); +} + +.hraness-marketing-hero__name { + position: absolute; + inline-size: 1px; + block-size: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0 0 0 0); + clip-path: inset(50%); + white-space: nowrap; + border: 0; +} + +.hraness-marketing-hero__heading { + max-inline-size: 18ch; + font-size: clamp(2.5rem, 5vw, 4.25rem); + letter-spacing: var(--hraness-marketing-heading-tracking); + line-height: 1.05; +} + +.hraness-marketing-hero__summary { + max-inline-size: var(--hraness-marketing-copy-measure); + font-size: clamp(1.125rem, 1.6vw, 1.3rem); + line-height: 1.45; +} + +.hraness-marketing-hero__example { + max-inline-size: var(--hraness-marketing-copy-measure); + margin-block-start: -0.35rem; + color: var(--hraness-marketing-ink); + font-size: 1.05rem; +} + +.hraness-marketing-hero__actions { + justify-content: center; + margin-block-start: 0.5rem; +} + +.hraness-marketing-hero[data-align="start"] .hraness-marketing-hero__actions { + justify-content: flex-start; } .hraness-marketing-hero__boundary { - max-inline-size: 48rem; - margin: 1.1rem 0 0; + max-inline-size: var(--hraness-marketing-copy-measure); + margin: 0; color: var(--hraness-marketing-muted); - line-height: 1.6; + font-size: 0.9rem; + line-height: 1.5; } -.hraness-marketing-proof { +.hraness-marketing-hero__frame { min-inline-size: 0; - align-self: stretch; - padding: clamp(1.25rem, 3.5vw, 2.4rem); - border: 1px solid color-mix(in oklch, var(--hraness-marketing-inverse-ink) 24%, transparent); +} + +/* Accent band: the hero paints edge to edge in the product accent. */ +.hraness-marketing-hero[data-tone="accent"] { + --hraness-marketing-ink: var(--hraness-marketing-accent-ink); + --hraness-marketing-muted: color-mix(in oklch, var(--hraness-marketing-accent-ink) 78%, transparent); + --hraness-marketing-line: color-mix(in oklch, var(--hraness-marketing-accent-ink) 22%, transparent); + --hraness-marketing-line-strong: color-mix(in oklch, var(--hraness-marketing-accent-ink) 40%, transparent); + --hraness-marketing-surface: color-mix(in oklch, var(--hraness-marketing-accent-ink) 12%, transparent); background: - linear-gradient(color-mix(in oklch, var(--hraness-marketing-inverse-ink) 6%, transparent) 1px, transparent 1px), - linear-gradient(90deg, color-mix(in oklch, var(--hraness-marketing-inverse-ink) 6%, transparent) 1px, transparent 1px), - var(--hraness-marketing-inverse); - background-size: 2.5rem 2.5rem; - color: var(--hraness-marketing-inverse-ink); + linear-gradient(color-mix(in oklch, var(--hraness-marketing-accent-ink) 7%, transparent) 1px, transparent 1px), + linear-gradient(90deg, color-mix(in oklch, var(--hraness-marketing-accent-ink) 7%, transparent) 1px, transparent 1px), + var(--hraness-marketing-accent); + background-size: 3.5rem 3.5rem, 3.5rem 3.5rem, auto; + box-shadow: 0 0 0 100vmax var(--hraness-marketing-accent); + clip-path: inset(0 -100vmax); + color: var(--hraness-marketing-accent-ink); +} + +.hraness-marketing-hero[data-tone="accent"] .hraness-marketing-hero__eyebrow { + border-color: color-mix(in oklch, var(--hraness-marketing-accent-ink) 40%, transparent); + background: color-mix(in oklch, var(--hraness-marketing-accent-ink) 14%, transparent); + color: var(--hraness-marketing-accent-ink); +} + +.hraness-marketing-hero[data-tone="accent"] .hraness-marketing-action[data-emphasis="primary"] { + border-color: var(--hraness-marketing-accent-ink); + background: var(--hraness-marketing-accent-ink); + color: var(--hraness-marketing-accent); +} + +.hraness-marketing-hero[data-tone="accent"] .hraness-marketing-action[data-emphasis="primary"]:hover { + background: color-mix(in oklch, var(--hraness-marketing-accent-ink) 90%, var(--hraness-marketing-accent)); +} + +.hraness-marketing-hero[data-tone="accent"] .hraness-marketing-action[data-emphasis="secondary"] { + border-color: var(--hraness-marketing-line-strong); + background: transparent; + color: var(--hraness-marketing-accent-ink); +} + +/* Legacy proof aside: now a light card beneath the copy. */ +.hraness-marketing-proof { + display: grid; + min-inline-size: 0; + gap: 1rem; + padding: clamp(1.25rem, 3vw, 2rem); + border: var(--hraness-marketing-rule); + border-radius: var(--hraness-marketing-frame-radius); + background: var(--hraness-marketing-surface); + box-shadow: var(--hraness-marketing-shadow); } .hraness-marketing-proof__kicker { - margin: 0 0 0.6rem; - color: color-mix(in oklch, var(--hraness-marketing-inverse-ink) 64%, transparent); + margin: 0; } .hraness-marketing-proof__heading { - max-inline-size: 16ch; - margin: 0 0 clamp(1.75rem, 4vw, 3.5rem); - font-family: var(--hraness-marketing-heading-font); - font-size: clamp(1.55rem, 3vw, 2.2rem); - line-height: 1.1; - text-wrap: balance; + max-inline-size: 24ch; + font-size: clamp(1.25rem, 2vw, 1.5rem); } +/* Ordered flow */ + .hraness-marketing-flow { display: grid; min-inline-size: 0; @@ -179,20 +513,27 @@ min-inline-size: 0; margin: 0; padding-block: 1rem; - border-block-start: 1px solid color-mix(in oklch, currentColor 24%, transparent); + border-block-start: var(--hraness-marketing-rule); gap: 0.85rem; grid-template-columns: 2.25rem minmax(0, 1fr); } +.hraness-marketing-flow__step:first-child { + border-block-start: 0; +} + .hraness-marketing-flow__number { - padding-block-start: 0.16rem; - color: color-mix(in oklch, currentColor 58%, transparent); + padding-block-start: 0.2rem; + color: var(--hraness-marketing-accent); font-family: var(--hraness-marketing-mono-font); - font-size: 0.72rem; + font-size: 0.75rem; + font-weight: 500; } .hraness-marketing-flow__body { + display: grid; min-inline-size: 0; + gap: 0.4rem; } .hraness-marketing-flow__label, @@ -202,128 +543,174 @@ } .hraness-marketing-flow__label { - margin-block-end: 0.35rem; - font-family: var(--hraness-marketing-text-font); - font-size: 0.84rem; + font-size: 0.95rem; + font-weight: 600; } .hraness-marketing-flow__code { - padding: 0; - background: transparent; + inline-size: fit-content; + max-inline-size: 100%; + padding: 0.35rem 0.6rem; + border-radius: 0.4rem; + background: color-mix(in oklch, var(--hraness-marketing-ink) 7%, transparent); color: inherit; font-family: var(--hraness-marketing-mono-font); - font-size: 0.76rem; + font-size: 0.8rem; overflow-wrap: anywhere; } .hraness-marketing-flow__detail { - margin: 0.45rem 0 0; - color: color-mix(in oklch, currentColor 72%, transparent); - font-family: var(--hraness-marketing-text-font); - font-size: 0.78rem; - line-height: 1.45; + margin: 0; + color: var(--hraness-marketing-muted); + font-size: 0.9rem; + line-height: 1.5; } -.hraness-marketing-facts { +/* Facts and stats */ + +.hraness-marketing-facts, +.hraness-marketing-stats__list { display: grid; margin: 0; border-block: var(--hraness-marketing-rule); - grid-column: 1 / -1; grid-template-columns: repeat(var(--hraness-marketing-fact-columns, 4), minmax(0, 1fr)); } -.hraness-marketing-facts > div { +.hraness-marketing-facts > div, +.hraness-marketing-stats__list > div { min-inline-size: 0; padding: 1.25rem clamp(0.8rem, 2vw, 1.5rem); } -.hraness-marketing-facts > div + div { +.hraness-marketing-facts > div + div, +.hraness-marketing-stats__list > div + div { border-inline-start: var(--hraness-marketing-rule); } -.hraness-marketing-facts dt { - margin-block-end: 0.55rem; - color: var(--hraness-marketing-muted); +.hraness-marketing-facts dt, +.hraness-marketing-stats dt { + margin-block-end: 0.4rem; } -.hraness-marketing-facts dd { +.hraness-marketing-facts dd, +.hraness-marketing-stats dd { margin: 0; } -.hraness-marketing-facts :where(strong, span) { +.hraness-marketing-facts :where(strong, span), +.hraness-marketing-stats :where(strong, span) { display: block; } .hraness-marketing-facts strong { - font-family: var(--hraness-marketing-text-font); - font-size: 1rem; + font-size: 1.05rem; + font-weight: 600; } -.hraness-marketing-facts span { - margin-block-start: 0.25rem; - color: var(--hraness-marketing-muted); - font-family: var(--hraness-marketing-text-font); - font-size: 0.76rem; - line-height: 1.45; +.hraness-marketing-stats strong { + font-family: var(--hraness-marketing-heading-font); + font-size: clamp(1.75rem, 3vw, 2.25rem); + font-weight: 500; + letter-spacing: -0.02em; + line-height: 1.1; + font-variant-numeric: tabular-nums; } -.hraness-marketing-install, -.hraness-marketing-section, -.hraness-marketing-interfaces, -.hraness-marketing-trust, -.hraness-marketing-questions, -.hraness-marketing-cta { - inline-size: min(100%, var(--hraness-marketing-measure)); - min-inline-size: 0; - margin-inline: auto; +.hraness-marketing-facts span, +.hraness-marketing-stats span { + margin-block-start: 0.3rem; + color: var(--hraness-marketing-muted); + font-size: 0.85rem; + line-height: 1.45; } -.hraness-marketing-install { +.hraness-marketing-stats { display: grid; - padding: clamp(1.25rem, 4vw, 2.5rem); - border: var(--hraness-marketing-rule); - gap: clamp(1.5rem, 4vw, 4rem); - grid-template-columns: minmax(11rem, 0.55fr) minmax(0, 1.45fr); - scroll-margin-block-start: 1rem; + gap: 0.75rem; + padding-block: clamp(1.5rem, 4vw, 3rem); } -.hraness-marketing-install__eyebrow { - margin: 0 0 0.6rem; +.hraness-marketing-stats__source { + margin: 0; color: var(--hraness-marketing-muted); + font-size: 0.85rem; } -.hraness-marketing-install__heading, -.hraness-marketing-section__heading, -.hraness-marketing-interfaces__heading, -.hraness-marketing-trust__heading, -.hraness-marketing-questions__heading, -.hraness-marketing-cta__heading { - margin: 0; - font-family: var(--hraness-marketing-heading-font); - line-height: 1.08; - text-wrap: balance; -} +/* Pillars */ -.hraness-marketing-install__heading { - max-inline-size: 10ch; - font-size: clamp(1.65rem, 3.4vw, 2.65rem); +.hraness-marketing-pillars { + display: grid; + margin-block: 0; + padding-block: 0; + border-block: var(--hraness-marketing-rule); + grid-template-columns: repeat(var(--hraness-marketing-pillar-columns, 3), minmax(0, 1fr)); } -.hraness-marketing-install__commands, -.hraness-marketing-section__body { +.hraness-marketing-pillars > div { + display: grid; min-inline-size: 0; + align-content: start; + gap: 0.45rem; + padding: clamp(1.25rem, 3vw, 2rem) clamp(1rem, 2.5vw, 1.75rem); } -.hraness-marketing-install__commands :where(pre) { - max-inline-size: 100%; - overflow: auto; +.hraness-marketing-pillars > div + div { + border-inline-start: var(--hraness-marketing-rule); } -.hraness-marketing-proof-frame { +.hraness-marketing-pillars dt { + font-size: 1.05rem; + font-weight: 600; + letter-spacing: -0.01em; +} + +.hraness-marketing-pillars dd { + margin: 0; + color: var(--hraness-marketing-muted); + font-size: 0.95rem; + line-height: 1.5; +} + +/* Product frame */ + +.hraness-marketing-proof-frame { min-inline-size: 0; margin: 0; + overflow: clip; border: var(--hraness-marketing-rule); + border-radius: var(--hraness-marketing-frame-radius); background: var(--hraness-marketing-surface); + box-shadow: var(--hraness-marketing-shadow); +} + +.hraness-marketing-proof-frame__chrome { + display: flex; + align-items: center; + gap: 0.75rem; + padding: 0.6rem 0.9rem; + border-block-end: var(--hraness-marketing-rule); + color: var(--hraness-marketing-muted); + font-size: 0.78rem; +} + +.hraness-marketing-proof-frame__lights { + display: inline-flex; + gap: 0.35rem; +} + +.hraness-marketing-proof-frame__lights span { + inline-size: 0.6rem; + block-size: 0.6rem; + border-radius: 999px; + background: color-mix(in oklch, var(--hraness-marketing-ink) 18%, transparent); +} + +.hraness-marketing-proof-frame__title { + flex: 1 1 auto; + overflow: hidden; + text-align: center; + text-overflow: ellipsis; + white-space: nowrap; } .hraness-marketing-proof-frame__content { @@ -331,51 +718,117 @@ overflow: auto; } +.hraness-marketing-proof-frame__content > :where(img, video) { + display: block; + inline-size: 100%; + block-size: auto; +} + +.hraness-marketing-proof-frame__content > :where(pre) { + border-radius: 0; +} + .hraness-marketing-proof-frame__caption { - display: grid; - padding: 0.75rem 0.9rem; + display: flex; + flex-wrap: wrap; + justify-content: space-between; + gap: 0.25rem 1rem; + padding: 0.75rem 0.95rem; border-block-start: var(--hraness-marketing-rule); color: var(--hraness-marketing-muted); - font-family: var(--hraness-marketing-text-font); - font-size: 0.78rem; - gap: 0.2rem; + font-size: 0.82rem; line-height: 1.45; } .hraness-marketing-proof-frame__caption small { - font-family: var(--hraness-marketing-mono-font); - font-size: 0.68rem; + font-size: 0.78rem; } -.hraness-marketing-section { +/* Install */ + +.hraness-marketing-install { display: grid; - padding-block: clamp(2.5rem, 7vw, 6rem); - border-block-start: var(--hraness-marketing-rule); - gap: clamp(2rem, 5vw, 6rem); - grid-template-columns: minmax(10rem, 0.55fr) minmax(0, 1.45fr); + padding: clamp(1.5rem, 4vw, 2.5rem); + border: var(--hraness-marketing-rule); + border-radius: var(--hraness-marketing-frame-radius); + background: var(--hraness-marketing-surface); + gap: clamp(1.25rem, 4vw, 3rem); + grid-template-columns: minmax(12rem, 0.6fr) minmax(0, 1.4fr); + scroll-margin-block-start: 5rem; } -.hraness-marketing-section__label, -.hraness-marketing-interfaces__label, -.hraness-marketing-trust__label, -.hraness-marketing-questions__label { - margin: 0; - color: var(--hraness-marketing-muted); +.hraness-marketing-page > .hraness-marketing-install { + inline-size: min(100% - 2 * var(--hraness-marketing-gutter), var(--hraness-marketing-measure)); + padding-inline: clamp(1.5rem, 4vw, 2.5rem); +} + +.hraness-marketing-install__heading-group { + display: grid; + align-content: start; + gap: 0.5rem; } -.hraness-marketing-section__heading, -.hraness-marketing-interfaces__heading, -.hraness-marketing-trust__heading, -.hraness-marketing-questions__heading { - font-size: clamp(1.75rem, 4vw, 3rem); +.hraness-marketing-install__heading { + max-inline-size: 14ch; + font-size: clamp(1.5rem, 2.6vw, 2rem); } +.hraness-marketing-install__commands, .hraness-marketing-section__body { + min-inline-size: 0; +} + +.hraness-marketing-install__commands { + display: grid; + gap: 0.75rem; +} + +/* Narrative section */ + +.hraness-marketing-section, +.hraness-marketing-primitives, +.hraness-marketing-interfaces, +.hraness-marketing-trust, +.hraness-marketing-quotes, +.hraness-marketing-pricing, +.hraness-marketing-questions, +.hraness-marketing-maker { + padding-block: var(--hraness-marketing-section-space); + border-block-start: var(--hraness-marketing-rule); + scroll-margin-block-start: 4rem; +} + +.hraness-marketing-section, +.hraness-marketing-interfaces, +.hraness-marketing-trust, +.hraness-marketing-questions { + display: grid; + gap: clamp(1.5rem, 4vw, 3rem); +} + +.hraness-marketing-section__heading-group, +.hraness-marketing-primitives__header, +.hraness-marketing-interfaces__header, +.hraness-marketing-trust__header, +.hraness-marketing-quotes__header, +.hraness-marketing-pricing__header, +.hraness-marketing-questions__header, +.hraness-marketing-maker__header { display: grid; max-inline-size: var(--hraness-marketing-copy-measure); + gap: 0.75rem; +} + +.hraness-marketing-section__body { + display: grid; gap: 1rem; } +.hraness-marketing-section__body > :where(p) { + max-inline-size: var(--hraness-marketing-prose-measure); + margin: 0; +} + .hraness-marketing-section__body > :first-child { margin-block-start: 0; } @@ -384,43 +837,92 @@ margin-block-end: 0; } -.hraness-marketing-interfaces, -.hraness-marketing-trust, -.hraness-marketing-questions { - padding-block: clamp(2.5rem, 7vw, 6rem); - border-block-start: var(--hraness-marketing-rule); +.hraness-marketing-section[data-layout="split"], +.hraness-marketing-section[data-layout="split-reverse"] { + align-items: center; + grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr); } -.hraness-marketing-interfaces__header, -.hraness-marketing-trust__header, -.hraness-marketing-questions__header { +.hraness-marketing-section[data-layout="split-reverse"] > .hraness-marketing-section__heading-group { + order: 2; +} + +.hraness-marketing-section[data-layout="split"] > .hraness-marketing-section__heading-group, +.hraness-marketing-section[data-layout="split-reverse"] > .hraness-marketing-section__heading-group { + max-inline-size: none; +} + +/* Primitives: numbered building blocks */ + +.hraness-marketing-primitives { display: grid; - max-inline-size: var(--hraness-marketing-copy-measure); - margin-block-end: clamp(1.5rem, 4vw, 3rem); - gap: 0.65rem; + gap: clamp(1.5rem, 4vw, 3rem); } -.hraness-marketing-interfaces__header > p:last-child, -.hraness-marketing-trust__header > p:last-child, -.hraness-marketing-questions__header > p:last-child { +.hraness-marketing-primitives__list { + display: grid; + margin: 0; + padding: 0; + list-style: none; + gap: 1rem; + grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr)); +} + +.hraness-marketing-primitive { + display: grid; + min-inline-size: 0; + align-content: start; + gap: 0.6rem; + padding: clamp(1.25rem, 2.5vw, 1.75rem); + border: var(--hraness-marketing-rule); + border-radius: var(--hraness-marketing-frame-radius); + background: var(--hraness-marketing-surface); +} + +.hraness-marketing-primitive__number { + color: var(--hraness-marketing-accent); + font-family: var(--hraness-marketing-mono-font); + font-size: 0.78rem; + font-weight: 500; +} + +.hraness-marketing-primitive__heading { + margin: 0; + font-size: 1.1rem; + font-weight: 600; + letter-spacing: -0.01em; +} + +.hraness-marketing-primitive p { margin: 0; color: var(--hraness-marketing-muted); - font-family: var(--hraness-marketing-text-font); + font-size: 0.95rem; + line-height: 1.5; +} + +.hraness-marketing-primitive > :where(pre, figure) { + margin-block-start: 0.5rem; } +/* Interfaces and trust: cards */ + .hraness-marketing-interface-grid, .hraness-marketing-trust-grid { display: grid; - gap: 1px; - border: var(--hraness-marketing-rule); - background: var(--hraness-marketing-line); + margin: 0; + gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr)); } .hraness-marketing-interface, .hraness-marketing-trust-item { + display: grid; min-inline-size: 0; - padding: clamp(1rem, 2.5vw, 1.5rem); + align-content: start; + gap: 0.5rem; + padding: clamp(1.25rem, 2.5vw, 1.75rem); + border: var(--hraness-marketing-rule); + border-radius: var(--hraness-marketing-frame-radius); background: var(--hraness-marketing-surface); } @@ -431,24 +933,187 @@ .hraness-marketing-interface__heading, .hraness-marketing-trust-item dt { - font-family: var(--hraness-marketing-text-font); - font-size: 0.95rem; - font-weight: 700; + font-size: 1.05rem; + font-weight: 600; + letter-spacing: -0.01em; } .hraness-marketing-interface p, .hraness-marketing-trust-item dd { - margin-block-start: 0.5rem; color: var(--hraness-marketing-muted); - font-family: var(--hraness-marketing-text-font); - font-size: 0.84rem; + font-size: 0.95rem; line-height: 1.5; } .hraness-marketing-interface pre { - max-inline-size: 100%; - margin-block: 1rem 0; - overflow: auto; + margin-block-start: 0.5rem; +} + +/* Quotes */ + +.hraness-marketing-quotes { + display: grid; + gap: clamp(1.5rem, 4vw, 3rem); +} + +.hraness-marketing-quote-grid { + display: grid; + margin: 0; + padding: 0; + list-style: none; + gap: 1rem; + grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr)); +} + +.hraness-marketing-quote { + display: grid; + min-inline-size: 0; + align-content: space-between; + gap: 1.25rem; + margin: 0; + padding: clamp(1.25rem, 2.5vw, 1.75rem); + border: var(--hraness-marketing-rule); + border-radius: var(--hraness-marketing-frame-radius); + background: var(--hraness-marketing-surface); +} + +.hraness-marketing-quote blockquote { + margin: 0; + font-size: 1rem; + line-height: 1.55; +} + +.hraness-marketing-quote blockquote p { + margin: 0; +} + +.hraness-marketing-quote figcaption { + display: flex; + flex-wrap: wrap; + align-items: baseline; + gap: 0.25rem 0.5rem; + color: var(--hraness-marketing-muted); + font-size: 0.88rem; +} + +.hraness-marketing-quote figcaption strong { + color: var(--hraness-marketing-ink); + font-weight: 600; +} + +.hraness-marketing-quote figcaption a { + color: inherit; + text-decoration: none; +} + +.hraness-marketing-quote figcaption a:hover { + text-decoration: underline; +} + +/* Pricing */ + +.hraness-marketing-pricing { + display: grid; + gap: clamp(1.5rem, 4vw, 3rem); +} + +.hraness-marketing-plan-grid { + display: grid; + margin: 0; + padding: 0; + list-style: none; + gap: 1rem; + grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr)); +} + +.hraness-marketing-plan { + display: grid; + min-inline-size: 0; + align-content: start; + gap: 1rem; + padding: clamp(1.5rem, 3vw, 2rem); + border: var(--hraness-marketing-rule); + border-radius: var(--hraness-marketing-frame-radius); + background: var(--hraness-marketing-surface); +} + +.hraness-marketing-plan[data-emphasis="primary"] { + border-color: color-mix(in oklch, var(--hraness-marketing-accent) 55%, transparent); + box-shadow: 0 0 0 1px color-mix(in oklch, var(--hraness-marketing-accent) 35%, transparent); +} + +.hraness-marketing-plan__name { + margin: 0; + font-size: 1.1rem; + font-weight: 600; +} + +.hraness-marketing-plan__price { + display: flex; + align-items: baseline; + gap: 0.35rem; + margin: 0; +} + +.hraness-marketing-plan__price strong { + font-family: var(--hraness-marketing-heading-font); + font-size: 2.25rem; + font-weight: 500; + letter-spacing: -0.02em; + line-height: 1; +} + +.hraness-marketing-plan__price span { + color: var(--hraness-marketing-muted); + font-size: 0.95rem; +} + +.hraness-marketing-plan__summary { + margin: 0; + color: var(--hraness-marketing-muted); + font-size: 0.95rem; +} + +.hraness-marketing-plan__features { + display: grid; + margin: 0; + padding: 0; + list-style: none; + gap: 0.5rem; + font-size: 0.95rem; +} + +.hraness-marketing-plan__features li { + display: grid; + gap: 0.6rem; + grid-template-columns: 1rem minmax(0, 1fr); +} + +.hraness-marketing-plan__features li::before { + content: ""; + inline-size: 1rem; + block-size: 1rem; + margin-block-start: 0.2rem; + border-radius: 999px; + background: + linear-gradient(var(--hraness-marketing-accent), var(--hraness-marketing-accent)) center / 0.4rem 0.4rem no-repeat, + var(--hraness-marketing-accent-soft); +} + +.hraness-marketing-plan__note { + margin: 0; + color: var(--hraness-marketing-muted); + font-size: 0.85rem; +} + +.hraness-marketing-plan .hraness-marketing-action { + justify-self: start; +} + +/* Questions */ + +.hraness-marketing-question-list { + display: grid; } .hraness-marketing-question { @@ -460,82 +1125,213 @@ } .hraness-marketing-question summary { - min-block-size: 3rem; + display: flex; + min-block-size: 3.25rem; + align-items: center; + justify-content: space-between; + gap: 1rem; padding-block: 1rem; color: var(--hraness-marketing-ink); cursor: pointer; - font-family: var(--hraness-marketing-text-font); - font-weight: 700; + font-size: 1.05rem; + font-weight: 500; + list-style: none; +} + +.hraness-marketing-question summary::-webkit-details-marker { + display: none; +} + +.hraness-marketing-question summary::after { + content: "+"; + flex: 0 0 auto; + color: var(--hraness-marketing-muted); + font-size: 1.25rem; + font-weight: 400; + line-height: 1; +} + +.hraness-marketing-question[open] summary::after { + transform: rotate(45deg); +} + +.hraness-marketing-question summary:focus-visible { + outline: 2px solid var(--hraness-marketing-accent); + outline-offset: 2px; + border-radius: 0.25rem; } .hraness-marketing-question__answer { - max-inline-size: var(--hraness-marketing-copy-measure); - padding-block: 0 1.25rem; + max-inline-size: var(--hraness-marketing-prose-measure); + padding-block: 0 1.5rem; color: var(--hraness-marketing-muted); - font-family: var(--hraness-marketing-text-font); + line-height: 1.6; } .hraness-marketing-question__answer > :first-child { margin-block-start: 0; } -.hraness-marketing-cta { +.hraness-marketing-question__answer > :last-child { + margin-block-end: 0; +} + +/* Maker */ + +.hraness-marketing-maker { display: grid; - padding: clamp(2rem, 6vw, 5rem); - background: var(--hraness-marketing-inverse); - color: var(--hraness-marketing-inverse-ink); + align-items: start; + gap: clamp(1.5rem, 4vw, 3rem); + grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr); +} + +.hraness-marketing-maker__portrait { + inline-size: 4.5rem; + block-size: 4.5rem; + overflow: hidden; + border-radius: 999px; + background: var(--hraness-marketing-accent-soft); +} + +.hraness-marketing-maker__portrait :where(img, svg) { + display: block; + inline-size: 100%; + block-size: 100%; + object-fit: cover; +} + +.hraness-marketing-maker__body { + display: grid; + min-inline-size: 0; gap: 1rem; } -.hraness-marketing-cta__eyebrow, -.hraness-marketing-cta__summary { +.hraness-marketing-maker__body > p { + max-inline-size: var(--hraness-marketing-prose-measure); + margin: 0; + color: var(--hraness-marketing-muted); + font-size: 1.05rem; + line-height: 1.55; +} + +.hraness-marketing-maker__links { + display: flex; + flex-wrap: wrap; + gap: 0.5rem 1.25rem; margin: 0; - color: color-mix(in oklch, currentColor 72%, transparent); + padding: 0; + list-style: none; + font-size: 0.95rem; + font-weight: 500; +} + +/* Closing call to action */ + +.hraness-marketing-cta { + display: grid; + justify-items: center; + gap: 1.25rem; + padding-block: var(--hraness-marketing-section-space); + border-block-start: var(--hraness-marketing-rule); + text-align: center; } .hraness-marketing-cta__heading { - max-inline-size: 18ch; - font-size: clamp(2rem, 5vw, 4.5rem); + max-inline-size: 20ch; + font-size: clamp(2rem, 4vw, 3.25rem); + letter-spacing: var(--hraness-marketing-heading-tracking); + line-height: 1.08; } .hraness-marketing-cta__summary { max-inline-size: var(--hraness-marketing-copy-measure); - font-family: var(--hraness-marketing-text-font); - text-wrap: pretty; } -.hraness-marketing-cta .hraness-marketing-action { - border-color: currentColor; - color: inherit; +.hraness-marketing-cta__actions { + justify-content: center; + margin-block-start: 0.5rem; +} + +.hraness-marketing-cta__footnote { + margin: 0; + color: var(--hraness-marketing-muted); + font-size: 0.9rem; +} + +.hraness-marketing-cta[data-tone="accent"] { + --hraness-marketing-ink: var(--hraness-marketing-accent-ink); + --hraness-marketing-muted: color-mix(in oklch, var(--hraness-marketing-accent-ink) 78%, transparent); + --hraness-marketing-line-strong: color-mix(in oklch, var(--hraness-marketing-accent-ink) 40%, transparent); + --hraness-marketing-surface: transparent; + border-block-start: 0; + background: var(--hraness-marketing-accent); + box-shadow: 0 0 0 100vmax var(--hraness-marketing-accent); + clip-path: inset(0 -100vmax); + color: var(--hraness-marketing-accent-ink); } -.hraness-marketing-cta .hraness-marketing-action[data-emphasis="primary"] { - background: var(--hraness-marketing-inverse-ink); - color: var(--hraness-marketing-inverse); +.hraness-marketing-cta[data-tone="accent"] .hraness-marketing-action[data-emphasis="primary"] { + border-color: var(--hraness-marketing-accent-ink); + background: var(--hraness-marketing-accent-ink); + color: var(--hraness-marketing-accent); +} + +.hraness-marketing-cta[data-tone="accent"] .hraness-marketing-action[data-emphasis="secondary"] { + background: transparent; + color: var(--hraness-marketing-accent-ink); } +/* Responsive */ + @media (max-width: 48rem) { - .hraness-marketing-hero, - .hraness-marketing-install, - .hraness-marketing-section { - grid-template-columns: minmax(0, 1fr); + .hraness-marketing-header__inner { + flex-wrap: wrap; + padding-block: 0.6rem; } - .hraness-marketing-hero__copy { - padding-block-end: 0; + .hraness-marketing-header__nav { + order: 3; + inline-size: 100%; + gap: 0.15rem 1rem; } .hraness-marketing-hero__heading { - max-inline-size: 12ch; + max-inline-size: 14ch; } - .hraness-marketing-facts { + .hraness-marketing-install, + .hraness-marketing-section[data-layout="split"], + .hraness-marketing-section[data-layout="split-reverse"], + .hraness-marketing-maker { grid-template-columns: minmax(0, 1fr); } - .hraness-marketing-facts > div + div { + .hraness-marketing-section[data-layout="split-reverse"] > .hraness-marketing-section__heading-group { + order: 0; + } + + .hraness-marketing-facts, + .hraness-marketing-stats__list { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + + .hraness-marketing-facts > div:nth-child(odd), + .hraness-marketing-stats__list > div:nth-child(odd) { + border-inline-start: 0; + } + + .hraness-marketing-facts > div:nth-child(n + 3), + .hraness-marketing-stats__list > div:nth-child(n + 3) { border-block-start: var(--hraness-marketing-rule); + } + + .hraness-marketing-pillars { + grid-template-columns: minmax(0, 1fr); + } + + .hraness-marketing-pillars > div + div { border-inline-start: 0; + border-block-start: var(--hraness-marketing-rule); } .hraness-marketing-install__heading { @@ -551,16 +1347,33 @@ } @media (forced-colors: active) { + .hraness-marketing-header, + .hraness-marketing-hero[data-tone="accent"], + .hraness-marketing-cta[data-tone="accent"], .hraness-marketing-proof, - .hraness-marketing-cta { + .hraness-marketing-proof-frame, + .hraness-marketing-install, + .hraness-marketing-primitive, + .hraness-marketing-interface, + .hraness-marketing-trust-item, + .hraness-marketing-quote, + .hraness-marketing-plan { + border: 1px solid CanvasText; + background: Canvas; + box-shadow: none; + color: CanvasText; + } + + .hraness-marketing-action, + .hraness-marketing-hero__eyebrow { border: 1px solid CanvasText; background: Canvas; color: CanvasText; } - .hraness-marketing-interface-grid, - .hraness-marketing-trust-grid { + .hraness-marketing-action[data-emphasis="primary"] { background: CanvasText; + color: Canvas; } } diff --git a/src/react/design-gallery.test.tsx b/src/react/design-gallery.test.tsx index e79cf25..407a656 100644 --- a/src/react/design-gallery.test.tsx +++ b/src/react/design-gallery.test.tsx @@ -112,7 +112,10 @@ test("the gallery is product-neutral and server renderable", () => { expect(html).toContain('data-hraness-marketing="flow"'); expect(html).toContain('data-hraness-marketing="facts"'); expect(html).toContain('data-hraness-marketing="install"'); - expect(html).toContain("Move one exact job across every interface."); + expect(html).toContain("Move one job across every interface"); + expect(html).toContain('data-hraness-marketing="pillars"'); + expect(html).toContain('data-hraness-marketing="pricing"'); + expect(html).toContain('data-hraness-marketing="maker"'); expect(html).toContain("bun add --global relay@1.2.3"); }); diff --git a/src/react/design-gallery.tsx b/src/react/design-gallery.tsx index dc6ebbc..7e7dbc0 100644 --- a/src/react/design-gallery.tsx +++ b/src/react/design-gallery.tsx @@ -32,8 +32,18 @@ import { PlaybackTransport, type PlaybackTransportStatus } from "./playback-tran import { ProceduralBackdrop } from "./procedural-backdrop.js"; import { ProductionDataPreviewNotice } from "./production-data-preview-notice.js"; import { + MarketingCallToAction, MarketingFlow, MarketingInstallPanel, + MarketingMaker, + MarketingPillars, + MarketingPricing, + MarketingPrimitives, + MarketingProofFrame, + MarketingQuestionList, + MarketingQuoteGrid, + MarketingSiteHeader, + MarketingStatStrip, ProductHero, } from "./product-marketing.js"; import { @@ -208,39 +218,52 @@ export function DesignSystemGallery({

Product-marketing grammar

-
+
+ +
{'{"status":"complete","job":"job-01","durationMs":412}'}
+ + )} + heading="Move one job across every interface" headingId="design-gallery-marketing-title" headingLevel={3} name="Relay" - proof={{ - content: ( - - ), - heading: "One job, three observable transitions", - kicker: "Working model", - }} - summary="The same owned job can be initialized, run, and inspected from a human or agent surface." + summary="Relay runs the same job from a terminal, typed code, or a coding agent, and hands back one receipt you can read." + /> +
bun add --global relay@1.2.3
+
+ + + + + No. The local workflow works without one.

, question: "Does it require an account?" }, + { answer:

Nothing leaves your machine unless you turn on sync.

, question: "Does it phone home?" }, + ]} + /> + +

A short, plain-words bio: who made it, what they did before, where they are, and why this product exists.

+
+
diff --git a/src/react/product-marketing.test.tsx b/src/react/product-marketing.test.tsx index 0f9b487..412e773 100644 --- a/src/react/product-marketing.test.tsx +++ b/src/react/product-marketing.test.tsx @@ -6,9 +6,17 @@ import { MarketingFlow, MarketingInstallPanel, MarketingInterfaceGrid, + MarketingMaker, + MarketingPage, + MarketingPillars, + MarketingPricing, + MarketingPrimitives, MarketingProofFrame, MarketingQuestionList, + MarketingQuoteGrid, MarketingSection, + MarketingSiteHeader, + MarketingStatStrip, MarketingTrustBoundary, ProductHero, } from "./product-marketing"; @@ -166,3 +174,132 @@ test("every public heading level renders its matching native element", () => { ); } }); + +test("the premium roles render semantic, server-only HTML with the shared data hooks", () => { + const html = renderToStaticMarkup( + + + +
{'{"status":"complete"}'}
+ + )} + heading="Move one job across every interface" + headingId="relay-title" + name="Relay" + summary="Relay runs the same job from a terminal, typed code, or a coding agent." + tone="accent" + /> + + +

Body.

+
+ + + + + +

A short bio.

+
+ +
, + ); + + expect(html).toContain('class="hraness-marketing-page"'); + expect(html).toContain('data-hraness-marketing="header"'); + expect(html).toContain('