diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..31ae398 Binary files /dev/null and b/.DS_Store differ diff --git a/.gitignore b/.gitignore index f695edc..3bc8b71 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,6 @@ apps/specimens/dist/ packages/ui/dist/ artifacts/mobile-quality/ artifacts/visual-review/ +.superpowers/ +artifacts/visual-baseline/ +artifacts/visual-luxe/ diff --git a/README.md b/README.md index e5f1e37..0ca33ae 100644 --- a/README.md +++ b/README.md @@ -9,20 +9,24 @@ quietly drift back into copied HTML. ## Foundation -| Decision | Value | -| --------------- | ------------------------------------------- | -| Component base | Base UI for new interactive primitives | -| shadcn style | `base-nova` | -| Scaffold seed | Zinc | -| Brand semantics | Coven-owned CSS variables | -| Presence | Lavender `#9386d0` in dark mode | -| Density | `default` and explicit `compact` variants | -| Language | Strict TypeScript | -| Styling | Tailwind CSS 4 and CSS custom properties | -| Icons | Lucide | -| Distribution | `@opencoven/ui` package and shadcn registry | - -Zinc supplies neutral scaffolding only. Components consume semantic tokens such +| Decision | Value | +| --------------- | --------------------------------------------- | +| Component base | Base UI for new interactive primitives | +| shadcn style | `base-nova` | +| Scaffold seed | Zinc | +| Brand semantics | OpenCoven web profile `1.0.0` | +| Action | Coven Violet `#8e3dff` dark / `#7a22ee` light | +| Presence | `#b991ff` dark / `#5e2a8a` light | +| Density | `default` and explicit `compact` variants | +| Language | Strict TypeScript | +| Styling | Tailwind CSS 4 and CSS custom properties | +| Icons | Lucide | +| Distribution | `@opencoven/ui` package and shadcn registry | + +Zinc supplies scaffold structure only. Colors, display/reading/mono font roles, +and the 4/8/12/16/24/32/48/64/96px spacing scale map to the pinned canonical +brand profile. Fonts use its local/system fallback stacks; no font files or +third-party font requests are bundled. Components consume semantic tokens such as `background`, `card`, `presence`, `success`, and the canonical `tool-read`/`tool-write`/`tool-exec`/`tool-net` mappings. @@ -30,7 +34,7 @@ as `background`, `card`, `presence`, `success`, and the canonical ```text . -├── apps/specimens/ React/Vite component library and five-state lab +├── apps/specimens/ React/Vite component library and six-scene lab ├── packages/ui/ │ └── src/ │ ├── components/ui/ Base UI and native primitives @@ -54,6 +58,24 @@ pnpm dev The specimen app opens at `http://127.0.0.1:5173/`. Its assembled lab is at `http://127.0.0.1:5173/lab`. +The library presents one specimen per row, with bounded live surfaces, +responsive block layouts, and a compact installation strip. It keeps live previews above syntax-highlighted install commands, +imports, and full component source, with copy controls and explicit +clipboard-failure feedback. The shared code renderer supports Bash, +TypeScript/TSX, and CSS. Each specimen has Preview/Source tabs in a fixed-size +preview area, so opening source does not change the card or page height. +Preview or Escape returns to the same component state; source scrolls inside +that area. Supported states live in a separate, always-visible footer rather +than a tab. The Lab +fits the viewport and offers six scenes through tabs, previous/next controls, +and touch swipes. Only the active scene scrolls when space is limited or text +is enlarged; the page and navigation stay fixed. Demo actions are local and +do not send agent requests. + +The monochrome crown/lotus mark in `public/opencoven-mark.svg` is vendored +unchanged from `OpenCoven/brand`'s `web/assets/mark.svg`, pinned to commit +`798e2f5f2f1a69f5d156ccc0a9aafc4f7da55fc8`. + ## Consume the package ```bash @@ -131,6 +153,12 @@ The initial migration includes: Search Field, Empty State, and Error State. - Blocks: Composer, Run Rail, Transcript Turn, and Session Header. +Composer accepts an optional `tools` slot for supporting controls and supports +Ctrl/Cmd+Enter to send a non-empty draft while idle. Run Rail accepts optional +`plan` and `resources` arrays using the public Plan Row and Resource Row props; +omit them to retain the metrics/activity/limits composition. +Send Control only displays its options action when `onOpenOptions` is supplied. + No Radix implementation existed to retain. No React Aria dependency was added; the current component set does not require its collection or internationalization architecture. @@ -149,6 +177,13 @@ export checks. CI runs the same command on every pull request and push to `main`. +The Visual review workflow also runs `scripts/visual-review.mjs` and +`scripts/mobile-quality-review.mjs` against the production app. It publishes +individual specimens and Lab scenes, contact sheets, and browser measurements. +Coverage includes every specimen's source overlay, real keyboard/mouse and +clipboard flows, touch navigation, theme persistence, forced colors, RTL, +narrow screens, and 200% text. + ## Legacy migration `index.html` and `Components.dc.html` remain as parity references. They are not diff --git a/apps/specimens/index.html b/apps/specimens/index.html index dd5245f..a3150de 100644 --- a/apps/specimens/index.html +++ b/apps/specimens/index.html @@ -3,6 +3,7 @@ + ( + "../../../packages/ui/src/{components,blocks}/*.tsx", + { query: "?raw", import: "default", eager: true }, +); + +const groupDetails: Record< + SpecimenGroup, + { id: string; eyebrow: string; description: string } +> = { + Composer: { + id: "group-composer", + eyebrow: "Input layer", + description: "Intent, authority, attachments, and send readiness.", + }, + "Run rail": { + id: "group-run-rail", + eyebrow: "Evidence layer", + description: "Execution evidence, limits, resources, and failure states.", + }, + Blocks: { + id: "group-blocks", + eyebrow: "Complete surfaces", + description: "Public components assembled into reusable agent workflows.", + }, +}; + +function SpecimenCard({ specimen }: { specimen: Specimen }) { + const sourceKind = specimen.group === "Blocks" ? "blocks" : "components"; + const headingId = `${specimen.id}-title`; + const exportName = specimen.id + .split("-") + .map((part) => part[0]?.toUpperCase() + part.slice(1)) + .join(""); + const registryUrl = `https://ui.opencoven.ai/r/${specimen.id}.json`; + const packagePath = `@opencoven/ui/${sourceKind}/${specimen.id}`; + const importCode = `import { ${exportName} } from "${packagePath}";`; + const source = + componentSources[ + `../../../packages/ui/src/${sourceKind}/${specimen.id}.tsx` + ]; + + return ( +
+
+
+ + {sourceKind === "blocks" ? : } + {sourceKind === "blocks" ? "Block" : "Component"} + + {specimen.primitive} +
+

+ {specimen.title} +

+

{specimen.description}

+
+ + {specimen.preview} + + + + CLI + React API + + + + + + + + + +
+ ); +} + +function Library({ density, query }: { density: Density; query: string }) { + const [mode, setMode] = useState("do"); + + const specimens = useMemo( + () => [ + { + id: "mode-switch", + title: "Mode switch", + group: "Composer", + primitive: "native", + description: + "A pressed-state control for Chat, Do, and Plan authority.", + states: "default, selected, focus, disabled", + preview: ( + + ), + }, + { + id: "send-control", + title: "Send control", + group: "Composer", + primitive: "Base UI", + description: + "The surface's one filled action, with a stable stop state.", + states: "ready, running, disabled", + preview: , + }, + { + id: "completion-palette", + title: "Completion palette", + group: "Composer", + primitive: "Base UI Menu", + description: + "Keyboard-ready slash commands in a collision-aware overlay.", + states: "closed, open, focused, disabled", + preview: , + }, + { + id: "attachment-chip", + title: "Attachment chip", + group: "Composer", + primitive: "native", + description: "A file attachment with explicit operational state.", + states: "ready, uploading, failed", + preview: ( +
+ + + +
+ ), + }, + { + id: "metric-display", + title: "Metric display", + group: "Run rail", + primitive: "native", + description: + "Comparable run figures in stable tabular numeric typography.", + states: "neutral, success, warning, information", + preview: ( + + + + + + ), + }, + { + id: "plan-row", + title: "Plan row", + group: "Run rail", + primitive: "native", + description: + "A task step whose icon, text treatment, and label carry state.", + states: "pending, active, complete, blocked", + preview: ( + + + + + + ), + }, + { + id: "activity-item", + title: "Activity item", + group: "Run rail", + primitive: "native", + description: + "One append-only tool event using the canonical class mapping.", + states: "read, write, exec, net, running", + preview: ( +
+ + + + +
+ ), + }, + { + id: "resource-row", + title: "Resource row", + group: "Run rail", + primitive: "native", + description: + "A direction-aware path row with operation and diff evidence.", + states: "modified, added, deleted, renamed", + preview: ( + + + + + ), + }, + { + id: "tool-mix", + title: "Tool mix", + group: "Run rail", + primitive: "native", + description: + "A readable summary with one fixed read/exec/write/net order.", + states: "populated, empty", + preview: ( + + ), + }, + { + id: "failure-surface", + title: "Failure surface", + group: "Run rail", + primitive: "Base UI Button", + description: + "A durable failure receipt with quiet output and explicit next moves.", + states: "failed, retried", + preview: , + }, + { + id: "context-meter", + title: "Context meter", + group: "Run rail", + primitive: "native progress", + description: + "Window consumption with a fixed threshold and stable numbers.", + states: "normal, warning, full", + preview: ( +
+ + +
+ ), + }, + { + id: "budget-pill", + title: "Budget pill", + group: "Run rail", + primitive: "native", + description: + "Spend against a limit with icon, text weight, and semantic tone.", + states: "normal, warning, over", + preview: ( +
+ + + +
+ ), + }, + { + id: "composer", + title: "Composer block", + group: "Blocks", + primitive: "composition", + description: + "The full intent-taking surface, built only from public modules.", + states: "empty, ready, running, disabled", + preview: , + }, + { + id: "run-rail", + title: "Run rail block", + group: "Blocks", + primitive: "composition", + description: + "Metrics, activity, context, and budget as one operational report.", + states: "populated, loading, empty, error", + preview: , + }, + { + id: "transcript-turn", + title: "Transcript turn", + group: "Blocks", + primitive: "composition", + description: + "Familiar identity and provenance lead an editorial response.", + states: "streaming, complete, with artifacts", + preview: ( + + Reply + Copy + 1.8K tokens + + } + > +

+ The component source, registry item, and specimen now share one + implementation boundary. +

+
+ ), + }, + { + id: "session-header", + title: "Session header", + group: "Blocks", + primitive: "composition", + description: + "The session task, branch, execution state, and spend in one line.", + states: "pending, active, complete, blocked", + preview: ( + + ), + }, + ], + [density, mode], + ); + + const normalizedQuery = query.trim().toLowerCase(); + const filtered = specimens.filter((specimen) => + `${specimen.title} ${specimen.group} ${specimen.description} ${specimen.states}` + .toLowerCase() + .includes(normalizedQuery), + ); + + if (filtered.length === 0) { + return ( +
+ +

No matching specimens

+

Try a component name, block, state, or operational concept.

+
+ ); + } + + return ( +
+ {groupOrder.map((group) => { + const groupedSpecimens = filtered.filter( + (specimen) => specimen.group === group, + ); + + if (groupedSpecimens.length === 0) { + return null; + } + + const detail = groupDetails[group]; + + return ( +
+
+
+

+ {detail.eyebrow} +

+

{group}

+

{detail.description}

+
+ + {groupedSpecimens.length}{" "} + {groupedSpecimens.length === 1 ? "specimen" : "specimens"} + +
+
+ {groupedSpecimens.map((specimen) => ( + + ))} +
+
+ ); + })} +
+ ); +} + +function DensityControl({ + density, + onDensityChange, +}: { + density: Density; + onDensityChange: (density: Density) => void; +}) { + return ( +
+ + +
+ ); +} + function App() { - const path = window.location.pathname.replace(/\/+$/, "") || "/"; const [scheme, setScheme] = useState(() => preference("coven-ui:scheme", "dark") === "light" ? "light" : "dark", ); @@ -41,25 +524,14 @@ function App() { : "default", ); const [query, setQuery] = useState(""); - const [searchOpen, setSearchOpen] = useState(false); - const [menuOpen, setMenuOpen] = useState(false); const searchRef = useRef(null); - const searchRegion = useRef(null); - const isHome = path === "/"; - const isLab = path === "/lab"; - const searchItems = [ - ...guides, - ...catalog.map((entry) => ({ - title: entry.title, - href: componentHref(entry.name), - })), - ].filter((entry) => - entry.title.toLowerCase().includes(query.trim().toLowerCase()), - ); + const topbarRef = useRef(null); + const normalizedPath = window.location.pathname.replace(/\/+$/, "") || "/"; + const isLab = normalizedPath === "/lab"; useEffect(() => { document.documentElement.classList.toggle("dark", scheme === "dark"); - document.documentElement.dataset.density = "default"; + document.documentElement.dataset.density = density; try { localStorage.setItem("coven-ui:scheme", scheme); localStorage.setItem("coven-ui:density", density); @@ -67,196 +539,190 @@ function App() { /* Preferences remain session-local when browser storage is blocked. */ } }, [density, scheme]); + useEffect(() => { - const title = - catalog.find((entry) => componentHref(entry.name) === path)?.title ?? - guides.find((guide) => guide.href === path)?.title ?? - (isHome - ? "Built for agents. Made for humans." - : isLab - ? "Component lab" - : "Components"); - document.title = `${title} — OpenCoven UI`; - const onKey = (event: KeyboardEvent) => { + const onKeyDown = (event: KeyboardEvent) => { if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === "k") { event.preventDefault(); searchRef.current?.focus(); - setSearchOpen(true); - } - if (event.key === "Escape") { - setSearchOpen(false); - setMenuOpen(false); } }; - const onPointer = (event: PointerEvent) => { - if (!searchRegion.current?.contains(event.target as Node)) - setSearchOpen(false); + + window.addEventListener("keydown", onKeyDown); + return () => window.removeEventListener("keydown", onKeyDown); + }, []); + + useEffect(() => { + const topbar = topbarRef.current; + if (!topbar) return; + + const updateTopbarHeight = () => { + document.documentElement.style.setProperty( + "--specimen-topbar-height", + `${Math.ceil(topbar.getBoundingClientRect().height)}px`, + ); }; - window.addEventListener("keydown", onKey); - window.addEventListener("pointerdown", onPointer); + const observer = new ResizeObserver(updateTopbarHeight); + + updateTopbarHeight(); + observer.observe(topbar); + return () => { - window.removeEventListener("keydown", onKey); - window.removeEventListener("pointerdown", onPointer); + observer.disconnect(); + document.documentElement.style.removeProperty("--specimen-topbar-height"); }; - }, [path, isHome, isLab]); + }, []); return ( -
- - Skip to content +
+ + Skip to specimens -
-
- -
+
+ + -
- {isHome ? ( - - ) : isLab ? ( - - ) : ( - - )} - +
+ +
+
+
+
+

+ {isLab + ? "The component workbench" + : "Sixteen public building blocks"} +

+

+ {isLab ? ( + <> + A little room to experiment. + + ) : ( + <> + Agent surfaces. +
+ Made tangible. + + )} +

+

+ {isLab + ? "Six scenes. Real components. One focused canvas." + : "Try the interaction, then take the source. Composable inputs, execution evidence, and complete agent workflows."} +

+
+
+
+
{isLab ? "Views" : "Specimens"}
+
{isLab ? "06" : "16"}
+
+
+
Schemes
+
02
+
+
+
Densities
+
02
+
+
+
+ {isLab ? ( + + ) : ( + + )} +
+
+
); diff --git a/apps/specimens/src/block-demos.tsx b/apps/specimens/src/block-demos.tsx new file mode 100644 index 0000000..1a767ba --- /dev/null +++ b/apps/specimens/src/block-demos.tsx @@ -0,0 +1,148 @@ +import { + Button, + CompletionPalette, + Composer, + RunRail, + type ComposerAttachment, + type ComposerMode, +} from "@opencoven/ui"; +import { Paperclip, RotateCcw, Slash } from "lucide-react"; +import { useState } from "react"; + +function ComposerDemo({ density }: { density: "default" | "compact" }) { + const [mode, setMode] = useState("do"); + const [message, setMessage] = useState( + "Review the changed files and suggest a focused fix.", + ); + const [running, setRunning] = useState(false); + const [attachments, setAttachments] = useState([ + { id: "spec", name: "spec.md", meta: "4.2 KB" }, + ]); + const [status, setStatus] = useState("Local preview. No requests are sent."); + + return ( +
+ { + setRunning(true); + setStatus("Demo run started. Use Stop to return to editing."); + }} + onStop={() => { + setRunning(false); + setStatus("Demo run stopped. Your draft is preserved."); + }} + attachments={attachments} + onRemoveAttachment={(id) => + setAttachments((items) => items.filter((item) => item.id !== id)) + } + tools={ + <> + + + Commands + + } + commands={[ + { + id: "review", + label: "/review", + description: "Review the changed files", + }, + { + id: "test", + label: "/test", + description: "Find missing test coverage", + }, + { + id: "plan", + label: "/plan", + description: "Plan a focused implementation", + }, + ]} + onSelect={(command) => { + setMessage(command.description); + if (command.id === "plan") setMode("plan"); + setStatus(`${command.label} added to your draft.`); + }} + /> + + + } + /> +

+ {status} +

+
+ ); +} + +function RunRailDemo({ density }: { density: "default" | "compact" }) { + return ( + + ); +} + +export { ComposerDemo, RunRailDemo }; diff --git a/apps/specimens/src/code-block.tsx b/apps/specimens/src/code-block.tsx index 3ffd024..3461ac3 100644 --- a/apps/specimens/src/code-block.tsx +++ b/apps/specimens/src/code-block.tsx @@ -1,52 +1,19 @@ -import { useState } from "react"; -import { Button } from "@opencoven/ui"; -import { Check, Copy, Terminal } from "lucide-react"; +import { CodeSnippet, type CodeLanguage } from "./code-snippet"; export function CodeBlock({ code, label = "Terminal", compact = false, + language = "bash", }: { code: string; label?: string; compact?: boolean; + language?: CodeLanguage; }) { - const [status, setStatus] = useState(""); - async function copy() { - try { - await navigator.clipboard.writeText(code); - setStatus("Copied"); - } catch { - setStatus("Copy unavailable. Select the code to copy it."); - } - } return (
-
- - - -
-
-        {code}
-      
- - {status} - +
); } diff --git a/apps/specimens/src/code-snippet.tsx b/apps/specimens/src/code-snippet.tsx new file mode 100644 index 0000000..7cff842 --- /dev/null +++ b/apps/specimens/src/code-snippet.tsx @@ -0,0 +1,110 @@ +import { Button } from "@opencoven/ui"; +import hljs from "highlight.js/lib/core"; +import bash from "highlight.js/lib/languages/bash"; +import typescript from "highlight.js/lib/languages/typescript"; +import css from "highlight.js/lib/languages/css"; +import xml from "highlight.js/lib/languages/xml"; +import { Check, Copy, Terminal } from "lucide-react"; +import { useEffect, useMemo, useState } from "react"; + +hljs.registerLanguage("bash", (api) => { + const grammar = bash(api); + grammar.contains?.push( + { scope: "built_in", begin: /\b(?:pnpm|npm|npx)\b/ }, + { scope: "keyword", begin: /\b(?:dlx|add|init|install)\b/ }, + { scope: "title", begin: /\bshadcn@latest\b/ }, + ); + return grammar; +}); +hljs.registerLanguage("typescript", typescript); +hljs.registerLanguage("xml", xml); +hljs.registerLanguage("css", css); + +type CodeLanguage = "bash" | "typescript" | "css"; + +function HighlightedCode({ + code, + language = "typescript", +}: { + code: string; + language?: CodeLanguage; +}) { + const html = useMemo( + () => hljs.highlight(code, { language }).value, + [code, language], + ); + + // highlight.js escapes source text before adding its own token markup. + return ( + + ); +} + +function CodeSnippet({ + code, + language, + label, +}: { + code: string; + language: CodeLanguage; + label: string; +}) { + const [copyState, setCopyState] = useState< + "idle" | "copying" | "copied" | "failed" + >("idle"); + + useEffect(() => { + if (copyState !== "copied") return; + const timeout = window.setTimeout(() => setCopyState("idle"), 2500); + return () => window.clearTimeout(timeout); + }, [copyState]); + + async function copy() { + setCopyState("copying"); + try { + await navigator.clipboard.writeText(code); + setCopyState("copied"); + } catch { + setCopyState("failed"); + } + } + + return ( +
+
+ + + +
+
+        
+      
+ + {copyState === "failed" + ? "Could not copy. Select the code and copy it manually." + : copyState === "copied" + ? "Copied to clipboard." + : ""} + +
+ ); +} + +export { CodeSnippet, HighlightedCode, type CodeLanguage }; diff --git a/apps/specimens/src/component-preview.tsx b/apps/specimens/src/component-preview.tsx new file mode 100644 index 0000000..853f3aa --- /dev/null +++ b/apps/specimens/src/component-preview.tsx @@ -0,0 +1,81 @@ +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@opencoven/ui"; +import { Braces, Eye } from "lucide-react"; +import { type ReactNode, useRef, useState } from "react"; + +import { CodeSnippet } from "./code-snippet"; + +function ComponentPreview({ + children, + source, + title, + filename, +}: { + children: ReactNode; + source: string | undefined; + title: string; + filename: string; +}) { + const [sourceOpen, setSourceOpen] = useState(false); + const triggerRef = useRef(null); + + return ( +
{ + if (event.key === "Escape" && sourceOpen) { + event.preventDefault(); + setSourceOpen(false); + triggerRef.current?.focus({ preventScroll: true }); + } + }} + > + setSourceOpen(value === "source")} + className="specimen-preview__tabs" + > + + + + + + +
+ {/* Keep the live component's dimensions and state behind its source. */} + + + {source ? ( + + ) : ( +

+ Source unavailable for this specimen. +

+ )} +
+
+
+
+ ); +} + +export { ComponentPreview }; diff --git a/apps/specimens/src/docs.tsx b/apps/specimens/src/docs.tsx index 3a90222..85de306 100644 --- a/apps/specimens/src/docs.tsx +++ b/apps/specimens/src/docs.tsx @@ -281,7 +281,11 @@ function ComponentDoc({
- + @@ -306,6 +310,7 @@ function ComponentDoc({

@@ -332,7 +337,11 @@ function ComponentDoc({ : "This primitive forwards its underlying element or Base UI props. See the source for its composition and supported variants."}

{entry.api ? ( - + ) : (

Add your first component

@@ -430,6 +440,7 @@ function Guide({ path }: { path: string }) {

Light and dark

@@ -486,6 +498,7 @@ function Guide({ path }: { path: string }) {

Density is explicit

@@ -496,6 +509,7 @@ function Guide({ path }: { path: string }) {

'} />

State is not decoration

diff --git a/apps/specimens/src/examples.tsx b/apps/specimens/src/examples.tsx index f0af335..c193f4b 100644 --- a/apps/specimens/src/examples.tsx +++ b/apps/specimens/src/examples.tsx @@ -213,7 +213,7 @@ export function SendControlExample({ }) { const [running, setRunning] = useState(false); return ( -
+
p:last-child, +.specimen-app--lab .specimen-stats { + display: none; +} + +.assembled-lab { + --scene-color: var(--presence); + display: flex; + flex-direction: column; + min-width: 0; + min-height: 0; + border: 1px solid color-mix(in srgb, var(--scene-color) 28%, var(--border)); +} + +.assembled-lab[data-tone="information"] { + --scene-color: var(--information); +} +.assembled-lab[data-tone="success"] { + --scene-color: var(--success); +} +.assembled-lab[data-tone="warning"] { + --scene-color: var(--warning); +} + +.lab-scene-header { + display: flex; + flex: none; + align-items: center; + justify-content: space-between; + gap: 1rem; + border-block-end: 1px solid var(--border); + padding: 0.875rem 1.25rem; +} + +.lab-scene-heading, +.lab-carousel-controls { + display: flex; + min-width: 0; + align-items: center; + gap: 0.75rem; +} + +.lab-scene-icon { + display: grid; + width: 2.5rem; + height: 2.5rem; + flex: none; + place-items: center; + border: 1px solid color-mix(in srgb, var(--scene-color) 28%, var(--border)); + border-radius: var(--radius-2); + background: color-mix(in srgb, var(--scene-color) 8%, var(--card)); + color: var(--scene-color); +} + +.lab-scene-icon svg { + width: 1.125rem; + height: 1.125rem; +} +.lab-scene-heading h2 { + margin: 0; + color: var(--scene-color); + font-size: 1rem; + font-weight: 700; +} +.lab-scene-heading p { + margin: 0.2rem 0 0; + color: var(--muted-foreground); + font-size: 0.75rem; +} +.lab-carousel-controls > span { + color: var(--muted-foreground); + font-size: 0.6875rem; + white-space: nowrap; +} +.lab-carousel-controls button { + width: 2.75rem; + min-height: 2.75rem; + padding: 0; +} + +.assembled-lab .lab-carousel { + display: flex; + flex: 1; + min-height: 0; + gap: 0; +} + +.lab-carousel__viewport { + container: lab-viewport / size; + display: grid; + flex: 1; + min-width: 0; + min-height: 0; + overflow: hidden; + touch-action: pan-y pinch-zoom; +} + +.lab-scene-panel { + height: 100%; + min-height: 0; + overflow: auto; + overscroll-behavior: contain; + scrollbar-width: thin; + touch-action: pan-y pinch-zoom; +} + +.lab-scene-panel[hidden] { + display: none; +} +.lab-scene-panel:focus-visible { + outline-offset: -3px; +} + +.assembled-lab .assembled-lab__stage { + display: grid; + min-height: 100%; + align-content: safe center; + padding: clamp(1rem, 3vh, 2.5rem) clamp(1rem, 4vw, 4rem); + background: var(--oc-surface-2); +} + +.lab-scene-surface { + width: min(100%, 50rem); + min-width: 0; + margin-inline: auto; +} + +.lab-scene-panel:not([hidden]) .lab-scene-surface { + animation: scene-enter var(--motion-slow) var(--motion-ease) both; +} + +.lab-scene-surface [data-slot="composer"] { + box-shadow: var(--elevation-3); +} +.lab-scene-surface .demo-status { + text-align: center; +} +.lab-scene-surface [data-slot="run-rail"] { + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 1.25rem; +} +.lab-scene-surface [data-slot="run-rail"] > div:first-child { + grid-column: 1 / -1; +} +.lab-scene-surface [data-slot="run-rail"] > div { + min-width: 0; +} + +.assembled-lab .assembled-lab__nav { + flex: none; + overflow: visible; + border-block: 1px solid var(--border); + padding: 0.625rem; + background: var(--card); +} + +.assembled-lab .assembled-lab__tabs { + display: grid; + width: 100%; + min-width: 0; + grid-template-columns: repeat(6, minmax(0, 1fr)); + gap: 0.375rem; + padding: 0; + background: transparent; +} + +.assembled-lab__tabs [role="tab"] { + display: flex; + min-width: 0; + min-height: 3.5rem; + flex-direction: column; + gap: 0.375rem; + border: 1px solid transparent; + border-radius: var(--radius-2); + padding: 0.5rem; + font-size: 0.75rem; +} + +.assembled-lab__tabs [role="tab"] svg { + width: 1.125rem; + height: 1.125rem; +} +.assembled-lab__tabs [role="tab"][data-active] { + border-color: color-mix(in srgb, var(--scene-color) 35%, var(--border)); + background: color-mix(in srgb, var(--scene-color) 10%, var(--card)); + color: var(--scene-color); + box-shadow: inset 0 -2px 0 var(--scene-color); +} + +.lab-footer { + display: flex; + flex: none; + flex-wrap: wrap; + align-items: center; + justify-content: space-between; + gap: 0.5rem; + padding: 0.625rem 1.25rem; + color: var(--muted-foreground); + font-size: 0.625rem; +} + +.lab-footer a { + display: inline-flex; + align-items: center; + gap: 0.375rem; + color: var(--scene-color); + text-decoration: none; +} +.lab-footer a:hover { + text-decoration: underline; +} +.lab-footer svg { + width: 0.875rem; + height: 0.875rem; +} +.lab-message-stack { + width: 100%; +} +.lab-message-stack [data-slot="transcript-turn"] { + padding-block: 1rem; +} +.lab-message-stack .specimen-code-snippet { + margin-block-start: 1rem; +} +.lab-context__heading { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 0.75rem; + margin-block-end: 1rem; + color: var(--success); +} +.lab-context__heading svg { + width: 1.25rem; + height: 1.25rem; +} +.lab-context__heading h3 { + font-size: 1rem; + font-weight: 600; +} +.lab-action-grid { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 1rem; +} +.lab-action-grid button { + height: auto; + min-width: 0; + align-items: start; + justify-content: start; + padding: 1.25rem; + white-space: normal; + text-align: start; +} +.lab-action-grid button > svg { + flex: none; + margin-block-start: 0.15rem; + color: var(--warning); +} +.lab-action-grid span { + display: grid; + gap: 0.375rem; +} +.lab-action-grid small { + color: var(--muted-foreground); + font-weight: 400; + line-height: 1.5; +} +.lab-action-result { + margin-block-start: 1rem; + padding: 1.25rem; +} +.lab-action-result p { + margin-block: 0.75rem; + line-height: 1.6; +} +.lab-card-grid { + width: 100%; +} +.lab-artifact summary { + display: grid; + gap: 0.75rem; + padding: 1.25rem; + cursor: pointer; + list-style: none; +} +.lab-artifact summary::-webkit-details-marker { + display: none; +} +.lab-artifact summary [data-slot="badge"] { + justify-self: start; +} +.lab-artifact strong { + font-size: 1rem; +} +.lab-artifact small { + color: var(--muted-foreground); +} +.lab-artifact__open { + display: flex; + align-items: center; + justify-content: space-between; + color: var(--information); + font-size: 0.75rem; +} +.lab-artifact__open svg { + width: 1rem; + height: 1rem; +} +.lab-artifact details[open] .lab-artifact__open svg { + rotate: 90deg; +} +.lab-artifact details > p { + margin: 0; + border-block-start: 1px solid var(--border); + padding: 1rem 1.25rem; + color: var(--muted-foreground); + font-size: 0.8125rem; + line-height: 1.6; +} + +@keyframes scene-enter { + from { + opacity: 0; + transform: translateY(6px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +@container lab-viewport (max-height: 440px) { + .assembled-lab .assembled-lab__stage { + padding-block: 0.75rem; + } + + .lab-scene-surface [data-slot="composer"] { + gap: 0.625rem; + padding: 1rem; + } + + .lab-scene-surface [data-slot="composer"] textarea { + min-height: 4rem; + } + + .lab-message-stack [data-slot="transcript-turn"] { + padding-block: 0.5rem; + } + + .lab-message-stack .specimen-code-snippet { + margin-block-start: 0.5rem; + } + + .lab-scene-surface [data-slot="run-rail"] { + gap: 0.75rem; + } +} + +@media (min-width: 48.01rem) and (max-height: 800px) { + .specimen-app--lab .specimen-hero { + display: flex; + align-items: baseline; + padding-block-end: 0.625rem; + } + + .specimen-app--lab .specimen-hero h1 { + margin: 0; + font-size: 1.5rem; + } + + .specimen-app--lab .specimen-hero .specimen-kicker { + display: none; + } +} + +@media (max-width: 68rem) { + .specimen-app--lab .specimen-topbar__inner { + flex-wrap: nowrap; + padding-block: 0.5rem; + gap: 0.5rem; + } + .specimen-app--lab .specimen-topbar__actions { + flex: 0 1 auto; + width: auto; + } + .specimen-app--lab .specimen-brand > span:last-child { + display: none; + } + .specimen-app--lab .surface-switcher { + margin-inline-start: 0; + margin-inline-end: auto; + } +} + +@media (max-width: 48rem) { + .specimen-app--lab .scheme-control span { + display: none; + } + .specimen-app--lab .specimen-hero { + padding-block-end: 0.75rem; + } + .lab-scene-header { + padding: 0.75rem; + gap: 0.5rem; + } + .lab-scene-icon { + display: none; + } + .lab-scene-heading p { + display: none; + } + .lab-carousel-controls { + gap: 0.375rem; + } + .lab-carousel-controls > span { + margin-inline-end: 0.25rem; + } + .assembled-lab .assembled-lab__stage { + padding: 1rem; + } + .lab-scene-surface [data-slot="composer"] { + padding: 1rem; + } + .lab-scene-surface [data-slot="composer"] textarea { + min-height: 5rem; + } + .lab-scene-surface [data-slot="run-rail"] { + grid-template-columns: minmax(0, 1fr); + gap: 0.875rem; + } + .assembled-lab .assembled-lab__tabs { + gap: 0.125rem; + } + .assembled-lab__tabs [role="tab"] { + min-height: 3rem; + padding: 0.5rem 0.125rem; + font-size: 0.6rem; + white-space: normal; + } + .lab-footer { + padding: 0.5rem 0.75rem; + } + .lab-footer > span { + display: none; + } + .lab-footer a { + min-height: 1.75rem; + margin-inline-start: auto; + } + .lab-action-grid { + grid-template-columns: minmax(0, 1fr); + gap: 0.625rem; + } + .lab-action-grid button { + padding: 1rem; + } + .lab-artifact summary { + padding: 1rem; + } +} + +@media (max-width: 24rem) { + .specimen-app--lab .specimen-topbar__inner { + padding-inline: 0.5rem; + gap: 0.25rem; + } + .specimen-app--lab .density-control button { + padding-inline: 0.3rem; + } + .specimen-app--lab .specimen-brand { + gap: 0; + } + .specimen-app--lab .specimen-brand__mark { + width: 1.5rem; + } + .specimen-app--lab .specimen-brand__mark > span { + width: 1.5rem; + height: 1.5rem; + } + .assembled-lab .assembled-lab__tabs { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } + .assembled-lab__tabs [role="tab"] { + flex-direction: row; + min-height: 2.75rem; + } +} + +@media (max-height: 650px) { + .specimen-app--lab .specimen-hero { + display: none; + } + .specimen-app--lab .specimen-main__inner { + grid-template-rows: minmax(0, 1fr); + padding-block: 0.5rem; + } + .lab-scene-header { + padding-block: 0.375rem; + } + .lab-footer { + display: none; + } +} diff --git a/apps/specimens/src/lab.tsx b/apps/specimens/src/lab.tsx index 8fc6c38..f467df4 100644 --- a/apps/specimens/src/lab.tsx +++ b/apps/specimens/src/lab.tsx @@ -1,186 +1,365 @@ -import { useState } from "react"; import { Badge, Button, Card, - CardContent, - CardFooter, - CardHeader, ResourceRow, - SessionHeader, Tabs, TabsContent, TabsList, TabsTrigger, TranscriptTurn, } from "@opencoven/ui"; -import { ComposerExample } from "./examples"; -import type { Density } from "./catalog"; +import { + Activity, + ArrowLeft, + ArrowRight, + FileCode2, + Layers3, + MessageSquare, + PenLine, + Wand2, +} from "lucide-react"; +import { useRef, useState } from "react"; -export function Lab({ density }: { density: Density }) { - const [notice, setNotice] = useState(""); - return ( -
-
- The component lab -

- See how it all -
- comes together. -

-

- Five focused compositions. One shared language. A place to try the - pieces before making them your own. +import { ComposerDemo, RunRailDemo } from "./block-demos"; +import { CodeSnippet, HighlightedCode } from "./code-snippet"; + +const scenes = [ + { + id: "composer", + title: "Composer", + subtitle: "From intent to action", + icon: PenLine, + source: "composer", + tone: "presence", + }, + { + id: "run-rail", + title: "Run rail", + subtitle: "Every step, accounted for", + icon: Activity, + source: "run-rail", + tone: "information", + }, + { + id: "messages", + title: "Messages", + subtitle: "A familiar voice, with evidence", + icon: MessageSquare, + source: "transcript-turn", + tone: "presence", + }, + { + id: "context", + title: "Context", + subtitle: "The right files, within reach", + icon: FileCode2, + source: "resource-row", + tone: "success", + }, + { + id: "actions", + title: "Actions", + subtitle: "Small controls, clear intent", + icon: Wand2, + source: "completion-palette", + tone: "warning", + }, + { + id: "cards", + title: "Cards", + subtitle: "Outcomes you can open", + icon: Layers3, + source: "session-header", + tone: "information", + }, +] as const; + +function Lab({ density }: { density: "default" | "compact" }) { + const [activeIndex, setActiveIndex] = useState(0); + const [actionStatus, setActionStatus] = useState( + "Choose an action to try its local preview.", + ); + const [attached, setAttached] = useState(false); + const [prompt, setPrompt] = useState("Review this change."); + const pointerStart = useRef<{ x: number; y: number } | null>(null); + const scene = scenes[activeIndex]!; + const SceneIcon = scene.icon; + const navigate = (offset: number) => + setActiveIndex((index) => (index + offset + scenes.length) % scenes.length); + + const views = { + composer: , + "run-rail": , + messages: ( +

+ +

+ The draft stays yours. Use {" "} + to keep it in sync with your application. +

+ ("do");\n\n' + } + /> +
+
+ ), + context: ( +
+
+
+ + + + + +

+ Context stays explicit. File operations keep their own color and + label.

-
-
- - -
- - {["Composer", "Messages", "Context", "Actions", "Cards"].map( - (name) => ( - - {name} - - ), - )} - -
- -
- -

- The component source, registry item, and specimen share one - implementation boundary. Ready when you are. -

-
- -
-
- -
- -

- Model selection, linked context, and send readiness stay - visible without interrupting the writing flow. -

-
- -

- The same primitives carry a different familiar identity - without changing their accessibility contract. -

-
-
-
- -
- - - -
-
- -
-

Give your next step a little context.

-
- -
+ ), + actions: ( +
+
+ + +
+ + Your draft +

{prompt}

+ {attached ? ( + changes.diff · 8.1 KB + ) : null} +
+

+ {actionStatus} +

+
+ ), + cards: ( +
+ {[ + { + kind: "Pull request", + title: "Recover attachment ingestion", + meta: "12 checks passed", + detail: + "The sample change keeps attachment metadata intact across retries.", + }, + { + kind: "Proposal", + title: "A smaller composer", + meta: "Ready for your review", + detail: + "Keep the draft visible, group supporting controls, and retain one primary send action.", + }, + { + kind: "Attachment", + title: "Component preview", + meta: "384 KB · added by Cody", + detail: + "A sample image artifact associated with the current review.", + }, + { + kind: "Handoff", + title: "Deployment notes", + meta: "Source, registry, package", + detail: + "Build the package and publish the same component source through the registry.", + }, + ].map((card) => ( + +
+ + - Enhance prompt - -
-

- {notice || "Local interaction examples. No files are accessed."} -

-
-
- -
- {[ - [ - "Pull request", - "Recover attachment ingestion", - "Checks 12 / 12", - ], - ["Proposal", "Merge with confidence", "Awaiting your review"], - [ - "Attachment", - "Components-preview.png", - "384 KB · added by Cody", - ], - ["Handoff", "Deployment ledger", "7 sections"], - ].map(([kind, title, meta]) => ( - - - {kind} - {title} -

{meta}

-
- - Example {kind?.toLowerCase()} surface composed from public - modules. - - - - -
- ))} -

{notice}

-
-
-
+ {card.kind} + + {card.title} + {card.meta} + + Read details + +

{card.detail}

+ + + ))}
-

- Example data only. These components connect to your own application - logic. -

-
+ ), + }; + + return ( +
+
+
+ + +
+

{scene.title}

+

{scene.subtitle}

+
+
+
+ + {scene.title}, scene + {String(activeIndex + 1).padStart(2, "0")} / 06 + + + +
+
+ { + const index = scenes.findIndex((item) => item.id === value); + if (index !== -1) setActiveIndex(index); + }} + className="lab-carousel" + > +
{ + pointerStart.current = null; + if ( + event.pointerType !== "touch" || + (event.target instanceof Element && + event.target.closest( + "button, input, textarea, a, summary, pre, code, [role=tab]", + )) + ) + return; + pointerStart.current = { x: event.clientX, y: event.clientY }; + }} + onPointerCancel={() => { + pointerStart.current = null; + }} + onPointerUp={(event) => { + const start = pointerStart.current; + pointerStart.current = null; + if (!start || window.getSelection()?.toString()) return; + const dx = event.clientX - start.x; + const dy = event.clientY - start.y; + if (Math.abs(dx) > 60 && Math.abs(dx) > Math.abs(dy) * 1.5) + navigate(dx < 0 ? 1 : -1); + }} + > + {scenes.map((item) => ( + + ))} +
+
+ + {scenes.map((item) => ( + + + ))} + +
+
+
+
); } + +export { Lab }; diff --git a/apps/specimens/src/main.tsx b/apps/specimens/src/main.tsx index 90b76dd..dbd0dfe 100644 --- a/apps/specimens/src/main.tsx +++ b/apps/specimens/src/main.tsx @@ -4,8 +4,23 @@ import { createRoot } from "react-dom/client"; import "@opencoven/ui/globals.css"; import "./specimens.css"; import "./specimens-fixes.css"; +import "./lab.css"; import { App } from "./app"; +const normalizedPath = window.location.pathname.replace(/\/+$/, "") || "/"; + +if (normalizedPath !== "/") { + window.addEventListener( + "keydown", + (event) => { + if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === "k") { + event.stopImmediatePropagation(); + } + }, + { capture: true }, + ); +} + const root = document.getElementById("root"); if (!root) { diff --git a/apps/specimens/src/specimens-fixes.css b/apps/specimens/src/specimens-fixes.css index 2116a3f..378f841 100644 --- a/apps/specimens/src/specimens-fixes.css +++ b/apps/specimens/src/specimens-fixes.css @@ -1,41 +1,216 @@ -/* Focused regression guards layered after the specimen shell styles. */ - -/* Keep the supported viewport floor stable when users enlarge root text. */ -html { - min-width: 320px; +/* Responsive guards for the catalog and its source panels. */ +body:not(:has(#group-composer)) .specimen-rail a[href="#group-composer"], +body:not(:has(#group-run-rail)) .specimen-rail a[href="#group-run-rail"], +body:not(:has(#group-blocks)) .specimen-rail a[href="#group-blocks"] { + display: none; } -/* Nested source previews must scroll themselves rather than widen the page. */ -.docs-main, -.component-stage, -.showcase-conversation, -.lab-stage, -.home-component, -.doc-preview, -.doc-preview [data-slot="tabs"], -.doc-preview [data-slot="tabs-content"] { - min-width: 0; - max-width: 100%; -} +@media (max-width: 68rem) { + .specimen-topbar__inner { + display: flex; + flex-wrap: wrap; + } + + .surface-switcher { + margin-inline-start: auto; + } -.component-stage > *, -.home-component-preview > *, -.lab-stage > * { - min-width: 0; - max-width: 100%; + .specimen-topbar__actions { + display: flex; + flex: 1 0 100%; + flex-wrap: wrap; + } + + .specimen-search { + width: auto; + max-width: none; + min-width: 7rem; + flex: 1 1 10rem; + } } @media (max-width: 48rem) { - .component-stage [data-slot="session-header"], - .lab-surface [data-slot="session-header"] { - flex-wrap: wrap; + html { + scroll-padding-top: 1rem; } - .component-stage [data-slot="resource-row"], - .lab-stage [data-slot="resource-row"] { + + .specimen-topbar { + position: static; + } + + .specimen-shell, + .specimen-main__inner, + .specimen-rail, + .specimen-card { + box-sizing: border-box; + width: 100%; + min-width: 0; + max-width: 100%; + } + + .specimen-hero, + .specimen-hero__copy, + .specimen-stats, + .specimen-stats div, + .specimen-rail > * { + min-width: 0; + max-width: 100%; + } + + .specimen-stats :where(dt, dd), + .specimen-rail__context, + .specimen-rail__package { overflow-wrap: anywhere; } - .code-block pre { + + .specimen-rail__nav { + display: grid; + width: 100%; + min-width: 0; + grid-template-columns: repeat(auto-fit, minmax(min(100%, 5.5rem), 1fr)); + } + + .specimen-rail__nav a { + min-width: 0; + justify-content: center; + gap: min(0.375rem, 8px); + padding-inline: 4px; + } + + .specimen-rail__nav small { + display: none; + } + + .specimen-card > [data-slot="tabs"] { + width: 100%; + min-width: 0; max-width: 100%; + } + + .specimen-card > [data-slot="tabs"] > [data-slot="tabs-list"] { + display: grid; + box-sizing: border-box; + width: 100%; + min-width: 0; + max-width: 100%; + min-height: 2.75rem; + grid-template-columns: repeat(2, minmax(5.25rem, 1fr)); + gap: 0; overflow-x: auto; + border-block-end: 1px solid var(--border); + padding: 0 0.75rem; + scrollbar-width: thin; + } + + .specimen-code-tabs [role="tab"] { + min-width: 0; + padding: 0.625rem 0.5rem; + } + + .specimen-code-tabs [role="tab"][data-active]::after { + inset-block-end: 0; + } + + .specimen-code-tabs [role="tab"]:focus-visible { + outline-offset: -3px; + } + + .specimen-card__header { + min-height: 0; + padding: 16px; + overflow-wrap: anywhere; + } + + .specimen-preview { + margin-inline: 16px; + } + + .specimen-stage { + min-width: 0; + min-height: 10rem; + justify-items: stretch; + padding: 16px; + } + + .specimen-stage [data-slot="composer"] { + padding: min(var(--density-panel), 24px); + } + + .specimen-stage + :is([data-slot="button"], [data-slot="dropdown-menu-trigger"]) { + height: auto; + min-height: var(--density-control); + white-space: normal; + overflow-wrap: anywhere; + } + + .specimen-stage > * { + box-sizing: border-box; + width: 100%; + min-width: 0; + max-width: 100%; + } + + .specimen-stage *, + .specimen-documentation * { + min-width: 0; + max-width: 100%; + } + + .specimen-stage :where(p, span, strong, small, code), + .specimen-documentation :where(p, span, strong, small, code) { + overflow-wrap: anywhere; + } + + .specimen-documentation { + min-width: 0; + max-width: 100%; + padding: 0.75rem 1rem 1rem; + } +} + +@media (max-width: 20rem) { + .specimen-topbar__inner { + gap: 0.375rem; + padding-block: 0.375rem; + } + + .specimen-main__inner { + padding-block-start: 0.75rem; + } + + .specimen-hero { + gap: 0.75rem; + margin-block-end: 1.25rem; + padding-block-end: 0.75rem; + } + + .specimen-hero h1 { + font-size: 2rem; + } + + .catalog-group__header { + gap: 0.375rem; + } + + .catalog-group__count { + display: none; + } +} + +@media (prefers-reduced-motion: reduce) { + .specimen-card:hover, + .specimen-card:focus-within { + translate: none; + } +} + +@media (forced-colors: active) { + .specimen-brand__mark { + color: CanvasText; + } + + .specimen-brand__mark > span { + forced-color-adjust: none; } } diff --git a/apps/specimens/src/specimens.css b/apps/specimens/src/specimens.css index 7dd3ec5..b057834 100644 --- a/apps/specimens/src/specimens.css +++ b/apps/specimens/src/specimens.css @@ -1,1470 +1,1262 @@ -:root { - --background: #f7f6f9; - --foreground: #242329; - --card: #ffffff; - --card-foreground: var(--foreground); - --muted-foreground: #716c7b; - --presence: #75629e; - --presence-foreground: var(--card); - --border: color-mix(in srgb, var(--foreground) 12%, var(--background)); - --font-numeric: var(--font-ui); - --site-width: 1240px; -} -html.dark { - --background: #111113; - --foreground: #efedf2; - --card: #19191c; - --card-foreground: var(--foreground); - --muted-foreground: #99979f; - --presence: #baabe6; - --presence-foreground: var(--background); - --border: color-mix(in srgb, var(--foreground) 12%, var(--background)); -} html { min-width: 320px; - scroll-padding-top: 100px; + --specimen-topbar-height: 3.75rem; + scroll-padding-top: calc(var(--specimen-topbar-height) + 1rem); } + body { min-height: 100vh; + overflow-x: clip; } -.site { - font-size: 14px; - line-height: 1.5; -} -.site a { - text-decoration: none; -} -.site button:not(:disabled), -.site select { - cursor: pointer; -} -.site :where(a, button, input, select, textarea):focus-visible { - outline: 2px solid var(--presence); - outline-offset: 4px; -} -.site p { - text-wrap: pretty; -} -.site h1, -.site h2, -.site h3 { - text-wrap: balance; -} -.site em { - font-weight: 400; -} + .skip-link { position: fixed; - top: 12px; - left: 12px; + max-width: calc(100% - 1.5rem); + overflow-wrap: anywhere; + inset-block-start: 0.75rem; + inset-inline-start: 0.75rem; z-index: 100; - transform: translateY(-180%); + translate: 0 -200%; + border-radius: var(--radius-2); background: var(--foreground); color: var(--background); - padding: 12px 20px; - border-radius: 6px; + padding: 0.625rem 0.875rem; + font-size: 0.8125rem; + font-weight: 700; } + .skip-link:focus { - transform: translateY(0); + translate: 0; } -.site-header { + +.specimen-topbar { position: sticky; - top: 0; - z-index: 40; - background: var(--background); - border-bottom: 1px solid var(--border); -} -.site-header-inner { - max-width: 1440px; - min-height: 76px; - margin-inline: auto; - padding-inline: 40px; + inset-block-start: 0; + z-index: 50; + border-block-end: 1px solid var(--border); + background: color-mix(in srgb, var(--background) 92%, transparent); + backdrop-filter: blur(18px); +} + +.specimen-topbar__inner { display: flex; + flex-wrap: wrap; + min-height: 3.75rem; + max-width: 96rem; align-items: center; - gap: 52px; + gap: 0.75rem; + margin-inline: auto; + padding-inline: clamp(1rem, 3vw, 1.5rem); } -.site-brand { + +.specimen-brand { display: inline-flex; align-items: center; - gap: 8px; + gap: var(--oc-space-2); + min-width: max-content; color: var(--foreground); - flex-shrink: 0; + text-decoration: none; } -.site-brand > svg { - width: 34px; - height: 34px; - color: var(--presence); - stroke-width: 2; + +.specimen-brand__mark { + display: grid; + width: 2rem; + height: 2rem; + flex: none; + place-items: center; + color: var(--foreground); } -.site-brand > span { - font-size: 25px; - font-weight: 650; - letter-spacing: -1.3px; + +.specimen-brand__mark > span { + width: 1.875rem; + height: 1.875rem; + background: currentColor; + mask: url("/opencoven-mark.svg") center / contain no-repeat; } -.brand-ui { + +.specimen-brand > span:last-child { + display: grid; + font-size: 0.875rem; + font-weight: 750; + letter-spacing: -0.015em; + line-height: 1.1; + font-family: var(--font-display); +} + +.specimen-brand small { + margin-block-start: 0.2rem; color: var(--muted-foreground); - font-size: 17px; - letter-spacing: -0.7px; - margin-left: 4px; - font-weight: 450; + font-family: var(--font-numeric); + font-size: 0.625rem; + font-weight: 600; + letter-spacing: 0.08em; + text-transform: uppercase; } -.primary-nav { - display: flex; + +.surface-switcher, +.density-control { + display: inline-flex; align-items: center; - gap: 28px; + gap: 0.125rem; + padding: 0.1875rem; + border: 1px solid var(--border); + border-radius: var(--radius-2); + background: var(--card); } -.primary-nav a { + +.surface-switcher a, +.density-control button { + border: 0; + border-radius: calc(var(--radius-2) - 2px); + background: transparent; color: var(--muted-foreground); - display: inline-flex; - align-items: center; - gap: 7px; + padding: 0.375rem 0.75rem; + font-size: 0.75rem; + font-weight: 700; + line-height: 1.25rem; + text-decoration: none; + white-space: nowrap; } -.primary-nav a:hover, -.primary-nav a[aria-current], -.site-footer a:hover { + +.surface-switcher a:hover, +.density-control button:hover { + background: var(--muted); color: var(--foreground); } -.nav-dot, -.release-dot { - width: 5px; - height: 5px; - border-radius: 50%; - background: var(--presence); + +.surface-switcher a[aria-current="page"], +.density-control button[aria-pressed="true"] { + background: var(--foreground); + color: var(--background); + box-shadow: var(--elevation-1); } -.header-tools { + +.specimen-topbar__actions { display: flex; + flex: 1 1 34rem; + flex-wrap: wrap; + min-width: 0; align-items: center; - gap: 14px; - margin-left: auto; + justify-content: flex-end; + gap: 0.5rem; +} + +.specimen-search { + width: min(20rem, 34vw); + max-width: 20rem; + flex: 1 1 16rem; +} + +.scheme-control { + flex: none; + white-space: nowrap; } -.icon-link { - display: inline-flex; - align-items: center; - color: var(--muted-foreground); - padding: 6px; + +.scheme-control svg { + width: 0.875rem; + height: 0.875rem; } -.icon-link svg { - width: 18px; - height: 18px; + +.specimen-shell { + display: grid; + max-width: 96rem; + min-height: calc(100vh - var(--specimen-topbar-height)); + grid-template-columns: 13.5rem minmax(0, 1fr); + margin-inline: auto; } -.site-search { - position: relative; - display: flex; - align-items: center; - gap: 9px; - width: 212px; - height: 34px; - border: 1px solid var(--border); - border-radius: 6px; - background: var(--card); - color: var(--muted-foreground); - padding-inline: 10px; + +.specimen-rail { + position: sticky; + inset-block-start: var(--specimen-topbar-height); + align-self: start; + height: calc(100vh - var(--specimen-topbar-height)); + overflow-y: auto; + border-inline-end: 1px solid var(--border); + background: color-mix(in srgb, var(--card) 72%, var(--background)); + padding: 1.5rem 0.875rem; + scrollbar-width: thin; } -.site-search > svg { - width: 14px; - height: 14px; - flex-shrink: 0; + +.specimen-rail__context { + padding-inline: 0.625rem; } -.site-search input { - min-width: 0; - width: 100%; - background: transparent; - border: none; - color: var(--foreground); - outline: none; - font-size: 14px; + +.specimen-rail__context h2 { + margin: 0.4rem 0 0; + font-size: 1rem; + font-weight: 750; + letter-spacing: -0.015em; } -.site-search input::placeholder { + +.specimen-rail__context p:last-child { + margin: 0.625rem 0 0; color: var(--muted-foreground); + font-size: 0.75rem; + line-height: 1.55; } -.site-search:focus-within { - outline: 2px solid var(--presence); - outline-offset: 2px; -} -.site-search input:focus-visible { - outline: none; -} -.site-search kbd { - white-space: nowrap; - font: inherit; - font-size: 14px; -} -.search-results { - position: absolute; - right: 0; - top: 44px; - width: 320px; - max-height: 440px; - overflow-y: auto; - padding: 8px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--card); - color: var(--foreground); - box-shadow: var(--elevation-2); + +.specimen-kicker { + margin: 0; + color: var(--presence); + font-size: 0.625rem; + font-weight: 750; + letter-spacing: 0.14em; + text-transform: uppercase; } -.search-heading { - display: block; - color: var(--muted-foreground); - padding: 8px; + +.specimen-rail__nav { + display: grid; + gap: 0.25rem; + margin-block-start: 1.25rem; } -.search-result { + +.specimen-rail__nav a { display: flex; - justify-content: space-between; align-items: center; - padding: 10px; - border-radius: 5px; + justify-content: space-between; + gap: 0.75rem; + border-radius: var(--radius-2); + color: var(--muted-foreground); + padding: 0.5rem 0.625rem; + font-size: 0.8125rem; + font-weight: 650; + text-decoration: none; } -.search-result:hover, -.search-result:focus-visible { + +.specimen-rail__nav a:hover { background: var(--muted); + color: var(--foreground); } -.search-result svg { - width: 14px; - height: 14px; -} -.search-results > p { - padding: 12px; -} -.mobile-nav-button { - display: none; + +.specimen-rail__nav small { + color: color-mix(in srgb, var(--muted-foreground) 76%, transparent); + font-size: 0.625rem; } -.home-main { - max-width: var(--site-width); - margin-inline: auto; - padding-inline: 40px; + +.specimen-rail__package { + margin-block-start: 1.5rem; + border-block-start: 1px solid var(--border); + padding: 1rem 0.625rem 0; } -.home-hero { - display: flex; - flex-direction: column; - align-items: center; - text-align: center; - padding-block: 78px 60px; + +.specimen-rail__package code { + display: block; + overflow: hidden; + margin-block-start: 0.5rem; + color: var(--foreground); + font-size: 0.75rem; + text-overflow: ellipsis; + white-space: nowrap; } -.release-note { - display: inline-flex; - align-items: center; - gap: 10px; + +.specimen-rail__package p { + margin: 0.625rem 0 0; color: var(--muted-foreground); - font-size: 14px; + font-size: 0.7rem; + line-height: 1.5; } -.release-note svg { - width: 14px; - height: 14px; + +.specimen-main { + min-width: 0; } -.release-divider { - height: 13px; - width: 1px; - background: var(--border); + +.specimen-main__inner { + width: min(100%, 76rem); + margin-inline: auto; + padding: var(--oc-space-8) var(--oc-space-8) var(--oc-space-16); } -.home-hero h1 { - font-size: clamp(56px, 7.6vw, 96px); - font-weight: 450; - letter-spacing: -5px; - line-height: 1.07; - margin: 30px 0 24px; + +.specimen-hero { + display: grid; + grid-template-columns: minmax(0, 1fr) minmax(15rem, 20rem); + align-items: center; + gap: 1.5rem; + margin-block-end: clamp(2rem, 4vw, 3rem); + border-block-end: 1px solid var(--border); + padding-block-end: clamp(1.5rem, 3vw, 2rem); +} + +.specimen-hero__copy { + max-width: 52rem; +} + +.specimen-hero h1 { + max-width: 19ch; + overflow-wrap: anywhere; + margin: 0.5rem 0 0; + font-family: var(--font-display); + font-size: var(--oc-type-4); + font-weight: 700; + letter-spacing: var(--oc-tracking-heading); + line-height: var(--oc-leading-heading); + color: var(--foreground); + text-wrap: balance; } -.home-hero h1 em { + +.specimen-hero h1 em { color: var(--presence); - letter-spacing: -4px; -} -.hero-description { - color: var(--muted-foreground); - font-size: 17px; - line-height: 1.7; - margin: 0; - max-width: 620px; + font-style: normal; } -.hero-actions { - display: flex; - align-items: center; - gap: 12px; - padding-top: 29px; + +.specimen-stats div:nth-child(2) dd { + color: var(--information); } -.hero-cta { - height: 42px; - padding-inline: 20px; - border-radius: 7px; - font-size: 14px; + +.specimen-stats div:nth-child(3) dd { + color: var(--success); } -.hero-install { - padding-top: 22px; - max-width: 100%; -} -.hero-foundations { - display: flex; - gap: 22px; - align-items: center; + +.specimen-hero__copy > p:last-child { + max-width: var(--oc-reading-measure); + margin: var(--oc-space-4) 0 0; color: var(--muted-foreground); - padding-top: 18px; - font-size: 14px; -} -.hero-foundations span { - display: inline-flex; - align-items: center; - gap: 5px; + font-size: var(--oc-type--1); + line-height: var(--oc-leading-reading); } -.hero-foundations svg { - width: 13px; - height: 13px; - color: var(--presence); + +.specimen-stats { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 0.5rem; + margin: 0; } -.code-block { - border: 1px solid var(--border); - border-radius: 8px; - background: var(--card); - color: var(--foreground); - overflow: hidden; - max-width: 100%; + +.specimen-stats div { min-width: 0; - text-align: left; + border-inline-start: 1px solid var(--border); + padding-inline-start: 0.875rem; } -.code-block__bar { - display: flex; - align-items: center; - justify-content: space-between; - padding: 8px 12px; - border-bottom: 1px solid var(--border); + +.specimen-stats dt { color: var(--muted-foreground); + font-size: 0.625rem; + font-weight: 700; + letter-spacing: 0.08em; + text-transform: uppercase; +} + +.specimen-stats dd { + margin: 0.25rem 0 0; + color: var(--foreground); + font-size: 1.25rem; + font-weight: 650; } -.code-block__bar > span { - display: flex; - align-items: center; - gap: 8px; - font-size: 14px; + +.catalog { + display: grid; + gap: clamp(2.75rem, 5vw, 4.5rem); } -.code-block__bar svg { - width: 14px; - height: 14px; + +.catalog-group { + --section-color: var(--presence); + scroll-margin-block-start: 0; } -.code-block pre { - margin: 0; - padding: 20px; - overflow-x: auto; - font-size: 14px; - line-height: 1.7; - tab-size: 2; + +#group-run-rail { + --section-color: var(--information); } -.code-block code { - white-space: pre; + +#group-blocks { + --section-color: var(--success); } -.code-block--compact { + +.catalog-group__header { display: flex; - align-items: center; - flex-direction: row-reverse; - background: transparent; - border-color: transparent; -} -.code-block--compact .code-block__bar { - padding: 0; - border: none; + align-items: end; + justify-content: space-between; + gap: 2rem; + margin-block-end: 0.875rem; } -.code-block--compact .code-block__bar > span { - display: none; + +.catalog-group__eyebrow { + margin: 0; + color: var(--section-color); + font-size: 0.625rem; + font-weight: 750; + letter-spacing: 0.14em; + text-transform: uppercase; +} + +.catalog-group__header h2 { + max-width: 34rem; + margin: 0.35rem 0 0; + font-size: clamp(1.25rem, 2vw, 1.6rem); + font-weight: 700; + letter-spacing: -0.025em; + line-height: 1.2; + color: var(--section-color); + text-wrap: balance; } -.code-block--compact pre { - padding: 4px 8px; + +.catalog-group__summary { + max-width: 52ch; + margin: 0.35rem 0 0; color: var(--muted-foreground); - font-size: 14px; -} -.copy-feedback { - display: block; - padding: 8px 12px; - color: var(--presence); + font-size: 0.75rem; + line-height: 1.5; } -.section-overline { - display: flex; - justify-content: space-between; - align-items: center; + +.catalog-group__count { + flex: none; color: var(--muted-foreground); - font-size: 14px; - padding-bottom: 15px; + font-size: 0.6875rem; + letter-spacing: 0.04em; + text-transform: uppercase; } -.section-overline > span:last-child { - display: flex; - gap: 8px; - align-items: center; -} -.section-overline svg { - width: 14px; - height: 14px; + +.specimen-grid { + display: grid; + grid-template-columns: minmax(0, 1fr); + gap: var(--oc-space-8); } -.agent-showcase { + +.specimen-card { + display: flex; + flex-direction: column; + min-width: 0; + overflow: hidden; + scroll-margin-block-start: 0; border: 1px solid var(--border); - border-radius: 12px; + border-radius: var(--radius-4); background: var(--card); - overflow: hidden; - box-shadow: 0 12px 48px color-mix(in srgb, var(--background) 80%, transparent); + color: var(--card-foreground); + box-shadow: var(--elevation-1); + transition: + border-color var(--motion-standard) var(--motion-ease), + box-shadow var(--motion-standard) var(--motion-ease), + translate var(--motion-standard) var(--motion-ease); +} + +.specimen-card:hover, +.specimen-card:focus-within { + border-color: color-mix(in srgb, var(--section-color) 48%, var(--border)); + box-shadow: var(--elevation-2); } -.showcase-title { + +.specimen-card__header { + min-height: 8.25rem; + padding: var(--oc-space-6) var(--oc-space-6) var(--oc-space-4); +} + +.specimen-card__meta { display: flex; - justify-content: space-between; + flex-wrap: wrap; align-items: center; - padding: 17px 24px; - border-bottom: 1px solid var(--border); + justify-content: space-between; + gap: 1rem; } -.showcase-title > span:first-child { + +.specimen-card__kind { display: inline-flex; align-items: center; - gap: 9px; - font-weight: 500; -} -.coven-glyph { - width: 20px; - height: 20px; - color: var(--presence); + gap: 0.45rem; + color: var(--section-color); + font-size: 0.625rem; + font-weight: 700; + letter-spacing: 0.12em; + text-transform: uppercase; +} + +.specimen-card__kind svg { + width: 0.875rem; + height: 0.875rem; +} + +.specimen-card__title { + margin: 0.75rem 0 0; + color: color-mix(in srgb, var(--section-color) 55%, var(--foreground)); + font-family: var(--font-display); + font-size: var(--oc-type-1); + font-weight: 650; + letter-spacing: var(--oc-tracking-heading); } -.showcase-workspace { - display: grid; - grid-template-columns: minmax(0, 1fr) 270px; + +.specimen-card__description { + max-width: 46ch; + margin: var(--oc-space-2) 0 0; + color: var(--muted-foreground); + font-size: var(--oc-type--1); + line-height: var(--oc-leading-reading); } -.showcase-conversation { + +.specimen-preview { + position: relative; + display: flex; + flex: 1; + flex-direction: column; + min-width: 0; + margin: 0 var(--oc-space-4) var(--oc-space-4); + overflow: hidden; + border: 1px solid color-mix(in srgb, var(--section-color) 24%, var(--border)); + border-radius: var(--radius-2); + background: var(--oc-surface-2); + box-shadow: inset 0 1px 0 + color-mix(in srgb, var(--section-color) 18%, transparent); +} + +.specimen-preview__tabs { + flex: 1; min-width: 0; - padding: 24px 28px 12px; + gap: 0; } -.showcase-context { - display: flex; - align-items: center; - gap: 7px; - color: var(--muted-foreground); - font-size: 14px; - padding-bottom: 28px; + +.specimen-view-tabs { + width: 100%; + gap: var(--oc-space-1); + border-block-end: 1px solid var(--border); + border-radius: 0; + background: var(--card); + padding: var(--oc-space-2); + justify-content: flex-start; + overflow-x: auto; + scrollbar-width: thin; } -.showcase-context svg { - width: 14px; - height: 14px; + +.specimen-view-tabs [role="tab"] { + flex: 0 0 auto; + min-width: 0; + min-height: 2.75rem; + gap: var(--oc-space-2); + padding-inline: var(--oc-space-4); + font-size: 0.8125rem; +} + +.specimen-view-tabs [role="tab"][data-active] { + border-color: var(--border); + background: var(--oc-surface-2); + color: var(--presence); + box-shadow: inset 0 -2px 0 var(--presence); } -.showcase-context span { - margin-left: auto; + +.specimen-view-tabs svg { + width: 0.875rem; + height: 0.875rem; } -.showcase-plan { - padding-block: 16px 24px; + +.specimen-view-tabs [role="tab"]:focus-visible { + outline-offset: -3px; +} + +.specimen-preview__canvas { + position: relative; + display: grid; + flex: 1; + min-width: 0; } -.showcase-composer { + +.specimen-live-panel { + display: grid; min-width: 0; } -.showcase-footnote { + +.specimen-source-overlay { + position: absolute; + inset: 0; display: flex; - align-items: center; - justify-content: space-between; - color: var(--muted-foreground); - font-size: 14px; - padding-top: 8px; + box-sizing: border-box; + min-width: 0; + min-height: 0; + padding: 0.75rem; + background: var(--card); } -.showcase-evidence { - border-left: 1px solid var(--border); + +.specimen-source-overlay .specimen-code-snippet { display: flex; + flex: 1; flex-direction: column; - padding: 28px 24px; - background: color-mix(in srgb, var(--card) 55%, var(--background)); + min-width: 0; + min-height: 0; } -.eyebrow { - color: var(--muted-foreground); - font-size: 14px; - letter-spacing: 0.01em; -} -.showcase-evidence h3 { - font-family: var(--font-editorial); - font-size: 26px; - font-weight: 400; - line-height: 1.35; - margin: 16px 0 30px; -} -.evidence-ownership { - font-size: 14px; - line-height: 1.7; - color: var(--muted-foreground); - padding-bottom: 24px; + +.specimen-source-overlay .specimen-code-snippet__header { + flex: none; } -.evidence-files { - padding-top: 24px; + +.specimen-source-overlay .specimen-command { + flex: 1; + min-height: 0; + max-height: none; + overscroll-behavior: contain; } -.evidence-files > span { - display: block; - color: var(--muted-foreground); - padding-bottom: 12px; + +.specimen-source-overlay .code-copy-error { + flex: none; } -.evidence-note { - margin-top: auto; - padding-top: 32px; - display: flex; - align-items: center; - gap: 12px; + +.specimen-stage { + display: grid; + flex: 1; + min-height: 14rem; + align-content: center; + justify-items: center; + padding: var(--oc-space-6); +} + +.specimen-stage > * { + min-width: 0; + max-width: min(100%, 48rem); +} + +.composer-demo { + width: 100%; + min-width: 0; +} + +.demo-status { + margin: 0.75rem 0 0; color: var(--muted-foreground); + font-size: 0.6875rem; + line-height: 1.5; } -.evidence-note svg { - width: 25px; - height: 25px; - color: var(--presence); + +.specimen-stage > .composer-demo, +.specimen-stage > [data-slot="card"] { + width: 100%; +} + +.specimen-stage > [data-slot="composer"], +.specimen-stage > [data-slot="session-header"] { + width: 100%; +} + +.specimen-stage > [data-slot="run-rail"] { + width: min(100%, 48rem); } -.evidence-note p { - font-size: 14px; + +.specimen-stage > [data-slot="transcript-turn"] { + width: min(100%, 42rem); +} + +.specimen-documentation { + display: grid; + min-height: 7.5rem; + align-content: start; + gap: var(--oc-space-3); + padding: var(--oc-space-3) var(--oc-space-4) var(--oc-space-4); + font-size: 0.8125rem; line-height: 1.6; } -.showcase-caption { - display: flex; - justify-content: space-between; - padding-top: 16px; - font-size: 14px; - color: var(--muted-foreground); + +.specimen-states { + display: grid; + gap: var(--oc-space-2); + border-block-start: 1px solid var(--border); + padding: var(--oc-space-4); + font-size: 0.6875rem; } -.showcase-caption a, -.section-heading > a { + +.specimen-states > span { display: inline-flex; align-items: center; - gap: 8px; -} -.showcase-caption svg, -.section-heading > a svg { - width: 16px; - height: 16px; + gap: var(--oc-space-2); + color: var(--muted-foreground); + font-weight: 600; } -.home-library { - padding-top: 106px; + +.specimen-states svg { + width: 0.875rem; + height: 0.875rem; } -.section-heading { +.specimen-states ul { display: flex; - justify-content: space-between; - align-items: flex-end; - padding-bottom: 28px; -} -.section-heading h2 { - font-size: 36px; - letter-spacing: -1.3px; - font-weight: 450; - margin: 12px 0; + flex-wrap: wrap; + gap: var(--oc-space-2); + margin: 0; + padding: 0; + list-style: none; } -.section-heading p:last-child { - color: var(--muted-foreground); +.specimen-states li { + border: 1px solid var(--border); + border-radius: var(--radius-1); + background: var(--oc-surface-2); + color: var(--oc-text-muted); + padding: var(--oc-space-1) var(--oc-space-2); +} + +.specimen-card > [data-slot="tabs"] { + flex: none; + gap: 0; + border-block-start: 1px solid var(--border); + background: color-mix(in srgb, var(--background) 70%, var(--card)); +} + +.specimen-code-tabs { margin: 0; + padding: 0.375rem 0.75rem; +} + +@media (min-width: 64rem) { + .specimen-card__header { + display: grid; + grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr); + align-items: center; + column-gap: var(--oc-space-8); + row-gap: var(--oc-space-4); + padding: var(--oc-space-6); + } + + .specimen-card__meta { + grid-column: 1 / -1; + } + + .specimen-card__title, + .specimen-card__description { + margin: 0; + } + + .specimen-card__description { + max-width: 60ch; + justify-self: end; + } + + .specimen-preview { + margin-inline: var(--oc-space-6); + margin-block-end: var(--oc-space-6); + } + + .specimen-stage { + padding: var(--oc-space-8); + } + + .specimen-stage > [data-slot="run-rail"] { + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: var(--oc-space-6); + } + + .specimen-stage > [data-slot="run-rail"] > div { + min-width: 0; + } + + .specimen-stage > [data-slot="run-rail"] > div:first-child { + grid-column: 1 / -1; + } + + .specimen-card > [data-slot="tabs"] { + display: grid; + grid-template-columns: auto minmax(0, 1fr); + align-items: start; + gap: var(--oc-space-6); + padding-inline: var(--oc-space-6); + } + + .specimen-code-tabs { + margin-block-start: var(--oc-space-4); + padding-inline: 0; + } + + .specimen-documentation { + min-height: 0; + padding: var(--oc-space-4) 0; + } + + .specimen-states { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: var(--oc-space-4); + padding-inline: var(--oc-space-6); + } } -.section-heading > a { - flex-shrink: 0; - font-size: 14px; - padding-bottom: 4px; + +.specimen-code-tabs [role="tab"] { + min-height: 2.75rem; + font-size: 0.6875rem; } -.home-component-grid { - display: grid; - grid-template-columns: repeat(3, minmax(0, 1fr)); - gap: 16px; + +.specimen-code-tabs [role="tab"][data-active] { + color: var(--section-color); } -.home-component { - border: 1px solid var(--border); - border-radius: 9px; - background: var(--card); - min-width: 0; - overflow: hidden; + +.specimen-code-tabs [role="tab"][data-active]::after { + background: var(--section-color); } -.home-component-preview { - display: flex; - min-height: 195px; - justify-content: center; - align-items: center; - padding: 20px; - overflow: auto; + +.specimen-documentation p { + margin: 0; } -.home-component-preview [data-slot="plan-row"] { - font-size: 14px; + +.specimen-code-snippet { + display: grid; + gap: 0.4rem; } -.home-component > a { + +.specimen-code-snippet__header { display: flex; align-items: center; justify-content: space-between; - border-top: 1px solid var(--border); - padding: 15px 20px; - font-size: 14px; -} -.home-component > a:hover { - color: var(--presence); - background: var(--muted); + gap: 0.75rem; } -.home-component > a svg { - width: 16px; - height: 16px; + +.specimen-code-snippet__header span { + display: inline-flex; + align-items: center; + gap: 0.4rem; color: var(--muted-foreground); + font-size: 0.6rem; + font-weight: 750; + letter-spacing: 0.08em; + text-transform: uppercase; +} + +.specimen-code-snippet__header svg { + width: 0.75rem; + height: 0.75rem; +} + +.specimen-code-snippet__header button { + min-height: 2.75rem; + font-size: 0.625rem; +} + +.code-copy-error { + color: var(--destructive); + font-size: 0.75rem; +} + +.specimen-command { + display: block; + max-height: 22rem; + overflow: auto; + scrollbar-width: thin; + margin: 0; + overflow-wrap: anywhere; + border: 1px solid var(--border); + border-radius: var(--radius-2); + background: var(--background); + color: var(--foreground); + padding: 0.75rem; + font-size: 0.7rem; + line-height: 1.6; + white-space: pre-wrap; + word-break: break-word; } -.principles { - display: grid; - grid-template-columns: repeat(3, minmax(0, 1fr)); - gap: 45px; - padding-block: 80px; -} -.principles svg { - width: 22px; - height: 22px; - color: var(--presence); -} -.principles h3 { - font-size: 16px; - font-weight: 500; - margin: 16px 0 10px; -} -.principles p { - font-size: 14px; - color: var(--muted-foreground); - line-height: 1.7; - margin: 0; -} -.home-closing { - border-top: 1px solid var(--border); - text-align: center; - padding-block: 70px 90px; -} -.home-closing h2 { - font-size: 55px; - line-height: 1.14; - letter-spacing: -2px; - font-weight: 450; - margin: 22px 0 32px; -} -.home-closing em { - color: var(--presence); -} -.site-footer { - max-width: 1440px; - padding: 28px 40px; - margin-inline: auto; - display: flex; - align-items: center; - gap: 24px; - border-top: 1px solid var(--border); -} -.site-footer .site-brand > span { - font-size: 21px; -} -.site-footer .site-brand > svg { - width: 27px; - height: 27px; -} -.site-footer > p { - color: var(--muted-foreground); - font-size: 14px; -} -.site-footer nav { - display: flex; - align-items: center; - gap: 24px; - margin-left: auto; - color: var(--muted-foreground); - font-size: 14px; -} -.site-footer nav a { - display: inline-flex; - gap: 5px; - align-items: center; -} -.site-footer nav svg { - width: 14px; - height: 14px; -} -.docs-layout { - display: grid; - grid-template-columns: 220px minmax(0, 1fr) 170px; - max-width: 1440px; - margin-inline: auto; - padding-inline: 40px; - gap: 48px; - min-height: 80vh; -} -.docs-sidebar { - position: sticky; - top: 76px; - align-self: start; - height: calc(100vh - 76px); - overflow-y: auto; - padding-block: 32px; - padding-right: 16px; - scrollbar-width: thin; - scrollbar-color: var(--border) transparent; -} -.sidebar-group { - display: flex; - flex-direction: column; - padding-bottom: 24px; -} -.sidebar-group h2 { - font-size: 14px; - font-weight: 600; - padding-inline: 10px; - margin: 0 0 8px; -} -.sidebar-group a { - padding: 7px 10px; - color: var(--muted-foreground); - border-radius: 5px; - display: flex; - align-items: center; - justify-content: space-between; -} -.sidebar-group a:hover { + +.hljs { color: var(--foreground); + font-family: var(--font-numeric); } -.sidebar-group a[aria-current] { + +.hljs-keyword, +.hljs-built_in, +.hljs-selector-tag, +.hljs-meta { color: var(--presence); - background: color-mix(in srgb, var(--presence) 9%, transparent); -} -.sidebar-group a span { - font-size: 14px; -} -.sidebar-lab { - display: flex; - align-items: center; - gap: 10px; - border: 1px solid var(--border); - border-radius: 8px; - padding: 14px; -} -.sidebar-lab > svg { - width: 16px; - height: 16px; - flex-shrink: 0; -} -.sidebar-lab small { - display: block; - color: var(--muted-foreground); - font-size: 14px; - margin-top: 4px; -} -.docs-main { - min-width: 0; - padding-block: 36px 80px; -} -.breadcrumbs { - display: flex; - flex-wrap: wrap; - gap: 10px; - color: var(--muted-foreground); - font-size: 14px; - margin: 0 0 32px; -} -.breadcrumbs a:hover { - color: var(--foreground); -} -.docs-heading { - display: flex; - flex-direction: column; - align-items: flex-start; -} -.docs-heading h1 { - font-size: clamp(36px, 4.1vw, 52px); - font-weight: 450; - letter-spacing: -2px; - line-height: 1.13; - margin: 20px 0 16px; -} -.docs-heading > p { - color: var(--muted-foreground); - font-size: 16px; - line-height: 1.65; - margin: 0; - max-width: 640px; -} -.source-link { - display: inline-flex; - align-items: center; - gap: 5px; - color: var(--muted-foreground); - font-size: 14px; -} -.docs-heading .source-link { - margin-top: 18px; } -.source-link svg { - width: 14px; - height: 14px; -} -.doc-preview { - border: 1px solid var(--border); - border-radius: 10px; - margin-top: 28px; - overflow: hidden; -} -.preview-toolbar { - display: flex; - align-items: center; - justify-content: space-between; - padding: 10px 16px; - border-bottom: 1px solid var(--border); -} -.density-select { - display: flex; - align-items: center; - gap: 7px; + +.hljs-selector-class, +.hljs-selector-pseudo, +.hljs-selector-id, +.hljs-attribute { + color: var(--information); +} + +.hljs-string, +.hljs-regexp, +.hljs-template-tag { + color: var(--success); +} + +.hljs-title, +.hljs-name, +.hljs-attr, +.hljs-property, +.hljs-type { + color: var(--information); +} + +.hljs-number, +.hljs-literal, +.hljs-variable, +.hljs-template-variable, +.hljs-params { + color: var(--warning); +} + +.hljs-comment, +.hljs-punctuation { color: var(--muted-foreground); - font-size: 14px; } -.density-select svg { - width: 14px; - height: 14px; -} -.density-select select { - background: var(--background); - color: var(--foreground); - border-radius: 5px; + +p > .hljs { border: 1px solid var(--border); - padding: 4px; - font: inherit; -} -.component-stage { - min-height: 280px; - display: flex; - align-items: center; - justify-content: center; - padding: 40px; - min-width: 0; -} -.component-stage > * { - max-width: 100%; -} -.preview-caption { - display: flex; - justify-content: space-between; - padding: 10px 16px; - color: var(--muted-foreground); - font-size: 14px; - background: var(--card); - border-top: 1px solid var(--border); -} -.doc-preview .code-block { - border: none; - border-radius: 0; -} -.doc-preview .code-block pre { - max-height: 560px; -} -.doc-section { - padding-top: 40px; - min-width: 0; -} -.doc-section h2 { - font-size: 24px; - font-weight: 500; - letter-spacing: -0.7px; - margin: 0 0 16px; -} -.doc-section p { - color: var(--muted-foreground); - font-size: 15px; - line-height: 1.75; - margin: 0 0 20px; -} -.doc-section p a { - color: var(--foreground); - text-decoration: underline; - text-underline-offset: 3px; -} -.doc-section p code { - font-size: 14px; - color: var(--presence); + border-radius: var(--radius-1); + background: var(--muted); + padding: 0.1em 0.3em; + color: var(--information); + font-size: 0.8em; overflow-wrap: anywhere; } -.doc-section > .code-block { - margin-bottom: 24px; -} -.state-list { - display: flex; - flex-wrap: wrap; - align-items: center; - gap: 8px; - padding-block: 12px; -} -.state-list > span:first-child { - color: var(--muted-foreground); - padding-right: 8px; -} -.docs-contents { - position: sticky; - top: 116px; - align-self: start; - display: flex; - flex-direction: column; - gap: 12px; - padding-top: 40px; + +.specimen-install-meta { + display: grid; + grid-template-columns: auto minmax(0, 1fr); + gap: 0.75rem; color: var(--muted-foreground); - font-size: 14px; } -.docs-contents > span { - color: var(--foreground); - font-weight: 500; -} -.docs-contents a:hover { + +.specimen-install-meta span { color: var(--presence); + font-size: 0.625rem; + font-weight: 750; + letter-spacing: 0.08em; + text-transform: uppercase; +} + +.specimen-install-meta svg { + width: 1rem; + height: 1rem; +} + +.run-spine { + position: relative; } -.docs-contents > div { - border-top: 1px solid var(--border); - padding-top: 24px; - margin-top: 16px; -} -.docs-contents > div > svg { - width: 20px; - height: 20px; - color: var(--presence); -} -.docs-contents > div p { - margin-block: 12px; -} -.docs-contents > div a { - display: inline-flex; - align-items: center; - gap: 3px; -} -.docs-contents > div a svg { - width: 14px; - height: 14px; -} -.catalog-section { - padding-top: 40px; -} -.catalog-section > h2 { - font-size: 20px; - font-weight: 500; - display: flex; - align-items: center; - gap: 12px; - padding-bottom: 16px; -} -.catalog-section > h2 > span { - color: var(--muted-foreground); - font-size: 14px; + +.run-spine::before { + position: absolute; + inset-block: 0.5rem; + inset-inline-start: 1.1rem; + width: 1px; + background: color-mix(in srgb, var(--presence) 38%, var(--border)); + content: ""; } -.docs-catalog-grid { + +.catalog-empty { display: grid; - grid-template-columns: repeat(2, minmax(0, 1fr)); - gap: 12px; + min-height: 24rem; + place-items: center; + align-content: center; + border: 1px dashed var(--border); + border-radius: var(--radius-3); + padding: 2rem; + text-align: center; } -.catalog-tile { - display: block; + +.catalog-empty__mark { + display: grid; + width: 2.75rem; + height: 2.75rem; + place-items: center; border: 1px solid var(--border); - border-radius: 8px; - padding: 20px; - background: var(--card); - transition: border-color 150ms; -} -.catalog-tile:hover { - border-color: var(--presence); -} -.catalog-tile > div { - display: flex; - justify-content: space-between; - align-items: center; - gap: 12px; -} -.catalog-tile h3 { - font-size: 16px; - font-weight: 500; -} -.catalog-tile svg { - width: 15px; - height: 15px; - color: var(--muted-foreground); - flex-shrink: 0; -} -.catalog-tile p { - font-size: 14px; - color: var(--muted-foreground); - margin-top: 10px; - line-height: 1.6; -} -.docs-pagination { - display: flex; - justify-content: space-between; - border-top: 1px solid var(--border); - padding-top: 24px; - margin-top: 48px; -} -.docs-pagination a { - display: flex; - align-items: center; - gap: 10px; + border-radius: var(--radius-2); + color: var(--presence); } -.docs-pagination a:last-child { - text-align: right; + +.catalog-empty__mark svg { + width: 1rem; + height: 1rem; } -.docs-pagination svg { - width: 16px; - height: 16px; + +.catalog-empty h2 { + margin: 1rem 0 0; + font-size: 1.125rem; } -.docs-pagination small { - display: block; + +.catalog-empty p { + margin: 0.4rem 0 0; color: var(--muted-foreground); - font-size: 14px; + font-size: 0.8125rem; } -.docs-mobile-toggle { - display: none; -} -.intro-callout { - display: flex; - align-items: flex-start; - gap: 16px; + +.assembled-lab { + overflow: hidden; + scroll-margin-block-start: 0; border: 1px solid var(--border); - border-radius: 8px; - padding: 24px; + border-radius: var(--radius-3); background: var(--card); - margin-top: 32px; -} -.intro-callout svg { - width: 22px; - height: 22px; - flex-shrink: 0; - color: var(--presence); -} -.intro-callout p { - margin: 0; - color: var(--muted-foreground); - font-size: 15px; - line-height: 1.7; -} -.guide-links { - display: grid; - grid-template-columns: repeat(2, minmax(0, 1fr)); - gap: 12px; - padding-bottom: 36px; -} -.guide-links a { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 8px; - border: 1px solid var(--border); - padding: 20px; - border-radius: 8px; -} -.guide-links p { - margin: 0; - font-size: 14px; -} -.guide-links svg { - width: 16px; - height: 16px; -} -.guide-layer { - padding-block: 16px; -} -.guide-layer h3 { - font-size: 16px; - font-weight: 500; - padding-bottom: 8px; + color: var(--card-foreground); + box-shadow: var(--elevation-2); } -.token-swatches { - display: grid; - grid-template-columns: repeat(4, minmax(0, 1fr)); - gap: 12px; - padding-bottom: 24px; + +.assembled-lab__nav { + overflow-x: auto; + border-block-end: 1px solid var(--border); + padding: 0.75rem 1rem 0; } -.token-swatches > div { + +.assembled-lab__tabs { + width: max-content; min-width: 0; } -.token-swatches span { - display: block; - height: 70px; - border-radius: 7px; - border: 1px solid var(--border); + +.assembled-lab__tabs [data-slot="tabs-trigger"] { + flex: none; } -.token-swatches code { - display: block; - font-size: 14px; - color: var(--muted-foreground); - padding-top: 8px; - overflow-wrap: anywhere; + +.assembled-lab [data-slot="tabs"], +.assembled-lab__stage, +.lab-composer, +.lab-message-stack { + min-width: 0; } -.lab-main { - max-width: 1100px; - padding: 64px 40px 80px; + +.assembled-lab__stage { + display: grid; + min-height: 27rem; + align-content: center; + background: color-mix(in srgb, var(--muted) 42%, var(--background)); + padding: clamp(1rem, 3vw, 2rem); +} + +.lab-composer, +.lab-message-stack { + display: grid; + width: min(100%, 48rem); + gap: 1.25rem; margin-inline: auto; - min-height: 80vh; -} -.lab-main .docs-heading em { - color: var(--presence); -} -.lab-surface { - border: 1px solid var(--border); - border-radius: 12px; - margin-top: 40px; - overflow: hidden; -} -.lab-tabs { - border-bottom: 1px solid var(--border); - padding: 12px 20px; - overflow-x: auto; -} -.lab-stage { - display: flex; - flex-direction: column; - gap: 28px; - padding: 40px; - min-height: 280px; } + .lab-card-grid { display: grid; + width: min(100%, 52rem); grid-template-columns: repeat(2, minmax(0, 1fr)); - gap: 20px; - padding: 32px; -} -.lab-caption { - color: var(--muted-foreground); - text-align: center; - margin-top: 24px; -} -@media (min-width: 1400px) { - .home-hero { - padding-top: 105px; - padding-bottom: 80px; - } -} -@media (max-width: 1199px) { - .site-header-inner { - gap: 32px; - padding-inline: 32px; - } - .docs-layout { - grid-template-columns: 190px minmax(0, 1fr); - gap: 32px; - padding-inline: 32px; - } - .docs-contents { - display: none; - } - .site-footer { - flex-wrap: wrap; - } - .site-footer nav { - gap: 16px; - } + gap: 0.875rem; + margin-inline: auto; } -@media (max-width: 1000px) { - .site-header-inner { - gap: 28px; - } - .primary-nav { - gap: 20px; - } - .site-search { - width: 175px; - } - .home-main { - padding-inline: 32px; - } - .showcase-workspace { - grid-template-columns: minmax(0, 1fr) 225px; - } - .showcase-evidence { - padding-inline: 20px; - } - .home-component-grid { - grid-template-columns: repeat(2, minmax(0, 1fr)); - } - .site-footer > p { - display: none; - } + +.assembled-lab__stage > [data-slot="card"] { + width: min(100%, 48rem); + margin-inline: auto; } -@media (max-width: 767px) { - .site-header-inner { - min-height: 64px; - padding-inline: 20px; - gap: 20px; - } - .site-brand > span { - font-size: 23px; - } - .site-brand > svg { - width: 28px; - height: 28px; - } - .header-tools { - gap: 6px; + +@media (max-width: 68rem) { + .specimen-topbar__inner { + grid-template-columns: auto 1fr; + padding-block: 0.75rem; } - .site-search { - width: 160px; + + .surface-switcher { + justify-self: end; } - .site-search kbd { - display: none; + + .specimen-topbar__actions { + display: grid; + width: 100%; + grid-column: 1 / -1; + grid-template-columns: minmax(0, 1fr) auto auto; } - .github-link { - display: none; + + .specimen-search { + width: 100%; } - .mobile-nav-button { - display: inline-flex; + + .specimen-shell { + min-height: 0; + grid-template-columns: 1fr; } - .primary-nav { + + .specimen-rail { + position: static; + display: block; + height: auto; + overflow-x: auto; + border-inline-end: 0; + border-block-end: 1px solid var(--border); + padding: 0.5rem clamp(1rem, 4vw, 2rem); + } + + .specimen-rail__context, + .specimen-rail__package { display: none; } - .primary-nav[data-open="true"] { - position: absolute; - top: 64px; - left: 0; - right: 0; + + .specimen-rail__nav { display: flex; - flex-direction: column; - align-items: stretch; - padding: 20px; - background: var(--card); - border-bottom: 1px solid var(--border); - } - .primary-nav a { - padding: 8px; - } - .home-main { - padding-inline: 20px; - } - .home-hero { - padding-block: 62px 46px; - } - .home-hero h1 { - font-size: clamp(44px, 8.8vw, 65px); - letter-spacing: -2.7px; - line-height: 1.13; - margin-top: 28px; - } - .home-hero h1 em { - letter-spacing: -2.4px; - } - .hero-description { - font-size: 15px; - max-width: 440px; - } - .release-note { - gap: 7px; - font-size: 14px; - } - .hero-cta { - padding-inline: 15px; - } - .hero-foundations { - gap: 12px; - flex-wrap: wrap; - justify-content: center; - } - .hero-install { + width: max-content; + min-width: 100%; + gap: 0.375rem; + margin: 0; + } + + .specimen-rail__nav a { + min-width: 9rem; + flex: 1 0 auto; + border: 1px solid transparent; + background: color-mix(in srgb, var(--card) 72%, var(--background)); + } + + .specimen-main__inner { + padding-block-start: clamp(1.5rem, 4vw, 2.5rem); + } +} + +@media (max-width: 48rem) { + .specimen-hero { + grid-template-columns: 1fr; + align-items: start; + } + + .specimen-stats { width: 100%; } - .code-block--compact pre { - min-width: 0; - font-size: 14px; - } - .section-overline { - font-size: 14px; - } - .section-overline > span:last-child { - display: none; + + .specimen-hero { + gap: 1.25rem; + margin-block-end: 2rem; + padding-block-end: 1.25rem; } - .showcase-title { - padding: 14px 16px; + + .catalog-group__header { + align-items: start; } - .showcase-title > span:first-child { - font-size: 14px; - } - .showcase-title [data-slot="badge"] { - display: none; + + .specimen-grid { + grid-template-columns: 1fr; } - .showcase-workspace { - grid-template-columns: minmax(0, 1fr); + + .specimen-card__header { + min-height: 0; } - .showcase-evidence { - display: none; - } - .showcase-conversation { - padding: 18px 18px 10px; - } - .showcase-context { - font-size: 14px; +} + +@media (max-width: 36rem) { + .specimen-topbar__inner { + gap: 0.75rem; } - .showcase-context span { + + .specimen-brand small { display: none; } - .showcase-footnote { - font-size: 14px; + + .specimen-topbar__actions { + grid-template-columns: minmax(0, 1fr) auto auto; } - .showcase-caption { - gap: 16px; - font-size: 14px; + + .specimen-search { + grid-column: auto; } - .showcase-caption > span { + + .scheme-control span { display: none; } - .home-library { - padding-top: 64px; - } - .section-heading { - flex-direction: column; - align-items: flex-start; - gap: 20px; + + .specimen-main__inner { + padding-inline: 1rem; } - .section-heading h2 { - font-size: 30px; + + .specimen-hero { + margin-block-end: 2rem; } - .home-component-grid { - gap: 12px; + + .specimen-hero h1 { + font-size: clamp(2.25rem, 11vw, 3.25rem); } - .home-component-preview { - padding: 16px; - min-height: 190px; + + .catalog { + gap: 3rem; } - .principles { - grid-template-columns: minmax(0, 1fr); - gap: 32px; - padding-block: 54px; + + .catalog-group__header { + display: grid; + gap: 0.75rem; } - .home-closing { - padding-block: 48px 64px; + + .catalog-group__count { + justify-self: start; } - .home-closing h2 { - font-size: 43px; + + .specimen-stage, + .assembled-lab__stage { + padding: 1rem; } - .site-footer { - padding: 24px 20px; - gap: 20px; - } - .site-footer nav { - margin-left: 0; - flex-wrap: wrap; - } - .site-footer nav > span { - display: none; + + .assembled-lab__stage { + min-height: 24rem; } - .docs-layout { - display: flex; - flex-direction: column; - gap: 0; - padding-inline: 20px; + + .lab-card-grid { + grid-template-columns: 1fr; } - .docs-mobile-toggle { - display: block; - padding-top: 20px; +} + +@media (max-width: 24.375rem) { + html { + scroll-padding-top: 1rem; } - .docs-sidebar { - display: none; + + .specimen-topbar { position: static; - height: auto; - max-height: 65vh; - padding-top: 24px; - padding-right: 0; - } - .docs-sidebar[data-open="true"] { - display: block; - } - .docs-main { - padding-top: 28px; - } - .docs-heading h1 { - font-size: 40px; } - .component-stage { - min-height: 240px; - padding: 24px 16px; - } - .preview-caption { - font-size: 14px; - } - .preview-caption span { + + .specimen-brand > span:last-child { display: none; } - .docs-catalog-grid { - grid-template-columns: minmax(0, 1fr); + + .specimen-brand__mark { + width: 2rem; + height: 2rem; } - .lab-main { - padding: 40px 20px 60px; + + .surface-switcher a, + .density-control button { + padding-inline: 0.45rem; + font-size: 0.6875rem; } - .lab-stage { - padding: 24px 16px; + + .specimen-topbar__actions { + gap: 0.375rem; } - .lab-card-grid { - padding: 20px 16px; - grid-template-columns: minmax(0, 1fr); - } -} -@media (max-width: 479px) { - .site-search { - width: 130px; - padding-inline: 8px; - gap: 6px; + + .specimen-hero h1 { + font-size: 2rem; } - .site-header-inner { + + .specimen-main__inner { + padding-block-start: 16px; padding-inline: 16px; } - .site-brand > span { - font-size: 21px; - } - .brand-ui { - font-size: 14px; - } - .header-tools { - gap: 2px; - } - .home-main { - padding-inline: 20px; - } - .home-hero h1 { - font-size: 43px; + + .specimen-hero { + gap: 1rem; + margin-block-end: 1.5rem; } - .release-note > .release-divider, - .release-note > .release-divider + span { - display: none; - } - .desktop-break { - display: none; - } - .hero-actions { - gap: 8px; - } - .hero-cta { - padding-inline: 12px; - font-size: 14px; + + .specimen-hero__copy > p:last-child { + font-size: 0.8125rem; + line-height: 1.5; } - .home-component-grid { - grid-template-columns: minmax(0, 1fr); - } - .guide-links { - grid-template-columns: minmax(0, 1fr); - } - .token-swatches { - grid-template-columns: repeat(2, minmax(0, 1fr)); + + .specimen-stats div { + min-width: 0; + padding-inline-start: 0.625rem; } - .search-results { - position: fixed; - top: 60px; - left: 16px; - right: 16px; - width: auto; + + .specimen-stats dt { + font-size: 0.55rem; } - .docs-pagination { - gap: 12px; + + .specimen-stage { + min-height: 14rem; + padding: 0.875rem; } } -@media (max-width: 379px) { - .site-header-inner { - gap: 8px; - } - .site-search { - width: 96px; + +@media (prefers-reduced-motion: reduce) { + .skip-link { + transition: none; } - .home-hero h1 { - font-size: 37px; - } - .hero-actions { - flex-direction: column; - align-items: stretch; - width: 100%; - } - .release-note { - flex-wrap: wrap; - justify-content: center; + + .specimen-card { + translate: none; } } -@media (prefers-reduced-motion: no-preference) { - .home-hero { - animation: appear 650ms ease-out both; - } - .showcase-section { - animation: appear 650ms 100ms ease-out both; + +@media (forced-colors: active) { + .surface-switcher a[aria-current="page"], + .density-control button[aria-pressed="true"] { + border: 1px solid Highlight; } - @keyframes appear { - from { - opacity: 0; - transform: translateY(10px); - } - to { - opacity: 1; - transform: translateY(0); - } +} + +::selection { + background: color-mix(in srgb, var(--presence) 32%, transparent); + color: var(--foreground); +} + +@media (prefers-contrast: more) { + .specimen-card, + .specimen-rail, + .specimen-topbar { + background: var(--card); + backdrop-filter: none; } } diff --git a/packages/ui/src/blocks/composer.tsx b/packages/ui/src/blocks/composer.tsx index d373773..bfc138e 100644 --- a/packages/ui/src/blocks/composer.tsx +++ b/packages/ui/src/blocks/composer.tsx @@ -1,6 +1,7 @@ "use client"; import * as React from "react"; +import { Bot, CornerDownLeft, PenLine } from "lucide-react"; import { AttachmentChip } from "@opencoven/ui/components/attachment-chip"; import { @@ -28,6 +29,7 @@ type ComposerProps = { running?: boolean; onStop?: () => void; model?: string; + tools?: React.ReactNode; density?: "default" | "compact"; className?: string; }; @@ -43,29 +45,62 @@ function Composer({ running = false, onStop, model = "GPT-5.6 Sol", + tools, density = "default", className, }: ComposerProps) { + const messageId = React.useId(); + const hintId = React.useId(); + const modeHint = { + chat: "Explore ideas without changing files.", + do: "Make changes with the context you provide.", + plan: "Map the approach before making changes.", + }[mode]; + return (
-