@kontourai/survey 0.7.2 → 1.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.
@@ -11,11 +11,11 @@
11
11
  /* Local aliases preserve the existing workbench selectors while the values
12
12
  come from the shared Console Kit token contract. */
13
13
  --ink-1000: var(--k-bg);
14
- --ink-900: #0a0e13;
15
- --ink-850: #0d1219;
14
+ --ink-900: color-mix(in srgb, var(--k-bg) 60%, var(--k-panel));
15
+ --ink-850: color-mix(in srgb, var(--k-bg) 40%, var(--k-panel));
16
16
  --ink-800: var(--k-panel);
17
17
  --ink-750: var(--k-panel-raised);
18
- --ink-700: #1d2937;
18
+ --ink-700: color-mix(in srgb, var(--k-panel-raised) 80%, var(--k-line-strong));
19
19
  --paper: var(--k-text);
20
20
  --paper-dim: var(--k-text-muted);
21
21
  --paper-faint: var(--k-text-faint);
@@ -30,11 +30,52 @@
30
30
  --radius: var(--k-radius-md);
31
31
  --radius-sm: var(--k-radius-sm);
32
32
 
33
+ /* Panel surface alpha — stronger contrast in light mode, subtle in dark */
34
+ --surface-alpha: 0.55;
35
+ /* Overlay tint alpha for brand-coloured gradient overlays */
36
+ --overlay-alpha: 0.10;
37
+ /* Grain overlay: visible dark only, 0 in light */
38
+ --grain-opacity: 0.04;
39
+ /* VS marker bg */
40
+ --vs-bg: var(--ink-750);
41
+
33
42
  font-family: var(--k-font-ui);
34
43
  background: var(--ink-1000);
35
44
  color: var(--paper);
36
45
  }
37
46
 
47
+ /* ---- Light mode token overrides --------------------------------------- */
48
+ /* The token sheet already flips --k-bg/panel/text etc. for [data-theme="light"].
49
+ Here we tune the workbench-specific overlay and surface alphas so the
50
+ grain/gradient overlays are invisible in light mode, and panel surfaces
51
+ have enough contrast without the dark alpha tricks. */
52
+ [data-theme="light"] {
53
+ color-scheme: light;
54
+ /* Structural tokens: override .theme-survey which hardcodes dark values.
55
+ These match the [data-theme="light"] block in tokens.css. */
56
+ --k-bg: #f5f4ef;
57
+ --k-panel: #ffffff;
58
+ --k-panel-raised: #fbfaf7;
59
+ --k-line: rgba(36, 40, 46, 0.12);
60
+ --k-line-strong: rgba(36, 40, 46, 0.20);
61
+ --k-text: #202124;
62
+ --k-text-muted: #5b626b;
63
+ --k-text-faint: #707782;
64
+ --k-positive: #168257;
65
+ --k-caution: #8a5a00;
66
+ --k-negative: #c83b3b;
67
+ --k-active: #3f6fd6;
68
+ /* Workbench-specific overlay and surface alphas */
69
+ --grain-opacity: 0;
70
+ --overlay-alpha: 0.06;
71
+ --surface-alpha: 0.70;
72
+ --vs-bg: var(--ink-750);
73
+ /* In light mode the brand accent is remapped by themes.css — ensure the
74
+ ink aliases derive cleanly from the token bg/panel values. */
75
+ --ink-900: color-mix(in srgb, var(--k-bg) 60%, var(--k-panel));
76
+ --ink-850: color-mix(in srgb, var(--k-bg) 40%, var(--k-panel));
77
+ }
78
+
38
79
  * {
39
80
  box-sizing: border-box;
40
81
  }
@@ -44,14 +85,15 @@ body {
44
85
  min-width: 320px;
45
86
  position: relative;
46
87
  background:
47
- radial-gradient(1100px 620px at 12% -8%, rgba(92, 224, 198, 0.12), transparent 60%),
48
- radial-gradient(900px 560px at 100% 0%, rgba(122, 162, 255, 0.12), transparent 55%),
49
- radial-gradient(800px 800px at 88% 110%, rgba(243, 177, 75, 0.07), transparent 60%),
88
+ radial-gradient(1100px 620px at 12% -8%, color-mix(in srgb, var(--k-brand) 10%, transparent), transparent 60%),
89
+ radial-gradient(900px 560px at 100% 0%, color-mix(in srgb, var(--k-active) 10%, transparent), transparent 55%),
90
+ radial-gradient(800px 800px at 88% 110%, color-mix(in srgb, var(--k-caution) 7%, transparent), transparent 60%),
50
91
  linear-gradient(180deg, var(--ink-1000), var(--ink-900) 55%, var(--ink-1000));
51
92
  background-attachment: fixed;
52
93
  }
53
94
 
54
- /* Grain + faint engineering grid for control-room atmosphere. */
95
+ /* Grain + faint engineering grid for control-room atmosphere.
96
+ Grain opacity is 0 in light mode via --grain-opacity. */
55
97
  body::before {
56
98
  content: "";
57
99
  position: fixed;
@@ -59,10 +101,52 @@ body::before {
59
101
  z-index: 0;
60
102
  pointer-events: none;
61
103
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.55'/%3E%3C/svg%3E");
62
- opacity: 0.04;
104
+ opacity: var(--grain-opacity);
63
105
  mix-blend-mode: screen;
64
106
  }
65
107
 
108
+ /* ---- Demo page chrome -------------------------------------------------- */
109
+ /* Light/dark toggle button on the demo wrapper around the workbench */
110
+ .demo-toolbar {
111
+ position: fixed;
112
+ top: 12px;
113
+ right: 14px;
114
+ z-index: 100;
115
+ display: flex;
116
+ align-items: center;
117
+ gap: 8px;
118
+ }
119
+
120
+ .theme-toggle {
121
+ display: flex;
122
+ align-items: center;
123
+ gap: 6px;
124
+ height: 32px;
125
+ padding: 0 12px;
126
+ border: 1px solid var(--line-strong);
127
+ border-radius: 999px;
128
+ background: color-mix(in srgb, var(--k-panel) 90%, transparent);
129
+ color: var(--paper-dim);
130
+ cursor: pointer;
131
+ font-family: var(--k-font-mono, "IBM Plex Mono", monospace);
132
+ font-size: 11px;
133
+ font-weight: 600;
134
+ letter-spacing: 0.06em;
135
+ backdrop-filter: blur(6px);
136
+ transition: background 0.16s ease, border-color 0.16s ease, color 0.16s ease;
137
+ }
138
+
139
+ .theme-toggle:hover {
140
+ background: color-mix(in srgb, var(--k-panel) 100%, transparent);
141
+ border-color: var(--accent);
142
+ color: var(--accent);
143
+ }
144
+
145
+ .theme-toggle-icon {
146
+ font-size: 14px;
147
+ line-height: 1;
148
+ }
149
+
66
150
  button,
67
151
  textarea {
68
152
  font: inherit;
@@ -128,9 +212,9 @@ p {
128
212
  border: 1px solid var(--line-strong);
129
213
  border-radius: var(--radius);
130
214
  background:
131
- linear-gradient(135deg, rgba(92, 224, 198, 0.08), transparent 42%),
215
+ linear-gradient(135deg, color-mix(in srgb, var(--k-brand) 8%, transparent), transparent 42%),
132
216
  linear-gradient(180deg, var(--ink-800), var(--ink-850));
133
- box-shadow: 0 24px 60px -34px rgba(0, 0, 0, 0.9), inset 0 1px 0 rgba(255, 255, 255, 0.03);
217
+ box-shadow: var(--k-shadow, 0 24px 60px -34px rgba(0, 0, 0, 0.9)), inset 0 1px 0 var(--line);
134
218
  animation: rise 0.6s cubic-bezier(0.22, 1, 0.36, 1) both;
135
219
  }
136
220
 
@@ -196,7 +280,11 @@ h1 {
196
280
  padding: 11px 12px;
197
281
  border: 1px solid var(--line);
198
282
  border-radius: var(--radius-sm);
199
- background: rgba(8, 12, 18, 0.55);
283
+ background: color-mix(in srgb, var(--k-bg) 55%, var(--k-panel));
284
+ }
285
+
286
+ [data-theme="light"] .meta-item {
287
+ background: color-mix(in srgb, var(--k-bg) 70%, var(--k-panel));
200
288
  }
201
289
 
202
290
  .meta-value {
@@ -247,7 +335,7 @@ h1 {
247
335
  position: fixed;
248
336
  inset: 0;
249
337
  z-index: 40;
250
- background: rgba(0, 0, 0, 0.55);
338
+ background: color-mix(in srgb, var(--k-bg) 55%, transparent);
251
339
  backdrop-filter: blur(2px);
252
340
  opacity: 0;
253
341
  transition: opacity 0.22s ease;
@@ -270,7 +358,7 @@ h1 {
270
358
  height: 30px;
271
359
  border: 1px solid var(--line-strong);
272
360
  border-radius: 999px;
273
- background: rgba(8, 12, 18, 0.8);
361
+ background: color-mix(in srgb, var(--k-bg) 80%, transparent);
274
362
  color: var(--paper-faint);
275
363
  cursor: pointer;
276
364
  font-size: 14px;
@@ -287,7 +375,7 @@ h1 {
287
375
  border-radius: var(--radius);
288
376
  background: linear-gradient(180deg, var(--ink-800), var(--ink-850));
289
377
  padding: 14px;
290
- box-shadow: 0 22px 50px -38px rgba(0, 0, 0, 0.9);
378
+ box-shadow: var(--k-shadow, 0 22px 50px -38px rgba(0, 0, 0, 0.9));
291
379
  animation: rise 0.6s cubic-bezier(0.22, 1, 0.36, 1) both;
292
380
  animation-delay: 0.05s;
293
381
  }
@@ -324,7 +412,7 @@ h1 {
324
412
  border-radius: var(--radius-sm);
325
413
  margin-top: 8px;
326
414
  padding: 9px 10px;
327
- background: rgba(8, 12, 18, 0.5);
415
+ background: color-mix(in srgb, var(--k-bg) 50%, var(--k-panel));
328
416
  color: var(--paper);
329
417
  cursor: pointer;
330
418
  text-align: left;
@@ -334,12 +422,12 @@ h1 {
334
422
  .queue-row:hover {
335
423
  transform: translateX(2px);
336
424
  border-color: var(--line-strong);
337
- background: rgba(16, 24, 34, 0.8);
425
+ background: color-mix(in srgb, var(--k-bg) 20%, var(--k-panel));
338
426
  }
339
427
 
340
428
  .queue-row.is-active {
341
429
  border-left-width: 3px;
342
- background: linear-gradient(90deg, rgba(92, 224, 198, 0.12), rgba(8, 12, 18, 0.5) 60%);
430
+ background: color-mix(in srgb, var(--k-brand) 8%, var(--k-panel));
343
431
  box-shadow: inset 0 0 0 1px var(--line-strong);
344
432
  }
345
433
 
@@ -383,22 +471,22 @@ h1 {
383
471
  border-radius: 999px;
384
472
  text-align: center;
385
473
  color: var(--paper-dim);
386
- background: rgba(8, 12, 18, 0.6);
474
+ background: color-mix(in srgb, var(--k-bg) 60%, var(--k-panel));
387
475
  letter-spacing: 0.08em;
388
476
  font-size: 9.5px;
389
477
  }
390
478
 
391
- .queue-row[data-queue-status="resolved"] .state-label { color: var(--verify); border-color: rgba(52, 211, 153, 0.4); }
392
- .queue-row[data-queue-status="rejected"] .state-label { color: var(--reject); border-color: rgba(255, 111, 111, 0.4); }
393
- .queue-row[data-queue-status="escalated"] .state-label { color: var(--hold); border-color: rgba(243, 177, 75, 0.4); }
394
- .queue-row[data-queue-status="in-review"] .state-label { color: var(--accent); border-color: rgba(92, 224, 198, 0.4); }
479
+ .queue-row[data-queue-status="resolved"] .state-label { color: var(--verify); border-color: color-mix(in srgb, var(--verify) 40%, transparent); }
480
+ .queue-row[data-queue-status="rejected"] .state-label { color: var(--reject); border-color: color-mix(in srgb, var(--reject) 40%, transparent); }
481
+ .queue-row[data-queue-status="escalated"] .state-label { color: var(--hold); border-color: color-mix(in srgb, var(--hold) 40%, transparent); }
482
+ .queue-row[data-queue-status="in-review"] .state-label { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 40%, transparent); }
395
483
 
396
484
  .next-button {
397
485
  min-height: 34px;
398
486
  padding: 0 14px;
399
487
  border: 1px solid var(--line-strong);
400
488
  border-radius: 999px;
401
- background: rgba(92, 224, 198, 0.08);
489
+ background: color-mix(in srgb, var(--k-brand) 8%, transparent);
402
490
  color: var(--accent);
403
491
  cursor: pointer;
404
492
  font-family: "IBM Plex Mono", ui-monospace, monospace;
@@ -409,7 +497,7 @@ h1 {
409
497
  }
410
498
 
411
499
  .next-button:hover {
412
- background: rgba(92, 224, 198, 0.16);
500
+ background: color-mix(in srgb, var(--k-brand) 16%, transparent);
413
501
  border-color: var(--accent);
414
502
  }
415
503
 
@@ -426,7 +514,7 @@ h1 {
426
514
  display: grid;
427
515
  gap: 2px;
428
516
  padding: 10px;
429
- background: rgba(8, 12, 18, 0.6);
517
+ background: color-mix(in srgb, var(--k-bg) 60%, var(--k-panel));
430
518
  }
431
519
 
432
520
  .summary-grid .meta-value {
@@ -483,7 +571,7 @@ h1 {
483
571
  border: 1px solid var(--line);
484
572
  border-radius: var(--radius-sm);
485
573
  padding: 8px;
486
- background: rgba(6, 9, 13, 0.45);
574
+ background: color-mix(in srgb, var(--k-bg) 45%, transparent);
487
575
  }
488
576
 
489
577
  .event-sequence {
@@ -563,13 +651,13 @@ h1 {
563
651
  display: grid;
564
652
  gap: 12px;
565
653
  min-width: 0;
566
- border: 1px solid rgba(92, 224, 198, 0.28);
654
+ border: 1px solid color-mix(in srgb, var(--k-brand) 28%, transparent);
567
655
  border-radius: var(--radius);
568
656
  padding: 14px;
569
657
  background:
570
- linear-gradient(135deg, rgba(92, 224, 198, 0.12), transparent 34%),
658
+ linear-gradient(135deg, color-mix(in srgb, var(--k-brand) 12%, transparent), transparent 34%),
571
659
  linear-gradient(180deg, var(--ink-800), var(--ink-850));
572
- box-shadow: 0 26px 60px -42px rgba(0, 0, 0, 0.95), inset 0 1px 0 rgba(255, 255, 255, 0.04);
660
+ box-shadow: var(--k-shadow, 0 26px 60px -42px rgba(0, 0, 0, 0.95)), inset 0 1px 0 var(--line);
573
661
  }
574
662
 
575
663
  .focus-head,
@@ -592,7 +680,7 @@ h1 {
592
680
  border: 1px solid var(--line);
593
681
  border-radius: var(--radius-sm);
594
682
  padding: 10px 12px;
595
- background: rgba(6, 9, 13, 0.56);
683
+ background: color-mix(in srgb, var(--k-bg) 56%, var(--k-panel));
596
684
  }
597
685
 
598
686
  .focus-value strong {
@@ -614,8 +702,8 @@ h1 {
614
702
  }
615
703
 
616
704
  .focus-value.is-proposed {
617
- border-color: rgba(122, 162, 255, 0.34);
618
- background: linear-gradient(180deg, rgba(122, 162, 255, 0.1), rgba(6, 9, 13, 0.56));
705
+ border-color: color-mix(in srgb, var(--k-active) 34%, transparent);
706
+ background: color-mix(in srgb, var(--k-active) 10%, color-mix(in srgb, var(--k-bg) 56%, var(--k-panel)));
619
707
  }
620
708
 
621
709
  .focus-value.is-proposed strong {
@@ -658,12 +746,12 @@ h1 {
658
746
  place-items: center;
659
747
  border-radius: 999px;
660
748
  border: 1px solid var(--line-strong);
661
- background: var(--ink-750);
749
+ background: var(--vs-bg);
662
750
  color: var(--paper-faint);
663
751
  font-family: "Fraunces", Georgia, serif;
664
752
  font-style: italic;
665
753
  font-size: 13px;
666
- box-shadow: 0 10px 26px -12px rgba(0, 0, 0, 0.9);
754
+ box-shadow: var(--k-shadow, 0 10px 26px -12px rgba(0, 0, 0, 0.9));
667
755
  }
668
756
 
669
757
  .candidate-card,
@@ -673,7 +761,7 @@ h1 {
673
761
  border: 1px solid var(--line);
674
762
  border-radius: var(--radius);
675
763
  background: linear-gradient(180deg, var(--ink-800), var(--ink-850));
676
- box-shadow: 0 26px 60px -42px rgba(0, 0, 0, 0.95);
764
+ box-shadow: var(--k-shadow, 0 26px 60px -42px rgba(0, 0, 0, 0.95));
677
765
  }
678
766
 
679
767
  .candidate-card {
@@ -690,7 +778,7 @@ h1 {
690
778
 
691
779
  /* The proposed candidate (2nd card) is the incoming change — flag it. */
692
780
  .candidate-card:nth-child(2) {
693
- border-color: rgba(122, 162, 255, 0.32);
781
+ border-color: color-mix(in srgb, var(--k-active) 32%, transparent);
694
782
  }
695
783
 
696
784
  .candidate-card:nth-child(2)::after {
@@ -698,12 +786,12 @@ h1 {
698
786
  position: absolute;
699
787
  inset: 0;
700
788
  pointer-events: none;
701
- background: radial-gradient(420px 200px at 80% -10%, rgba(122, 162, 255, 0.12), transparent 70%);
789
+ background: radial-gradient(420px 200px at 80% -10%, color-mix(in srgb, var(--k-active) 12%, transparent), transparent 70%);
702
790
  }
703
791
 
704
792
  .candidate-card.is-selected {
705
- border-color: rgba(52, 211, 153, 0.55);
706
- box-shadow: 0 26px 60px -36px rgba(0, 0, 0, 0.95), inset 0 0 0 1px rgba(52, 211, 153, 0.35), inset 0 0 60px -30px rgba(52, 211, 153, 0.6);
793
+ border-color: color-mix(in srgb, var(--k-positive) 55%, transparent);
794
+ box-shadow: 0 26px 60px -36px rgba(0, 0, 0, 0.95), inset 0 0 0 1px color-mix(in srgb, var(--k-positive) 35%, transparent), inset 0 0 60px -30px color-mix(in srgb, var(--k-positive) 60%, transparent);
707
795
  }
708
796
 
709
797
  .candidate-card.is-unselected {
@@ -744,8 +832,8 @@ h1 {
744
832
 
745
833
  .is-selected .state-label {
746
834
  color: var(--verify);
747
- border-color: rgba(52, 211, 153, 0.5);
748
- background: rgba(52, 211, 153, 0.12);
835
+ border-color: color-mix(in srgb, var(--verify) 50%, transparent);
836
+ background: color-mix(in srgb, var(--verify) 12%, transparent);
749
837
  }
750
838
 
751
839
  /* The value — the single most important datapoint on the screen. */
@@ -799,9 +887,9 @@ h1 {
799
887
  display: inline-block;
800
888
  margin-top: 5px;
801
889
  padding: 4px 9px;
802
- border: 1px solid rgba(92, 224, 198, 0.35);
890
+ border: 1px solid color-mix(in srgb, var(--k-brand) 35%, transparent);
803
891
  border-radius: 999px;
804
- background: rgba(92, 224, 198, 0.1);
892
+ background: color-mix(in srgb, var(--k-brand) 10%, transparent);
805
893
  color: var(--accent);
806
894
  font-size: 11.5px;
807
895
  font-weight: 600;
@@ -817,6 +905,94 @@ h1 {
817
905
  color: var(--paper-dim) !important;
818
906
  }
819
907
 
908
+ /* ---- Excerpt / rationale 3-line clamp with inline expander ----------- */
909
+ /* Applied to .field-value inside .excerpt or .excerpt-clamp containers,
910
+ and to .rationale-clamp for reviewer rationale fields.
911
+ The "more / less" toggle is a <button class="clamp-toggle"> sibling. */
912
+
913
+ .excerpt-clamp .field-value,
914
+ .rationale-clamp .field-value {
915
+ display: -webkit-box;
916
+ -webkit-box-orient: vertical;
917
+ -webkit-line-clamp: 3;
918
+ overflow: hidden;
919
+ }
920
+
921
+ .excerpt-clamp.is-expanded .field-value,
922
+ .rationale-clamp.is-expanded .field-value {
923
+ display: block;
924
+ -webkit-line-clamp: unset;
925
+ overflow: visible;
926
+ }
927
+
928
+ .clamp-toggle {
929
+ display: inline;
930
+ margin-left: 4px;
931
+ padding: 0;
932
+ border: none;
933
+ background: none;
934
+ color: var(--accent);
935
+ cursor: pointer;
936
+ font-family: "IBM Plex Mono", ui-monospace, monospace;
937
+ font-size: 10.5px;
938
+ font-weight: 600;
939
+ letter-spacing: 0.04em;
940
+ text-decoration: underline;
941
+ text-underline-offset: 2px;
942
+ vertical-align: baseline;
943
+ }
944
+
945
+ .clamp-toggle:hover {
946
+ color: var(--paper);
947
+ }
948
+
949
+ /* ---- Candidate history expander -------------------------------------- */
950
+ /* When there are >3 unselected candidates the UI renders the first 3 and
951
+ hides the rest behind a "view all (N)" expander. */
952
+
953
+ .history-overflow {
954
+ display: none;
955
+ }
956
+
957
+ .history-expander.is-expanded .history-overflow {
958
+ display: contents;
959
+ }
960
+
961
+ .history-expand-btn {
962
+ display: inline-flex;
963
+ align-items: center;
964
+ gap: 4px;
965
+ margin-top: 6px;
966
+ padding: 3px 10px;
967
+ border: 1px solid var(--line-strong);
968
+ border-radius: 999px;
969
+ background: color-mix(in srgb, var(--k-brand) 6%, transparent);
970
+ color: var(--accent);
971
+ cursor: pointer;
972
+ font-family: "IBM Plex Mono", ui-monospace, monospace;
973
+ font-size: 10px;
974
+ font-weight: 600;
975
+ letter-spacing: 0.06em;
976
+ transition: background 0.14s ease, border-color 0.14s ease;
977
+ }
978
+
979
+ .history-expand-btn:hover {
980
+ background: color-mix(in srgb, var(--k-brand) 14%, transparent);
981
+ border-color: var(--accent);
982
+ }
983
+
984
+ .history-expander.is-expanded .history-expand-btn .expand-label {
985
+ display: none;
986
+ }
987
+
988
+ .history-expander.is-expanded .history-expand-btn .collapse-label {
989
+ display: inline;
990
+ }
991
+
992
+ .history-expand-btn .collapse-label {
993
+ display: none;
994
+ }
995
+
820
996
  /* ---- Decision column -------------------------------------------------- */
821
997
 
822
998
  .decision-column {
@@ -844,7 +1020,7 @@ textarea {
844
1020
  border-radius: var(--radius-sm);
845
1021
  padding: 10px;
846
1022
  color: var(--paper);
847
- background: rgba(6, 9, 13, 0.7);
1023
+ background: color-mix(in srgb, var(--k-bg) 70%, var(--k-panel));
848
1024
  font-family: "IBM Plex Mono", ui-monospace, monospace;
849
1025
  font-size: 12px;
850
1026
  line-height: 1.5;
@@ -857,7 +1033,7 @@ textarea::placeholder {
857
1033
  textarea:focus {
858
1034
  border-color: var(--accent);
859
1035
  outline: none;
860
- box-shadow: 0 0 0 3px rgba(92, 224, 198, 0.18);
1036
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--k-brand) 18%, transparent);
861
1037
  }
862
1038
 
863
1039
  /* Decision actions — color-coded to outcome (accept / keep / reject). */
@@ -872,7 +1048,7 @@ textarea:focus {
872
1048
  min-height: 42px;
873
1049
  border: 1px solid var(--line-strong);
874
1050
  border-radius: var(--radius-sm);
875
- background: rgba(8, 12, 18, 0.6);
1051
+ background: color-mix(in srgb, var(--k-bg) 60%, var(--k-panel));
876
1052
  color: var(--paper);
877
1053
  cursor: pointer;
878
1054
  font-weight: 700;
@@ -887,18 +1063,18 @@ textarea:focus {
887
1063
  outline: none;
888
1064
  }
889
1065
 
890
- .decision-button:nth-child(1):hover { border-color: var(--verify); box-shadow: 0 10px 24px -14px rgba(52, 211, 153, 0.8); }
891
- .decision-button:nth-child(2):hover { border-color: var(--hold); box-shadow: 0 10px 24px -14px rgba(243, 177, 75, 0.8); }
892
- .decision-button:nth-child(3):hover { border-color: var(--reject); box-shadow: 0 10px 24px -14px rgba(255, 111, 111, 0.8); }
1066
+ .decision-button:nth-child(1):hover { border-color: var(--verify); box-shadow: 0 10px 24px -14px color-mix(in srgb, var(--verify) 80%, transparent); }
1067
+ .decision-button:nth-child(2):hover { border-color: var(--hold); box-shadow: 0 10px 24px -14px color-mix(in srgb, var(--hold) 80%, transparent); }
1068
+ .decision-button:nth-child(3):hover { border-color: var(--reject); box-shadow: 0 10px 24px -14px color-mix(in srgb, var(--reject) 80%, transparent); }
893
1069
 
894
1070
  .decision-button.is-active {
895
- color: var(--ink-1000);
1071
+ color: var(--k-bg);
896
1072
  border-color: transparent;
897
1073
  }
898
1074
 
899
- .decision-button:nth-child(1).is-active { background: var(--verify); box-shadow: 0 14px 30px -14px rgba(52, 211, 153, 0.9); }
900
- .decision-button:nth-child(2).is-active { background: var(--hold); box-shadow: 0 14px 30px -14px rgba(243, 177, 75, 0.9); }
901
- .decision-button:nth-child(3).is-active { background: var(--reject); box-shadow: 0 14px 30px -14px rgba(255, 111, 111, 0.9); }
1075
+ .decision-button:nth-child(1).is-active { background: var(--verify); box-shadow: 0 14px 30px -14px color-mix(in srgb, var(--verify) 90%, transparent); }
1076
+ .decision-button:nth-child(2).is-active { background: var(--hold); box-shadow: 0 14px 30px -14px color-mix(in srgb, var(--hold) 90%, transparent); }
1077
+ .decision-button:nth-child(3).is-active { background: var(--reject); box-shadow: 0 14px 30px -14px color-mix(in srgb, var(--reject) 90%, transparent); }
902
1078
 
903
1079
  .effect {
904
1080
  display: grid;
@@ -932,7 +1108,7 @@ textarea:focus {
932
1108
  border: 1px solid var(--line-strong);
933
1109
  border-radius: 999px;
934
1110
  padding: 5px 11px;
935
- background: rgba(122, 162, 255, 0.08);
1111
+ background: color-mix(in srgb, var(--k-active) 8%, transparent);
936
1112
  color: var(--proposed);
937
1113
  font-family: "IBM Plex Mono", ui-monospace, monospace;
938
1114
  font-size: 11px;
@@ -940,7 +1116,7 @@ textarea:focus {
940
1116
  }
941
1117
 
942
1118
  .tag.is-empty {
943
- background: rgba(8, 12, 18, 0.6);
1119
+ background: color-mix(in srgb, var(--k-bg) 60%, var(--k-panel));
944
1120
  color: var(--paper-faint);
945
1121
  }
946
1122
 
@@ -1038,7 +1214,7 @@ details.surface-preview[open] .surface-summary-label::before {
1038
1214
  border: 1px solid var(--line);
1039
1215
  border-radius: var(--radius-sm);
1040
1216
  padding: 10px 11px;
1041
- background: rgba(6, 9, 13, 0.55);
1217
+ background: color-mix(in srgb, var(--k-bg) 55%, var(--k-panel));
1042
1218
  }
1043
1219
 
1044
1220
  .preview-section h3 {
@@ -1064,7 +1240,7 @@ details.surface-preview[open] .surface-summary-label::before {
1064
1240
  .preview-section.is-neutral {
1065
1241
  border-style: dashed;
1066
1242
  border-color: var(--line);
1067
- background: rgba(6, 9, 13, 0.35);
1243
+ background: color-mix(in srgb, var(--k-bg) 35%, var(--k-panel));
1068
1244
  }
1069
1245
 
1070
1246
  .preview-section.is-neutral h3 {
@@ -1137,7 +1313,7 @@ pre {
1137
1313
  border-radius: var(--radius-sm);
1138
1314
  background: var(--ink-1000);
1139
1315
  padding: 11px;
1140
- color: #b6f3df;
1316
+ color: color-mix(in srgb, var(--k-positive) 80%, var(--k-text));
1141
1317
  font-family: "IBM Plex Mono", ui-monospace, monospace;
1142
1318
  font-size: 11px;
1143
1319
  line-height: 1.55;
@@ -1197,9 +1373,9 @@ pre {
1197
1373
  border-radius: var(--radius);
1198
1374
  padding: 13px 14px;
1199
1375
  background:
1200
- linear-gradient(90deg, rgba(92, 224, 198, 0.12), transparent 46%),
1376
+ linear-gradient(90deg, color-mix(in srgb, var(--k-brand) 12%, transparent), transparent 46%),
1201
1377
  linear-gradient(180deg, var(--ink-800), var(--ink-850));
1202
- box-shadow: 0 18px 44px -36px rgba(0, 0, 0, 0.9);
1378
+ box-shadow: var(--k-shadow, 0 18px 44px -36px rgba(0, 0, 0, 0.9));
1203
1379
  }
1204
1380
 
1205
1381
  .active-review-copy,
@@ -1264,7 +1440,7 @@ pre {
1264
1440
  padding: 11px 14px;
1265
1441
  margin-bottom: 14px;
1266
1442
  background:
1267
- linear-gradient(90deg, rgba(92, 224, 198, 0.08), transparent 46%),
1443
+ linear-gradient(90deg, color-mix(in srgb, var(--k-brand) 8%, transparent), transparent 46%),
1268
1444
  linear-gradient(180deg, var(--ink-800), var(--ink-850));
1269
1445
  animation: rise 0.6s cubic-bezier(0.22, 1, 0.36, 1) both;
1270
1446
  }
@@ -1290,7 +1466,7 @@ pre {
1290
1466
  padding: 0 14px;
1291
1467
  border: 1px solid var(--line-strong);
1292
1468
  border-radius: 999px;
1293
- background: rgba(92, 224, 198, 0.08);
1469
+ background: color-mix(in srgb, var(--k-brand) 8%, transparent);
1294
1470
  color: var(--accent);
1295
1471
  cursor: pointer;
1296
1472
  font-family: "IBM Plex Mono", ui-monospace, monospace;
@@ -1301,7 +1477,7 @@ pre {
1301
1477
  }
1302
1478
 
1303
1479
  .mobile-queue-open:hover {
1304
- background: rgba(92, 224, 198, 0.16);
1480
+ background: color-mix(in srgb, var(--k-brand) 16%, transparent);
1305
1481
  border-color: var(--accent);
1306
1482
  }
1307
1483
 
@@ -1542,6 +1718,41 @@ pre {
1542
1718
  }
1543
1719
  }
1544
1720
 
1721
+ /* ---- Type legibility: serif → UI sans below 480px -------------------- */
1722
+ /* At small container sizes the Fraunces display font reads poorly; fall back
1723
+ to the UI sans-serif stack for headings while keeping serif on desktop. */
1724
+ @media (max-width: 480px) {
1725
+ h1,
1726
+ h2,
1727
+ h3,
1728
+ .role,
1729
+ .surface-summary-label,
1730
+ .queue-head h2,
1731
+ .session-summary h2,
1732
+ .session-audit h2,
1733
+ .surface-head h2,
1734
+ .summary-grid .meta-value {
1735
+ font-family: var(--k-font-ui, "Hanken Grotesk", system-ui, sans-serif);
1736
+ letter-spacing: -0.01em;
1737
+ }
1738
+ }
1739
+
1740
+ @container (max-width: 480px) {
1741
+ h1,
1742
+ h2,
1743
+ h3,
1744
+ .role,
1745
+ .surface-summary-label,
1746
+ .queue-head h2,
1747
+ .session-summary h2,
1748
+ .session-audit h2,
1749
+ .surface-head h2,
1750
+ .summary-grid .meta-value {
1751
+ font-family: var(--k-font-ui, "Hanken Grotesk", system-ui, sans-serif);
1752
+ letter-spacing: -0.01em;
1753
+ }
1754
+ }
1755
+
1545
1756
  @media (max-width: 420px) {
1546
1757
  h1 {
1547
1758
  font-size: 23px;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kontourai/survey",
3
- "version": "0.7.2",
3
+ "version": "1.0.0",
4
4
  "description": "Producer-side source, extraction, candidate, and review contracts for projecting verified claims into Surface.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -87,9 +87,10 @@
87
87
  "typescript": "^5.8.0"
88
88
  },
89
89
  "engines": {
90
- "node": ">=20"
90
+ "node": ">=22"
91
91
  },
92
92
  "bin": {
93
- "survey-review-mcp": "./bin/survey-review-mcp.mjs"
93
+ "survey-review-mcp": "./bin/survey-review-mcp.mjs",
94
+ "survey-review-console": "./bin/survey-review-console.mjs"
94
95
  }
95
96
  }