@hraness/peopleblade 0.3.0 → 0.3.4

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.
package/README.md CHANGED
@@ -15,7 +15,7 @@ Installation includes the pinned runtime dependencies Zod 4.4.3 and Effect 3.22.
15
15
  ## Install
16
16
 
17
17
  ```bash
18
- bun add --global @hraness/peopleblade@0.3.0
18
+ bun add --global @hraness/peopleblade@0.3.4
19
19
  peopleblade --version
20
20
  peopleblade init
21
21
  peopleblade stats --json
@@ -51,7 +51,7 @@ execution runtime.
51
51
  path. When both variables are set, they must name the same executable. The
52
52
  bridge still requires exact Ghostget 0.17.3 before invoking a provider operation.
53
53
 
54
- PeopleBlade 0.3.0 contains the reviewed Ghostget-backed Beeper, Google, and WhatsApp
54
+ PeopleBlade 0.3.4 contains the reviewed Ghostget-backed Beeper, Google, and WhatsApp
55
55
  live sync commands. Running them requires the separately installed public
56
56
  `@hraness/ghostget` 0.17.3 package. Beeper support is bounded to account-aware
57
57
  `contacts.list@3` reads, `contacts.search@1`, `messaging.search@2`, and the separate
@@ -28,3 +28,11 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28
28
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29
29
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30
30
  SOFTWARE.
31
+
32
+ ## Hraness Paper theme
33
+
34
+ The local workspace embeds the portable Paper theme from `@hraness/design-kit`.
35
+ Its reviewed source identity and file hashes are recorded in the source repository at
36
+ `styles/vendor/hraness-paper/provenance.json`. The theme is copyright (c) 2026 Hraness
37
+ and distributed under the MIT license reproduced in this package’s `LICENSE`.
38
+ It contains no fonts, scripts, or runtime dependencies.
@@ -6420,20 +6420,463 @@ function parseGranolaImportJson(raw) {
6420
6420
  }
6421
6421
  }
6422
6422
 
6423
+ // styles/vendor/hraness-paper/paper-theme.css
6424
+ var paper_theme_default = `/* @hraness/design-kit paper-theme.css, portable contract 1.
6425
+ * Generated by scripts/generate-paper-theme.ts from src/palettes.ts.
6426
+ * Opt in with data-hraness-theme="paper". Import after existing theme rules.
6427
+ * No imports, asset requests, resets, layout recipes, or runtime dependencies.
6428
+ * Appearance uses inherited color-scheme; set data-theme on the boundary for
6429
+ * an explicit island. A root without a mode follows the operating system.
6430
+ * A non-paper data-palette on the boundary retains its selected colors.
6431
+ * Requires CSS light-dark() (Chrome 123+, Firefox 120+, Safari 17.5+).
6432
+ */
6433
+
6434
+ [data-hraness-theme="paper"] {
6435
+ --font-text: "Nebula Sans", ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
6436
+ --font-heading: var(--font-text);
6437
+ --font-sans: var(--font-text);
6438
+ --font-mono: ui-monospace, "SFMono-Regular", Menlo, Monaco, Consolas, monospace;
6439
+ --ui-font-sans: var(--font-text);
6440
+ --ui-font-heading: var(--font-heading);
6441
+ --ui-font-mono: var(--font-mono);
6442
+ --text-body: 1rem;
6443
+ --text-caption: .75rem;
6444
+ --text-label: .875rem;
6445
+ --font-weight-regular: 400;
6446
+ --font-weight-medium: 550;
6447
+ --font-weight-bold: 700;
6448
+ --radius-sm: .375rem;
6449
+ --radius-md: .625rem;
6450
+ --radius-lg: .875rem;
6451
+ --ui-radius: .875rem;
6452
+ --control-radius: .625rem;
6453
+ --hraness-paper-heading-size: clamp(1.75rem, 3vw, 2.375rem);
6454
+ --hraness-paper-section-heading-size: clamp(1.25rem, 2.2vw, 1.75rem);
6455
+ --hraness-paper-summary-size: 1rem;
6456
+ --hraness-paper-heading-leading: 1.15;
6457
+ --hraness-paper-heading-tracking: -.035em;
6458
+ --hraness-marketing-measure: 80rem;
6459
+ --hraness-marketing-copy-measure: 40rem;
6460
+ --hraness-marketing-prose-measure: 68ch;
6461
+ --hraness-marketing-gutter: clamp(1.25rem, 4vw, 3rem);
6462
+ --hraness-marketing-radius: .625rem;
6463
+ --hraness-marketing-frame-radius: .875rem;
6464
+ --hraness-marketing-heading-weight: 550;
6465
+ --hraness-marketing-heading-tracking: -.025em;
6466
+ --hraness-marketing-section-space: clamp(3rem, 7vw, 6rem);
6467
+ --hraness-marketing-action-height: 2.75rem;
6468
+ font-family: var(--font-text);
6469
+ }
6470
+
6471
+ /* Existing marketing roles declare defaults directly, so inherit this
6472
+ * opt-in rhythm at each role boundary without replacing component recipes. */
6473
+ [data-hraness-theme="paper"] :where(.hraness-marketing-page, .hraness-marketing-header, .hraness-marketing-hero, .hraness-marketing-pillars, .hraness-marketing-install, .hraness-marketing-section, .hraness-marketing-primitives, .hraness-marketing-stats, .hraness-marketing-interfaces, .hraness-marketing-trust, .hraness-marketing-quotes, .hraness-marketing-pricing, .hraness-marketing-questions, .hraness-marketing-maker, .hraness-marketing-cta, .hraness-marketing-proof-frame) {
6474
+ --hraness-marketing-measure: inherit;
6475
+ --hraness-marketing-copy-measure: inherit;
6476
+ --hraness-marketing-prose-measure: inherit;
6477
+ --hraness-marketing-gutter: inherit;
6478
+ --hraness-marketing-radius: inherit;
6479
+ --hraness-marketing-frame-radius: inherit;
6480
+ --hraness-marketing-heading-weight: inherit;
6481
+ --hraness-marketing-heading-tracking: inherit;
6482
+ --hraness-marketing-section-space: inherit;
6483
+ --hraness-marketing-action-height: inherit;
6484
+ }
6485
+
6486
+ :root[data-hraness-theme="paper"]:where(:not([data-theme]):not(.dark), [data-theme="system"]) { color-scheme: light dark; }
6487
+ [data-hraness-theme="paper"]:where([data-theme="dark"], .dark:not([data-theme="light"])) { color-scheme: dark; }
6488
+ [data-hraness-theme="paper"][data-theme="light"] { color-scheme: light; }
6489
+
6490
+ /* Opted-in shared headers retain their layout and receive the shared paint
6491
+ * contract, including snapshots used with older component releases. */
6492
+ @layer components.hraness-design-kit.legacy {
6493
+ /* Keep the browser aliases in separate feature queries: CSS optimizers can
6494
+ * collapse adjacent aliases to the prefixed property and lose Chromium blur. */
6495
+ :where([data-hraness-theme="paper"]) .hraness-marketing-header, .hraness-marketing-header:where([data-hraness-theme="paper"]) {
6496
+ --hraness-marketing-header-background: var(--hraness-marketing-background);
6497
+ --hraness-marketing-header-backdrop: none;
6498
+ background: var(--hraness-marketing-header-background);
6499
+ }
6500
+
6501
+ @supports (-webkit-backdrop-filter: blur(1px)) {
6502
+ :where([data-hraness-theme="paper"]) .hraness-marketing-header, .hraness-marketing-header:where([data-hraness-theme="paper"]) {
6503
+ --hraness-marketing-header-background: color-mix(in oklch, var(--hraness-marketing-background) 82%, transparent);
6504
+ --hraness-marketing-header-backdrop: blur(14px) saturate(1.4);
6505
+ -webkit-backdrop-filter: var(--hraness-marketing-header-backdrop);
6506
+ }
6507
+ }
6508
+
6509
+ @supports (backdrop-filter: blur(1px)) {
6510
+ :where([data-hraness-theme="paper"]) .hraness-marketing-header, .hraness-marketing-header:where([data-hraness-theme="paper"]) {
6511
+ --hraness-marketing-header-background: color-mix(in oklch, var(--hraness-marketing-background) 82%, transparent);
6512
+ --hraness-marketing-header-backdrop: blur(14px) saturate(1.4);
6513
+ backdrop-filter: var(--hraness-marketing-header-backdrop);
6514
+ }
6515
+ }
6516
+
6517
+ @media (prefers-reduced-transparency: reduce), (forced-colors: active) {
6518
+ :where([data-hraness-theme="paper"]) .hraness-marketing-header, .hraness-marketing-header:where([data-hraness-theme="paper"]) {
6519
+ --hraness-marketing-header-background: var(--hraness-marketing-background);
6520
+ --hraness-marketing-header-backdrop: none;
6521
+ }
6522
+ }
6523
+ }
6524
+
6525
+ :root[data-hraness-theme="paper"]:where(:not([data-palette]), [data-palette="paper"]),
6526
+ [data-hraness-theme="paper"]:where(:not([data-palette]), [data-palette="paper"]) {
6527
+ --background: light-dark(#f8f7f4, #12100f);
6528
+ --foreground: light-dark(#1c1917, #f5f2ed);
6529
+ --muted: light-dark(#6c665f, #aaa29a);
6530
+ --faint: light-dark(#6c665f, #aaa29a);
6531
+ --grid: light-dark(#dfdcd6, #302b27);
6532
+ --line: light-dark(#b9b3ab, #514a44);
6533
+ --control-border: light-dark(#8a8177, #827a72);
6534
+ --surface: light-dark(#fffefa, #1d1a18);
6535
+ --surface-raised: light-dark(#fffefa, #211d1a);
6536
+ --surface-hover: light-dark(#ebe8e3, #292522);
6537
+ --card: light-dark(#fffefa, #1d1a18);
6538
+ --card-foreground: light-dark(#1c1917, #f5f2ed);
6539
+ --popover: light-dark(#fffefa, #211d1a);
6540
+ --popover-foreground: light-dark(#1c1917, #f5f2ed);
6541
+ --primary: light-dark(#1e5ae1, #8fb0ff);
6542
+ --primary-foreground: light-dark(#f8f7f4, #12100f);
6543
+ --primary-soft: light-dark(#dee5f3, #21232c);
6544
+ --secondary: light-dark(#ebe8e3, #292522);
6545
+ --secondary-foreground: light-dark(#1c1917, #f5f2ed);
6546
+ --accent: light-dark(#dee5f3, #21232c);
6547
+ --accent-foreground: light-dark(#1c1917, #f5f2ed);
6548
+ --focus: light-dark(#1e5ae1, #8fb0ff);
6549
+ --scrim: light-dark(#00000070, #000000b8);
6550
+ --disabled: light-dark(#fffefa, #211d1a);
6551
+ --disabled-foreground: light-dark(#6c665f, #aaa29a);
6552
+ --inverse: light-dark(#1c1917, #f5f2ed);
6553
+ --inverse-foreground: light-dark(#f8f7f4, #12100f);
6554
+ --danger: light-dark(#b23c34, #ef8c82);
6555
+ --danger-foreground: light-dark(#f8f7f4, #12100f);
6556
+ --danger-soft: light-dark(#f0e1dd, #2d1f1d);
6557
+ --warning: light-dark(#975600, #efae55);
6558
+ --warning-foreground: light-dark(#f8f7f4, #12100f);
6559
+ --warning-soft: light-dark(#eee5d7, #2d2317);
6560
+ --success: light-dark(#227445, #5fc98b);
6561
+ --success-foreground: light-dark(#f8f7f4, #12100f);
6562
+ --success-soft: light-dark(#dfe9e0, #1b261e);
6563
+ --info: light-dark(#1e5ae1, #8fb0ff);
6564
+ --info-foreground: light-dark(#f8f7f4, #12100f);
6565
+ --info-soft: light-dark(#dee5f3, #21232c);
6566
+ --chart1: light-dark(#a24a64, #db91aa);
6567
+ --chart2: light-dark(#227445, #5fc98b);
6568
+ --chart3: light-dark(#1e5ae1, #8fb0ff);
6569
+ --chart4: light-dark(#975600, #efae55);
6570
+ --chart5: light-dark(#7858a3, #b7a0dc);
6571
+ --ui-background: var(--background);
6572
+ --ui-foreground: var(--foreground);
6573
+ --ui-card: var(--card);
6574
+ --ui-card-foreground: var(--card-foreground);
6575
+ --ui-popover: var(--popover);
6576
+ --ui-popover-foreground: var(--popover-foreground);
6577
+ --ui-primary: var(--primary);
6578
+ --ui-primary-foreground: var(--primary-foreground);
6579
+ --ui-secondary: var(--secondary);
6580
+ --ui-secondary-foreground: var(--secondary-foreground);
6581
+ --ui-muted: var(--secondary);
6582
+ --ui-muted-foreground: var(--muted);
6583
+ --ui-accent: var(--accent);
6584
+ --ui-accent-foreground: var(--accent-foreground);
6585
+ --ui-destructive: var(--danger);
6586
+ --ui-destructive-foreground: var(--danger-foreground);
6587
+ --ui-destructive-soft: var(--danger-soft);
6588
+ --ui-border: var(--line);
6589
+ --ui-input: var(--control-border);
6590
+ --ui-ring: var(--focus);
6591
+ --ui-success: var(--success);
6592
+ --ui-success-foreground: var(--success-foreground);
6593
+ --ui-success-soft: var(--success-soft);
6594
+ --ui-warning: var(--warning);
6595
+ --ui-warning-foreground: var(--warning-foreground);
6596
+ --ui-warning-soft: var(--warning-soft);
6597
+ --ui-info: var(--info);
6598
+ --ui-info-foreground: var(--info-foreground);
6599
+ --ui-info-soft: var(--info-soft);
6600
+ --ui-chart-1: var(--chart1);
6601
+ --ui-chart-2: var(--chart2);
6602
+ --ui-chart-3: var(--chart3);
6603
+ --ui-chart-4: var(--chart4);
6604
+ --ui-chart-5: var(--chart5);
6605
+ --hraness-site-accent: var(--primary);
6606
+ --hraness-site-accent-ink: var(--primary-foreground);
6607
+ --plain-background: var(--background);
6608
+ --plain-foreground: var(--foreground);
6609
+ --plain-muted: var(--muted);
6610
+ --plain-line: var(--grid);
6611
+ --plain-surface: var(--secondary);
6612
+ --plain-link: var(--primary);
6613
+ --plain-syntax-keyword: var(--warning);
6614
+ --plain-syntax-string: var(--success);
6615
+ --plain-syntax-number: var(--danger);
6616
+ --plain-syntax-name: var(--info);
6617
+ --elevation-low: 0 1px 2px light-dark(rgb(33 25 18 / 8%), rgb(0 0 0 / 24%));
6618
+ --elevation-raised: 0 8px 24px -12px light-dark(rgb(33 25 18 / 22%), rgb(0 0 0 / 48%));
6619
+ --elevation-overlay: 0 18px 54px light-dark(rgb(33 25 18 / 20%), rgb(0 0 0 / 58%));
6620
+ }
6621
+
6622
+ @media (forced-colors: active) {
6623
+ :root[data-hraness-theme="paper"]:where(:not([data-palette]), [data-palette="paper"]),
6624
+ [data-hraness-theme="paper"]:where(:not([data-palette]), [data-palette="paper"]) {
6625
+ --background: Canvas;
6626
+ --foreground: CanvasText;
6627
+ --muted: CanvasText;
6628
+ --faint: CanvasText;
6629
+ --surface: Canvas;
6630
+ --surface-raised: Canvas;
6631
+ --surface-hover: Canvas;
6632
+ --card: Canvas;
6633
+ --card-foreground: CanvasText;
6634
+ --popover: Canvas;
6635
+ --popover-foreground: CanvasText;
6636
+ --secondary: Canvas;
6637
+ --secondary-foreground: CanvasText;
6638
+ --grid: CanvasText;
6639
+ --line: CanvasText;
6640
+ --control-border: ButtonText;
6641
+ --primary: Highlight;
6642
+ --primary-foreground: HighlightText;
6643
+ --plain-link: LinkText;
6644
+ --accent: Highlight;
6645
+ --accent-foreground: HighlightText;
6646
+ --focus: Highlight;
6647
+ --inverse: CanvasText;
6648
+ --inverse-foreground: Canvas;
6649
+ --disabled: Canvas;
6650
+ --disabled-foreground: GrayText;
6651
+ --elevation-low: none;
6652
+ --elevation-raised: none;
6653
+ --elevation-overlay: none;
6654
+ }
6655
+ }
6656
+ `;
6657
+
6658
+ // styles/vendor/hraness-lantern/lantern-material.css
6659
+ var lantern_material_default = `/* Lantern is an opt-in material, independent of palette and typography.
6660
+ * All paint is deterministic CSS. No texture is placed over meaningful content. */
6661
+ @layer base {
6662
+ [data-hraness-material="lantern"] {
6663
+ --hraness-material-module: 6rem;
6664
+ --hraness-material-warm: #d49a54;
6665
+ --hraness-material-cool: #8d9fc5;
6666
+ --hraness-material-plane: var(--surface, var(--ui-background, Canvas));
6667
+ --hraness-material-ink: var(--foreground, var(--ui-foreground, CanvasText));
6668
+ --hraness-material-muted: var(--muted, var(--ui-muted-foreground, CanvasText));
6669
+ --hraness-material-seam: color-mix(in oklch, var(--hraness-material-ink) 7%, var(--hraness-material-plane));
6670
+ --hraness-material-edge: color-mix(in oklch, white 18%, transparent);
6671
+ --hraness-material-shade: color-mix(in oklch, black 14%, transparent);
6672
+ --hraness-material-warm-plane: color-mix(in oklch, var(--hraness-material-warm) 12%, var(--hraness-material-plane));
6673
+ --hraness-material-inset: inset 2px 3px 6px color-mix(in oklch, black 9%, transparent), inset -1px -1px 2px color-mix(in oklch, white 12%, transparent);
6674
+ --hraness-material-lift: inset 0 1px 0 var(--hraness-material-edge), -3px -3px 10px color-mix(in oklch, white 4%, transparent), 2px 4px 8px color-mix(in oklch, black 7%, transparent), 8px 18px 40px color-mix(in oklch, black 9%, transparent);
6675
+ --hraness-material-focus: var(--focus, var(--ui-ring, Highlight));
6676
+ --hraness-material-duration: 160ms;
6677
+ }
6678
+ }
6679
+
6680
+ @layer components.hraness-design-kit.legacy {
6681
+ /* A quiet, opaque reading plane. The seam belongs to the surface perimeter. */
6682
+ :where([data-hraness-material="lantern"], [data-hraness-material="lantern"] *):is(.hraness-material-pane) {
6683
+ background-color: var(--hraness-material-plane);
6684
+ border: 1px solid var(--hraness-material-seam);
6685
+ border-radius: var(--radius-lg, 0.75rem);
6686
+ color: var(--hraness-material-ink);
6687
+ min-inline-size: 0;
6688
+ }
6689
+ :where([data-hraness-material="lantern"], [data-hraness-material="lantern"] *):is(.hraness-material-pane[data-depth="raised"]) {
6690
+ box-shadow: var(--hraness-material-lift);
6691
+ }
6692
+ :where([data-hraness-material="lantern"], [data-hraness-material="lantern"] *):is(.hraness-material-pane[data-depth="inset"]) {
6693
+ background-color: color-mix(in oklch, var(--background, Canvas) 70%, var(--hraness-material-plane));
6694
+ box-shadow: var(--hraness-material-inset);
6695
+ }
6696
+
6697
+ /* A translucent enclosure, only where content actually passes behind it.
6698
+ * Resolve these tokens on the chrome itself for nested palette islands. */
6699
+ :where([data-hraness-material="lantern"], [data-hraness-material="lantern"] *):is(.hraness-material-chrome) {
6700
+ --hraness-material-chrome-paint: var(--surface, var(--ui-background, Canvas));
6701
+ --hraness-material-chrome-blur: none;
6702
+ background-color: var(--hraness-material-chrome-paint);
6703
+ border-block-end: 1px solid var(--hraness-material-seam);
6704
+ box-shadow: inset 0 1px 0 var(--hraness-material-edge), 0 4px 12px color-mix(in oklch, black 4%, transparent);
6705
+ }
6706
+ /* Bind the compiled TopBar's public paint seam at its own surface boundary. */
6707
+ :where([data-hraness-material="lantern"], [data-hraness-material="lantern"] *):is(.hraness-material-chrome.hraness-design-top-bar[data-surface="glass"]) {
6708
+ --hraness-design-top-bar-background: var(--hraness-material-chrome-paint);
6709
+ --hraness-design-top-bar-backdrop: var(--hraness-material-chrome-blur);
6710
+ }
6711
+ @supports (-webkit-backdrop-filter: blur(1px)) {
6712
+ :where([data-hraness-material="lantern"], [data-hraness-material="lantern"] *):is(.hraness-material-chrome) {
6713
+ --hraness-material-chrome-paint: color-mix(in oklch, var(--surface, var(--ui-background, Canvas)) 90%, transparent);
6714
+ --hraness-material-chrome-blur: blur(20px) saturate(1.1);
6715
+ -webkit-backdrop-filter: var(--hraness-material-chrome-blur);
6716
+ }
6717
+ }
6718
+ @supports (backdrop-filter: blur(1px)) {
6719
+ :where([data-hraness-material="lantern"], [data-hraness-material="lantern"] *):is(.hraness-material-chrome) {
6720
+ --hraness-material-chrome-paint: color-mix(in oklch, var(--surface, var(--ui-background, Canvas)) 90%, transparent);
6721
+ --hraness-material-chrome-blur: blur(20px) saturate(1.1);
6722
+ backdrop-filter: var(--hraness-material-chrome-blur);
6723
+ }
6724
+ }
6725
+
6726
+ /* Glazing uses shaded faces rather than drawn seams, with a warm band
6727
+ * of transmitted light. Its edges suggest a rounded enclosure without
6728
+ * distorting the document, blurring text, or masking brand artwork. */
6729
+ :where([data-hraness-material="lantern"], [data-hraness-material="lantern"] *):is(.hraness-material-wall) {
6730
+ background-color: var(--background, var(--ui-background, Canvas));
6731
+ background-image:
6732
+ var(--hraness-material-wall-grain, none),
6733
+ var(--hraness-material-wall-cells, linear-gradient(145deg, color-mix(in oklch, white 5%, transparent), transparent 48%, color-mix(in oklch, black 7%, transparent))),
6734
+ radial-gradient(ellipse at 60% 110%, color-mix(in oklch, var(--hraness-material-warm) 22%, transparent), transparent 68%),
6735
+ linear-gradient(110deg, color-mix(in oklch, var(--hraness-material-cool) 14%, transparent), transparent 38%, color-mix(in oklch, white 4%, transparent) 65%, transparent);
6736
+ background-size: 64px 64px, var(--hraness-material-wall-cell-size, var(--hraness-material-module)) var(--hraness-material-wall-cell-size, var(--hraness-material-module)), 100% 100%, 100% 100%;
6737
+ background-position: 0 0, center top, center top, center top;
6738
+ color: var(--hraness-material-ink);
6739
+ }
6740
+
6741
+ /* A terminal remains a readable document. Source lines scroll intact;
6742
+ * only its enclosure catches light. Syntax spans inherit semantic colors. */
6743
+ :where([data-hraness-material="lantern"], [data-hraness-material="lantern"] *):is(.hraness-material-terminal) {
6744
+ min-inline-size: 0;
6745
+ overflow: hidden;
6746
+ border: 1px solid var(--hraness-material-seam);
6747
+ border-radius: .875rem;
6748
+ background: var(--hraness-material-plane);
6749
+ color: var(--hraness-material-ink);
6750
+ box-shadow: var(--hraness-material-lift);
6751
+ }
6752
+ :where([data-hraness-material="lantern"], [data-hraness-material="lantern"] *):is(.hraness-material-terminal__bar) {
6753
+ padding: .8rem 1.25rem;
6754
+ background: linear-gradient(to bottom, color-mix(in oklch, white 5%, var(--hraness-material-plane)), var(--hraness-material-plane));
6755
+ box-shadow: inset 0 1px 0 var(--hraness-material-edge), 0 1px 3px color-mix(in oklch, black 8%, transparent);
6756
+ color: var(--hraness-material-muted);
6757
+ font: .8125rem/1.5 var(--font-mono, ui-monospace, monospace);
6758
+ }
6759
+ :where([data-hraness-material="lantern"], [data-hraness-material="lantern"] *):is(.hraness-material-code) {
6760
+ min-inline-size: 0;
6761
+ max-inline-size: 100%;
6762
+ margin: 0;
6763
+ padding: 1.25rem;
6764
+ overflow: auto;
6765
+ background: var(--hraness-material-plane);
6766
+ color: var(--hraness-material-ink);
6767
+ font: .875rem/1.75 var(--font-mono, ui-monospace, monospace);
6768
+ white-space: pre;
6769
+ overflow-wrap: normal;
6770
+ word-break: normal;
6771
+ tab-size: 2;
6772
+ }
6773
+ :where([data-hraness-material="lantern"], [data-hraness-material="lantern"] *):is(.hraness-material-code) code {
6774
+ background: none;
6775
+ padding: 0;
6776
+ font: inherit;
6777
+ white-space: inherit;
6778
+ overflow-wrap: inherit;
6779
+ word-break: inherit;
6780
+ }
6781
+
6782
+ /* Plain HTML control adapters. Compiled UI primitives use the public
6783
+ * lanternControlStyles recipes through their documented controlXstyle seam.
6784
+ * Edge paint uses background images, leaving focus shadows and outlines alone. */
6785
+ :where([data-hraness-material="lantern"], [data-hraness-material="lantern"] *):is(.hraness-material-control) {
6786
+ background-image: linear-gradient(to bottom, var(--hraness-material-edge), transparent 2px);
6787
+ }
6788
+ :where([data-hraness-material="lantern"], [data-hraness-material="lantern"] *):is(.hraness-material-input) {
6789
+ background-image: linear-gradient(to bottom, var(--hraness-material-shade), transparent 4px);
6790
+ caret-color: var(--hraness-material-focus);
6791
+ }
6792
+ :where([data-hraness-material="lantern"], [data-hraness-material="lantern"] *):is(.hraness-material-choice[aria-pressed="true"], .hraness-material-choice[aria-selected="true"], .hraness-material-choice[data-selected]) {
6793
+ background-color: var(--hraness-material-warm-plane);
6794
+ color: var(--hraness-material-ink);
6795
+ background-image: linear-gradient(to top, var(--hraness-material-warm), var(--hraness-material-warm) 2px, transparent 2px);
6796
+ }
6797
+ :where([data-hraness-material="lantern"], [data-hraness-material="lantern"] *):is(.hraness-material-control:disabled, .hraness-material-control[aria-disabled="true"], .hraness-material-control[data-disabled], .hraness-material-input:disabled) {
6798
+ background-image: none;
6799
+ }
6800
+
6801
+ /* A collection is a readable sequence, never a requirement to fill a grid.
6802
+ * Products own grouping, columns and the meaning of each row. */
6803
+ :where([data-hraness-material="lantern"], [data-hraness-material="lantern"] *):is(.hraness-material-rows) {
6804
+ margin: 0;
6805
+ padding: 0;
6806
+ list-style: none;
6807
+ }
6808
+ :where([data-hraness-material="lantern"], [data-hraness-material="lantern"] *):is(.hraness-material-rows > * + *) {
6809
+ border-block-start: 1px solid var(--hraness-material-seam);
6810
+ }
6811
+ :where([data-hraness-material="lantern"], [data-hraness-material="lantern"] *):is(.hraness-material-disclosure > summary) {
6812
+ cursor: pointer;
6813
+ min-block-size: 2.75rem;
6814
+ padding-block: 0.75rem;
6815
+ }
6816
+ :where([data-hraness-material="lantern"], [data-hraness-material="lantern"] *):is(.hraness-material-disclosure > summary:focus-visible) {
6817
+ outline: 2px solid var(--hraness-material-focus);
6818
+ outline-offset: 3px;
6819
+ }
6820
+ [data-hraness-material="lantern"] ::selection {
6821
+ background-color: var(--hraness-material-warm-plane);
6822
+ color: var(--hraness-material-ink);
6823
+ }
6824
+
6825
+ @media (prefers-reduced-motion: reduce) {
6826
+ [data-hraness-material="lantern"] { --hraness-material-duration: 0ms; }
6827
+ }
6828
+ @media (prefers-reduced-transparency: reduce) {
6829
+ :where([data-hraness-material="lantern"], [data-hraness-material="lantern"] *):is(.hraness-material-chrome) {
6830
+ --hraness-material-chrome-paint: var(--surface, var(--ui-background, Canvas));
6831
+ --hraness-material-chrome-blur: none;
6832
+ }
6833
+ :where([data-hraness-material="lantern"], [data-hraness-material="lantern"] *):is(.hraness-material-wall) { background-image: none; }
6834
+ }
6835
+ @media (forced-colors: active) {
6836
+ [data-hraness-material="lantern"] {
6837
+ --hraness-material-plane: Canvas;
6838
+ --hraness-material-ink: CanvasText;
6839
+ --hraness-material-muted: CanvasText;
6840
+ --hraness-material-seam: CanvasText;
6841
+ --hraness-material-focus: Highlight;
6842
+ --hraness-material-warm-plane: Canvas;
6843
+ --hraness-material-warm: Highlight;
6844
+ --hraness-material-edge: transparent;
6845
+ --hraness-material-inset: none;
6846
+ --hraness-material-lift: none;
6847
+ }
6848
+ :where([data-hraness-material="lantern"], [data-hraness-material="lantern"] *):is(.hraness-material-wall, .hraness-material-chrome, .hraness-material-pane, .hraness-material-terminal, .hraness-material-terminal__bar, .hraness-material-code) {
6849
+ --hraness-material-chrome-paint: Canvas;
6850
+ --hraness-material-chrome-blur: none;
6851
+ background-color: Canvas;
6852
+ background-image: none;
6853
+ box-shadow: none;
6854
+ }
6855
+ :where([data-hraness-material="lantern"], [data-hraness-material="lantern"] *):is(.hraness-material-control, .hraness-material-input, .hraness-material-choice) { background-image: none; }
6856
+ :where([data-hraness-material="lantern"], [data-hraness-material="lantern"] *):is(.hraness-material-choice[aria-pressed="true"], .hraness-material-choice[aria-selected="true"], .hraness-material-choice[data-selected]) {
6857
+ background-color: Highlight;
6858
+ color: HighlightText;
6859
+ background-image: none;
6860
+ }
6861
+ }
6862
+ }
6863
+ `;
6864
+
6423
6865
  // src/local/workspace-assets.ts
6424
6866
  var workspaceHtml = `<!doctype html>
6425
- <html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
6867
+ <html lang="en" data-hraness-theme="paper" data-hraness-material="lantern"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
6426
6868
  <title>PeopleBlade \xB7 Local workspace</title><link rel="stylesheet" href="/workspace.css"><script src="/workspace.js" defer></script></head>
6427
- <body><a class="skip" href="#workspace">Skip to contacts</a><header><a class="brand" href="/">PeopleBlade<span>LOCAL WORKSPACE</span></a><p>Your people. Your machine.</p><span class="privacy">No cloud sync \xB7 no enrichment calls</span></header>
6428
- <main id="workspace"><section id="unlock" class="unlock"><span class="eyebrow">PRIVATE BY DEFAULT</span><h1>Open your local contact book.</h1><p>Select the access file printed by <code>peopleblade ui</code>. It connects this tab to that running process only. The file is not uploaded to a remote service.</p><label class="file-label">Workspace access file<input id="access-file" type="file" accept="application/json,.json"></label><p class="muted">Keep the terminal running. Closing it locks the workspace. Notes never leave this machine.</p></section>
6869
+ <body><a class="skip" href="#workspace">Skip to contacts</a><header class="workspace-header hraness-material-chrome"><a class="brand" href="/">PeopleBlade<span>LOCAL WORKSPACE</span></a><p>Your people. Your machine.</p><span class="privacy">No cloud sync \xB7 no enrichment calls</span></header>
6870
+ <main id="workspace"><section id="unlock" class="unlock hraness-material-pane"><span class="eyebrow">PRIVATE BY DEFAULT</span><h1>Open your local contact book.</h1><p>Select the access file printed by <code>peopleblade ui</code>. It connects this tab to that running process only. The file is not uploaded to a remote service.</p><label class="file-label">Workspace access file<input id="access-file" type="file" accept="application/json,.json"></label><p class="muted">Keep the terminal running. Closing it locks the workspace. Notes never leave this machine.</p></section>
6429
6871
  <section id="book" hidden><div class="page-heading"><div><span class="eyebrow">YOUR RELATIONSHIPS</span><h1>Contact book</h1></div><button id="lock" type="button">Lock workspace</button></div>
6430
6872
  <form id="filters" class="filters"><label class="search">Search contacts<input id="search" name="search" type="search" placeholder="Name, company, title, email, phone\u2026" maxlength="200"></label><label>Source<select id="source"><option value="">All sources</option><option>apple</option><option>beeper</option><option>google</option><option>imessage</option><option>linkedin</option><option>instagram</option><option>whatsapp</option><option>x</option></select></label><label>Email<select id="email"><option value="">Any email</option><option value="yes">Has email</option><option value="no">Needs email</option></select></label><label>Contact preference<select id="dnc"><option value="all">All contacts</option><option value="exclude">May contact</option><option value="only">Do not contact</option></select></label><button type="submit">Search</button><button id="reset" type="button">Reset</button></form>
6431
- <div class="workspace-grid"><section class="records" aria-label="Contacts"><div class="table-toolbar"><span id="range" aria-live="polite"></span><div><label>Sort <select id="sort"><option value="interactions">Interactions</option><option value="name">Name</option><option value="organization">Company</option><option value="last-contact">Last interaction</option></select></label><button id="direction" type="button" aria-label="Toggle sort direction">Descending \u2193</button></div></div><div class="table-scroll" tabindex="0" aria-label="Scrollable contacts"><table><caption class="sr-only">Local contacts; open a person to inspect details and notes.</caption><thead><tr><th scope="col">Person</th><th scope="col">Company</th><th scope="col">Interactions</th></tr></thead><tbody id="rows"></tbody></table></div><div id="empty" class="empty" hidden>No matches. Try another search or import a source with the CLI.</div><nav class="pagination" aria-label="Contact pages"><button id="previous" type="button">\u2190 Previous</button><span id="page"></span><button id="next" type="button">Next \u2192</button></nav><p class="live-note">Live view: imports and identity reviews can move rows between pages. Refresh after changes.</p></section>
6432
- <aside id="detail" class="detail" aria-label="Contact details"><div class="empty"><h2>A little context goes a long way.</h2><p>Open a person to see their contact methods, sources and private notes.</p></div></aside></div></section>
6873
+ <div class="workspace-grid"><section class="records hraness-material-pane" aria-label="Contacts"><div class="table-toolbar"><span id="range" aria-live="polite"></span><div><label>Sort <select id="sort"><option value="interactions">Interactions</option><option value="name">Name</option><option value="organization">Company</option><option value="last-contact">Last interaction</option></select></label><button id="direction" type="button" aria-label="Toggle sort direction">Descending \u2193</button></div></div><div class="table-scroll" tabindex="0" aria-label="Scrollable contacts"><table><caption class="sr-only">Local contacts; open a person to inspect details and notes.</caption><thead><tr><th scope="col">Person</th><th scope="col">Company</th><th scope="col">Interactions</th></tr></thead><tbody id="rows"></tbody></table></div><div id="empty" class="empty" hidden>No matches. Try another search or import a source with the CLI.</div><nav class="pagination" aria-label="Contact pages"><button id="previous" type="button">\u2190 Previous</button><span id="page"></span><button id="next" type="button">Next \u2192</button></nav><p class="live-note">Live view: imports and identity reviews can move rows between pages. Refresh after changes.</p></section>
6874
+ <aside id="detail" class="detail hraness-material-pane" aria-label="Contact details"><div class="empty"><h2>A little context goes a long way.</h2><p>Open a person to see their contact methods, sources and private notes.</p></div></aside></div></section>
6433
6875
  <p id="status" role="status" aria-live="polite"></p></main><footer>PeopleBlade \xB7 Local authority, reviewable identity, private notes.</footer></body></html>`;
6434
- var workspaceCss = `
6435
- :root{color-scheme:light dark;--bg:#f6f5f1;--panel:#fffefa;--text:#232721;--muted:#647064;--line:#dedfd6;--accent:#375a42;--soft:#edf1e8;--danger:#9c342d}*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--text);font:14px/1.55 system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif}button,input,select,textarea{font:inherit;color:inherit}button,input,select,textarea{border:1px solid var(--line);border-radius:7px;background:var(--panel);padding:9px 12px}button{cursor:pointer;font-weight:550}button:hover{border-color:var(--accent);background:var(--soft)}button:disabled{opacity:.45;cursor:default}a{color:var(--accent)}:focus-visible{outline:3px solid var(--accent);outline-offset:3px}header{display:flex;align-items:center;gap:30px;padding:22px 32px;border-bottom:1px solid var(--line);background:var(--panel)}header p{color:var(--muted);margin:0}.brand{color:var(--text);font-size:22px;line-height:1.1;text-decoration:none;font-weight:650;letter-spacing:-.7px}.brand span{display:block;font-size:9px;letter-spacing:1.8px;color:var(--muted);margin-top:8px}.privacy{margin-left:auto;border:1px solid var(--line);border-radius:99px;padding:6px 12px;font-size:11px;color:var(--muted)}main{max-width:1600px;margin:auto;padding:36px 32px}h1{font-size:34px;line-height:1.2;letter-spacing:-1px;font-weight:550;margin:8px 0 24px}h2{font-size:21px;line-height:1.3;letter-spacing:-.5px;margin:0 0 12px}.eyebrow{font-size:10px;letter-spacing:2px;color:var(--muted);font-weight:650}.unlock{max-width:600px;margin:7vh auto;padding:36px;background:var(--panel);border:1px solid var(--line);border-radius:12px}.unlock p{color:var(--muted)}.file-label{display:grid;gap:8px;margin:25px 0}.page-heading{display:flex;align-items:center;justify-content:space-between}.page-heading button{margin-bottom:20px}.filters{display:flex;gap:10px;align-items:end;margin-bottom:20px;flex-wrap:wrap}.filters label{display:grid;gap:5px;font-size:11px;color:var(--muted)}.filters input,.filters select{font-size:13px;color:var(--text);min-height:42px}.filters .search{flex:1;min-width:220px}.workspace-grid{display:grid;grid-template-columns:minmax(420px,1.4fr) minmax(320px,1fr);gap:20px;align-items:start}.records,.detail{border:1px solid var(--line);background:var(--panel);border-radius:10px;overflow:hidden}.table-toolbar{display:flex;justify-content:space-between;align-items:center;gap:12px;padding:13px 16px;border-bottom:1px solid var(--line);color:var(--muted);font-size:12px;flex-wrap:wrap}.table-toolbar>div{display:flex;align-items:center;gap:6px}.table-toolbar select,.table-toolbar button{padding:5px 8px;font-size:12px}.table-scroll{overflow:auto;max-height:65vh}table{width:100%;border-collapse:collapse;text-align:left}th{position:sticky;top:0;background:var(--soft);font-size:10px;text-transform:uppercase;letter-spacing:1px;color:var(--muted);z-index:1}th,td{padding:11px 16px;border-bottom:1px solid var(--line);vertical-align:top}td{font-size:12px}td small{display:block;color:var(--muted);margin-top:2px}td button{padding:0;border:0;background:none;text-align:left;font-size:13px;color:var(--text)}tr.selected{background:var(--soft)}tr:hover{background:var(--soft)}.pagination{display:flex;justify-content:space-between;align-items:center;padding:14px 16px;font-size:12px}.pagination button{font-size:12px;padding:6px 10px}.live-note{font-size:10px;color:var(--muted);padding:0 16px 12px;margin:0}.detail{padding:24px;position:sticky;top:20px;max-height:83vh;overflow:auto}.detail h2{font-size:25px}.detail dl{display:grid;grid-template-columns:90px 1fr;gap:8px;margin:22px 0}.detail dt{font-size:11px;color:var(--muted)}.detail dd{margin:0;font-size:12px;overflow-wrap:anywhere}.detail dd span{display:block}.pill{display:inline-block;border:1px solid var(--line);border-radius:99px;padding:2px 8px;margin:0 4px 5px 0;color:var(--muted);font-size:10px}.notes-heading{border-top:1px solid var(--line);padding-top:22px;margin-top:24px;display:flex;justify-content:space-between;align-items:center}.notes-heading h3{margin:0;font-weight:550}.note-card{border-bottom:1px solid var(--line);padding:16px 0}.note-card>button{font-size:12px;padding:5px 9px;margin:8px 6px 0 0}.note-meta{font-size:10px;color:var(--muted);margin:4px 0 10px}.note-title{font-size:14px;font-weight:600;margin:0}.markdown{font-size:13px;overflow-wrap:anywhere}.markdown h1,.markdown h2,.markdown h3{font-size:17px;margin:12px 0}.markdown pre{overflow:auto;background:var(--soft);padding:12px;border-radius:6px}.markdown img{display:none}.markdown blockquote{margin-left:0;padding-left:12px;border-left:3px solid var(--line);color:var(--muted)}.markdown p{margin:8px 0}.markdown td,.markdown th{padding:5px;position:static}.editor{display:grid;gap:10px}.editor label{display:grid;gap:4px;font-size:11px;color:var(--muted)}.editor textarea{min-height:230px;resize:vertical;font-family:ui-monospace,SFMono-Regular,monospace;font-size:12px;tab-size:2}.editor-actions{display:flex;gap:6px;flex-wrap:wrap}.editor-actions button{font-size:12px}.primary{background:var(--accent);color:var(--panel)}.primary:hover{background:var(--accent);color:var(--panel)}.empty{padding:44px 22px;color:var(--muted);text-align:center}.empty h2{font-size:21px}.muted{color:var(--muted);font-size:12px}.danger{color:var(--danger)}#status{background:var(--panel);border:1px solid var(--line);padding:12px 16px;border-radius:8px}#status:empty{display:none}footer{color:var(--muted);font-size:11px;text-align:center;padding:20px}.skip{position:absolute;left:12px;top:-100px;padding:8px;background:var(--panel);z-index:5}.skip:focus{top:8px}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}[hidden]{display:none!important}
6436
- @media(prefers-color-scheme:dark){:root{--bg:#151a17;--panel:#1c231e;--text:#e1e7dc;--muted:#a3b19e;--line:#354136;--accent:#a9c4a3;--soft:#28342b;--danger:#ffb4a9}.primary{color:#182019}}
6876
+ var workspaceCss = paper_theme_default + `
6877
+ ` + lantern_material_default + `
6878
+ :root{--bg:var(--background);--panel:var(--surface);--text:var(--foreground);--soft:var(--secondary)}*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--text);font:14px/1.55 var(--font-text)}button,input,select,textarea{font:inherit;color:inherit}button,input,select,textarea{border:1px solid var(--line);border-radius:7px;background:var(--panel);padding:9px 12px}button{cursor:pointer;font-weight:550}button:hover{border-color:var(--primary);background:var(--soft)}button:disabled{opacity:.45;cursor:default}a{color:var(--primary)}:focus-visible{outline:3px solid var(--primary);outline-offset:3px}header{display:flex;align-items:center;gap:30px;padding:22px 32px;border-bottom:1px solid var(--hraness-material-seam);background-color:var(--hraness-material-chrome-paint)}header p{color:var(--muted);margin:0}.brand{color:var(--text);font-size:22px;line-height:1.1;text-decoration:none;font-weight:650;letter-spacing:-.7px}.brand span{display:block;font-size:9px;letter-spacing:1.8px;color:var(--muted);margin-top:8px}.privacy{margin-left:auto;border:1px solid var(--line);border-radius:99px;padding:6px 12px;font-size:11px;color:var(--muted)}main{max-width:1600px;margin:auto;padding:36px 32px}h1{font-size:34px;line-height:1.2;letter-spacing:-1px;font-weight:550;margin:8px 0 24px}h2{font-size:21px;line-height:1.3;letter-spacing:-.5px;margin:0 0 12px}.eyebrow{font-size:10px;letter-spacing:2px;color:var(--muted);font-weight:650}.unlock{max-width:600px;margin:7vh auto;padding:36px;background:var(--hraness-material-plane);border:1px solid var(--hraness-material-seam);border-radius:12px;color:var(--hraness-material-ink)}.unlock p{color:var(--muted)}.file-label{display:grid;gap:8px;margin:25px 0}.page-heading{display:flex;align-items:center;justify-content:space-between}.page-heading button{margin-bottom:20px}.filters{display:flex;gap:10px;align-items:end;margin-bottom:20px;flex-wrap:wrap}.filters label{display:grid;gap:5px;font-size:11px;color:var(--muted)}.filters input,.filters select{font-size:13px;color:var(--text);min-height:42px}.filters .search{flex:1;min-width:220px}.workspace-grid{display:grid;grid-template-columns:minmax(420px,1.4fr) minmax(320px,1fr);gap:20px;align-items:start}.records,.detail{border:1px solid var(--hraness-material-seam);background:var(--hraness-material-plane);border-radius:10px;color:var(--hraness-material-ink);overflow:hidden}.table-toolbar{display:flex;justify-content:space-between;align-items:center;gap:12px;padding:13px 16px;border-bottom:1px solid var(--line);color:var(--muted);font-size:12px;flex-wrap:wrap}.table-toolbar>div{display:flex;align-items:center;gap:6px}.table-toolbar select,.table-toolbar button{padding:5px 8px;font-size:12px}.table-scroll{overflow:auto;max-height:65vh}table{width:100%;border-collapse:collapse;text-align:left}th{position:sticky;top:0;background:var(--soft);font-size:10px;text-transform:uppercase;letter-spacing:1px;color:var(--muted);z-index:1}th,td{padding:11px 16px;border-bottom:1px solid var(--line);vertical-align:top}td{font-size:12px}td small{display:block;color:var(--muted);margin-top:2px}td button{padding:0;border:0;background:none;text-align:left;font-size:13px;color:var(--text)}tr:hover{background:var(--soft)}tr.selected,tr.selected:hover{background:var(--hraness-material-warm-plane);color:var(--hraness-material-ink)}tr.selected td small,tr.selected td button{color:var(--hraness-material-ink)}.pagination{display:flex;justify-content:space-between;align-items:center;padding:14px 16px;font-size:12px}.pagination button{font-size:12px;padding:6px 10px}.live-note{font-size:10px;color:var(--muted);padding:0 16px 12px;margin:0}.detail{padding:24px;position:sticky;top:20px;max-height:83vh;overflow:auto}.detail h2{font-size:25px}.detail dl{display:grid;grid-template-columns:90px 1fr;gap:8px;margin:22px 0}.detail dt{font-size:11px;color:var(--muted)}.detail dd{margin:0;font-size:12px;overflow-wrap:anywhere}.detail dd span{display:block}.pill{display:inline-block;border:1px solid var(--line);border-radius:99px;padding:2px 8px;margin:0 4px 5px 0;color:var(--muted);font-size:10px}.notes-heading{border-top:1px solid var(--line);padding-top:22px;margin-top:24px;display:flex;justify-content:space-between;align-items:center}.notes-heading h3{margin:0;font-weight:550}.note-card{border-bottom:1px solid var(--line);padding:16px 0}.note-card>button{font-size:12px;padding:5px 9px;margin:8px 6px 0 0}.note-meta{font-size:10px;color:var(--muted);margin:4px 0 10px}.note-title{font-size:14px;font-weight:600;margin:0}.markdown{font-size:13px;overflow-wrap:anywhere}.markdown h1,.markdown h2,.markdown h3{font-size:17px;margin:12px 0}.markdown pre{overflow:auto;background:var(--soft);padding:12px;border-radius:6px}.markdown img{display:none}.markdown blockquote{margin-left:0;padding-left:12px;border-left:3px solid var(--line);color:var(--muted)}.markdown p{margin:8px 0}.markdown td,.markdown th{padding:5px;position:static}.editor{display:grid;gap:10px}.editor label{display:grid;gap:4px;font-size:11px;color:var(--muted)}.editor textarea{min-height:230px;resize:vertical;font-family:ui-monospace,SFMono-Regular,monospace;font-size:12px;tab-size:2}.editor-actions{display:flex;gap:6px;flex-wrap:wrap}.editor-actions button{font-size:12px}.primary{background:var(--primary);color:var(--primary-foreground)}.primary:hover{background:var(--primary);color:var(--primary-foreground)}.empty{padding:44px 22px;color:var(--muted);text-align:center}.empty h2{font-size:21px}.muted{color:var(--muted);font-size:12px}.danger{color:var(--danger)}#status{background:var(--panel);border:1px solid var(--line);padding:12px 16px;border-radius:8px}#status:empty{display:none}footer{color:var(--muted);font-size:11px;text-align:center;padding:20px}.skip{position:absolute;left:12px;top:-100px;padding:8px;background:var(--panel);z-index:5}.skip:focus{top:8px}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}[hidden]{display:none!important}
6879
+ @media(forced-colors:active){tr.selected,tr.selected:hover{background:Highlight;color:HighlightText}tr.selected td small,tr.selected td button{color:HighlightText}}
6437
6880
  @media(max-width:1000px){.workspace-grid{grid-template-columns:1fr}.detail{position:static;max-height:none}.privacy{display:none}}@media(max-width:600px){header{padding:18px;gap:18px}header p{font-size:11px}main{padding:26px 14px}.unlock{padding:22px;margin:25px 0}h1{font-size:28px}.filters{gap:8px}.filters label{flex:1;min-width:125px}.filters .search{flex-basis:100%}th,td{padding:10px}.detail{padding:18px}.table-toolbar{padding:10px}.page-heading{align-items:start}.page-heading button{font-size:11px}.table-scroll{max-height:50vh}}
6438
6881
  `;
6439
6882
  function workspaceClient() {
@@ -6503,6 +6946,7 @@ function workspaceClient() {
6503
6946
  el("rows").replaceChildren();
6504
6947
  for (const person of result.items) {
6505
6948
  const row = node("tr", "", selectedPerson === person.id ? "selected" : "");
6949
+ row.dataset.personId = String(person.id);
6506
6950
  const name = node("td");
6507
6951
  const open = node("button", person.displayName);
6508
6952
  open.type = "button";
@@ -6747,6 +7191,9 @@ function workspaceClient() {
6747
7191
  }
6748
7192
  activeEditor = null;
6749
7193
  selectedPerson = id;
7194
+ for (const row of el("rows").querySelectorAll("tr[data-person-id]")) {
7195
+ row.classList.toggle("selected", row.dataset.personId === String(id));
7196
+ }
6750
7197
  target.replaceChildren();
6751
7198
  target.append(node("span", `PERSON ${id} \xB7 ${result.memberCount} SOURCE RECORD${result.memberCount === 1 ? "" : "S"}`, "eyebrow"), node("h2", result.contact.displayName));
6752
7199
  const pills = node("div");
@@ -26057,7 +26504,20 @@ function syncWhatsAppRelationships(database, options = {}) {
26057
26504
  }
26058
26505
 
26059
26506
  // src/cli/version.ts
26060
- var peoplebladeVersion = "0.3.0";
26507
+ var peoplebladeVersion = "0.3.4";
26508
+
26509
+ // src/cli/intro.ts
26510
+ function terminalIntro(terminal) {
26511
+ if (terminal.isTTY !== true || terminal.term === "dumb" || (terminal.columns ?? 80) < 48)
26512
+ return "";
26513
+ return ` .--.--.
26514
+ /______/_ peopleblade
26515
+ | o --- | Your contacts, notes, and context.
26516
+ |___ --- |
26517
+ |____|
26518
+
26519
+ `;
26520
+ }
26061
26521
 
26062
26522
  // src/cli/main.ts
26063
26523
  var usage = `PeopleBlade \u2014 local-first contact intelligence
@@ -26292,6 +26752,8 @@ async function main(argv) {
26292
26752
  const asJson = flag(args, "--json");
26293
26753
  const autoAccept = flag(args, "--auto-accept");
26294
26754
  if (args.length === 0 || args[0] === "--help" || args[0] === "-h") {
26755
+ if (!asJson)
26756
+ process.stdout.write(terminalIntro({ isTTY: process.stdout.isTTY, columns: process.stdout.columns, term: process.env.TERM }));
26295
26757
  console.log(usage);
26296
26758
  return;
26297
26759
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hraness/peopleblade",
3
- "version": "0.3.0",
3
+ "version": "0.3.4",
4
4
  "description": "Local-first, source-aware contact intelligence for people and agents",
5
5
  "type": "module",
6
6
  "bin": {