privateboard 0.1.37 → 0.1.38

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/version.d.ts CHANGED
@@ -12,6 +12,6 @@
12
12
  * number ends up surfaced in the user-facing footer or banner. Keep
13
13
  * this file as the canonical source — every callsite reads from here.
14
14
  */
15
- declare const VERSION = "0.1.37";
15
+ declare const VERSION = "0.1.38";
16
16
 
17
17
  export { VERSION };
package/dist/version.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/version.ts
4
- var VERSION = "0.1.37";
4
+ var VERSION = "0.1.38";
5
5
  export {
6
6
  VERSION
7
7
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/version.ts"],"sourcesContent":["/**\n * Single source of truth for the app version.\n *\n * Imported by `cli.ts` (CLI banner / `--version`), `server.ts` (the\n * `/health` payload + the `/api/version` endpoint), and bundled into\n * the frontend via the version endpoint. Bump alongside `package.json`\n * on every release — the existing `npm version <patch|minor|major>`\n * + commit pattern updates package.json automatically; this file\n * needs the matching manual bump.\n *\n * If two strings drift (bumped one but not the other), the wrong\n * number ends up surfaced in the user-facing footer or banner. Keep\n * this file as the canonical source — every callsite reads from here.\n */\nexport const VERSION = \"0.1.37\";\n"],"mappings":";;;AAcO,IAAM,UAAU;","names":[]}
1
+ {"version":3,"sources":["../src/version.ts"],"sourcesContent":["/**\n * Single source of truth for the app version.\n *\n * Imported by `cli.ts` (CLI banner / `--version`), `server.ts` (the\n * `/health` payload + the `/api/version` endpoint), and bundled into\n * the frontend via the version endpoint. Bump alongside `package.json`\n * on every release — the existing `npm version <patch|minor|major>`\n * + commit pattern updates package.json automatically; this file\n * needs the matching manual bump.\n *\n * If two strings drift (bumped one but not the other), the wrong\n * number ends up surfaced in the user-facing footer or banner. Keep\n * this file as the canonical source — every callsite reads from here.\n */\nexport const VERSION = \"0.1.38\";\n"],"mappings":";;;AAcO,IAAM,UAAU;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "privateboard",
3
- "version": "0.1.37",
3
+ "version": "0.1.38",
4
4
  "description": "PrivateBoard · your private board meeting, on call. Local-first, multi-agent thinking amplifier.",
5
5
  "type": "module",
6
6
  "main": "electron-entry.cjs",
@@ -166,7 +166,7 @@
166
166
  }
167
167
  .adjourn-summary-val {
168
168
  font-family: var(--font-human);
169
- font-size: 13px;
169
+ font-size: 14px;
170
170
  color: var(--text);
171
171
  line-height: 1.4;
172
172
  word-break: break-word;
@@ -356,7 +356,7 @@
356
356
  }
357
357
  .adjourn-mode-title {
358
358
  font-family: var(--font-human);
359
- font-size: 13px;
359
+ font-size: 14px;
360
360
  font-weight: 600;
361
361
  color: var(--text);
362
362
  letter-spacing: -0.005em;
@@ -36,33 +36,45 @@ img[data-agent]:hover { filter: brightness(1.15); }
36
36
  width: 100%;
37
37
  max-width: 560px;
38
38
  max-height: calc(100vh - 60px);
39
- overflow-y: auto;
40
39
  background: var(--panel);
41
40
  border: 0.5px solid var(--line-strong);
42
41
  color: var(--text);
43
42
  animation: agent-rise 0.18s ease-out;
44
- /* Auto-hide scrollbar: thumb is transparent until the pointer is
45
- over the card OR the card is actively being scrolled (the
46
- .is-scrolling class is toggled by agent-overlay.js on each scroll
47
- event with a short trailing timeout). Reserved gutter avoids
48
- layout shift when the thumb fades in. */
43
+ /* Frame only · the scroll lives in the inner `.agent-card-scroll`
44
+ below. Keeping `.agent-card` a non-scrolling frame means the
45
+ decorative corner brackets (::before / ::after) stay pinned to the
46
+ card's corners instead of anchoring to the scrolled content and
47
+ drifting away. Flex column lets the inner scroller fill the frame
48
+ up to max-height. */
49
+ display: flex;
50
+ flex-direction: column;
51
+ }
52
+ /* Inner scroll region · owns the overflow + the auto-hide scrollbar
53
+ that used to live on `.agent-card`. Thumb stays transparent until the
54
+ pointer is over the region OR it's actively being scrolled (the
55
+ `.is-scrolling` class is toggled by agent-overlay.js with a short
56
+ trailing timeout). Reserved gutter avoids layout shift on fade-in. */
57
+ .agent-card-scroll {
58
+ flex: 1;
59
+ min-height: 0;
60
+ overflow-y: auto;
49
61
  scrollbar-width: thin;
50
62
  scrollbar-color: transparent transparent;
51
63
  scrollbar-gutter: stable;
52
64
  transition: scrollbar-color 0.18s;
53
65
  }
54
- .agent-card:hover,
55
- .agent-card.is-scrolling { scrollbar-color: var(--text-faint) transparent; }
56
- .agent-card::-webkit-scrollbar { width: 8px; }
57
- .agent-card::-webkit-scrollbar-track { background: transparent; }
58
- .agent-card::-webkit-scrollbar-thumb {
66
+ .agent-card-scroll:hover,
67
+ .agent-card-scroll.is-scrolling { scrollbar-color: var(--text-faint) transparent; }
68
+ .agent-card-scroll::-webkit-scrollbar { width: 8px; }
69
+ .agent-card-scroll::-webkit-scrollbar-track { background: transparent; }
70
+ .agent-card-scroll::-webkit-scrollbar-thumb {
59
71
  background: transparent;
60
72
  border-radius: 4px;
61
73
  transition: background 0.18s;
62
74
  }
63
- .agent-card:hover::-webkit-scrollbar-thumb,
64
- .agent-card.is-scrolling::-webkit-scrollbar-thumb { background: var(--text-faint); }
65
- .agent-card::-webkit-scrollbar-thumb:hover { background: var(--text-soft); }
75
+ .agent-card-scroll:hover::-webkit-scrollbar-thumb,
76
+ .agent-card-scroll.is-scrolling::-webkit-scrollbar-thumb { background: var(--text-faint); }
77
+ .agent-card-scroll::-webkit-scrollbar-thumb:hover { background: var(--text-soft); }
66
78
  @keyframes agent-rise {
67
79
  from { transform: translateY(8px); opacity: 0; }
68
80
  to { transform: translateY(0); opacity: 1; }
@@ -180,7 +192,7 @@ img[data-agent]:hover { filter: brightness(1.15); }
180
192
 
181
193
  .agent-lens {
182
194
  font-family: var(--sans);
183
- font-size: 13px;
195
+ font-size: 14px;
184
196
  line-height: 1.55;
185
197
  color: var(--text-soft);
186
198
  letter-spacing: -0.003em;
@@ -201,6 +201,7 @@
201
201
  const OVERLAY_HTML = `
202
202
  <div class="agent-overlay" id="agent-overlay" role="dialog" aria-modal="true" aria-hidden="true">
203
203
  <div class="agent-card" role="document">
204
+ <div class="agent-card-scroll">
204
205
  <div class="agent-classification">
205
206
  <span><span class="dot">●</span> <span data-i18n="ao_personnel_kicker">agent · personnel file</span></span>
206
207
  <span class="right" data-i18n="ao_classified_mark">// classified</span>
@@ -303,6 +304,7 @@
303
304
  <div class="meta public-only"><span data-i18n="ao_first_room_meta">first room ·</span> <span class="lime" data-i18n="ao_free">free</span></div>
304
305
  <a href="/#convene" class="agent-card-cta public-only" data-i18n="ao_signin_cta">[ → Sign in to convene ]</a>
305
306
  </footer>
307
+ </div>
306
308
  </div>
307
309
  </div>
308
310
  `;
@@ -366,7 +368,7 @@
366
368
  timer = setTimeout(() => node.classList.remove("is-scrolling"), 700);
367
369
  }, { passive: true });
368
370
  }
369
- bindScrollAutoHide(card);
371
+ bindScrollAutoHide(card.querySelector(".agent-card-scroll"));
370
372
  bindScrollAutoHide(card.querySelector(".agent-memory-list"));
371
373
 
372
374
  /** Build a card from a live /api/agents record (custom directors).
@@ -899,7 +899,7 @@
899
899
  color: var(--text-soft);
900
900
  text-transform: uppercase;
901
901
  background: transparent;
902
- border: 0.5px solid var(--line-bright);
902
+ border: 0.5px solid var(--line-strong);
903
903
  padding: 3px 8px;
904
904
  cursor: pointer;
905
905
  transition: border-color 0.12s, color 0.12s, background 0.12s;
@@ -1167,7 +1167,7 @@
1167
1167
  line-height: 1;
1168
1168
  }
1169
1169
  .dream-z.z1 { left: 14%; font-size: 18px; animation-delay: 0s; }
1170
- .dream-z.z2 { left: 30%; font-size: 13px; animation-delay: 0.6s; }
1170
+ .dream-z.z2 { left: 30%; font-size: 14px; animation-delay: 0.6s; }
1171
1171
  .dream-z.z3 { left: 50%; font-size: 11px; animation-delay: 1.2s; }
1172
1172
  .dream-z.z4 { left: 70%; font-size: 16px; animation-delay: 1.7s; }
1173
1173
  .dream-z.z5 { left: 86%; font-size: 12px; animation-delay: 2.4s; }
@@ -2439,7 +2439,7 @@
2439
2439
  }
2440
2440
  .ap-stat-v {
2441
2441
  font-family: var(--mono);
2442
- font-size: 13px;
2442
+ font-size: 14px;
2443
2443
  font-weight: 700;
2444
2444
  color: var(--text);
2445
2445
  letter-spacing: -0.005em;
@@ -2568,6 +2568,54 @@
2568
2568
  border-top: none;
2569
2569
  padding-top: 5px;
2570
2570
  }
2571
+ /* Cloned voices group · lime kicker so user-owned customs stand out
2572
+ from system / premade voices below them. Same density as the
2573
+ regular group header, just colored. */
2574
+ .ap-model-group.ap-model-group-cloned {
2575
+ color: var(--lime);
2576
+ }
2577
+ .ap-model-opt.ap-model-opt-cloned .ap-model-opt-label {
2578
+ color: var(--text);
2579
+ font-weight: 600;
2580
+ }
2581
+ .ap-model-opt.ap-model-opt-cloned::before {
2582
+ content: "✦";
2583
+ color: var(--lime);
2584
+ margin-right: 6px;
2585
+ font-size: 10px;
2586
+ }
2587
+ /* Row wrapper for inline rename · holds the option button + an
2588
+ optional ✎ chip. Hover anywhere on the row reveals the chip. */
2589
+ .ap-model-opt-row {
2590
+ position: relative;
2591
+ display: flex;
2592
+ align-items: stretch;
2593
+ }
2594
+ .ap-model-opt-row .ap-model-opt {
2595
+ flex: 1;
2596
+ min-width: 0;
2597
+ }
2598
+ .ap-model-opt-rename {
2599
+ flex-shrink: 0;
2600
+ width: 28px;
2601
+ background: transparent;
2602
+ border: 0;
2603
+ border-left: 0.5px solid var(--line);
2604
+ color: var(--text-faint);
2605
+ cursor: pointer;
2606
+ font-size: 12px;
2607
+ line-height: 1;
2608
+ opacity: 0;
2609
+ transition: opacity 0.14s, color 0.14s, background 0.14s;
2610
+ }
2611
+ .ap-model-opt-row:hover .ap-model-opt-rename,
2612
+ .ap-model-opt-rename:focus-visible {
2613
+ opacity: 1;
2614
+ }
2615
+ .ap-model-opt-rename:hover {
2616
+ color: var(--lime);
2617
+ background: var(--panel-2);
2618
+ }
2571
2619
 
2572
2620
  /* Row · single-line label + uppercase mono hint, baseline-aligned,
2573
2621
  same vertical rhythm as .cmp-dd-opt. No per-row divider. */
@@ -2920,7 +2968,7 @@
2920
2968
  .ap-instr-view em { color: var(--text-soft); font-style: italic; }
2921
2969
  .ap-instr-view code {
2922
2970
  font-family: var(--mono);
2923
- font-size: 13px;
2971
+ font-size: 14px;
2924
2972
  background: var(--bg);
2925
2973
  border: 0.5px solid var(--line-bright);
2926
2974
  padding: 1px 5px;
@@ -2937,7 +2985,7 @@
2937
2985
  background: transparent;
2938
2986
  border: none;
2939
2987
  padding: 0;
2940
- font-size: 13px;
2988
+ font-size: 14px;
2941
2989
  line-height: 1.5;
2942
2990
  }
2943
2991
 
@@ -3419,7 +3467,7 @@
3419
3467
  }
3420
3468
  .ap-ulm-claim {
3421
3469
  font-family: var(--font-human);
3422
- font-size: 13px;
3470
+ font-size: 14px;
3423
3471
  line-height: 1.5;
3424
3472
  color: var(--text);
3425
3473
  letter-spacing: -0.003em;
@@ -3432,7 +3480,7 @@
3432
3480
  border: 0.5px solid var(--text-soft);
3433
3481
  color: var(--text);
3434
3482
  font-family: var(--font-human);
3435
- font-size: 13px;
3483
+ font-size: 14px;
3436
3484
  line-height: 1.5;
3437
3485
  padding: 8px 10px;
3438
3486
  outline: none;
@@ -3988,11 +4036,251 @@
3988
4036
  .ap-skill-info-configure-mark { font-size: 12px; }
3989
4037
 
3990
4038
  /* ── Voice configuration panel ───────────────────────────── */
3991
- /* The wrapping `.ap-voice-config` no longer needs spacing of its
3992
- own — the parent `.ap-block-body` already handles padding now
3993
- that Voice Setup is its own section (was nested inside Track
3994
- Record before, where the inner offset disambiguated it from
3995
- the model row above). */
4039
+ /* The wrapping `.ap-voice-config` no longer needs outer spacing of
4040
+ its own — `.ap-block-body` already handles padding. Inside, each
4041
+ logical group (voice picker / emotion / preview line / clone /
4042
+ advanced) lives in its own `.ap-voice-section`. Sections separate
4043
+ with a hairline divider on top so the user can scan "what knob
4044
+ am I touching" without the panel feeling like a wall of mixed
4045
+ inputs. Each section can optionally carry an `.ap-voice-section-head`
4046
+ mono kicker label naming the group. */
4047
+ .ap-voice-config {
4048
+ display: flex;
4049
+ flex-direction: column;
4050
+ }
4051
+ .ap-voice-section {
4052
+ padding: 14px 0;
4053
+ border-top: 0.5px solid var(--line-bright);
4054
+ }
4055
+ .ap-voice-section:first-child {
4056
+ padding-top: 0;
4057
+ border-top: none;
4058
+ }
4059
+ .ap-voice-section:last-child {
4060
+ padding-bottom: 0;
4061
+ }
4062
+ .ap-voice-section-head {
4063
+ font-family: var(--mono);
4064
+ font-size: 10px;
4065
+ font-weight: 700;
4066
+ letter-spacing: 0.18em;
4067
+ text-transform: uppercase;
4068
+ color: var(--text-faint);
4069
+ margin-bottom: 10px;
4070
+ display: block;
4071
+ }
4072
+ .ap-voice-section-head::before {
4073
+ content: "// ";
4074
+ color: color-mix(in srgb, var(--lime) 60%, var(--text-faint));
4075
+ }
4076
+
4077
+ /* Clone voice trigger · sits below the advanced sliders, reads
4078
+ as a single CTA row (icon + title + hint) rather than a row of
4079
+ chips, mirroring `.ap-skill-info-configure` button gravity.
4080
+ Click opens the boardroomVoiceClone overlay (public/voice-clone.js). */
4081
+ /* Custom preview text row · the wrapping `.ap-voice-section` owns
4082
+ the section header now; this just holds the textarea. */
4083
+ .ap-voice-preview-row {
4084
+ display: flex;
4085
+ flex-direction: column;
4086
+ gap: 6px;
4087
+ }
4088
+ .ap-voice-preview-text {
4089
+ width: 100%;
4090
+ resize: vertical;
4091
+ min-height: 48px;
4092
+ max-height: 140px;
4093
+ padding: 8px 10px;
4094
+ background: var(--panel-2);
4095
+ border: 0.5px solid var(--line-bright);
4096
+ border-radius: 6px;
4097
+ color: var(--text);
4098
+ font-family: var(--sans);
4099
+ font-size: 14px;
4100
+ line-height: 1.5;
4101
+ outline: none;
4102
+ transition: border-color 0.12s;
4103
+ }
4104
+ .ap-voice-preview-text:focus { border-color: var(--lime); }
4105
+ .ap-voice-preview-text::placeholder {
4106
+ color: var(--text-faint);
4107
+ font-style: italic;
4108
+ }
4109
+
4110
+ /* ── "Forge Voice" CTA · HUD-styled trigger ─────────────────────
4111
+ The clone overlay is the most playful surface in the agent
4112
+ profile, so the CTA gets a gamified hardware-HUD look rather
4113
+ than a plain dashed-border card: lime L corners (same vocabulary
4114
+ as the room-settings modal frame), a pulsing mic rune, mono
4115
+ uppercase title with bracketed arrow, a slow horizontal
4116
+ scan-line sweep on hover, and a soft lime glow when focused. */
4117
+ .ap-voice-forge {
4118
+ position: relative;
4119
+ display: grid;
4120
+ grid-template-columns: 1fr;
4121
+ grid-auto-rows: auto;
4122
+ row-gap: 6px;
4123
+ width: 100%;
4124
+ padding: 14px 18px 12px;
4125
+ background: linear-gradient(
4126
+ 180deg,
4127
+ color-mix(in srgb, var(--lime) 6%, var(--panel-2)) 0%,
4128
+ var(--panel-2) 68%
4129
+ );
4130
+ border: 0.5px solid color-mix(in srgb, var(--lime) 36%, var(--line-bright));
4131
+ border-radius: 4px;
4132
+ color: var(--text);
4133
+ text-align: left;
4134
+ cursor: pointer;
4135
+ overflow: hidden;
4136
+ isolation: isolate;
4137
+ transition: border-color 0.18s ease, box-shadow 0.18s ease, transform 0.12s ease;
4138
+ }
4139
+ .ap-voice-forge:hover {
4140
+ border-color: var(--lime);
4141
+ box-shadow:
4142
+ 0 0 0 1px color-mix(in srgb, var(--lime) 24%, transparent),
4143
+ 0 8px 26px -14px color-mix(in srgb, var(--lime) 60%, transparent);
4144
+ }
4145
+ .ap-voice-forge:active { transform: translateY(1px); }
4146
+
4147
+ /* Corner brackets · four lime L shapes pinned to each corner. */
4148
+ .ap-voice-forge-corner {
4149
+ position: absolute;
4150
+ width: 10px;
4151
+ height: 10px;
4152
+ border: 1.5px solid var(--lime);
4153
+ pointer-events: none;
4154
+ z-index: 2;
4155
+ transition: width 0.18s, height 0.18s;
4156
+ }
4157
+ .ap-voice-forge-corner-tl { top: -1px; left: -1px; border-right: none; border-bottom: none; }
4158
+ .ap-voice-forge-corner-tr { top: -1px; right: -1px; border-left: none; border-bottom: none; }
4159
+ .ap-voice-forge-corner-bl { bottom: -1px; left: -1px; border-right: none; border-top: none; }
4160
+ .ap-voice-forge-corner-br { bottom: -1px; right: -1px; border-left: none; border-top: none; }
4161
+ .ap-voice-forge:hover .ap-voice-forge-corner { width: 14px; height: 14px; }
4162
+
4163
+ /* Horizontal scan-line sweep · slow lime gradient slides L→R on
4164
+ hover. Sits behind text. */
4165
+ .ap-voice-forge-scan {
4166
+ position: absolute;
4167
+ inset: 0;
4168
+ pointer-events: none;
4169
+ background: linear-gradient(
4170
+ 90deg,
4171
+ transparent 0%,
4172
+ transparent 38%,
4173
+ color-mix(in srgb, var(--lime) 18%, transparent) 50%,
4174
+ transparent 62%,
4175
+ transparent 100%
4176
+ );
4177
+ background-size: 260% 100%;
4178
+ background-position: -120% 0;
4179
+ z-index: 1;
4180
+ opacity: 0;
4181
+ transition: opacity 0.18s ease;
4182
+ }
4183
+ .ap-voice-forge:hover .ap-voice-forge-scan {
4184
+ opacity: 1;
4185
+ animation: ap-voice-forge-scan-sweep 2.4s linear infinite;
4186
+ }
4187
+ @keyframes ap-voice-forge-scan-sweep {
4188
+ 0% { background-position: -120% 0; }
4189
+ 100% { background-position: 220% 0; }
4190
+ }
4191
+
4192
+ .ap-voice-forge-kicker {
4193
+ position: relative;
4194
+ z-index: 3;
4195
+ font-family: var(--mono);
4196
+ font-size: 10px;
4197
+ font-weight: 700;
4198
+ letter-spacing: 0.22em;
4199
+ text-transform: uppercase;
4200
+ color: color-mix(in srgb, var(--lime) 80%, var(--text));
4201
+ }
4202
+
4203
+ .ap-voice-forge-body {
4204
+ position: relative;
4205
+ z-index: 3;
4206
+ display: flex;
4207
+ align-items: center;
4208
+ gap: 12px;
4209
+ }
4210
+ .ap-voice-forge-rune {
4211
+ position: relative;
4212
+ width: 36px;
4213
+ height: 36px;
4214
+ flex-shrink: 0;
4215
+ display: inline-flex;
4216
+ align-items: center;
4217
+ justify-content: center;
4218
+ color: var(--lime);
4219
+ border: 0.5px solid color-mix(in srgb, var(--lime) 45%, transparent);
4220
+ border-radius: 4px;
4221
+ background: color-mix(in srgb, var(--lime) 8%, transparent);
4222
+ }
4223
+ .ap-voice-forge-rune svg { width: 18px; height: 18px; }
4224
+ .ap-voice-forge-rune::after {
4225
+ content: "";
4226
+ position: absolute;
4227
+ inset: -3px;
4228
+ border-radius: 6px;
4229
+ border: 0.5px solid color-mix(in srgb, var(--lime) 50%, transparent);
4230
+ opacity: 0;
4231
+ transition: opacity 0.18s;
4232
+ pointer-events: none;
4233
+ }
4234
+ .ap-voice-forge:hover .ap-voice-forge-rune::after {
4235
+ opacity: 1;
4236
+ animation: ap-voice-forge-rune-pulse 1.4s ease-in-out infinite;
4237
+ }
4238
+ @keyframes ap-voice-forge-rune-pulse {
4239
+ 0%, 100% { transform: scale(1); opacity: 0.65; }
4240
+ 50% { transform: scale(1.18); opacity: 0; }
4241
+ }
4242
+ .ap-voice-forge-title {
4243
+ flex: 1;
4244
+ min-width: 0;
4245
+ font-family: var(--mono);
4246
+ font-size: 14px;
4247
+ font-weight: 700;
4248
+ letter-spacing: 0.08em;
4249
+ text-transform: uppercase;
4250
+ color: var(--text);
4251
+ white-space: nowrap;
4252
+ overflow: hidden;
4253
+ text-overflow: ellipsis;
4254
+ }
4255
+ .ap-voice-forge-title::before { content: "[ + "; color: var(--text-faint); }
4256
+ .ap-voice-forge-title::after { content: " ]"; color: var(--text-faint); }
4257
+ .ap-voice-forge:hover .ap-voice-forge-title::before,
4258
+ .ap-voice-forge:hover .ap-voice-forge-title::after { color: var(--lime); }
4259
+ .ap-voice-forge-arrow {
4260
+ flex-shrink: 0;
4261
+ font-family: var(--mono);
4262
+ font-size: 18px;
4263
+ line-height: 1;
4264
+ color: var(--lime);
4265
+ transform: translateX(0);
4266
+ transition: transform 0.18s ease;
4267
+ }
4268
+ .ap-voice-forge:hover .ap-voice-forge-arrow { transform: translateX(4px); }
4269
+
4270
+ .ap-voice-forge-hint {
4271
+ position: relative;
4272
+ z-index: 3;
4273
+ font-family: var(--mono);
4274
+ font-size: 11px;
4275
+ color: var(--text-faint);
4276
+ letter-spacing: 0.02em;
4277
+ line-height: 1.55;
4278
+ }
4279
+ .ap-voice-forge-hint::before {
4280
+ content: "// ";
4281
+ color: color-mix(in srgb, var(--lime) 60%, var(--text-faint));
4282
+ }
4283
+
3996
4284
  .ap-voice-picker-row {
3997
4285
  display: flex;
3998
4286
  align-items: center;
@@ -4078,7 +4366,6 @@
4078
4366
  display: flex;
4079
4367
  flex-direction: column;
4080
4368
  gap: 6px;
4081
- margin-top: 8px;
4082
4369
  }
4083
4370
  .ap-voice-emotion-row .ap-voice-emotion-trigger {
4084
4371
  width: 100%;
@@ -4299,45 +4586,54 @@
4299
4586
  pointer-events: none;
4300
4587
  z-index: 0;
4301
4588
  }
4589
+ /* Advanced tuning · sits at the very bottom of the voice block,
4590
+ under the Forge CTA. Plain header row — no chip / no border / no
4591
+ background — so it reads as "extra knobs if you need them" rather
4592
+ than another card vying for attention. Only the top hairline
4593
+ divider remains for section separation; the `+ / −` marker uses
4594
+ lime to stay legible in both light and dark themes. */
4595
+ /* Advanced details wrapper · now lives inside its own
4596
+ .ap-voice-section, which already supplies the top divider +
4597
+ vertical padding. Strip the duplicate spacing/border so the
4598
+ chevron row aligns with neighbouring section headers. */
4302
4599
  .ap-voice-advanced {
4303
- margin-top: 10px;
4304
- border-top: 1px solid var(--line);
4305
- padding-top: 8px;
4600
+ margin: 0;
4601
+ border-top: 0;
4602
+ padding-top: 0;
4306
4603
  }
4307
- /* Header row · label on the left, custom expand/collapse indicator
4308
- on the right. Removes the browser's default ▶ disclosure triangle
4309
- on the left so the row reads as a clean section header rather
4310
- than a list item. The right-edge `+ / −` glyph swaps when
4311
- [open] is set — same hairline mono register the rest of the
4312
- profile uses for header actions. */
4313
4604
  .ap-voice-advanced summary {
4314
4605
  display: flex;
4315
4606
  align-items: center;
4316
4607
  justify-content: space-between;
4317
4608
  gap: 12px;
4609
+ padding: 4px 0;
4318
4610
  font-family: var(--mono, monospace);
4319
- font-size: 10px;
4320
- letter-spacing: 0.04em;
4611
+ font-size: 11px;
4612
+ letter-spacing: 0.14em;
4321
4613
  text-transform: uppercase;
4322
4614
  color: var(--text-soft);
4323
4615
  cursor: pointer;
4324
4616
  user-select: none;
4325
4617
  list-style: none;
4618
+ transition: color 0.12s;
4326
4619
  }
4327
4620
  .ap-voice-advanced summary::-webkit-details-marker { display: none; }
4328
4621
  .ap-voice-advanced summary::marker { display: none; content: ""; }
4329
4622
  .ap-voice-advanced summary::after {
4330
4623
  content: "+";
4331
4624
  font-family: var(--mono, monospace);
4332
- font-size: 14px;
4333
- font-weight: 400;
4625
+ font-size: 16px;
4626
+ font-weight: 700;
4334
4627
  line-height: 1;
4335
- color: var(--text-faint);
4336
- transition: color 0.12s;
4628
+ color: var(--lime);
4629
+ transition: color 0.12s, transform 0.18s ease;
4630
+ }
4631
+ .ap-voice-advanced[open] summary::after {
4632
+ content: "−";
4633
+ transform: rotate(180deg);
4337
4634
  }
4338
- .ap-voice-advanced[open] summary::after { content: "−"; }
4339
4635
  .ap-voice-advanced summary:hover { color: var(--text); }
4340
- .ap-voice-advanced summary:hover::after { color: var(--text); }
4636
+ .ap-voice-advanced summary:hover::after { color: var(--lime); }
4341
4637
 
4342
4638
  /* ────────────────────────────────────────────────────────────
4343
4639
  Persona dossier · Full-mode agents only
@@ -4687,7 +4983,7 @@ html.is-electron-mac .ap-persona-overlay-backdrop {
4687
4983
  }
4688
4984
  .ap-persona-overlay-md h3 {
4689
4985
  font-family: var(--font-human);
4690
- font-size: 13px;
4986
+ font-size: 14px;
4691
4987
  font-weight: 700;
4692
4988
  color: var(--text);
4693
4989
  margin: 18px 0 6px;
@@ -4942,7 +5238,7 @@ body.ap-persona-overlay-open { overflow: hidden; }
4942
5238
  .ap-buildlog-phase-blurb {
4943
5239
  margin: 0;
4944
5240
  font-family: var(--font-human);
4945
- font-size: 13px;
5241
+ font-size: 14px;
4946
5242
  line-height: 1.6;
4947
5243
  color: var(--text-soft);
4948
5244
  padding-left: 34px;