@telepath-computer/television 0.1.116 → 0.1.117

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,14 +2,12 @@
2
2
  * Canonical artifact stylesheet — the curated subset of the design system
3
3
  * artifacts inherit at /canonical/v1/styles.css.
4
4
  *
5
- * Includes design-system primitives (reset, fonts, tokens, theme) plus
6
- * bare-tag styling (elements). Excludes app-chrome layers (materials and
7
- * components) since artifacts shouldn't render with panel/dropdown/modal
8
- * surfaces.
5
+ * Includes only the design-system primitives artifacts should inherit by
6
+ * default: reset, fonts, and tokens. Artifact-specific structure and rhythm
7
+ * should be authored explicitly in the artifact HTML so agents can see and
8
+ * control the result instead of relying on hidden bare-tag defaults.
9
9
  *
10
- * Source of truth for what's in v1. Edits here change what artifacts
11
- * inherit; gaps that surface during real authoring (lists, blockquote,
12
- * table, hr) get added to elements.css since they apply to bare tags.
10
+ * Source of truth for what's in v1. Edits here change what artifacts inherit.
13
11
  */
14
12
  *,
15
13
  *::before,
@@ -294,623 +292,6 @@ select {
294
292
 
295
293
 
296
294
 
297
- :root {
298
- --color-bg: var(--neutral-50);
299
- --color-bg-muted: var(--neutral-100);
300
- --color-surface: var(--white);
301
- --color-surface-muted: var(--neutral-100);
302
- --color-interactive: var(--neutral-200);
303
- --color-interactive-hover: var(--neutral-300);
304
-
305
- /* Borders use alpha so the same hairline reads on light, dark, or
306
- image bgs without needing a tone-aware swap. */
307
- --color-border: rgba(0, 0, 0, 0.10);
308
- --color-border-muted: rgba(0, 0, 0, 0.06);
309
-
310
- --color-text: var(--neutral-900);
311
- --color-text-muted: var(--neutral-500);
312
- --color-link: inherit;
313
- --color-focus-ring: var(--neutral-500);
314
- --color-overlay-backdrop: rgb(0 0 0 / 0.5);
315
- --color-highlight: rgb(255 255 255 / 0.5);
316
- --color-primary: var(--blue-500);
317
- --color-danger: var(--red-600);
318
-
319
- color-scheme: light;
320
- }
321
-
322
-
323
-
324
-
325
295
  body {
326
296
  font-family: var(--font-sans);
327
- font-size: var(--text-base);
328
- font-weight: var(--font-weight-body);
329
- line-height: var(--leading-base);
330
- letter-spacing: 0.015em;
331
- color: var(--color-text);
332
- background: var(--color-bg);
333
- -webkit-font-smoothing: antialiased;
334
- -moz-osx-font-smoothing: grayscale;
335
- }
336
-
337
- a {
338
- color: var(--color-link);
339
- text-underline-offset: 0.15em;
340
- text-decoration-thickness: 0.08em;
341
- }
342
-
343
- h1,
344
- h2,
345
- h3,
346
- h4,
347
- h5,
348
- h6 {
349
- font-weight: 600;
350
- color: inherit;
351
- }
352
-
353
- code {
354
- font-family: var(--font-mono);
355
- font-size: 0.9em;
356
- background: var(--color-bg-muted);
357
- padding: var(--space-2) var(--space-4);
358
- border-radius: var(--radius-4);
359
- }
360
-
361
- pre {
362
- font-family: var(--font-mono);
363
- background: var(--color-bg-muted);
364
- padding: var(--space-12);
365
- border-radius: var(--radius-8);
366
- overflow-x: auto;
367
- }
368
-
369
- pre code {
370
- background: none;
371
- padding: 0;
372
- }
373
-
374
- blockquote {
375
- padding-left: var(--space-16);
376
- border-left: 3px solid var(--color-border);
377
- color: var(--color-text-muted);
378
- }
379
-
380
- hr {
381
- border: none;
382
- border-top: 1px solid var(--color-border);
383
- }
384
-
385
- table {
386
- border-collapse: collapse;
387
- }
388
-
389
- th,
390
- td {
391
- padding: var(--space-8) var(--space-12);
392
- border: 1px solid var(--color-border);
393
- text-align: left;
394
- }
395
-
396
- th {
397
- background: var(--color-bg-muted);
398
- font-weight: 600;
399
- }
400
-
401
- /* Recessed text input — same geometry as a button at rest, sunken via a
402
- subtle tint and no drop shadow. Focus deepens the tint one step (more
403
- recessed) and adds a primary-blue ring as the focus signal. Text
404
- inherits its color from the surrounding context so the input reads on
405
- either light or dark surfaces. */
406
- input,
407
- textarea {
408
- border: 0.5px solid var(--tint-300);
409
- border-radius: var(--radius-12);
410
- background: var(--tint-100);
411
- color: inherit;
412
- font: inherit;
413
- box-sizing: border-box;
414
- transition:
415
- background 120ms ease,
416
- border-color 120ms ease,
417
- box-shadow 120ms ease;
418
- }
419
-
420
- /* Single-line input snaps to the `lg` control height — taller than
421
- buttons/segmented controls (`md`) so text-entry fields have visual
422
- presence as the primary affordance in forms. Padding goes
423
- horizontal-only since the explicit height handles vertical centering
424
- via the line-box. */
425
- input {
426
- height: var(--control-height-lg);
427
- padding: 0 12px;
428
- }
429
-
430
- /* Multi-line textarea stays intrinsic — height grows with content (or
431
- max-height on a host) rather than locking to a control unit. */
432
- textarea {
433
- padding: 6px 10px;
434
- resize: none;
435
- }
436
-
437
- input::placeholder,
438
- textarea::placeholder {
439
- color: var(--tint-500);
440
- }
441
-
442
- input:focus,
443
- textarea:focus {
444
- background: color-mix(in srgb, var(--white) var(--alpha-300), transparent);
445
- border-color: var(--color-primary);
446
- outline: none;
447
- box-shadow: 0 0 0 1.5px var(--color-primary);
448
- }
449
-
450
- /* Stacked label + control. Label text is smaller and lighter than body
451
- copy, sits flush with the control. Use as
452
- <label class="field"><span>Name</span><input /></label>. */
453
- label.field {
454
- display: grid;
455
- gap: 4px;
456
- font-size: 13px;
457
- }
458
-
459
- label.field > span {
460
- font-size: 11.5px;
461
- font-weight: 450;
462
- color: var(--tint-800);
463
- }
464
-
465
- /* Universal squircle corners. `corner-shape: squircle` only affects
466
- elements that already declare a non-zero `border-radius`, so applying
467
- to `*` is effectively a no-op everywhere except where corners exist.
468
- Token values in tokens.css bump ~25% inside the same @supports block
469
- to compensate for the perceived tightness difference. */
470
- @supports (corner-shape: squircle) {
471
- * {
472
- corner-shape: squircle;
473
- }
474
- }
475
-
476
- /* Button-only layout — placement of icon + label inside a single
477
- button. Segmented-button doesn't share these (it's a flex row of
478
- children, not a center-aligned label-and-icon stack).
479
- `height: var(--control-height-md)` is explicit so a row of mixed
480
- chrome (text button + icon-only button + segmented-control) lines up
481
- without each variant having to tune its intrinsic content + padding
482
- to match. Padding is purely horizontal — vertical centering is handled
483
- by `align-items: center`. */
484
- button {
485
- display: inline-flex;
486
- align-items: center;
487
- justify-content: center;
488
- gap: var(--space-6);
489
- box-sizing: border-box;
490
- height: var(--control-height-md);
491
- /* 2px extra bottom padding compensates for the visual offset from
492
- font ascender/descender asymmetry — `align-items: center` centers
493
- the line-box but the glyph mass sits below center because the
494
- ascender claims more vertical space than the descender. The
495
- icon-only override resets padding to 0 since icons are already
496
- symmetric. */
497
- padding: 0 14px 2px;
498
- font: inherit;
499
- cursor: default;
500
- }
501
-
502
- /* Default chrome — shared between <button> and <segmented-control> so
503
- the two stay in visual lockstep. Variant overrides (ghost, primary,
504
- danger) and tone-dark / tone-light / disabled cascades live below.
505
- The shared-with-segmented bits are intentional: a segmented control
506
- is a chrome surface that looks like a single button containing two
507
- click targets, so its host adopts the same fill, hairline, radius,
508
- and shadow. */
509
- button,
510
- segmented-control {
511
- background: var(--color-surface);
512
- border: 0.5px solid var(--tint-200);
513
- border-radius: var(--radius-12);
514
- box-shadow: var(--shadow-control);
515
- color: inherit;
516
- }
517
-
518
- button:not([material]):hover:not(:disabled) {
519
- background: color-mix(in srgb, var(--color-surface) 96%, black);
520
- }
521
-
522
- button:not([material]):active:not(:disabled) {
523
- background: color-mix(in srgb, var(--color-surface) 88%, black);
524
- box-shadow: inset 0 1px 2px rgb(0 0 0 / 0.08);
525
- }
526
-
527
- button:focus-visible {
528
- outline: 2px solid var(--color-focus-ring);
529
- outline-offset: 2px;
530
- }
531
-
532
- button[variant="primary"] {
533
- background: var(--color-primary);
534
- border-color: rgb(0 0 0 / 0.18);
535
- color: var(--white);
536
- }
537
-
538
- button[variant="primary"]:hover:not(:disabled) {
539
- background: color-mix(in srgb, var(--color-primary) 92%, black);
540
- }
541
-
542
- button[variant="primary"]:active:not(:disabled) {
543
- background: color-mix(in srgb, var(--color-primary) 82%, black);
544
- box-shadow: inset 0 1px 2px rgb(0 0 0 / 0.18);
545
- }
546
-
547
- button[variant="danger"] {
548
- background: var(--color-danger);
549
- border-color: rgb(0 0 0 / 0.18);
550
- color: var(--white);
551
- }
552
-
553
- button[variant="danger"]:hover:not(:disabled) {
554
- background: color-mix(in srgb, var(--color-danger) 92%, black);
555
- }
556
-
557
- button[variant="danger"]:active:not(:disabled) {
558
- background: color-mix(in srgb, var(--color-danger) 82%, black);
559
- box-shadow: inset 0 1px 2px rgb(0 0 0 / 0.18);
560
- }
561
-
562
- button[variant="ghost"] {
563
- background: transparent;
564
- border-color: transparent;
565
- color: inherit;
566
- box-shadow: none;
567
- }
568
-
569
- /* Ghost is a chromeless overlay — at rest it's invisible and relies on
570
- the surface behind it. The overlay tokens cascade through `tone="dark"`
571
- (set on the button itself by the auto-tone watcher in
572
- `utils/button-tone.ts`, or inherited from a tone-sampled ancestor), so
573
- one rule covers light + dark backdrops.
574
-
575
- Hover/active also bump the backdrop saturation — the same "comes alive"
576
- gesture glass uses. Ghost has no blur or brightness to absorb the
577
- filter, so a much gentler ladder (1.2 / 1.3 / 1.4) reads as the right
578
- weight against ghost's ~8–16% tint overlay. Glass's higher numbers
579
- would punch through too hard here. */
580
- /* Ghost uses currentColor tints directly (auto-flip via tone) rather than
581
- the shared --color-overlay-hover / -active tokens. The shared tokens
582
- read too quietly on ghost's bare surface — bumping ghost a step heavier
583
- (alpha-150 hover, alpha-300 active) gives the hover real presence
584
- without affecting other chrome that uses the overlay tokens. */
585
- button[variant="ghost"]:hover:not(:disabled) {
586
- background: var(--tint-150);
587
- backdrop-filter: saturate(1.2);
588
- -webkit-backdrop-filter: saturate(1.2);
589
- }
590
-
591
- button[variant="ghost"]:active:not(:disabled) {
592
- background: var(--tint-300);
593
- backdrop-filter: saturate(1.4);
594
- -webkit-backdrop-filter: saturate(1.4);
595
- box-shadow: none;
596
297
  }
597
-
598
- /* Pinned-active state for ghost triggers — used while a dropdown
599
- `[aria-expanded="true"]` is open against this button (set automatically
600
- by `dropdown-menu`), while a consumer manually pins `[data-active]`
601
- (e.g. anchored popover), or while the button is `[aria-pressed="true"]`
602
- (toggle/tab in its on state). All three override hover so the button
603
- stays visibly active even as the cursor moves over it. */
604
- button[variant="ghost"][data-active]:not(:disabled),
605
- button[variant="ghost"][data-active]:hover:not(:disabled),
606
- button[variant="ghost"][aria-pressed="true"]:not(:disabled),
607
- button[variant="ghost"][aria-pressed="true"]:hover:not(:disabled),
608
- button[variant="ghost"][aria-expanded="true"]:not(:disabled),
609
- button[variant="ghost"][aria-expanded="true"]:hover:not(:disabled) {
610
- background: var(--color-overlay-active);
611
- backdrop-filter: saturate(1.3);
612
- -webkit-backdrop-filter: saturate(1.3);
613
- box-shadow: none;
614
- }
615
-
616
- /* Glass variant — translucent surface with backdrop blur. Shared between
617
- <button variant="glass"> and <segmented-control variant="glass"> so a
618
- chrome row of buttons + segmented controls reads as one surface
619
- family. Self-contained per-variant chrome (bg + border + shadow + blur
620
- + hover/active overlays) means no fighting with default-button rules
621
- or tone-driven default fills.
622
-
623
- No explicit `color` here — auto-tone (utils/button-tone.ts) writes
624
- `tone="light"` or `tone="dark"` on the element after sampling its
625
- actual backdrop. The materials.css `[tone="…"]` color rules then set
626
- text color on the element directly (specificity 0,1,0), beating the
627
- shared `button { color: inherit }` (0,0,1). An explicit `color:
628
- inherit` here would be 0,1,1 and would defeat the tone-aware color. */
629
- button[variant="glass"],
630
- segmented-control[variant="glass"] {
631
- background: transparent;
632
- border: 0.5px solid color-mix(in srgb, var(--black) var(--alpha-100), transparent);
633
- box-shadow: none;
634
- }
635
-
636
- /* Glass-variant standalone button: backdrop-filter on the host. The
637
- segmented-control variant moves the filter onto each segment so per-
638
- child hover/active saturation works without nested-filter compounding
639
- issues — see segmented-control.css. */
640
- button[variant="glass"] {
641
- backdrop-filter: blur(20px) brightness(0.95) saturate(1.5);
642
- -webkit-backdrop-filter: blur(20px) brightness(0.95) saturate(1.5);
643
- }
644
-
645
- /* `background:` shorthand (not `background-image`) resets background-color
646
- back to transparent — necessary because the default-button hover rule
647
- `button:not([material]):hover` fires on glass too (glass has no
648
- material) at equal specificity and would otherwise paint a 96% white
649
- surface underneath this overlay.
650
-
651
- Hover and active also crank the backdrop saturate filter (1.5 → 1.8 →
652
- 2.2). On a light backdrop, darkening overlays read as visual weight
653
- rather than feedback; the saturation bump is direction-agnostic — the
654
- surface "comes alive" the same way regardless of tone. The overlay
655
- stays as a quieter backstop. */
656
- button[variant="glass"]:hover:not(:disabled) {
657
- background: linear-gradient(var(--color-overlay-hover), var(--color-overlay-hover));
658
- backdrop-filter: blur(20px) brightness(0.95) saturate(1.8);
659
- -webkit-backdrop-filter: blur(20px) brightness(0.95) saturate(1.8);
660
- }
661
-
662
- button[variant="glass"]:active:not(:disabled) {
663
- background: linear-gradient(var(--color-overlay-active), var(--color-overlay-active));
664
- backdrop-filter: blur(20px) brightness(0.95) saturate(2.2);
665
- -webkit-backdrop-filter: blur(20px) brightness(0.95) saturate(2.2);
666
- }
667
-
668
- /* Persistent active state — `aria-pressed="true"` (tab/toggle that is
669
- "currently on") and `aria-expanded="true"` (popover/menu trigger whose
670
- panel is open). Both stay lit through hover so the active overlay isn't
671
- visually masked by the hover overlay when the cursor is over them.
672
- `<ui-popover>` and `<dropdown-menu>` set `aria-expanded` automatically;
673
- tab-style consumers set `aria-pressed`. */
674
- button[variant="glass"][aria-pressed="true"]:not(:disabled),
675
- button[variant="glass"][aria-pressed="true"]:hover:not(:disabled),
676
- button[variant="glass"][aria-expanded="true"]:not(:disabled),
677
- button[variant="glass"][aria-expanded="true"]:hover:not(:disabled) {
678
- background: linear-gradient(var(--color-overlay-active), var(--color-overlay-active));
679
- backdrop-filter: blur(20px) brightness(0.95) saturate(2);
680
- -webkit-backdrop-filter: blur(20px) brightness(0.95) saturate(2);
681
- }
682
-
683
- [tone="dark"] button[variant="glass"],
684
- [tone="dark"] segmented-control[variant="glass"] {
685
- border-color: var(--tint-400);
686
- }
687
-
688
- /* Material composition with controls (option B in the design notes —
689
- contained override rather than refactoring materials.css globally).
690
- Material is a passive-surface primitive: it locks color, draws a
691
- fixed-alpha hairline, and a default-variant `:hover` would replace
692
- its background entirely. These overrides let `<button material="...">`
693
- and `<segmented-control material="...">` compose:
694
-
695
- - `color: inherit` so the tone-aware text cascade still applies
696
- (material sets a fixed `--color-text` which doesn't flip on dark).
697
- - `box-shadow: none` because both materials want a flat surface; the
698
- default control shadow fights glass especially.
699
- - hover/active paint via `background-image` (a flat linear-gradient)
700
- so the material's `background-color` is preserved underneath.
701
- - dark-tone bumps the hairline to `--tint-400` so the rim reads on
702
- dark backdrops (material's locked black-alpha border vanishes
703
- against tone-dark patches). */
704
- button[material],
705
- segmented-control[material] {
706
- color: inherit;
707
- box-shadow: none;
708
- }
709
-
710
- button[material]:hover:not(:disabled) {
711
- background-image: linear-gradient(var(--color-overlay-hover), var(--color-overlay-hover));
712
- }
713
-
714
- button[material]:active:not(:disabled) {
715
- background-image: linear-gradient(var(--color-overlay-active), var(--color-overlay-active));
716
- }
717
-
718
- [tone="dark"] button[material],
719
- [tone="dark"] segmented-control[material] {
720
- border-color: var(--tint-400);
721
- }
722
-
723
- button:disabled {
724
- background: var(--tint-300);
725
- border-color: transparent;
726
- color: var(--tint-700);
727
- box-shadow: none;
728
- }
729
-
730
- /* Ghost buttons stay chromeless when disabled — they have no
731
- resting chrome to "grey out", so the dimmed foreground (inherited
732
- via `color: var(--tint-700)` above) is the entire signal. The
733
- default disabled bg would otherwise paint a tint-300 surface
734
- that fights ghost's transparent baseline. */
735
- button[variant="ghost"]:disabled {
736
- background: transparent;
737
- }
738
-
739
- /* Default-variant button on a dark surface — drop the chromed light fill,
740
- pick up a brighter white-tint than inputs (15% vs 8%) to read as raised
741
- rather than recessed, and replace the ineffective black drop shadow
742
- with a top-edge inset highlight (macOS NSButton-on-dark convention).
743
- `:not([material])` opts the tone-driven default fill OUT when the
744
- element has explicit `material` — material owns the surface in that
745
- case, regardless of tone. */
746
- :where([tone="dark"]) button:not([variant]):not([material]):not(:disabled),
747
- :where([tone="dark"]) button[variant="default"]:not([material]):not(:disabled),
748
- :where([tone="dark"]) segmented-control:not([variant]):not([material]),
749
- :where([tone="dark"]) segmented-control[variant="default"]:not([material]) {
750
- background: var(--tint-200);
751
- border-color: var(--tint-300);
752
- box-shadow: inset 0 0.5px 0 var(--tint-300);
753
- }
754
-
755
- :where([tone="dark"]) button:not([variant]):hover:not(:disabled),
756
- :where([tone="dark"]) button[variant="default"]:hover:not(:disabled) {
757
- background: var(--tint-300);
758
- }
759
-
760
- :where([tone="dark"]) button:not([variant]):active:not(:disabled),
761
- :where([tone="dark"]) button[variant="default"]:active:not(:disabled) {
762
- background: var(--tint-400);
763
- box-shadow: inset 0 1px 2px rgb(0 0 0 / 0.20);
764
- }
765
-
766
- /* Explicit light-tone button rules — restore the chromed white-card
767
- styling when a `tone="light"` ancestor sits inside a `tone="dark"`
768
- one (e.g. a paper popover anchored inside dark chrome). Same
769
- specificity as the dark-tone rules above; source order makes the
770
- closer light-tone scope win for slotted descendants. */
771
- :where([tone="light"]) button:not([variant]):not([material]):not(:disabled),
772
- :where([tone="light"]) button[variant="default"]:not([material]):not(:disabled),
773
- :where([tone="light"]) segmented-control:not([variant]):not([material]),
774
- :where([tone="light"]) segmented-control[variant="default"]:not([material]) {
775
- background: var(--color-surface);
776
- border-color: var(--tint-200);
777
- box-shadow: var(--shadow-control);
778
- }
779
-
780
- :where([tone="light"]) button:not([variant]):hover:not(:disabled) {
781
- background: color-mix(in srgb, var(--color-surface) 96%, black);
782
- }
783
-
784
- :where([tone="light"]) button:not([variant]):active:not(:disabled) {
785
- background: color-mix(in srgb, var(--color-surface) 88%, black);
786
- box-shadow: inset 0 1px 2px rgb(0 0 0 / 0.08);
787
- }
788
-
789
- /* Size opt-in: `size="sm"` swaps to the smaller control-height token.
790
- Same applies to `<segmented-control size="sm">` so the host stretches
791
- children correctly, and to `<button size="sm" icon-only>` so the
792
- square footprint stays at the smaller control unit. The default
793
- (md, 28px) is set on the base `<button>` rule above; only sm needs
794
- an explicit override. */
795
- button[size="sm"],
796
- segmented-control[size="sm"] {
797
- height: var(--control-height-sm);
798
- }
799
-
800
- button[size="sm"][icon-only] {
801
- width: var(--control-height-sm);
802
- }
803
-
804
- button[size="xs"] {
805
- height: var(--control-height-xs);
806
- padding: 0 var(--space-6) 1px;
807
- border-radius: var(--radius-8);
808
- }
809
-
810
- button[size="xs"][icon-only] {
811
- width: var(--control-height-xs);
812
- padding: 0;
813
- }
814
-
815
- /* Square icon-only buttons. Width = control height so the footprint is
816
- square at the same vertical size as a text-button sibling. Chrome is
817
- determined by the variant (default = chromed pill, ghost = chromeless
818
- overlay). */
819
- button[icon-only] {
820
- width: var(--control-height-md);
821
- padding: 0;
822
- }
823
-
824
- [data-ui-icon] {
825
- display: inline-block;
826
- vertical-align: middle;
827
- }
828
-
829
- /* Attribute conventions — see docs/ui.md § Attribute conventions.
830
- `[selectable]` opts a subtree back into text selection inside an
831
- ancestor that disabled it (the app's main area sets
832
- `user-select: none` to suppress accidental chrome selection).
833
- `[unselectable]` is the inverse — opts a subtree back OUT of
834
- selection inside a `[selectable]` ancestor, for chrome labels
835
- (e.g. "Used 5 tools") that sit alongside copyable content. */
836
- [selectable],
837
- [selectable] * {
838
- user-select: text;
839
- -webkit-user-select: text;
840
- }
841
-
842
- [unselectable],
843
- [unselectable] * {
844
- user-select: none;
845
- -webkit-user-select: none;
846
- }
847
-
848
- /* Prose — opt-in typography for document content */
849
-
850
- .prose {
851
- line-height: var(--leading-base);
852
- }
853
-
854
- .prose h1 {
855
- font-size: var(--text-xl);
856
- margin-bottom: var(--space-8);
857
- }
858
-
859
- .prose h2 {
860
- font-size: var(--text-lg);
861
- margin-top: var(--space-24);
862
- margin-bottom: var(--space-8);
863
- }
864
-
865
- .prose h3,
866
- .prose h4,
867
- .prose h5,
868
- .prose h6 {
869
- font-size: var(--text-base);
870
- margin-top: var(--space-24);
871
- margin-bottom: var(--space-8);
872
- }
873
-
874
- .prose p {
875
- margin: var(--space-12) 0;
876
- }
877
-
878
- .prose ul,
879
- .prose ol {
880
- padding-left: var(--space-24);
881
- margin: var(--space-12) 0;
882
- }
883
-
884
- .prose blockquote {
885
- margin: var(--space-12) 0;
886
- }
887
-
888
- .prose pre {
889
- margin: var(--space-12) 0;
890
- }
891
-
892
- .prose hr {
893
- margin: var(--space-24) 0;
894
- }
895
-
896
- .prose table {
897
- width: 100%;
898
- margin: var(--space-12) 0;
899
- }
900
-
901
- .prose img {
902
- max-width: 100%;
903
- height: auto;
904
- }
905
-
906
- .prose > :first-child {
907
- margin-top: 0;
908
- }
909
-
910
- .prose > :last-child {
911
- margin-bottom: 0;
912
- }
913
-
914
-
915
-
916
-