返回 CodeWhale
globals.css
根目录 / web / app / globals.css
1 @import "./tokens.css";
2
3 @tailwind base;
4 @tailwind components;
5 @tailwind utilities;
6
7 /* ---------- root tokens — GPUI theme ---------- */
8 /*
9 * The site is a folio read in the product client's light: warm paper at the
10 * surface, warm charcoal at depth. Above the waterline the field is the GPUI
11 * light theme's paper and the ink is its plum-charcoal foreground. Below the
12 * waterline (`.ocean-column`, the footer, every terminal plate) the same
13 * names resolve to the dark charcoal tokens, so a component written once
14 * reads correctly on either side.
15 *
16 * The token NAMES keep their historical shape (`--paper`, `--ink`,
17 * `--indigo`) so every component rule stays diffable; the VALUES resolve
18 * through the `--gpui-*` block below, which now references the generated
19 * Shoreline tokens in ./tokens.css (crates/palette/src/tokens.rs is the
20 * single source — the same constants the GPUI client and the TUI open on).
21 * Only values with no Shoreline slot stay literal: the hover tones, the
22 * accent washes, and the AA-adapted state hues. `--whale-*`/`--light-*`
23 * remain available to anything that genuinely wants the terminal palette.
24 */
25 :root {
26 /* --- The GPUI source palette (generated Shoreline slots) --- */
27 --gpui-paper: var(--shoreline-light-surface); /* light background — warm paper */
28 --gpui-paper-raised: var(--shoreline-light-elevated); /* light card/popover */
29 --gpui-paper-muted: var(--shoreline-light-panel); /* light muted surface */
30 --gpui-ink: var(--shoreline-light-text-body); /* light foreground */
31 --gpui-ink-soft: var(--shoreline-light-text-soft);
32 --gpui-ink-mute: var(--shoreline-light-text-muted); /* light muted_foreground */
33 --gpui-edge: var(--shoreline-light-border); /* light border */
34 --gpui-primary: var(--shoreline-light-action); /* light primary */
35 --gpui-primary-hover: #00536d; /* light button_primary_hover — no Shoreline slot */
36 --gpui-accent: #dcebee; /* light accent — no Shoreline slot */
37 --gpui-selection: var(--shoreline-light-selection); /* light selection */
38
39 --gpui-stage: var(--shoreline-surface); /* dark background — warm charcoal */
40 --gpui-stage-deep: var(--shoreline-chrome); /* deepest dark */
41 --gpui-stage-muted: var(--shoreline-panel); /* dark muted surface */
42 --gpui-stage-raised: var(--shoreline-elevated); /* raised dark plate */
43 --gpui-stage-ink: var(--shoreline-text-body); /* dark foreground */
44 --gpui-stage-ink-soft: var(--shoreline-text-muted); /* dark muted_foreground */
45 --gpui-stage-ink-dim: var(--shoreline-text-dim);
46 --gpui-stage-edge: var(--shoreline-border); /* dark border */
47 --gpui-primary-dark: var(--shoreline-action); /* dark primary */
48 --gpui-primary-hover-dark: #93cde1; /* dark button_primary_hover — no Shoreline slot */
49 --gpui-on-primary: #102d38; /* dark primary_foreground — no Shoreline slot */
50 --gpui-accent-dark: #303f48; /* dark accent — no Shoreline slot */
51 --gpui-selection-dark: var(--shoreline-selection); /* dark selection */
52
53 /* Warm-muted state hues from the GPUI mockups, darkened or lifted per
54 side of the waterline so text uses of them still clear AA. No Shoreline
55 slots: these are site-specific adaptations. */
56 --gpui-tan: #b1a17a; /* human mark */
57 --gpui-moss: #739686; /* outcome */
58 --gpui-rust: #aa6f6c; /* attention */
59
60 /* RGB channel triples backing the Tailwind surface/ink tokens (see
61 tailwind.config.ts). `.ocean-column` and the opt-in docs dark sheet
62 override them for their dark subtree. */
63 --c-paper: var(--shoreline-light-surface-rgb);
64 --c-paper-deep: var(--shoreline-light-panel-rgb);
65 --c-paper-edge: var(--shoreline-light-border-rgb);
66 --c-ink: var(--shoreline-light-text-body-rgb);
67 --c-ink-soft: var(--shoreline-light-text-soft-rgb);
68 --c-ink-mute: var(--shoreline-light-text-muted-rgb);
69 --c-indigo: var(--shoreline-light-action-rgb);
70 --c-indigo-deep: 0 83 109; /* light primary hover — no Shoreline slot */
71 --c-stage-soft: var(--shoreline-text-muted-rgb);
72 --c-stage-deep: var(--shoreline-chrome-rgb);
73 --c-primary-dark: var(--shoreline-action-rgb);
74
75 /* The sheet. */
76 --paper: var(--gpui-paper);
77 --paper-deep: var(--gpui-paper-muted);
78 --paper-edge: var(--gpui-edge);
79 --paper-card: var(--gpui-paper-raised);
80 --paper-line: var(--gpui-edge);
81 --paper-line-soft: var(--gpui-edge);
82 --ink: var(--gpui-ink);
83 --ink-soft: var(--gpui-ink-soft);
84 --ink-mute: var(--gpui-ink-mute);
85 /* Action on paper is the GPUI light primary; hover sinks to its hover. */
86 --indigo: var(--gpui-primary);
87 --indigo-deep: var(--gpui-primary-hover);
88 --indigo-pale: rgb(var(--c-indigo) / 0.1);
89 --action-on-dark: var(--gpui-primary-dark);
90 /* State inks darkened from the mockup hues so they clear AA on paper:
91 moss is outcome, rust is attention, tan is the human mark. */
92 --ochre: #7d6a3f;
93 --jade: #4e6f61;
94 --seafoam: var(--gpui-moss);
95 --cobalt: var(--gpui-primary);
96 --cyan: var(--gpui-primary); /* reserved for the composer prompt glyph and the release line */
97 --ocean-deep: var(--gpui-stage-deep);
98 --ocean-mid: var(--gpui-stage-muted);
99 --ocean-current: var(--gpui-primary-dark);
100 --ocean-mist: var(--gpui-stage-ink-soft);
101 --ocean-coral: #8f5a56;
102 --signal-gold: #7d6a3f;
103 /* The whale mark is ink on paper; below the waterline it is the light
104 stage foreground. The warm tan stays reserved for human moments. */
105 --mark-ink: var(--gpui-ink);
106 --stage-text: var(--gpui-stage-ink);
107 --stage-soft: var(--gpui-stage-ink-soft);
108 --stage-muted: var(--gpui-stage-ink-dim);
109
110 /* The water column, re-inked in the GPUI dark ramp. */
111 --stage-field-top: var(--gpui-stage-muted); /* surface */
112 --stage-field-mid: var(--gpui-stage); /* the authored 42% break */
113 --stage-field-deep: var(--gpui-stage-deep); /* deep field, and the footer seabed */
114 --stage-ambient: var(--gpui-accent-dark);
115 --stage-composer: var(--gpui-stage-muted); /* the raised input plate */
116 --stage-elevated: var(--gpui-stage-raised);
117 --stage-line: var(--gpui-stage-edge); /* the charcoal border on stage */
118 --stage-hint: var(--gpui-stage-ink-dim);
119 --stage-dim: var(--gpui-stage-ink-soft);
120 --violet: var(--gpui-selection-dark); /* 1px rules only, never text */
121
122 /* Newsreader carries h1/h2; Shannon Sans supplies body and small headings.
123 The historic condensed role keeps its scale and weight, not a second face.
124 IBM Plex Mono and the Unicode fallback stacks retain their own roles. */
125 --font-body: var(--font-shannon-sans);
126 --font-display: var(--font-shannon-sans);
127 --font-cjk: "PingFang SC", "Hiragino Sans GB", "Source Han Serif SC",
128 "Noto Serif CJK SC", serif;
129
130 /* Hairline + code surfaces routed through vars so the dark subtrees can
131 re-ink them without touching every rule. Code plates are always the
132 stage's own deepest field, on either side of the waterline. */
133 --hairline: rgb(var(--c-ink) / 0.16);
134 --code-bg: var(--gpui-stage-deep);
135 --code-fg: var(--gpui-stage-ink);
136
137 /* One site container and one vertical rhythm. Every page gutter aligns
138 with the nav; every hero and section shares a single padding token. */
139 --container: min(100% - 2rem, 76rem);
140 --hero-pad: clamp(3rem, 6vw, 4.75rem);
141 --section-pad: clamp(2.75rem, 5vw, 4rem);
142 color-scheme: light;
143 }
144
145 /*
146 * Below the waterline. One rule, applied to every dark subtree — the water
147 * column on the homepage, the footer seabed, the opt-in docs dark sheet
148 * (`.docs-portal` is the docs layout root, which also carries `.docs-theme`)
149 * — so a component never needs to know which side of the surface it is on.
150 */
151 .ocean-column,
152 .site-footer,
153 html[data-theme="dark"] .docs-portal {
154 --c-paper: var(--shoreline-surface-rgb);
155 --c-paper-deep: var(--shoreline-panel-rgb);
156 --c-paper-edge: var(--shoreline-border-rgb);
157 --c-ink: var(--shoreline-text-body-rgb);
158 --c-ink-soft: var(--shoreline-text-muted-rgb);
159 --c-ink-mute: var(--shoreline-text-dim-rgb);
160 --c-indigo: var(--shoreline-action-rgb);
161 --c-indigo-deep: 147 205 225; /* lifted primary — hover on dark, no Shoreline slot */
162 --paper: var(--gpui-stage);
163 --paper-deep: var(--gpui-stage-muted);
164 --paper-edge: var(--gpui-stage-edge);
165 --paper-card: var(--gpui-stage-muted);
166 --paper-line: var(--gpui-stage-edge);
167 --paper-line-soft: var(--gpui-stage-edge);
168 --ink: var(--gpui-stage-ink);
169 --ink-soft: var(--gpui-stage-ink-soft);
170 --ink-mute: var(--gpui-stage-ink-dim);
171 --indigo: var(--gpui-primary-dark);
172 --indigo-deep: var(--gpui-primary-hover-dark);
173 --indigo-pale: rgb(var(--c-primary-dark) / 0.14);
174 --ochre: #d6c78f;
175 --jade: #9ec7b2;
176 --cyan: var(--gpui-primary-dark);
177 --ocean-coral: #d08a80;
178 --signal-gold: #d6c78f;
179 --mark-ink: var(--gpui-stage-ink);
180 --hairline: rgb(var(--c-stage-soft) / 0.2);
181 color-scheme: dark;
182 }
183 /* ---------- base ---------- */
184 html {
185 -webkit-font-smoothing: antialiased;
186 -moz-osx-font-smoothing: grayscale;
187 max-width: 100%;
188 overflow-x: clip;
189 }
190
191 body {
192 /* The sheet: one opaque paper field. The descent into the water is drawn
193 by the waterline band and the ocean column, never by a page gradient. */
194 background: var(--paper);
195 color: var(--ink);
196 font-family: var(--font-body), "Noto Sans SC", system-ui, sans-serif;
197 font-feature-settings: "ss01", "cv11", "tnum";
198 max-width: 100%;
199 overflow-x: clip;
200 position: relative;
201 }
202
203 .codewhale-mark-primary { fill: var(--mark-ink); }
204
205 main, header, footer, nav { position: relative; z-index: 1; }
206
207 /* ---------- type ---------- */
208 /* The folio voice: Newsreader for the big headings, set at book weight with
209 a little negative tracking so it reads as a title page rather than a
210 blog. Small headings use the shared Shannon Sans label face. */
211 .font-display { font-family: var(--font-serif), "Newsreader", Georgia, "Times New Roman", serif; font-weight: 500; }
212 .font-serif { font-family: var(--font-serif), "Newsreader", Georgia, "Times New Roman", serif; }
213 .font-condensed { font-family: var(--font-display), ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif; font-weight: 600; }
214 .font-cjk { font-family: var(--font-cjk), "PingFang SC", "Source Han Serif SC", serif; }
215
216 /* CJK paragraph rhythm — looser leading, wider tracking for body; tighter for headings */
217 .cjk-body {
218 line-height: 1.9;
219 letter-spacing: 0.02em;
220 word-break: break-all;
221 }
222 .cjk-heading {
223 letter-spacing: -0.01em;
224 }
225 .cjk-prose p {
226 line-height: 1.9;
227 letter-spacing: 0.02em;
228 }
229 /* Full-width punctuation should use CJK spacing */
230 .cjk-prose {
231 font-feature-settings: "halt", "pwid";
232 }
233 .font-mono { font-family: var(--font-mono), "IBM Plex Mono", ui-monospace, monospace; }
234
235 /* ---------- the ` · ` chain ---------- */
236 /* The single most recognisable thing about the TUI — its header, empty state
237 and footer all speak in dot chains — and the grammar the product's voice is
238 carried by on this site, on both sides of the waterline. The separator is
239 punctuation emitted by CSS, never copy: no locale translates it, and no
240 string is ever concatenated around one. No uppercase and no wide tracking:
241 the TUI header has neither, and both are what break Han. */
242 .dotline {
243 display: flex;
244 flex-wrap: wrap;
245 align-items: baseline;
246 font-family: var(--font-mono), "IBM Plex Mono", ui-monospace, monospace;
247 font-size: 0.75rem;
248 letter-spacing: 0.02em;
249 text-transform: none;
250 }
251
252 /* The separator hangs off the END of the preceding item, not the start of the
253 next one. When a long chain wraps, a line ending in `·` reads as
254 continuation; a line beginning with one reads as a bullet list. */
255 .dotline > *:not(:last-child)::after {
256 content: "·";
257 margin-inline: 0.5em;
258 color: var(--stage-dim);
259 }
260
261 html[lang="zh"] .dotline,
262 html[lang="ja"] .dotline,
263 html[lang="ko"] .dotline {
264 letter-spacing: 0;
265 }
266
267 h1, h2 {
268 font-family: var(--font-serif), "Newsreader", Georgia, "Times New Roman", serif;
269 font-weight: 500;
270 letter-spacing: -0.022em;
271 color: var(--ink);
272 text-wrap: balance;
273 }
274 h3, h4 {
275 font-family: var(--font-display), ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
276 font-weight: 600;
277 letter-spacing: -0.01em;
278 color: var(--ink);
279 }
280
281 h1 { font-size: clamp(2.5rem, 5.6vw, 5rem); line-height: 1.02; word-break: keep-all; overflow-wrap: anywhere; }
282 h2 { font-size: clamp(1.6rem, 2.9vw, 2.6rem); line-height: 1.1; word-break: keep-all; overflow-wrap: anywhere; }
283 h3, h4 { font-size: 1.12rem; line-height: 1.25; font-weight: 600; }
284 h1.font-display, h2.font-display { font-weight: 500; }
285 /* Han has no serif/sans distinction to spend; the CJK stack already leads
286 with a serif. */
287 html[lang="zh"] h1, html[lang="ja"] h1, html[lang="ko"] h1,
288 html[lang="zh"] h2, html[lang="ja"] h2, html[lang="ko"] h2 { letter-spacing: 0; font-weight: 600; }
289
290 /* `overflow-wrap: anywhere` keeps long English headings safe, but can strand
291 CJK punctuation — or a lone numeral — on a line of its own. Strict CJK
292 line-breaking keeps punctuation attached while still allowing breaks between
293 Han characters. ja and ko want the same rule: ja for the identical reason as
294 zh, ko because it has real word boundaries and should break on them. */
295 html[lang="zh"] h1,
296 html[lang="zh"] h2,
297 html[lang="zh"] h3,
298 html[lang="ja"] h1,
299 html[lang="ja"] h2,
300 html[lang="ja"] h3,
301 html[lang="ko"] h1,
302 html[lang="ko"] h2,
303 html[lang="ko"] h3 {
304 line-break: strict;
305 word-break: normal;
306 overflow-wrap: break-word;
307 }
308
309 @media (max-width: 640px) {
310 h1 .font-cjk {
311 display: inline-block;
312 font-size: clamp(1.6rem, 7.5vw, 2.2rem);
313 overflow-wrap: anywhere;
314 }
315 /* Keep headings inside the viewport without inserting awkward English hyphens. */
316 h1, h2 { hyphens: auto; }
317 html[lang="en"] h1,
318 html[lang="en"] h2 { hyphens: none; }
319 }
320
321 /* ---------- structural primitives ---------- */
322 /* One hairline everywhere: action blue at low alpha, visible on the deep
323 field without ever becoming a border wall. */
324 .hairline { border-color: var(--hairline); }
325 .hairline-t { border-top: 1px solid var(--hairline); }
326 .hairline-b { border-bottom: 1px solid var(--hairline); }
327 .hairline-l { border-left: 1px solid var(--hairline); }
328 .hairline-r { border-right: 1px solid var(--hairline); }
329
330 /* The single site container: width + auto margins so every page's gutters
331 line up with the nav. */
332 .site-container {
333 width: var(--container);
334 margin-inline: auto;
335 }
336
337 /* The single hero band shared by home, docs, and the community portals: a
338 quiet, flat stage surface against the deep field. */
339 .hero {
340 position: relative;
341 overflow: hidden;
342 border-bottom: 1px solid var(--hairline);
343 background: transparent;
344 color: var(--ink);
345 padding-block: var(--hero-pad);
346 }
347
348 /* The single section rhythm for per-route hero/section blocks. */
349 .section {
350 padding-block: var(--section-pad);
351 }
352
353 .double-rule {
354 background-image:
355 linear-gradient(var(--hairline), var(--hairline)),
356 linear-gradient(var(--hairline), var(--hairline));
357 background-size: 100% 1px, 100% 1px;
358 background-position: top, bottom;
359 background-repeat: no-repeat;
360 padding: 0.45rem 0;
361 }
362
363 .col-rule > * + * {
364 border-left: 1px solid var(--hairline);
365 }
366 /* Single-column phones: drop the column rules so cards stack flush. */
367 @media (max-width: 767px) {
368 .col-rule > * + * { border-left: 0; border-top: 1px solid var(--hairline); }
369 }
370
371 /* small-caps eyebrow — muted mono chrome for compact labels */
372 .eyebrow {
373 font-family: var(--font-mono), "IBM Plex Mono", monospace;
374 font-size: 0.7rem;
375 font-weight: 500;
376 letter-spacing: 0.18em;
377 text-transform: uppercase;
378 color: var(--ink-mute);
379 }
380
381 /* ---------- compact section marker ---------- */
382 /* The seal keeps its Han glyph but speaks as Tideline chrome now: a bordered
383 stage plate with muted ink, not an ink block on paper. */
384 .seal {
385 display: inline-flex;
386 align-items: center;
387 justify-content: center;
388 background: var(--paper-deep);
389 border: 1px solid var(--stage-line);
390 color: var(--ink-mute);
391 font-family: var(--font-cjk), "PingFang SC", serif;
392 font-weight: 700;
393 width: 2.6rem;
394 height: 2.6rem;
395 border-radius: 6px;
396 letter-spacing: -0.04em;
397 }
398
399 /* Action-blue variant for the few routes that need a stronger section marker. */
400 .seal-indigo {
401 color: var(--indigo);
402 border-color: color-mix(in srgb, var(--indigo) 55%, transparent);
403 }
404
405 /* Below the waterline the seal stays the same plate — the whole page is water
406 now, so there is nothing left to invert. */
407 .ocean-column .seal {
408 background: var(--stage-elevated);
409 color: var(--ink-mute);
410 }
411
412 /* ---------- pills / status ---------- */
413 .pill {
414 display: inline-flex;
415 align-items: center;
416 gap: 0.35rem;
417 padding: 0.12rem 0.45rem;
418 font-family: var(--font-mono), monospace;
419 font-size: 0.7rem;
420 font-weight: 500;
421 letter-spacing: 0.06em;
422 text-transform: uppercase;
423 border: 1px solid var(--paper-line);
424 background: var(--paper-deep);
425 color: var(--ink);
426 }
427 .pill-hot { background: var(--indigo); color: var(--paper); border-color: var(--indigo); }
428 .pill-new { background: var(--paper-deep); color: var(--ink); border-color: var(--ink-mute); }
429 .pill-jade { background: var(--jade); color: var(--paper); border-color: var(--jade); }
430 .pill-ochre { background: var(--ochre); color: var(--paper); border-color: var(--ochre); }
431 .pill-ghost { background: transparent; color: var(--ink-mute); border-color: var(--ink-mute); }
432
433 /* ---------- numbers ---------- */
434 .tabular { font-variant-numeric: tabular-nums; }
435 .bignum {
436 font-family: var(--font-body), system-ui, sans-serif;
437 font-weight: 600;
438 font-size: 2.2rem;
439 line-height: 1;
440 letter-spacing: -0.04em;
441 font-variant-numeric: tabular-nums;
442 }
443
444 /* ---------- code blocks ---------- */
445 pre.code-block {
446 background: var(--code-bg);
447 color: var(--code-fg);
448 max-width: 100%;
449 min-width: 0;
450 padding: 1rem 1.1rem;
451 font-family: var(--font-mono), monospace;
452 font-size: 0.82rem;
453 line-height: 1.55;
454 border: 1px solid var(--stage-line);
455 border-radius: 6px;
456 overflow-x: auto;
457 position: relative;
458 white-space: pre;
459 -webkit-overflow-scrolling: touch;
460 }
461 pre.code-block::before {
462 content: "";
463 position: absolute;
464 top: 0; left: 0; right: 0;
465 height: 1px;
466 background: var(--hairline);
467 }
468 pre.code-block .prompt { color: var(--action-on-dark); }
469 pre.code-block .comment { color: var(--gpui-stage-ink-dim); }
470 pre.code-block .key { color: var(--signal-gold); }
471
472 @media (max-width: 640px) {
473 pre.code-block { font-size: 0.76rem; padding: 0.85rem 0.95rem; }
474 }
475
476 code.inline {
477 background: var(--paper-deep);
478 border: 1px solid var(--hairline);
479 padding: 0.05rem 0.32rem;
480 font-family: var(--font-mono), monospace;
481 font-size: 0.85em;
482 border-radius: 2px;
483 }
484
485
486 /* ---------- search ---------- */
487 .search-input {
488 font-family: var(--font-body), system-ui, sans-serif;
489 font-size: 1rem;
490 padding: 0.75rem 2.5rem 0.75rem 1rem;
491 background: var(--paper);
492 color: var(--ink);
493 border: 1px solid var(--hairline);
494 transition: border-color 180ms ease, box-shadow 180ms ease;
495 }
496 .search-input::placeholder { color: var(--ink-mute); }
497 .search-input:focus {
498 outline: none;
499 border-color: var(--indigo);
500 box-shadow: 0 0 0 3px var(--indigo-pale);
501 }
502
503 mark.search-highlight {
504 background: var(--indigo-pale);
505 color: var(--indigo-deep);
506 padding: 0.02em 0.08em;
507 border-radius: 2px;
508 }
509
510 /* ---------- nav link ---------- */
511 .site-nav {
512 position: sticky;
513 z-index: 30;
514 top: 0;
515 border-bottom: 1px solid var(--hairline);
516 background: rgb(var(--c-paper) / 0.94);
517 backdrop-filter: blur(10px);
518 }
519
520 .site-nav-inner {
521 display: flex;
522 width: var(--container);
523 min-height: 4.25rem;
524 align-items: center;
525 justify-content: space-between;
526 gap: 1.5rem;
527 margin-inline: auto;
528 }
529
530 .site-wordmark {
531 display: inline-flex;
532 flex-shrink: 0;
533 align-items: center;
534 gap: 0.7rem;
535 color: var(--ink);
536 font-family: var(--font-display), ui-sans-serif, system-ui, sans-serif;
537 font-size: 1.15rem;
538 font-weight: 600;
539 letter-spacing: -0.03em;
540 }
541
542 .paper-nav-inner {
543 min-height: 3.85rem;
544 padding-block: 0.55rem;
545 }
546
547 .paper-wordmark {
548 flex: 0 1 auto;
549 gap: 0.75rem;
550 max-width: 15rem;
551 min-width: 8.75rem;
552 overflow: hidden;
553 }
554
555 .paper-wordmark-text {
556 display: flex;
557 align-items: center;
558 gap: 8px;
559 line-height: 1.1;
560 min-width: 0;
561 }
562
563 .paper-wordmark-mark {
564 display: block;
565 flex: 0 0 auto;
566 width: 22px;
567 height: 22px;
568 }
569
570 /* The traced wordmark is ~7.1:1; when the compact nav clamps its width the
571 glyphs scale down inside the box instead of squashing. */
572 .paper-wordmark-logo {
573 display: block;
574 flex: 0 1 auto;
575 width: auto;
576 min-width: 0;
577 max-width: 100%;
578 height: 20px;
579 object-fit: contain;
580 object-position: left center;
581 }
582
583 .paper-star-badge {
584 font-family: var(--font-mono), "IBM Plex Mono", monospace;
585 font-size: 0.75rem;
586 letter-spacing: 0.04em;
587 text-transform: uppercase;
588 }
589
590 .paper-install-cta {
591 align-items: center;
592 min-height: 2.25rem;
593 padding: 0.35rem 0.85rem;
594 background: var(--indigo-deep);
595 color: var(--paper);
596 font-family: var(--font-mono), "IBM Plex Mono", monospace;
597 font-size: 0.7rem;
598 font-weight: 600;
599 letter-spacing: 0.1em;
600 text-transform: uppercase;
601 border-radius: 5px;
602 transition: background-color 150ms ease;
603 }
604
605 .paper-install-cta:hover {
606 background: var(--indigo);
607 color: var(--paper);
608 }
609
610 .paper-auth {
611 display: inline-flex;
612 align-items: center;
613 gap: 0.5rem;
614 }
615
616 .paper-auth-signin,
617 .paper-auth-register {
618 align-items: center;
619 min-height: 2.25rem;
620 padding: 0.35rem 0.75rem;
621 font-family: var(--font-mono), "IBM Plex Mono", monospace;
622 font-size: 0.7rem;
623 font-weight: 600;
624 letter-spacing: 0.08em;
625 text-transform: uppercase;
626 transition: background-color 150ms ease, color 150ms ease, border-color 150ms ease;
627 }
628
629 .paper-auth-signin,
630 .paper-auth-register {
631 color: var(--ink);
632 }
633
634 .paper-auth-signin:hover,
635 .paper-auth-register:hover {
636 color: var(--indigo);
637 }
638
639 .site-nav-actions {
640 display: flex;
641 flex-shrink: 0;
642 align-items: center;
643 gap: 0.65rem;
644 }
645
646 .site-nav-actions > * { flex-shrink: 0; }
647
648 /* Native <select> sizes to the selected option (Safari) or the longest
649 option (Chrome). Unbounded, "Bahasa Indonesia (sebagian)" / "Deutsch
650 (teilweise)" push the compact controls past overflow-x: clip. */
651 .site-nav-actions select {
652 width: 6.75rem;
653 max-width: 6.75rem;
654 min-width: 0;
655 }
656
657 .site-github-link {
658 display: inline-flex;
659 min-height: 2.25rem;
660 align-items: center;
661 padding: 0.35rem 0.75rem;
662 border: 1px solid var(--hairline);
663 border-radius: 6px;
664 font-family: var(--font-body), system-ui, sans-serif;
665 font-size: 0.75rem;
666 font-weight: 600;
667 }
668
669 .site-github-link:hover { border-color: var(--ink); }
670
671 .brand-mark { width: 1rem; height: 1rem; display: block; }
672
673 .paper-star-badge .brand-mark { margin-right: 0.3rem; }
674
675 .nav-link {
676 font-family: var(--font-body), system-ui, sans-serif;
677 font-size: 0.78rem;
678 letter-spacing: 0;
679 color: var(--ink);
680 position: relative;
681 padding: 0.25rem 0;
682 }
683 .nav-link::after {
684 content: "";
685 position: absolute;
686 left: 0; right: 0; bottom: -2px;
687 height: 2px;
688 background: var(--indigo);
689 transform: scaleX(0);
690 transform-origin: left;
691 transition: transform 180ms ease;
692 }
693 .nav-link:hover::after, .nav-link[aria-current="page"]::after { transform: scaleX(1); }
694
695 /* ---------- footer ---------- */
696 .site-footer {
697 position: relative;
698 background: var(--ocean-deep);
699 color: var(--stage-soft);
700 }
701
702 /* The waterline before the seabed. Every page that is still on paper when
703 it reaches the footer descends here; the homepage is already under water
704 by then, so its column hides the band and the seabed simply continues. */
705 .site-footer-waterline {
706 position: relative;
707 height: clamp(9rem, 18vw, 15rem);
708 overflow: hidden;
709 background: var(--paper);
710 }
711 .site-footer-waterline > svg {
712 position: absolute;
713 inset: 0;
714 width: 100%;
715 height: 100%;
716 }
717 main:has(.ocean-column) + .site-footer .site-footer-waterline { display: none; }
718 .site-footer-main { border-top: 1px solid rgb(var(--c-stage-soft) / 0.13); }
719 main:has(.ocean-column) + .site-footer .site-footer-main { border-top-color: transparent; }
720
721 .site-footer-main,
722 .site-footer-meta {
723 width: var(--container);
724 margin-inline: auto;
725 }
726
727 .site-footer-main {
728 display: grid;
729 grid-template-columns: minmax(16rem, 1.25fr) minmax(18rem, 0.75fr);
730 gap: 4rem;
731 padding-block: 2.8rem;
732 }
733
734 .site-wordmark-footer { color: var(--stage-text); }
735 .site-wordmark-footer img { display: block; width: auto; height: 18px; }
736 .site-footer-brand p { max-width: 30rem; margin-top: 0.8rem; color: rgb(var(--c-stage-soft) / 0.62); font-size: 0.86rem; line-height: 1.6; }
737
738 .site-footer-links {
739 display: grid;
740 grid-template-columns: repeat(2, minmax(0, 1fr));
741 gap: 2rem;
742 }
743
744 .site-footer-links > div { display: flex; flex-direction: column; gap: 0.55rem; }
745 .site-footer-links span { margin-bottom: 0.25rem; color: var(--ocean-current); font-family: var(--font-mono), "IBM Plex Mono", monospace; font-size: 0.75rem; letter-spacing: 0.1em; text-transform: uppercase; }
746 .site-footer-links a { color: rgb(var(--c-stage-soft) / 0.76); font-size: 0.82rem; }
747 .site-footer-links a:hover { color: var(--stage-text); }
748
749 .site-footer-meta {
750 display: grid;
751 grid-template-columns: 1fr auto auto;
752 gap: 1.5rem;
753 align-items: center;
754 padding-block: 1rem;
755 border-top: 1px solid rgb(var(--c-stage-soft) / 0.13);
756 color: rgb(var(--c-stage-soft) / 0.5);
757 font-family: var(--font-mono), "IBM Plex Mono", monospace;
758 font-size: 0.75rem;
759 }
760
761 .site-footer-meta a:hover { color: var(--ocean-current); }
762 .site-footer-meta > div { display: flex; gap: 1rem; }
763 .site-footer-meta > p { min-width: 0; max-width: 70ch; overflow-wrap: anywhere; }
764
765 /* ---------- ticker ---------- */
766 .ticker-viewport {
767 position: relative;
768 flex: 1 1 auto;
769 overflow: hidden;
770 }
771
772 .ticker-track {
773 display: inline-flex;
774 gap: 3rem;
775 white-space: nowrap;
776 animation: ticker 80s linear infinite;
777 padding-right: 3rem;
778 }
779 @keyframes ticker {
780 from { transform: translateX(0); }
781 to { transform: translateX(-50%); }
782 }
783
784 /* One wire entry: verb, number or tag, title, by-line, age. Baseline-aligned
785 so the mono verb sits on the same line as the title it qualifies. */
786 .ticker-item {
787 display: inline-flex;
788 align-items: baseline;
789 gap: 0.5rem;
790 }
791
792 /* The verb carries the state. Merges are the headline case, so they get the
793 one warm-neutral ink on the sheet; releases take ochre; anything closed
794 recedes to mute. Everything else is the action blue. */
795 .ticker-verb {
796 color: var(--indigo);
797 font-size: 0.7rem;
798 letter-spacing: 0.12em;
799 text-transform: uppercase;
800 }
801
802 .ticker-verb[data-event="merged"] { color: var(--jade); }
803 .ticker-verb[data-event="published"] { color: var(--ochre); }
804 .ticker-verb[data-event="closed"] { color: var(--ink-mute); }
805
806 .ticker-num,
807 .ticker-tag,
808 .ticker-by,
809 .ticker-age {
810 color: var(--ink-mute);
811 }
812
813 .ticker-title {
814 color: var(--ink);
815 max-width: 24rem;
816 overflow: hidden;
817 text-overflow: ellipsis;
818 white-space: nowrap;
819 }
820
821 /* The contributor's handle is the point of the line, not a footnote. */
822 .ticker-handle {
823 color: var(--ink);
824 font-weight: 600;
825 }
826
827 .ticker-first {
828 padding: 0 0.35rem;
829 border: 1px solid var(--ochre);
830 color: var(--ochre);
831 font-size: 0.7rem;
832 letter-spacing: 0.1em;
833 text-transform: uppercase;
834 }
835
836 .ticker-sep { color: var(--paper-line-soft); }
837
838 @media (prefers-reduced-motion: reduce) {
839 .ticker-track { animation: none; }
840 /* A frozen track would clip every entry past the fold with no way to reach
841 them. Stopping the motion must not also remove the content. */
842 .ticker-viewport { overflow-x: auto; }
843 }
844
845 /* ---------- ambient ---------- */
846 /*
847 * Two effects, both OPT-IN under `no-preference` rather than opted out under
848 * `reduce`. A `reduce` override can be defeated by specificity; a gate cannot.
849 * Reduced motion freezes the field — it never removes it, so the column's
850 * gradient and the whale below are unconditional and only the movement is not.
851 *
852 * The TUI's ambient life — fish, jellyfish, bubbles, the whale cameo — stays
853 * out of scope. This page quotes the product's restraint doctrine in its own
854 * copy. The standing loops on the whole site are four — ticker, caret, and
855 * these two. Entrances are transitions, and the one-shot settles live in the
856 * Motion section below under the same no-preference gate.
857 */
858
859 /* M1 — the column breath. Opacity only, on a 90s cycle: the TUI's authored
860 0.018–0.055 phase bias expressed as the same fraction of a mix. Opacity is
861 the one property that cannot cause layout work on an element four bands
862 tall. No position change, no hue shift, no filter. */
863 @keyframes cw-breath {
864 0%, 100% { opacity: 0; }
865 50% { opacity: 0.045; }
866 }
867
868 /* M2 — the caustic. `ambient_life.rs`'s literal behaviour: ~1.3s crossing the
869 mark, parked off-canvas for the remaining ~2.7s, peak 0.33. The easing is a
870 sine in-out, i.e. the raised cosine it is meant to be. */
871 @keyframes cw-caustic {
872 0% { transform: translateX(0); }
873 32.5% { transform: translateX(1560px); }
874 100% { transform: translateX(1560px); }
875 }
876
877 @media (prefers-reduced-motion: no-preference) {
878 .ocean-column::after {
879 content: "";
880 position: absolute;
881 inset: 0;
882 z-index: -1;
883 pointer-events: none;
884 background: var(--stage-ambient);
885 opacity: 0;
886 animation: cw-breath 90s ease-in-out infinite;
887 }
888
889 .codewhale-caustic {
890 animation: cw-caustic 4s cubic-bezier(0.37, 0, 0.63, 1) infinite;
891 }
892 }
893
894 /* ------------------------------------------------------------------ */
895 /* Motion — entrances, considered hovers, and one-shot settles */
896 /* ------------------------------------------------------------------ */
897 /*
898 * Grammar: the page is complete and static; motion answers a person's action
899 * (a hover draws a rule, a press stamps a copy). The one authored ambient
900 * moment is the column breath above. Everything here animates transform
901 * and/or opacity only and is gated on `no-preference`, so reduced motion is
902 * the *absence* of motion rather than an override fighting it.
903 */
904 /* The nav-link underline draw, extended to the other mono-voice links. Hover
905 draws the rule; the transition is the whole effect, so reduced motion keeps
906 the existing colour change and simply skips the draw. */
907 .product-start-links a,
908 .gs-step-link,
909 .product-surfaces > .product-container > a,
910 .product-community nav a {
911 position: relative;
912 }
913
914 .product-start-links a::after,
915 .gs-step-link::after,
916 .product-surfaces > .product-container > a::after,
917 .product-community nav a::after {
918 content: "";
919 position: absolute;
920 left: 0;
921 right: 0;
922 bottom: -2px;
923 height: 1px;
924 background: currentColor;
925 transform: scaleX(0);
926 transform-origin: left;
927 transition: transform 180ms ease;
928 }
929
930 @media (prefers-reduced-motion: no-preference) {
931 .product-start-links a:hover::after,
932 .gs-step-link:hover::after,
933 .product-surfaces > .product-container > a:hover::after,
934 .product-community nav a:hover::after {
935 transform: scaleX(1);
936 }
937 }
938
939 /* The primary-button arrow leans into the direction it points. */
940 .product-button > span[aria-hidden="true"] {
941 display: inline-block;
942 transition: transform 150ms ease;
943 }
944
945 @media (prefers-reduced-motion: no-preference) {
946 .product-button:hover > span[aria-hidden="true"],
947 .product-button:focus-visible > span[aria-hidden="true"] {
948 transform: translateX(2px);
949 }
950 }
951
952 /* Copy-to-clipboard: the press is a stamp, the confirmation a jade seal —
953 the wire's merge verb colour, borrowed for one beat. The colour change is
954 unconditional (it is the confirmation); only the motion is gated. */
955 .copy-btn[data-copied="true"] {
956 background: var(--jade);
957 color: var(--paper);
958 }
959
960 @media (prefers-reduced-motion: no-preference) {
961 .copy-btn {
962 transition: background-color 150ms ease, color 150ms ease, transform 120ms ease;
963 }
964
965 .copy-btn:active {
966 transform: scale(0.95);
967 }
968
969 .copy-btn[data-copied="true"] {
970 animation: copy-settle 300ms cubic-bezier(0.25, 0.46, 0.45, 0.94);
971 }
972 }
973
974 @keyframes copy-settle {
975 0% { transform: scale(1); }
976 35% { transform: scale(0.93); }
977 70% { transform: scale(1.04); }
978 100% { transform: scale(1); }
979 }
980
981 /* Mobile menu: the sheet drops a few points while its items settle in
982 sequence; exit is a short fade. The exit is driven by a delayed unmount in
983 components/mobile-menu.tsx — with reduced motion the menu mounts and
984 unmounts instantly, exactly as before. */
985 @media (prefers-reduced-motion: no-preference) {
986 .mm-panel {
987 animation: mm-in 240ms cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
988 }
989
990 .mm-panel.mm-closing {
991 animation: mm-out 170ms cubic-bezier(0.4, 0, 0.8, 0.4) both;
992 pointer-events: none;
993 }
994
995 .mm-panel li,
996 .mm-panel nav > a {
997 animation: mm-rise 280ms cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
998 }
999
1000 .mm-panel li:nth-child(1) { animation-delay: 34ms; }
1001 .mm-panel li:nth-child(2) { animation-delay: 58ms; }
1002 .mm-panel li:nth-child(3) { animation-delay: 82ms; }
1003 .mm-panel li:nth-child(4) { animation-delay: 106ms; }
1004 .mm-panel li:nth-child(5) { animation-delay: 130ms; }
1005 .mm-panel li:nth-child(6) { animation-delay: 154ms; }
1006 .mm-panel li:nth-child(7) { animation-delay: 178ms; }
1007 .mm-panel li:nth-child(8) { animation-delay: 202ms; }
1008 .mm-panel nav > a { animation-delay: 226ms; }
1009 }
1010
1011 @keyframes mm-in {
1012 from { opacity: 0; transform: translateY(-8px); }
1013 to { opacity: 1; transform: translateY(0); }
1014 }
1015
1016 @keyframes mm-out {
1017 from { opacity: 1; transform: translateY(0); }
1018 to { opacity: 0; transform: translateY(-6px); }
1019 }
1020
1021 @keyframes mm-rise {
1022 from { opacity: 0; transform: translateY(6px); }
1023 to { opacity: 1; transform: translateY(0); }
1024 }
1025
1026 /* ---------- decorative big CJK in margin ---------- */
1027 .margin-glyph {
1028 font-family: var(--font-cjk), "PingFang SC", "Source Han Serif SC", serif;
1029 font-weight: 700;
1030 color: var(--ink);
1031 opacity: 0.04;
1032 font-size: 18rem;
1033 line-height: 0.9;
1034 pointer-events: none;
1035 user-select: none;
1036 position: absolute;
1037 }
1038
1039 /* ---------- focus + selection ---------- */
1040 ::selection { background: var(--indigo); color: var(--paper); }
1041 :focus-visible { outline: 2px solid var(--indigo); outline-offset: 2px; }
1042
1043 /* ---------- link reset ---------- */
1044 a { color: inherit; text-decoration: none; }
1045 a.body-link {
1046 color: var(--ink);
1047 background-image: linear-gradient(var(--indigo), var(--indigo));
1048 background-repeat: no-repeat;
1049 background-position: 0 100%;
1050 background-size: 100% 1px;
1051 transition: background-size 180ms ease;
1052 }
1053 a.body-link:hover { background-size: 100% 6px; color: var(--ink); }
1054
1055 /* ---------- mobile-only adjustments ---------- */
1056 @media (max-width: 640px) {
1057 /* Big CJK margin glyph already hidden via tailwind's `hidden lg:block`,
1058 but re-assert that nothing hits the viewport edge. */
1059 .margin-glyph { display: none; }
1060
1061 /* Ticker text gets cramped on phones — shrink + tighten gaps */
1062 .ticker-track { gap: 1.5rem; padding-right: 1.5rem; }
1063 }
1064
1065 @media (max-width: 900px) {
1066 .site-nav-inner { gap: 1rem; }
1067 .site-github-link { display: none; }
1068 .site-footer-main { grid-template-columns: 1fr; gap: 2.5rem; }
1069 .site-footer-meta { grid-template-columns: minmax(0, 1fr); gap: 0.7rem; }
1070 .site-footer-meta > div { min-width: 0; flex-wrap: wrap; }
1071 }
1072
1073 @media (max-width: 700px) {
1074 .site-wordmark { font-size: 1.05rem; }
1075 }
1076
1077 /* Anchor fallback; page-level scroll-mt utilities should be able to override it. */
1078 :where([id]) { scroll-margin-top: 5rem; }
1079
1080 /* ------------------------------------------------------------------ */
1081 /* Documentation-led public home */
1082 /* ------------------------------------------------------------------ */
1083
1084 .portal-home {
1085 background: var(--paper);
1086 color: var(--ink);
1087 }
1088
1089 .portal-container {
1090 width: var(--container);
1091 margin-inline: auto;
1092 }
1093
1094 .portal-current {
1095 position: absolute;
1096 inset: 0;
1097 opacity: 0.22;
1098 pointer-events: none;
1099 background-image: repeating-radial-gradient(
1100 ellipse 82% 44% at 24% -22%,
1101 transparent 0,
1102 transparent 2.7rem,
1103 rgb(var(--c-stage-soft) / 0.18) 2.76rem,
1104 transparent 2.83rem
1105 );
1106 mask-image: linear-gradient(to bottom, transparent, black 24%, black 72%, transparent);
1107 }
1108
1109 .portal-hero-grid {
1110 position: relative;
1111 display: grid;
1112 grid-template-columns: minmax(0, 1.12fr) minmax(20rem, 0.88fr);
1113 gap: clamp(2.5rem, 6vw, 5rem);
1114 align-items: center;
1115 padding-block: clamp(3.25rem, 6vw, 4.75rem);
1116 }
1117
1118 .portal-hero-copy {
1119 max-width: 42rem;
1120 }
1121
1122 .portal-mark {
1123 display: flex;
1124 align-items: center;
1125 gap: 0.7rem;
1126 margin-bottom: 1.25rem;
1127 color: var(--ink-mute);
1128 font-size: 0.76rem;
1129 font-weight: 600;
1130 }
1131
1132 .portal-hero h1 {
1133 max-width: 41rem;
1134 font-size: clamp(2.3rem, 4.8vw, 3.75rem);
1135 line-height: 1.01;
1136 }
1137
1138 .portal-lede {
1139 max-width: 40rem;
1140 margin-top: 1.35rem;
1141 color: var(--ink-soft);
1142 font-size: clamp(1rem, 1.7vw, 1.18rem);
1143 line-height: 1.7;
1144 }
1145
1146 .portal-actions {
1147 display: flex;
1148 flex-wrap: wrap;
1149 gap: 0.7rem;
1150 margin-top: 1.7rem;
1151 }
1152
1153 .portal-button {
1154 display: inline-flex;
1155 min-height: 2.75rem;
1156 align-items: center;
1157 justify-content: center;
1158 padding: 0.65rem 1rem;
1159 border: 1px solid transparent;
1160 border-radius: 5px;
1161 font-size: 0.82rem;
1162 font-weight: 600;
1163 transition: background-color 150ms ease, border-color 150ms ease, color 150ms ease;
1164 }
1165
1166 .portal-button-primary {
1167 border-color: var(--indigo);
1168 background: var(--indigo);
1169 color: var(--paper);
1170 }
1171
1172 .portal-button-primary:hover {
1173 background: var(--indigo-deep);
1174 border-color: var(--indigo-deep);
1175 }
1176
1177 .portal-button-secondary {
1178 border-color: var(--paper-edge);
1179 background: var(--paper-deep);
1180 color: var(--ink);
1181 }
1182
1183 .portal-button-secondary:hover {
1184 border-color: var(--indigo);
1185 color: var(--indigo);
1186 }
1187
1188 .portal-meta {
1189 max-width: 38rem;
1190 margin-top: 0.9rem;
1191 color: var(--ink-mute);
1192 font-size: 0.76rem;
1193 line-height: 1.55;
1194 }
1195
1196 .portal-quickstart {
1197 padding: clamp(1.35rem, 3vw, 2rem);
1198 border: 1px solid rgb(var(--c-stage-soft) / 0.2);
1199 border-radius: 8px;
1200 background: var(--ocean-deep);
1201 box-shadow: 0 1.25rem 3rem rgba(0, 0, 0, 0.45);
1202 color: var(--stage-soft);
1203 }
1204
1205 .portal-quickstart > span {
1206 color: var(--stage-muted);
1207 font-family: var(--font-mono), "IBM Plex Mono", monospace;
1208 font-size: 0.7rem;
1209 letter-spacing: 0.1em;
1210 text-transform: uppercase;
1211 }
1212
1213 .portal-quickstart h2 {
1214 margin-top: 0.65rem;
1215 color: var(--stage-text);
1216 font-size: clamp(1.2rem, 2vw, 1.55rem);
1217 letter-spacing: -0.02em;
1218 }
1219
1220 .portal-quickstart p {
1221 margin-top: 0.7rem;
1222 color: rgb(var(--c-stage-soft) / 0.7);
1223 font-size: 0.84rem;
1224 line-height: 1.65;
1225 }
1226
1227 .portal-quickstart pre.code-block {
1228 margin-top: 1.15rem;
1229 border-color: rgb(var(--c-stage-soft) / 0.2);
1230 background: rgb(var(--c-stage-deep) / 0.6);
1231 }
1232
1233 .portal-quickstart > a {
1234 display: inline-block;
1235 margin-top: 1rem;
1236 color: var(--ocean-current);
1237 font-size: 0.76rem;
1238 }
1239
1240 .portal-quickstart > a:hover {
1241 text-decoration: underline;
1242 text-underline-offset: 0.25rem;
1243 }
1244
1245 .portal-section {
1246 padding-block: clamp(3.25rem, 6vw, 4.75rem);
1247 border-bottom: 1px solid var(--hairline);
1248 }
1249
1250 .portal-section-muted {
1251 background: var(--paper-deep);
1252 }
1253
1254 .legal-doc {
1255 width: var(--container);
1256 margin-inline: auto;
1257 padding-block: clamp(3.25rem, 6vw, 4.75rem);
1258 max-width: 42rem;
1259 }
1260
1261 .legal-doc-kicker {
1262 margin: 0 0 0.75rem;
1263 font-size: 0.7rem;
1264 letter-spacing: 0.14em;
1265 text-transform: uppercase;
1266 color: var(--ink-muted, color-mix(in srgb, var(--ink) 62%, var(--paper)));
1267 }
1268
1269 .legal-doc h1 {
1270 margin: 0 0 0.5rem;
1271 font-family: var(--font-display), serif;
1272 font-size: clamp(1.85rem, 3.6vw, 2.7rem);
1273 line-height: 1.15;
1274 }
1275
1276 .legal-doc-updated,
1277 .legal-doc p,
1278 .legal-doc section p {
1279 margin: 0 0 1.15rem;
1280 line-height: 1.6;
1281 }
1282
1283 .legal-doc section h2 {
1284 margin: 1.75rem 0 0.5rem;
1285 font-size: 1.15rem;
1286 }
1287
1288 .legal-doc-nav {
1289 display: flex;
1290 flex-wrap: wrap;
1291 gap: 1rem 1.5rem;
1292 margin-top: 2rem;
1293 }
1294
1295 .legal-doc-nav a {
1296 text-decoration: underline;
1297 text-underline-offset: 0.2rem;
1298 }
1299
1300 .public-account-entry {
1301 max-width: 32rem;
1302 }
1303
1304 .public-account-mark {
1305 display: block;
1306 width: 64px;
1307 height: 64px;
1308 margin: 0 0 1.15rem;
1309 border-radius: 14px;
1310 }
1311
1312 .portal-section-grid {
1313 display: grid;
1314 grid-template-columns: minmax(14rem, 0.62fr) minmax(0, 1.38fr);
1315 gap: clamp(2.5rem, 7vw, 6.5rem);
1316 }
1317
1318 .portal-section-copy > span,
1319 .portal-docs-heading span,
1320 .portal-community-grid > div:first-child > span {
1321 color: var(--ink-mute);
1322 font-size: 0.75rem;
1323 font-weight: 600;
1324 }
1325
1326 .portal-section-copy h2,
1327 .portal-docs-heading h2,
1328 .portal-community h2 {
1329 margin-top: 0.65rem;
1330 font-size: clamp(1.55rem, 3vw, 2.4rem);
1331 }
1332
1333 .portal-section-copy p {
1334 margin-top: 0.9rem;
1335 color: var(--ink-soft);
1336 font-size: 0.92rem;
1337 line-height: 1.7;
1338 }
1339
1340 .portal-topic-list {
1341 border-top: 1px solid var(--hairline);
1342 }
1343
1344 .portal-topic-list > a,
1345 .portal-topic-list > div {
1346 display: grid;
1347 grid-template-columns: minmax(8rem, 0.42fr) minmax(0, 1fr) auto;
1348 gap: 1.25rem;
1349 align-items: start;
1350 padding-block: 1.15rem;
1351 border-bottom: 1px solid var(--hairline);
1352 transition: background-color 150ms ease, color 150ms ease;
1353 }
1354
1355 .portal-topic-list > a:hover {
1356 color: var(--indigo);
1357 background: color-mix(in srgb, var(--indigo) 7%, transparent);
1358 }
1359
1360 .portal-topic-list strong {
1361 font-size: 0.9rem;
1362 font-weight: 600;
1363 }
1364
1365 .portal-topic-list span {
1366 color: var(--ink-soft);
1367 font-size: 0.84rem;
1368 line-height: 1.55;
1369 }
1370
1371 .portal-topic-list span:last-child {
1372 color: var(--ink-mute);
1373 }
1374
1375 .portal-docs-heading {
1376 display: flex;
1377 align-items: end;
1378 justify-content: space-between;
1379 gap: 2rem;
1380 margin-bottom: 2rem;
1381 }
1382
1383 .portal-docs-heading a {
1384 flex: none;
1385 color: var(--indigo-deep);
1386 font-size: 0.78rem;
1387 }
1388
1389 .portal-docs-heading a:hover,
1390 .portal-community-links a:hover {
1391 text-decoration: underline;
1392 text-underline-offset: 0.25rem;
1393 }
1394
1395 /* Sortable model table — quiet column-header buttons; the active column
1396 carries a direction mark instead of a color change. */
1397 .models-sort {
1398 display: inline-flex;
1399 align-items: baseline;
1400 gap: 0.35rem;
1401 padding: 0;
1402 border: 0;
1403 background: none;
1404 color: var(--ink-mute);
1405 font: inherit;
1406 font-weight: 500;
1407 cursor: pointer;
1408 white-space: nowrap;
1409 }
1410
1411 .models-sort:hover {
1412 color: var(--ink);
1413 }
1414
1415 .models-sort.is-active {
1416 color: var(--indigo-deep);
1417 }
1418
1419 .models-sort-mark {
1420 font-size: 0.72em;
1421 color: var(--ink-mute);
1422 }
1423
1424 .models-sort.is-active .models-sort-mark {
1425 color: var(--indigo-deep);
1426 }
1427
1428 .models-sort:focus-visible {
1429 outline: 2px solid var(--indigo);
1430 outline-offset: 3px;
1431 border-radius: 2px;
1432 }
1433
1434 .models-reasoning {
1435 display: inline-block;
1436 margin-left: 0.5rem;
1437 padding: 0.05rem 0.4rem;
1438 border: 1px solid var(--hairline);
1439 border-radius: 999px;
1440 color: var(--ink-mute);
1441 font-family: var(--font-mono);
1442 font-size: 0.62rem;
1443 letter-spacing: 0.04em;
1444 vertical-align: middle;
1445 white-space: nowrap;
1446 }
1447
1448 .portal-doc-groups {
1449 display: grid;
1450 grid-template-columns: repeat(2, minmax(0, 1fr));
1451 gap: clamp(2.5rem, 6vw, 5rem);
1452 }
1453
1454 .portal-doc-groups h3 {
1455 font-size: 1.05rem;
1456 letter-spacing: -0.01em;
1457 }
1458
1459 .portal-doc-groups section > p {
1460 min-height: 4.5rem;
1461 margin-top: 0.55rem;
1462 color: var(--ink-soft);
1463 font-size: 0.84rem;
1464 line-height: 1.6;
1465 }
1466
1467 .portal-doc-groups .portal-topic-list {
1468 margin-top: 1.25rem;
1469 }
1470
1471 .portal-doc-groups .portal-topic-list > a {
1472 grid-template-columns: minmax(7rem, 0.42fr) minmax(0, 1fr) auto;
1473 gap: 0.9rem;
1474 }
1475
1476 .portal-community {
1477 padding-block: clamp(3.25rem, 6vw, 4.75rem);
1478 background:
1479 radial-gradient(circle at 84% -30%, rgb(var(--c-primary-dark) / 0.1), transparent 30rem),
1480 var(--ocean-deep);
1481 color: var(--stage-soft);
1482 }
1483
1484 .portal-community-grid {
1485 display: grid;
1486 grid-template-columns: minmax(16rem, 0.85fr) minmax(0, 1.15fr);
1487 gap: clamp(2.5rem, 7vw, 7rem);
1488 }
1489
1490 .portal-community-grid > div:first-child > span {
1491 color: var(--stage-muted);
1492 }
1493
1494 .portal-community h2 {
1495 color: var(--stage-text);
1496 }
1497
1498 .portal-community p {
1499 color: rgb(var(--c-stage-soft) / 0.76);
1500 font-size: 0.96rem;
1501 line-height: 1.75;
1502 }
1503
1504 .portal-community-links {
1505 display: grid;
1506 grid-template-columns: repeat(2, minmax(0, 1fr));
1507 gap: 0.8rem 1.5rem;
1508 margin-top: 1.5rem;
1509 padding-top: 1.25rem;
1510 border-top: 1px solid rgb(var(--c-stage-soft) / 0.18);
1511 }
1512
1513 .portal-community-links a {
1514 color: var(--ocean-current);
1515 font-size: 0.78rem;
1516 }
1517
1518 .contribute-path-grid {
1519 display: grid;
1520 grid-template-columns: repeat(2, minmax(0, 1fr));
1521 border-top: 1px solid var(--hairline);
1522 }
1523
1524 .contribute-path-grid article {
1525 padding: 1.5rem 1.5rem 1.5rem 0;
1526 border-bottom: 1px solid var(--hairline);
1527 }
1528
1529 .contribute-path-grid article:nth-child(even) {
1530 padding-inline: 1.5rem 0;
1531 border-left: 1px solid var(--hairline);
1532 }
1533
1534 .contribute-path-grid h3 {
1535 font-size: 1rem;
1536 letter-spacing: -0.01em;
1537 }
1538
1539 .contribute-path-grid p {
1540 margin-top: 0.55rem;
1541 color: var(--ink-soft);
1542 font-size: 0.84rem;
1543 line-height: 1.65;
1544 }
1545
1546 .contribute-path-grid a,
1547 .contribute-steps a {
1548 display: inline-block;
1549 margin-top: 0.9rem;
1550 color: var(--indigo-deep);
1551 font-size: 0.75rem;
1552 font-weight: 600;
1553 }
1554
1555 .contribute-path-grid a:hover,
1556 .contribute-steps a:hover {
1557 text-decoration: underline;
1558 text-underline-offset: 0.22rem;
1559 }
1560
1561 .contribute-steps {
1562 display: grid;
1563 grid-template-columns: repeat(2, minmax(0, 1fr));
1564 border-top: 1px solid var(--hairline);
1565 }
1566
1567 .contribute-steps li {
1568 display: grid;
1569 grid-template-columns: 2.25rem minmax(0, 1fr);
1570 gap: 1rem;
1571 padding: 1.5rem 1.5rem 1.5rem 0;
1572 border-bottom: 1px solid var(--hairline);
1573 }
1574
1575 .contribute-steps li:nth-child(even) {
1576 padding-inline: 1.5rem 0;
1577 border-left: 1px solid var(--hairline);
1578 }
1579
1580 .contribute-steps li > span {
1581 color: var(--indigo-deep);
1582 font-family: var(--font-mono), "IBM Plex Mono", monospace;
1583 font-size: 0.75rem;
1584 }
1585
1586 .contribute-steps h3 {
1587 font-size: 1rem;
1588 letter-spacing: -0.01em;
1589 }
1590
1591 .contribute-steps p {
1592 margin-top: 0.5rem;
1593 color: var(--ink-soft);
1594 font-size: 0.82rem;
1595 line-height: 1.65;
1596 }
1597
1598 .contribute-review-list {
1599 border-top: 1px solid var(--hairline);
1600 }
1601
1602 .contribute-review-list li {
1603 padding-block: 1rem;
1604 border-bottom: 1px solid var(--hairline);
1605 color: var(--ink-soft);
1606 font-size: 0.84rem;
1607 line-height: 1.6;
1608 }
1609
1610 .contribute-dev-loop {
1611 padding-block: clamp(3.25rem, 6vw, 4.75rem);
1612 background: var(--ocean-deep);
1613 }
1614
1615 .contribute-dev-loop .portal-section-copy > span {
1616 color: var(--stage-muted);
1617 }
1618
1619 .contribute-dev-loop .portal-section-copy h2 {
1620 color: var(--stage-text);
1621 }
1622
1623 .contribute-dev-loop .portal-section-copy p {
1624 color: rgb(var(--c-stage-soft) / 0.76);
1625 }
1626
1627 .contribute-dev-loop pre.code-block {
1628 border-color: rgb(var(--c-stage-soft) / 0.2);
1629 background: rgb(var(--c-stage-deep) / 0.62);
1630 }
1631
1632 @media (max-width: 900px) {
1633 .portal-hero-grid,
1634 .portal-section-grid,
1635 .portal-community-grid {
1636 grid-template-columns: 1fr;
1637 }
1638
1639 .portal-hero-copy {
1640 max-width: 48rem;
1641 }
1642
1643 .portal-quickstart {
1644 max-width: 42rem;
1645 }
1646 }
1647
1648 @media (max-width: 760px) {
1649 .portal-doc-groups {
1650 grid-template-columns: 1fr;
1651 }
1652
1653 .portal-doc-groups section > p {
1654 min-height: 0;
1655 }
1656
1657 .contribute-path-grid,
1658 .contribute-steps {
1659 grid-template-columns: 1fr;
1660 }
1661
1662 .contribute-path-grid article,
1663 .contribute-path-grid article:nth-child(even),
1664 .contribute-steps li,
1665 .contribute-steps li:nth-child(even) {
1666 padding-inline: 0;
1667 border-left: 0;
1668 }
1669 }
1670
1671 @media (max-width: 560px) {
1672 .portal-hero-grid {
1673 gap: 2.25rem;
1674 padding-block: 2.75rem;
1675 }
1676
1677 .portal-actions,
1678 .portal-docs-heading {
1679 align-items: stretch;
1680 flex-direction: column;
1681 }
1682
1683 .portal-button {
1684 width: 100%;
1685 }
1686
1687 .portal-topic-list > a,
1688 .portal-topic-list > div,
1689 .portal-doc-groups .portal-topic-list > a,
1690 .portal-doc-groups .portal-topic-list > div {
1691 grid-template-columns: 1fr auto;
1692 gap: 0.45rem 1rem;
1693 }
1694
1695 .portal-topic-list > a span:nth-child(2),
1696 .portal-topic-list > div span:nth-child(2) {
1697 grid-column: 1 / -1;
1698 }
1699
1700 .portal-topic-list > a span:last-child,
1701 .portal-topic-list > div span:last-child {
1702 grid-column: 2;
1703 grid-row: 1;
1704 }
1705
1706 .portal-community-links {
1707 grid-template-columns: 1fr;
1708 }
1709 }
1710
1711 /* ------------------------------------------------------------------ */
1712 /* Product home — the Tidal Folio: a sheet read under the sea. */
1713 /* */
1714 /* The hero is one illustrated plate: paper at the top left, the */
1715 /* whale's water rising from the bottom right, and the real terminal */
1716 /* capture floating at the waterline. The reading sections that */
1717 /* follow are plain paper; the page descends for good at the */
1718 /* waterline band, and the footer is the seabed. */
1719 /* ------------------------------------------------------------------ */
1720
1721 .product-home {
1722 background: var(--paper);
1723 color: var(--ink);
1724 }
1725
1726 .product-container {
1727 width: var(--container);
1728 margin-inline: auto;
1729 }
1730
1731 /* ---------- the hero plate ---------- */
1732
1733 .folio-hero {
1734 position: relative;
1735 isolation: isolate;
1736 overflow: hidden;
1737 padding-block: clamp(3rem, 7vh, 5.5rem) 0;
1738 /* The plate ends on the deep field so the drawing can run to the edge. */
1739 background: var(--paper);
1740 }
1741
1742 /* The strata: geometry, not a picture. Anchored to the bottom edge so the
1743 water always fills the plate's floor whatever the copy height. */
1744 .folio-strata {
1745 position: absolute;
1746 inset: 0;
1747 z-index: 0;
1748 width: 100%;
1749 height: 100%;
1750 pointer-events: none;
1751 }
1752
1753 /* Copy on the paper at the left; the terminal and its running head on the
1754 water at the right, so the plate reads as a page with a marginal figure
1755 rather than a screenshot with a caption. */
1756 .folio-hero-grid {
1757 position: relative;
1758 z-index: 1;
1759 display: grid;
1760 grid-template-columns: minmax(0, 1.15fr) minmax(18rem, 0.85fr);
1761 grid-template-rows: auto auto;
1762 column-gap: clamp(2rem, 5vw, 5rem);
1763 row-gap: clamp(1.25rem, 2.5vw, 2rem);
1764 align-items: end;
1765 padding-bottom: clamp(3rem, 7vw, 6rem);
1766 }
1767
1768 .folio-hero-copy {
1769 position: relative;
1770 isolation: isolate;
1771 grid-column: 1;
1772 grid-row: 1 / 3;
1773 align-self: start;
1774 max-width: 40rem;
1775 padding-bottom: clamp(0.5rem, 2vw, 1.5rem);
1776 }
1777 .folio-hero-copy::before { content: ""; position: absolute; inset: -2rem -3rem; z-index: -1; background: var(--paper); filter: blur(24px); pointer-events: none; }
1778
1779 .folio-hero-copy h1 {
1780 max-width: 14ch;
1781 font-size: clamp(2.75rem, 6.4vw, 5.75rem);
1782 line-height: 0.98;
1783 }
1784
1785 .folio-lede {
1786 max-width: 34rem;
1787 margin: 1.6rem 0 0;
1788 color: var(--ink-soft);
1789 font-size: clamp(1.02rem, 1.5vw, 1.2rem);
1790 line-height: 1.6;
1791 }
1792
1793 .folio-actions {
1794 display: flex;
1795 flex-wrap: wrap;
1796 gap: 0.75rem;
1797 margin-top: 1.9rem;
1798 }
1799
1800 /* Buttons on paper: brand navy fills the primary; the secondary is an
1801 outlined sheet. Sentence case in the body face — this is a title page,
1802 not a status bar. */
1803 .folio-button {
1804 display: inline-flex;
1805 min-height: 3rem;
1806 align-items: center;
1807 justify-content: center;
1808 gap: 0.5rem;
1809 padding: 0.7rem 1.35rem;
1810 border: 1px solid var(--indigo-deep);
1811 border-radius: 5px;
1812 color: var(--indigo-deep);
1813 font-family: var(--font-body), system-ui, sans-serif;
1814 font-size: 0.95rem;
1815 font-weight: 500;
1816 line-height: 1;
1817 transition: background-color 150ms ease, border-color 150ms ease, color 150ms ease;
1818 }
1819
1820 .folio-button:hover {
1821 background: var(--indigo-pale);
1822 }
1823
1824 .folio-button-primary {
1825 background: var(--indigo-deep);
1826 color: var(--paper);
1827 }
1828
1829 .folio-button-primary:hover {
1830 background: var(--indigo);
1831 border-color: var(--indigo);
1832 color: var(--paper);
1833 }
1834
1835 /* ---------- the terminal at the waterline ---------- */
1836
1837 .folio-shot {
1838 grid-column: 2;
1839 grid-row: 1;
1840 align-self: end;
1841 position: relative;
1842 width: min(100%, 40rem);
1843 margin-top: clamp(4rem, 12vw, 11rem);
1844 margin: 0;
1845 border: 1px solid rgb(var(--c-stage-soft) / 0.2);
1846 border-radius: 8px;
1847 overflow: hidden;
1848 background: var(--gpui-stage-deep);
1849 /* The one shadow on the site: the plate is lifted off the water, so the
1850 shadow is soft and offset downward the way light through water would
1851 cast it. */
1852 box-shadow: 0 30px 60px -24px rgb(var(--c-stage-deep) / 0.75);
1853 }
1854
1855 .folio-shot img {
1856 display: block;
1857 width: 100%;
1858 height: auto;
1859 background: var(--gpui-stage-deep);
1860 }
1861
1862 .folio-shot figcaption {
1863 display: grid;
1864 gap: 0.35rem;
1865 padding: 0.7rem 0.95rem 0.8rem;
1866 border-top: 1px solid rgb(var(--c-stage-soft) / 0.14);
1867 background: var(--gpui-stage);
1868 color: var(--stage-soft);
1869 font-family: var(--font-mono), "IBM Plex Mono", monospace;
1870 font-size: 0.75rem;
1871 line-height: 1.5;
1872 }
1873
1874 /* The status line under the capture is the TUI header, typeset as facts:
1875 a `cw` chip and a dot chain. Spacing comes from `.dotline`; the
1876 separators are CSS punctuation. */
1877 .folio-shot .paper-facts {
1878 color: var(--stage-muted);
1879 }
1880
1881 .folio-shot .paper-facts .dotline-chip {
1882 padding: 0.08rem 0.36rem;
1883 border-radius: 3px;
1884 background: var(--gpui-stage-muted);
1885 color: var(--stage-text);
1886 font-weight: 600;
1887 }
1888
1889 .folio-shot .paper-facts > *:not(:last-child)::after {
1890 color: var(--stage-hint);
1891 }
1892
1893 /* The chapter marker on the water: the plate's running head. */
1894 .folio-chapter {
1895 grid-column: 2;
1896 grid-row: 2;
1897 align-self: start;
1898 justify-self: start;
1899 width: min(100%, 22rem);
1900 color: var(--stage-text);
1901 }
1902
1903 .folio-chapter-num {
1904 display: block;
1905 padding-bottom: 0.7rem;
1906 border-bottom: 1px solid rgb(var(--c-stage-soft) / 0.3);
1907 color: var(--action-on-dark);
1908 font-family: var(--font-mono), "IBM Plex Mono", monospace;
1909 font-size: 0.75rem;
1910 letter-spacing: 0.12em;
1911 text-transform: uppercase;
1912 }
1913
1914 .folio-chapter-title {
1915 margin: 0.9rem 0 0;
1916 font-family: var(--font-serif), "Newsreader", Georgia, serif;
1917 font-size: clamp(1.35rem, 1.9vw, 1.7rem);
1918 line-height: 1.25;
1919 }
1920
1921 /* ---------- reading sections on paper ---------- */
1922
1923 .folio-section {
1924 padding-block: clamp(3.5rem, 7vw, 6rem);
1925 border-bottom: 1px solid var(--hairline);
1926 }
1927
1928 .folio-section h2 {
1929 max-width: 24ch;
1930 }
1931
1932 .folio-section-lede {
1933 max-width: 40rem;
1934 margin: 1.1rem 0 0;
1935 color: var(--ink-soft);
1936 font-size: 1.05rem;
1937 line-height: 1.65;
1938 }
1939
1940 /* What you gain: three ruled columns, no cards, no icons. */
1941 .folio-gain-grid {
1942 display: grid;
1943 grid-template-columns: repeat(3, minmax(0, 1fr));
1944 margin-top: clamp(2rem, 4vw, 3rem);
1945 border-top: 1px solid var(--hairline);
1946 }
1947
1948 .folio-gain-grid > div {
1949 padding: 1.5rem 1.75rem 1.75rem 0;
1950 }
1951
1952 .folio-gain-grid > div + div {
1953 padding-left: 1.75rem;
1954 border-left: 1px solid var(--hairline);
1955 }
1956
1957 .folio-gain-grid h3 {
1958 font-family: var(--font-serif), "Newsreader", Georgia, serif;
1959 font-size: 1.45rem;
1960 font-weight: 500;
1961 letter-spacing: -0.015em;
1962 line-height: 1.2;
1963 }
1964
1965 .folio-gain-grid p {
1966 margin-top: 0.75rem;
1967 color: var(--ink-soft);
1968 font-size: 0.95rem;
1969 line-height: 1.65;
1970 }
1971
1972 /* A two-column chapter: the argument on the left, the facts on the right. */
1973 .folio-chapter-grid {
1974 display: grid;
1975 grid-template-columns: minmax(0, 1fr) minmax(16rem, 0.8fr);
1976 gap: clamp(2rem, 6vw, 6rem);
1977 align-items: start;
1978 }
1979
1980 .folio-running-head {
1981 display: block;
1982 margin-bottom: 1.1rem;
1983 color: var(--indigo);
1984 font-family: var(--font-mono), "IBM Plex Mono", monospace;
1985 font-size: 0.75rem;
1986 letter-spacing: 0.12em;
1987 text-transform: uppercase;
1988 }
1989
1990 .folio-fact-list {
1991 border-top: 1px solid var(--hairline);
1992 }
1993
1994 .folio-fact-list > div {
1995 display: grid;
1996 grid-template-columns: minmax(8rem, 0.5fr) minmax(0, 1fr);
1997 gap: 1rem;
1998 padding: 0.95rem 0;
1999 border-bottom: 1px solid var(--hairline);
2000 }
2001
2002 .folio-fact-list dt {
2003 color: var(--ink);
2004 font-family: var(--font-mono), "IBM Plex Mono", monospace;
2005 font-size: 0.8rem;
2006 font-weight: 500;
2007 }
2008
2009 .folio-fact-list dd {
2010 color: var(--ink-soft);
2011 font-size: 0.92rem;
2012 line-height: 1.55;
2013 }
2014
2015 .folio-link {
2016 display: inline-block;
2017 margin-top: 1.4rem;
2018 color: var(--indigo);
2019 font-size: 0.95rem;
2020 font-weight: 500;
2021 text-decoration: underline;
2022 text-decoration-color: rgb(var(--c-indigo) / 0.35);
2023 text-underline-offset: 0.25em;
2024 transition: text-decoration-color 150ms ease;
2025 }
2026
2027 .folio-link:hover {
2028 text-decoration-color: currentColor;
2029 }
2030
2031 /* ---------- the waterline band ---------- */
2032
2033 .folio-waterline {
2034 position: relative;
2035 height: clamp(11rem, 24vw, 20rem);
2036 overflow: hidden;
2037 background: var(--paper);
2038 }
2039
2040 .folio-waterline > svg {
2041 position: absolute;
2042 inset: 0;
2043 width: 100%;
2044 height: 100%;
2045 }
2046
2047
2048 /* ---------- product: start-here band + shared getting-started steps ---------- */
2049
2050 .product-start {
2051 padding-block: clamp(3.5rem, 7vw, 6rem);
2052 border-bottom: 1px solid var(--hairline);
2053 }
2054
2055 .product-start h2 {
2056 max-width: 24ch;
2057 }
2058
2059 .product-start-lede {
2060 margin-top: 1.1rem;
2061 max-width: 40rem;
2062 color: var(--ink-soft);
2063 font-size: 1.05rem;
2064 line-height: 1.65;
2065 }
2066
2067 .product-start-links {
2068 display: flex;
2069 flex-wrap: wrap;
2070 gap: 1.5rem;
2071 margin-top: 2rem;
2072 }
2073
2074 .product-start-links a {
2075 color: var(--indigo);
2076 font-size: 0.95rem;
2077 font-weight: 500;
2078 }
2079
2080 .product-start-links a:hover {
2081 color: var(--indigo-deep);
2082 }
2083
2084 /* Shared step list rendered by <GettingStartedSteps> (homepage band and the
2085 /docs/guide page). Light tokens; the docs dark theme re-themes it through
2086 the same --hairline/--ink-* vars as the rest of the docs subtree. */
2087 .gs-steps {
2088 display: grid;
2089 grid-template-columns: repeat(4, minmax(0, 1fr));
2090 margin-top: clamp(2rem, 4vw, 3rem);
2091 padding: 0;
2092 border-top: 1px solid var(--hairline);
2093 list-style: none;
2094 }
2095
2096 .gs-steps li {
2097 padding: 1.35rem 1.5rem 1.5rem 0;
2098 border-bottom: 1px solid var(--hairline);
2099 }
2100
2101 .gs-steps li + li {
2102 padding-left: 1.5rem;
2103 border-left: 1px solid var(--hairline);
2104 }
2105 .docs-content .gs-steps { grid-template-columns: minmax(0, 1fr); }
2106 .docs-content .gs-steps li + li { padding-left: 0; border-left: 0; }
2107
2108 .gs-step-index {
2109 color: var(--indigo);
2110 font-family: var(--font-mono), "IBM Plex Mono", monospace;
2111 font-size: 0.75rem;
2112 }
2113
2114 .gs-steps h3 {
2115 margin-top: 1.1rem;
2116 font-size: 1.05rem;
2117 }
2118
2119 .gs-steps p {
2120 margin-top: 0.6rem;
2121 color: var(--ink-soft);
2122 font-size: 0.86rem;
2123 line-height: 1.7;
2124 }
2125
2126 .gs-step-commands {
2127 margin-top: 0.9rem;
2128 font-size: 0.75rem;
2129 }
2130
2131 pre.gs-step-commands {
2132 white-space: pre-wrap;
2133 overflow-wrap: anywhere;
2134 }
2135
2136 .gs-step-link {
2137 display: inline-block;
2138 margin-top: 0.9rem;
2139 color: var(--indigo);
2140 font-family: var(--font-mono), "IBM Plex Mono", monospace;
2141 font-size: 0.75rem;
2142 }
2143
2144 .gs-step-link:hover {
2145 color: var(--indigo-deep);
2146 }
2147
2148 /* ---------- a11y: skip link ---------- */
2149
2150 .skip-link {
2151 position: absolute;
2152 left: 1rem;
2153 top: -3.5rem;
2154 z-index: 60;
2155 padding: 0.55rem 0.9rem;
2156 background: var(--ink);
2157 color: var(--paper);
2158 font-family: var(--font-mono), "IBM Plex Mono", monospace;
2159 font-size: 0.75rem;
2160 }
2161
2162 .skip-link:focus-visible {
2163 top: 0.5rem;
2164 outline: 2px solid var(--indigo);
2165 outline-offset: 2px;
2166 }
2167
2168 /* ---------- honest status badges ---------- */
2169
2170 .status-badge {
2171 display: inline-flex;
2172 align-items: center;
2173 gap: 0.4rem;
2174 padding: 0.2rem 0.55rem;
2175 border: 1px solid var(--hairline);
2176 font-family: var(--font-mono), "IBM Plex Mono", monospace;
2177 font-size: 0.7rem;
2178 letter-spacing: 0.08em;
2179 text-transform: uppercase;
2180 color: var(--ink-soft);
2181 }
2182
2183 .status-badge-dot {
2184 width: 0.45rem;
2185 height: 0.45rem;
2186 border-radius: 999px;
2187 }
2188
2189 .status-badge-experimental .status-badge-dot { background: var(--ochre); }
2190 .status-badge-preview .status-badge-dot { background: var(--indigo); }
2191 .status-badge-pending .status-badge-dot { background: var(--ochre); }
2192 .status-badge-unavailable .status-badge-dot { background: var(--ink-mute); }
2193
2194 /* ---------- session media (real-session surface) ---------- */
2195
2196 .session-media {
2197 border: 1px solid var(--hairline);
2198 }
2199
2200 .session-media video {
2201 display: block;
2202 width: 100%;
2203 height: auto;
2204 background: var(--ocean-deep);
2205 }
2206
2207 .session-media-stage {
2208 display: flex;
2209 flex-direction: column;
2210 align-items: flex-start;
2211 gap: 0.9rem;
2212 padding: clamp(1.5rem, 4vw, 2.5rem);
2213 border-bottom: 1px solid var(--hairline);
2214 background: var(--paper-deep);
2215 }
2216
2217 .session-media-pending-note {
2218 max-width: 44rem;
2219 margin: 0;
2220 color: var(--ink-soft);
2221 font-size: 0.88rem;
2222 line-height: 1.7;
2223 }
2224
2225 .session-media-caption {
2226 display: grid;
2227 gap: 0.5rem;
2228 padding: 1rem 1.25rem;
2229 color: var(--ink-soft);
2230 font-size: 0.84rem;
2231 line-height: 1.6;
2232 }
2233
2234 .session-media-caption strong {
2235 color: var(--ink);
2236 font-size: 0.95rem;
2237 }
2238
2239 .session-media-caption a {
2240 color: var(--indigo);
2241 font-family: var(--font-mono), "IBM Plex Mono", monospace;
2242 font-size: 0.75rem;
2243 }
2244
2245 .session-media-caption a:hover {
2246 color: var(--indigo-deep);
2247 }
2248
2249 /* The boundaries band carries no field of its own — the water is the page. */
2250 .product-boundaries {
2251 padding-block: clamp(4rem, 8vw, 7rem);
2252 }
2253
2254 .product-boundaries-grid {
2255 display: grid;
2256 grid-template-columns: minmax(16rem, 0.8fr) minmax(0, 1.2fr);
2257 gap: clamp(3rem, 8vw, 8rem);
2258 }
2259
2260 .product-boundaries h2 {
2261 font-size: clamp(2.5rem, 5vw, 4.7rem);
2262 }
2263
2264 .product-boundaries h2 span {
2265 color: var(--indigo);
2266 }
2267
2268 .product-boundaries-grid > div > p {
2269 max-width: 31rem;
2270 margin-top: 1.25rem;
2271 color: var(--ink-soft);
2272 line-height: 1.75;
2273 }
2274
2275 .product-boundary-list {
2276 display: grid;
2277 gap: 0.75rem;
2278 }
2279
2280 .product-boundary-list > div {
2281 display: grid;
2282 grid-template-columns: minmax(12rem, 0.85fr) minmax(0, 1.15fr);
2283 align-items: baseline;
2284 gap: 1.5rem;
2285 padding: 1.25rem 1.4rem;
2286 border: 1px solid var(--stage-line);
2287 border-radius: 6px;
2288 background: var(--paper-card);
2289 }
2290
2291 .product-boundary-list dt {
2292 font-weight: 700;
2293 }
2294
2295 .product-boundary-list dd {
2296 color: var(--ink-soft);
2297 font-size: 0.88rem;
2298 }
2299
2300 /* ---------- below the waterline ---------- */
2301 /* */
2302 /* The water column. Its tokens are the dark whale palette (see the shared */
2303 /* rule beside :root), so every component inside reads correctly without */
2304 /* knowing it is under water. The field starts at the panel surface just */
2305 /* under the waterline band and sinks to the deep stop the footer continues, */
2306 /* so the seabed arrives without a seam. */
2307 /* -------------------------------------------------------------------------- */
2308 .ocean-column {
2309 position: relative;
2310 isolation: isolate;
2311 background: linear-gradient(180deg, var(--gpui-stage) 0%, var(--gpui-stage-deep) 38rem);
2312 color: var(--ink);
2313 }
2314
2315 /* Bands inside the column carry no field of their own. */
2316 .ocean-column > section {
2317 position: relative;
2318 background: transparent;
2319 }
2320
2321 /* One line weight on the field. */
2322 .ocean-column .hairline,
2323 .ocean-column .hairline-t,
2324 .ocean-column .hairline-b,
2325 .ocean-column .hairline-l {
2326 border-color: var(--stage-line);
2327 }
2328
2329 .ocean-column h2 {
2330 max-width: 24ch;
2331 color: var(--stage-text);
2332 }
2333
2334 /* Where Codewhale runs today: one honest table, no badges. */
2335 .folio-availability {
2336 padding-block: clamp(3.5rem, 7vw, 6rem);
2337 border-bottom: 1px solid var(--stage-line);
2338 }
2339
2340 .folio-availability-list {
2341 margin-top: clamp(2rem, 4vw, 3rem);
2342 border-top: 1px solid var(--stage-line);
2343 }
2344
2345 .folio-availability-list > div {
2346 display: grid;
2347 grid-template-columns: minmax(9rem, 0.35fr) minmax(0, 1fr);
2348 gap: 1.25rem;
2349 padding: 1.15rem 0;
2350 border-bottom: 1px solid var(--stage-line);
2351 }
2352
2353 .folio-availability-list dt {
2354 color: var(--stage-text);
2355 font-family: var(--font-serif), "Newsreader", Georgia, serif;
2356 font-size: 1.3rem;
2357 font-weight: 500;
2358 line-height: 1.2;
2359 }
2360
2361 .folio-availability-list dd {
2362 color: var(--stage-soft);
2363 font-size: 0.95rem;
2364 line-height: 1.6;
2365 }
2366
2367 .folio-availability-list dd strong {
2368 display: block;
2369 margin-bottom: 0.2rem;
2370 color: var(--stage-text);
2371 font-weight: 600;
2372 }
2373
2374 .folio-availability-note {
2375 max-width: 40rem;
2376 margin-top: 1.4rem;
2377 color: var(--stage-muted);
2378 font-size: 0.88rem;
2379 line-height: 1.6;
2380 }
2381
2382 .product-surfaces {
2383 padding-block: clamp(3.5rem, 7vw, 6rem);
2384 border-bottom: 1px solid var(--stage-line);
2385 }
2386
2387 .product-surface-list {
2388 margin-top: 2.5rem;
2389 border-top: 1px solid var(--stage-line);
2390 }
2391
2392 .product-surface-list > div {
2393 display: grid;
2394 grid-template-columns: minmax(13rem, 0.7fr) minmax(0, 1.3fr);
2395 gap: 2rem;
2396 padding: 1.2rem 0;
2397 border-bottom: 1px solid var(--stage-line);
2398 }
2399
2400 .product-surface-list strong {
2401 color: var(--stage-text);
2402 font-family: var(--font-mono), "IBM Plex Mono", monospace;
2403 font-size: 1rem;
2404 }
2405
2406 .product-surface-list span {
2407 color: var(--stage-soft);
2408 }
2409
2410 .product-surfaces > .product-container > a {
2411 display: inline-block;
2412 margin-top: 1.5rem;
2413 color: var(--action-on-dark);
2414 font-size: 0.95rem;
2415 }
2416
2417 /* The install band is the TUI composer: a raised plate on the column,
2418 bracketed above by Signal Gold and below by Operate violet — the
2419 product's exact composer framing, and the one place gold is legitimate
2420 here, because what it brackets is the point of human intent. The
2421 descendant selector out-ranks `.ocean-column > section { transparent }`. */
2422 .ocean-column .product-install-band {
2423 padding-block: clamp(3rem, 6vw, 5rem);
2424 border-top: 1px solid color-mix(in srgb, var(--signal-gold) 40%, transparent);
2425 border-bottom: 1px solid color-mix(in srgb, var(--violet) 40%, transparent);
2426 background: var(--stage-composer);
2427 color: var(--stage-text);
2428 }
2429
2430 .product-install-grid {
2431 display: grid;
2432 grid-template-columns: minmax(15rem, 0.65fr) minmax(0, 1.35fr);
2433 gap: clamp(2rem, 7vw, 7rem);
2434 align-items: start;
2435 }
2436
2437 /* `❯` sits inside the plate, where the TUI puts it — a code-owned literal in
2438 the same class as `Codewhale` and `npm install -g codewhale`. */
2439 .product-composer {
2440 position: relative;
2441 }
2442
2443 .product-composer pre.code-block {
2444 padding-left: 2.6rem;
2445 }
2446
2447 .product-composer button {
2448 color: var(--ink);
2449 }
2450
2451 .product-composer-prompt {
2452 position: absolute;
2453 top: 1rem;
2454 left: 1.1rem;
2455 z-index: 1;
2456 color: var(--cyan);
2457 font-family: var(--font-mono), "IBM Plex Mono", ui-monospace, monospace;
2458 font-size: 0.78rem;
2459 line-height: 1.55;
2460 pointer-events: none;
2461 }
2462
2463 @media (max-width: 640px) {
2464 .product-composer pre.code-block {
2465 padding-left: 2.3rem;
2466 }
2467
2468 .product-composer-prompt {
2469 top: 0.85rem;
2470 left: 0.95rem;
2471 font-size: 0.76rem;
2472 }
2473 }
2474
2475 .product-install-band pre.code-block {
2476 margin: 0;
2477 border-color: var(--stage-line);
2478 }
2479
2480 .product-install-band .dotline {
2481 margin-top: 1rem;
2482 color: var(--stage-hint);
2483 }
2484
2485 .product-install-band a {
2486 display: inline-block;
2487 margin-top: 1.2rem;
2488 padding-bottom: 0.2rem;
2489 border-bottom: 1px solid var(--stage-line);
2490 color: var(--action-on-dark);
2491 font-size: 0.95rem;
2492 transition: border-color 150ms ease;
2493 }
2494
2495 .product-install-band a:hover {
2496 border-color: var(--action-on-dark);
2497 }
2498
2499 .product-community {
2500 padding-block: clamp(3.5rem, 7vw, 6rem);
2501 }
2502
2503 .product-community-grid {
2504 display: grid;
2505 grid-template-columns: minmax(0, 1.1fr) minmax(16rem, 0.75fr);
2506 gap: clamp(2rem, 5vw, 5rem);
2507 align-items: end;
2508 }
2509
2510 .product-community p {
2511 max-width: 42rem;
2512 margin-top: 1rem;
2513 color: var(--stage-soft);
2514 font-size: 1rem;
2515 line-height: 1.75;
2516 }
2517
2518 .product-community nav {
2519 display: grid;
2520 grid-template-columns: repeat(2, minmax(0, 1fr));
2521 gap: 1rem;
2522 padding-top: 1.25rem;
2523 border-top: 1px solid var(--stage-line);
2524 }
2525
2526 .product-community nav a {
2527 color: var(--ocean-current);
2528 font-size: 0.95rem;
2529 font-weight: 500;
2530 }
2531
2532 .product-community nav a:hover {
2533 color: var(--stage-text);
2534 }
2535
2536 .product-home a:focus-visible {
2537 outline: 3px solid var(--signal-gold);
2538 outline-offset: 4px;
2539 }
2540
2541 @media (max-width: 1050px) {
2542 .folio-hero-grid {
2543 grid-template-columns: 1fr;
2544 grid-template-rows: auto auto auto;
2545 }
2546
2547 .folio-hero-copy {
2548 max-width: 44rem;
2549 }
2550
2551 .folio-hero-copy {
2552 grid-row: 1;
2553 }
2554
2555 .folio-shot {
2556 grid-column: 1;
2557 grid-row: 2;
2558 width: min(100%, 44rem);
2559 margin-top: clamp(1.5rem, 6vw, 3rem);
2560 }
2561
2562 .folio-chapter {
2563 grid-column: 1;
2564 grid-row: 3;
2565 justify-self: start;
2566 }
2567 }
2568
2569 @media (max-width: 760px) {
2570 .folio-gain-grid {
2571 grid-template-columns: 1fr;
2572 }
2573
2574 .folio-gain-grid > div,
2575 .folio-gain-grid > div + div {
2576 padding: 1.35rem 0;
2577 border-left: 0;
2578 border-bottom: 1px solid var(--hairline);
2579 }
2580
2581 .folio-chapter-grid,
2582 .product-install-grid,
2583 .product-community-grid {
2584 grid-template-columns: 1fr;
2585 }
2586
2587 .gs-steps {
2588 grid-template-columns: repeat(2, minmax(0, 1fr));
2589 }
2590
2591 .gs-steps li:nth-child(3) {
2592 padding-left: 0;
2593 border-left: 0;
2594 }
2595
2596 .folio-availability-list > div,
2597 .product-surface-list > div {
2598 grid-template-columns: 1fr;
2599 gap: 0.45rem;
2600 }
2601 }
2602
2603 @media (max-width: 520px) {
2604 .site-nav-inner {
2605 gap: 0.5rem;
2606 }
2607
2608 .site-nav-actions {
2609 min-width: 0;
2610 gap: 0.35rem;
2611 }
2612
2613 .site-nav-actions select {
2614 width: 6.75rem;
2615 min-width: 0;
2616 }
2617
2618 .paper-wordmark {
2619 max-width: 9.75rem;
2620 }
2621
2622 .folio-hero-copy h1 {
2623 max-width: 100%;
2624 font-size: clamp(2.3rem, 11vw, 3.2rem);
2625 word-break: normal;
2626 overflow-wrap: break-word;
2627 }
2628
2629 .paper-install-cta {
2630 display: none;
2631 }
2632
2633 .folio-actions {
2634 display: grid;
2635 grid-template-columns: 1fr;
2636 }
2637
2638 .folio-button {
2639 width: 100%;
2640 }
2641
2642 .gs-steps {
2643 grid-template-columns: 1fr;
2644 }
2645
2646 .gs-steps li,
2647 .gs-steps li + li,
2648 .gs-steps li:nth-child(3) {
2649 padding: 1.25rem 0;
2650 border-left: 0;
2651 }
2652
2653 .product-community nav {
2654 grid-template-columns: 1fr;
2655 }
2656 }
2657
2658
2659 /* ------------------------------------------------------------------ */
2660 /* Documentation portal */
2661 /* ------------------------------------------------------------------ */
2662
2663 .docs-portal {
2664 background: var(--paper);
2665 }
2666
2667 .community-welcome-inner {
2668 position: relative;
2669 }
2670
2671 .community-welcome-inner h1 {
2672 max-width: 50rem;
2673 font-size: clamp(2rem, 4.2vw, 3.6rem);
2674 line-height: 1.03;
2675 }
2676
2677 .community-welcome-inner h1 {
2678 margin-top: 0.85rem;
2679 }
2680
2681 .community-welcome-inner p {
2682 max-width: 47rem;
2683 margin-top: 1rem;
2684 color: var(--ink-soft);
2685 font-size: 1rem;
2686 line-height: 1.7;
2687 }
2688
2689 .docs-portal .hero {
2690 padding-block: 0.75rem;
2691 }
2692
2693 .docs-portal-band {
2694 display: flex;
2695 flex-wrap: wrap;
2696 align-items: baseline;
2697 gap: 1rem;
2698 }
2699
2700 .docs-portal-band .portal-mark,
2701 .docs-portal-band .release-truth {
2702 margin: 0;
2703 }
2704
2705 .docs-hub-lede {
2706 margin: 0.8rem 0 1.5rem;
2707 color: var(--ink-soft);
2708 }
2709
2710 .docs-shell {
2711 display: grid;
2712 grid-template-columns: minmax(13rem, 0.28fr) minmax(0, 0.72fr);
2713 grid-template-areas: "sidebar content";
2714 gap: clamp(2rem, 5vw, 4.5rem);
2715 align-items: start;
2716 padding-block: clamp(2.25rem, 5vw, 4rem);
2717 }
2718
2719 .docs-sidebar {
2720 grid-area: sidebar;
2721 border-top: 1px solid var(--hairline);
2722 }
2723
2724 .docs-sidebar-heading {
2725 padding-block: 0.9rem;
2726 border-bottom: 1px solid var(--hairline);
2727 color: var(--ink);
2728 font-size: 0.82rem;
2729 font-weight: 600;
2730 }
2731
2732 .docs-sidebar-heading a {
2733 display: flex;
2734 align-items: center;
2735 justify-content: space-between;
2736 gap: 1rem;
2737 }
2738
2739 .docs-sidebar-heading a > span:last-child {
2740 color: var(--ink-mute);
2741 font-size: 0.75rem;
2742 }
2743
2744 .docs-sidebar-group {
2745 padding-block: 0.9rem;
2746 border-bottom: 1px solid var(--hairline);
2747 }
2748
2749 .docs-sidebar-category {
2750 margin-bottom: 0.35rem;
2751 color: var(--ink-mute);
2752 font-size: 0.75rem;
2753 font-weight: 600;
2754 letter-spacing: 0.08em;
2755 text-transform: uppercase;
2756 }
2757
2758 .docs-sidebar-link {
2759 display: flex;
2760 align-items: center;
2761 justify-content: space-between;
2762 gap: 0.8rem;
2763 padding-block: 0.32rem;
2764 color: var(--ink-soft);
2765 font-size: 0.8rem;
2766 line-height: 1.4;
2767 transition: color 150ms ease;
2768 }
2769
2770 .docs-sidebar-link:hover,
2771 .docs-sidebar-link-current {
2772 color: var(--docs-accent);
2773 }
2774
2775 .docs-sidebar-link-current {
2776 font-weight: 600;
2777 }
2778
2779 .docs-sidebar-link > span:last-child:not(:first-child) {
2780 color: var(--ink-mute);
2781 font-size: 0.75rem;
2782 }
2783
2784 .docs-content {
2785 grid-area: content;
2786 width: 100%;
2787 max-width: 52rem;
2788 }
2789
2790 .docs-content p {
2791 max-width: 70ch;
2792 }
2793
2794 .docs-breadcrumb {
2795 margin-bottom: 1.15rem;
2796 color: var(--ink-mute);
2797 font-family: var(--font-mono), "IBM Plex Mono", ui-monospace, monospace;
2798 font-size: 0.75rem;
2799 }
2800
2801 .docs-breadcrumb ol {
2802 display: flex;
2803 flex-wrap: wrap;
2804 align-items: baseline;
2805 margin: 0;
2806 padding: 0;
2807 list-style: none;
2808 }
2809
2810 .docs-breadcrumb li:not(:last-child)::after {
2811 content: "/";
2812 margin-inline: 0.5em;
2813 color: var(--ink-mute);
2814 }
2815
2816 .docs-breadcrumb a {
2817 color: var(--indigo);
2818 }
2819
2820 .docs-breadcrumb a:hover {
2821 text-decoration: underline;
2822 }
2823
2824 .docs-breadcrumb [aria-current="page"] {
2825 color: var(--ink);
2826 }
2827
2828 .docs-search-block {
2829 margin-bottom: 2.25rem;
2830 }
2831
2832 .docs-search-label {
2833 display: block;
2834 margin-bottom: 0.55rem;
2835 color: var(--ink-mute);
2836 font-size: 0.75rem;
2837 font-weight: 600;
2838 }
2839
2840 .docs-search-input {
2841 min-height: 3rem;
2842 padding-right: 3rem;
2843 border-color: var(--paper-line-soft);
2844 border-radius: 5px;
2845 background: color-mix(in srgb, var(--paper) 88%, transparent);
2846 }
2847
2848 .docs-search-clear {
2849 position: absolute;
2850 right: 0.9rem;
2851 top: 50%;
2852 translate: 0 -50%;
2853 color: var(--ink-mute);
2854 font-size: 0.82rem;
2855 }
2856
2857 .docs-search-clear:hover {
2858 color: var(--ink);
2859 }
2860
2861 .docs-search-count {
2862 margin-top: 0.55rem;
2863 color: var(--ink-mute);
2864 font-size: 0.75rem;
2865 }
2866
2867 .docs-result-groups {
2868 display: grid;
2869 gap: 2.5rem;
2870 }
2871
2872 .docs-result-heading {
2873 display: flex;
2874 align-items: baseline;
2875 justify-content: space-between;
2876 gap: 1rem;
2877 margin-bottom: 0.55rem;
2878 }
2879
2880 .docs-result-heading h2 {
2881 font-size: 1.28rem;
2882 letter-spacing: -0.02em;
2883 }
2884
2885 .docs-result-heading > span {
2886 color: var(--ink-mute);
2887 font-size: 0.75rem;
2888 }
2889
2890 .docs-topic-list {
2891 border-top: 1px solid var(--hairline);
2892 }
2893
2894 .docs-topic-row {
2895 display: grid;
2896 grid-template-columns: minmax(0, 1fr) minmax(8rem, 0.34fr) auto;
2897 gap: 1.25rem;
2898 align-items: center;
2899 padding-block: 1rem;
2900 border-bottom: 1px solid var(--hairline);
2901 transition: background-color 150ms ease, color 150ms ease;
2902 }
2903
2904 .docs-topic-row:hover {
2905 color: var(--docs-accent);
2906 background: color-mix(in srgb, var(--paper-deep) 68%, transparent);
2907 }
2908
2909 .docs-topic-title {
2910 display: flex;
2911 flex-wrap: wrap;
2912 gap: 0.5rem;
2913 align-items: baseline;
2914 color: var(--ink);
2915 font-size: 0.9rem;
2916 font-weight: 600;
2917 }
2918
2919 .docs-topic-title > span:last-child {
2920 color: var(--ink-mute);
2921 font-size: 0.75rem;
2922 font-weight: 500;
2923 letter-spacing: 0.06em;
2924 text-transform: uppercase;
2925 }
2926
2927 .docs-topic-main p {
2928 margin-top: 0.28rem;
2929 color: var(--ink-soft);
2930 font-size: 0.78rem;
2931 line-height: 1.55;
2932 }
2933
2934 .docs-topic-source {
2935 overflow: hidden;
2936 color: var(--ink-mute);
2937 font-family: var(--font-mono), "IBM Plex Mono", monospace;
2938 font-size: 0.75rem;
2939 line-height: 1.5;
2940 text-overflow: ellipsis;
2941 }
2942
2943 .docs-topic-source span {
2944 overflow-wrap: anywhere;
2945 }
2946
2947 .docs-topic-arrow {
2948 color: var(--ink-mute);
2949 font-size: 0.78rem;
2950 }
2951
2952 .docs-empty {
2953 padding-block: 3.5rem;
2954 border-block: 1px solid var(--hairline);
2955 text-align: center;
2956 }
2957
2958 .docs-empty > p:first-child {
2959 color: var(--ink);
2960 font-size: 1rem;
2961 font-weight: 600;
2962 }
2963
2964 .docs-empty > p:nth-child(2) {
2965 margin: 0.5rem auto 1.25rem;
2966 color: var(--ink-mute);
2967 font-size: 0.8rem;
2968 }
2969
2970 .docs-source-note {
2971 margin-top: 2.5rem;
2972 padding-top: 1.25rem;
2973 border-top: 1px solid var(--hairline);
2974 }
2975
2976 .docs-source-note p {
2977 max-width: 70ch;
2978 color: var(--ink-mute);
2979 font-size: 0.75rem;
2980 line-height: 1.6;
2981 }
2982
2983 @media (max-width: 900px) {
2984 .docs-shell {
2985 grid-template-columns: 1fr;
2986 grid-template-areas:
2987 "content"
2988 "sidebar";
2989 }
2990
2991 /* The one docs nav stays reachable below the article: the groups reflow
2992 into columns so 23 topics read as an index, not a scroll of links. */
2993 .docs-sidebar nav {
2994 display: grid;
2995 grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr));
2996 column-gap: 2rem;
2997 }
2998
2999 .docs-sidebar-group:last-child { border-bottom: 0; }
3000 }
3001
3002 @media (max-width: 640px) {
3003 .docs-topic-row {
3004 grid-template-columns: minmax(0, 1fr) auto;
3005 gap: 0.6rem 1rem;
3006 }
3007
3008 .docs-topic-source {
3009 grid-column: 1 / -1;
3010 grid-row: 2;
3011 }
3012
3013 .docs-topic-arrow {
3014 grid-column: 2;
3015 grid-row: 1;
3016 }
3017 }
3018
3019 /* ---------- community release record ---------- */
3020 .community-credit-section {
3021 border-bottom: 0;
3022 }
3023
3024 .community-record-links {
3025 display: flex;
3026 flex-wrap: wrap;
3027 gap: 0.65rem 1.25rem;
3028 margin-top: 1.25rem;
3029 }
3030
3031 .community-record-links a {
3032 color: var(--indigo-deep);
3033 font-size: 0.75rem;
3034 font-weight: 600;
3035 }
3036
3037 .community-record-links a:hover {
3038 text-decoration: underline;
3039 text-underline-offset: 0.22rem;
3040 }
3041
3042 .community-credit-groups {
3043 display: grid;
3044 gap: 2rem;
3045 }
3046
3047 .community-credit-groups section {
3048 padding-top: 1rem;
3049 border-top: 1px solid var(--hairline);
3050 }
3051
3052 .community-credit-groups h3 {
3053 margin-bottom: 0.9rem;
3054 color: var(--ink-mute);
3055 font-size: 0.7rem;
3056 font-weight: 600;
3057 letter-spacing: 0.04em;
3058 text-transform: uppercase;
3059 }
3060
3061 .community-credit-list {
3062 display: flex;
3063 flex-wrap: wrap;
3064 gap: 0.45rem;
3065 }
3066
3067 .community-credit-list a {
3068 padding: 0.3rem 0.45rem;
3069 border: 1px solid var(--hairline);
3070 color: var(--ink-soft);
3071 font-family: var(--font-mono), "IBM Plex Mono", monospace;
3072 font-size: 0.75rem;
3073 }
3074
3075 .community-credit-list a:hover {
3076 border-color: var(--indigo);
3077 color: var(--indigo-deep);
3078 }
3079
3080 /* ------------------------------------------------------------------ */
3081 /* Docs theme — paper is the site default */
3082 /* */
3083 /* The docs sheet reads on the same paper as the rest of the folio. */
3084 /* The theme toggle (docs routes only) offers the whale's dark stage */
3085 /* as an opt-in, exactly the way the TUI keeps Blue Stage beside its */
3086 /* light preset. The dark override is set on */
3087 /* `html[data-theme="dark"] .docs-theme` through the shared */
3088 /* below-the-waterline rule beside :root; the attribute is applied */
3089 /* before paint by the inline script in the locale layout, so there */
3090 /* is no theme flash. */
3091 /* ------------------------------------------------------------------ */
3092
3093 .docs-theme {
3094 --docs-accent: var(--gpui-primary);
3095 --docs-button-bg: var(--gpui-paper-raised);
3096 --docs-button-border: var(--gpui-edge);
3097 --docs-button-text: var(--gpui-ink);
3098 background: var(--paper);
3099 color: var(--ink);
3100 }
3101
3102 .docs-theme .portal-button-secondary {
3103 border-color: var(--docs-button-border);
3104 background: var(--docs-button-bg);
3105 color: var(--docs-button-text);
3106 }
3107
3108 .docs-theme .portal-button-secondary:hover {
3109 border-color: var(--docs-accent);
3110 background: var(--docs-button-bg);
3111 color: var(--docs-accent);
3112 }
3113
3114 .docs-theme .portal-button-secondary:focus-visible,
3115 .docs-sidebar-link:focus-visible {
3116 outline: 2px solid var(--docs-accent);
3117 outline-offset: 2px;
3118 }
3119
3120 /* The opt-in dark sheet: the whale's stage tokens, scoped to the docs
3121 subtree so the shared nav keeps the paper. Surface/ink tokens come from
3122 the shared below-the-waterline rule; only the docs-specific inks are
3123 restated here. */
3124 html[data-theme="dark"] .docs-theme {
3125 --docs-accent: var(--gpui-primary-dark);
3126 --docs-button-bg: var(--gpui-stage-muted);
3127 --docs-button-border: var(--gpui-stage-edge);
3128 --docs-button-text: var(--gpui-stage-ink);
3129 --code-bg: var(--gpui-stage-deep);
3130 --code-fg: var(--gpui-stage-ink);
3131 }
3132
3133
3134 /* ------------------------------------------------------------------ */
3135 /* Shared surface states — empty / loading / error (surface-state.tsx) */
3136 /* ------------------------------------------------------------------ */
3137 /*
3138 * One plate for every data-bearing page's non-data moments. The mark on the
3139 * left carries the state in colour AND the copy carries it in words, so no
3140 * state is conveyed by colour alone: mute for empty, action blue for loading,
3141 * coral for error — the status-bar grammar the product already speaks.
3142 */
3143 .state-block {
3144 display: grid;
3145 grid-template-columns: auto minmax(0, 1fr);
3146 gap: 1rem;
3147 align-items: start;
3148 padding: clamp(1.5rem, 4vw, 2.25rem) clamp(1.25rem, 3vw, 1.75rem);
3149 border: 1px solid var(--stage-line);
3150 border-radius: 6px;
3151 background: var(--paper-card);
3152 color: var(--ink);
3153 }
3154
3155 .state-block-compact {
3156 padding: 1rem 1.15rem;
3157 gap: 0.8rem;
3158 }
3159
3160 .state-mark {
3161 width: 0.6rem;
3162 height: 0.6rem;
3163 margin-top: 0.42rem;
3164 border-radius: 999px;
3165 background: var(--ink-mute);
3166 flex: none;
3167 }
3168
3169 .state-block-loading .state-mark { background: var(--indigo); }
3170 .state-block-error .state-mark { background: var(--ocean-coral); }
3171 .state-block-error { border-color: color-mix(in srgb, var(--ocean-coral) 45%, var(--stage-line)); }
3172
3173 .state-copy { min-width: 0; }
3174
3175 .state-title {
3176 color: var(--ink);
3177 font-size: 0.98rem;
3178 font-weight: 600;
3179 letter-spacing: -0.01em;
3180 }
3181
3182 .state-body {
3183 max-width: 44rem;
3184 margin-top: 0.4rem;
3185 color: var(--ink-soft);
3186 font-size: 0.86rem;
3187 line-height: 1.65;
3188 }
3189
3190 .state-actions {
3191 display: flex;
3192 flex-wrap: wrap;
3193 gap: 0.6rem;
3194 margin-top: 1rem;
3195 }
3196
3197 .state-retry[aria-busy="true"] { opacity: 0.7; cursor: progress; }
3198
3199 /* Skeleton lines: neutral bars, never fake words. The shimmer is opt-in
3200 under no-preference; reduced motion sees still bars. */
3201 .state-skeleton {
3202 display: grid;
3203 gap: 0.55rem;
3204 margin-top: 0.85rem;
3205 }
3206
3207 .state-skeleton > span {
3208 display: block;
3209 height: 0.7rem;
3210 border-radius: 3px;
3211 background: color-mix(in srgb, var(--ink-mute) 22%, transparent);
3212 }
3213
3214 @media (prefers-reduced-motion: no-preference) {
3215 .state-skeleton > span {
3216 background: linear-gradient(
3217 90deg,
3218 color-mix(in srgb, var(--ink-mute) 18%, transparent) 0%,
3219 color-mix(in srgb, var(--ink-mute) 34%, transparent) 50%,
3220 color-mix(in srgb, var(--ink-mute) 18%, transparent) 100%
3221 );
3222 background-size: 200% 100%;
3223 animation: state-shimmer 1.6s ease-in-out infinite;
3224 }
3225 }
3226
3227 @keyframes state-shimmer {
3228 from { background-position: 200% 0; }
3229 to { background-position: -200% 0; }
3230 }
3231
3232 /* Route-level boundaries (loading.tsx / error.tsx / not-found.tsx) sit in
3233 the site container with the page rhythm so a boundary never looks like a
3234 different site. */
3235 .route-state {
3236 width: var(--container);
3237 margin-inline: auto;
3238 padding-block: clamp(3rem, 6vw, 4.75rem);
3239 max-width: 52rem;
3240 }
3241
3242 /* ------------------------------------------------------------------ */
3243 /* Connection banner — offline / reconnecting / degraded / restored */
3244 /* ------------------------------------------------------------------ */
3245 .connection-banner {
3246 position: sticky;
3247 top: 0;
3248 z-index: 35;
3249 display: grid;
3250 grid-template-columns: auto minmax(0, 1fr) auto;
3251 gap: 0.9rem;
3252 align-items: center;
3253 width: var(--container);
3254 margin: 0.75rem auto 0;
3255 padding: 0.7rem 1rem;
3256 border: 1px solid var(--stage-line);
3257 border-radius: 6px;
3258 background: color-mix(in srgb, var(--paper-card) 92%, transparent);
3259 backdrop-filter: blur(8px);
3260 color: var(--ink);
3261 }
3262
3263 .connection-mark {
3264 width: 0.6rem;
3265 height: 0.6rem;
3266 border-radius: 999px;
3267 background: var(--ink-mute);
3268 }
3269
3270 .connection-banner-offline { border-color: color-mix(in srgb, var(--ocean-coral) 50%, var(--stage-line)); }
3271 .connection-banner-offline .connection-mark { background: var(--ocean-coral); }
3272 .connection-banner-reconnecting .connection-mark { background: var(--indigo); }
3273 .connection-banner-degraded .connection-mark { background: var(--ochre); }
3274 .connection-banner-restored { border-color: color-mix(in srgb, var(--jade) 50%, var(--stage-line)); }
3275 .connection-banner-restored .connection-mark { background: var(--jade); }
3276
3277 @media (prefers-reduced-motion: no-preference) {
3278 .connection-banner-reconnecting .connection-mark {
3279 animation: connection-pulse 1.2s ease-in-out infinite;
3280 }
3281 .connection-banner {
3282 animation: mm-in 200ms cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
3283 }
3284 }
3285
3286 @keyframes connection-pulse {
3287 0%, 100% { opacity: 1; }
3288 50% { opacity: 0.35; }
3289 }
3290
3291 .connection-copy { min-width: 0; }
3292 .connection-title { font-size: 0.86rem; font-weight: 600; }
3293 .connection-body { margin-top: 0.15rem; color: var(--ink-soft); font-size: 0.78rem; line-height: 1.5; }
3294 .connection-checked { color: var(--ink-mute); font-family: var(--font-mono), "IBM Plex Mono", monospace; font-size: 0.75rem; }
3295
3296 .connection-actions { display: flex; gap: 0.5rem; }
3297
3298 .connection-button {
3299 display: inline-flex;
3300 min-height: 2.25rem;
3301 align-items: center;
3302 padding: 0.35rem 0.75rem;
3303 border: 1px solid var(--stage-line);
3304 border-radius: 5px;
3305 color: var(--ink);
3306 font-family: var(--font-mono), "IBM Plex Mono", monospace;
3307 font-size: 0.75rem;
3308 font-weight: 600;
3309 letter-spacing: 0.08em;
3310 text-transform: uppercase;
3311 transition: border-color 150ms ease, background-color 150ms ease, color 150ms ease;
3312 }
3313
3314 .connection-button:hover { border-color: var(--indigo); color: var(--indigo); }
3315 .connection-button-primary { border-color: var(--indigo); background: var(--indigo); color: var(--paper); }
3316 .connection-button-primary:hover { background: var(--indigo-deep); border-color: var(--indigo-deep); color: var(--paper); }
3317 .connection-button:disabled { opacity: 0.55; cursor: not-allowed; }
3318 .connection-button[aria-busy="true"] { cursor: progress; }
3319
3320 @media (max-width: 560px) {
3321 .connection-banner {
3322 grid-template-columns: auto minmax(0, 1fr);
3323 }
3324 .connection-actions {
3325 grid-column: 2;
3326 }
3327 }
3328
3329 /* ------------------------------------------------------------------ */
3330 /* Docs: release truth, task index, contextual help */
3331 /* ------------------------------------------------------------------ */
3332 .release-truth {
3333 margin-top: 1.4rem;
3334 color: var(--ink-mute);
3335 }
3336
3337 .release-truth-label {
3338 color: var(--ink-mute);
3339 letter-spacing: 0.12em;
3340 text-transform: uppercase;
3341 font-size: 0.7rem;
3342 }
3343
3344 .release-truth a {
3345 color: var(--indigo);
3346 }
3347
3348 .release-truth a:hover {
3349 color: var(--indigo-deep);
3350 text-decoration: underline;
3351 text-underline-offset: 0.2rem;
3352 }
3353
3354 .release-truth[data-release-state="published"] > span:not(.release-truth-label) {
3355 color: var(--jade);
3356 }
3357
3358 .docs-result-lead {
3359 margin: -0.2rem 0 0.9rem;
3360 color: var(--ink-soft);
3361 font-size: 0.82rem;
3362 }
3363
3364 .docs-result-heading h3 {
3365 font-size: 1.05rem;
3366 letter-spacing: -0.01em;
3367 }
3368
3369 .docs-result-heading-topics {
3370 margin-bottom: 0;
3371 padding-bottom: 0.75rem;
3372 }
3373
3374 .docs-result-topics {
3375 display: grid;
3376 gap: 2rem;
3377 }
3378
3379 .docs-task-group .docs-topic-list {
3380 border-top: 1px solid var(--stage-line);
3381 }
3382
3383 .docs-task-row .docs-topic-source {
3384 font-size: 0.75rem;
3385 }
3386
3387 .docs-help {
3388 display: grid;
3389 grid-template-columns: minmax(0, 1.3fr) minmax(12rem, 0.7fr);
3390 gap: clamp(1.5rem, 4vw, 3rem);
3391 margin-top: 3rem;
3392 padding: clamp(1.4rem, 3vw, 2rem);
3393 border: 1px solid var(--stage-line);
3394 border-radius: 6px;
3395 background: var(--paper-card);
3396 }
3397
3398 .docs-help-copy h2 {
3399 font-size: 1.15rem;
3400 letter-spacing: -0.015em;
3401 }
3402
3403 .docs-help-copy p {
3404 margin-top: 0.55rem;
3405 color: var(--ink-soft);
3406 font-size: 0.84rem;
3407 line-height: 1.65;
3408 }
3409
3410 .docs-help-source {
3411 font-family: var(--font-mono), "IBM Plex Mono", monospace;
3412 font-size: 0.75rem !important;
3413 color: var(--ink-mute) !important;
3414 }
3415
3416 .docs-help-source a {
3417 color: var(--indigo);
3418 }
3419
3420 .docs-help-source a:hover { text-decoration: underline; text-underline-offset: 0.2rem; }
3421
3422 .docs-help-links {
3423 display: grid;
3424 gap: 0.35rem;
3425 align-content: start;
3426 border-top: 1px solid var(--stage-line);
3427 padding-top: 0.6rem;
3428 }
3429
3430 .docs-help-links a {
3431 display: inline-flex;
3432 min-height: 2.5rem;
3433 align-items: center;
3434 color: var(--indigo);
3435 font-family: var(--font-mono), "IBM Plex Mono", monospace;
3436 font-size: 0.75rem;
3437 }
3438
3439 .docs-help-links a:hover { color: var(--indigo-deep); text-decoration: underline; text-underline-offset: 0.2rem; }
3440
3441 @media (max-width: 760px) {
3442 .docs-help { grid-template-columns: 1fr; }
3443 }
3444
3445 /* ---------- reference tables on docs pages ---------- */
3446 .docs-ref-rows {
3447 display: grid;
3448 border-top: 1px solid var(--hairline);
3449 }
3450
3451 .docs-ref-rows > div {
3452 display: grid;
3453 grid-template-columns: minmax(10rem, 0.42fr) minmax(0, 1fr);
3454 gap: 1.25rem;
3455 padding: 0.9rem 0;
3456 border-bottom: 1px solid var(--hairline);
3457 }
3458
3459 .docs-ref-rows dt {
3460 color: var(--ink);
3461 font-size: 0.88rem;
3462 font-weight: 600;
3463 }
3464
3465 .docs-ref-rows dd {
3466 min-width: 0;
3467 overflow-wrap: anywhere;
3468 color: var(--ink-soft);
3469 font-size: 0.86rem;
3470 line-height: 1.6;
3471 }
3472
3473 .docs-ref-rows code.inline { white-space: nowrap; }
3474
3475 @media (max-width: 560px) {
3476 .docs-ref-rows > div { grid-template-columns: 1fr; gap: 0.3rem; }
3477 }
3478
3479 /* ------------------------------------------------------------------ */
3480 /* Changelog */
3481 /* ------------------------------------------------------------------ */
3482 .changelog-facts {
3483 display: grid;
3484 grid-template-columns: repeat(2, minmax(0, 1fr));
3485 gap: 1rem;
3486 margin-top: 1.75rem;
3487 }
3488
3489 .changelog-facts > div {
3490 padding: 1.1rem 1.25rem;
3491 border: 1px solid var(--stage-line);
3492 border-radius: 6px;
3493 background: var(--paper-card);
3494 }
3495
3496 .changelog-facts span {
3497 display: block;
3498 color: var(--ink-mute);
3499 font-family: var(--font-mono), "IBM Plex Mono", monospace;
3500 font-size: 0.7rem;
3501 letter-spacing: 0.1em;
3502 text-transform: uppercase;
3503 }
3504
3505 .changelog-facts > div { min-width: 0; }
3506
3507 .changelog-facts strong {
3508 display: block;
3509 overflow-wrap: anywhere;
3510 margin-top: 0.45rem;
3511 color: var(--ink);
3512 font-size: 1.05rem;
3513 font-weight: 600;
3514 font-variant-numeric: tabular-nums;
3515 }
3516
3517 .changelog-facts a {
3518 display: inline-block;
3519 margin-top: 0.55rem;
3520 color: var(--indigo);
3521 font-size: 0.76rem;
3522 }
3523
3524 .changelog-facts a:hover { text-decoration: underline; text-underline-offset: 0.2rem; }
3525
3526 .changelog-facts [data-published="true"] strong { color: var(--jade); }
3527 .changelog-facts [data-candidate="unreleased"] strong { color: var(--ochre); }
3528
3529 .changelog-release {
3530 padding-block: 2.25rem;
3531 border-top: 1px solid var(--hairline);
3532 }
3533
3534 .changelog-release-head {
3535 min-width: 0;
3536 overflow-wrap: anywhere;
3537 display: flex;
3538 flex-wrap: wrap;
3539 align-items: baseline;
3540 justify-content: space-between;
3541 gap: 0.75rem 1.5rem;
3542 }
3543
3544 .changelog-release-head h2 {
3545 font-size: clamp(1.4rem, 2.6vw, 1.9rem);
3546 font-variant-numeric: tabular-nums;
3547 }
3548
3549 .changelog-release-head .dotline {
3550 color: var(--ink-mute);
3551 }
3552
3553 .changelog-release-head .dotline a { color: var(--indigo); }
3554 .changelog-release-head .dotline a:hover { text-decoration: underline; text-underline-offset: 0.2rem; }
3555
3556 .changelog-unreleased-note {
3557 max-width: 44rem;
3558 margin-top: 0.6rem;
3559 color: var(--ink-soft);
3560 font-size: 0.86rem;
3561 line-height: 1.6;
3562 }
3563
3564 .changelog-sections {
3565 display: grid;
3566 gap: 1.35rem;
3567 margin-top: 1.4rem;
3568 }
3569
3570 .changelog-sections h3 {
3571 display: flex;
3572 align-items: baseline;
3573 gap: 0.6rem;
3574 font-size: 0.7rem;
3575 font-weight: 600;
3576 letter-spacing: 0.1em;
3577 text-transform: uppercase;
3578 color: var(--ink-mute);
3579 }
3580
3581 .changelog-sections h3 a {
3582 color: var(--ink-mute);
3583 font-family: var(--font-mono), "IBM Plex Mono", monospace;
3584 font-size: 0.75rem;
3585 letter-spacing: 0.04em;
3586 text-transform: none;
3587 }
3588
3589 .changelog-sections h3 a:hover {
3590 color: var(--indigo);
3591 text-decoration: underline;
3592 text-underline-offset: 0.2rem;
3593 }
3594
3595 .changelog-sections ul {
3596 margin-top: 0.55rem;
3597 border-top: 1px solid var(--hairline);
3598 }
3599
3600 .changelog-sections li {
3601 min-width: 0;
3602 padding: 0.6rem 0;
3603 border-bottom: 1px solid var(--hairline);
3604 color: var(--ink-soft);
3605 font-size: 0.86rem;
3606 line-height: 1.6;
3607 /* Release notes quote commands, env names, and URLs verbatim; a long
3608 unbroken token must wrap inside the column, never widen the page. */
3609 overflow-wrap: anywhere;
3610 }
3611
3612 .changelog-sections li::before {
3613 content: "·";
3614 margin-right: 0.6rem;
3615 color: var(--stage-dim);
3616 }
3617
3618 @media (max-width: 640px) {
3619 .changelog-facts { grid-template-columns: 1fr; }
3620 }
3621
3622 /* ---------- /product: the availability table on paper ---------- */
3623 /* The same list the homepage sets in the water, re-inked for the sheet. */
3624 .product-availability-paper,
3625 .product-availability-paper > div {
3626 border-color: var(--hairline);
3627 }
3628 .product-availability-paper dt,
3629 .product-availability-paper dd strong {
3630 color: var(--ink);
3631 }
3632 .product-availability-paper dd {
3633 color: var(--ink-soft);
3634 }
3635
3636 /* ---------- usage counting: the consent sheet and its footer control ---------- */
3637 /* A quiet sheet at the foot of the viewport, on paper, with the site's own
3638 inks. It is not a modal: the page stays usable, and the choice is one
3639 click either way. */
3640 .usage-counting {
3641 display: grid;
3642 gap: 0.75rem;
3643 margin-top: 0.5rem;
3644 }
3645
3646 .usage-counting-status {
3647 color: var(--ink);
3648 font-weight: 500;
3649 }
3650
3651 .usage-counting-elsewhere {
3652 color: var(--ink-mute);
3653 font-size: 0.9rem;
3654 }
3655
3656 .usage-counting-button {
3657 display: inline-flex;
3658 justify-self: start;
3659 min-height: 2.75rem;
3660 align-items: center;
3661 padding: 0.5rem 1.1rem;
3662 border: 1px solid var(--indigo);
3663 border-radius: 5px;
3664 color: var(--indigo);
3665 font-size: 0.95rem;
3666 font-weight: 500;
3667 cursor: pointer;
3668 transition: background-color 150ms ease, color 150ms ease;
3669 }
3670
3671 .usage-counting-button:hover {
3672 background: rgb(var(--c-indigo) / 0.1);
3673 }
3674
3675 .usage-counting-button:focus-visible {
3676 outline: 2px solid var(--indigo);
3677 outline-offset: 2px;
3678 }
3679
3680 /* ---------- docs: the reading sheet ---------- */
3681 /* Read mode: comprehension first. The article gets a book measure, the serif
3682 title voice on its headings, generous leading, and a contents rail that
3683 stays put while the sheet scrolls. */
3684 .docs-content {
3685 max-width: 46rem;
3686 }
3687
3688 .docs-content h1 {
3689 font-size: clamp(2.2rem, 3.6vw, 3rem);
3690 line-height: 1.05;
3691 margin-bottom: 0.35rem;
3692 }
3693
3694 .docs-content h2 {
3695 font-family: var(--font-serif), "Newsreader", Georgia, serif;
3696 font-weight: 500;
3697 font-size: clamp(1.5rem, 2.2vw, 1.9rem);
3698 line-height: 1.15;
3699 letter-spacing: -0.015em;
3700 margin-bottom: 0.25rem;
3701 }
3702
3703 .docs-content h3 {
3704 font-size: 1.05rem;
3705 }
3706
3707 .docs-content p,
3708 .docs-content li {
3709 max-width: 66ch;
3710 font-size: 1rem;
3711 line-height: 1.7;
3712 }
3713
3714 .docs-content > section + section {
3715 padding-top: 0.5rem;
3716 }
3717
3718 .docs-content code.inline {
3719 background: var(--paper-card);
3720 border-color: var(--hairline);
3721 }
3722
3723 .docs-content pre.code-block {
3724 margin-block: 1rem;
3725 }
3726
3727 /* The contents rail: a running index in the margin, sticky on tall screens. */
3728 @media (min-width: 901px) {
3729 .docs-sidebar {
3730 position: sticky;
3731 top: 5.25rem;
3732 max-height: calc(100vh - 6rem);
3733 overflow-y: auto;
3734 padding-right: 0.5rem;
3735 }
3736 }
3737
3738 .docs-sidebar-heading {
3739 font-family: var(--font-serif), "Newsreader", Georgia, serif;
3740 font-size: 1.05rem;
3741 font-weight: 500;
3742 }
3743
3744 .docs-sidebar-category {
3745 font-family: var(--font-mono), "IBM Plex Mono", monospace;
3746 font-size: 0.68rem;
3747 letter-spacing: 0.14em;
3748 }
3749
3750 .docs-sidebar-link {
3751 font-size: 0.86rem;
3752 padding-block: 0.36rem;
3753 }
3754
3755 .docs-sidebar-link-current {
3756 color: var(--ink);
3757 font-weight: 600;
3758 }
3759
3760 .docs-sidebar-link-current::before {
3761 content: "";
3762 display: inline-block;
3763 width: 0.4rem;
3764 height: 1px;
3765 margin-right: 0.45rem;
3766 vertical-align: middle;
3767 background: var(--indigo);
3768 }
3769
3770 /* Topic rows on the hub: a title with room to breathe, the source path quiet. */
3771 .docs-topic-title {
3772 font-size: 0.98rem;
3773 }
3774
3775 .docs-topic-main p {
3776 font-size: 0.86rem;
3777 line-height: 1.6;
3778 }
3779
3780 .docs-result-heading h2 {
3781 font-family: var(--font-serif), "Newsreader", Georgia, serif;
3782 font-weight: 500;
3783 font-size: 1.6rem;
3784 }
3785
3786 /* The docs hero band: the mark and the release line as one running head. */
3787 .docs-portal .hero {
3788 padding-block: 1rem;
3789 background: var(--paper-deep);
3790 }
3791
3792 .docs-portal .portal-mark {
3793 color: var(--ink);
3794 font-family: var(--font-serif), "Newsreader", Georgia, serif;
3795 font-size: 1.05rem;
3796 font-weight: 500;
3797 }
3798
3799 .release-truth {
3800 margin-top: 0;
3801 }
3802
3803 /* Contextual help plate at the foot of every page, on the sheet's own card. */
3804 .docs-help {
3805 background: var(--paper-card);
3806 border-color: var(--hairline);
3807 }
3808
3809 .docs-help-copy h2 {
3810 font-family: var(--font-serif), "Newsreader", Georgia, serif;
3811 font-weight: 500;
3812 font-size: 1.4rem;
3813 }
3814
3815 /* Keep the terminal centered and compact beneath the introductory copy. */
3816 .folio-hero-grid { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto auto auto; row-gap: 2rem; }
3817 .folio-hero-copy { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: clamp(2rem, 5vw, 5rem); max-width: none; grid-column: 1; grid-row: 1; padding-bottom: 0; }
3818 .folio-hero-copy h1 { grid-column: 1; grid-row: 1 / 3; max-width: none; font-size: clamp(2.75rem, 5vw, 4.5rem); line-height: 1.06; text-wrap: balance; }
3819 .folio-hero-copy .folio-lede { grid-column: 2; grid-row: 1; margin-top: 0; align-self: end; }
3820 .folio-hero-copy .folio-actions { grid-column: 2; grid-row: 2; align-self: start; margin-top: 1.25rem; }
3821 .folio-shot { grid-column: 1; grid-row: 2; width: min(100%, 56rem); justify-self: center; margin-top: 0; }
3822 .folio-chapter { grid-column: 1; grid-row: 3; justify-self: start; }
3823 .product-install-grid > div, .product-composer, .product-composer > div { min-width: 0; }
3824 @media (max-width: 760px) {
3825 .folio-hero-copy { display: block; }
3826 .folio-hero-copy .folio-lede { margin-top: 1.25rem; }
3827 .folio-shot { width: 100%; }
3828 }
3829
3829 lines CSS