返回 CodeWhale
globals.css
根目录 / web / app / globals.css
1 @tailwind base;
2 @tailwind components;
3 @tailwind utilities;
4
5 /* ---------- root tokens — Codewhale ocean ---------- */
6 :root {
7 /* RGB channel triples backing the Tailwind surface/ink tokens (see
8 tailwind.config.ts). These carry the same light values as the hex vars
9 below; the docs routes override them for dark mode. */
10 --c-paper: 244 247 251;
11 --c-paper-deep: 232 238 248;
12 --c-paper-edge: 203 211 223;
13 --c-ink: 20 33 58;
14 --c-ink-soft: 69 81 104;
15 --c-ink-mute: 91 103 128;
16 --c-stage-soft: 182 192 212;
17
18 /* Paper-newspaper baseline (issue #4934) uses Blue Stage light tokens so
19 the editorial sheet stays in lockstep with the TUI palette. Ocean deep
20 values below power the terminal chrome accents only. */
21 --paper: #f4f7fb;
22 --paper-deep: #e8eef8;
23 --paper-edge: #cbd3df;
24 /* Blue Stage Light's LIGHT_PANEL — cwc's `--surface`. This is the product's
25 *card* value, not its page value: the desktop capture is ivory cards on a
26 blue-grey page. Raising the sheet itself to ivory would break lockstep in
27 the other direction, so warmth arrives only where the product puts it. */
28 --paper-card: #fffdf8;
29 --paper-line: #1b2230;
30 --paper-line-soft: #cbd3df;
31 --ink: #14213a;
32 --ink-soft: #455168;
33 --ink-mute: #5b6780;
34 --indigo: #315fd8;
35 --indigo-deep: #2448a6;
36 --indigo-pale: #e8eef8;
37 --action-on-dark: #6aaef2;
38 --ochre: #7a5500;
39 --jade: #08766d;
40 --seafoam: #4fd1c5;
41 --cobalt: #315fd8;
42 --ocean-deep: #03070d;
43 --ocean-mid: #0e1729;
44 --ocean-current: #d1ebf4;
45 --ocean-mist: #b6c0d4;
46 --ocean-coral: #ff7a59;
47 --signal-gold: #f6c453;
48 --stage-text: #f6f2e8;
49 --stage-soft: #b6c0d4;
50 --stage-muted: #93a0b8;
51
52 /* Blue Stage field, verbatim from crates/tui/src/palette/tokens.rs. These
53 back the single water column below the waterline: one gradient sampled by
54 absolute page position across four DOM bands, exactly as the TUI samples
55 one column across header / transcript / phase / composer. No widget
56 restarts its own gradient. */
57 --stage-field-top: #0e1729; /* WHALE_PANEL — surface */
58 --stage-field-mid: #08111c; /* WHALE_CHROME — the authored 42% break */
59 --stage-field-deep: #03070d; /* WHALE_BG — deep field, and the footer seabed */
60 --stage-ambient: #264866;
61 --stage-composer: #162238; /* WHALE_COMPOSER — the raised input plate */
62 --stage-elevated: #182742; /* WHALE_ELEVATED */
63 --stage-line: #263e5c; /* WHALE_BORDER — blue at 25% on stage */
64 --stage-hint: #8491aa;
65 --stage-dim: #697791;
66 --violet: #ad88ff; /* WHALE_MODE_OPERATE — 1px rules only, never text */
67
68 /* Hairline + code surfaces routed through vars so the docs dark theme can
69 lighten hairlines and raise the code panel without touching every rule. */
70 --hairline: rgba(20, 35, 70, 0.14);
71 --code-bg: #03070d;
72 --code-fg: #f6f2e8;
73 }
74
75 /* ---------- base ---------- */
76 html {
77 -webkit-font-smoothing: antialiased;
78 -moz-osx-font-smoothing: grayscale;
79 max-width: 100%;
80 overflow-x: clip;
81 }
82
83 body {
84 background: var(--paper);
85 color: var(--ink);
86 font-family: var(--font-body), "IBM Plex Sans", "Noto Sans SC", system-ui, sans-serif;
87 font-feature-settings: "ss01", "cv11", "tnum";
88 max-width: 100%;
89 overflow-x: clip;
90 position: relative;
91 }
92
93 .codewhale-mark-primary { fill: var(--signal-gold); }
94 .codewhale-mark-current { fill: #48d7ff; }
95
96 main, header, footer, nav { position: relative; z-index: 1; }
97
98 /* ---------- type ---------- */
99 .font-display { font-family: var(--font-display), "Fraunces", "Noto Serif SC", Georgia, serif; }
100 .font-cjk { font-family: "Noto Serif SC", "Source Han Serif SC", serif; }
101
102 /* CJK paragraph rhythm — looser leading, wider tracking for body; tighter for headings */
103 .cjk-body {
104 line-height: 1.9;
105 letter-spacing: 0.02em;
106 word-break: break-all;
107 }
108 .cjk-heading {
109 letter-spacing: -0.01em;
110 }
111 .cjk-prose p {
112 line-height: 1.9;
113 letter-spacing: 0.02em;
114 }
115 /* Full-width punctuation should use CJK spacing */
116 .cjk-prose {
117 font-feature-settings: "halt", "pwid";
118 }
119 .font-mono { font-family: var(--font-mono), "JetBrains Mono", ui-monospace, monospace; }
120
121 /* ---------- the ` · ` chain ---------- */
122 /* The single most recognisable thing about the TUI — its header, empty state
123 and footer all speak in dot chains — and the grammar the product's voice is
124 carried by on this site, on both sides of the waterline. The separator is
125 punctuation emitted by CSS, never copy: no locale translates it, and no
126 string is ever concatenated around one. No uppercase and no wide tracking:
127 the TUI header has neither, and both are what break Han. */
128 .dotline {
129 display: flex;
130 flex-wrap: wrap;
131 align-items: baseline;
132 font-family: var(--font-mono), "JetBrains Mono", ui-monospace, monospace;
133 font-size: 0.72rem;
134 letter-spacing: 0.02em;
135 text-transform: none;
136 }
137
138 /* The separator hangs off the END of the preceding item, not the start of the
139 next one. When a long chain wraps, a line ending in `·` reads as
140 continuation; a line beginning with one reads as a bullet list. */
141 .dotline > *:not(:last-child)::after {
142 content: "·";
143 margin-inline: 0.5em;
144 color: var(--stage-dim);
145 }
146
147 html[lang="zh"] .dotline,
148 html[lang="ja"] .dotline,
149 html[lang="ko"] .dotline {
150 letter-spacing: 0;
151 }
152
153 h1, h2, h3, h4 {
154 font-family: var(--font-display), "Fraunces", "Noto Serif SC", Georgia, serif;
155 font-weight: 600;
156 letter-spacing: -0.03em;
157 color: var(--ink);
158 }
159
160 h1 { font-size: clamp(2.25rem, 5vw, 4.75rem); line-height: 0.98; word-break: keep-all; overflow-wrap: anywhere; }
161 h2 { font-size: clamp(1.5rem, 2.8vw, 2.6rem); line-height: 1.08; word-break: keep-all; overflow-wrap: anywhere; }
162 h3 { font-size: 1.18rem; line-height: 1.25; }
163
164 /* `overflow-wrap: anywhere` keeps long English headings safe, but can strand
165 CJK punctuation — or a lone numeral — on a line of its own. Strict CJK
166 line-breaking keeps punctuation attached while still allowing breaks between
167 Han characters. ja and ko want the same rule: ja for the identical reason as
168 zh, ko because it has real word boundaries and should break on them. */
169 html[lang="zh"] h1,
170 html[lang="zh"] h2,
171 html[lang="zh"] h3,
172 html[lang="ja"] h1,
173 html[lang="ja"] h2,
174 html[lang="ja"] h3,
175 html[lang="ko"] h1,
176 html[lang="ko"] h2,
177 html[lang="ko"] h3 {
178 line-break: strict;
179 word-break: normal;
180 overflow-wrap: break-word;
181 }
182
183 @media (max-width: 640px) {
184 h1 .font-cjk {
185 display: inline-block;
186 font-size: clamp(1.6rem, 7.5vw, 2.2rem);
187 overflow-wrap: anywhere;
188 }
189 /* Keep headings inside the viewport without inserting awkward English hyphens. */
190 h1, h2 { hyphens: auto; }
191 html[lang="en"] h1,
192 html[lang="en"] h2 { hyphens: none; }
193 }
194
195 /* ---------- structural primitives ---------- */
196 /* Hairlines stay charcoal but softened with a touch of opacity so a pure-white
197 background doesn't read as harsh black-on-white office stationery. */
198 .hairline { border-color: var(--hairline); }
199 .hairline-t { border-top: 1px solid var(--hairline); }
200 .hairline-b { border-bottom: 1px solid var(--hairline); }
201 .hairline-l { border-left: 1px solid var(--hairline); }
202 .hairline-r { border-right: 1px solid var(--hairline); }
203
204 .double-rule {
205 background-image:
206 linear-gradient(var(--hairline), var(--hairline)),
207 linear-gradient(var(--hairline), var(--hairline));
208 background-size: 100% 1px, 100% 1px;
209 background-position: top, bottom;
210 background-repeat: no-repeat;
211 padding: 0.45rem 0;
212 }
213
214 .col-rule > * + * {
215 border-left: 1px solid var(--hairline);
216 }
217 /* Single-column phones: drop the column rules so cards stack flush. */
218 @media (max-width: 767px) {
219 .col-rule > * + * { border-left: 0; border-top: 1px solid var(--hairline); }
220 }
221
222 /* small-caps eyebrow */
223 .eyebrow {
224 font-family: var(--font-mono), "JetBrains Mono", monospace;
225 font-size: 0.66rem;
226 font-weight: 500;
227 letter-spacing: 0.18em;
228 text-transform: uppercase;
229 color: var(--ink-mute);
230 }
231
232 /* ---------- compact section marker retained on legacy routes ---------- */
233 .seal {
234 display: inline-flex;
235 align-items: center;
236 justify-content: center;
237 background: var(--ink);
238 color: var(--paper);
239 font-family: "Noto Serif SC", serif;
240 font-weight: 700;
241 width: 2.6rem;
242 height: 2.6rem;
243 border-radius: 4px;
244 letter-spacing: -0.04em;
245 }
246
247 /* Indigo variant for the few routes that need a stronger section marker. */
248 .seal-indigo {
249 background: var(--indigo);
250 }
251
252 /* Below the waterline the seal inverts. An ink block on the field reads as a
253 hole punched in the water; ivory-on-deep reads as the last editorial device
254 before the seabed. */
255 .ocean-column .seal {
256 background: var(--stage-text);
257 color: var(--ocean-deep);
258 }
259
260 /* ---------- pills / status ---------- */
261 .pill {
262 display: inline-flex;
263 align-items: center;
264 gap: 0.35rem;
265 padding: 0.12rem 0.45rem;
266 font-family: var(--font-mono), monospace;
267 font-size: 0.66rem;
268 font-weight: 500;
269 letter-spacing: 0.06em;
270 text-transform: uppercase;
271 border: 1px solid var(--paper-line);
272 background: var(--paper);
273 color: var(--ink);
274 }
275 .pill-hot { background: var(--indigo); color: var(--paper); border-color: var(--indigo); }
276 .pill-new { background: var(--paper); color: var(--ink); border-color: var(--ink); }
277 .pill-jade { background: var(--jade); color: var(--paper); border-color: var(--jade); }
278 .pill-ochre { background: var(--ochre); color: var(--paper); border-color: var(--ochre); }
279 .pill-ghost { background: transparent; color: var(--ink-mute); border-color: var(--ink-mute); }
280
281 /* ---------- numbers ---------- */
282 .tabular { font-variant-numeric: tabular-nums; }
283 .bignum {
284 font-family: var(--font-body), "IBM Plex Sans", system-ui, sans-serif;
285 font-weight: 600;
286 font-size: 2.2rem;
287 line-height: 1;
288 letter-spacing: -0.04em;
289 font-variant-numeric: tabular-nums;
290 }
291
292 /* ---------- code blocks ---------- */
293 pre.code-block {
294 background: var(--code-bg);
295 color: var(--code-fg);
296 max-width: 100%;
297 min-width: 0;
298 padding: 1rem 1.1rem;
299 font-family: var(--font-mono), monospace;
300 font-size: 0.82rem;
301 line-height: 1.55;
302 border: 1px solid var(--hairline);
303 overflow-x: auto;
304 position: relative;
305 white-space: pre;
306 -webkit-overflow-scrolling: touch;
307 }
308 pre.code-block::before {
309 content: "";
310 position: absolute;
311 top: 0; left: 0; right: 0;
312 height: 3px;
313 background: linear-gradient(90deg, var(--action-on-dark) 0 70%, var(--seafoam) 70% 100%);
314 }
315 pre.code-block .prompt { color: var(--action-on-dark); }
316 pre.code-block .comment { color: #8b8f9a; }
317 pre.code-block .key { color: var(--signal-gold); }
318
319 @media (max-width: 640px) {
320 pre.code-block { font-size: 0.76rem; padding: 0.85rem 0.95rem; }
321 }
322
323 code.inline {
324 background: var(--paper-deep);
325 border: 1px solid var(--hairline);
326 padding: 0.05rem 0.32rem;
327 font-family: var(--font-mono), monospace;
328 font-size: 0.85em;
329 border-radius: 2px;
330 }
331
332
333 /* ---------- search ---------- */
334 .search-input {
335 font-family: var(--font-body), system-ui, sans-serif;
336 font-size: 1rem;
337 padding: 0.75rem 2.5rem 0.75rem 1rem;
338 background: var(--paper);
339 color: var(--ink);
340 border: 1px solid var(--hairline);
341 transition: border-color 180ms ease, box-shadow 180ms ease;
342 }
343 .search-input::placeholder { color: var(--ink-mute); }
344 .search-input:focus {
345 outline: none;
346 border-color: var(--indigo);
347 box-shadow: 0 0 0 3px var(--indigo-pale);
348 }
349
350 mark.search-highlight {
351 background: var(--indigo-pale);
352 color: var(--indigo-deep);
353 padding: 0.02em 0.08em;
354 border-radius: 2px;
355 }
356
357 /* ---------- nav link ---------- */
358 .site-nav {
359 position: sticky;
360 z-index: 30;
361 top: 0;
362 border-bottom: 1px solid var(--hairline);
363 background: rgba(244, 247, 251, 0.94);
364 backdrop-filter: blur(10px);
365 }
366
367 .site-nav-inner {
368 display: flex;
369 width: min(100% - 2.5rem, 74rem);
370 min-height: 4.25rem;
371 align-items: center;
372 justify-content: space-between;
373 gap: 2rem;
374 margin-inline: auto;
375 }
376
377 .site-wordmark {
378 display: inline-flex;
379 flex-shrink: 0;
380 align-items: center;
381 gap: 0.7rem;
382 color: var(--ink);
383 font-family: var(--font-display), "Fraunces", Georgia, serif;
384 font-size: 1.15rem;
385 font-weight: 600;
386 letter-spacing: -0.03em;
387 }
388
389 /* Newspaper masthead (issue #4934 baseline) */
390 .paper-issue-bar {
391 border-bottom: 1px solid var(--hairline);
392 background: var(--paper);
393 }
394
395 .paper-issue-inner {
396 display: flex;
397 width: min(100% - 2.5rem, 74rem);
398 margin-inline: auto;
399 align-items: center;
400 justify-content: space-between;
401 gap: 1rem;
402 padding-block: 0.4rem;
403 font-family: var(--font-mono), "JetBrains Mono", monospace;
404 font-size: 0.62rem;
405 font-weight: 500;
406 letter-spacing: 0.16em;
407 text-transform: uppercase;
408 color: var(--ink-mute);
409 }
410
411 .paper-issue-left,
412 .paper-issue-right {
413 display: flex;
414 align-items: center;
415 gap: 0.65rem;
416 }
417
418 .paper-issue-sep { opacity: 0.55; }
419
420 .paper-nav-inner {
421 min-height: 3.85rem;
422 padding-block: 0.55rem;
423 }
424
425 .paper-wordmark {
426 gap: 0.75rem;
427 min-width: 0;
428 }
429
430 .paper-wordmark-text {
431 display: flex;
432 flex-direction: column;
433 line-height: 1.1;
434 min-width: 0;
435 }
436
437 .paper-wordmark-name {
438 display: inline-flex;
439 align-items: center;
440 gap: 0.4rem;
441 font-size: 1.25rem;
442 letter-spacing: -0.03em;
443 }
444
445 .paper-wordmark-whale {
446 color: var(--indigo);
447 flex-shrink: 0;
448 }
449
450 .paper-wordmark-tag {
451 margin-top: 0.18rem;
452 font-family: "Noto Serif SC", "Source Han Serif SC", serif;
453 font-size: 0.66rem;
454 font-weight: 400;
455 letter-spacing: 0.12em;
456 color: var(--ink-mute);
457 white-space: nowrap;
458 overflow: hidden;
459 text-overflow: ellipsis;
460 }
461
462 .paper-star-badge {
463 font-family: var(--font-mono), "JetBrains Mono", monospace;
464 font-size: 0.68rem;
465 letter-spacing: 0.04em;
466 text-transform: uppercase;
467 }
468
469 .paper-install-cta {
470 align-items: center;
471 min-height: 2.25rem;
472 padding: 0.35rem 0.85rem;
473 background: var(--indigo);
474 color: var(--paper);
475 font-family: var(--font-mono), "JetBrains Mono", monospace;
476 font-size: 0.7rem;
477 font-weight: 600;
478 letter-spacing: 0.1em;
479 text-transform: uppercase;
480 transition: background-color 150ms ease;
481 }
482
483 .paper-install-cta:hover {
484 background: var(--indigo-deep);
485 color: var(--paper);
486 }
487
488 .site-nav-actions {
489 display: flex;
490 align-items: center;
491 gap: 0.65rem;
492 }
493
494 .site-github-link {
495 display: inline-flex;
496 min-height: 2.25rem;
497 align-items: center;
498 padding: 0.35rem 0.75rem;
499 border: 1px solid var(--hairline);
500 border-radius: 6px;
501 font-family: var(--font-body), "IBM Plex Sans", system-ui, sans-serif;
502 font-size: 0.72rem;
503 font-weight: 600;
504 }
505
506 .site-github-link:hover { border-color: var(--ink); }
507
508 .nav-link {
509 font-family: var(--font-body), "IBM Plex Sans", system-ui, sans-serif;
510 font-size: 0.78rem;
511 letter-spacing: 0;
512 color: var(--ink);
513 position: relative;
514 padding: 0.25rem 0;
515 }
516 .nav-link::after {
517 content: "";
518 position: absolute;
519 left: 0; right: 0; bottom: -2px;
520 height: 2px;
521 background: var(--indigo);
522 transform: scaleX(0);
523 transform-origin: left;
524 transition: transform 180ms ease;
525 }
526 .nav-link:hover::after, .nav-link[aria-current="page"]::after { transform: scaleX(1); }
527
528 /* ---------- footer ---------- */
529 .site-footer {
530 border-top: 1px solid rgb(var(--c-stage-soft) / 0.13);
531 background: var(--ocean-deep);
532 color: var(--stage-soft);
533 }
534
535 .site-footer-main,
536 .site-footer-meta {
537 width: min(100% - 2.5rem, 74rem);
538 margin-inline: auto;
539 }
540
541 .site-footer-main {
542 display: grid;
543 grid-template-columns: minmax(16rem, 1.25fr) minmax(18rem, 0.75fr);
544 gap: 4rem;
545 padding-block: 2.8rem;
546 }
547
548 .site-wordmark-footer,
549 .site-wordmark-footer span { color: var(--stage-text); }
550 .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; }
551
552 .site-footer-links {
553 display: grid;
554 grid-template-columns: repeat(2, minmax(0, 1fr));
555 gap: 2rem;
556 }
557
558 .site-footer-links > div { display: flex; flex-direction: column; gap: 0.55rem; }
559 .site-footer-links span { margin-bottom: 0.25rem; color: var(--ocean-current); font-family: var(--font-mono), "JetBrains Mono", monospace; font-size: 0.64rem; letter-spacing: 0.1em; text-transform: uppercase; }
560 .site-footer-links a { color: rgb(var(--c-stage-soft) / 0.76); font-size: 0.82rem; }
561 .site-footer-links a:hover { color: var(--stage-text); }
562
563 .site-footer-meta {
564 display: grid;
565 grid-template-columns: 1fr auto auto;
566 gap: 1.5rem;
567 align-items: center;
568 padding-block: 1rem;
569 border-top: 1px solid rgb(var(--c-stage-soft) / 0.13);
570 color: rgb(var(--c-stage-soft) / 0.5);
571 font-family: var(--font-mono), "JetBrains Mono", monospace;
572 font-size: 0.62rem;
573 }
574
575 .site-footer-meta a:hover { color: var(--ocean-current); }
576 .site-footer-meta > div { display: flex; gap: 1rem; }
577
578 /* ---------- ticker ---------- */
579 .ticker-viewport {
580 position: relative;
581 flex: 1 1 auto;
582 overflow: hidden;
583 }
584
585 .ticker-track {
586 display: inline-flex;
587 gap: 3rem;
588 white-space: nowrap;
589 animation: ticker 80s linear infinite;
590 padding-right: 3rem;
591 }
592 @keyframes ticker {
593 from { transform: translateX(0); }
594 to { transform: translateX(-50%); }
595 }
596
597 /* One wire entry: verb, number or tag, title, by-line, age. Baseline-aligned
598 so the mono verb sits on the same line as the title it qualifies. */
599 .ticker-item {
600 display: inline-flex;
601 align-items: baseline;
602 gap: 0.5rem;
603 }
604
605 /* The verb carries the state. Merges are the headline case, so they get the
606 one warm-neutral ink on the sheet; releases take ochre; anything closed
607 recedes to mute. Everything else is the action blue. */
608 .ticker-verb {
609 color: var(--indigo);
610 font-size: 0.62rem;
611 letter-spacing: 0.12em;
612 text-transform: uppercase;
613 }
614
615 .ticker-verb[data-event="merged"] { color: var(--jade); }
616 .ticker-verb[data-event="published"] { color: var(--ochre); }
617 .ticker-verb[data-event="closed"] { color: var(--ink-mute); }
618
619 .ticker-num,
620 .ticker-tag,
621 .ticker-by,
622 .ticker-age {
623 color: var(--ink-mute);
624 }
625
626 .ticker-title { color: var(--ink); }
627
628 /* The contributor's handle is the point of the line, not a footnote. */
629 .ticker-handle {
630 color: var(--ink);
631 font-weight: 600;
632 }
633
634 .ticker-first {
635 padding: 0 0.35rem;
636 border: 1px solid var(--ochre);
637 color: var(--ochre);
638 font-size: 0.58rem;
639 letter-spacing: 0.1em;
640 text-transform: uppercase;
641 }
642
643 .ticker-sep { color: var(--paper-line-soft); }
644
645 /* ---------- terminal player caret ---------- */
646 .tp-caret {
647 display: inline-block;
648 width: 0.55em;
649 height: 1.05em;
650 margin-left: 1px;
651 vertical-align: text-bottom;
652 background: var(--action-on-dark);
653 animation: tp-blink 1.06s steps(1, end) infinite;
654 }
655 @keyframes tp-blink {
656 50% { opacity: 0; }
657 }
658
659 @media (prefers-reduced-motion: reduce) {
660 .tp-caret { animation: none; }
661 .ticker-track { animation: none; }
662 /* A frozen track would clip every entry past the fold with no way to reach
663 them. Stopping the motion must not also remove the content. */
664 .ticker-viewport { overflow-x: auto; }
665 }
666
667 /* ---------- ambient ---------- */
668 /*
669 * Two effects, both OPT-IN under `no-preference` rather than opted out under
670 * `reduce`. A `reduce` override can be defeated by specificity; a gate cannot.
671 * Reduced motion freezes the field — it never removes it, so the column's
672 * gradient and the whale below are unconditional and only the movement is not.
673 *
674 * The TUI's ambient life — fish, jellyfish, bubbles, the whale cameo — stays
675 * out of scope. This page quotes the product's restraint doctrine in its own
676 * copy. Four keyframes on the whole site, and this is two of them.
677 */
678
679 /* M1 — the column breath. Opacity only, on a 90s cycle: the TUI's authored
680 0.018–0.055 phase bias expressed as the same fraction of a mix. Opacity is
681 the one property that cannot cause layout work on an element four bands
682 tall. No position change, no hue shift, no filter. */
683 @keyframes cw-breath {
684 0%, 100% { opacity: 0; }
685 50% { opacity: 0.045; }
686 }
687
688 /* M2 — the caustic. `ambient_life.rs`'s literal behaviour: ~1.3s crossing the
689 mark, parked off-canvas for the remaining ~2.7s, peak 0.33. The easing is a
690 sine in-out, i.e. the raised cosine it is meant to be. */
691 @keyframes cw-caustic {
692 0% { transform: translateX(0); }
693 32.5% { transform: translateX(160px); }
694 100% { transform: translateX(160px); }
695 }
696
697 @media (prefers-reduced-motion: no-preference) {
698 .ocean-column::after {
699 content: "";
700 position: absolute;
701 inset: 0;
702 z-index: -1;
703 pointer-events: none;
704 background: var(--stage-ambient);
705 opacity: 0;
706 animation: cw-breath 90s ease-in-out infinite;
707 }
708
709 .codewhale-caustic {
710 animation: cw-caustic 4s cubic-bezier(0.37, 0, 0.63, 1) infinite;
711 }
712 }
713
714 /* ---------- decorative big CJK in margin ---------- */
715 .margin-glyph {
716 font-family: "Noto Serif SC", serif;
717 font-weight: 700;
718 color: var(--ink);
719 opacity: 0.04;
720 font-size: 18rem;
721 line-height: 0.9;
722 pointer-events: none;
723 user-select: none;
724 position: absolute;
725 }
726
727 /* ---------- focus + selection ---------- */
728 ::selection { background: var(--indigo); color: var(--paper); }
729 :focus-visible { outline: 2px solid var(--indigo); outline-offset: 2px; }
730
731 /* ---------- link reset ---------- */
732 a { color: inherit; text-decoration: none; }
733 a.body-link {
734 color: var(--ink);
735 background-image: linear-gradient(var(--indigo), var(--indigo));
736 background-repeat: no-repeat;
737 background-position: 0 100%;
738 background-size: 100% 1px;
739 transition: background-size 180ms ease;
740 }
741 a.body-link:hover { background-size: 100% 6px; color: var(--ink); }
742
743 /* ---------- mobile-only adjustments ---------- */
744 @media (max-width: 640px) {
745 /* Big CJK margin glyph already hidden via tailwind's `hidden lg:block`,
746 but re-assert that nothing hits the viewport edge. */
747 .margin-glyph { display: none; }
748
749 /* Ticker text gets cramped on phones — shrink + tighten gaps */
750 .ticker-track { gap: 1.5rem; padding-right: 1.5rem; }
751 }
752
753 @media (max-width: 900px) {
754 .site-nav-inner { gap: 1rem; }
755 .site-github-link { display: none; }
756 .site-footer-main { grid-template-columns: 1fr; gap: 2.5rem; }
757 .site-footer-meta { grid-template-columns: 1fr; gap: 0.7rem; }
758 }
759
760 @media (max-width: 700px) {
761 .site-nav-inner,
762 .site-footer-main,
763 .site-footer-meta { width: min(100% - 2rem, 74rem); }
764 .site-wordmark { font-size: 1.05rem; }
765 }
766
767 /* Anchor fallback; page-level scroll-mt utilities should be able to override it. */
768 :where([id]) { scroll-margin-top: 5rem; }
769
770 /* ------------------------------------------------------------------ */
771 /* Documentation-led public home */
772 /* ------------------------------------------------------------------ */
773
774 .portal-home {
775 background: var(--paper);
776 color: var(--ink);
777 }
778
779 .portal-container {
780 width: min(100% - 2.5rem, 72rem);
781 margin-inline: auto;
782 }
783
784 .portal-hero {
785 position: relative;
786 overflow: hidden;
787 border-bottom: 1px solid var(--hairline);
788 background:
789 radial-gradient(circle at 84% 8%, rgba(125, 177, 197, 0.15), transparent 28rem),
790 linear-gradient(180deg, #ffffff 0%, var(--ocean-mist) 100%);
791 }
792
793 .portal-current {
794 position: absolute;
795 inset: 0;
796 opacity: 0.22;
797 pointer-events: none;
798 background-image: repeating-radial-gradient(
799 ellipse 82% 44% at 24% -22%,
800 transparent 0,
801 transparent 2.7rem,
802 rgba(104, 143, 157, 0.18) 2.76rem,
803 transparent 2.83rem
804 );
805 mask-image: linear-gradient(to bottom, transparent, black 24%, black 72%, transparent);
806 }
807
808 .portal-hero-grid {
809 position: relative;
810 display: grid;
811 grid-template-columns: minmax(0, 1.12fr) minmax(20rem, 0.88fr);
812 gap: clamp(2.5rem, 6vw, 5rem);
813 align-items: center;
814 padding-block: clamp(3.25rem, 6vw, 4.75rem);
815 }
816
817 .portal-hero-copy {
818 max-width: 42rem;
819 }
820
821 .portal-mark {
822 display: flex;
823 align-items: center;
824 gap: 0.7rem;
825 margin-bottom: 1.25rem;
826 color: var(--ink-mute);
827 font-size: 0.76rem;
828 font-weight: 600;
829 }
830
831 .portal-mark svg {
832 color: var(--signal-gold);
833 }
834
835 .portal-hero h1 {
836 max-width: 41rem;
837 font-size: clamp(2.4rem, 5vw, 3.7rem);
838 line-height: 1.01;
839 }
840
841 .portal-lede {
842 max-width: 40rem;
843 margin-top: 1.35rem;
844 color: var(--ink-soft);
845 font-size: clamp(1rem, 1.7vw, 1.18rem);
846 line-height: 1.7;
847 }
848
849 .portal-actions {
850 display: flex;
851 flex-wrap: wrap;
852 gap: 0.7rem;
853 margin-top: 1.7rem;
854 }
855
856 .portal-button {
857 display: inline-flex;
858 min-height: 2.75rem;
859 align-items: center;
860 justify-content: center;
861 padding: 0.65rem 1rem;
862 border: 1px solid transparent;
863 border-radius: 5px;
864 font-size: 0.82rem;
865 font-weight: 600;
866 transition: background-color 150ms ease, border-color 150ms ease, color 150ms ease;
867 }
868
869 .portal-button-primary {
870 border-color: var(--indigo-deep);
871 background: var(--indigo-deep);
872 color: #fff;
873 }
874
875 .portal-button-primary:hover {
876 background: var(--ocean-deep);
877 }
878
879 .portal-button-secondary {
880 border-color: var(--paper-line-soft);
881 background: rgba(255, 255, 255, 0.72);
882 color: var(--ink);
883 }
884
885 .portal-button-secondary:hover {
886 border-color: var(--ink-soft);
887 background: #fff;
888 }
889
890 .portal-meta {
891 max-width: 38rem;
892 margin-top: 0.9rem;
893 color: var(--ink-mute);
894 font-size: 0.76rem;
895 line-height: 1.55;
896 }
897
898 .portal-quickstart {
899 padding: clamp(1.35rem, 3vw, 2rem);
900 border: 1px solid rgba(209, 235, 244, 0.22);
901 border-radius: 8px;
902 background: var(--ocean-deep);
903 box-shadow: 0 1.25rem 3rem rgba(5, 12, 24, 0.16);
904 color: var(--stage-soft);
905 }
906
907 .portal-quickstart > span {
908 color: var(--stage-muted);
909 font-family: var(--font-mono), "JetBrains Mono", monospace;
910 font-size: 0.65rem;
911 letter-spacing: 0.1em;
912 text-transform: uppercase;
913 }
914
915 .portal-quickstart h2 {
916 margin-top: 0.65rem;
917 color: var(--stage-text);
918 font-size: clamp(1.2rem, 2vw, 1.55rem);
919 letter-spacing: -0.02em;
920 }
921
922 .portal-quickstart p {
923 margin-top: 0.7rem;
924 color: rgb(var(--c-stage-soft) / 0.7);
925 font-size: 0.84rem;
926 line-height: 1.65;
927 }
928
929 .portal-quickstart pre.code-block {
930 margin-top: 1.15rem;
931 border-color: rgba(209, 235, 244, 0.2);
932 background: rgba(2, 8, 18, 0.6);
933 }
934
935 .portal-quickstart > a {
936 display: inline-block;
937 margin-top: 1rem;
938 color: var(--ocean-current);
939 font-size: 0.76rem;
940 }
941
942 .portal-quickstart > a:hover {
943 text-decoration: underline;
944 text-underline-offset: 0.25rem;
945 }
946
947 .portal-section {
948 padding-block: clamp(3.25rem, 6vw, 4.75rem);
949 border-bottom: 1px solid var(--hairline);
950 }
951
952 .portal-section-muted {
953 background: var(--paper-deep);
954 }
955
956 .portal-section-grid {
957 display: grid;
958 grid-template-columns: minmax(14rem, 0.62fr) minmax(0, 1.38fr);
959 gap: clamp(2.5rem, 7vw, 6.5rem);
960 }
961
962 .portal-section-copy > span,
963 .portal-docs-heading span,
964 .portal-community-grid > div:first-child > span {
965 color: var(--ink-mute);
966 font-size: 0.72rem;
967 font-weight: 600;
968 }
969
970 .portal-section-copy h2,
971 .portal-docs-heading h2,
972 .portal-community h2 {
973 margin-top: 0.65rem;
974 font-size: clamp(1.55rem, 3vw, 2.4rem);
975 }
976
977 .portal-section-copy p {
978 margin-top: 0.9rem;
979 color: var(--ink-soft);
980 font-size: 0.92rem;
981 line-height: 1.7;
982 }
983
984 .portal-topic-list {
985 border-top: 1px solid var(--hairline);
986 }
987
988 .portal-topic-list > a {
989 display: grid;
990 grid-template-columns: minmax(8rem, 0.42fr) minmax(0, 1fr) auto;
991 gap: 1.25rem;
992 align-items: start;
993 padding-block: 1.15rem;
994 border-bottom: 1px solid var(--hairline);
995 transition: background-color 150ms ease, color 150ms ease;
996 }
997
998 .portal-topic-list > a:hover {
999 color: var(--indigo-deep);
1000 background: rgba(255, 255, 255, 0.52);
1001 }
1002
1003 .portal-topic-list strong {
1004 font-size: 0.9rem;
1005 font-weight: 600;
1006 }
1007
1008 .portal-topic-list span {
1009 color: var(--ink-soft);
1010 font-size: 0.84rem;
1011 line-height: 1.55;
1012 }
1013
1014 .portal-topic-list span:last-child {
1015 color: var(--ink-mute);
1016 }
1017
1018 .portal-docs-heading {
1019 display: flex;
1020 align-items: end;
1021 justify-content: space-between;
1022 gap: 2rem;
1023 margin-bottom: 2rem;
1024 }
1025
1026 .portal-docs-heading a {
1027 flex: none;
1028 color: var(--indigo-deep);
1029 font-size: 0.78rem;
1030 }
1031
1032 .portal-docs-heading a:hover,
1033 .portal-community-links a:hover {
1034 text-decoration: underline;
1035 text-underline-offset: 0.25rem;
1036 }
1037
1038 .portal-doc-groups {
1039 display: grid;
1040 grid-template-columns: repeat(2, minmax(0, 1fr));
1041 gap: clamp(2.5rem, 6vw, 5rem);
1042 }
1043
1044 .portal-doc-groups h3 {
1045 font-size: 1.05rem;
1046 letter-spacing: -0.01em;
1047 }
1048
1049 .portal-doc-groups section > p {
1050 min-height: 4.5rem;
1051 margin-top: 0.55rem;
1052 color: var(--ink-soft);
1053 font-size: 0.84rem;
1054 line-height: 1.6;
1055 }
1056
1057 .portal-doc-groups .portal-topic-list {
1058 margin-top: 1.25rem;
1059 }
1060
1061 .portal-doc-groups .portal-topic-list > a {
1062 grid-template-columns: minmax(7rem, 0.42fr) minmax(0, 1fr) auto;
1063 gap: 0.9rem;
1064 }
1065
1066 .portal-community {
1067 padding-block: clamp(3.25rem, 6vw, 4.75rem);
1068 background:
1069 radial-gradient(circle at 84% -30%, rgba(111, 183, 204, 0.14), transparent 30rem),
1070 var(--ocean-deep);
1071 color: var(--stage-soft);
1072 }
1073
1074 .portal-community-grid {
1075 display: grid;
1076 grid-template-columns: minmax(16rem, 0.85fr) minmax(0, 1.15fr);
1077 gap: clamp(2.5rem, 7vw, 7rem);
1078 }
1079
1080 .portal-community-grid > div:first-child > span {
1081 color: var(--stage-muted);
1082 }
1083
1084 .portal-community h2 {
1085 color: var(--stage-text);
1086 }
1087
1088 .portal-community p {
1089 color: rgb(var(--c-stage-soft) / 0.76);
1090 font-size: 0.96rem;
1091 line-height: 1.75;
1092 }
1093
1094 .portal-community-links {
1095 display: grid;
1096 grid-template-columns: repeat(2, minmax(0, 1fr));
1097 gap: 0.8rem 1.5rem;
1098 margin-top: 1.5rem;
1099 padding-top: 1.25rem;
1100 border-top: 1px solid rgba(209, 235, 244, 0.18);
1101 }
1102
1103 .portal-community-links a {
1104 color: var(--ocean-current);
1105 font-size: 0.78rem;
1106 }
1107
1108 .contribute-path-grid {
1109 display: grid;
1110 grid-template-columns: repeat(2, minmax(0, 1fr));
1111 border-top: 1px solid var(--hairline);
1112 }
1113
1114 .contribute-path-grid article {
1115 padding: 1.5rem 1.5rem 1.5rem 0;
1116 border-bottom: 1px solid var(--hairline);
1117 }
1118
1119 .contribute-path-grid article:nth-child(even) {
1120 padding-inline: 1.5rem 0;
1121 border-left: 1px solid var(--hairline);
1122 }
1123
1124 .contribute-path-grid h3 {
1125 font-size: 1rem;
1126 letter-spacing: -0.01em;
1127 }
1128
1129 .contribute-path-grid p {
1130 margin-top: 0.55rem;
1131 color: var(--ink-soft);
1132 font-size: 0.84rem;
1133 line-height: 1.65;
1134 }
1135
1136 .contribute-path-grid a,
1137 .contribute-steps a {
1138 display: inline-block;
1139 margin-top: 0.9rem;
1140 color: var(--indigo-deep);
1141 font-size: 0.74rem;
1142 font-weight: 600;
1143 }
1144
1145 .contribute-path-grid a:hover,
1146 .contribute-steps a:hover {
1147 text-decoration: underline;
1148 text-underline-offset: 0.22rem;
1149 }
1150
1151 .contribute-steps {
1152 display: grid;
1153 grid-template-columns: repeat(2, minmax(0, 1fr));
1154 border-top: 1px solid var(--hairline);
1155 }
1156
1157 .contribute-steps li {
1158 display: grid;
1159 grid-template-columns: 2.25rem minmax(0, 1fr);
1160 gap: 1rem;
1161 padding: 1.5rem 1.5rem 1.5rem 0;
1162 border-bottom: 1px solid var(--hairline);
1163 }
1164
1165 .contribute-steps li:nth-child(even) {
1166 padding-inline: 1.5rem 0;
1167 border-left: 1px solid var(--hairline);
1168 }
1169
1170 .contribute-steps li > span {
1171 color: var(--indigo-deep);
1172 font-family: var(--font-mono), "JetBrains Mono", monospace;
1173 font-size: 0.68rem;
1174 }
1175
1176 .contribute-steps h3 {
1177 font-size: 1rem;
1178 letter-spacing: -0.01em;
1179 }
1180
1181 .contribute-steps p {
1182 margin-top: 0.5rem;
1183 color: var(--ink-soft);
1184 font-size: 0.82rem;
1185 line-height: 1.65;
1186 }
1187
1188 .contribute-review-list {
1189 border-top: 1px solid var(--hairline);
1190 }
1191
1192 .contribute-review-list li {
1193 padding-block: 1rem;
1194 border-bottom: 1px solid var(--hairline);
1195 color: var(--ink-soft);
1196 font-size: 0.84rem;
1197 line-height: 1.6;
1198 }
1199
1200 .contribute-dev-loop {
1201 padding-block: clamp(3.25rem, 6vw, 4.75rem);
1202 background: var(--ocean-deep);
1203 }
1204
1205 .contribute-dev-loop .portal-section-copy > span {
1206 color: var(--stage-muted);
1207 }
1208
1209 .contribute-dev-loop .portal-section-copy h2 {
1210 color: var(--stage-text);
1211 }
1212
1213 .contribute-dev-loop .portal-section-copy p {
1214 color: rgb(var(--c-stage-soft) / 0.76);
1215 }
1216
1217 .contribute-dev-loop pre.code-block {
1218 border-color: rgba(209, 235, 244, 0.2);
1219 background: rgba(2, 8, 18, 0.62);
1220 }
1221
1222 @media (max-width: 900px) {
1223 .portal-hero-grid,
1224 .portal-section-grid,
1225 .portal-community-grid {
1226 grid-template-columns: 1fr;
1227 }
1228
1229 .portal-hero-copy {
1230 max-width: 48rem;
1231 }
1232
1233 .portal-quickstart {
1234 max-width: 42rem;
1235 }
1236 }
1237
1238 @media (max-width: 760px) {
1239 .portal-container {
1240 width: min(100% - 2rem, 72rem);
1241 }
1242
1243 .portal-doc-groups {
1244 grid-template-columns: 1fr;
1245 }
1246
1247 .portal-doc-groups section > p {
1248 min-height: 0;
1249 }
1250
1251 .contribute-path-grid,
1252 .contribute-steps {
1253 grid-template-columns: 1fr;
1254 }
1255
1256 .contribute-path-grid article,
1257 .contribute-path-grid article:nth-child(even),
1258 .contribute-steps li,
1259 .contribute-steps li:nth-child(even) {
1260 padding-inline: 0;
1261 border-left: 0;
1262 }
1263 }
1264
1265 @media (max-width: 560px) {
1266 .portal-hero-grid {
1267 gap: 2.25rem;
1268 padding-block: 2.75rem;
1269 }
1270
1271 .portal-actions,
1272 .portal-docs-heading {
1273 align-items: stretch;
1274 flex-direction: column;
1275 }
1276
1277 .portal-button {
1278 width: 100%;
1279 }
1280
1281 .portal-topic-list > a,
1282 .portal-doc-groups .portal-topic-list > a {
1283 grid-template-columns: 1fr auto;
1284 gap: 0.45rem 1rem;
1285 }
1286
1287 .portal-topic-list > a span:nth-child(2) {
1288 grid-column: 1 / -1;
1289 }
1290
1291 .portal-topic-list > a span:last-child {
1292 grid-column: 2;
1293 grid-row: 1;
1294 }
1295
1296 .portal-community-links {
1297 grid-template-columns: 1fr;
1298 }
1299 }
1300
1301 /* ------------------------------------------------------------------ */
1302 /* Product home — newspaper baseline + ocean terminal accents */
1303 /* (issue #4934: restore crisp editorial sheet; fit underwater to it) */
1304 /* ------------------------------------------------------------------ */
1305
1306 .product-home {
1307 background: var(--paper);
1308 color: var(--ink);
1309 }
1310
1311 .product-container {
1312 width: min(100% - 2.5rem, 76rem);
1313 margin-inline: auto;
1314 }
1315
1316 .product-hero,
1317 .paper-hero {
1318 position: relative;
1319 overflow: hidden;
1320 border-bottom: 1px solid var(--hairline);
1321 background:
1322 linear-gradient(180deg, rgba(232, 238, 248, 0.55) 0%, transparent 42%),
1323 var(--paper);
1324 color: var(--ink);
1325 }
1326
1327 .product-hero-brandline {
1328 display: flex;
1329 align-items: center;
1330 gap: 0.65rem;
1331 margin-bottom: 1.35rem;
1332 color: var(--ink);
1333 font-size: 0.78rem;
1334 font-weight: 600;
1335 }
1336
1337 .product-hero-brandline em {
1338 margin-left: 0.25rem;
1339 padding: 0.2rem 0.48rem;
1340 border: 1px solid var(--hairline);
1341 border-radius: 4px;
1342 color: var(--ink-mute);
1343 font-family: var(--font-mono), "JetBrains Mono", monospace;
1344 font-size: 0.62rem;
1345 font-style: normal;
1346 font-weight: 500;
1347 letter-spacing: 0.08em;
1348 text-transform: uppercase;
1349 }
1350
1351 .product-kicker {
1352 margin: 0 0 0.85rem;
1353 color: var(--ink-mute);
1354 font-family: var(--font-mono), "JetBrains Mono", ui-monospace, monospace;
1355 font-size: 0.72rem;
1356 font-weight: 500;
1357 letter-spacing: 0.14em;
1358 text-transform: uppercase;
1359 }
1360
1361 .product-hero-grid,
1362 .paper-hero-grid {
1363 position: relative;
1364 display: grid;
1365 grid-template-columns: minmax(22rem, 1fr) minmax(22rem, 1fr);
1366 gap: clamp(1.75rem, 3.5vw, 3.5rem);
1367 align-items: start;
1368 min-height: 0;
1369 padding-block: clamp(2.5rem, 5vw, 4.25rem);
1370 }
1371
1372 .product-hero-copy h1,
1373 .paper-hero-copy h1 {
1374 color: var(--ink);
1375 max-width: 38rem;
1376 font-size: clamp(2.35rem, 4.6vw, 4.15rem);
1377 line-height: 1.02;
1378 letter-spacing: -0.035em;
1379 }
1380
1381 .product-hero-copy,
1382 .product-install {
1383 min-width: 0;
1384 }
1385
1386 .product-hero-copy h1 span,
1387 .paper-hero-accent {
1388 color: var(--indigo);
1389 }
1390
1391 .paper-hero-lede,
1392 .product-hero-copy > p {
1393 max-width: 38rem;
1394 margin-top: 1.35rem;
1395 color: var(--ink-soft);
1396 font-size: clamp(1rem, 1.5vw, 1.12rem);
1397 line-height: 1.72;
1398 }
1399
1400 .product-actions,
1401 .paper-actions {
1402 display: flex;
1403 flex-wrap: wrap;
1404 gap: 0.75rem;
1405 margin-top: 1.55rem;
1406 }
1407
1408 .product-button {
1409 display: inline-flex;
1410 min-width: 6.4rem;
1411 min-height: 2.75rem;
1412 align-items: center;
1413 justify-content: center;
1414 padding: 0.65rem 1rem;
1415 border: 1px solid var(--ink);
1416 border-radius: 2px;
1417 color: var(--ink);
1418 font-family: var(--font-mono), "JetBrains Mono", monospace;
1419 font-size: 0.74rem;
1420 font-weight: 600;
1421 letter-spacing: 0.08em;
1422 text-transform: uppercase;
1423 transition: border-color 150ms ease, background-color 150ms ease, color 150ms ease;
1424 }
1425
1426 .product-button:hover {
1427 border-color: var(--indigo);
1428 background: var(--indigo-pale);
1429 color: var(--indigo-deep);
1430 }
1431
1432 .product-button-primary {
1433 border-color: var(--ink);
1434 background: var(--ink);
1435 color: var(--paper);
1436 }
1437
1438 .product-button-primary:hover {
1439 border-color: var(--indigo);
1440 background: var(--indigo);
1441 color: var(--paper);
1442 }
1443
1444 .product-button-ghost {
1445 border-color: transparent;
1446 color: var(--ink-mute);
1447 }
1448
1449 .product-button-ghost:hover {
1450 border-color: transparent;
1451 background: transparent;
1452 color: var(--indigo);
1453 }
1454
1455 .product-install,
1456 .paper-install {
1457 max-width: 32rem;
1458 margin-top: 1.5rem;
1459 }
1460
1461 .product-install pre.code-block,
1462 .paper-install pre.code-block {
1463 border-color: var(--ocean-mid);
1464 background: linear-gradient(180deg, #131d31 0%, #060b16 100%);
1465 color: var(--stage-text);
1466 }
1467
1468 .paper-install-meta {
1469 display: flex;
1470 flex-wrap: wrap;
1471 align-items: center;
1472 justify-content: space-between;
1473 gap: 0.5rem 1rem;
1474 margin-top: 0.55rem;
1475 font-family: var(--font-mono), "JetBrains Mono", monospace;
1476 font-size: 0.68rem;
1477 color: var(--ink-mute);
1478 }
1479
1480 /* The hero status line is the TUI header, typeset on paper: a `cw` chip and
1481 then a dot chain of the facts the binary would report about itself. Spacing
1482 comes from `.dotline`; the separators are CSS punctuation. */
1483 .product-facts,
1484 .paper-facts {
1485 margin-top: 1.1rem;
1486 /* !important because this <p> is also `.product-hero-copy > p`, which sets
1487 the lede's clamp at higher specificity. The status line is not a lede. */
1488 font-size: 0.72rem !important;
1489 color: var(--ink-mute);
1490 line-height: 1.55;
1491 }
1492
1493 .paper-facts .dotline-chip {
1494 padding: 0.08rem 0.36rem;
1495 border-radius: 3px;
1496 background: var(--paper-deep);
1497 color: var(--ink);
1498 font-weight: 600;
1499 }
1500
1501 .paper-facts > *:not(:last-child)::after {
1502 color: var(--ink-mute);
1503 }
1504
1505 /* Ocean terminal frame around the newest session capture */
1506 .product-shot,
1507 .paper-shot {
1508 position: relative;
1509 margin: 0;
1510 overflow: hidden;
1511 border: 1px solid rgba(15, 22, 38, 0.88);
1512 border-radius: 6px;
1513 background: var(--ocean-deep);
1514 box-shadow:
1515 0 0 0 1px rgba(79, 209, 197, 0.08),
1516 0 18px 48px rgba(3, 7, 13, 0.18);
1517 }
1518
1519 .product-shot-toolbar,
1520 .paper-shot-toolbar {
1521 display: flex;
1522 min-height: 2.55rem;
1523 align-items: center;
1524 justify-content: space-between;
1525 gap: 1rem;
1526 padding: 0.5rem 0.8rem;
1527 border-bottom: 1px solid rgba(79, 209, 197, 0.16);
1528 background: linear-gradient(180deg, #131d31 0%, #0a1220 100%);
1529 color: var(--stage-muted);
1530 font-family: var(--font-mono), "JetBrains Mono", monospace;
1531 font-size: 0.64rem;
1532 letter-spacing: 0.06em;
1533 text-transform: uppercase;
1534 }
1535
1536 .product-shot-toolbar > span:first-child {
1537 display: inline-flex;
1538 align-items: center;
1539 gap: 0.5rem;
1540 color: var(--signal-gold);
1541 }
1542
1543 .product-shot img {
1544 display: block;
1545 width: 100%;
1546 height: auto;
1547 background: var(--ocean-deep);
1548 }
1549
1550 .product-shot figcaption {
1551 padding: 0.6rem 0.8rem;
1552 border-top: 1px solid rgba(79, 209, 197, 0.12);
1553 background: #060b16;
1554 color: var(--stage-muted);
1555 font-family: var(--font-mono), "JetBrains Mono", monospace;
1556 font-size: 0.64rem;
1557 text-align: right;
1558 }
1559
1560 /* Paper home keeps light sticky nav (no dark ocean override). */
1561 body:has(.product-home) .site-nav {
1562 border-color: var(--hairline);
1563 background: rgba(244, 247, 251, 0.94);
1564 }
1565
1566 body:has(.product-home) .site-wordmark,
1567 body:has(.product-home) .nav-link,
1568 body:has(.product-home) .site-github-link,
1569 body:has(.product-home) .site-nav-actions button,
1570 body:has(.product-home) .site-nav-actions select {
1571 color: var(--ink);
1572 }
1573
1574 body:has(.product-home) .site-nav-actions button,
1575 body:has(.product-home) .site-nav-actions select,
1576 body:has(.product-home) .site-github-link {
1577 border-color: var(--hairline);
1578 }
1579
1580 /* Constitution trace pane */
1581 .paper-decides {
1582 border-bottom: 1px solid var(--hairline);
1583 background: var(--paper-deep);
1584 padding-block: clamp(2.5rem, 5vw, 4rem);
1585 }
1586
1587 .paper-decides-grid {
1588 display: grid;
1589 grid-template-columns: minmax(14rem, 0.85fr) minmax(20rem, 1.15fr);
1590 gap: clamp(1.5rem, 4vw, 3rem);
1591 align-items: start;
1592 }
1593
1594 .paper-decides-lede {
1595 max-width: 28rem;
1596 color: var(--ink-soft);
1597 font-size: 0.95rem;
1598 line-height: 1.7;
1599 }
1600
1601 .paper-start {
1602 border-bottom: 1px solid var(--hairline);
1603 background: var(--paper);
1604 padding-block: clamp(2.75rem, 5vw, 4.5rem);
1605 }
1606
1607 .paper-start .product-start-lede {
1608 margin-bottom: 1.5rem;
1609 }
1610
1611 /* The one pull-quote on the page: a raised editorial sheet, so it takes the
1612 ivory card value rather than the raw white it used to bypass tokens with. */
1613 .product-proof {
1614 border-bottom: 1px solid var(--hairline);
1615 background: var(--paper-card);
1616 }
1617
1618 .product-proof-grid {
1619 display: grid;
1620 grid-template-columns: minmax(0, 1.15fr) minmax(18rem, 0.85fr);
1621 gap: clamp(2rem, 6vw, 6rem);
1622 align-items: center;
1623 padding-block: clamp(2.7rem, 5vw, 4.5rem);
1624 }
1625
1626 .product-proof h2 {
1627 font-size: clamp(1.8rem, 3.3vw, 3rem);
1628 }
1629
1630 .product-proof p {
1631 padding-left: clamp(1.5rem, 4vw, 3rem);
1632 border-left: 1px solid var(--paper-edge);
1633 color: var(--ink-soft);
1634 line-height: 1.75;
1635 }
1636
1637 /* Workflow is paper. It is four numbered editorial steps that happen to quote
1638 a receipt; making the whole band ocean is what stopped the receipt reading
1639 as evidence. The receipt below stays an ocean plate ON paper. */
1640 .product-workflow {
1641 position: relative;
1642 overflow: hidden;
1643 padding-block: clamp(4rem, 8vw, 7rem);
1644 border-bottom: 1px solid var(--hairline);
1645 background: var(--paper);
1646 }
1647
1648 .product-workflow h2 {
1649 max-width: 54rem;
1650 color: var(--ink);
1651 font-size: clamp(1.8rem, 3.3vw, 3rem);
1652 }
1653
1654 /* Hairline-ruled ivory cards on the cool page — cwc's exact card grammar, and
1655 the only place the warmth the sheet is asking for actually belongs. No
1656 shadow: paper stays flat, and the hairline stays sharp because it is. */
1657 .product-workflow-steps {
1658 display: grid;
1659 grid-template-columns: repeat(4, minmax(0, 1fr));
1660 gap: 1rem;
1661 margin-top: clamp(2.5rem, 5vw, 4.5rem);
1662 }
1663
1664 .product-workflow-steps li {
1665 position: relative;
1666 min-height: 12rem;
1667 padding: 1.35rem 1.5rem 1.5rem;
1668 border: 1px solid var(--hairline);
1669 border-radius: 6px;
1670 background: var(--paper-card);
1671 }
1672
1673 .product-workflow-steps li > span {
1674 color: var(--indigo);
1675 font-family: var(--font-mono), "JetBrains Mono", monospace;
1676 font-size: 0.68rem;
1677 }
1678
1679 .product-workflow-steps h3 {
1680 margin-top: 2.5rem;
1681 color: var(--ink);
1682 font-size: 1.12rem;
1683 }
1684
1685 .product-workflow-steps p {
1686 margin-top: 0.65rem;
1687 color: var(--ink-soft);
1688 font-size: 0.84rem;
1689 line-height: 1.65;
1690 }
1691
1692 .product-receipt {
1693 display: grid;
1694 gap: 0.45rem;
1695 max-width: 58rem;
1696 margin-top: 2.5rem;
1697 padding: 1.35rem 1.5rem;
1698 border: 1px solid var(--stage-line);
1699 background: var(--stage-field-top);
1700 color: var(--stage-soft);
1701 font-family: var(--font-mono), "JetBrains Mono", monospace;
1702 font-size: clamp(0.68rem, 1.2vw, 0.8rem);
1703 line-height: 1.45;
1704 }
1705
1706 .product-receipt span:first-child {
1707 padding-bottom: 0.65rem;
1708 border-bottom: 1px solid var(--stage-line);
1709 color: var(--stage-text);
1710 }
1711
1712 .product-receipt strong {
1713 color: var(--signal-gold);
1714 font-weight: 500;
1715 }
1716
1717 /* ---------- product: start-here band + shared getting-started steps ---------- */
1718
1719 .product-start {
1720 padding-block: clamp(4rem, 8vw, 7rem);
1721 border-bottom: 1px solid var(--hairline);
1722 }
1723
1724 .product-start h2 {
1725 max-width: 54rem;
1726 font-size: clamp(1.8rem, 3.3vw, 3rem);
1727 }
1728
1729 .product-start-lede {
1730 margin-top: 0.9rem;
1731 max-width: 46rem;
1732 color: var(--ink-soft);
1733 line-height: 1.75;
1734 }
1735
1736 .product-start-links {
1737 display: flex;
1738 flex-wrap: wrap;
1739 gap: 1.5rem;
1740 margin-top: 2rem;
1741 }
1742
1743 .product-start-links a {
1744 color: var(--indigo);
1745 font-family: var(--font-mono), "JetBrains Mono", monospace;
1746 font-size: 0.78rem;
1747 }
1748
1749 .product-start-links a:hover {
1750 color: var(--indigo-deep);
1751 }
1752
1753 /* Shared step list rendered by <GettingStartedSteps> (homepage band and the
1754 /docs/guide page). Light tokens; the docs dark theme re-themes it through
1755 the same --hairline/--ink-* vars as the rest of the docs subtree. */
1756 .gs-steps {
1757 display: grid;
1758 grid-template-columns: repeat(4, minmax(0, 1fr));
1759 margin-top: clamp(2rem, 4vw, 3rem);
1760 padding: 0;
1761 border-top: 1px solid var(--hairline);
1762 list-style: none;
1763 }
1764
1765 .gs-steps li {
1766 padding: 1.35rem 1.5rem 1.5rem 0;
1767 border-bottom: 1px solid var(--hairline);
1768 }
1769
1770 .gs-steps li + li {
1771 padding-left: 1.5rem;
1772 border-left: 1px solid var(--hairline);
1773 }
1774
1775 .gs-step-index {
1776 color: var(--indigo);
1777 font-family: var(--font-mono), "JetBrains Mono", monospace;
1778 font-size: 0.68rem;
1779 }
1780
1781 .gs-steps h3 {
1782 margin-top: 1.1rem;
1783 font-size: 1.05rem;
1784 }
1785
1786 .gs-steps p {
1787 margin-top: 0.6rem;
1788 color: var(--ink-soft);
1789 font-size: 0.86rem;
1790 line-height: 1.7;
1791 }
1792
1793 .gs-step-commands {
1794 margin-top: 0.9rem;
1795 font-size: 0.72rem;
1796 }
1797
1798 .gs-step-link {
1799 display: inline-block;
1800 margin-top: 0.9rem;
1801 color: var(--indigo);
1802 font-family: var(--font-mono), "JetBrains Mono", monospace;
1803 font-size: 0.72rem;
1804 }
1805
1806 .gs-step-link:hover {
1807 color: var(--indigo-deep);
1808 }
1809
1810 /* ---------- a11y: skip link ---------- */
1811
1812 .skip-link {
1813 position: absolute;
1814 left: 1rem;
1815 top: -3.5rem;
1816 z-index: 60;
1817 padding: 0.55rem 0.9rem;
1818 background: var(--ink);
1819 color: var(--paper);
1820 font-family: var(--font-mono), "JetBrains Mono", monospace;
1821 font-size: 0.72rem;
1822 }
1823
1824 .skip-link:focus-visible {
1825 top: 0.5rem;
1826 outline: 2px solid var(--indigo);
1827 outline-offset: 2px;
1828 }
1829
1830 /* ---------- honest status badges ---------- */
1831
1832 .status-badge {
1833 display: inline-flex;
1834 align-items: center;
1835 gap: 0.4rem;
1836 padding: 0.2rem 0.55rem;
1837 border: 1px solid var(--hairline);
1838 font-family: var(--font-mono), "JetBrains Mono", monospace;
1839 font-size: 0.62rem;
1840 letter-spacing: 0.08em;
1841 text-transform: uppercase;
1842 color: var(--ink-soft);
1843 }
1844
1845 .status-badge-dot {
1846 width: 0.45rem;
1847 height: 0.45rem;
1848 border-radius: 999px;
1849 }
1850
1851 .status-badge-experimental .status-badge-dot { background: var(--ochre); }
1852 .status-badge-preview .status-badge-dot { background: var(--indigo); }
1853 .status-badge-pending .status-badge-dot { background: var(--ochre); }
1854 .status-badge-unavailable .status-badge-dot { background: var(--ink-mute); }
1855
1856 /* ---------- session media (real-session surface) ---------- */
1857
1858 .session-media {
1859 border: 1px solid var(--hairline);
1860 }
1861
1862 .session-media video {
1863 display: block;
1864 width: 100%;
1865 height: auto;
1866 background: var(--ocean-deep);
1867 }
1868
1869 .session-media-stage {
1870 display: flex;
1871 flex-direction: column;
1872 align-items: flex-start;
1873 gap: 0.9rem;
1874 padding: clamp(1.5rem, 4vw, 2.5rem);
1875 border-bottom: 1px solid var(--hairline);
1876 background: var(--paper-deep);
1877 }
1878
1879 .session-media-pending-note {
1880 max-width: 44rem;
1881 margin: 0;
1882 color: var(--ink-soft);
1883 font-size: 0.88rem;
1884 line-height: 1.7;
1885 }
1886
1887 .session-media-caption {
1888 display: grid;
1889 gap: 0.5rem;
1890 padding: 1rem 1.25rem;
1891 color: var(--ink-soft);
1892 font-size: 0.84rem;
1893 line-height: 1.6;
1894 }
1895
1896 .session-media-caption strong {
1897 color: var(--ink);
1898 font-size: 0.95rem;
1899 }
1900
1901 .session-media-caption a {
1902 color: var(--indigo);
1903 font-family: var(--font-mono), "JetBrains Mono", monospace;
1904 font-size: 0.72rem;
1905 }
1906
1907 .session-media-caption a:hover {
1908 color: var(--indigo-deep);
1909 }
1910
1911 /* Last band above the waterline. It ends with no rule: a hairline here would be
1912 an editorial rule trespassing into water. The transition is the transition. */
1913 .product-boundaries {
1914 padding-block: clamp(4rem, 8vw, 7rem);
1915 background: var(--paper);
1916 }
1917
1918 .product-boundaries-grid {
1919 display: grid;
1920 grid-template-columns: minmax(16rem, 0.8fr) minmax(0, 1.2fr);
1921 gap: clamp(3rem, 8vw, 8rem);
1922 }
1923
1924 .product-boundaries h2 {
1925 font-size: clamp(2.5rem, 5vw, 4.7rem);
1926 }
1927
1928 .product-boundaries h2 span {
1929 color: var(--indigo);
1930 }
1931
1932 .product-boundaries-grid > div > p {
1933 max-width: 31rem;
1934 margin-top: 1.25rem;
1935 color: var(--ink-soft);
1936 line-height: 1.75;
1937 }
1938
1939 .product-boundary-list {
1940 display: grid;
1941 gap: 0.75rem;
1942 }
1943
1944 .product-boundary-list > div {
1945 display: grid;
1946 grid-template-columns: minmax(12rem, 0.85fr) minmax(0, 1.15fr);
1947 align-items: baseline;
1948 gap: 1.5rem;
1949 padding: 1.25rem 1.4rem;
1950 border: 1px solid var(--hairline);
1951 border-radius: 6px;
1952 background: var(--paper-card);
1953 }
1954
1955 .product-boundary-list dt {
1956 font-weight: 700;
1957 }
1958
1959 .product-boundary-list dd {
1960 color: var(--ink-soft);
1961 font-size: 0.88rem;
1962 }
1963
1964 /* ---------- the waterline ---------- */
1965 /* */
1966 /* Paper is the editorial voice ABOUT the machine. Ocean is the machine */
1967 /* speaking in its own voice. The page dives exactly once, between */
1968 /* Boundaries and Surfaces — where it stops describing and starts handing */
1969 /* over — and never comes back up. */
1970 /* */
1971 /* One column, one gradient, sampled by absolute page position across the */
1972 /* three bands it wraps. The footer's --ocean-deep is the same value as the */
1973 /* column's deep stop, so the seabed continues without a seam and */
1974 /* `.site-footer` needs no change. There is no rule at the waterline. */
1975 /* -------------------------------------------------------------------------- */
1976 .ocean-column {
1977 position: relative;
1978 isolation: isolate;
1979 background:
1980 radial-gradient(120% 60% at 50% 0%, rgba(38, 72, 102, 0.35), transparent),
1981 linear-gradient(
1982 180deg,
1983 var(--stage-field-top) 0%,
1984 var(--stage-field-mid) 42%,
1985 var(--stage-field-deep) 100%
1986 );
1987 }
1988
1989 /* Bands inside the column carry no field of their own. */
1990 .ocean-column > section {
1991 position: relative;
1992 background: transparent;
1993 }
1994
1995 /* One line weight below the waterline. The ink hairline is invisible on the
1996 field, and the three ad-hoc action-blue alphas it replaced were three
1997 different answers to a question the product settled once. */
1998 .ocean-column .hairline,
1999 .ocean-column .hairline-t,
2000 .ocean-column .hairline-b,
2001 .ocean-column .hairline-l {
2002 border-color: var(--stage-line);
2003 }
2004
2005 /* Below the waterline, hierarchy comes the TUI way — colour weight and ` · `
2006 chains, not scale. A 4rem high-contrast serif on deep field was the loudest
2007 object on the page and the least like either product. */
2008 .ocean-column h2 {
2009 max-width: 54rem;
2010 color: var(--stage-text);
2011 font-size: clamp(1.6rem, 2.6vw, 2.4rem);
2012 font-weight: 600;
2013 letter-spacing: -0.025em;
2014 line-height: 1.12;
2015 }
2016
2017 /* Tight tracking flatters Fraunces and collides Han; Noto Serif SC also wants
2018 the extra leading at this optical size. Extend the existing zh overrides
2019 rather than routing around them. */
2020 html[lang="zh"] .ocean-column h2,
2021 html[lang="ja"] .ocean-column h2,
2022 html[lang="ko"] .ocean-column h2 {
2023 letter-spacing: 0;
2024 line-height: 1.5;
2025 }
2026
2027 .product-surfaces {
2028 padding-block: clamp(4rem, 8vw, 7rem);
2029 }
2030
2031 .product-surface-list {
2032 margin-top: 2.5rem;
2033 border-top: 1px solid var(--stage-line);
2034 }
2035
2036 .product-surface-list > div {
2037 display: grid;
2038 grid-template-columns: minmax(13rem, 0.7fr) minmax(0, 1.3fr);
2039 gap: 2rem;
2040 padding: 1.2rem 0;
2041 border-bottom: 1px solid var(--stage-line);
2042 }
2043
2044 .product-surface-list strong {
2045 color: var(--stage-text);
2046 font-family: var(--font-mono), "JetBrains Mono", monospace;
2047 font-size: 1rem;
2048 }
2049
2050 .product-surface-list span {
2051 color: var(--stage-soft);
2052 }
2053
2054 .product-surfaces > .product-container > a {
2055 display: inline-block;
2056 margin-top: 1.5rem;
2057 color: var(--action-on-dark);
2058 font-size: 0.82rem;
2059 }
2060
2061 /* The install band is the TUI composer.
2062 *
2063 * It used to be `--indigo-deep` full-bleed: a third register belonging to
2064 * neither system, and the last thing on the page that looked like a generic
2065 * marketing CTA. The composer is a *raised* plate in the product, so this one
2066 * band is opaque over the column rather than transparent through it, bracketed
2067 * above by Signal Gold and below by Operate violet — the product's exact
2068 * composer framing, and the one place gold is legitimate here, because what it
2069 * brackets is the point of human intent.
2070 *
2071 * The descendant selector is deliberate: it has to out-rank
2072 * `.ocean-column > section { background: transparent }`.
2073 */
2074 .ocean-column .product-install-band {
2075 padding-block: clamp(3rem, 6vw, 5rem);
2076 border-top: 1px solid color-mix(in srgb, var(--signal-gold) 40%, transparent);
2077 border-bottom: 1px solid color-mix(in srgb, var(--violet) 40%, transparent);
2078 background: var(--stage-composer);
2079 color: var(--stage-text);
2080 }
2081
2082 .product-install-grid {
2083 display: grid;
2084 grid-template-columns: minmax(15rem, 0.65fr) minmax(0, 1.35fr);
2085 gap: clamp(2rem, 7vw, 7rem);
2086 align-items: start;
2087 }
2088
2089 /* `❯` sits inside the plate, where the TUI puts it — a code-owned literal in
2090 the same class as `Codewhale` and `npm install -g codewhale`. */
2091 .product-composer {
2092 position: relative;
2093 }
2094
2095 .product-composer pre.code-block {
2096 padding-left: 2.6rem;
2097 }
2098
2099 /* The copy control sits on `--paper` and must not inherit the band's ivory. */
2100 .product-composer button {
2101 color: var(--ink);
2102 }
2103
2104 .product-composer-prompt {
2105 position: absolute;
2106 top: 1rem;
2107 left: 1.1rem;
2108 z-index: 1;
2109 color: var(--action-on-dark);
2110 font-family: var(--font-mono), "JetBrains Mono", ui-monospace, monospace;
2111 font-size: 0.78rem;
2112 line-height: 1.55;
2113 pointer-events: none;
2114 }
2115
2116 @media (max-width: 640px) {
2117 .product-composer pre.code-block {
2118 padding-left: 2.3rem;
2119 }
2120
2121 .product-composer-prompt {
2122 top: 0.85rem;
2123 left: 0.95rem;
2124 font-size: 0.76rem;
2125 }
2126 }
2127
2128 .product-install-band pre.code-block {
2129 margin: 0;
2130 border-color: var(--stage-line);
2131 }
2132
2133 .product-install-band .dotline {
2134 margin-top: 1rem;
2135 color: var(--stage-hint);
2136 }
2137
2138 .product-install-band a {
2139 display: inline-block;
2140 margin-top: 1.2rem;
2141 padding-bottom: 0.2rem;
2142 border-bottom: 1px solid var(--stage-line);
2143 color: var(--action-on-dark);
2144 font-size: 0.82rem;
2145 }
2146
2147 .product-community {
2148 padding-block: clamp(3.5rem, 7vw, 6rem);
2149 }
2150
2151 .product-community-grid {
2152 display: grid;
2153 grid-template-columns: minmax(9rem, 0.42fr) minmax(0, 1.08fr) minmax(16rem, 0.75fr);
2154 gap: clamp(2rem, 5vw, 5rem);
2155 align-items: end;
2156 }
2157
2158 .product-community-illustration {
2159 display: grid;
2160 min-height: 10rem;
2161 place-items: center;
2162 }
2163
2164 .product-community-illustration svg {
2165 max-width: 100%;
2166 }
2167
2168 /* The editorial full stop stays, in Ice rather than Signal Gold. Gold's budget
2169 on this page is three marks — the whale, the composer's upper hairline, the
2170 receipt's `report` line — and a decorative period is not one of them. */
2171 .product-community h2::after {
2172 content: ".";
2173 color: var(--ocean-current);
2174 }
2175
2176 .product-community p {
2177 max-width: 42rem;
2178 margin-top: 1rem;
2179 color: var(--stage-soft);
2180 font-size: 1rem;
2181 line-height: 1.75;
2182 }
2183
2184 .product-community nav {
2185 display: grid;
2186 grid-template-columns: repeat(2, minmax(0, 1fr));
2187 gap: 1rem;
2188 padding-top: 1.25rem;
2189 border-top: 1px solid var(--stage-line);
2190 }
2191
2192 .product-community nav a {
2193 color: var(--ocean-current);
2194 font-size: 0.82rem;
2195 font-weight: 600;
2196 }
2197
2198 .product-community nav a:hover {
2199 color: var(--stage-text);
2200 }
2201
2202 .product-home a:focus-visible {
2203 outline: 3px solid var(--signal-gold);
2204 outline-offset: 4px;
2205 }
2206
2207 @media (max-width: 1050px) {
2208 .product-hero-grid,
2209 .paper-hero-grid,
2210 .paper-decides-grid {
2211 grid-template-columns: 1fr;
2212 min-height: auto;
2213 }
2214
2215 .product-hero-copy {
2216 max-width: 48rem;
2217 }
2218
2219 .product-shot {
2220 width: min(100%, 56rem);
2221 }
2222 }
2223
2224 @media (max-width: 760px) {
2225 .product-container {
2226 width: min(100% - 2rem, 76rem);
2227 }
2228
2229 .paper-issue-inner {
2230 width: min(100% - 2rem, 74rem);
2231 }
2232
2233 .paper-wordmark-tag {
2234 max-width: 11rem;
2235 }
2236
2237 .product-proof-grid,
2238 .product-boundaries-grid,
2239 .product-install-grid,
2240 .product-community-grid {
2241 grid-template-columns: 1fr;
2242 }
2243
2244 .product-proof p {
2245 padding-top: 1.5rem;
2246 padding-left: 0;
2247 border-top: 1px solid var(--paper-edge);
2248 border-left: 0;
2249 }
2250
2251 .product-workflow-steps {
2252 grid-template-columns: repeat(2, minmax(0, 1fr));
2253 }
2254
2255 .gs-steps {
2256 grid-template-columns: repeat(2, minmax(0, 1fr));
2257 }
2258
2259 .gs-steps li:nth-child(3) {
2260 padding-left: 0;
2261 border-left: 0;
2262 }
2263
2264 .product-boundary-list > div,
2265 .product-surface-list > div {
2266 grid-template-columns: 1fr;
2267 gap: 0.45rem;
2268 }
2269 }
2270
2271 @media (max-width: 520px) {
2272 .site-nav-inner {
2273 gap: 0.5rem;
2274 }
2275
2276 .site-nav-actions {
2277 min-width: 0;
2278 gap: 0.35rem;
2279 }
2280
2281 .site-nav-actions select {
2282 width: 8rem;
2283 min-width: 0;
2284 }
2285
2286 .product-hero-grid {
2287 padding-block: 2.75rem 3.5rem;
2288 }
2289
2290 .product-hero-copy h1,
2291 .paper-hero-copy h1 {
2292 max-width: 100%;
2293 font-size: clamp(2.15rem, 11vw, 3rem);
2294 }
2295
2296 .paper-install-cta {
2297 display: none;
2298 }
2299
2300 .product-actions {
2301 display: grid;
2302 grid-template-columns: 1fr;
2303 }
2304
2305 .product-workflow-steps {
2306 grid-template-columns: 1fr;
2307 }
2308
2309 .product-workflow-steps li,
2310 .product-workflow-steps li + li,
2311 .product-workflow-steps li:nth-child(3) {
2312 min-height: 0;
2313 padding: 1.25rem 0;
2314 border-left: 0;
2315 }
2316
2317 .gs-steps {
2318 grid-template-columns: 1fr;
2319 }
2320
2321 .gs-steps li,
2322 .gs-steps li + li,
2323 .gs-steps li:nth-child(3) {
2324 padding: 1.25rem 0;
2325 border-left: 0;
2326 }
2327
2328 .product-workflow-steps h3 {
2329 margin-top: 1.25rem;
2330 }
2331
2332 .product-receipt {
2333 overflow-x: auto;
2334 white-space: nowrap;
2335 }
2336
2337 .product-community nav {
2338 grid-template-columns: 1fr;
2339 }
2340 }
2341
2342 /* ------------------------------------------------------------------ */
2343 /* Documentation portal */
2344 /* ------------------------------------------------------------------ */
2345
2346 .docs-portal {
2347 background: var(--paper);
2348 }
2349
2350 .docs-portal-hero,
2351 .community-welcome {
2352 position: relative;
2353 overflow: hidden;
2354 border-bottom: 1px solid var(--hairline);
2355 background:
2356 radial-gradient(circle at 82% 0%, rgba(125, 177, 197, 0.16), transparent 28rem),
2357 linear-gradient(180deg, color-mix(in srgb, var(--paper) 72%, white) 0%, var(--paper-deep) 100%);
2358 }
2359
2360 .docs-portal-hero-inner,
2361 .community-welcome-inner {
2362 position: relative;
2363 padding-block: clamp(2.75rem, 5vw, 4rem);
2364 }
2365
2366 .docs-portal-hero .portal-mark {
2367 margin-bottom: 1rem;
2368 }
2369
2370 .docs-portal-hero h1,
2371 .community-welcome h1 {
2372 max-width: 50rem;
2373 font-size: clamp(2.2rem, 4.8vw, 3.55rem);
2374 line-height: 1.03;
2375 }
2376
2377 .community-welcome h1 {
2378 margin-top: 0.85rem;
2379 }
2380
2381 .docs-portal-hero p,
2382 .community-welcome p {
2383 max-width: 47rem;
2384 margin-top: 1rem;
2385 color: var(--ink-soft);
2386 font-size: 1rem;
2387 line-height: 1.7;
2388 }
2389
2390 .docs-shell {
2391 display: grid;
2392 grid-template-columns: minmax(13rem, 0.28fr) minmax(0, 0.72fr);
2393 grid-template-areas: "sidebar content";
2394 gap: clamp(2rem, 5vw, 4.5rem);
2395 align-items: start;
2396 padding-block: clamp(2.25rem, 5vw, 4rem);
2397 }
2398
2399 .docs-sidebar {
2400 grid-area: sidebar;
2401 border-top: 1px solid var(--hairline);
2402 }
2403
2404 .docs-sidebar-heading {
2405 padding-block: 0.9rem;
2406 border-bottom: 1px solid var(--hairline);
2407 color: var(--ink);
2408 font-size: 0.82rem;
2409 font-weight: 600;
2410 }
2411
2412 .docs-sidebar-heading a {
2413 display: flex;
2414 align-items: center;
2415 justify-content: space-between;
2416 gap: 1rem;
2417 }
2418
2419 .docs-sidebar-heading a > span:last-child {
2420 color: var(--ink-mute);
2421 font-size: 0.72rem;
2422 }
2423
2424 .docs-sidebar-group {
2425 padding-block: 0.9rem;
2426 border-bottom: 1px solid var(--hairline);
2427 }
2428
2429 .docs-sidebar-category {
2430 margin-bottom: 0.35rem;
2431 color: var(--ink-mute);
2432 font-size: 0.64rem;
2433 font-weight: 600;
2434 letter-spacing: 0.08em;
2435 text-transform: uppercase;
2436 }
2437
2438 .docs-sidebar-link {
2439 display: flex;
2440 align-items: center;
2441 justify-content: space-between;
2442 gap: 0.8rem;
2443 padding-block: 0.32rem;
2444 color: var(--ink-soft);
2445 font-size: 0.8rem;
2446 line-height: 1.4;
2447 transition: color 150ms ease;
2448 }
2449
2450 .docs-sidebar-link:hover,
2451 .docs-sidebar-link-current {
2452 color: var(--docs-accent);
2453 }
2454
2455 .docs-sidebar-link-current {
2456 font-weight: 600;
2457 }
2458
2459 .docs-sidebar-link > span:last-child:not(:first-child) {
2460 color: var(--ink-mute);
2461 font-size: 0.68rem;
2462 }
2463
2464 .docs-content {
2465 grid-area: content;
2466 width: 100%;
2467 max-width: 52rem;
2468 }
2469
2470 .docs-search-block {
2471 margin-bottom: 2.25rem;
2472 }
2473
2474 .docs-search-label {
2475 display: block;
2476 margin-bottom: 0.55rem;
2477 color: var(--ink-mute);
2478 font-size: 0.72rem;
2479 font-weight: 600;
2480 }
2481
2482 .docs-search-input {
2483 min-height: 3rem;
2484 padding-right: 3rem;
2485 border-color: var(--paper-line-soft);
2486 border-radius: 5px;
2487 background: color-mix(in srgb, var(--paper) 88%, transparent);
2488 }
2489
2490 .docs-search-clear {
2491 position: absolute;
2492 right: 0.9rem;
2493 top: 50%;
2494 translate: 0 -50%;
2495 color: var(--ink-mute);
2496 font-size: 0.82rem;
2497 }
2498
2499 .docs-search-clear:hover {
2500 color: var(--ink);
2501 }
2502
2503 .docs-search-count {
2504 margin-top: 0.55rem;
2505 color: var(--ink-mute);
2506 font-size: 0.72rem;
2507 }
2508
2509 .docs-result-groups {
2510 display: grid;
2511 gap: 2.5rem;
2512 }
2513
2514 .docs-result-heading {
2515 display: flex;
2516 align-items: baseline;
2517 justify-content: space-between;
2518 gap: 1rem;
2519 margin-bottom: 0.55rem;
2520 }
2521
2522 .docs-result-heading h2 {
2523 font-size: 1.28rem;
2524 letter-spacing: -0.02em;
2525 }
2526
2527 .docs-result-heading > span {
2528 color: var(--ink-mute);
2529 font-size: 0.7rem;
2530 }
2531
2532 .docs-topic-list {
2533 border-top: 1px solid var(--hairline);
2534 }
2535
2536 .docs-topic-row {
2537 display: grid;
2538 grid-template-columns: minmax(0, 1fr) minmax(8rem, 0.34fr) auto;
2539 gap: 1.25rem;
2540 align-items: center;
2541 padding-block: 1rem;
2542 border-bottom: 1px solid var(--hairline);
2543 transition: background-color 150ms ease, color 150ms ease;
2544 }
2545
2546 .docs-topic-row:hover {
2547 color: var(--docs-accent);
2548 background: color-mix(in srgb, var(--paper-deep) 68%, transparent);
2549 }
2550
2551 .docs-topic-title {
2552 display: flex;
2553 flex-wrap: wrap;
2554 gap: 0.5rem;
2555 align-items: baseline;
2556 color: var(--ink);
2557 font-size: 0.9rem;
2558 font-weight: 600;
2559 }
2560
2561 .docs-topic-title > span:last-child {
2562 color: var(--ink-mute);
2563 font-size: 0.6rem;
2564 font-weight: 500;
2565 letter-spacing: 0.06em;
2566 text-transform: uppercase;
2567 }
2568
2569 .docs-topic-main p {
2570 margin-top: 0.28rem;
2571 color: var(--ink-soft);
2572 font-size: 0.78rem;
2573 line-height: 1.55;
2574 }
2575
2576 .docs-topic-source {
2577 overflow: hidden;
2578 color: var(--ink-mute);
2579 font-family: var(--font-mono), "JetBrains Mono", monospace;
2580 font-size: 0.62rem;
2581 line-height: 1.5;
2582 text-overflow: ellipsis;
2583 }
2584
2585 .docs-topic-arrow {
2586 color: var(--ink-mute);
2587 font-size: 0.78rem;
2588 }
2589
2590 .docs-empty {
2591 padding-block: 3.5rem;
2592 border-block: 1px solid var(--hairline);
2593 text-align: center;
2594 }
2595
2596 .docs-empty > p:first-child {
2597 color: var(--ink);
2598 font-size: 1rem;
2599 font-weight: 600;
2600 }
2601
2602 .docs-empty > p:nth-child(2) {
2603 margin: 0.5rem auto 1.25rem;
2604 color: var(--ink-mute);
2605 font-size: 0.8rem;
2606 }
2607
2608 .docs-source-note {
2609 margin-top: 2.5rem;
2610 padding-top: 1.25rem;
2611 border-top: 1px solid var(--hairline);
2612 }
2613
2614 .docs-source-note p {
2615 max-width: 42rem;
2616 color: var(--ink-mute);
2617 font-size: 0.74rem;
2618 line-height: 1.6;
2619 }
2620
2621 @media (max-width: 900px) {
2622 .docs-shell {
2623 grid-template-columns: 1fr;
2624 grid-template-areas:
2625 "content"
2626 "sidebar";
2627 }
2628
2629 .docs-sidebar nav { display: none; }
2630 }
2631
2632 @media (max-width: 640px) {
2633 .docs-topic-row {
2634 grid-template-columns: minmax(0, 1fr) auto;
2635 gap: 0.6rem 1rem;
2636 }
2637
2638 .docs-topic-source {
2639 grid-column: 1 / -1;
2640 grid-row: 2;
2641 }
2642
2643 .docs-topic-arrow {
2644 grid-column: 2;
2645 grid-row: 1;
2646 }
2647 }
2648
2649 /* ---------- community release record ---------- */
2650 .community-credit-section {
2651 border-bottom: 0;
2652 }
2653
2654 .community-record-links {
2655 display: flex;
2656 flex-wrap: wrap;
2657 gap: 0.65rem 1.25rem;
2658 margin-top: 1.25rem;
2659 }
2660
2661 .community-record-links a {
2662 color: var(--indigo-deep);
2663 font-size: 0.75rem;
2664 font-weight: 600;
2665 }
2666
2667 .community-record-links a:hover {
2668 text-decoration: underline;
2669 text-underline-offset: 0.22rem;
2670 }
2671
2672 .community-credit-groups {
2673 display: grid;
2674 gap: 2rem;
2675 }
2676
2677 .community-credit-groups section {
2678 padding-top: 1rem;
2679 border-top: 1px solid var(--hairline);
2680 }
2681
2682 .community-credit-groups h3 {
2683 margin-bottom: 0.9rem;
2684 color: var(--ink-mute);
2685 font-size: 0.7rem;
2686 font-weight: 600;
2687 letter-spacing: 0.04em;
2688 text-transform: uppercase;
2689 }
2690
2691 .community-credit-list {
2692 display: flex;
2693 flex-wrap: wrap;
2694 gap: 0.45rem;
2695 }
2696
2697 .community-credit-list a {
2698 padding: 0.3rem 0.45rem;
2699 border: 1px solid var(--hairline);
2700 color: var(--ink-soft);
2701 font-family: var(--font-mono), "JetBrains Mono", monospace;
2702 font-size: 0.68rem;
2703 }
2704
2705 .community-credit-list a:hover {
2706 border-color: var(--indigo);
2707 color: var(--indigo-deep);
2708 }
2709
2710 /* ------------------------------------------------------------------ */
2711 /* Dark mode — scoped to the /docs routes */
2712 /* */
2713 /* A full site-wide inversion is unsafe here: several marketing */
2714 /* surfaces are intentionally dark (`bg-ink text-paper` — the hero */
2715 /* closer, the terminal player, the LIVE ticker badge) and would */
2716 /* invert into light blocks. The reference-site minimum is dark */
2717 /* docs, so the dark token overrides are set ON the `.docs-theme` */
2718 /* wrapper only. Because the Tailwind surface/ink utilities resolve */
2719 /* through these vars, everything inside the docs subtree re-themes */
2720 /* while the rest of the site (and the shared nav/footer) stays */
2721 /* light. Default follows prefers-color-scheme; an explicit */
2722 /* data-theme on <html> wins. */
2723 /* ------------------------------------------------------------------ */
2724
2725 .docs-theme {
2726 --docs-accent: #315fd8;
2727 --docs-button-bg: #fff;
2728 --docs-button-border: #aeb8c6;
2729 --docs-button-text: #1b2230;
2730 background: var(--paper);
2731 color: var(--ink);
2732 }
2733
2734 .docs-theme .portal-button-secondary {
2735 border-color: var(--docs-button-border);
2736 background: var(--docs-button-bg);
2737 color: var(--docs-button-text);
2738 }
2739
2740 .docs-theme .portal-button-secondary:hover {
2741 border-color: var(--docs-accent);
2742 background: var(--docs-button-bg);
2743 color: var(--docs-accent);
2744 }
2745
2746 .docs-theme .portal-button-secondary:focus-visible,
2747 .docs-sidebar-link:focus-visible {
2748 outline: 2px solid var(--docs-accent);
2749 outline-offset: 2px;
2750 }
2751
2752 @media (prefers-color-scheme: dark) {
2753 html:not([data-theme="light"]) .docs-theme {
2754 color-scheme: dark;
2755 --c-paper: 3 7 13;
2756 --c-paper-deep: 14 23 41;
2757 --c-paper-edge: 38 62 92;
2758 --c-ink: 246 242 232;
2759 --c-ink-soft: 182 192 212;
2760 --c-ink-mute: 147 160 184;
2761 --paper: #03070d;
2762 --paper-deep: #0e1729;
2763 --paper-edge: #263e5c;
2764 --paper-card: #182742;
2765 --ink: #f6f2e8;
2766 --ink-soft: #b6c0d4;
2767 --ink-mute: #93a0b8;
2768 --hairline: rgba(106, 174, 242, 0.22);
2769 --code-bg: #08111c;
2770 --code-fg: #f6f2e8;
2771 --docs-accent: #6aaef2;
2772 --docs-button-bg: #182742;
2773 --docs-button-border: #263e5c;
2774 --docs-button-text: #f6f2e8;
2775 }
2776 }
2777
2778 [data-theme="dark"] .docs-theme {
2779 color-scheme: dark;
2780 --c-paper: 3 7 13;
2781 --c-paper-deep: 14 23 41;
2782 --c-paper-edge: 38 62 92;
2783 --c-ink: 246 242 232;
2784 --c-ink-soft: 182 192 212;
2785 --c-ink-mute: 147 160 184;
2786 --paper: #03070d;
2787 --paper-deep: #0e1729;
2788 --paper-edge: #263e5c;
2789 --paper-card: #182742;
2790 --ink: #f6f2e8;
2791 --ink-soft: #b6c0d4;
2792 --ink-mute: #93a0b8;
2793 --hairline: rgba(106, 174, 242, 0.22);
2794 --code-bg: #08111c;
2795 --code-fg: #f6f2e8;
2796 --docs-accent: #6aaef2;
2797 --docs-button-bg: #182742;
2798 --docs-button-border: #263e5c;
2799 --docs-button-text: #f6f2e8;
2800 }
2801
2801 lines CSS