1/* ============================================================
2 Marketing layout primitives. Lean — only the pieces actually
3 used by the home + product pages remain. Token defs live in
4 tokens.css; terminal chrome (shared with docs) lives in
5 terminal.css.
6 ============================================================ */
7
8@import "./terminal.css";
9@import "./text-wrap.css";
10
11body.alc-root,
12.alc-root {
13 background: var(--alc-bg);
14 color: var(--alc-fg-2);
15 font-family: var(--alc-font-sans);
16 font-size: 15px;
17 line-height: 1.6;
18 -webkit-font-smoothing: antialiased;
19 -moz-osx-font-smoothing: grayscale;
20}
21
22::selection {
23 background: var(--alc-accent-soft);
24 color: var(--alc-fg-1);
25}
26
27/* Inline "Learn more →" link used at the end of section descriptions. */
28.alc-learn-more {
29 color: var(--alc-accent-deep);
30 font-weight: 500;
31 text-decoration: none;
32 white-space: nowrap;
33 margin-left: 4px;
34 transition: opacity 140ms ease;
35}
36.alc-learn-more:hover {
37 opacity: 0.7;
38 text-decoration: underline;
39 text-underline-offset: 3px;
40}
41
42/* ============================================================
43 Code block — terminal-themed wrapper used by static <CodeBlock>
44 ============================================================ */
45
46.alc-code-block {
47 background: var(--alc-bg-code);
48 border: 1px solid var(--alc-hairline);
49 border-radius: 10px;
50 overflow: hidden;
51 box-shadow: var(--alc-shadow-sm);
52 display: flex;
53 flex-direction: column;
54 min-width: 0;
55 max-width: 100%;
56}
57.alc-code-block__header {
58 display: flex;
59 align-items: center;
60 gap: 6px;
61 padding: 10px 14px;
62 border-bottom: 1px solid rgba(232, 220, 192, 0.08);
63 background: rgba(255, 255, 255, 0.02);
64 flex: 0 0 auto;
65}
66.alc-code-block__filename {
67 margin-left: 2px;
68 font-family: var(--alc-font-mono);
69 font-size: 11px;
70 color: var(--alc-code-comment);
71}
72/* Wrapper used when CodeBlock has a caption — keeps the block + the
73 hand-written caption visually grouped beneath the window chrome. */
74.alc-code-block__wrap {
75 display: flex;
76 flex-direction: column;
77 gap: 8px;
78}
79.alc-code-block__caption {
80 font-family: var(--alc-font-hand);
81 font-size: 20px;
82 line-height: 1.2;
83 color: var(--alc-accent-deep);
84 text-align: center;
85 letter-spacing: 0.01em;
86 animation: alc-code-caption-in 320ms ease;
87}
88@keyframes alc-code-caption-in {
89 from {
90 opacity: 0;
91 transform: translateY(-2px);
92 }
93 to {
94 opacity: 1;
95 transform: translateY(0);
96 }
97}
98@media (prefers-reduced-motion: reduce) {
99 .alc-code-block__caption {
100 animation: none;
101 }
102}
103.alc-code-block__pre {
104 margin: 0;
105 padding: 18px 20px;
106 font-family: var(--alc-font-mono);
107 font-size: 13px;
108 line-height: 1.7;
109 color: var(--alc-code-var);
110 overflow-x: auto;
111}
112.alc-code-block--compact .alc-code-block__pre {
113 padding: 12px 16px;
114 font-size: 12px;
115}
116
117/* ============================================================
118 Bindings → IAM / EventSource animation (/product/providers/aws)
119 Code on the left, animated arrows in the middle, resources
120 on the right, generated IAM policy below.
121 ============================================================ */
122
123.bindings-iam {
124 display: grid;
125 grid-template-columns: minmax(0, 1fr) 200px minmax(0, 0.85fr);
126 grid-template-rows: minmax(280px, auto);
127 gap: 18px;
128 align-items: stretch;
129 max-width: 1180px;
130 margin: 0 auto;
131}
132.bindings-iam__code {
133 grid-column: 1;
134 grid-row: 1;
135 min-width: 0;
136}
137.bindings-iam__arrows {
138 grid-column: 2;
139 grid-row: 1;
140 position: relative;
141 align-self: stretch;
142}
143.bindings-iam__arrows svg {
144 position: absolute;
145 inset: 0;
146 width: 100%;
147 height: 100%;
148 overflow: visible;
149}
150.bindings-iam__resources {
151 grid-column: 3;
152 grid-row: 1;
153 display: flex;
154 flex-direction: column;
155 justify-content: space-around;
156 gap: 14px;
157 min-width: 0;
158}
159.bindings-iam__resource {
160 display: flex;
161 align-items: center;
162 gap: 10px;
163 padding: 10px 12px;
164 background: var(--alc-bg-elev-1);
165 border: 1px solid var(--alc-hairline);
166 border-radius: 10px;
167}
168.bindings-iam__resource-label {
169 font-family: var(--alc-font-sans);
170 font-size: 13px;
171 font-weight: 600;
172 color: var(--alc-fg-1);
173 line-height: 1.2;
174}
175.bindings-iam__resource-sub {
176 font-family: var(--alc-font-mono);
177 font-size: 10px;
178 color: var(--alc-fg-3);
179 line-height: 1.3;
180 margin-top: 2px;
181}
182.bindings-iam__policy {
183 display: none;
184 overflow: hidden;
185 box-shadow: var(--alc-shadow-sm);
186}
187@media (max-width: 980px) {
188 .bindings-iam {
189 grid-template-columns: 1fr;
190 grid-template-rows: auto auto auto auto;
191 }
192 .bindings-iam__code,
193 .bindings-iam__arrows,
194 .bindings-iam__resources,
195 .bindings-iam__policy {
196 grid-column: 1;
197 grid-row: auto;
198 }
199 .bindings-iam__arrows {
200 display: none;
201 }
202}
203
204/* ============================================================
205 Stack → DeployTerminal diagram (/product/iac)
206 ============================================================ */
207
208.stack-deploy-diagram {
209 display: grid;
210 grid-template-columns: minmax(0, 1fr) 60px minmax(0, 1fr);
211 align-items: stretch;
212 gap: 16px;
213 max-width: 1180px;
214 margin: 0 auto;
215}
216.stack-deploy-diagram__col {
217 min-width: 0;
218 display: flex;
219 flex-direction: column;
220 gap: 12px;
221}
222/* Lock both panels to the same fixed height so the captions align and
223 the right terminal's animated content can't push it taller than the
224 left code block (or vice versa). The terminal is rendered inside an
225 <astro-island> hydration wrapper, so the selectors must be descendant
226 (not direct-child) and the wrapper itself must stretch. */
227.stack-deploy-diagram__col,
228.stack-deploy-diagram__col > astro-island {
229 display: flex;
230 flex-direction: column;
231}
232.stack-deploy-diagram__col > astro-island {
233 flex: 0 0 auto;
234}
235.stack-deploy-diagram__col .alc-code-block,
236.stack-deploy-diagram__col .alc-term {
237 flex: 0 0 auto;
238 height: 360px;
239 min-height: 360px;
240 max-height: 360px;
241 box-sizing: border-box;
242}
243.stack-deploy-diagram__col .alc-code-block .alc-code-block__pre,
244.stack-deploy-diagram__col .alc-term .alc-term__body {
245 flex: 1;
246 min-height: 0;
247}
248/* Static code snippet fits the fixed-height card already; allowing
249 `overflow: auto` here causes a few-pixel scroll region that
250 hijacks page wheel events. Clip instead. */
251.stack-deploy-diagram__col .alc-code-block .alc-code-block__pre {
252 overflow: hidden;
253}
254/* The animated deploy terminal grows as resources stream in, so it
255 genuinely needs to scroll. */
256.stack-deploy-diagram__col .alc-term .alc-term__body {
257 overflow: auto;
258}
259.stack-deploy-diagram__caption {
260 display: flex;
261 flex-direction: column;
262 align-items: center;
263 text-align: center;
264 gap: 2px;
265}
266.stack-deploy-diagram__caption span {
267 font-family: var(--alc-font-mono);
268 font-size: 11px;
269 letter-spacing: 0.08em;
270 text-transform: uppercase;
271 color: var(--alc-fg-3);
272}
273.stack-deploy-diagram__arrow {
274 display: flex;
275 flex-direction: column;
276 align-items: center;
277 justify-content: center;
278 align-self: center;
279 gap: 4px;
280 color: var(--alc-accent-deep);
281 font-family: var(--alc-font-hand);
282 font-size: 16px;
283}
284
285/* ============================================================
286 Effect-pilled showcase (home page section 2)
287 One terminal-chromed card with two tabs (IAM bindings / Event
288 sources). Each panel is code on the left and a stylized
289 "generated artifact" panel on the right. On narrow screens the
290 split collapses into a vertical stack with a "↓ generates" cue
291 between code and artifact, so nothing depends on SVG arrows that
292 break on mobile.
293 ============================================================ */
294
295.eff-showcase {
296 display: flex;
297 flex-direction: column;
298 gap: 8px;
299 max-width: 1080px;
300 margin: 0 auto;
301}
302.eff-showcase__chrome {
303 background: var(--alc-bg-code);
304 border: 1px solid var(--alc-hairline);
305 border-radius: 10px;
306 overflow: hidden;
307 box-shadow: var(--alc-shadow-sm);
308 display: flex;
309 flex-direction: column;
310}
311.eff-showcase__header {
312 display: flex;
313 align-items: center;
314 gap: 6px;
315 padding: 8px 12px;
316 border-bottom: 1px solid rgba(232, 220, 192, 0.08);
317 background: rgba(255, 255, 255, 0.02);
318}
319.eff-showcase__tabs {
320 display: flex;
321 gap: 4px;
322 margin-left: 12px;
323 flex: 1;
324 min-width: 0;
325 overflow-x: auto;
326 scrollbar-width: none;
327}
328.eff-showcase__tabs::-webkit-scrollbar {
329 display: none;
330}
331.eff-showcase__tab {
332 flex: 0 0 auto;
333 appearance: none;
334 background: transparent;
335 border: 1px solid transparent;
336 color: var(--alc-code-comment);
337 font-family: var(--alc-font-mono);
338 font-size: 11px;
339 padding: 4px 10px;
340 border-radius: 5px;
341 cursor: pointer;
342 transition:
343 color 160ms ease,
344 background 160ms ease,
345 border-color 160ms ease;
346}
347.eff-showcase__tab:hover {
348 color: var(--alc-fg-invert);
349}
350.eff-showcase__tab[data-active="true"] {
351 color: var(--alc-fg-invert);
352 background: rgba(255, 255, 255, 0.05);
353 border-color: rgba(232, 220, 192, 0.12);
354}
355.eff-showcase__body {
356 position: relative;
357 display: flex;
358 flex-direction: column;
359}
360.eff-showcase__panel {
361 display: flex;
362 flex-direction: column;
363}
364.eff-showcase__panel[hidden] {
365 display: none;
366}
367.eff-showcase__split {
368 display: grid;
369 grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
370 gap: 0;
371 /* Fixed height keeps the page below stable as the auto-cycle swaps
372 between tabs whose code/artifact have different intrinsic heights. */
373 height: 420px;
374}
375.eff-showcase__code {
376 display: flex;
377 flex-direction: column;
378 min-width: 0;
379 border-right: 1px solid rgba(232, 220, 192, 0.08);
380}
381.eff-showcase__pre {
382 margin: 0;
383 padding: 16px 18px;
384 font-family: var(--alc-font-mono);
385 font-size: 12.5px;
386 line-height: 1.7;
387 color: var(--alc-code-var);
388 overflow: auto;
389 flex: 1;
390 min-height: 0;
391}
392.eff-showcase__artifact {
393 display: flex;
394 flex-direction: column;
395 gap: 18px;
396 padding: 18px 20px;
397 /* Slightly sunken vs the main terminal bg so the lifted cards inside
398 read as "panels on a panel" rather than "dark on dark". */
399 background: var(--alc-walnut-950);
400 min-width: 0;
401 overflow: auto;
402 min-height: 0;
403}
404.eff-showcase__group {
405 display: flex;
406 flex-direction: column;
407 gap: 8px;
408 min-width: 0;
409}
410.eff-showcase__group-title {
411 font-family: var(--alc-font-mono);
412 font-size: 10.5px;
413 letter-spacing: 0.08em;
414 text-transform: uppercase;
415 color: var(--alc-walnut-300);
416}
417.eff-showcase__perm {
418 display: flex;
419 align-items: center;
420 gap: 10px;
421 padding: 10px 12px;
422 background: var(--alc-walnut-700);
423 border: 1px solid var(--alc-walnut-600);
424 border-radius: 8px;
425 font-family: var(--alc-font-mono);
426 font-size: 12.5px;
427 color: var(--alc-fg-invert);
428 min-width: 0;
429 opacity: 0;
430 animation: eff-fade-up 460ms cubic-bezier(0.4, 0, 0.2, 1) both;
431}
432.eff-showcase__perm-icon {
433 flex: 0 0 auto;
434 border-radius: 4px;
435}
436.eff-showcase__perm-action {
437 color: var(--alc-code-keyword);
438 font-weight: 600;
439 white-space: nowrap;
440}
441.eff-showcase__perm-arrow {
442 color: var(--alc-accent-bright);
443 flex: 0 0 auto;
444}
445.eff-showcase__perm-target {
446 color: var(--alc-fg-invert);
447 white-space: nowrap;
448 overflow: hidden;
449 text-overflow: ellipsis;
450 min-width: 0;
451}
452.eff-showcase__envs {
453 display: flex;
454 flex-direction: column;
455 gap: 6px;
456}
457.eff-showcase__env {
458 display: flex;
459 align-items: baseline;
460 gap: 8px;
461 padding: 8px 12px;
462 background: var(--alc-walnut-700);
463 border: 1px solid var(--alc-walnut-600);
464 border-left: 2px solid var(--alc-accent-bright);
465 border-radius: 6px;
466 font-family: var(--alc-font-mono);
467 font-size: 12px;
468 color: var(--alc-fg-invert);
469 min-width: 0;
470 opacity: 0;
471 animation: eff-fade-up 460ms cubic-bezier(0.4, 0, 0.2, 1) both;
472}
473.eff-showcase__env-name {
474 color: var(--alc-code-keyword);
475 font-weight: 600;
476 flex: 0 0 auto;
477}
478.eff-showcase__env-eq {
479 color: var(--alc-code-comment);
480}
481.eff-showcase__env-value {
482 color: var(--alc-fg-invert);
483 white-space: nowrap;
484 overflow: hidden;
485 text-overflow: ellipsis;
486 min-width: 0;
487 flex: 1;
488}
489
490/* Feature row — used by Durable Objects / Containers / Layers tabs.
491 Icon on the left, label + sub stacked on the right. Same lifted card
492 treatment as .eff-showcase__perm so the artifact panels feel related. */
493.eff-showcase__feature {
494 display: flex;
495 align-items: center;
496 gap: 12px;
497 padding: 10px 12px;
498 background: var(--alc-walnut-700);
499 border: 1px solid var(--alc-walnut-600);
500 border-radius: 8px;
501 min-width: 0;
502 opacity: 0;
503 animation: eff-fade-up 460ms cubic-bezier(0.4, 0, 0.2, 1) both;
504}
505.eff-showcase__feature-icon {
506 flex: 0 0 auto;
507}
508.eff-showcase__feature-text {
509 display: flex;
510 flex-direction: column;
511 gap: 2px;
512 min-width: 0;
513 flex: 1;
514}
515.eff-showcase__feature-label {
516 font-family: var(--alc-font-mono);
517 font-size: 12.5px;
518 color: var(--alc-code-keyword);
519 font-weight: 600;
520 white-space: nowrap;
521 overflow: hidden;
522 text-overflow: ellipsis;
523}
524.eff-showcase__feature-sub {
525 font-family: var(--alc-font-mono);
526 font-size: 11px;
527 color: var(--alc-walnut-300);
528 white-space: nowrap;
529 overflow: hidden;
530 text-overflow: ellipsis;
531}
532
533/* Workflow steps — numbered ordered list with rounded badges. */
534.eff-showcase__steps {
535 display: flex;
536 flex-direction: column;
537 gap: 6px;
538}
539.eff-showcase__step {
540 display: grid;
541 grid-template-columns: 22px minmax(0, auto) minmax(0, 1fr);
542 align-items: center;
543 gap: 10px;
544 padding: 8px 12px;
545 background: var(--alc-walnut-700);
546 border: 1px solid var(--alc-walnut-600);
547 border-radius: 8px;
548 min-width: 0;
549 opacity: 0;
550 animation: eff-fade-up 460ms cubic-bezier(0.4, 0, 0.2, 1) both;
551}
552.eff-showcase__step-num {
553 width: 22px;
554 height: 22px;
555 border-radius: 50%;
556 background: var(--alc-accent-bright);
557 color: var(--alc-bg-code);
558 font-family: var(--alc-font-mono);
559 font-size: 11px;
560 font-weight: 700;
561 display: inline-flex;
562 align-items: center;
563 justify-content: center;
564}
565.eff-showcase__step-label {
566 font-family: var(--alc-font-mono);
567 font-size: 12.5px;
568 font-weight: 600;
569 color: var(--alc-code-keyword);
570 white-space: nowrap;
571}
572.eff-showcase__step-sub {
573 font-family: var(--alc-font-mono);
574 font-size: 11px;
575 color: var(--alc-walnut-300);
576 white-space: nowrap;
577 overflow: hidden;
578 text-overflow: ellipsis;
579 text-align: right;
580}
581
582/* Event source flow — three nodes connected by labelled edges. */
583.eff-showcase__flow {
584 display: grid;
585 grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr) auto minmax(0, 1fr);
586 align-items: center;
587 gap: 6px;
588 margin-top: 4px;
589}
590.eff-showcase__node {
591 display: flex;
592 flex-direction: column;
593 align-items: center;
594 gap: 4px;
595 padding: 14px 10px;
596 background: var(--alc-walnut-700);
597 border: 1px solid var(--alc-walnut-600);
598 border-radius: 10px;
599 text-align: center;
600 min-width: 0;
601 opacity: 0;
602 animation: eff-fade-up 460ms cubic-bezier(0.4, 0, 0.2, 1) both;
603}
604.eff-showcase__node--accent {
605 background: var(--alc-walnut-600);
606 border-color: var(--alc-accent-bright);
607 box-shadow: 0 0 0 2px rgba(143, 177, 94, 0.18);
608}
609.eff-showcase__node-label {
610 font-family: var(--alc-font-sans);
611 font-size: 13px;
612 font-weight: 600;
613 color: var(--alc-fg-invert);
614 line-height: 1.2;
615}
616.eff-showcase__node-sub {
617 font-family: var(--alc-font-mono);
618 font-size: 10px;
619 color: var(--alc-walnut-300);
620 line-height: 1.2;
621}
622.eff-showcase__edge {
623 position: relative;
624 width: 28px;
625 height: 1.6px;
626 background: var(--alc-accent-bright);
627 opacity: 0;
628 animation: eff-fade-in 320ms ease both;
629}
630.eff-showcase__edge::after {
631 content: "";
632 position: absolute;
633 right: -1px;
634 top: 50%;
635 width: 0;
636 height: 0;
637 border-top: 4px solid transparent;
638 border-bottom: 4px solid transparent;
639 border-left: 6px solid var(--alc-accent-bright);
640 transform: translateY(-50%);
641}
642.eff-showcase__edge::before {
643 content: attr(data-label);
644 position: absolute;
645 left: 50%;
646 bottom: 100%;
647 transform: translate(-50%, -2px);
648 font-family: var(--alc-font-mono);
649 font-size: 9.5px;
650 letter-spacing: 0.04em;
651 color: var(--alc-walnut-300);
652 white-space: nowrap;
653 background: var(--alc-walnut-950);
654 padding: 0 4px;
655}
656
657.eff-showcase__hint {
658 font-family: var(--alc-font-mono);
659 font-size: 10.5px;
660 color: var(--alc-fg-3);
661 text-align: center;
662 letter-spacing: 0.04em;
663}
664
665@keyframes eff-fade-up {
666 from {
667 opacity: 0;
668 transform: translateY(6px);
669 }
670 to {
671 opacity: 1;
672 transform: translateY(0);
673 }
674}
675@keyframes eff-fade-in {
676 from {
677 opacity: 0;
678 }
679 to {
680 opacity: 1;
681 }
682}
683
684/* Used on the code <pre> so it fades in alongside the artifact rows
685 when the panel remounts (tab switch). */
686.eff-showcase__fade {
687 animation: eff-fade-in 320ms ease both;
688}
689
690/* ------------------------------------------------------------
691 Layer tab — diff renderer with overlay variant crossfade.
692 Common lines render statically. Each diff segment is a "slot"
693 that overlays both variants in the same grid cell so only the
694 active one is visible — the inactive fades to opacity 0 and is
695 replaced by the active in a long ease-in-out crossfade.
696 ------------------------------------------------------------ */
697
698.eff-showcase__diff {
699 margin: 0;
700 padding: 14px 16px 14px 12px;
701 font-family: var(--alc-font-mono);
702 font-size: 11.5px;
703 line-height: 1.7;
704 /* Bright parchment for any character that isn't tokenized by
705 highlightTS (punctuation: <, =, (, ), {, }, ;, etc.) so symbols
706 don't disappear into the walnut bg. */
707 color: var(--alc-code-var);
708 overflow: auto;
709 flex: 1;
710 min-height: 0;
711 display: flex;
712 flex-direction: column;
713}
714
715.eff-diff__common {
716 display: flex;
717 flex-direction: column;
718}
719
720/* Slot: a CSS grid with one cell. Both variants share that cell, so the
721 slot's height is the max of the two variants and the panel never jumps
722 when the impl swaps. */
723.eff-diff__slot {
724 display: grid;
725 grid-template-areas: "stack";
726}
727.eff-diff__variant {
728 grid-area: stack;
729 display: flex;
730 flex-direction: column;
731 opacity: 0;
732 pointer-events: none;
733 transition: opacity 1100ms cubic-bezier(0.4, 0, 0.2, 1);
734}
735.eff-diff__variant[data-active="true"] {
736 opacity: 1;
737 pointer-events: auto;
738}
739
740.eff-diff__line {
741 display: grid;
742 grid-template-columns: 14px minmax(0, 1fr);
743 align-items: baseline;
744 gap: 6px;
745 padding: 0 6px;
746 margin: 0 -6px;
747}
748.eff-diff__marker {
749 display: inline-block;
750 width: 12px;
751 text-align: center;
752 font-weight: 700;
753 user-select: none;
754 color: var(--alc-accent-bright);
755}
756.eff-diff__content {
757 display: block;
758 white-space: pre;
759 min-width: 0;
760}
761
762/* Diff lines get a subtle green tint background so the whole line
763 reads as "added" — not just the "+" prefix. The tint is soft enough
764 not to fight the syntax-highlighted tokens. */
765.eff-diff__line--ddb,
766.eff-diff__line--d1 {
767 background-color: rgba(143, 177, 94, 0.12);
768 box-shadow: inset 2px 0 0 var(--alc-accent-bright);
769}
770.eff-diff__line--ddb .eff-diff__marker::before,
771.eff-diff__line--d1 .eff-diff__marker::before {
772 content: "+";
773}
774
775/* ------------------------------------------------------------
776 Layer tab — artifact panel uses the same overlay pattern for
777 the "Composed from" group so the ddb / d1 feature-row stacks
778 crossfade in place rather than competing for visual weight.
779 ------------------------------------------------------------ */
780
781.eff-showcase__variant-stack {
782 display: grid;
783 grid-template-areas: "stack";
784}
785.eff-showcase__variant {
786 grid-area: stack;
787 display: flex;
788 flex-direction: column;
789 gap: 8px;
790 opacity: 0;
791 pointer-events: none;
792 transition: opacity 1100ms cubic-bezier(0.4, 0, 0.2, 1);
793}
794.eff-showcase__variant[data-active="true"] {
795 opacity: 1;
796 pointer-events: auto;
797}
798
799/* Mobile: drop the right-hand artifact panel entirely — the generated
800 permissions / environment / flow visualizations don't read well at narrow
801 widths and the code itself is the primary story. */
802@media (max-width: 880px) {
803 .eff-showcase__split {
804 grid-template-columns: minmax(0, 1fr);
805 /* Code-only: let the panel size to the code's natural height instead
806 of holding the desktop's fixed 420px slot. */
807 height: auto;
808 }
809 .eff-showcase__code {
810 border-right: 0;
811 }
812 .eff-showcase__pre {
813 overflow-x: auto;
814 }
815 .eff-showcase__artifact {
816 display: none;
817 }
818 .eff-showcase__flow {
819 grid-template-columns: minmax(0, 1fr);
820 grid-auto-flow: row;
821 gap: 4px;
822 justify-items: stretch;
823 }
824 .eff-showcase__edge {
825 width: 1.6px;
826 height: 24px;
827 margin: 0 auto;
828 }
829 .eff-showcase__edge::after {
830 right: 50%;
831 top: auto;
832 bottom: -1px;
833 transform: translateX(50%);
834 border-left: 4px solid transparent;
835 border-right: 4px solid transparent;
836 border-top: 6px solid var(--alc-accent-bright);
837 border-bottom: 0;
838 }
839 .eff-showcase__edge::before {
840 left: 100%;
841 bottom: 50%;
842 transform: translate(4px, 50%);
843 }
844}
845
846/* ============================================================
847 Stack / Deploy — narrow-screen fallback (home page section 1)
848 The 3-column "code + arrow + terminal" diagram needs horizontal
849 room to read well. On iPad-and-narrower we drop the source code
850 panel entirely and just show the live deploy terminal — the
851 Alchemy.Stack code is already visible elsewhere on the page.
852 ============================================================ */
853
854.stack-deploy-mobile {
855 display: none;
856 max-width: 720px;
857 margin: 0 auto;
858}
859.stack-deploy-mobile > .alc-term {
860 width: 100%;
861}
862
863@media (max-width: 880px) {
864 .stack-deploy-diagram {
865 display: none;
866 }
867 .stack-deploy-mobile {
868 display: block;
869 }
870}
871
872/* ============================================================
873 Async-fetch escape hatch — narrow-screen tabs
874 On wide screens the two files sit side-by-side. Below 1024px
875 they collapse into a single tabbed card that auto-flips between
876 alchemy.run.ts and src/worker.ts with a short caption.
877 ============================================================ */
878
879.async-split-mobile {
880 display: none;
881}
882.async-tabs {
883 display: flex;
884 flex-direction: column;
885 gap: 10px;
886 max-width: 720px;
887 margin: 0 auto;
888}
889.async-tabs__chrome {
890 background: var(--alc-bg-code);
891 border: 1px solid var(--alc-hairline);
892 border-radius: 10px;
893 overflow: hidden;
894 box-shadow: var(--alc-shadow-sm);
895 display: flex;
896 flex-direction: column;
897}
898.async-tabs__header {
899 display: flex;
900 align-items: center;
901 gap: 6px;
902 padding: 8px 12px;
903 border-bottom: 1px solid rgba(232, 220, 192, 0.08);
904 background: rgba(255, 255, 255, 0.02);
905}
906.async-tabs__tabs {
907 display: flex;
908 gap: 4px;
909 margin-left: 12px;
910 flex: 1;
911 min-width: 0;
912 overflow-x: auto;
913 scrollbar-width: none;
914}
915.async-tabs__tabs::-webkit-scrollbar {
916 display: none;
917}
918.async-tabs__tab {
919 flex: 0 0 auto;
920 appearance: none;
921 background: transparent;
922 border: 1px solid transparent;
923 color: var(--alc-code-comment);
924 font-family: var(--alc-font-mono);
925 font-size: 11px;
926 padding: 4px 10px;
927 border-radius: 5px;
928 cursor: pointer;
929 transition:
930 color 160ms ease,
931 background 160ms ease,
932 border-color 160ms ease;
933}
934.async-tabs__tab:hover {
935 color: var(--alc-fg-invert);
936}
937.async-tabs__tab[data-active="true"] {
938 color: var(--alc-fg-invert);
939 background: rgba(255, 255, 255, 0.05);
940 border-color: rgba(232, 220, 192, 0.12);
941}
942.async-tabs__body {
943 position: relative;
944 display: flex;
945 flex-direction: column;
946}
947.async-tabs__panel {
948 display: flex;
949 flex-direction: column;
950 flex: 1;
951 min-width: 0;
952}
953.async-tabs__panel[hidden] {
954 display: none;
955}
956.async-tabs__pre {
957 margin: 0;
958 padding: 14px 16px;
959 font-family: var(--alc-font-mono);
960 font-size: 12px;
961 line-height: 1.65;
962 color: var(--alc-code-var);
963 overflow-x: auto;
964 flex: 1;
965}
966@media (max-width: 880px) {
967 .alc-split-2.async-split-desktop {
968 display: none;
969 }
970 .async-split-mobile {
971 display: block;
972 }
973}
974
975/* ============================================================
976 Animated Output / resource-graph (/product/iac)
977 Code on the left, progressive nodes/edges on the right with
978 a step indicator + rotating annotation.
979 ============================================================ */
980
981.output-anim-grid {
982 display: grid;
983 grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
984 gap: 24px;
985 align-items: stretch;
986 max-width: 1100px;
987 margin: 0 auto;
988}
989.output-anim-grid > .alc-code-block {
990 min-height: 100%;
991}
992
993.output-anim-stage {
994 background: var(--alc-bg-elev-1);
995 border: 1px solid var(--alc-hairline);
996 border-radius: 14px;
997 padding: 22px 22px 18px;
998 display: flex;
999 flex-direction: column;
1000 gap: 18px;
1001}
1002
1003.output-anim-graph {
1004 flex: 1;
1005 display: grid;
1006 grid-template-columns: minmax(0, auto) minmax(60px, 1fr) minmax(0, auto);
1007 grid-template-rows: auto minmax(48px, 1fr) auto;
1008 align-items: center;
1009 justify-items: center;
1010 gap: 0;
1011}
1012
1013.output-anim-node {
1014 display: inline-flex;
1015 flex-direction: column;
1016 align-items: center;
1017 gap: 2px;
1018 padding: 10px 18px;
1019 border-radius: 10px;
1020 min-width: 110px;
1021 white-space: nowrap;
1022 transition:
1023 opacity 380ms ease,
1024 transform 380ms ease;
1025}
1026.output-anim-node--accent {
1027 background: rgba(184, 138, 74, 0.1);
1028 border: 1.4px solid var(--alc-accent-deep);
1029}
1030.output-anim-node--ghost {
1031 background: var(--alc-bg);
1032 border: 1.4px dashed var(--alc-hairline-2);
1033}
1034.output-anim-node__label {
1035 font-family: var(--alc-font-sans);
1036 font-size: 13px;
1037 font-weight: 600;
1038 color: var(--alc-fg-1);
1039 line-height: 1.15;
1040}
1041.output-anim-node__id {
1042 font-family: var(--alc-font-mono);
1043 font-size: 10.5px;
1044 color: var(--alc-fg-3);
1045 line-height: 1.15;
1046}
1047
1048.output-anim-edge {
1049 position: relative;
1050 width: 100%;
1051 height: 100%;
1052 display: flex;
1053 align-items: center;
1054 justify-content: center;
1055 opacity: 0.18;
1056 transition: opacity 360ms ease;
1057}
1058.output-anim-edge.is-on {
1059 opacity: 1;
1060}
1061
1062.output-anim-edge--h::before {
1063 content: "";
1064 position: absolute;
1065 left: 6px;
1066 right: 14px;
1067 top: 50%;
1068 height: 1.6px;
1069 background: var(--alc-accent-deep);
1070 transform: translateY(-50%);
1071}
1072.output-anim-edge--h::after {
1073 content: "";
1074 position: absolute;
1075 right: 6px;
1076 top: 50%;
1077 width: 0;
1078 height: 0;
1079 border-top: 5px solid transparent;
1080 border-bottom: 5px solid transparent;
1081 border-left: 7px solid var(--alc-accent-deep);
1082 transform: translateY(-50%);
1083}
1084.output-anim-edge--v::before {
1085 content: "";
1086 position: absolute;
1087 top: 4px;
1088 bottom: 12px;
1089 left: 50%;
1090 width: 1.6px;
1091 background: var(--alc-accent-deep);
1092 transform: translateX(-50%);
1093}
1094.output-anim-edge--v::after {
1095 content: "";
1096 position: absolute;
1097 bottom: 2px;
1098 left: 50%;
1099 width: 0;
1100 height: 0;
1101 border-left: 5px solid transparent;
1102 border-right: 5px solid transparent;
1103 border-top: 7px solid var(--alc-accent-deep);
1104 transform: translateX(-50%);
1105}
1106.output-anim-edge__label {
1107 position: relative;
1108 z-index: 1;
1109 font-family: var(--alc-font-mono);
1110 font-size: 11px;
1111 color: var(--alc-fg-3);
1112 background: var(--alc-bg-elev-1);
1113 padding: 2px 8px;
1114 border-radius: 4px;
1115}
1116
1117.output-anim-steps {
1118 display: flex;
1119 align-items: center;
1120 justify-content: center;
1121 gap: 6px;
1122 padding-top: 4px;
1123}
1124.output-anim-steps__dot {
1125 width: 6px;
1126 height: 6px;
1127 border-radius: 50%;
1128 background: var(--alc-hairline-2);
1129 transition:
1130 background 280ms ease,
1131 transform 280ms ease;
1132}
1133.output-anim-steps__dot.is-active {
1134 background: var(--alc-accent-deep);
1135 transform: scale(1.35);
1136}
1137
1138.output-anim-annotation {
1139 font-size: 13px;
1140 line-height: 1.55;
1141 color: var(--alc-fg-2);
1142 text-align: center;
1143 min-height: 3.2em; /* reserve space so layout doesn't jump */
1144}
1145.output-anim-annotation strong {
1146 color: var(--alc-fg-1);
1147 font-weight: 600;
1148}
1149.output-anim-annotation code {
1150 font-family: var(--alc-font-mono);
1151 font-size: 0.92em;
1152 color: var(--alc-accent-deep);
1153 background: rgba(184, 138, 74, 0.1);
1154 padding: 0 4px;
1155 border-radius: 3px;
1156}
1157
1158@media (max-width: 880px) {
1159 .output-anim-grid {
1160 grid-template-columns: 1fr;
1161 }
1162}
1163
1164/* ============================================================
1165 Service-as-Layer swap (/product/iac)
1166 Worker code on left, Sessions → Layer → Resource on right
1167 cycles through KV, DynamoDB, D1 backings.
1168 ============================================================ */
1169
1170.service-swap-grid {
1171 display: grid;
1172 grid-template-columns: minmax(0, 1.25fr) minmax(280px, 1fr);
1173 gap: 24px;
1174 align-items: stretch;
1175 max-width: 1100px;
1176 margin: 0 auto;
1177}
1178
1179.service-swap-stage {
1180 background: var(--alc-bg-elev-1);
1181 border: 1px solid var(--alc-hairline);
1182 border-radius: 14px;
1183 padding: 22px 18px 14px;
1184 display: flex;
1185 flex-direction: column;
1186 align-items: center;
1187 justify-content: center;
1188 gap: 0;
1189}
1190
1191.service-swap-stage__node {
1192 display: inline-flex;
1193 flex-direction: column;
1194 align-items: center;
1195 gap: 3px;
1196 padding: 10px 16px 8px;
1197 background: var(--alc-bg-elev-1);
1198 border: 1.4px solid var(--alc-hairline-2);
1199 border-radius: 10px;
1200 min-width: 150px;
1201 text-align: center;
1202 transition:
1203 border-color 320ms ease,
1204 box-shadow 320ms ease;
1205}
1206.service-swap-stage__node--accent {
1207 border-color: var(--alc-accent-deep);
1208 box-shadow: 0 0 0 2px rgba(184, 138, 74, 0.12);
1209}
1210.service-swap-stage__label {
1211 font-family: var(--alc-font-sans);
1212 font-size: 13px;
1213 font-weight: 600;
1214 color: var(--alc-fg-1);
1215 line-height: 1.2;
1216}
1217.service-swap-stage__sub {
1218 font-family: var(--alc-font-mono);
1219 font-size: 10.5px;
1220 color: var(--alc-fg-3);
1221 line-height: 1.2;
1222}
1223
1224.service-swap-stage__edge {
1225 position: relative;
1226 height: 28px;
1227 width: 1.6px;
1228 background: currentColor;
1229 margin: 4px 0;
1230 color: var(--alc-accent-deep);
1231 display: flex;
1232 align-items: center;
1233 justify-content: center;
1234 transition:
1235 background 320ms ease,
1236 color 320ms ease;
1237}
1238.service-swap-stage__edge--down::after {
1239 content: "";
1240 position: absolute;
1241 bottom: -1px;
1242 left: 50%;
1243 transform: translateX(-50%);
1244 width: 0;
1245 height: 0;
1246 border-left: 5px solid transparent;
1247 border-right: 5px solid transparent;
1248 border-top: 7px solid currentColor;
1249 transition: border-top-color 320ms ease;
1250}
1251.service-swap-stage__edge-label {
1252 position: absolute;
1253 left: 100%;
1254 top: 50%;
1255 transform: translateY(-50%);
1256 margin-left: 10px;
1257 font-family: var(--alc-font-mono);
1258 font-size: 10.5px;
1259 background: var(--alc-bg-elev-1);
1260 border: 1px solid currentColor;
1261 padding: 1px 7px;
1262 border-radius: 3px;
1263 white-space: nowrap;
1264 transition:
1265 color 320ms ease,
1266 border-color 320ms ease;
1267}
1268
1269.service-swap-stage__steps {
1270 display: flex;
1271 align-items: center;
1272 justify-content: center;
1273 gap: 6px;
1274 padding-top: 14px;
1275}
1276.service-swap-stage__dot {
1277 width: 6px;
1278 height: 6px;
1279 border-radius: 50%;
1280 background: var(--alc-hairline-2);
1281 transition:
1282 background 280ms ease,
1283 transform 280ms ease;
1284}
1285.service-swap-stage__dot.is-active {
1286 transform: scale(1.35);
1287}
1288
1289/* Reuse the existing layer-cycle-node keyframes for the fade-in
1290 when the active Layer/Resource node swaps. */
1291@keyframes service-swap-pop {
1292 0% {
1293 opacity: 0;
1294 transform: scale(0.92) translateY(-3px);
1295 filter: blur(2px);
1296 }
1297 18% {
1298 opacity: 1;
1299 transform: scale(1) translateY(0);
1300 filter: blur(0);
1301 }
1302 100% {
1303 opacity: 1;
1304 }
1305}
1306.service-swap-stage .layer-swap-node {
1307 animation: service-swap-pop 700ms cubic-bezier(0.4, 0, 0.2, 1) both;
1308}
1309@keyframes layer-swap-text {
1310 0% {
1311 opacity: 0;
1312 transform: translateY(-2px);
1313 }
1314 20% {
1315 opacity: 1;
1316 transform: translateY(0);
1317 }
1318 100% {
1319 opacity: 1;
1320 }
1321}
1322.alc-code-block .layer-swap {
1323 display: inline-block;
1324 padding: 1px 5px;
1325 margin: 0 -1px;
1326 border-radius: 3px;
1327 animation: layer-swap-text 700ms cubic-bezier(0.4, 0, 0.2, 1) both;
1328}
1329
1330@media (max-width: 880px) {
1331 .service-swap-grid {
1332 grid-template-columns: 1fr;
1333 }
1334}
1335
1336/* ============================================================
1337 Output graph diagram (/product/iac)
1338 ============================================================ */
1339
1340.output-graph {
1341 background: var(--alc-bg-elev-1);
1342 border: 1px solid var(--alc-hairline);
1343 border-radius: 14px;
1344 padding: 22px 22px 18px;
1345 display: flex;
1346 flex-direction: column;
1347 justify-content: center; /* center stage+caption so extra column height
1348 is split top/bottom instead of dumped below */
1349 gap: 18px;
1350 align-self: stretch;
1351}
1352
1353/* 3x3 grid: nodes occupy corners, edges occupy middle cells. */
1354.output-graph__stage {
1355 display: grid;
1356 grid-template-columns: minmax(0, auto) minmax(48px, 1fr) minmax(0, auto);
1357 grid-template-rows: auto minmax(40px, 1fr) auto;
1358 align-items: center;
1359 justify-items: center;
1360 gap: 0;
1361 padding: 8px 4px;
1362}
1363
1364.output-graph__node {
1365 display: inline-flex;
1366 flex-direction: column;
1367 align-items: center;
1368 gap: 2px;
1369 padding: 10px 18px;
1370 background: rgba(184, 138, 74, 0.1);
1371 border: 1.4px solid var(--alc-accent-deep);
1372 border-radius: 10px;
1373 min-width: 110px;
1374 white-space: nowrap;
1375}
1376.output-graph__node--ghost {
1377 background: var(--alc-bg);
1378 border-color: var(--alc-hairline-2);
1379 border-style: dashed;
1380}
1381.output-graph__node-label {
1382 font-family: var(--alc-font-sans);
1383 font-size: 13px;
1384 font-weight: 600;
1385 color: var(--alc-fg-1);
1386 line-height: 1.15;
1387}
1388.output-graph__node-id {
1389 font-family: var(--alc-font-mono);
1390 font-size: 10.5px;
1391 color: var(--alc-fg-3);
1392 line-height: 1.15;
1393}
1394
1395/* An edge cell renders a line + arrowhead via pseudo-elements,
1396 plus a label on top via the inner span. */
1397.output-graph__edge {
1398 position: relative;
1399 width: 100%;
1400 height: 100%;
1401 display: flex;
1402 align-items: center;
1403 justify-content: center;
1404}
1405.output-graph__edge--h::before {
1406 content: "";
1407 position: absolute;
1408 left: 8px;
1409 right: 14px;
1410 top: 50%;
1411 height: 1.6px;
1412 background: var(--alc-accent-deep);
1413 transform: translateY(-50%);
1414}
1415.output-graph__edge--h::after {
1416 content: "";
1417 position: absolute;
1418 right: 8px;
1419 top: 50%;
1420 width: 0;
1421 height: 0;
1422 border-top: 5px solid transparent;
1423 border-bottom: 5px solid transparent;
1424 border-left: 7px solid var(--alc-accent-deep);
1425 transform: translateY(-50%);
1426}
1427.output-graph__edge--v::before {
1428 content: "";
1429 position: absolute;
1430 top: 4px;
1431 bottom: 12px;
1432 left: 50%;
1433 width: 1.6px;
1434 background: var(--alc-accent-deep);
1435 transform: translateX(-50%);
1436}
1437.output-graph__edge--v::after {
1438 content: "";
1439 position: absolute;
1440 bottom: 4px;
1441 left: 50%;
1442 width: 0;
1443 height: 0;
1444 border-left: 5px solid transparent;
1445 border-right: 5px solid transparent;
1446 border-top: 7px solid var(--alc-accent-deep);
1447 transform: translateX(-50%);
1448}
1449.output-graph__edge-label {
1450 position: relative;
1451 z-index: 1;
1452 font-family: var(--alc-font-mono);
1453 font-size: 11px;
1454 color: var(--alc-fg-3);
1455 background: var(--alc-bg-elev-1);
1456 padding: 2px 8px;
1457 border-radius: 4px;
1458}
1459
1460.output-graph__caption {
1461 font-size: 12.5px;
1462 line-height: 1.55;
1463 color: var(--alc-fg-3);
1464 text-align: center;
1465}
1466.output-graph__caption strong {
1467 color: var(--alc-fg-1);
1468 font-weight: 600;
1469}
1470.output-graph__caption code {
1471 font-family: var(--alc-font-mono);
1472 font-size: 0.92em;
1473 color: var(--alc-accent-deep);
1474 background: rgba(184, 138, 74, 0.1);
1475 padding: 0 4px;
1476 border-radius: 3px;
1477}
1478
1479@media (max-width: 720px) {
1480 .output-graph__stage {
1481 gap: 14px 40px;
1482 }
1483 .output-graph__node {
1484 min-width: 100px;
1485 padding: 8px 12px;
1486 }
1487}
1488
1489/* ============================================================
1490 Async-style code tabs (/product/providers/cloudflare)
1491 ============================================================ */
1492
1493.code-tabs {
1494 background: var(--alc-bg-elev-1);
1495 border: 1px solid var(--alc-hairline);
1496 border-radius: 12px;
1497 overflow: hidden;
1498}
1499.code-tabs__nav {
1500 display: flex;
1501 background: var(--alc-bg-nav);
1502 border-bottom: 1px solid var(--alc-hairline);
1503}
1504.code-tabs__btn {
1505 flex: 0 0 auto;
1506 padding: 10px 16px;
1507 background: transparent;
1508 border: 0;
1509 color: var(--alc-fg-2);
1510 font-family: var(--alc-font-mono);
1511 font-size: 12px;
1512 cursor: pointer;
1513 border-bottom: 2px solid transparent;
1514 transition:
1515 color 160ms ease,
1516 border-color 160ms ease,
1517 background 160ms ease;
1518}
1519.code-tabs__btn[data-active="true"] {
1520 color: var(--alc-fg-1);
1521 border-bottom-color: var(--alc-accent-deep);
1522 background: var(--alc-bg-elev-1);
1523}
1524.code-tabs__btn:hover {
1525 color: var(--alc-fg-1);
1526}
1527.code-tabs__panel {
1528 display: none;
1529}
1530.code-tabs__panel[data-active="true"] {
1531 display: block;
1532}
1533.code-tabs__panel .alc-code-block {
1534 border: 0;
1535 border-radius: 0;
1536 box-shadow: none;
1537}
1538
1539/* TS token colors used inside .alc-code-block */
1540.alc-tok-k {
1541 color: var(--alc-code-keyword);
1542}
1543.alc-tok-s {
1544 color: var(--alc-code-string);
1545}
1546.alc-tok-f {
1547 color: var(--alc-code-fn);
1548}
1549.alc-tok-t {
1550 color: var(--alc-code-type);
1551}
1552.alc-tok-c {
1553 color: var(--alc-code-comment);
1554 font-style: italic;
1555}
1556.alc-tok-v {
1557 color: var(--alc-code-var);
1558}
1559.alc-tok-n {
1560 color: var(--alc-code-literal);
1561}
1562
1563/* ============================================================
1564 Card / panel utilities — used widely across product pages
1565 ============================================================ */
1566
1567.alc-card {
1568 background: var(--alc-bg-elev-1);
1569 border: 1px solid var(--alc-hairline);
1570 border-radius: 10px;
1571 padding: 18px;
1572}
1573.alc-card--lg {
1574 border-radius: 12px;
1575 padding: 22px;
1576}
1577.alc-card__title {
1578 font-family: var(--alc-font-sans);
1579 font-size: 15px;
1580 font-weight: 600;
1581 color: var(--alc-fg-1);
1582 margin-bottom: 6px;
1583}
1584.alc-card__title--lg {
1585 font-size: 17px;
1586}
1587.alc-card__body {
1588 font-size: 13px;
1589 line-height: 1.55;
1590 color: var(--alc-fg-3);
1591}
1592
1593/* ============================================================
1594 Provider overview cards (/product/providers)
1595 ============================================================ */
1596
1597.provider-overview {
1598 display: grid;
1599 grid-template-columns: repeat(3, minmax(0, 1fr));
1600 gap: 18px;
1601 max-width: 1100px;
1602 margin: 0 auto;
1603}
1604@media (max-width: 980px) {
1605 .provider-overview {
1606 grid-template-columns: 1fr;
1607 }
1608}
1609.provider-overview__card {
1610 background: var(--alc-bg-elev-1);
1611 border: 1px solid var(--alc-hairline);
1612 border-radius: 14px;
1613 padding: 22px;
1614 text-decoration: none;
1615 color: inherit;
1616 display: flex;
1617 flex-direction: column;
1618 gap: 12px;
1619 transition:
1620 border-color 200ms ease,
1621 transform 200ms ease;
1622}
1623.provider-overview__card:hover {
1624 border-color: var(--prov-color);
1625 transform: translateY(-2px);
1626}
1627.provider-overview__card--soon {
1628 background: linear-gradient(
1629 180deg,
1630 var(--alc-bg-elev-1) 0%,
1631 color-mix(in srgb, var(--alc-bg-nav) 60%, transparent) 100%
1632 );
1633}
1634.provider-overview__head {
1635 display: flex;
1636 align-items: center;
1637 gap: 10px;
1638}
1639.provider-overview__name {
1640 font-family: var(--alc-font-serif);
1641 font-size: 22px;
1642 font-weight: 500;
1643 color: var(--alc-fg-1);
1644}
1645.provider-overview__badge {
1646 margin-left: auto;
1647 font-family: var(--alc-font-mono);
1648 font-size: 9.5px;
1649 font-weight: 700;
1650 letter-spacing: 0.14em;
1651 text-transform: uppercase;
1652 color: var(--prov-color);
1653 background: color-mix(in srgb, var(--prov-color) 14%, transparent);
1654 padding: 2px 7px;
1655 border-radius: 4px;
1656}
1657.provider-overview__body {
1658 font-size: 13.5px;
1659 line-height: 1.55;
1660 color: var(--alc-fg-2);
1661 margin: 0;
1662 flex: 1;
1663}
1664.provider-overview__body code {
1665 font-family: var(--alc-font-mono);
1666 font-size: 0.92em;
1667 color: var(--alc-accent-deep);
1668 background: rgba(184, 138, 74, 0.1);
1669 padding: 0 4px;
1670 border-radius: 3px;
1671}
1672.provider-overview__cta {
1673 font-family: var(--alc-font-mono);
1674 font-size: 12px;
1675 color: var(--prov-color);
1676 margin-top: 4px;
1677}
1678
1679/* ============================================================
1680 IAM action table (/product/providers/aws)
1681 ============================================================ */
1682
1683.iam-table {
1684 width: 100%;
1685 border-collapse: collapse;
1686 background: var(--alc-bg-elev-1);
1687 border: 1px solid var(--alc-hairline);
1688 border-radius: 10px;
1689 overflow: hidden;
1690 font-family: var(--alc-font-mono);
1691 font-size: 12.5px;
1692}
1693.iam-table th {
1694 text-align: left;
1695 padding: 10px 14px;
1696 background: var(--alc-bg-nav);
1697 color: var(--alc-fg-2);
1698 font-weight: 600;
1699 font-size: 11px;
1700 letter-spacing: 0.08em;
1701 text-transform: uppercase;
1702 border-bottom: 1px solid var(--alc-hairline);
1703}
1704.iam-table td {
1705 padding: 9px 14px;
1706 border-bottom: 1px solid var(--alc-hairline);
1707 color: var(--alc-fg-2);
1708}
1709.iam-table tr:last-child td {
1710 border-bottom: none;
1711}
1712.iam-table code {
1713 font-family: var(--alc-font-mono);
1714 font-size: 12px;
1715 color: var(--alc-fg-1);
1716}
1717.iam-table td:nth-child(2) code {
1718 color: #ff9900;
1719}
1720
1721/* ============================================================
1722 CI walkthrough steps (/product/cicd)
1723 ============================================================ */
1724
1725.ci-steps {
1726 list-style: none;
1727 margin: 0 auto;
1728 padding: 0;
1729 max-width: 820px;
1730 display: flex;
1731 flex-direction: column;
1732 gap: 14px;
1733}
1734.ci-step {
1735 display: grid;
1736 grid-template-columns: 36px 1fr;
1737 gap: 16px;
1738 align-items: flex-start;
1739 background: var(--alc-bg-elev-1);
1740 border: 1px solid var(--alc-hairline);
1741 border-radius: 10px;
1742 padding: 16px 18px;
1743}
1744.ci-step__num {
1745 width: 28px;
1746 height: 28px;
1747 border-radius: 50%;
1748 background: var(--alc-accent-deep);
1749 color: var(--alc-bg-elev-1);
1750 display: inline-flex;
1751 align-items: center;
1752 justify-content: center;
1753 font-family: var(--alc-font-mono);
1754 font-size: 12px;
1755 font-weight: 700;
1756}
1757.ci-step__title {
1758 font-family: var(--alc-font-sans);
1759 font-size: 15px;
1760 font-weight: 600;
1761 color: var(--alc-fg-1);
1762 margin-bottom: 2px;
1763}
1764.ci-step__body {
1765 margin: 0;
1766 font-size: 13.5px;
1767 color: var(--alc-fg-2);
1768 line-height: 1.55;
1769}
1770
1771/* GitHub-styled comment mock (/product/cicd) */
1772.gh-mock {
1773 max-width: 720px;
1774 margin: 0 auto;
1775 background: var(--alc-bg-elev-1);
1776 border: 1px solid var(--alc-hairline);
1777 border-radius: 10px;
1778 overflow: hidden;
1779 box-shadow: var(--alc-shadow-sm);
1780}
1781.gh-mock__head {
1782 display: flex;
1783 align-items: center;
1784 gap: 10px;
1785 padding: 10px 14px;
1786 border-bottom: 1px solid var(--alc-hairline);
1787 background: var(--alc-bg-nav);
1788}
1789.gh-mock__avatar {
1790 width: 28px;
1791 height: 28px;
1792 border-radius: 50%;
1793 background: var(--alc-accent-deep);
1794 color: var(--alc-bg-elev-1);
1795 display: inline-flex;
1796 align-items: center;
1797 justify-content: center;
1798 font-family: var(--alc-font-mono);
1799 font-size: 13px;
1800 font-weight: 700;
1801}
1802.gh-mock__author {
1803 display: flex;
1804 align-items: center;
1805 gap: 6px;
1806 font-size: 13px;
1807 color: var(--alc-fg-2);
1808}
1809.gh-mock__author strong {
1810 color: var(--alc-fg-1);
1811}
1812.gh-mock__bot-tag {
1813 font-family: var(--alc-font-mono);
1814 font-size: 9.5px;
1815 font-weight: 700;
1816 color: var(--alc-fg-3);
1817 border: 1px solid var(--alc-hairline);
1818 border-radius: 4px;
1819 padding: 1px 6px;
1820 background: var(--alc-bg);
1821}
1822.gh-mock__meta {
1823 font-size: 11.5px;
1824 color: var(--alc-fg-3);
1825 margin-left: 4px;
1826}
1827.gh-mock__body {
1828 padding: 16px 18px;
1829}
1830.gh-mock__h3 {
1831 font-family: var(--alc-font-sans);
1832 font-size: 16px;
1833 font-weight: 600;
1834 color: var(--alc-fg-1);
1835 margin: 0 0 10px;
1836}
1837.gh-mock__p {
1838 margin: 6px 0;
1839 font-size: 13.5px;
1840 color: var(--alc-fg-2);
1841}
1842.gh-mock__url {
1843 color: var(--alc-accent-deep);
1844 text-decoration: underline;
1845 font-family: var(--alc-font-mono);
1846 font-size: 12.5px;
1847}
1848.gh-mock__code {
1849 font-family: var(--alc-font-mono);
1850 font-size: 12px;
1851 color: var(--alc-fg-1);
1852 background: var(--alc-bg);
1853 padding: 1px 5px;
1854 border-radius: 3px;
1855}
1856.gh-mock__hr {
1857 border: none;
1858 border-top: 1px solid var(--alc-hairline);
1859 margin: 12px 0;
1860}
1861.gh-mock__small {
1862 color: var(--alc-fg-3);
1863 font-size: 12px;
1864 margin: 0;
1865}
1866
1867/* ============================================================
1868 OTel destination cards (/product/observability)
1869 ============================================================ */
1870
1871.otel-card {
1872 background: var(--alc-bg-elev-1);
1873 border: 1px solid var(--alc-hairline);
1874 border-left: 3px solid var(--c);
1875 border-radius: 8px;
1876 padding: 12px 14px;
1877 display: flex;
1878 flex-direction: column;
1879 gap: 4px;
1880}
1881.otel-card__name {
1882 font-family: var(--alc-font-sans);
1883 font-size: 13.5px;
1884 font-weight: 600;
1885 color: var(--alc-fg-1);
1886}
1887.otel-card__sub {
1888 font-family: var(--alc-font-mono);
1889 font-size: 11px;
1890 color: var(--alc-fg-3);
1891}
1892@media (max-width: 760px) {
1893 .otel-card {
1894 font-size: 12px;
1895 }
1896}
1897
1898/* ============================================================
1899 Operational readiness — code-pair illustration
1900 ============================================================ */
1901
1902.alc-ops-col {
1903 display: flex;
1904 flex-direction: column;
1905 gap: 10px;
1906 min-width: 0;
1907}
1908.alc-ops-caption {
1909 font-size: 13.5px;
1910 line-height: 1.55;
1911 color: var(--alc-fg-2);
1912 margin: 2px 2px 0;
1913}
1914.alc-ops-caption strong {
1915 color: var(--alc-fg-1);
1916 font-weight: 600;
1917}
1918
1919/* ============================================================
1920 Hero (home page)
1921 ============================================================ */
1922
1923.alc-hero {
1924 position: relative;
1925 isolation: isolate;
1926}
1927/* Aged-paper plate behind the entire hero. Two layers of SVG fractal
1928 noise — a fine fiber grain plus a large-scale foxing/aging blotch
1929 pattern — combine to read as old printed paper rather than a uniform
1930 texture. No directional banding (which would look like slats). */
1931/* Faint paper-fiber grain behind the hero. Single layer of fine SVG
1932 fractal noise, multiply-blended into the parchment background and
1933 feathered with a vignette so it never reads as a hard plate. */
1934.alc-hero::before {
1935 content: "";
1936 position: absolute;
1937 inset: 0;
1938 z-index: -1;
1939 pointer-events: none;
1940 opacity: 0.28;
1941 mix-blend-mode: multiply;
1942 background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='280' height='280'><filter id='g'><feTurbulence type='fractalNoise' baseFrequency='1.3' numOctaves='2' seed='6' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0.30 0 0 0 0 0.22 0 0 0 0 0.13 0 0 0 0.5 0'/></filter><rect width='100%' height='100%' filter='url(%23g)'/></svg>");
1943 background-size: 280px 280px;
1944 -webkit-mask-image: radial-gradient(
1945 ellipse 100% 95% at 50% 45%,
1946 #000 55%,
1947 transparent 100%
1948 );
1949 mask-image: radial-gradient(
1950 ellipse 100% 95% at 50% 45%,
1951 #000 55%,
1952 transparent 100%
1953 );
1954}
1955/* In dark mode the brown noise multiplied onto the dark page just turns
1956 to mud. Flip to `screen` so the same noise pattern adds a faint warm
1957 highlight grain instead of subtracting into black. */
1958[data-theme="dark"] .alc-hero::before {
1959 mix-blend-mode: screen;
1960 opacity: 0.16;
1961}
1962/* Parchment "halo" between the animation canvas and the hero text.
1963 Solid parchment at the center (where the headline + subtitle live)
1964 so the animation never competes with type, fading to transparent
1965 well before the edges so the corners of the canvas stay visible.
1966 z-index 0 + source order (rendered after the canvas) keeps it
1967 above the canvas (z:0) and below the content (z:1). */
1968.alc-hero::after {
1969 content: "";
1970 position: absolute;
1971 inset: 0;
1972 z-index: 0;
1973 pointer-events: none;
1974 /* The halo's job is to fade the page color *over* the canvas animation
1975 so the headline reads cleanly. Anchored to `--alc-bg` so it matches
1976 whatever theme is active. */
1977 background: radial-gradient(
1978 ellipse 55% 50% at 50% 52%,
1979 color-mix(in srgb, var(--alc-bg) 92%, transparent) 0%,
1980 color-mix(in srgb, var(--alc-bg) 78%, transparent) 30%,
1981 color-mix(in srgb, var(--alc-bg) 40%, transparent) 60%,
1982 transparent 100%
1983 );
1984}
1985
1986/* Animated 3D cubic-coordinate tunnel behind the hero, rendered to
1987 <canvas>. Sits above the ::before paper grain (z-index: -1) and below
1988 the ::after parchment halo + content layer. */
1989.alc-hero__bg-graph {
1990 position: absolute;
1991 inset: 0;
1992 width: 100%;
1993 height: 100%;
1994 z-index: 0;
1995 pointer-events: none;
1996 opacity: 0.9;
1997 mix-blend-mode: multiply;
1998 color: var(--alc-fg-1);
1999 /* Vanishing-point coordinates pushed in from JS once it has measured
2000 the Yantra mark. Defaults are the canvas geometric center, so the
2001 mask still looks reasonable before the script runs. */
2002 --alc-bg-cx: 50%;
2003 --alc-bg-cy: 50%;
2004 /* Feather around the vanishing point so the animation appears to
2005 emanate from the bindu and fades into the parchment at the edges. */
2006 -webkit-mask-image: radial-gradient(
2007 ellipse 95% 90% at var(--alc-bg-cx) var(--alc-bg-cy),
2008 #000 60%,
2009 transparent 100%
2010 );
2011 mask-image: radial-gradient(
2012 ellipse 95% 90% at var(--alc-bg-cx) var(--alc-bg-cy),
2013 #000 60%,
2014 transparent 100%
2015 );
2016}
2017/* In dark mode `multiply` collapses the strokes into the page (cream × dark
2018 walnut ≈ dark walnut). Flip to `screen` so the same stroke reads as a
2019 light highlight on the dark page. Color is bumped to pure white and
2020 opacity raised so the screen-blended markings sit a notch above
2021 light-mode visibility — they otherwise read as muted warm cream. */
2022[data-theme="dark"] .alc-hero__bg-graph {
2023 mix-blend-mode: screen;
2024 color: #ffffff;
2025 opacity: 1;
2026 /* Strokes are drawn at low alpha by the JS (cap ~0.32). Boost the
2027 compositing brightness so they read clearly above the dark page. */
2028 filter: brightness(3.6);
2029}
2030/* On phones the hero canvas takes up a much larger fraction of the
2031 viewport than on desktop, so the same brightness multiplier plus
2032 wide mask makes the mandala bloom over the headline / subtitle and
2033 reads as harsher than the dark-mode desktop view. Pull the brightness
2034 back, drop opacity, and tighten the mask so strokes feather out well
2035 before they reach the type. */
2036@media (max-width: 640px) {
2037 [data-theme="dark"] .alc-hero__bg-graph {
2038 filter: brightness(2.2);
2039 opacity: 0.75;
2040 -webkit-mask-image: radial-gradient(
2041 ellipse 80% 70% at var(--alc-bg-cx) var(--alc-bg-cy),
2042 #000 35%,
2043 transparent 100%
2044 );
2045 mask-image: radial-gradient(
2046 ellipse 80% 70% at var(--alc-bg-cx) var(--alc-bg-cy),
2047 #000 35%,
2048 transparent 100%
2049 );
2050 }
2051}
2052.alc-hero__inner {
2053 position: relative;
2054 z-index: 1;
2055 text-align: center;
2056 max-width: 880px;
2057 margin: 0 auto 16px;
2058}
2059/* Centered alchemical glyph above the title — the "title-page mark"
2060 in the spirit of an engraved frontispiece. */
2061.alc-hero__mark {
2062 display: flex;
2063 justify-content: center;
2064 margin: 0 auto 18px;
2065}
2066.alc-hero__mark svg {
2067 display: block;
2068}
2069.alc-hero__title {
2070 font-family: var(--alc-font-serif);
2071 font-weight: 500;
2072 font-size: clamp(40px, 8.4vw, 72px);
2073 line-height: 1.04;
2074 letter-spacing: -0.02em;
2075 margin: 18px 0 0;
2076 color: var(--alc-fg-1);
2077}
2078.alc-hero__subtitle {
2079 font-family: var(--alc-font-serif);
2080 font-weight: 400;
2081 font-size: clamp(18px, 3.4vw, 30px);
2082 line-height: 1.25;
2083 letter-spacing: -0.005em;
2084 margin: 8px auto 32px;
2085 color: var(--alc-fg-2);
2086 max-width: 780px;
2087}
2088.alc-hero__cta {
2089 display: flex;
2090 gap: 10px;
2091 justify-content: center;
2092 flex-wrap: wrap;
2093}
2094
2095/* ============================================================
2096 Responsive overrides for home page sections
2097 ============================================================ */
2098
2099/* Reduce side gutters on small phones. Inline padding on <Section>
2100 uses shorthand, so we override via a more-specific selector. */
2101@media (max-width: 640px) {
2102 section.alc-section {
2103 padding-left: 20px !important;
2104 padding-right: 20px !important;
2105 }
2106}
2107@media (max-width: 480px) {
2108 section.alc-section {
2109 padding-left: 16px !important;
2110 padding-right: 16px !important;
2111 }
2112}
2113
2114/* Fluid section heading */
2115.alc-h2 {
2116 font-size: clamp(26px, 4.8vw, 34px);
2117}
2118/* MDX wraps loose text fragments inside JSX headings in <p> tags
2119 (e.g. the outro CTA's split "Paste this … to get started" h2 ends
2120 up as `<p>…</p><span><p>…</p></span><p>.</p>`). The UA's default
2121 1em block margin on those <p>s opens up a big gap between the two
2122 wrapped lines. Flatten them back to inline so the heading reads as
2123 one piece of text. */
2124.alc-h2 p {
2125 display: inline;
2126 margin: 0;
2127}
2128/* Prefix ornament on a centered CTA heading sits ABOVE the text as a
2129 printer's mark, not inline next to the first word. (The previous
2130 behavior — where the ornament happened to land on its own line —
2131 was an accidental side-effect of UA <p> margins inside the h2 that
2132 we just collapsed.) */
2133.alc-cta .alc-h2 > .alc-orn--prefix {
2134 display: block;
2135 width: 1.4em;
2136 height: 1.4em;
2137 margin: 0 auto 14px;
2138}
2139
2140/* Hero-scale serif statement used in place of an .alc-h2 + small lede
2141 when a section's value-prop reads better as one big sentence. */
2142.alc-section-statement {
2143 font-family: var(--alc-font-serif);
2144 font-weight: 400;
2145 font-size: clamp(22px, 3.6vw, 34px);
2146 line-height: 1.25;
2147 letter-spacing: -0.005em;
2148 color: var(--alc-fg-1);
2149 max-width: 820px;
2150 margin: 12px auto 0;
2151}
2152
2153/* Sub-section heading inside a section (e.g. Effect-pilled / async fetch
2154 modes inside the bindings-iam section). */
2155.alc-h3 {
2156 font-family: var(--alc-font-serif);
2157 font-weight: 500;
2158 font-size: clamp(20px, 2.6vw, 24px);
2159 line-height: 1.2;
2160 letter-spacing: -0.01em;
2161 color: var(--alc-fg-1);
2162 margin: 6px 0 0;
2163}
2164
2165/* ============================================================
2166 Modes stack — used inside the "Type IAM + env vars" section
2167 to present the Effect-pilled (recommended) and async-fetch
2168 (escape hatch) sub-sections one above the other. The escape
2169 hatch is visually softened so the recommended path leads.
2170 ============================================================ */
2171
2172.alc-modes {
2173 display: flex;
2174 flex-direction: column;
2175 gap: 56px;
2176 max-width: 1100px;
2177 margin: 0 auto;
2178}
2179.alc-mode {
2180 display: grid;
2181 grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
2182 gap: 28px;
2183 align-items: start;
2184}
2185.alc-mode__head {
2186 display: flex;
2187 flex-direction: column;
2188 gap: 10px;
2189 min-width: 0;
2190 padding-top: 4px;
2191}
2192.alc-mode__lede {
2193 margin: 0;
2194 font-size: 14.5px;
2195 line-height: 1.6;
2196 color: var(--alc-fg-2);
2197}
2198.alc-mode__lede code {
2199 font-family: var(--alc-font-mono);
2200 font-size: 0.92em;
2201 color: var(--alc-accent-deep);
2202 background: rgba(184, 138, 74, 0.1);
2203 padding: 0 4px;
2204 border-radius: 3px;
2205}
2206/* The escape-hatch mode keeps a 2-up code split inside the right column,
2207 so on desktop we let it span the full row instead of competing with
2208 the head column. Keeps reading order: title → details → 2 code blocks. */
2209.alc-mode--escape {
2210 grid-template-columns: minmax(0, 1fr);
2211 gap: 18px;
2212}
2213.alc-mode--escape .alc-mode__head {
2214 text-align: center;
2215 align-items: center;
2216 max-width: 760px;
2217 margin: 0 auto;
2218}
2219.alc-mode--escape .alc-mode__lede {
2220 text-align: center;
2221}
2222@media (max-width: 880px) {
2223 .alc-mode {
2224 grid-template-columns: minmax(0, 1fr);
2225 gap: 16px;
2226 }
2227 .alc-modes {
2228 gap: 44px;
2229 }
2230}
2231
2232/* ============================================================
2233 Dev terminal stage (Hot reload section). Single, centered
2234 terminal — narrower than full-width so it doesn't sprawl.
2235 ============================================================ */
2236.alc-dev-stage {
2237 max-width: 880px;
2238 margin: 0 auto;
2239}
2240
2241/* ============================================================
2242 Browser hot-reload demo (Hot reload section).
2243
2244 Desktop: two columns — a pseudo browser rendering a sample
2245 app on the left, the alchemy dev terminal on the right.
2246 They are driven by the same state machine so an edit in the
2247 terminal causes the page to reload.
2248
2249 Mobile (<= 760px): the browser preview is hidden and only the
2250 terminal is shown — the rendered app is too small to read on
2251 phones, but the terminal narrative still lands.
2252 ============================================================ */
2253.bhr-stage {
2254 display: grid;
2255 grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
2256 gap: 18px;
2257 align-items: stretch;
2258 max-width: 1180px;
2259 margin: 0 auto;
2260}
2261.bhr-stage > * {
2262 min-width: 0;
2263}
2264.bhr-term {
2265 display: flex;
2266 min-width: 0;
2267}
2268.bhr-term > .alc-term {
2269 flex: 1;
2270}
2271@media (max-width: 760px) {
2272 .bhr-stage {
2273 grid-template-columns: minmax(0, 1fr);
2274 }
2275 .bhr-stage > .bhr-browser {
2276 display: none;
2277 }
2278}
2279
2280/* Pseudo browser chrome. */
2281.bhr-browser {
2282 display: flex;
2283 flex-direction: column;
2284 background: var(--alc-bg-elev-1);
2285 border: 1px solid var(--alc-hairline-2);
2286 border-radius: 12px;
2287 overflow: hidden;
2288 box-shadow:
2289 0 1px 0 rgba(42, 38, 32, 0.04),
2290 0 8px 20px -10px rgba(42, 38, 32, 0.18),
2291 0 24px 48px -24px rgba(42, 38, 32, 0.22);
2292 min-height: 360px;
2293}
2294.bhr-browser__header {
2295 display: flex;
2296 align-items: center;
2297 gap: 8px;
2298 padding: 10px 12px 10px 14px;
2299 background: var(--alc-bg-nav);
2300 border-bottom: 1px solid var(--alc-hairline);
2301}
2302.bhr-browser__nav {
2303 display: flex;
2304 align-items: center;
2305 gap: 2px;
2306 margin-left: 6px;
2307 color: var(--alc-fg-3);
2308 font-size: 14px;
2309 line-height: 1;
2310}
2311.bhr-browser__navbtn {
2312 width: 22px;
2313 height: 22px;
2314 display: inline-flex;
2315 align-items: center;
2316 justify-content: center;
2317 border-radius: 5px;
2318 font-family: var(--alc-font-mono);
2319 user-select: none;
2320}
2321.bhr-browser__navbtn:hover {
2322 background: var(--alc-bg-elev-2);
2323}
2324.bhr-browser__reload.is-spinning {
2325 animation: bhr-spin 700ms linear infinite;
2326 color: var(--alc-accent-deep);
2327}
2328@keyframes bhr-spin {
2329 to {
2330 transform: rotate(360deg);
2331 }
2332}
2333@media (prefers-reduced-motion: reduce) {
2334 .bhr-browser__reload.is-spinning {
2335 animation: none;
2336 }
2337}
2338.bhr-browser__url {
2339 flex: 1;
2340 display: flex;
2341 align-items: center;
2342 gap: 6px;
2343 padding: 5px 12px;
2344 background: var(--alc-bg-elev-2);
2345 border: 1px solid var(--alc-hairline);
2346 border-radius: 999px;
2347 font-family: var(--alc-font-mono);
2348 font-size: 12px;
2349 color: var(--alc-fg-2);
2350 min-width: 0;
2351}
2352.bhr-browser__lock {
2353 color: var(--alc-success);
2354 font-size: 8px;
2355 line-height: 1;
2356}
2357.bhr-browser__urlhost {
2358 color: var(--alc-fg-1);
2359 font-weight: 500;
2360}
2361.bhr-browser__urlmuted {
2362 color: var(--alc-fg-3);
2363}
2364.bhr-browser__hmr {
2365 display: inline-flex;
2366 align-items: center;
2367 gap: 5px;
2368 font-size: 10px;
2369 letter-spacing: 0.1em;
2370 color: var(--alc-accent-deep);
2371 font-weight: 600;
2372}
2373.bhr-browser__hmrdot {
2374 width: 6px;
2375 height: 6px;
2376 border-radius: 50%;
2377 background: var(--alc-accent-bright);
2378 box-shadow: 0 0 0 3px var(--alc-accent-12);
2379 animation: bhr-pulse 1800ms ease-in-out infinite;
2380}
2381@keyframes bhr-pulse {
2382 0%,
2383 100% {
2384 opacity: 1;
2385 }
2386 50% {
2387 opacity: 0.35;
2388 }
2389}
2390@media (prefers-reduced-motion: reduce) {
2391 .bhr-browser__hmrdot {
2392 animation: none;
2393 }
2394}
2395
2396.bhr-browser__body {
2397 position: relative;
2398 flex: 1;
2399 background: var(--alc-bg);
2400 padding: 22px 24px 26px;
2401 overflow: hidden;
2402}
2403
2404/* Indeterminate top-progress bar shown while the worker rebuilds. */
2405.bhr-browser__progress {
2406 position: absolute;
2407 top: 0;
2408 left: 0;
2409 height: 2px;
2410 width: 40%;
2411 background: linear-gradient(
2412 90deg,
2413 transparent,
2414 var(--alc-accent-bright),
2415 transparent
2416 );
2417 animation: bhr-progress 900ms ease-in-out infinite;
2418}
2419@keyframes bhr-progress {
2420 0% {
2421 transform: translateX(-100%);
2422 }
2423 100% {
2424 transform: translateX(350%);
2425 }
2426}
2427@media (prefers-reduced-motion: reduce) {
2428 .bhr-browser__progress {
2429 animation: none;
2430 opacity: 0.4;
2431 }
2432}
2433
2434/* Sample "rendered app" inside the browser. */
2435.bhr-app {
2436 display: flex;
2437 flex-direction: column;
2438 gap: 16px;
2439 animation: bhr-fade-in 280ms ease;
2440}
2441@keyframes bhr-fade-in {
2442 from {
2443 opacity: 0;
2444 transform: translateY(4px);
2445 }
2446 to {
2447 opacity: 1;
2448 transform: translateY(0);
2449 }
2450}
2451@media (prefers-reduced-motion: reduce) {
2452 .bhr-app {
2453 animation: none;
2454 }
2455}
2456.bhr-app__header {
2457 display: flex;
2458 align-items: flex-end;
2459 justify-content: space-between;
2460 gap: 12px;
2461}
2462.bhr-app__eyebrow {
2463 font-family: var(--alc-font-mono);
2464 font-size: 10px;
2465 letter-spacing: 0.14em;
2466 text-transform: uppercase;
2467 color: var(--alc-fg-3);
2468 margin-bottom: 4px;
2469}
2470.bhr-app__title {
2471 margin: 0;
2472 font-family: var(--alc-font-serif, var(--alc-font-sans));
2473 font-size: 22px;
2474 line-height: 1.15;
2475 color: var(--alc-fg-1);
2476 font-weight: 600;
2477 letter-spacing: -0.01em;
2478}
2479.bhr-app__btn {
2480 appearance: none;
2481 border: 1px solid var(--alc-accent-deep);
2482 background: var(--alc-accent-deep);
2483 color: var(--alc-fg-on-accent);
2484 padding: 6px 12px;
2485 border-radius: 6px;
2486 font-family: var(--alc-font-sans);
2487 font-size: 12px;
2488 font-weight: 600;
2489 cursor: default;
2490 animation: bhr-pop 320ms ease;
2491}
2492@keyframes bhr-pop {
2493 from {
2494 opacity: 0;
2495 transform: scale(0.92);
2496 }
2497 to {
2498 opacity: 1;
2499 transform: scale(1);
2500 }
2501}
2502.bhr-app__grid {
2503 display: grid;
2504 grid-template-columns: repeat(4, minmax(0, 1fr));
2505 gap: 10px;
2506}
2507.bhr-tile {
2508 display: flex;
2509 flex-direction: column;
2510 gap: 6px;
2511}
2512.bhr-tile__img {
2513 aspect-ratio: 1 / 1;
2514 border-radius: 8px;
2515 background:
2516 linear-gradient(135deg, var(--alc-accent-soft), var(--alc-bg-sunk)),
2517 var(--alc-bg-elev-1);
2518 border: 1px solid var(--alc-hairline);
2519}
2520.bhr-tile:nth-child(2) .bhr-tile__img {
2521 background: linear-gradient(135deg, #d4b888, var(--alc-bg-sunk));
2522}
2523.bhr-tile:nth-child(3) .bhr-tile__img {
2524 background: linear-gradient(
2525 135deg,
2526 var(--alc-accent-warm),
2527 var(--alc-accent-soft)
2528 );
2529}
2530.bhr-tile:nth-child(4) .bhr-tile__img {
2531 background: linear-gradient(135deg, #c89a6a, var(--alc-accent-soft));
2532}
2533.bhr-tile__label {
2534 font-family: var(--alc-font-mono);
2535 font-size: 10.5px;
2536 color: var(--alc-fg-3);
2537 text-align: center;
2538}
2539.bhr-tile--ghost {
2540 height: 70px;
2541 background: var(--alc-bg-sunk);
2542 border: 1px dashed var(--alc-hairline-2);
2543 border-radius: 8px;
2544 opacity: 0.5;
2545}
2546
2547.bhr-app__footer {
2548 display: flex;
2549 flex-wrap: wrap;
2550 gap: 6px;
2551 margin-top: 4px;
2552 animation: bhr-fade-in 320ms ease;
2553}
2554.bhr-app__chip {
2555 font-family: var(--alc-font-mono);
2556 font-size: 10.5px;
2557 color: var(--alc-fg-2);
2558 background: var(--alc-bg-elev-1);
2559 border: 1px solid var(--alc-hairline);
2560 padding: 3px 8px;
2561 border-radius: 999px;
2562}
2563.bhr-app__chip strong {
2564 color: var(--alc-accent-deep);
2565 font-weight: 600;
2566}
2567
2568.bhr-app--boot .bhr-app__skeleton {
2569 height: 22px;
2570 width: 40%;
2571 border-radius: 6px;
2572 background: linear-gradient(
2573 90deg,
2574 var(--alc-bg-sunk),
2575 var(--alc-bg-elev-1),
2576 var(--alc-bg-sunk)
2577 );
2578 background-size: 200% 100%;
2579 animation: bhr-shimmer 1400ms linear infinite;
2580}
2581.bhr-app--boot .bhr-app__skeleton--sm {
2582 height: 12px;
2583 width: 25%;
2584 margin-top: 8px;
2585}
2586@keyframes bhr-shimmer {
2587 to {
2588 background-position: -200% 0;
2589 }
2590}
2591@media (prefers-reduced-motion: reduce) {
2592 .bhr-app--boot .bhr-app__skeleton {
2593 animation: none;
2594 }
2595}
2596
2597/* Two-column code+illustration splits */
2598.alc-split-2 {
2599 display: grid;
2600 grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
2601 gap: 24px;
2602 align-items: start;
2603 max-width: 1100px;
2604 margin: 0 auto;
2605}
2606.alc-split-2 > * {
2607 min-width: 0;
2608}
2609.alc-split-2--wide-left {
2610 grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
2611}
2612@media (max-width: 880px) {
2613 .alc-split-2,
2614 .alc-split-2--wide-left {
2615 grid-template-columns: minmax(0, 1fr);
2616 gap: 18px;
2617 }
2618}
2619
2620/* Three-up cards */
2621.alc-cards-3 {
2622 display: grid;
2623 grid-template-columns: repeat(3, minmax(0, 1fr));
2624 gap: 14px;
2625 max-width: 1080px;
2626 margin: 32px auto 0;
2627}
2628.alc-cards-3 > * {
2629 min-width: 0;
2630}
2631@media (max-width: 880px) {
2632 .alc-cards-3 {
2633 grid-template-columns: repeat(2, minmax(0, 1fr));
2634 }
2635}
2636@media (max-width: 560px) {
2637 .alc-cards-3 {
2638 display: none;
2639 }
2640}
2641
2642/* Two-up small cards (e.g. OTel destinations) */
2643.alc-cards-2 {
2644 display: grid;
2645 grid-template-columns: repeat(2, minmax(0, 1fr));
2646 gap: 10px;
2647}
2648.alc-cards-2 > * {
2649 min-width: 0;
2650}
2651@media (max-width: 380px) {
2652 .alc-cards-2 {
2653 grid-template-columns: minmax(0, 1fr);
2654 }
2655}
2656@media (max-width: 560px) {
2657 .alc-cards-2 {
2658 display: none;
2659 }
2660}
2661
2662/* Inline "stat strip" — a single row of monospace labels separated
2663 by middots. Used in place of card grids when the artifact above
2664 already carries the narrative and we just want a tight caption. */
2665.alc-stat-strip {
2666 display: flex;
2667 flex-wrap: wrap;
2668 align-items: center;
2669 justify-content: center;
2670 gap: 10px 18px;
2671 max-width: 920px;
2672 margin: 24px auto 0;
2673 padding: 12px 18px;
2674 border-top: 1px solid var(--alc-hairline);
2675 border-bottom: 1px solid var(--alc-hairline);
2676 font-family: var(--alc-font-mono);
2677 font-size: 12px;
2678 color: var(--alc-fg-3);
2679 text-align: center;
2680}
2681.alc-stat-strip__item {
2682 display: inline-flex;
2683 align-items: center;
2684 gap: 6px;
2685 white-space: nowrap;
2686}
2687.alc-stat-strip__item strong {
2688 color: var(--alc-fg-1);
2689 font-weight: 600;
2690}
2691.alc-stat-strip__item code {
2692 color: var(--alc-accent-deep);
2693 background: rgba(184, 138, 74, 0.1);
2694 padding: 0 4px;
2695 border-radius: 3px;
2696 font-size: 11.5px;
2697}
2698.alc-stat-strip__sep {
2699 color: var(--alc-hairline-2);
2700}
2701@media (max-width: 560px) {
2702 .alc-stat-strip {
2703 font-size: 11.5px;
2704 padding: 10px 12px;
2705 }
2706 .alc-stat-strip__sep {
2707 display: none;
2708 }
2709}
2710
2711/* Local-dev right-hand card column: fills space at >tablet, then
2712 becomes 2-up on tablet, then a single column on phones. */
2713.alc-card-stack {
2714 display: flex;
2715 flex-direction: column;
2716 gap: 14px;
2717 min-width: 0;
2718}
2719.alc-card-stack > * {
2720 min-width: 0;
2721}
2722@media (max-width: 880px) {
2723 .alc-card-stack {
2724 display: grid;
2725 grid-template-columns: repeat(2, minmax(0, 1fr));
2726 }
2727}
2728@media (max-width: 560px) {
2729 .alc-card-stack {
2730 display: none;
2731 }
2732}
2733
2734/* ============================================================
2735 Bindings -> IAM mobile additions
2736 When the arrows column is hidden (<=980px), each resource card
2737 shows its IAM action inline so the binding -> permission
2738 relationship isn't lost.
2739 ============================================================ */
2740
2741.bindings-iam__resource-iam {
2742 display: none;
2743 font-family: var(--alc-font-mono);
2744 font-size: 10.5px;
2745 color: var(--alc-fg-3);
2746 margin-top: 4px;
2747 white-space: nowrap;
2748 overflow: hidden;
2749 text-overflow: ellipsis;
2750}
2751.bindings-iam__resource-iam[data-stream] {
2752 font-style: italic;
2753}
2754
2755@media (max-width: 980px) {
2756 .bindings-iam__resource-iam {
2757 display: block;
2758 }
2759 .bindings-iam__code .alc-code-block__pre {
2760 font-size: 11.5px;
2761 padding: 14px 14px;
2762 }
2763}
2764
2765/* ============================================================
2766 Outro: copy-prompt-for-coding-agent pill.
2767 ============================================================ */
2768
2769.alc-copy-agent {
2770 position: relative;
2771 max-width: 720px;
2772 margin: 24px auto 0;
2773 background: var(--alc-bg-sunk);
2774 border: 1px solid var(--alc-hairline);
2775 border-radius: 10px;
2776 overflow: hidden;
2777 text-align: left;
2778}
2779.alc-copy-agent__text {
2780 display: block;
2781 /* Reserve space at the right edge so long prompt lines never run
2782 under the floating copy icon. */
2783 padding: 12px 52px 12px 16px;
2784 font-family: var(--alc-font-mono);
2785 font-size: 13.5px;
2786 line-height: 1.5;
2787 color: var(--alc-fg-1);
2788 background: transparent;
2789 border: 0;
2790 white-space: pre-wrap;
2791 overflow-wrap: anywhere;
2792 text-align: left;
2793 max-height: 240px;
2794 overflow-y: auto;
2795}
2796.alc-copy-agent__btn {
2797 position: absolute;
2798 top: 8px;
2799 right: 8px;
2800 display: inline-flex;
2801 align-items: center;
2802 justify-content: center;
2803 width: 32px;
2804 height: 32px;
2805 padding: 0;
2806 background: transparent;
2807 border: 1px solid transparent;
2808 border-radius: 8px;
2809 color: var(--alc-fg-3);
2810 cursor: pointer;
2811 transition:
2812 color 120ms ease,
2813 background 120ms ease,
2814 border-color 120ms ease;
2815}
2816.alc-copy-agent__btn:hover {
2817 color: var(--alc-accent-deep);
2818 background: var(--alc-bg-elev-1);
2819 border-color: var(--alc-hairline-2);
2820}
2821.alc-copy-agent__btn:focus-visible {
2822 outline: 2px solid var(--alc-accent-40);
2823 outline-offset: 2px;
2824}
2825
2826/* ============================================================
2827 Button styles (also defined scoped in Button.astro). Copied
2828 here so React islands can render the same look.
2829 ============================================================ */
2830
2831.alc-btn {
2832 font-family: var(--alc-font-sans);
2833 font-size: 14px;
2834 font-weight: 500;
2835 padding: 10px 18px;
2836 border-radius: 8px;
2837 border: 1px solid transparent;
2838 display: inline-flex;
2839 align-items: center;
2840 gap: 8px;
2841 white-space: nowrap;
2842 cursor: pointer;
2843 text-decoration: none;
2844 transition:
2845 background 120ms var(--alc-ease, cubic-bezier(0.2, 0, 0, 1)),
2846 border-color 120ms var(--alc-ease, cubic-bezier(0.2, 0, 0, 1)),
2847 color 120ms var(--alc-ease, cubic-bezier(0.2, 0, 0, 1));
2848}
2849/* Deep forest instead of var(--alc-accent): mid-green moss cannot reach
2850 the AAA 7:1 ratio with any text color; #3f5a2a gives 7.2:1 against
2851 --alc-fg-on-accent in both themes. */
2852.alc-btn--primary {
2853 background: #3f5a2a;
2854 color: var(--alc-fg-on-accent);
2855}
2856.alc-btn--primary:hover {
2857 background: #324a1e;
2858}
2859.alc-btn--secondary {
2860 background: transparent;
2861 border-color: var(--alc-hairline-3);
2862 color: var(--alc-fg-1);
2863}
2864.alc-btn--secondary:hover {
2865 border-color: var(--alc-accent);
2866 color: var(--alc-accent-deep);
2867}
2868.alc-btn--ghost {
2869 background: transparent;
2870 color: var(--alc-fg-2);
2871}
2872.alc-btn--ghost:hover {
2873 color: var(--alc-accent-deep);
2874}
2875.alc-btn--accent {
2876 background: var(--alc-terracotta);
2877 color: var(--alc-fg-on-accent);
2878}
2879
2880/* ============================================================
2881 Hero CTA — two-up "for humans / for coding agents".
2882 Tight: eyebrow + single content row.
2883 ============================================================ */
2884
2885.hero-cta {
2886 display: grid;
2887 grid-template-columns: 1fr 1fr;
2888 gap: 10px;
2889 max-width: 560px;
2890 margin: 6px auto 0;
2891 text-align: left;
2892}
2893.hero-cta__card {
2894 display: flex;
2895 flex-direction: column;
2896 justify-content: space-between;
2897 gap: 4px;
2898 padding: 10px 14px;
2899 min-width: 0;
2900 border: 1px solid var(--alc-hairline);
2901 border-radius: 10px;
2902 text-decoration: none;
2903 color: inherit;
2904 cursor: pointer;
2905 font-family: var(--alc-font-sans);
2906 text-align: left;
2907 background: var(--alc-bg-sunk);
2908 /* The CTA cards sit directly on the hero mandala, and their tint
2909 fills are translucent so the pattern bleeds through. Blur what
2910 sits behind so the card text stays readable — same approach as
2911 the marketing header. */
2912 backdrop-filter: saturate(140%) blur(8px);
2913 -webkit-backdrop-filter: saturate(140%) blur(8px);
2914 transition:
2915 border-color 140ms ease,
2916 transform 140ms ease;
2917}
2918.hero-cta__card:hover {
2919 transform: translateY(-1px);
2920}
2921/* The card heading is the primary line; the content under it is
2922 supporting detail. */
2923.hero-cta__eyebrow {
2924 display: flex;
2925 align-items: center;
2926 justify-content: space-between;
2927 gap: 8px;
2928 font-size: 13.5px;
2929 font-weight: 700;
2930 letter-spacing: 0.07em;
2931 text-transform: uppercase;
2932 color: var(--alc-fg-1);
2933}
2934.hero-cta__icon {
2935 display: inline-flex;
2936 align-items: center;
2937 color: var(--alc-fg-2);
2938}
2939.hero-cta__title {
2940 display: inline-flex;
2941 align-items: center;
2942 gap: 6px;
2943 font-size: 13px;
2944 font-weight: 500;
2945 color: var(--alc-fg-3);
2946}
2947.hero-cta__card--human {
2948 background: var(--alc-accent-soft);
2949 border-color: var(--alc-accent);
2950}
2951.hero-cta__card--human:hover {
2952 border-color: var(--alc-accent-deep);
2953}
2954.hero-cta__card--agent {
2955 background: var(--alc-terracotta-soft);
2956 border-color: var(--alc-terracotta);
2957}
2958.hero-cta__card--agent:hover {
2959 border-color: var(--alc-terracotta-deep);
2960}
2961.hero-cta__prompt-code {
2962 display: block;
2963 min-width: 0;
2964 max-width: 100%;
2965 font-family: var(--alc-font-mono);
2966 font-size: 11.5px;
2967 line-height: 1.4;
2968 color: var(--alc-fg-2);
2969 background: transparent;
2970 border: 0;
2971 padding: 0;
2972 white-space: nowrap;
2973 overflow: hidden;
2974 text-overflow: ellipsis;
2975}
2976
2977.hero-cta--simple {
2978 display: none;
2979}
2980
2981@media (max-width: 640px) {
2982 .hero-cta--cards {
2983 display: none;
2984 }
2985 .hero-cta--simple {
2986 display: flex;
2987 flex-direction: column;
2988 align-items: center;
2989 gap: 12px;
2990 margin-top: 6px;
2991 }
2992}
2993
2994.hero-cta__buttons {
2995 display: inline-flex;
2996 gap: 10px;
2997 flex-wrap: wrap;
2998 justify-content: center;
2999}
3000.hero-cta__line {
3001 display: inline-flex;
3002 align-items: center;
3003 gap: 10px;
3004 font-size: 13px;
3005 color: var(--alc-fg-3);
3006}
3007.hero-cta__chip {
3008 display: inline-flex;
3009 align-items: center;
3010 gap: 6px;
3011 padding: 5px 10px;
3012 background: var(--alc-bg-sunk);
3013 border: 1px solid var(--alc-hairline);
3014 border-radius: 6px;
3015 font-family: var(--alc-font-mono);
3016 font-size: 12px;
3017 color: var(--alc-fg-1);
3018 cursor: pointer;
3019 transition:
3020 color 120ms ease,
3021 border-color 120ms ease;
3022}
3023.hero-cta__chip:hover {
3024 color: var(--alc-accent-deep);
3025 border-color: var(--alc-accent);
3026}
3027
3028/* ── Landing: "Pick your cloud" cards + integrations chip strip ── */
3029.alc-cloud-cards {
3030 display: grid;
3031 grid-template-columns: repeat(2, minmax(0, 1fr));
3032 gap: 14px;
3033 max-width: 640px;
3034 margin: 0 auto;
3035}
3036@media (max-width: 560px) {
3037 .alc-cloud-cards {
3038 grid-template-columns: 1fr;
3039 }
3040}
3041.alc-cloud-card {
3042 display: flex;
3043 flex-direction: column;
3044 gap: 6px;
3045 padding: 18px 20px;
3046 background: var(--alc-bg-elev-1);
3047 border: 1px solid var(--alc-hairline);
3048 border-radius: 14px;
3049 text-decoration: none;
3050 color: inherit;
3051 transition:
3052 border-color 200ms ease,
3053 transform 200ms ease;
3054}
3055.alc-cloud-card:hover {
3056 border-color: var(--alc-accent-40);
3057 transform: translateY(-2px);
3058}
3059.alc-cloud-card__title {
3060 display: inline-flex;
3061 align-items: center;
3062 gap: 10px;
3063 font-size: 17px;
3064 font-weight: 600;
3065 color: var(--alc-fg-1);
3066}
3067.alc-cloud-card__title .alc-provider-mark {
3068 flex-shrink: 0;
3069 opacity: 0.9;
3070}
3071.alc-cloud-card__body {
3072 font-size: 13.5px;
3073 line-height: 1.5;
3074 color: var(--alc-fg-2);
3075}
3076.alc-cloud-card__cta {
3077 margin-top: 4px;
3078 font-size: 13.5px;
3079 color: var(--alc-accent-deep);
3080}
3081.alc-cloud-chips {
3082 display: flex;
3083 align-items: center;
3084 justify-content: center;
3085 flex-wrap: wrap;
3086 gap: 8px;
3087 margin-top: 18px;
3088}
3089.alc-cloud-chips__label {
3090 font-size: 13px;
3091 color: var(--alc-fg-4);
3092}
3093.alc-cloud-chip {
3094 font-size: 13px;
3095 color: var(--alc-fg-2);
3096 text-decoration: none;
3097 border: 1px solid var(--alc-hairline-2);
3098 border-radius: 999px;
3099 padding: 3px 12px;
3100 transition:
3101 color 200ms ease,
3102 border-color 200ms ease;
3103}
3104.alc-cloud-chip:hover {
3105 color: var(--alc-accent-deep);
3106 border-color: var(--alc-accent-40);
3107}