@maka/maka-cli 5.183.0 → 5.184.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.
Files changed (28) hide show
  1. package/bundle/typescript/package.json +1 -1
  2. package/bundle/typescript/src/commands/game/sideQuest/commands/ar.js +6 -6
  3. package/bundle/typescript/src/commands/game/sideQuest/commands/delay.js +1 -1
  4. package/bundle/typescript/src/commands/game/sideQuest/commands/disable.js +2 -2
  5. package/bundle/typescript/src/commands/game/sideQuest/commands/download.js +3 -3
  6. package/bundle/typescript/src/commands/game/sideQuest/commands/end-turn.js +1 -1
  7. package/bundle/typescript/src/commands/game/sideQuest/commands/enter-host.js +11 -13
  8. package/bundle/typescript/src/commands/game/sideQuest/commands/hack.js +7 -7
  9. package/bundle/typescript/src/commands/game/sideQuest/commands/hop.js +2 -2
  10. package/bundle/typescript/src/commands/game/sideQuest/commands/look.js +5 -5
  11. package/bundle/typescript/src/commands/game/sideQuest/commands/map.js +1 -1
  12. package/bundle/typescript/src/commands/game/sideQuest/commands/mark.js +1 -1
  13. package/bundle/typescript/src/commands/game/sideQuest/commands/search.js +3 -3
  14. package/bundle/typescript/src/commands/game/sideQuest/commands/snoop.js +1 -1
  15. package/bundle/typescript/src/commands/game/sideQuest/commands/sprites.js +1 -1
  16. package/bundle/typescript/src/commands/game/sideQuest/commands/tap.js +7 -7
  17. package/bundle/typescript/src/commands/game/sideQuest/commands/thread.js +1 -1
  18. package/bundle/typescript/src/commands/game/sideQuest/game.js +3 -3
  19. package/bundle/typescript/src/commands/game/sideQuest/models/player.js +2 -1
  20. package/bundle/typescript/src/commands/game/sideQuest/utilities/ar.js +1 -1
  21. package/bundle/typescript/src/commands/game/sideQuest/utilities/combat-turn.js +2 -2
  22. package/bundle/typescript/src/commands/game/sideQuest/utilities/grid-reach.js +1 -1
  23. package/bundle/typescript/src/commands/game/sideQuest/utilities/grid-view.js +14 -14
  24. package/bundle/typescript/src/commands/game/sideQuest/utilities/matrix-style.js +8 -0
  25. package/bundle/typescript/src/commands/game/sideQuest/utilities/overwatch.js +2 -2
  26. package/bundle/typescript/src/commands/game/sideQuest/utilities/planes.js +3 -3
  27. package/bundle/typescript/src/commands/game/sideQuest/utilities/shared-run.js +2 -1
  28. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maka/maka-cli",
3
- "version": "5.183.0",
3
+ "version": "5.184.0",
4
4
  "type": "module",
5
5
  "summary": "A command line tool for scaffolding Meteor 3.x applications using either React.",
6
6
  "description": "A command line tool for scaffolding Meteor 3.x applications using React.",
@@ -64,14 +64,14 @@ export class ArCommand extends Command {
64
64
  return `Overlay back on -- over nothing. No commlink, no deck, no AR: you're reading the street with your eyes like it's 2050.`;
65
65
  }
66
66
  const tags = aroTags(this.scene, actor, actor.currentLocation);
67
- const head = `{cyan-fg}The overlay blinks back in.{/cyan-fg}`;
67
+ const head = `{lightblue-fg}The overlay blinks back in.{/lightblue-fg}`;
68
68
  // Turning AR back on while silent is the other moment the question
69
69
  // lands -- you have just done the thing you were unsure was allowed.
70
70
  const note = silentAndSeeingNote(actor);
71
71
  if (tags.length === 0) {
72
- return [head, `{cyan-fg}Nothing here is talking -- a dead patch of street.{/cyan-fg}`, note].filter(Boolean).join('\n');
72
+ return [head, `{lightblue-fg}Nothing here is talking -- a dead patch of street.{/lightblue-fg}`, note].filter(Boolean).join('\n');
73
73
  }
74
- return [head, ...tags.map(t => ` {cyan-fg}${t}{/cyan-fg}`), note].filter(Boolean).join('\n');
74
+ return [head, ...tags.map(t => ` {lightblue-fg}${t}{/lightblue-fg}`), note].filter(Boolean).join('\n');
75
75
  }
76
76
  }
77
77
  /**
@@ -105,11 +105,11 @@ export class ArosCommand extends Command {
105
105
  const note = silentAndSeeingNote(actor);
106
106
  const tags = aroTags(this.scene, actor, actor.currentLocation);
107
107
  if (tags.length === 0) {
108
- return [`{cyan-fg}Nothing here is talking -- a dead patch of street.{/cyan-fg}`, note].filter(Boolean).join('\n');
108
+ return [`{lightblue-fg}Nothing here is talking -- a dead patch of street.{/lightblue-fg}`, note].filter(Boolean).join('\n');
109
109
  }
110
110
  return [
111
- `{cyan-fg}AR OVERLAY:{/cyan-fg}`,
112
- ...tags.map(t => ` {cyan-fg}${t}{/cyan-fg}`),
111
+ `{lightblue-fg}AR OVERLAY:{/lightblue-fg}`,
112
+ ...tags.map(t => ` {lightblue-fg}${t}{/lightblue-fg}`),
113
113
  note,
114
114
  ].filter(Boolean).join('\n');
115
115
  }
@@ -25,7 +25,7 @@ export class DelayCommand extends Command {
25
25
  return `Too late to delay -- you've already acted this phase (${budget.ledger()}). "end turn" instead.`;
26
26
  }
27
27
  if (this.scene.isHumanControlled(actor)) {
28
- this.logger.log(`{cyan-fg}You hold your action, watching.{/cyan-fg}`, { actor: actor.name });
28
+ this.logger.log(`{yellow-fg}You hold your action, watching.{/yellow-fg}`, { actor: actor.name });
29
29
  }
30
30
  await enc.delayPhase(actor);
31
31
  return this.scene.isHumanControlled(actor) ? '' : `${actor.name} holds their action.`;
@@ -180,7 +180,7 @@ export class DisableCommand extends Command {
180
180
  const defence = this.defence(t);
181
181
  const defenceRoll = rollPool(defence.pool);
182
182
  const net = roll.hits - defenceRoll.hits;
183
- actor.performAction('takes control of a device', name);
183
+ actor.performAction('takes control of a device', name, { quiet: this.scene.isHumanControlled(actor) });
184
184
  if (this.scene.isHumanControlled(actor)) {
185
185
  this.logger.meta(`Control Device (Electronic Warfare + Intuition [Sleaze])${gridNote(grid)}: ${formatRoll(roll)}`);
186
186
  this.logger.meta(`${defence.label}: ${formatRoll(defenceRoll)} -- net ${net >= 0 ? '+' : ''}${net}`);
@@ -236,7 +236,7 @@ export class DisableCommand extends Command {
236
236
  const defence = this.defence(t);
237
237
  const defenceRoll = rollPool(defence.pool);
238
238
  const net = roll.hits - defenceRoll.hits;
239
- actor.performAction('throws a Data Spike', name);
239
+ actor.performAction('throws a Data Spike', name, { quiet: this.scene.isHumanControlled(actor) });
240
240
  if (this.scene.isHumanControlled(actor)) {
241
241
  this.logger.meta(`Data Spike (Cybercombat + Logic [Attack ${limit}])${gridNote(grid)}: ${formatRoll(roll)}`);
242
242
  this.logger.meta(`${defence.label}: ${formatRoll(defenceRoll)} -- net ${net >= 0 ? '+' : ''}${net}`);
@@ -92,7 +92,7 @@ export class DownloadCommand extends Command {
92
92
  // is that nobody could find the file should say what it can see.
93
93
  const query = args.join(' ').trim();
94
94
  if (query.length === 0) {
95
- const lines = [`{cyan-fg}Within reach to pull down:{/cyan-fg}`];
95
+ const lines = [`{lightblue-fg}Within reach to pull down:{/lightblue-fg}`];
96
96
  for (const i of loose)
97
97
  lines.push(` ${planeTintItemName(i, actor.plane)} -- loose on the grid here`);
98
98
  for (const c of carried)
@@ -134,11 +134,11 @@ export class DownloadCommand extends Command {
134
134
  this.scene.updateStatus();
135
135
  return fromSprite
136
136
  ? [
137
- `{cyan-fg}${fromSprite.npc.name} opens its hands and the data pours out of them.{/cyan-fg}`,
137
+ `{lightblue-fg}${fromSprite.npc.name} opens its hands and the data pours out of them.{/lightblue-fg}`,
138
138
  `You pull {bold}{underline}${item.name}{/underline}{/bold} down onto a chip -- meat-world cargo now.${hint(` (You can "give ${item.name}" to somebody standing in front of you.)`)}`,
139
139
  ].join('\n')
140
140
  : [
141
- `{cyan-fg}You pull {bold}{underline}${item.name}{/underline}{/bold} down off the grid -- written to a chip.{/cyan-fg}`,
141
+ `{lightblue-fg}You pull {bold}{underline}${item.name}{/underline}{/bold} down off the grid -- written to a chip.{/lightblue-fg}`,
142
142
  hint(`(Meat-world cargo now: carry it, stash it, or "give" it to somebody.)`),
143
143
  ].join('\n');
144
144
  }
@@ -49,7 +49,7 @@ export class EndTurnCommand extends Command {
49
49
  // Logged now rather than returned: the phases that follow announce
50
50
  // themselves while this command is still running, and a return
51
51
  // value would land under them, out of order.
52
- this.logger.log(`{cyan-fg}You end your Action Phase${budget && budget.spent.length > 0 ? ` -- ${ledger}` : ' -- nothing spent'}.{/cyan-fg}`, { actor: actor.name });
52
+ this.logger.log(`{yellow-fg}You end your Action Phase${budget && budget.spent.length > 0 ? ` -- ${ledger}` : ' -- nothing spent'}.{/yellow-fg}`, { actor: actor.name });
53
53
  }
54
54
  await enc.endPhase(actor);
55
55
  return this.scene.isHumanControlled(actor) ? '' : `${actor.name} ends their Action Phase.`;
@@ -64,7 +64,7 @@ export class EnterHostCommand extends Command {
64
64
  const marks = target.hostMarksBy.get(actor.name) ?? 0;
65
65
  if (marks < 1 && !target.hostCracked && !target.hostSanctioned) {
66
66
  return [
67
- `{cyan-fg}${hostLabel(target, { capital: true })} doesn't know you. Its architecture has no door shaped like your icon.{/cyan-fg}`,
67
+ `{lightblue-fg}${hostLabel(target, { capital: true })} doesn't know you. Its architecture has no door shaped like your icon.{/lightblue-fg}`,
68
68
  hint(`A host opens to anyone holding a MARK on it (p.239) -- "mark ${target.name}" softens it, or "hack" takes one by force.`),
69
69
  ].join('\n');
70
70
  }
@@ -79,14 +79,15 @@ export class EnterHostCommand extends Command {
79
79
  // you there). currentLocation is never written -- it is the body's.
80
80
  actor.matrixPosition = { kind: 'host', host: target.host, from: actor.currentGrid };
81
81
  movePersonaWith(this.game ?? undefined, actor);
82
- actor.performAction('enters a host', `icon crossing into ${target.name}'s architecture`);
82
+ actor.performAction('enters a host', `icon crossing into ${target.name}'s architecture`, { quiet: this.scene.isHumanControlled(actor) });
83
83
  this.logger.write(`${actor.name} entered the host at ${target.name}.`);
84
84
  this.scene.updateStatus();
85
+ // ONE LINE (2026-09-13, "too much text"): the crossing, and the
86
+ // coaching behind the hints toggle.
85
87
  return [
86
- `{cyan-fg}You cross into ${hostLabel(target, { capital: false })}.{/cyan-fg}`,
87
- `{cyan-fg}The outside grid folds shut behind you -- the icons in reach, the PANs, the personas out on the grid: all of it gone, not hidden. In here there is only what the host keeps.{/cyan-fg}`,
88
- hint(`"look" reads the space you're standing in now. "exit" puts you back on the grid.`),
89
- ].join('\n');
88
+ `{lightblue-fg}You cross into ${hostLabel(target, { capital: false })} -- the outside grid folds shut behind you.{/lightblue-fg}`,
89
+ hint(`(In here there is only what the host keeps. "look" reads it; "exit" puts you back on the grid.)`),
90
+ ].filter(Boolean).join('\n');
90
91
  }
91
92
  /**
92
93
  * The host this verb means. Bare `enter` takes the one under your feet
@@ -109,14 +110,14 @@ export class EnterHostCommand extends Command {
109
110
  const over = hostOver(gridVicinity(this.actor)) ?? hostOver(here);
110
111
  if (over)
111
112
  return over;
112
- return `{cyan-fg}Thin grid here -- no host stands over ${gridVicinity(this.actor).name}.{/cyan-fg} ${hint(`Overhead: ${roster} -- "enter <name>" crosses into any of them from here.`)}`;
113
+ return `{lightblue-fg}Thin grid here -- no host stands over ${gridVicinity(this.actor).name}.{/lightblue-fg} ${hint(`Overhead: ${roster} -- "enter <name>" crosses into any of them from here.`)}`;
113
114
  }
114
115
  const host = resolveHostInReach(rooms, this.actor, named);
115
116
  if (host)
116
117
  return host;
117
118
  const street = Object.values(rooms).find(r => r.name.toLowerCase() === named.toLowerCase());
118
119
  if (street)
119
- return `{cyan-fg}${street.name} has no host over it -- nothing to enter. Overhead: ${roster}.{/cyan-fg}`;
120
+ return `{lightblue-fg}${street.name} has no host over it -- nothing to enter. Overhead: ${roster}.{/lightblue-fg}`;
120
121
  return `No host called "${named}" overhead. ${hint(`Overhead: ${roster}.`)}`;
121
122
  }
122
123
  }
@@ -148,13 +149,10 @@ export class ExitHostCommand extends Command {
148
149
  const from = actor.matrixPosition?.kind === 'host' ? actor.matrixPosition.from : undefined;
149
150
  actor.matrixPosition = { kind: 'grid', grid: from };
150
151
  movePersonaWith(this.game ?? undefined, actor);
151
- actor.performAction('exits a host', `icon surfacing out of ${host.name}'s architecture`);
152
+ actor.performAction('exits a host', `icon surfacing out of ${host.name}'s architecture`, { quiet: this.scene.isHumanControlled(actor) });
152
153
  this.logger.write(`${actor.name} exited the host at ${host.name}.`);
153
154
  this.scene.updateStatus();
154
- return [
155
- `{cyan-fg}You step back out of ${hostLabel(host, { capital: false })} and onto the grid -- your body still sits in ${actor.currentLocation.name}.{/cyan-fg}`,
156
- `{cyan-fg}The host seals behind you: one icon again, whatever you saw in there now on the other side of its wall.{/cyan-fg}`,
157
- ].join('\n');
155
+ return `{lightblue-fg}You step back out of ${hostLabel(host, { capital: false })} onto the grid; the host seals behind you. Your body still sits in ${actor.currentLocation.name}.{/lightblue-fg}`;
158
156
  }
159
157
  }
160
158
  //# sourceMappingURL=enter-host.js.map
@@ -173,7 +173,7 @@ export class HackCommand extends BypassCommand {
173
173
  const burned = this.actor.burnedAttributeRefusal(mode === 'attack' ? 'attack' : 'sleaze');
174
174
  if (burned)
175
175
  return burned;
176
- this.actor.performAction('hacks the host', room.name);
176
+ this.actor.performAction('hacks the host', room.name, { quiet: this.scene.isHumanControlled(this.actor) });
177
177
  const attempt = await this.hostIntrusionRoll(mode, declared, room);
178
178
  const success = attempt.success;
179
179
  // GOD BILLS THE DEFENDER'S HITS (p.231-232): "your OS increases by
@@ -276,7 +276,7 @@ export class HackCommand extends BypassCommand {
276
276
  if (marksNow >= 1)
277
277
  lines.push(` One mark is the door: "enter" walks your persona inside (p.239).`);
278
278
  if (perception > 0)
279
- lines.push(` {cyan-fg}And you read it on the way past -- ${perception} Matrix Perception hit${perception === 1 ? '' : 's'} of what this node is (p.240).{/cyan-fg}`);
279
+ lines.push(` {lightblue-fg}And you read it on the way past -- ${perception} Matrix Perception hit${perception === 1 ? '' : 's'} of what this node is (p.240).{/lightblue-fg}`);
280
280
  if (forcedDv > 0)
281
281
  lines.push(` The forcing burns ${forcedDv} DV into the architecture -- a host has no boards to brick, so it only announces you louder.`);
282
282
  lines.push(` ${MAX_MARKS - marksNow} more and its architecture stops asking who you are.${hint(` ("hack for ${MAX_MARKS - marksNow}" reaches for the rest at once -- ${declarationPenalty(MAX_MARKS - marksNow, this.actor.hasQuality(GO_BIG_QUALITY))} dice.)`)}`);
@@ -340,13 +340,13 @@ export class HackCommand extends BypassCommand {
340
340
  lines.push(` ${iconLocks.length} ${iconLocks.length === 1 ? 'lock hangs' : 'locks hang'} off it, still sealed -- each its own icon behind its own rating: ${iconLocks.map(d => d.name).join(', ')}.${hint(` ("hack <lock>" from in here keys one; the host's key is not the door's.)`)}`);
341
341
  }
342
342
  if (vaultedFiles.length > 0) {
343
- lines.push(` {cyan-fg}The data vault unseals -- ${vaultedFiles.map(i => i.name).join(', ')} spill${vaultedFiles.length === 1 ? 's' : ''} into the open.${hint(` Yours to "take".`)}{/cyan-fg}`);
343
+ lines.push(` {lightblue-fg}The data vault unseals -- ${vaultedFiles.map(i => i.name).join(', ')} spill${vaultedFiles.length === 1 ? 's' : ''} into the open.${hint(` Yours to "take".`)}{/lightblue-fg}`);
344
344
  }
345
345
  // AND WHAT THE CRACK DID NOT REACH: a wired site's data sits on an
346
346
  // air-gapped box the host never held (p.233) -- say so, or the next
347
347
  // "take" reads as a contradiction.
348
348
  if (room.offlineServer && room.inventory.getAllItems().some(i => i.plane === 'matrix')) {
349
- lines.push(` {cyan-fg}Nothing on the grid side of the vault -- whatever this place keeps sits on the ${room.offlineServer}, an air-gapped box with no Matrix presence. Your BODY has to be in ${room.name} to cable in (p.233).{/cyan-fg}`);
349
+ lines.push(` {lightblue-fg}Nothing on the grid side of the vault -- whatever this place keeps sits on the ${room.offlineServer}, an air-gapped box with no Matrix presence. Your BODY has to be in ${room.name} to cable in (p.233).{/lightblue-fg}`);
350
350
  }
351
351
  // THE FEEDS ARE A REAL GAIN AND WERE NEVER MENTIONED
352
352
  // (BpR5cjhYuvgCyDSZc, 7aNWnDSHeZMYmS2De: "what have I gained?").
@@ -540,7 +540,7 @@ export class HackCommand extends BypassCommand {
540
540
  ? Math.max(1, actor.getAttackPool() + silence + actor.bonus('matrix-attack') + declarePenalty)
541
541
  : Math.max(1, actor.logic + actor.skillRating('hacking') + actor.bonus('hacking') + actor.bonus('matrix-sleaze')
542
542
  + silence + actor.woundModifier - actor.sustainingPenalty + declarePenalty);
543
- actor.performAction('works a slaved icon', device.name);
543
+ actor.performAction('works a slaved icon', device.name, { quiet: this.scene.isHumanControlled(actor) });
544
544
  const roll = rollPool(pool, limit, { gremlins: actor.deckGremlins });
545
545
  // From the grid the slave borrows its master's numbers where they are
546
546
  // higher (p.233); inside, it stands alone (Data Trails p.87-88).
@@ -606,7 +606,7 @@ export class HackCommand extends BypassCommand {
606
606
  else {
607
607
  const perception = freeMatrixPerceptionHits(netHits);
608
608
  if (perception > 0)
609
- lines.push(` {cyan-fg}And you read it on the way past -- ${perception} Matrix Perception hit${perception === 1 ? '' : 's'} of what it guards (p.240).{/cyan-fg}`);
609
+ lines.push(` {lightblue-fg}And you read it on the way past -- ${perception} Matrix Perception hit${perception === 1 ? '' : 's'} of what it guards (p.240).{/lightblue-fg}`);
610
610
  }
611
611
  // TWO MARKS COMMAND IT (p.238 Control Device: 1 mark for a Free
612
612
  // action, 2 for a Simple, 3 for a Complex -- and unlocking a maglock
@@ -765,7 +765,7 @@ export class HackCommand extends BypassCommand {
765
765
  // Intuition + Firewall against a sleaze, Willpower + Firewall
766
766
  // against a smash (p.240 / p.238), and no limit on either.
767
767
  const defense = rollPool(target.getPanDefensePool(mode === 'attack' ? 'attack' : 'sleaze'));
768
- actor.performAction('runs a PAN intrusion', target.name);
768
+ actor.performAction('runs a PAN intrusion', target.name, { quiet: this.scene.isHumanControlled(actor) });
769
769
  this.logger.write(`${actor.name} PAN-hacks ${target.name}: ${attack.hits} vs ${defense.hits} (silent=${target.runningSilent}).`);
770
770
  // Dice anatomy to the Mechanics ticker (readability pass) --
771
771
  // player-gated like every roll site: an NPC's probe isn't your dice.
@@ -53,7 +53,7 @@ export class HopCommand extends Command {
53
53
  actor.performAction('hops grids', `persona blinking across to ${target.name}`);
54
54
  this.logger.write(`${actor.name} hopped to ${target.key} (legal, ${tier}).`);
55
55
  this.scene.updateStatus();
56
- return `{cyan-fg}The sky changes texture and you're on ${target.name}.{/cyan-fg}${target.userPenalty ? ` ${hint(`Public grid: -2 on everything you do out here.`)}` : ''}`;
56
+ return `{lightblue-fg}The sky changes texture and you're on ${target.name}.{/lightblue-fg}${target.userPenalty ? ` ${hint(`Public grid: -2 on everything you do out here.`)}` : ''}`;
57
57
  }
58
58
  // ILLEGAL HOP (p.240): Hack on the Fly against the grid itself.
59
59
  const burned = actor.burnedAttributeRefusal('sleaze');
@@ -87,7 +87,7 @@ export class HopCommand extends Command {
87
87
  this.logger.write(`${actor.name} hopped to ${target.key} (illegal, ${attempt.hits} v ${defence.hits}).`);
88
88
  this.scene.updateStatus();
89
89
  return [
90
- `{cyan-fg}You slip through a seam nobody sold you and come up on ${target.name}.{/cyan-fg}`,
90
+ `{lightblue-fg}You slip through a seam nobody sold you and come up on ${target.name}.{/lightblue-fg}`,
91
91
  ...bill.lines,
92
92
  ].join('\n');
93
93
  }
@@ -379,7 +379,7 @@ export class LookCommand extends Command {
379
379
  const dim = this.scene.getActorsInRoom(far)
380
380
  .find(a => a !== this.actor && a.name.toLowerCase() === target.toLowerCase() && this.actor.canPerceive(a));
381
381
  if (dim)
382
- return `${this.inspectPersona(dim)}\n{cyan-fg} -- a far icon, ${far.name}${noiseNote(noise)}{/cyan-fg}`;
382
+ return `${this.inspectPersona(dim)}\n{lightblue-fg} -- a far icon, ${far.name}${noiseNote(noise)}{/lightblue-fg}`;
383
383
  }
384
384
  }
385
385
  // 3. THE HOST, as a thing you can name. gridIcons already renders it
@@ -396,8 +396,8 @@ export class LookCommand extends Command {
396
396
  // `deck` reads out your own array.
397
397
  const a = namedHost.hostAttributes();
398
398
  return [
399
- `{cyan-fg}${hostIcon}{/cyan-fg}`,
400
- `{cyan-fg} Attack ${a.attack} Sleaze ${a.sleaze} Data Processing ${a.dataProcessing} Firewall ${a.firewall}{/cyan-fg}`,
399
+ `{lightblue-fg}${hostIcon}{/lightblue-fg}`,
400
+ `{lightblue-fg} Attack ${a.attack} Sleaze ${a.sleaze} Data Processing ${a.dataProcessing} Firewall ${a.firewall}{/lightblue-fg}`,
401
401
  ].join('\n');
402
402
  }
403
403
  }
@@ -409,7 +409,7 @@ export class LookCommand extends Command {
409
409
  if (matchesCameraName(target)) {
410
410
  const eye = gridIcons(this.scene, this.actor, room).find(i => i.startsWith('◎'));
411
411
  if (eye)
412
- return `{cyan-fg}${eye}{/cyan-fg}`;
412
+ return `{lightblue-fg}${eye}{/lightblue-fg}`;
413
413
  // Named correctly, and there is simply nothing here to name.
414
414
  // Worth its own line: the old answer said the WORDS were wrong,
415
415
  // which sent the player hunting for a synonym that never
@@ -525,7 +525,7 @@ export class LookCommand extends Command {
525
525
  * there's a deck anywhere in the shape of it.
526
526
  */
527
527
  inspectPersona(target) {
528
- const lines = [`{cyan-fg}◆ ${target.name} -- a persona on this grid.{/cyan-fg}`];
528
+ const lines = [`{lightblue-fg}◆ ${target.name} -- a persona on this grid.{/lightblue-fg}`];
529
529
  const companion = this.scene.ownerGame?.companions.find(c => c.npc === target);
530
530
  if (companion) {
531
531
  lines.push(`Yours -- it goes where you go, and it answers when you speak.`);
@@ -93,7 +93,7 @@ export class MapCommand extends Command {
93
93
  actor.insideHost
94
94
  ? `THE GRID -- INSIDE ${hostLabel(actor.insideHost, { capital: true }).toUpperCase()}`
95
95
  : `THE GRID -- ${actor.currentGrid ? `on ${actor.currentGrid.name}, ` : ''}jacked in from ${body.name}`,
96
- `{cyan-fg}Black flatland under a black sky. No streets out here -- only icons. The hosts hang overhead; ${actor.insideHost ? '"exit" puts you back under them' : '"go <host>" (or "go <number>") crosses into one you hold a mark on, from anywhere'}.{/cyan-fg}`,
96
+ `{lightblue-fg}Black flatland under a black sky. No streets out here -- only icons. The hosts hang overhead; ${actor.insideHost ? '"exit" puts you back under them' : '"go <host>" (or "go <number>") crosses into one you hold a mark on, from anywhere'}.{/lightblue-fg}`,
97
97
  ];
98
98
  if (hosts.length === 0) {
99
99
  lines.push(' Nothing overhead -- no host stands over this district.');
@@ -51,7 +51,7 @@ export class MarkCommand extends Command {
51
51
  screen: this.screen,
52
52
  game: this.game,
53
53
  }).execute(args);
54
- return `{cyan-fg}Placing a mark IS ${action} -- running it (p.238/p.240).{/cyan-fg}\n${result}`;
54
+ return `{lightblue-fg}Placing a mark IS ${action} -- running it (p.238/p.240).{/lightblue-fg}\n${result}`;
55
55
  }
56
56
  }
57
57
  //# sourceMappingURL=mark.js.map
@@ -175,7 +175,7 @@ export class SearchCommand extends Command {
175
175
  // seconds spent is what makes the next illegal action pay for them.
176
176
  if (actor.overwatchLastTick > 0)
177
177
  actor.overwatchLastTick -= seconds * 1000;
178
- actor.performAction('runs a Matrix Search', host ? `inside ${hostLabel(where)}` : `across ${where.name}'s grid`);
178
+ actor.performAction('runs a Matrix Search', host ? `inside ${hostLabel(where)}` : `across ${where.name}'s grid`, { quiet: this.scene.isHumanControlled(actor) });
179
179
  const files = where.offlineServer ? [] : where.inventory.getAllItems().filter(i => i.plane === 'matrix');
180
180
  const clock = `(${seconds}s of Matrix time${browse ? ', Browse cutting it' : ''})`;
181
181
  if (roll.hits < row.threshold) {
@@ -313,8 +313,8 @@ export class SearchCommand extends Command {
313
313
  // tells a player standing next to an offline server that it is
314
314
  // there and what it wants from them.
315
315
  description += room.offlineServer
316
- ? `\n{cyan-fg}A ${room.offlineServer} sits here, dark and off the network -- no aerial, no marquee, nothing broadcasting. Whatever it holds comes out through a cable and no other way.${hint(` "jack in" RIGHT HERE to touch its files.`)}{/cyan-fg}`
317
- : `\n{cyan-fg}The node here hums with locked files -- whatever's worth taking lives on the grid, inside the host.${hint(` "jack in", then "enter" the host.`)}{/cyan-fg}`;
316
+ ? `\n{lightblue-fg}A ${room.offlineServer} sits here, dark and off the network -- no aerial, no marquee, nothing broadcasting. Whatever it holds comes out through a cable and no other way.${hint(` "jack in" RIGHT HERE to touch its files.`)}{/lightblue-fg}`
317
+ : `\n{lightblue-fg}The node here hums with locked files -- whatever's worth taking lives on the grid, inside the host.${hint(` "jack in", then "enter" the host.`)}{/lightblue-fg}`;
318
318
  }
319
319
  description += describeContainers(room, this.actor);
320
320
  description += describeBarriers(room, this.actor);
@@ -49,7 +49,7 @@ export class SnoopCommand extends Command {
49
49
  this.logger.write(`Snoop: ${actor.name} watching ${target.name} via camera feed.`);
50
50
  const lines = [`CAMERA FEED: ${target.name.toUpperCase()}`];
51
51
  if (!camerasLive(allRooms, target)) {
52
- lines.push(`{cyan-fg}(Security sees a loop of empty hallways -- these eyes answer only to you now.){/cyan-fg}`);
52
+ lines.push(`{lightblue-fg}(Security sees a loop of empty hallways -- these eyes answer only to you now.){/lightblue-fg}`);
53
53
  }
54
54
  const seen = this.scene.getActorsInRoom(target)
55
55
  .filter(a => a !== actor && a.plane === 'meat' && !a.sneaking);
@@ -73,7 +73,7 @@ export class SpritesCommand extends Command {
73
73
  const name = type?.name ?? set.spriteKey;
74
74
  const isMine = mineType === set.spriteKey;
75
75
  const powers = powersForSprite(set.spriteKey);
76
- lines.push(`${name.toUpperCase()} SPRITE${isMine ? ' {cyan-fg}(yours){/cyan-fg}' : ''}${type ? ` -- ${type.blurb}` : ''}`);
76
+ lines.push(`${name.toUpperCase()} SPRITE${isMine ? ' {lightblue-fg}(yours){/lightblue-fg}' : ''}${type ? ` -- ${type.blurb}` : ''}`);
77
77
  lines.push(` Skills: ${skillsForSprite(set.spriteKey).join(', ')}${hint(` (${set.page})`)}`);
78
78
  if (!detailed) {
79
79
  // The names alone, which is the comparison view.
@@ -158,9 +158,9 @@ export class TapCommand extends Command {
158
158
  }
159
159
  this.logger.write(`${actor.name} now holds ${now} mark(s) on ${host.name} via the ${room.name} cameras.`);
160
160
  const lines = [
161
- `{cyan-fg}The filament finds the connector and the camera stops being a camera -- it's a device, and it's talking to you.{/cyan-fg}`,
162
- ` {cyan-fg}It never gets to hide behind ${hostLabel(host)}: a cable doesn't ask the network for permission, so the lens has to defend itself with what a lens has. It doesn't have much.{/cyan-fg}`,
163
- ` {cyan-fg}MARK PLACED -- and it lands on the host too. The camera answers to ${host.name}, and anything ${host.name} trusts to speak for it just handed you a key. [${now}/${MAX_MARKS}]{/cyan-fg}`,
161
+ `{lightblue-fg}The filament finds the connector and the camera stops being a camera -- it's a device, and it's talking to you.{/lightblue-fg}`,
162
+ ` {lightblue-fg}It never gets to hide behind ${hostLabel(host)}: a cable doesn't ask the network for permission, so the lens has to defend itself with what a lens has. It doesn't have much.{/lightblue-fg}`,
163
+ ` {lightblue-fg}MARK PLACED -- and it lands on the host too. The camera answers to ${host.name}, and anything ${host.name} trusts to speak for it just handed you a key. [${now}/${MAX_MARKS}]{/lightblue-fg}`,
164
164
  ];
165
165
  if (mode === 'attack') {
166
166
  lines.push(` The housing is visibly forced -- the host FELT that one, even if nothing saw your face.`);
@@ -169,15 +169,15 @@ export class TapCommand extends Command {
169
169
  lines.push(` Nothing logged, nothing flagged. You were never here.`);
170
170
  }
171
171
  if (host === room) {
172
- lines.push(` {cyan-fg}${now >= MAX_MARKS
172
+ lines.push(` {lightblue-fg}${now >= MAX_MARKS
173
173
  ? `The host thinks you belong now -- "hack" walks straight in.`
174
- : `${hostLabel(host, { capital: true })} cracks easier with every key you hold${hint(` -- "jack in" and "hack", or come back for another lens`)}.`}{/cyan-fg}`);
174
+ : `${hostLabel(host, { capital: true })} cracks easier with every key you hold${hint(` -- "jack in" and "hack", or come back for another lens`)}.`}{/lightblue-fg}`);
175
175
  }
176
176
  else {
177
- lines.push(` {cyan-fg}These lenses ride the site network, so the key fits ${hostLabel(host)}${hint(` -- "jack in", "go ${host.name}", "hack"`)}.{/cyan-fg}`);
177
+ lines.push(` {lightblue-fg}These lenses ride the site network, so the key fits ${hostLabel(host)}${hint(` -- "jack in", "go ${host.name}", "hack"`)}.{/lightblue-fg}`);
178
178
  }
179
179
  // A mark is all canSnoopFeeds ever wanted (surveillance.ts).
180
- lines.push(` {cyan-fg}And the eyes are half yours already${hint(` -- jacked in, "snoop <room>" rides any feed on this network`)}.{/cyan-fg}`);
180
+ lines.push(` {lightblue-fg}And the eyes are half yours already${hint(` -- jacked in, "snoop <room>" rides any feed on this network`)}.{/lightblue-fg}`);
181
181
  lines.push(...godLines);
182
182
  this.scene.updateStatus();
183
183
  return lines.join('\n');
@@ -67,7 +67,7 @@ export class ThreadCommand extends Command {
67
67
  const lines = [`COMPLEX FORMS (thread <form> <level>)`];
68
68
  for (const f of FORMS) {
69
69
  const held = actor.sustainedForms.some(s => s.key === f.key);
70
- lines.push(` ${f.name.padEnd(16)} ${f.kind === 'sustained' ? '[sustained]' : '[instant] '} ${f.blurb}${held ? ' {cyan-fg}(HELD){/cyan-fg}' : ''}`);
70
+ lines.push(` ${f.name.padEnd(16)} ${f.kind === 'sustained' ? '[sustained]' : '[instant] '} ${f.blurb}${held ? ' {lightblue-fg}(HELD){/lightblue-fg}' : ''}`);
71
71
  }
72
72
  if (actor.sustainedForms.length > 0) {
73
73
  lines.push('', ` Holding ${actor.sustainedForms.length} form${actor.sustainedForms.length === 1 ? '' : 's'} (${sustainTotal(actor.sustainedLedger().filter(w => w.kind === 'form'))}).${hint(` ("thread drop <form>" releases.)`)}`);
@@ -5665,7 +5665,7 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
5665
5665
  // works the grid while you're back in the meat (the AR-drop exit).
5666
5666
  const remoteAgent = this.companions.find(c => c.kind === 'agent');
5667
5667
  if (remoteAgent && player.plane !== 'matrix') {
5668
- lines.push(`{cyan-fg}▣ DECK IN AR -- ${remoteAgent.npc.name} on the grid${remoteAgent.npc.objective ? ', working its directive' : ''}${hint(' ("jack in" to rejoin it, "recall" to fold it home)')}{/cyan-fg}`);
5668
+ lines.push(`{lightblue-fg}▣ DECK IN AR -- ${remoteAgent.npc.name} on the grid${remoteAgent.npc.objective ? ', working its directive' : ''}${hint(' ("jack in" to rejoin it, "recall" to fold it home)')}{/lightblue-fg}`);
5669
5669
  }
5670
5670
  // Off-plane context: which reality you're in, your persona's Matrix
5671
5671
  // track (cold-sim damage lands there), and where your empty body lies.
@@ -5684,7 +5684,7 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
5684
5684
  const track = jackedDeck
5685
5685
  ? ` Deck A${jackedDeck.attack} S${jackedDeck.sleaze} D${jackedDeck.dataProcessing} F${jackedDeck.firewall} ${jackedDeck.deckSummary()}${player.simMode === 'hot' ? ' +biofeedback' : ''}${pgms}`
5686
5686
  : ` (living persona -- damage is REAL stun)`;
5687
- lines.push(`{cyan-fg}▣ MATRIX ${(player.simMode ?? 'cold').toUpperCase()}-SIM${track} -- body at ${player.bodyRoom?.name ?? '???'}{/cyan-fg}`);
5687
+ lines.push(`{lightblue-fg}▣ MATRIX ${(player.simMode ?? 'cold').toUpperCase()}-SIM${track} -- body at ${player.bodyRoom?.name ?? '???'}{/lightblue-fg}`);
5688
5688
  }
5689
5689
  else if (player.plane === 'astral') {
5690
5690
  lines.push(`{magenta-fg}✧ ASTRAL -- ${player.astralTicks} move${player.astralTicks === 1 ? '' : 's'} out -- body at ${player.bodyRoom?.name ?? '???'}{/magenta-fg}`);
@@ -5776,7 +5776,7 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
5776
5776
  const dockW = mapWidth ?? 15;
5777
5777
  const lines = hosts.length > 0
5778
5778
  ? hosts.map(h => hostDockLine(h, this.player, dockW))
5779
- : ['{cyan-fg}nothing overhead{/cyan-fg}'];
5779
+ : ['{lightblue-fg}nothing overhead{/lightblue-fg}'];
5780
5780
  lines.push(caption(this.player.insideHost ? `inside ${this.player.insideHost.name}` : `on the grid from ${gridVicinity(this.player).name}`, mapWidth));
5781
5781
  this.setMapOverlay(lines);
5782
5782
  if (onTheGrid) {
@@ -8,6 +8,7 @@ import { hint } from '../utilities/hints.js';
8
8
  import { Category } from '../types/shared/item-enum.js';
9
9
  import { Logger } from '../utilities/logger.js';
10
10
  import { CALL_ICON, CALL_COLOR } from '../utilities/comm-style.js';
11
+ import { FEED_COLOR } from '../utilities/matrix-style.js';
11
12
  // The Physical limit already lives here (subduing, p.195) -- imported
12
13
  // rather than re-derived so meat combat and the grapple cannot drift
13
14
  // into two different formulas for the same canon number.
@@ -2851,7 +2852,7 @@ export class Player extends AbstractPlayer {
2851
2852
  // as before -- only the human's log line is dropped.
2852
2853
  if (quiet)
2853
2854
  return;
2854
- this.logger.logWithColor(`${actor.name} ${verb} ${details}`, 'cyan');
2855
+ this.logger.logWithColor(`${actor.name} ${verb} ${details}`, FEED_COLOR);
2855
2856
  }
2856
2857
  }
2857
2858
  performAction(verb, details, opts) {
@@ -256,7 +256,7 @@ export function aroBlock(scene, actor, room) {
256
256
  const tags = aroTags(scene, actor, room);
257
257
  if (tags.length === 0)
258
258
  return '';
259
- return `{cyan-fg}AR OVERLAY:{/cyan-fg}\n${tags.map(t => ` {cyan-fg}${t}{/cyan-fg}`).join('\n')}`;
259
+ return `{lightblue-fg}AR OVERLAY:{/lightblue-fg}\n${tags.map(t => ` {lightblue-fg}${t}{/lightblue-fg}`).join('\n')}`;
260
260
  }
261
261
  /** Gear that talks to the grid on its own, lying LOOSE in the room.
262
262
  * Weapons are absent here because a carried one is handled above, as
@@ -475,7 +475,7 @@ export class CombatEncounter {
475
475
  // A persona has no metres to spend: the grid sees no distance.
476
476
  const ground = this.arena.kind === 'room' ? `; ${this.movementLine(p.actor)}` : '';
477
477
  const budgetLine = `Your Action Phase -- Combat Turn ${this.turn}, pass ${this.pass}, Initiative ${p.score}. ${this.budget.describe()}${ground}. "end turn" when you're done.`;
478
- this.logger.log(`\n{cyan-fg}${budgetLine}{/cyan-fg}`, { actor: p.actor.name });
478
+ this.logger.log(`\n{yellow-fg}${budgetLine}{/yellow-fg}`, { actor: p.actor.name });
479
479
  this.scene.updateStatus();
480
480
  this.onHumanPhase?.(p.actor, this);
481
481
  return;
@@ -742,7 +742,7 @@ export class CombatEncounter {
742
742
  return undefined;
743
743
  if (this.phaseActor === player && this.budget) {
744
744
  const ground = this.arena.kind === 'room' ? ` · ${player.movementLeftMeters} m` : '';
745
- return `{cyan-fg}⏱ YOUR PHASE{/cyan-fg} T${this.turn}/P${this.pass} Init ${p.score} · ${this.budget.describe()}${ground} · "end turn"`;
745
+ return `{yellow-fg}⏱ YOUR PHASE{/yellow-fg} T${this.turn}/P${this.pass} Init ${p.score} · ${this.budget.describe()}${ground} · "end turn"`;
746
746
  }
747
747
  const who = this.phaseActor ? `${this.phaseActor.name} acting` : 'resolving';
748
748
  return `⏱ COMBAT T${this.turn}/P${this.pass} Init ${p.score} · ${who}${p.fullDefenseTurn === this.turn ? ' · FULL DEFENSE' : ''}`;
@@ -106,6 +106,6 @@ export function hostDockLine(room, actor, width) {
106
106
  const tag = room.hostCracked ? ' open' : marks > 0 ? ` ${marks}/3` : '';
107
107
  const raw = `${inside ? '▣' : '●'} ${room.name} HR${room.hostRating}${tag}`;
108
108
  const cut = [...raw].slice(0, Math.max(4, width)).join('');
109
- return `{cyan-fg}${cut}{/cyan-fg}`;
109
+ return `{lightblue-fg}${cut}{/lightblue-fg}`;
110
110
  }
111
111
  //# sourceMappingURL=grid-reach.js.map
@@ -440,20 +440,20 @@ export function gridSculpt(actor, room) {
440
440
  const purpose = room.host?.purpose;
441
441
  const sculpt = room.host?.sculpt;
442
442
  return [
443
- `{cyan-fg}INSIDE :: ${hostLabel(room, { capital: true }).toUpperCase()} [HR ${room.hostRating}]${purpose ? ` -- ${purpose}` : ''}{/cyan-fg}`,
444
- `{cyan-fg}${sculpt ?? 'Architecture all the way around -- the outside grid is a wall away and might as well be weather.'}{/cyan-fg}`,
443
+ `{lightblue-fg}INSIDE :: ${hostLabel(room, { capital: true }).toUpperCase()} [HR ${room.hostRating}]${purpose ? ` -- ${purpose}` : ''}{/lightblue-fg}`,
444
+ `{lightblue-fg}${sculpt ?? 'Architecture all the way around -- the outside grid is a wall away and might as well be weather.'}{/lightblue-fg}`,
445
445
  ].join('\n');
446
446
  }
447
447
  // ON THE GRID (SR5 pp.217-218): no street under the persona -- a black
448
448
  // flatland, the body's room named only because that is where the
449
449
  // signal comes from. A host directly overhead gets a line of its own.
450
450
  const body = actor.bodyRoom ?? room;
451
- const header = `{cyan-fg}THE GRID :: jacked in from ${body.name.toUpperCase()}{/cyan-fg}`;
451
+ const header = `{lightblue-fg}THE GRID :: jacked in from ${body.name.toUpperCase()}{/lightblue-fg}`;
452
452
  const grid = actor.currentGrid;
453
- const flat = `{cyan-fg}Black flatland under a black sky -- the icons are the only things out here.${grid ? ` Riding ${grid.name}${grid.userPenalty ? ' (-2 on everything you do, p.233)' : ''}.` : ''}{/cyan-fg}`;
453
+ const flat = `{lightblue-fg}Black flatland under a black sky -- the icons are the only things out here.${grid ? ` Riding ${grid.name}${grid.userPenalty ? ' (-2 on everything you do, p.233)' : ''}.` : ''}{/lightblue-fg}`;
454
454
  if (!room.hasNode)
455
455
  return `${header}\n${flat}`;
456
- return `${header}\n${flat}\n{cyan-fg}${hostLabel(room, { capital: true })} hangs directly overhead, sealed. What it holds is inside it.{/cyan-fg}`;
456
+ return `${header}\n${flat}\n{lightblue-fg}${hostLabel(room, { capital: true })} hangs directly overhead, sealed. What it holds is inside it.{/lightblue-fg}`;
457
457
  }
458
458
  /**
459
459
  * The icons rendered as the standard cyan block, or the thin-grid line.
@@ -482,19 +482,19 @@ export function gridIconBlock(scene, actor, room, rooms) {
482
482
  if (actor.insideHost || !rooms) {
483
483
  const icons = gridIcons(scene, actor, room);
484
484
  if (icons.length === 0) {
485
- return `{cyan-fg}Thin grid out here -- background noise, nothing worth cracking.{/cyan-fg}`;
485
+ return `{lightblue-fg}Thin grid out here -- background noise, nothing worth cracking.{/lightblue-fg}`;
486
486
  }
487
- return `{cyan-fg}ICONS IN REACH:{/cyan-fg}\n${icons.map(i => ` {cyan-fg}${i}{/cyan-fg}`).join('\n')}`;
487
+ return `{lightblue-fg}ICONS IN REACH:{/lightblue-fg}\n${icons.map(i => ` {lightblue-fg}${i}{/lightblue-fg}`).join('\n')}`;
488
488
  }
489
489
  const out = [];
490
490
  const hosts = hostsInReach(rooms, actor);
491
491
  out.push(hosts.length > 0
492
- ? `{cyan-fg}HOSTS OVERHEAD:{/cyan-fg}\n${hosts.map(h => ` {cyan-fg}${hostLine(h, actor)}{/cyan-fg}`).join('\n')}`
493
- : `{cyan-fg}Nothing overhead -- no host stands over this district.{/cyan-fg}`);
492
+ ? `{lightblue-fg}HOSTS OVERHEAD:{/lightblue-fg}\n${hosts.map(h => ` {lightblue-fg}${hostLine(h, actor)}{/lightblue-fg}`).join('\n')}`
493
+ : `{lightblue-fg}Nothing overhead -- no host stands over this district.{/lightblue-fg}`);
494
494
  const near = gridIcons(scene, actor, gridVicinity(actor)).filter(i => !isHostLine(i));
495
495
  out.push(near.length > 0
496
- ? `{cyan-fg}ICONS IN REACH:{/cyan-fg}\n${near.map(i => ` {cyan-fg}${i}{/cyan-fg}`).join('\n')}`
497
- : `{cyan-fg}Nothing near -- background noise around your signal.{/cyan-fg}`);
496
+ ? `{lightblue-fg}ICONS IN REACH:{/lightblue-fg}\n${near.map(i => ` {lightblue-fg}${i}{/lightblue-fg}`).join('\n')}`
497
+ : `{lightblue-fg}Nothing near -- background noise around your signal.{/lightblue-fg}`);
498
498
  // FARTHER OUT, WITHOUT AN ADDRESS (SR5 p.235, p.243): Matrix Perception
499
499
  // never tells you where a device physically sits -- that is Trace Icon,
500
500
  // two marks and an opposed test. So far icons are listed by the noise
@@ -519,9 +519,9 @@ export function gridIconBlock(scene, actor, room, rooms) {
519
519
  byBand.set(noise, list);
520
520
  }
521
521
  const far = [...byBand.entries()].sort((a, b) => a[0] - b[0])
522
- .map(([noise, names]) => ` {cyan-fg}· dim, noise -${noise}: ${names.join(', ')}{/cyan-fg}`);
522
+ .map(([noise, names]) => ` {lightblue-fg}· dim, noise -${noise}: ${names.join(', ')}{/lightblue-fg}`);
523
523
  if (far.length > 0)
524
- out.push(`{cyan-fg}FARTHER OUT -- dimmer with distance:{/cyan-fg}\n${far.join('\n')}`);
524
+ out.push(`{lightblue-fg}FARTHER OUT -- dimmer with distance:{/lightblue-fg}\n${far.join('\n')}`);
525
525
  // A blank line between the distance bands (user, 2026-09-02): three
526
526
  // sections read as three when they do not touch.
527
527
  return out.join('\n\n');
@@ -536,7 +536,7 @@ export function gridIconBlock(scene, actor, room, rooms) {
536
536
  * the other personas, and the files. Cut to the dock's rows and columns.
537
537
  */
538
538
  export function hostInteriorPanel(scene, actor, host, rows, cols) {
539
- const cut = (raw) => `{cyan-fg}${[...raw].slice(0, Math.max(4, cols)).join('')}{/cyan-fg}`;
539
+ const cut = (raw) => `{lightblue-fg}${[...raw].slice(0, Math.max(4, cols)).join('')}{/lightblue-fg}`;
540
540
  const lines = [];
541
541
  lines.push(cut(`INSIDE ${host.name}`));
542
542
  if (host.purpose)
@@ -0,0 +1,8 @@
1
+ export const MATRIX_COLOR = 'lightblue';
2
+ export const FEED_COLOR = 'white';
3
+ export const TURN_COLOR = 'yellow';
4
+ /** Matrix-plane prose, tagged. */
5
+ export function mx(text) {
6
+ return `{${MATRIX_COLOR}-fg}${text}{/${MATRIX_COLOR}-fg}`;
7
+ }
8
+ //# sourceMappingURL=matrix-style.js.map
@@ -58,10 +58,10 @@ export function accrueOverwatch(scene, actor, defenseHits, why) {
58
58
  // The grid's built-in warning system (p.221): subtle ripples, once
59
59
  // per band -- the only free hint the player ever gets.
60
60
  if (before < 30 && actor.overwatchScore >= 30) {
61
- return { lines: [`{cyan-fg}The grid RIPPLES -- hard, close, and looking. Something vast has nearly found the thread you're hanging by. ("reboot" is a clean slate.){/cyan-fg}`], converged: false };
61
+ return { lines: [`{lightblue-fg}The grid RIPPLES -- hard, close, and looking. Something vast has nearly found the thread you're hanging by. ("reboot" is a clean slate.){/lightblue-fg}`], converged: false };
62
62
  }
63
63
  if (before < 20 && actor.overwatchScore >= 20) {
64
- return { lines: [`{cyan-fg}A ripple crosses the grid -- subtle, wrong, deliberate. Somewhere above, an eye has started counting your fingerprints.{/cyan-fg}`], converged: false };
64
+ return { lines: [`{lightblue-fg}A ripple crosses the grid -- subtle, wrong, deliberate. Somewhere above, an eye has started counting your fingerprints.{/lightblue-fg}`], converged: false };
65
65
  }
66
66
  return { lines: [], converged: false };
67
67
  }
@@ -107,7 +107,7 @@ export function enterMatrix(scene, actor, mode) {
107
107
  // half-done, which would be a fresh canon violation wearing a
108
108
  // feature's clothes. See the PR for CgJ6uTfEvTd8JXdDN.
109
109
  actor.activeDeck = actor.isTechnomancer() ? undefined : actor.getCyberdeck();
110
- actor.performAction('jacks in', `slumping where they stand, eyes flickering (${mode}-sim)`);
110
+ actor.performAction('jacks in', `slumping where they stand, eyes flickering (${mode}-sim)`, { quiet: scene.isHumanControlled?.(actor) ?? false });
111
111
  scene.addWorldEvent(`${actor.name} jacked into the Matrix in ${actor.bodyRoom.name}.`);
112
112
  Logger.getInstance().write(`${actor.name} entered the Matrix (${mode}-sim, ${actor.activeDeck?.name ?? (actor.isTechnomancer() ? 'living persona' : 'no deck?!')}) from ${actor.bodyRoom.name}.`);
113
113
  const hotWarning = mode === 'hot'
@@ -267,7 +267,7 @@ export function leaveMatrix(scene, actor, opts) {
267
267
  actor.bodyRoom = undefined;
268
268
  lines.push(`You're back in your body in ${body.name}.`);
269
269
  }
270
- actor.performAction('jacks out', 'stirring awake');
270
+ actor.performAction('jacks out', 'stirring awake', { quiet: scene.isHumanControlled?.(actor) ?? false });
271
271
  scene.addWorldEvent(`${actor.name} jacked out of the Matrix.`);
272
272
  scene.updateStatus();
273
273
  return lines;
@@ -449,7 +449,7 @@ export function fileReach(actor, room) {
449
449
  */
450
450
  export function planeTintItemName(item, viewerPlane) {
451
451
  if (item.plane === 'matrix') {
452
- return `{cyan-fg}${item.name} [data]{/cyan-fg}`;
452
+ return `{lightblue-fg}${item.name} [data]{/lightblue-fg}`;
453
453
  }
454
454
  if (item.plane === 'astral') {
455
455
  return `{magenta-fg}${item.name} [astral]{/magenta-fg}`;
@@ -24,6 +24,7 @@ import { join, dirname } from 'node:path';
24
24
  import { Logger } from './logger.js';
25
25
  import { hint } from './hints.js';
26
26
  import { CALL_ICON, CALL_COLOR, END_CALL_SENTINEL } from './comm-style.js';
27
+ import { FEED_COLOR } from './matrix-style.js';
27
28
  import { ENGINE_VERSION } from '../engine-version.js';
28
29
  import { authToken, fetchSave } from './cloud-saves.js';
29
30
  import { saveSlug, restorePlayer, writeSaveAtomic } from './persistence.js';
@@ -1143,7 +1144,7 @@ export class SharedRunSession {
1143
1144
  break;
1144
1145
  }
1145
1146
  for (const line of ev.text.split('\n'))
1146
- g.logBox?.pushLine(`{cyan-fg}${line}{/cyan-fg}`);
1147
+ g.logBox?.pushLine(`{${FEED_COLOR}-fg}${line}{/${FEED_COLOR}-fg}`);
1147
1148
  Logger.getInstance().transcript(ev.text);
1148
1149
  g.followLog?.();
1149
1150
  if (ev.kind === 'death' && ev.data?.player === g.player.name) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maka/maka-cli",
3
- "version": "5.183.0",
3
+ "version": "5.184.0",
4
4
  "type": "module",
5
5
  "summary": "A command line tool for scaffolding Meteor 3.x applications using either React.",
6
6
  "description": "A command line tool for scaffolding Meteor 3.x applications using React.",