@idle-screens/schema 2.4.0 → 3.0.0

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/dist/index.js CHANGED
@@ -1187,6 +1187,11 @@ function hexToRgba(hex, alpha) {
1187
1187
  return `rgba(${n >> 16 & 255},${n >> 8 & 255},${n & 255},${alpha})`;
1188
1188
  }
1189
1189
  var FONT_PREFIX_RE = /^((?:(?:italic|oblique|bold|bolder|lighter|normal|\d{3})\s+)+)/;
1190
+ var FONT_PX_RE = /(\d*\.?\d+)px/;
1191
+ function scaleFontPx(font, factor) {
1192
+ if (factor === 1) return font;
1193
+ return font.replace(FONT_PX_RE, (_m, n) => `${(Number(n) * factor).toFixed(2)}px`);
1194
+ }
1190
1195
  function composeFontShorthand(sz, font) {
1191
1196
  const m = FONT_PREFIX_RE.exec(font);
1192
1197
  if (m) return `${m[1].trim()} ${sz}px ${font.slice(m[0].length)}`;
@@ -1258,6 +1263,11 @@ var SpecInstance = class {
1258
1263
  /** Active glide between two resolved specs (live setParam/applyTrack). */
1259
1264
  transition = null;
1260
1265
  lastStructural = "";
1266
+ /** Viewport factor for absolute px sizes — 1 for `units: 'px'` specs. */
1267
+ fontScale() {
1268
+ if (this.effSpec.units === "px") return 1;
1269
+ return Math.min(this.w, this.h) / (this.effSpec.referenceViewport ?? LIMITS.referenceViewport);
1270
+ }
1261
1271
  sizeCanvas() {
1262
1272
  const dpr = Math.min(this.saverCtx.dpr, 2);
1263
1273
  this.canvas.width = Math.max(1, Math.round(this.w * dpr));
@@ -1472,7 +1482,7 @@ var SpecInstance = class {
1472
1482
  } else {
1473
1483
  ctx.textAlign = sprite.align ?? "center";
1474
1484
  ctx.textBaseline = sprite.baseline ?? "middle";
1475
- ctx.font = sprite.font ? /\dpx/.test(sprite.font) ? sprite.font : composeFontShorthand(sz, sprite.font) : `${sz}px system-ui, sans-serif`;
1485
+ ctx.font = sprite.font ? FONT_PX_RE.test(sprite.font) ? scaleFontPx(sprite.font, this.fontScale()) : composeFontShorthand(sz, sprite.font) : `${sz}px system-ui, sans-serif`;
1476
1486
  ctx.fillStyle = sprite.color ?? "#e6e8ef";
1477
1487
  const idx = spriteIndexAt(e, t, sprite.strings.length);
1478
1488
  const text = sprite.strings[idx] ?? sprite.strings[0];
@@ -2553,84 +2563,113 @@ var DASHBOARD_SPEC = {
2553
2563
  background: {
2554
2564
  type: "gradient",
2555
2565
  stops: [
2556
- { at: 0, color: "#06060c" },
2557
- { at: 0.5, color: "#0a0a14" },
2558
- { at: 1, color: "#0c0c18" }
2566
+ { at: 0, color: "#05070d" },
2567
+ { at: 0.55, color: "#080b14" },
2568
+ { at: 1, color: "#0a0d18" }
2559
2569
  ]
2560
2570
  },
2561
2571
  layers: [
2562
- // --- ambient depth ---
2563
- {
2564
- key: "dust",
2565
- count: 40,
2566
- sprite: { kind: "circle", radius: [1852e-7, 7407e-7], color: "#1a2538" },
2567
- alpha: [0.1, 0.25],
2568
- motion: { type: "drift", speed: [2778e-7, 1111e-6], bob: 2778e-7 }
2569
- },
2572
+ // ---- ambient: the LED wall behind everything ----
2570
2573
  {
2571
2574
  key: "led-wall",
2572
- count: 140,
2573
- sprite: { kind: "circle", radius: [8e-4, 12e-4], color: "#274058" },
2574
- alpha: [0.05, 0.11],
2575
- layout: { type: "grid", columns: 20, jitter: 0.15 },
2576
- // A slow breath travels diagonally across the wall of dots.
2577
- pulse: { amp: 0.3, period: 5e3, wave: { wavelength: 0.35, angle: 20 } },
2575
+ count: 240,
2576
+ sprite: { kind: "circle", radius: [7e-4, 11e-4], color: "#22344c" },
2577
+ alpha: [0.04, 0.1],
2578
+ layout: { type: "grid", columns: 24, jitter: 0.1 },
2579
+ pulse: { amp: 0.3, period: 6200, wave: { wavelength: 0.4, angle: 24 } },
2578
2580
  motion: { type: "static" }
2579
2581
  },
2580
- // --- header (boots first) ---
2582
+ // ---- frame chrome (boots first) ----
2583
+ {
2584
+ key: "rule-header",
2585
+ count: 1,
2586
+ position: { x: 0.5, y: 0.085 },
2587
+ sprite: { kind: "rect", width: [0.93, 0.93], aspect: [12e-4, 12e-4], color: "#24384f" },
2588
+ alpha: [0.8, 0.8],
2589
+ motion: { type: "static" },
2590
+ life: { enter: 100, fade: 400 }
2591
+ },
2592
+ {
2593
+ key: "rule-footer",
2594
+ count: 1,
2595
+ position: { x: 0.5, y: 0.915 },
2596
+ sprite: { kind: "rect", width: [0.93, 0.93], aspect: [12e-4, 12e-4], color: "#24384f" },
2597
+ alpha: [0.8, 0.8],
2598
+ motion: { type: "static" },
2599
+ life: { enter: 100, fade: 400 }
2600
+ },
2601
+ {
2602
+ key: "rule-col-left",
2603
+ count: 1,
2604
+ position: { x: 0.265, y: 0.5 },
2605
+ sprite: { kind: "rect", width: [9e-4, 9e-4], aspect: [620, 620], color: "#1c2c40" },
2606
+ alpha: [0.7, 0.7],
2607
+ motion: { type: "static" },
2608
+ life: { enter: 100, fade: 400 }
2609
+ },
2610
+ {
2611
+ key: "rule-col-right",
2612
+ count: 1,
2613
+ position: { x: 0.645, y: 0.5 },
2614
+ sprite: { kind: "rect", width: [9e-4, 9e-4], aspect: [620, 620], color: "#1c2c40" },
2615
+ alpha: [0.7, 0.7],
2616
+ motion: { type: "static" },
2617
+ life: { enter: 100, fade: 400 }
2618
+ },
2619
+ // ---- header band ----
2581
2620
  {
2582
2621
  key: "title",
2583
2622
  count: 1,
2584
- position: { x: 0.5, y: 0.045 },
2623
+ position: { x: 0.035, y: 0.052 },
2585
2624
  sprite: {
2586
2625
  kind: "text",
2587
- strings: ["CONTROL CENTER"],
2588
- color: "#556677",
2626
+ strings: ["VIREO-9 \xB7 TRANS-LUNAR RELAY \xB7 OPS WALL 03"],
2627
+ color: "#7f93ab",
2589
2628
  font: "600 13px 'SF Mono', monospace",
2590
- align: "center"
2629
+ align: "left"
2591
2630
  },
2592
2631
  motion: { type: "static" },
2593
2632
  life: { enter: 200, fade: 600 }
2594
2633
  },
2595
2634
  {
2596
- key: "status",
2635
+ key: "clock",
2597
2636
  count: 1,
2598
- position: { x: 0.94, y: 0.045 },
2637
+ position: { x: 0.5, y: 0.058 },
2599
2638
  sprite: {
2600
2639
  kind: "text",
2601
- strings: ["\u25CF ALL SYSTEMS GO"],
2602
- color: "#44cc66",
2603
- font: "bold 10px monospace",
2604
- align: "right"
2640
+ strings: ["04:17:26 UTC"],
2641
+ color: "#c8d4e4",
2642
+ font: "600 20px 'SF Mono', monospace",
2643
+ align: "center"
2605
2644
  },
2606
- pulse: { amp: 0.2, period: 2400 },
2607
2645
  motion: { type: "static" },
2608
2646
  life: { enter: 200, fade: 600 }
2609
2647
  },
2610
2648
  {
2611
- key: "clock",
2649
+ key: "status",
2612
2650
  count: 1,
2613
- position: { x: 0.06, y: 0.045 },
2651
+ position: { x: 0.965, y: 0.052 },
2614
2652
  sprite: {
2615
2653
  kind: "text",
2616
- strings: ["21:47"],
2617
- color: "#8899aa",
2618
- font: "bold 12px monospace",
2619
- align: "left"
2654
+ strings: ["\u25CF UPLINK LOCKED \xB7 WATCH C"],
2655
+ color: "#46d17a",
2656
+ font: "bold 11px 'SF Mono', monospace",
2657
+ align: "right"
2620
2658
  },
2659
+ pulse: { amp: 0.18, period: 2600 },
2621
2660
  motion: { type: "static" },
2622
2661
  life: { enter: 200, fade: 600 }
2623
2662
  },
2624
- // --- left column: readings (boots second) ---
2663
+ // ---- left column: arrays (boots second) ----
2625
2664
  {
2626
- key: "power-label",
2665
+ key: "dish1",
2627
2666
  count: 1,
2628
- position: { x: 0.06, y: 0.14 },
2667
+ position: { x: 0.035, y: 0.148 },
2629
2668
  sprite: {
2630
2669
  kind: "text",
2631
- strings: ["POWER"],
2632
- color: "#445566",
2633
- font: "9px monospace",
2670
+ strings: ["DSA-1 EAST AZ 214.6\xB0 EL 38.2\xB0"],
2671
+ color: "#9fb2c8",
2672
+ font: "11px 'SF Mono', monospace",
2634
2673
  align: "left",
2635
2674
  baseline: "top"
2636
2675
  },
@@ -2638,267 +2677,245 @@ var DASHBOARD_SPEC = {
2638
2677
  life: { enter: 700, fade: 600 }
2639
2678
  },
2640
2679
  {
2641
- key: "power-value",
2642
- count: 1,
2643
- position: { x: 0.06, y: 0.18 },
2644
- sprite: {
2645
- kind: "text",
2646
- strings: ["3.2 kW"],
2647
- color: "#ffd166",
2648
- font: "bold 26px monospace",
2649
- align: "left",
2650
- baseline: "top"
2651
- },
2680
+ key: "dish1-bars",
2681
+ count: 14,
2682
+ sprite: { kind: "rect", width: [38e-4, 38e-4], aspect: [0.5, 2.6], color: "#2ee6c8" },
2683
+ alpha: [0.3, 0.65],
2684
+ layout: { type: "grid", columns: 14 },
2685
+ region: { x: [0.035, 0.15], y: [0.183, 0.203] },
2686
+ pulse: { amp: 0.42, period: 1500, wave: { wavelength: 0.09, angle: 0 } },
2652
2687
  motion: { type: "static" },
2653
2688
  life: { enter: 700, fade: 600 }
2654
2689
  },
2655
2690
  {
2656
- key: "network-label",
2691
+ key: "dish2",
2657
2692
  count: 1,
2658
- position: { x: 0.06, y: 0.28 },
2693
+ position: { x: 0.035, y: 0.243 },
2659
2694
  sprite: {
2660
2695
  kind: "text",
2661
- strings: ["NETWORK"],
2662
- color: "#445566",
2663
- font: "9px monospace",
2696
+ strings: ["DSA-2 WEST AZ 097.1\xB0 EL 61.7\xB0"],
2697
+ color: "#9fb2c8",
2698
+ font: "11px 'SF Mono', monospace",
2664
2699
  align: "left",
2665
2700
  baseline: "top"
2666
2701
  },
2667
2702
  motion: { type: "static" },
2668
- life: { enter: 700, fade: 600 }
2703
+ life: { enter: 850, fade: 600 }
2669
2704
  },
2670
2705
  {
2671
- key: "network-value",
2672
- count: 1,
2673
- position: { x: 0.06, y: 0.32 },
2674
- sprite: {
2675
- kind: "text",
2676
- strings: ["940 Mb/s"],
2677
- color: "#44aaff",
2678
- font: "bold 26px monospace",
2679
- align: "left",
2680
- baseline: "top"
2681
- },
2706
+ key: "dish2-bars",
2707
+ count: 14,
2708
+ sprite: { kind: "rect", width: [38e-4, 38e-4], aspect: [0.5, 2.2], color: "#44aaff" },
2709
+ alpha: [0.3, 0.6],
2710
+ layout: { type: "grid", columns: 14 },
2711
+ region: { x: [0.035, 0.15], y: [0.278, 0.298] },
2712
+ pulse: { amp: 0.4, period: 1900, wave: { wavelength: 0.11, angle: 0 } },
2682
2713
  motion: { type: "static" },
2683
- life: { enter: 700, fade: 600 }
2714
+ life: { enter: 850, fade: 600 }
2684
2715
  },
2685
2716
  {
2686
- key: "climate-label",
2717
+ key: "dish3",
2687
2718
  count: 1,
2688
- position: { x: 0.06, y: 0.42 },
2719
+ position: { x: 0.035, y: 0.338 },
2689
2720
  sprite: {
2690
2721
  kind: "text",
2691
- strings: ["CLIMATE"],
2692
- color: "#445566",
2693
- font: "9px monospace",
2722
+ strings: ["DSA-3 POLAR AZ 002.4\xB0 EL 12.9\xB0 \u25B3 WIND"],
2723
+ color: "#5d7089",
2724
+ font: "11px 'SF Mono', monospace",
2694
2725
  align: "left",
2695
2726
  baseline: "top"
2696
2727
  },
2697
2728
  motion: { type: "static" },
2698
- life: { enter: 700, fade: 600 }
2729
+ life: { enter: 1e3, fade: 600 }
2699
2730
  },
2700
2731
  {
2701
- key: "climate-value",
2702
- count: 1,
2703
- position: { x: 0.06, y: 0.46 },
2704
- sprite: {
2705
- kind: "text",
2706
- strings: ["21.5\xB0"],
2707
- color: "#44ddcc",
2708
- font: "bold 26px monospace",
2709
- align: "left",
2710
- baseline: "top"
2711
- },
2732
+ key: "dish3-bars",
2733
+ count: 14,
2734
+ sprite: { kind: "rect", width: [38e-4, 38e-4], aspect: [0.4, 1.1], color: "#5d7089" },
2735
+ alpha: [0.2, 0.4],
2736
+ layout: { type: "grid", columns: 14 },
2737
+ region: { x: [0.035, 0.15], y: [0.373, 0.393] },
2738
+ pulse: { amp: 0.3, period: 2600, wave: { wavelength: 0.14, angle: 0 } },
2712
2739
  motion: { type: "static" },
2713
- life: { enter: 700, fade: 600 }
2740
+ life: { enter: 1e3, fade: 600 }
2741
+ },
2742
+ {
2743
+ key: "dish-leds",
2744
+ count: 3,
2745
+ sprite: { kind: "circle", radius: [4e-3, 4e-3], color: "#46d17a" },
2746
+ alpha: [0.9, 0.9],
2747
+ layout: { type: "grid", columns: 1 },
2748
+ region: { x: [0.238, 0.246], y: [0.15, 0.35] },
2749
+ pulse: { amp: 0.25, period: 2100 },
2750
+ motion: { type: "static" },
2751
+ life: { enter: 1e3, fade: 600 }
2714
2752
  },
2753
+ // carrier + doppler + station env
2715
2754
  {
2716
- key: "alerts-label",
2755
+ key: "carrier-wave",
2756
+ count: 30,
2757
+ sprite: { kind: "rect", width: [32e-4, 32e-4], aspect: [0.4, 3.6], color: "#2ee6c8" },
2758
+ alpha: [0.25, 0.6],
2759
+ layout: { type: "grid", columns: 30 },
2760
+ region: { x: [0.035, 0.245], y: [0.47, 0.5] },
2761
+ pulse: { amp: 0.5, period: 2100, wave: { wavelength: 0.16, angle: 0 } },
2762
+ motion: { type: "static" },
2763
+ life: { enter: 1150, fade: 600 }
2764
+ },
2765
+ {
2766
+ key: "doppler",
2717
2767
  count: 1,
2718
- position: { x: 0.06, y: 0.56 },
2768
+ position: { x: 0.035, y: 0.535 },
2719
2769
  sprite: {
2720
2770
  kind: "text",
2721
- strings: ["ALERTS"],
2722
- color: "#445566",
2723
- font: "9px monospace",
2771
+ strings: ["CARRIER X-BAND \xB7 DOPPLER +2.114 kHz \xB7 DRIFT 0.03"],
2772
+ color: "#9fb2c8",
2773
+ font: "10px 'SF Mono', monospace",
2724
2774
  align: "left",
2725
2775
  baseline: "top"
2726
2776
  },
2727
2777
  motion: { type: "static" },
2728
- life: { enter: 700, fade: 600 }
2778
+ life: { enter: 1150, fade: 600 }
2729
2779
  },
2730
2780
  {
2731
- key: "alerts-value",
2781
+ key: "env-line",
2732
2782
  count: 1,
2733
- position: { x: 0.06, y: 0.6 },
2783
+ position: { x: 0.035, y: 0.6 },
2734
2784
  sprite: {
2735
2785
  kind: "text",
2736
- strings: ["0"],
2737
- color: "#44cc66",
2738
- font: "bold 26px monospace",
2786
+ strings: ["STATION \xB7 PWR 28.1 V \xB7 THERM 312 K \xB7 GYRO NOM \xB7 PROP 81%"],
2787
+ color: "#5d7089",
2788
+ font: "10px 'SF Mono', monospace",
2739
2789
  align: "left",
2740
2790
  baseline: "top"
2741
2791
  },
2742
2792
  motion: { type: "static" },
2743
- life: { enter: 700, fade: 600 }
2793
+ life: { enter: 1300, fade: 600 }
2744
2794
  },
2745
- // --- center: energy gauge (boots third) ---
2795
+ // ---- center: the orbital plot (boots third) ----
2746
2796
  {
2747
- key: "gauge-ring",
2797
+ key: "moon",
2748
2798
  count: 1,
2749
- position: { x: 0.4, y: 0.36 },
2750
- sprite: { kind: "ring", radius: [0.105, 0.105], color: "#1e3a52", width: 28e-4 },
2751
- alpha: [0.85, 0.85],
2799
+ position: { x: 0.455, y: 0.4 },
2800
+ sprite: { kind: "circle", radius: [0.028, 0.028], color: "#8fa3bd", soft: true },
2801
+ alpha: [0.9, 0.9],
2752
2802
  motion: { type: "static" },
2753
2803
  life: { enter: 1200, fade: 700 }
2754
2804
  },
2755
2805
  {
2756
- key: "gauge-glow",
2757
- count: 1,
2758
- position: { x: 0.4, y: 0.36 },
2759
- sprite: { kind: "ring", radius: [0.088, 0.088], color: "#2ee6c8", width: 16e-4 },
2806
+ key: "orbit-guides",
2807
+ count: 3,
2808
+ // All three guides pin to the plot centre; the seeded radius range
2809
+ // spreads them into concentric orbits (`position` is count:1-only).
2810
+ region: { x: [0.455, 0.455], y: [0.4, 0.4] },
2811
+ sprite: { kind: "ring", radius: [0.075, 0.185], color: "#1e3a52", width: 11e-4 },
2760
2812
  alpha: [0.55, 0.55],
2761
- blend: "lighter",
2762
- pulse: { amp: 0.25, period: 4e3 },
2763
- grow: { amp: 0.05, period: 4e3 },
2764
- motion: { type: "static" },
2765
- life: { enter: 1200, fade: 700 }
2766
- },
2767
- {
2768
- key: "gauge-label",
2769
- count: 1,
2770
- position: { x: 0.4, y: 0.29 },
2771
- sprite: {
2772
- kind: "text",
2773
- strings: ["ENERGY"],
2774
- color: "#445566",
2775
- font: "9px monospace",
2776
- align: "center"
2777
- },
2778
- motion: { type: "static" },
2779
- life: { enter: 1200, fade: 700 }
2780
- },
2781
- {
2782
- key: "gauge-value",
2783
- count: 1,
2784
- position: { x: 0.4, y: 0.375 },
2785
- sprite: {
2786
- kind: "text",
2787
- strings: ["73%"],
2788
- color: "#2ee6c8",
2789
- font: "bold 34px monospace",
2790
- align: "center"
2791
- },
2792
2813
  motion: { type: "static" },
2793
2814
  life: { enter: 1200, fade: 700 }
2794
2815
  },
2795
2816
  {
2796
- key: "equalizer",
2797
- count: 22,
2817
+ key: "fleet",
2818
+ count: 5,
2798
2819
  sprite: {
2799
- kind: "rect",
2800
- width: [5e-3, 5e-3],
2801
- aspect: [0.6, 3.4],
2820
+ kind: "circle",
2821
+ radius: [45e-4, 65e-4],
2802
2822
  color: "#2ee6c8",
2803
- colors: ["#2ee6c8", "#44aaff", "#aa88ff"],
2804
- colorWeights: [3, 2, 1]
2823
+ colors: ["#2ee6c8", "#44aaff", "#ffd166", "#aa88ff", "#ff9f43"]
2805
2824
  },
2806
- alpha: [0.35, 0.7],
2807
- layout: { type: "grid", columns: 22 },
2808
- region: { x: [0.28, 0.52], y: [0.585, 0.615] },
2809
- // Wave-phased pulse sweeps along the bars — reads as a live meter.
2810
- pulse: { amp: 0.4, period: 1600, wave: { wavelength: 0.1, angle: 0 } },
2811
- motion: { type: "static" },
2812
- life: { enter: 1200, fade: 700 }
2825
+ alpha: [0.85, 0.95],
2826
+ blend: "lighter",
2827
+ motion: { type: "orbit", speed: [4, 11], radius: [0.075, 0.185], center: { x: 0.455, y: 0.4 } },
2828
+ trail: { length: 9, fade: 0.75 },
2829
+ // The relay web: each craft holds a comm chain to its neighbours.
2830
+ links: { k: 2, maxDist: 0.5, color: "#2ee6c8", alpha: 0.2, width: 12e-4, mode: "chain" },
2831
+ life: { enter: 1350, fade: 700 }
2813
2832
  },
2814
- // --- right column: agenda + devices (boots fourth) ---
2815
2833
  {
2816
- key: "agenda-label",
2834
+ key: "fleet-legend",
2817
2835
  count: 1,
2818
- position: { x: 0.64, y: 0.14 },
2836
+ position: { x: 0.455, y: 0.63 },
2819
2837
  sprite: {
2820
2838
  kind: "text",
2821
- strings: ["AGENDA"],
2822
- color: "#445566",
2823
- font: "9px monospace",
2824
- align: "left",
2839
+ strings: ["TRACKING 5 \xB7 KESTREL TIDE-2 LIMELIGHT CATWALK-1 SLIPSTREAM"],
2840
+ color: "#5d7089",
2841
+ font: "9px 'SF Mono', monospace",
2842
+ align: "center",
2825
2843
  baseline: "top"
2826
2844
  },
2827
2845
  motion: { type: "static" },
2828
- life: { enter: 1700, fade: 600 }
2846
+ life: { enter: 1500, fade: 700 }
2829
2847
  },
2848
+ // pass schedule under the plot
2830
2849
  {
2831
- key: "agenda-1",
2850
+ key: "pass-label",
2832
2851
  count: 1,
2833
- position: { x: 0.64, y: 0.19 },
2852
+ position: { x: 0.3, y: 0.69 },
2834
2853
  sprite: {
2835
2854
  kind: "text",
2836
- strings: ["09:00 Standup"],
2837
- color: "#8899aa",
2838
- font: "11px monospace",
2855
+ strings: ["PASS SCHEDULE"],
2856
+ color: "#41536b",
2857
+ font: "9px 'SF Mono', monospace",
2839
2858
  align: "left",
2840
- baseline: "top",
2841
- maxWidth: 0.2593
2859
+ baseline: "top"
2842
2860
  },
2843
2861
  motion: { type: "static" },
2844
- life: { enter: 1700, fade: 600 }
2862
+ life: { enter: 1650, fade: 600 }
2845
2863
  },
2846
2864
  {
2847
- key: "agenda-2",
2865
+ key: "pass-1",
2848
2866
  count: 1,
2849
- position: { x: 0.64, y: 0.23 },
2867
+ position: { x: 0.3, y: 0.72 },
2850
2868
  sprite: {
2851
2869
  kind: "text",
2852
- strings: ["12:30 Lunch w/ Kai"],
2853
- color: "#778899",
2854
- font: "11px monospace",
2870
+ strings: ["04:41 CATWALK-1 ACQUIRE \xB7 DSA-1 \u25B2 12 MIN"],
2871
+ color: "#c8d4e4",
2872
+ font: "11px 'SF Mono', monospace",
2855
2873
  align: "left",
2856
- baseline: "top",
2857
- maxWidth: 0.2593
2874
+ baseline: "top"
2858
2875
  },
2859
2876
  motion: { type: "static" },
2860
- life: { enter: 1700, fade: 600 }
2877
+ life: { enter: 1650, fade: 600 }
2861
2878
  },
2862
2879
  {
2863
- key: "agenda-3",
2880
+ key: "pass-2",
2864
2881
  count: 1,
2865
- position: { x: 0.64, y: 0.27 },
2882
+ position: { x: 0.3, y: 0.757 },
2866
2883
  sprite: {
2867
2884
  kind: "text",
2868
- strings: ["18:00 Gym"],
2869
- color: "#667788",
2870
- font: "11px monospace",
2885
+ strings: ["05:03 TIDE-2 OCCULT EXIT \xB7 DSA-2"],
2886
+ color: "#7f93ab",
2887
+ font: "11px 'SF Mono', monospace",
2871
2888
  align: "left",
2872
- baseline: "top",
2873
- maxWidth: 0.2593
2889
+ baseline: "top"
2874
2890
  },
2875
2891
  motion: { type: "static" },
2876
- life: { enter: 1700, fade: 600 }
2892
+ life: { enter: 1750, fade: 600 }
2877
2893
  },
2878
2894
  {
2879
- key: "devices-label",
2895
+ key: "pass-3",
2880
2896
  count: 1,
2881
- position: { x: 0.64, y: 0.36 },
2897
+ position: { x: 0.3, y: 0.794 },
2882
2898
  sprite: {
2883
2899
  kind: "text",
2884
- strings: ["DEVICES"],
2885
- color: "#445566",
2886
- font: "9px monospace",
2900
+ strings: ["05:47 KESTREL RANGING \xB7 DSA-1+2"],
2901
+ color: "#7f93ab",
2902
+ font: "11px 'SF Mono', monospace",
2887
2903
  align: "left",
2888
2904
  baseline: "top"
2889
2905
  },
2890
2906
  motion: { type: "static" },
2891
- life: { enter: 1700, fade: 600 }
2907
+ life: { enter: 1850, fade: 600 }
2892
2908
  },
2909
+ // ---- right column: telemetry (boots fourth) ----
2893
2910
  {
2894
- key: "devices-1",
2911
+ key: "signal-label",
2895
2912
  count: 1,
2896
- position: { x: 0.64, y: 0.41 },
2913
+ position: { x: 0.665, y: 0.115 },
2897
2914
  sprite: {
2898
2915
  kind: "text",
2899
- strings: ["Lights 6 on"],
2900
- color: "#8899aa",
2901
- font: "11px monospace",
2916
+ strings: ["PRIMARY CARRIER \xB7 CATWALK-1"],
2917
+ color: "#41536b",
2918
+ font: "9px 'SF Mono', monospace",
2902
2919
  align: "left",
2903
2920
  baseline: "top"
2904
2921
  },
@@ -2906,14 +2923,14 @@ var DASHBOARD_SPEC = {
2906
2923
  life: { enter: 1700, fade: 600 }
2907
2924
  },
2908
2925
  {
2909
- key: "devices-2",
2926
+ key: "signal-value",
2910
2927
  count: 1,
2911
- position: { x: 0.64, y: 0.45 },
2928
+ position: { x: 0.665, y: 0.14 },
2912
2929
  sprite: {
2913
2930
  kind: "text",
2914
- strings: ["Thermostat eco"],
2915
- color: "#778899",
2916
- font: "11px monospace",
2931
+ strings: ["-112.4 dBm"],
2932
+ color: "#ffd166",
2933
+ font: "bold 30px 'SF Mono', monospace",
2917
2934
  align: "left",
2918
2935
  baseline: "top"
2919
2936
  },
@@ -2921,130 +2938,130 @@ var DASHBOARD_SPEC = {
2921
2938
  life: { enter: 1700, fade: 600 }
2922
2939
  },
2923
2940
  {
2924
- key: "devices-3",
2941
+ key: "telemetry-row",
2925
2942
  count: 1,
2926
- position: { x: 0.64, y: 0.49 },
2943
+ position: { x: 0.665, y: 0.215 },
2927
2944
  sprite: {
2928
2945
  kind: "text",
2929
- strings: ["Locks secured"],
2930
- color: "#667788",
2931
- font: "11px monospace",
2946
+ strings: ["RANGE 1.28 LS DOWNLINK 2.048 Mb/s BUFFER 38%"],
2947
+ color: "#9fb2c8",
2948
+ font: "11px 'SF Mono', monospace",
2932
2949
  align: "left",
2933
2950
  baseline: "top"
2934
2951
  },
2935
2952
  motion: { type: "static" },
2936
- life: { enter: 1700, fade: 600 }
2953
+ life: { enter: 1800, fade: 600 }
2937
2954
  },
2955
+ // event log
2938
2956
  {
2939
- key: "devices-4",
2957
+ key: "feed-1",
2940
2958
  count: 1,
2941
- position: { x: 0.64, y: 0.53 },
2959
+ position: { x: 0.665, y: 0.3 },
2942
2960
  sprite: {
2943
2961
  kind: "text",
2944
- strings: ["Media paused"],
2945
- color: "#556677",
2946
- font: "11px monospace",
2962
+ strings: ["04:15:02 DSA-1 LOCK RE-ACQUIRED"],
2963
+ color: "#9fb2c8",
2964
+ font: "10px 'SF Mono', monospace",
2947
2965
  align: "left",
2948
2966
  baseline: "top"
2949
2967
  },
2950
2968
  motion: { type: "static" },
2951
- life: { enter: 1700, fade: 600 }
2969
+ life: { enter: 1950, fade: 600 }
2952
2970
  },
2953
- // --- bottom: activity feed (boots last) ---
2954
2971
  {
2955
- key: "feed-label",
2972
+ key: "feed-2",
2956
2973
  count: 1,
2957
- position: { x: 0.06, y: 0.74 },
2974
+ position: { x: 0.665, y: 0.334 },
2958
2975
  sprite: {
2959
2976
  kind: "text",
2960
- strings: ["ACTIVITY"],
2961
- color: "#445566",
2962
- font: "9px monospace",
2977
+ strings: ["04:12:47 CATWALK-1 WHEEL DESAT OK"],
2978
+ color: "#7f93ab",
2979
+ font: "10px 'SF Mono', monospace",
2963
2980
  align: "left",
2964
2981
  baseline: "top"
2965
2982
  },
2966
2983
  motion: { type: "static" },
2967
- life: { enter: 2200, fade: 600 }
2984
+ life: { enter: 2050, fade: 600 }
2968
2985
  },
2969
2986
  {
2970
- key: "feed-1",
2987
+ key: "feed-3",
2971
2988
  count: 1,
2972
- position: { x: 0.06, y: 0.78 },
2989
+ position: { x: 0.665, y: 0.368 },
2973
2990
  sprite: {
2974
2991
  kind: "text",
2975
- strings: ["21:42 Front door locked"],
2976
- color: "#7a8a7a",
2977
- font: "10px monospace",
2992
+ strings: ["04:09:31 RANGING RESIDUAL 0.4 m"],
2993
+ color: "#5d7089",
2994
+ font: "10px 'SF Mono', monospace",
2978
2995
  align: "left",
2979
- baseline: "top",
2980
- maxWidth: 0.5556
2996
+ baseline: "top"
2981
2997
  },
2982
2998
  motion: { type: "static" },
2983
- life: { enter: 2200, fade: 600 }
2999
+ life: { enter: 2150, fade: 600 }
2984
3000
  },
3001
+ // alert + relay load
2985
3002
  {
2986
- key: "feed-2",
3003
+ key: "alert",
2987
3004
  count: 1,
2988
- position: { x: 0.06, y: 0.82 },
3005
+ position: { x: 0.665, y: 0.49 },
2989
3006
  sprite: {
2990
3007
  kind: "text",
2991
- strings: ["21:36 Thermostat \u2192 eco"],
2992
- color: "#6a7a6a",
2993
- font: "10px monospace",
3008
+ strings: ["\u25B3 SOLAR FLUX ELEVATED \u2014 MONITORING"],
3009
+ color: "#ff9f43",
3010
+ font: "bold 11px 'SF Mono', monospace",
2994
3011
  align: "left",
2995
- baseline: "top",
2996
- maxWidth: 0.5556
3012
+ baseline: "top"
2997
3013
  },
3014
+ pulse: { amp: 0.22, period: 3400 },
2998
3015
  motion: { type: "static" },
2999
- life: { enter: 2200, fade: 600 }
3016
+ life: { enter: 2450, fade: 600 }
3000
3017
  },
3001
3018
  {
3002
- key: "feed-3",
3003
- count: 1,
3004
- position: { x: 0.06, y: 0.86 },
3019
+ key: "load-bars",
3020
+ count: 24,
3005
3021
  sprite: {
3006
- kind: "text",
3007
- strings: ["21:14 Backup completed"],
3008
- color: "#5a6a5a",
3009
- font: "10px monospace",
3010
- align: "left",
3011
- baseline: "top",
3012
- maxWidth: 0.5556
3022
+ kind: "rect",
3023
+ width: [42e-4, 42e-4],
3024
+ aspect: [0.5, 3.2],
3025
+ color: "#aa88ff",
3026
+ colors: ["#aa88ff", "#44aaff", "#2ee6c8"],
3027
+ colorWeights: [2, 2, 3]
3013
3028
  },
3029
+ alpha: [0.3, 0.65],
3030
+ layout: { type: "grid", columns: 24 },
3031
+ region: { x: [0.665, 0.965], y: [0.58, 0.615] },
3032
+ pulse: { amp: 0.45, period: 1800, wave: { wavelength: 0.12, angle: 0 } },
3014
3033
  motion: { type: "static" },
3015
- life: { enter: 2200, fade: 600 }
3034
+ life: { enter: 2550, fade: 600 }
3016
3035
  },
3017
3036
  {
3018
- key: "feed-4",
3037
+ key: "load-note",
3019
3038
  count: 1,
3020
- position: { x: 0.06, y: 0.9 },
3039
+ position: { x: 0.665, y: 0.65 },
3021
3040
  sprite: {
3022
3041
  kind: "text",
3023
- strings: ["20:58 Motion \xB7 driveway"],
3024
- color: "#4d5e4d",
3025
- font: "10px monospace",
3042
+ strings: ["RELAY LOAD \xB7 QUEUE 14 FRAMES \xB7 NOMINAL"],
3043
+ color: "#5d7089",
3044
+ font: "10px 'SF Mono', monospace",
3026
3045
  align: "left",
3027
- baseline: "top",
3028
- maxWidth: 0.5556
3046
+ baseline: "top"
3029
3047
  },
3030
3048
  motion: { type: "static" },
3031
- life: { enter: 2200, fade: 600 }
3049
+ life: { enter: 2550, fade: 600 }
3032
3050
  },
3051
+ // ---- footer band ----
3033
3052
  {
3034
- key: "feed-5",
3053
+ key: "footer",
3035
3054
  count: 1,
3036
- position: { x: 0.06, y: 0.94 },
3055
+ position: { x: 0.035, y: 0.95 },
3037
3056
  sprite: {
3038
3057
  kind: "text",
3039
- strings: ["20:41 Sunset scene on"],
3040
- color: "#3d4e3d",
3041
- font: "10px monospace",
3042
- align: "left",
3043
- baseline: "top",
3044
- maxWidth: 0.5556
3058
+ strings: ["NET STATE GREEN \xB7 3 ARRAYS \xB7 5 CARRIERS \xB7 DSN HANDOVER 23:34 \xB7 NEXT WINDOW 04:41:00"],
3059
+ color: "#41536b",
3060
+ font: "9px 'SF Mono', monospace",
3061
+ align: "left"
3045
3062
  },
3046
3063
  motion: { type: "static" },
3047
- life: { enter: 2200, fade: 600 }
3064
+ life: { enter: 2750, fade: 600 }
3048
3065
  }
3049
3066
  ]
3050
3067
  };
@@ -3182,6 +3199,120 @@ var MATRIX_RAIN_SPEC = {
3182
3199
  ]
3183
3200
  };
3184
3201
 
3202
+ // src/examples/nostalghia-candle.ts
3203
+ var NOSTALGHIA_CANDLE_SPEC = {
3204
+ schemaVersion: 1,
3205
+ id: "nostalghia-candle",
3206
+ label: "Nostalghia's Candle",
3207
+ seed: 1983,
3208
+ motionIntensity: "calm",
3209
+ background: {
3210
+ type: "gradient",
3211
+ stops: [
3212
+ { at: 0, color: "#050302" },
3213
+ { at: 0.55, color: "#0a0704" },
3214
+ { at: 1, color: "#120c08" }
3215
+ ]
3216
+ },
3217
+ layers: [
3218
+ {
3219
+ key: "halo",
3220
+ count: 1,
3221
+ position: { x: 0.5, y: 0.52 },
3222
+ sprite: {
3223
+ kind: "circle",
3224
+ radius: [0.11, 0.11],
3225
+ color: "#c4782a",
3226
+ soft: true
3227
+ },
3228
+ // Base 0.04 + amp 0.02 → breathes ~0.02..0.06; never clamps to 0.
3229
+ // (pulse.amp is ADDED to alpha, not multiplied.) Kept subordinate to the flame.
3230
+ alpha: [0.04, 0.04],
3231
+ blend: "lighter",
3232
+ pulse: { amp: 0.02, period: 1e4 },
3233
+ grow: { amp: 0.08, period: 1e4 },
3234
+ motion: { type: "static" }
3235
+ },
3236
+ {
3237
+ key: "smoke",
3238
+ count: 3,
3239
+ sprite: {
3240
+ kind: "circle",
3241
+ radius: [0.01, 0.022],
3242
+ color: "#6a6258",
3243
+ soft: true
3244
+ },
3245
+ alpha: [0.02, 0.04],
3246
+ blend: "lighter",
3247
+ region: { x: [0.46, 0.54], y: [0.36, 0.48] },
3248
+ pulse: { amp: 0.015, period: 4500 },
3249
+ motion: { type: "rise", speed: [2e-3, 4e-3], sway: 8e-3 }
3250
+ },
3251
+ {
3252
+ key: "flame-glow",
3253
+ count: 1,
3254
+ sprite: {
3255
+ kind: "circle",
3256
+ radius: [0.028, 0.028],
3257
+ color: "#ffb040",
3258
+ soft: true
3259
+ },
3260
+ alpha: [0.32, 0.32],
3261
+ blend: "lighter",
3262
+ pulse: { amp: 0.12, period: 1400 },
3263
+ grow: { amp: 0.4, period: 1600 },
3264
+ // Tiny orbit = positional lean without drifting off-center (wander has vx).
3265
+ motion: {
3266
+ type: "orbit",
3267
+ speed: [18, 18],
3268
+ radius: [3e-3, 3e-3],
3269
+ center: { x: 0.5, y: 0.52 }
3270
+ }
3271
+ },
3272
+ {
3273
+ key: "flame-core",
3274
+ count: 1,
3275
+ sprite: {
3276
+ kind: "circle",
3277
+ radius: [0.014, 0.014],
3278
+ color: "#fff6e0",
3279
+ soft: true
3280
+ },
3281
+ alpha: [0.95, 0.95],
3282
+ blend: "lighter",
3283
+ pulse: { amp: 0.25, period: 900 },
3284
+ grow: { amp: 0.55, period: 1100 },
3285
+ motion: {
3286
+ type: "orbit",
3287
+ speed: [22, 22],
3288
+ radius: [25e-4, 25e-4],
3289
+ center: { x: 0.5, y: 0.52 }
3290
+ }
3291
+ },
3292
+ {
3293
+ key: "embers",
3294
+ count: 7,
3295
+ sprite: {
3296
+ kind: "circle",
3297
+ radius: [18e-4, 4e-3],
3298
+ color: "#e08a34",
3299
+ soft: true
3300
+ },
3301
+ alpha: [0.4, 0.8],
3302
+ blend: "lighter",
3303
+ region: { x: [0.35, 0.65], y: [0.4, 0.7] },
3304
+ pulse: { amp: 0.2, period: 2200 },
3305
+ trail: { length: 2200, fade: 1 },
3306
+ motion: {
3307
+ type: "drift",
3308
+ speed: [4e-3, 0.012],
3309
+ angle: 270,
3310
+ bob: 8e-3
3311
+ }
3312
+ }
3313
+ ]
3314
+ };
3315
+
3185
3316
  // src/examples/polygons.ts
3186
3317
  var POLYGONS_SPEC = {
3187
3318
  schemaVersion: 1,
@@ -3627,7 +3758,8 @@ var SCHEMA_EXAMPLES = [
3627
3758
  { id: "warp-tunnel", label: "Warp Tunnel", spec: WARP_TUNNEL_SPEC },
3628
3759
  { id: "polygons", label: "Polygons", spec: POLYGONS_SPEC },
3629
3760
  { id: "matrix-rain", label: "Matrix Rain", spec: MATRIX_RAIN_SPEC },
3630
- { id: "procession", label: "Night Procession", spec: PROCESSION_SPEC }
3761
+ { id: "procession", label: "Night Procession", spec: PROCESSION_SPEC },
3762
+ { id: "nostalghia-candle", label: "Nostalghia's Candle", spec: NOSTALGHIA_CANDLE_SPEC }
3631
3763
  ];
3632
3764
  var EXAMPLE_SPECS = SCHEMA_EXAMPLES.map((e) => e.spec);
3633
3765
  var EXAMPLE_BY_ID = Object.fromEntries(
@@ -3644,6 +3776,7 @@ export {
3644
3776
  LANTERNS_SPEC,
3645
3777
  LIMITS,
3646
3778
  MATRIX_RAIN_SPEC,
3779
+ NOSTALGHIA_CANDLE_SPEC,
3647
3780
  ORRERY_SPEC,
3648
3781
  POLYGONS_SPEC,
3649
3782
  PROCESSION_SPEC,