Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
249 changes: 0 additions & 249 deletions apps/website/src/app/global.css
Original file line number Diff line number Diff line change
Expand Up @@ -15,36 +15,6 @@
@import "../styles/marketing.css";
@import "../styles/pages.css";

/*
* Local, non-token constants.
*
* These are deliberately NOT design tokens. Promoting them to
* @threadplane/design-tokens would imply the design system owns the syntax
* theme and the docs figure treatment. It does not.
*
* The --docs-code-* group is coupled to `rehypeOptions.theme` ('tokyo-night')
* in components/docs/MdxRenderer.tsx. Change the shiki theme and these must
* change with it.
* --docs-code-title-fg is here rather than on --color-text-muted for the same
* reason: it sits on a dark surface, where the light-theme muted token drops
* to 3.6:1 contrast.
*/
:root {
--docs-code-bg: #1a1b26;
--docs-code-title-fg: #8b8fa3;
--docs-code-border: rgba(0, 0, 0, 0.1);
--docs-code-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
--docs-code-title-rule: rgba(255, 255, 255, 0.06);
--docs-figure-shadow: 0 4px 16px rgba(0, 32, 72, 0.1);
--docs-figure-shadow-bare: 0 4px 16px rgba(0, 32, 72, 0.08);
/* Accent tints in the 3.5–10% range, around --color-accent-surface (6%).
* Derived rather than hardcoded so they track the accent. */
--docs-accent-tint-faint: color-mix(in srgb, var(--color-accent) 3.5%, transparent);
--docs-accent-tint-soft: color-mix(in srgb, var(--color-accent) 8%, transparent);
--docs-accent-tint-line: color-mix(in srgb, var(--color-accent) 10%, transparent);
}


* {
box-sizing: border-box;
}
Expand Down Expand Up @@ -95,222 +65,3 @@ h1, h2, h3, h4, h5, h6 {
html {
scroll-behavior: smooth;
}

/* Shiki code blocks — tokyo-night theme */
.shiki {
padding: 1.5rem;
background: var(--docs-code-bg) !important;
overflow-x: auto;
}
.shiki code {
font-family: var(--font-mono), monospace;
font-size: 0.75rem;
line-height: 1.7;
}

/* rehype-pretty-code — docs code blocks */
.docs-prose [data-rehype-pretty-code-figure] {
margin: 1.5rem 0;
max-width: 100%;
overflow: hidden;
}

.docs-prose [data-rehype-pretty-code-figure] pre {
padding: 1.25rem 1.5rem;
border-radius: 0.75rem;
border: 1px solid var(--docs-code-border);
box-shadow: var(--docs-code-shadow);
overflow-x: auto;
font-size: 0.8rem;
line-height: 1.7;
}

.docs-prose [data-rehype-pretty-code-figure] code {
font-family: var(--font-mono), monospace;
font-size: inherit;
background: none !important;
padding: 0 !important;
border-radius: 0 !important;
color: inherit !important;
}

.docs-prose [data-rehype-pretty-code-figure] [data-line] {
padding: 0 0.25rem;
}

.docs-prose [data-rehype-pretty-code-figure] [data-rehype-pretty-code-title] {
font-family: var(--font-mono), monospace;
font-size: 0.7rem;
color: var(--docs-code-title-fg);
padding: 0.5rem 1.5rem;
background: var(--docs-code-bg);
border-bottom: 1px solid var(--docs-code-title-rule);
border-radius: 0.75rem 0.75rem 0 0;
}

.docs-prose [data-rehype-pretty-code-figure]:has([data-rehype-pretty-code-title]) pre {
border-radius: 0 0 0.75rem 0.75rem;
}

.docs-prose :not(pre) > code {
font-family: var(--font-mono), monospace;
font-size: 0.85em;
background: var(--color-accent-surface);
color: var(--color-accent);
padding: 0.15rem 0.4rem;
border-radius: 0.25rem;
font-weight: 400;
}

.docs-prose { overflow-wrap: break-word; word-break: break-word; max-width: 100%; }
.docs-prose > * { max-width: 100%; }
.docs-prose h1 { font-size: 1.875rem; font-weight: 700; margin-top: 0; margin-bottom: 1rem; font-family: var(--font-garamond); }
.docs-prose h2 { font-size: 1.5rem; font-weight: 600; margin-top: 2.5rem; margin-bottom: 1rem; font-family: var(--font-garamond); }
.docs-prose h3 { font-size: 1.25rem; font-weight: 600; margin-top: 2rem; margin-bottom: 0.75rem; font-family: var(--font-garamond); }
.docs-prose p { line-height: 1.75; margin-bottom: 1.25rem; }
.docs-prose ul, .docs-prose ol {
margin-bottom: 1.25rem;
padding-left: 1.5rem;
list-style-position: outside;
}
/* Use longhand `list-style-type` to dodge Lightning CSS shorthand rewriting
`list-style: disc` to `list-style: outside` (which drops the bullet type
and lets Tailwind's `ol, ul, menu { list-style: none }` preflight win). */
.docs-prose ul { list-style-type: disc; }
.docs-prose ol { list-style-type: decimal; }
.docs-prose li { margin-bottom: 0.5rem; line-height: 1.6; }
.docs-prose li > p { margin-bottom: 0.5rem; }
.docs-prose li::marker { color: var(--color-text-muted); }
.docs-prose ul ul, .docs-prose ol ol, .docs-prose ul ol, .docs-prose ol ul {
margin-top: 0.5rem;
margin-bottom: 0.5rem;
}

/* Figures (screenshots + caption).
* Goal: lift the screenshot off the page so it reads as a distinct artifact
* rather than an inline asset. Tinted backdrop + soft shadow + clean caption.
* Scoped to image figures via :has(> img) so it doesn't collide with the
* code-block figures from rehype-pretty-code or component figures (e.g.
* AgUiArchDiagram). */
.docs-prose figure:has(> img) {
margin: 2.5rem 0;
padding: 0.75rem 0.75rem 0;
background: var(--docs-accent-tint-faint);
border: 1px solid var(--docs-accent-tint-line);
border-radius: 0.75rem;
}
.docs-prose figure:has(> img) > img {
display: block;
width: 100%;
height: auto;
border-radius: 0.5rem;
box-shadow: var(--docs-figure-shadow);
}
.docs-prose figure:has(> img) > figcaption {
margin: 0;
padding: 0.875rem 0.5rem 0.625rem;
font-size: 0.875rem;
line-height: 1.5;
color: var(--color-text-muted);
text-align: center;
font-style: italic;
}
/* Bare images (no figure wrapper) — give them the same lift treatment. */
.docs-prose > p > img,
.docs-prose > img {
display: block;
max-width: 100%;
height: auto;
margin: 2rem auto;
border-radius: 0.5rem;
box-shadow: var(--docs-figure-shadow-bare);
}

/* Architecture diagrams are authored at exactly the width `.docs-prose`
* computes to (70ch = ~706px), so they render 1:1 and their labels stay at
* their authored size. Below that, scaling the whole figure down would take
* 11.5px labels under 5px, so the paragraph scrolls instead — the same
* treatment `.docs-table-scroll` gives a wide table. */
.docs-prose > p:has(> .docs-diagram) { overflow-x: auto; }
.docs-prose > p > img.docs-diagram { max-width: none; }

.docs-table-scroll { max-width: 100%; overflow-x: auto; margin: 1.5rem 0; }
.docs-prose table { width: 100%; border-collapse: collapse; font-size: 0.875rem; margin: 0; }
.docs-prose th { text-align: left; padding: 0.5rem 0.75rem; font-family: var(--font-mono); font-size: 0.75rem; text-transform: uppercase; color: var(--color-text-muted); border-bottom: 1px solid var(--color-accent-border); }
.docs-prose td { padding: 0.5rem 0.75rem; border-bottom: 1px solid var(--docs-accent-tint-soft); color: var(--color-text-secondary); }
.docs-prose td code { font-size: 0.8em; }

/* AG-UI architecture diagram */
.ag-ui-arch-grid {
display: grid;
grid-template-columns: 1fr auto 1fr auto 1fr;
align-items: stretch;
gap: 0;
}
@media (max-width: 720px) {
.ag-ui-arch-grid {
grid-template-columns: 1fr;
}
.ag-ui-arch-arrow {
transform: rotate(90deg);
padding: 12px 0;
margin: 4px auto;
}
}

/* Docs — readable column max-width */
.docs-prose {
max-width: 70ch;
}
@media (max-width: 768px) {
.docs-prose {
max-width: 100%;
}
}

/* Docs — hash-anchor affordance on H2/H3 */
.docs-prose h2,
.docs-prose h3 {
position: relative;
}
.docs-prose h2 .heading-anchor,
.docs-prose h3 .heading-anchor {
position: absolute;
left: -1.25em;
top: 0;
font-family: var(--font-mono);
font-weight: 400;
color: var(--color-text-muted);
opacity: 0;
text-decoration: none;
transition: opacity 120ms ease;
}
/*
* The `#` glyph is generated content, never a text node: that keeps it out of
* the heading's textContent so extracted headings ("Prerequisites") stay clean
* for search snippets, page outlines, and agents reading the DOM.
*/
.docs-prose h2 .heading-anchor::before,
.docs-prose h3 .heading-anchor::before {
content: '#';
}
.docs-prose h2:hover .heading-anchor,
.docs-prose h3:hover .heading-anchor,
.docs-prose h2 .heading-anchor:focus-visible,
.docs-prose h3 .heading-anchor:focus-visible {
opacity: 0.6;
}
.docs-prose h2 .heading-anchor:hover,
.docs-prose h3 .heading-anchor:hover {
opacity: 1;
color: var(--color-accent);
}
@media (max-width: 768px) {
/* On narrow viewports, drop the absolute positioning so the hash doesn't overlap the page edge. */
.docs-prose h2 .heading-anchor,
.docs-prose h3 .heading-anchor {
position: static;
margin-right: 6px;
display: none;
}
}
85 changes: 9 additions & 76 deletions apps/website/src/components/docs/AgUiArchDiagram.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { tokens } from '@threadplane/design-tokens';

interface BoxProps {
eyebrow: string;
title: string;
Expand All @@ -8,49 +6,15 @@ interface BoxProps {
}

function Box({ eyebrow, title, meta, tone = 'neutral' }: BoxProps) {
const isAccent = tone === 'accent';
return (
<div
style={{
background: isAccent ? tokens.colors.accentSurface : tokens.surfaces.surface,
border: `1px solid ${isAccent ? tokens.colors.accent + '33' : tokens.surfaces.border}`,
borderRadius: tokens.radius.lg,
padding: '20px 22px',
display: 'flex',
flexDirection: 'column',
gap: 6,
minHeight: 116,
}}
>
<span
style={{
fontFamily: tokens.typography.eyebrow.family,
fontSize: '0.7rem',
fontWeight: 600,
letterSpacing: '0.08em',
textTransform: 'uppercase',
color: isAccent ? tokens.colors.accent : tokens.colors.textMuted,
}}
>
<div className="ag-ui-arch-box" data-tone={tone}>
<span className="ag-ui-arch-box-eyebrow">
{eyebrow}
</span>
<span
style={{
fontFamily: tokens.typography.fontMono,
fontSize: '0.95rem',
fontWeight: 600,
color: tokens.colors.textPrimary,
}}
>
<span className="ag-ui-arch-box-title">
{title}
</span>
<span
style={{
fontSize: '0.85rem',
lineHeight: 1.5,
color: tokens.colors.textSecondary,
}}
>
<span className="ag-ui-arch-box-meta">
{meta}
</span>
</div>
Expand All @@ -62,30 +26,11 @@ function ArrowLabel({ label, sub }: { label: string; sub: string }) {
<div
aria-hidden
className="ag-ui-arch-arrow"
style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
gap: 4,
color: tokens.colors.textMuted,
padding: '0 4px',
}}
>
<span
style={{
fontFamily: tokens.typography.eyebrow.family,
fontSize: '0.65rem',
fontWeight: 600,
letterSpacing: '0.08em',
textTransform: 'uppercase',
color: tokens.colors.accent,
whiteSpace: 'nowrap',
}}
>
<span className="ag-ui-arch-arrow-label">
{label}
</span>
<svg width="44" height="14" viewBox="0 0 44 14" fill="none" style={{ display: 'block' }}>
<svg width="44" height="14" viewBox="0 0 44 14" fill="none" className="ag-ui-arch-arrow-svg">
<path
d="M2 7 H36 M30 2 L36 7 L30 12"
stroke="currentColor"
Expand All @@ -94,7 +39,7 @@ function ArrowLabel({ label, sub }: { label: string; sub: string }) {
strokeLinejoin="round"
/>
</svg>
<span style={{ fontSize: '0.72rem', color: tokens.colors.textMuted, whiteSpace: 'nowrap' }}>
<span className="ag-ui-arch-arrow-sub">
{sub}
</span>
</div>
Expand All @@ -104,13 +49,7 @@ function ArrowLabel({ label, sub }: { label: string; sub: string }) {
export function AgUiArchDiagram() {
return (
<figure
style={{
margin: '2rem 0',
padding: '28px 24px',
background: tokens.surfaces.canvas,
border: `1px solid ${tokens.surfaces.border}`,
borderRadius: tokens.radius.lg,
}}
className="ag-ui-arch-figure"
>
<div className="ag-ui-arch-grid">
<Box
Expand All @@ -133,13 +72,7 @@ export function AgUiArchDiagram() {
/>
</div>
<figcaption
style={{
marginTop: 16,
fontSize: '0.8rem',
color: tokens.colors.textMuted,
textAlign: 'center',
fontStyle: 'italic',
}}
className="ag-ui-arch-caption"
>
Backend speaks AG-UI over SSE → adapter exposes a signal-shaped Agent contract → chat UI renders.
</figcaption>
Expand Down
Loading
Loading