dsh-team 0.2.6 → 0.2.7

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/client.js CHANGED
@@ -171,7 +171,7 @@ window.__ModuleLoader__.load({
171
171
  h: 60
172
172
  };
173
173
  /** The break corner, in the near right of the room. */
174
- const LOUNGE = {
174
+ const LOUNGE$1 = {
175
175
  x: 69,
176
176
  y: 40,
177
177
  w: 29,
@@ -252,16 +252,16 @@ window.__ModuleLoader__.load({
252
252
  function breakAt(index) {
253
253
  const spots = [
254
254
  {
255
- x: LOUNGE.x + 8,
256
- y: LOUNGE.y + 29
255
+ x: LOUNGE$1.x + 8,
256
+ y: LOUNGE$1.y + 29
257
257
  },
258
258
  {
259
- x: LOUNGE.x + 15,
260
- y: LOUNGE.y + 33
259
+ x: LOUNGE$1.x + 15,
260
+ y: LOUNGE$1.y + 33
261
261
  },
262
262
  {
263
- x: LOUNGE.x + 14,
264
- y: LOUNGE.y + 23
263
+ x: LOUNGE$1.x + 14,
264
+ y: LOUNGE$1.y + 23
265
265
  }
266
266
  ];
267
267
  const spot = spots[index % spots.length] ?? spots[0];
@@ -309,32 +309,32 @@ window.__ModuleLoader__.load({
309
309
  (
310
310
  /** The sofa, along the back of the corner. */
311
311
  {
312
- x: LOUNGE.x + 2.3,
313
- y: LOUNGE.y + 1,
312
+ x: LOUNGE$1.x + 2.3,
313
+ y: LOUNGE$1.y + 1,
314
314
  w: 14.5,
315
315
  h: 7
316
316
  }),
317
317
  (
318
318
  /** The low table in front of it. */
319
319
  {
320
- x: LOUNGE.x + 4.9,
321
- y: LOUNGE.y + 11,
320
+ x: LOUNGE$1.x + 4.9,
321
+ y: LOUNGE$1.y + 11,
322
322
  w: 10,
323
323
  h: 4.5
324
324
  }),
325
325
  (
326
326
  /** The plant, in the far corner. */
327
327
  {
328
- x: LOUNGE.x + 21,
329
- y: LOUNGE.y + 2,
328
+ x: LOUNGE$1.x + 21,
329
+ y: LOUNGE$1.y + 2,
330
330
  w: 6,
331
331
  h: 6
332
332
  }),
333
333
  (
334
334
  /** The water cooler, against the right wall. */
335
335
  {
336
- x: LOUNGE.x + 22,
337
- y: LOUNGE.y + 12,
336
+ x: LOUNGE$1.x + 22,
337
+ y: LOUNGE$1.y + 12,
338
338
  w: 6,
339
339
  h: 6.5
340
340
  }),
@@ -542,7 +542,11 @@ window.__ModuleLoader__.load({
542
542
  const grown = inflate(rect, CLEARANCE * .5);
543
543
  return !inside(from, grown) && !inside(to, grown);
544
544
  });
545
- const clear = (a, b) => !blocks.some((rect) => crossesRect(a, b, rect));
545
+ const clear = (a, b) => !blocks.some((rect) => {
546
+ if (crossesRect(a, b, rect)) return true;
547
+ const grown = inflate(rect, CLEARANCE);
548
+ return !inside(a, grown) && !inside(b, grown) && crossesRect(a, b, grown);
549
+ });
546
550
  if (clear(from, to)) return [from, to];
547
551
  const nodes = [
548
552
  from,
@@ -556,13 +560,16 @@ window.__ModuleLoader__.load({
556
560
  best[0] = 0;
557
561
  for (;;) {
558
562
  let at = -1;
559
- for (const [index, cost] of best.entries()) if (!done[index] && cost < (at < 0 ? Infinity : best[at])) at = index;
563
+ for (let index = 0; index < nodes.length; index += 1) {
564
+ const cost = best[index];
565
+ if (!done[index] && cost < (at < 0 ? Infinity : best[at])) at = index;
566
+ }
560
567
  if (at < 0 || at === goal) break;
561
568
  done[at] = true;
562
569
  const here = nodes[at];
563
- for (const [index, node] of nodes.entries()) {
564
- if (done[index] || index === at || !clear(here, node)) continue;
565
- const cost = best[at] + span(here, node);
570
+ for (let index = 0; index < nodes.length; index += 1) {
571
+ if (done[index] || index === at || !clear(here, nodes[index])) continue;
572
+ const cost = best[at] + span(here, nodes[index]);
566
573
  if (cost < best[index]) {
567
574
  best[index] = cost;
568
575
  via[index] = at;
@@ -911,7 +918,6 @@ window.__ModuleLoader__.load({
911
918
  const gait = (0, react.useRef)(0);
912
919
  const facing = (0, react.useRef)("front");
913
920
  const scale = (0, react.useRef)(base);
914
- scale.current = base;
915
921
  const [pose, setPose] = (0, react.useState)({
916
922
  facing: "front",
917
923
  walking: false
@@ -932,21 +938,30 @@ window.__ModuleLoader__.load({
932
938
  place(at.current);
933
939
  }, [place]);
934
940
  (0, react.useEffect)(() => {
941
+ scale.current = base;
935
942
  place(at.current);
936
943
  }, [place, base]);
944
+ /** Stop wherever the member stands, without keeping a walk pose alive. */
945
+ const settle = (0, react.useCallback)(() => {
946
+ facing.current = "front";
947
+ setPose((current) => current.walking ? {
948
+ facing: "front",
949
+ walking: false
950
+ } : current);
951
+ }, []);
937
952
  (0, react.useEffect)(() => {
938
953
  const start = at.current;
939
- if (Math.abs(start.x - target.x) < NEAR && Math.abs(start.y - target.y) < NEAR) return void 0;
954
+ if (Math.abs(start.x - target.x) < NEAR && Math.abs(start.y - target.y) < NEAR) {
955
+ settle();
956
+ return;
957
+ }
940
958
  if (still()) {
941
959
  at.current = {
942
960
  x: target.x,
943
961
  y: target.y
944
962
  };
945
963
  place(at.current);
946
- setPose({
947
- facing: "front",
948
- walking: false
949
- });
964
+ settle();
950
965
  return;
951
966
  }
952
967
  const path = smooth(routeBetween(start, target, obstacles), obstacles);
@@ -957,6 +972,7 @@ window.__ModuleLoader__.load({
957
972
  y: target.y
958
973
  };
959
974
  place(at.current);
975
+ settle();
960
976
  return;
961
977
  }
962
978
  /** Distance along the path at which each corner is reached. */
@@ -966,10 +982,10 @@ window.__ModuleLoader__.load({
966
982
  const began = now();
967
983
  const from = gait.current;
968
984
  let frame = 0;
985
+ let leg = 1;
969
986
  const tick = () => {
970
987
  const through = Math.min(1, (now() - began) / span);
971
988
  const covered = ease(through) * total;
972
- let leg = 1;
973
989
  while (leg < marks.length - 1 && marks[leg] < covered) leg += 1;
974
990
  const back = path[leg - 1];
975
991
  const ahead = path[leg];
@@ -1017,7 +1033,8 @@ window.__ModuleLoader__.load({
1017
1033
  target.x,
1018
1034
  target.y,
1019
1035
  obstacles,
1020
- place
1036
+ place,
1037
+ settle
1021
1038
  ]);
1022
1039
  return {
1023
1040
  ref: hang,
@@ -1062,487 +1079,512 @@ window.__ModuleLoader__.load({
1062
1079
  document.head.appendChild(tag);
1063
1080
  }
1064
1081
  var TeamStage_module_css_default = {
1065
- "pendant": "nesYQG_pendant",
1066
- "propBoxTop": "nesYQG_propBoxTop",
1067
- "team-drift": "nesYQG_team-drift",
1068
- "crewHoodOpening": "nesYQG_crewHoodOpening",
1069
- "chairMesh": "nesYQG_chairMesh",
1082
+ "logTail": "nesYQG_logTail",
1083
+ "sofaPillowWarm": "nesYQG_sofaPillowWarm",
1084
+ "roomPane": "nesYQG_roomPane",
1085
+ "coolerCapTop": "nesYQG_coolerCapTop",
1086
+ "team-bob": "nesYQG_team-bob",
1087
+ "crewShoeStripe": "nesYQG_crewShoeStripe",
1088
+ "crewBrow": "nesYQG_crewBrow",
1089
+ "crewAglet": "nesYQG_crewAglet",
1090
+ "propShade": "nesYQG_propShade",
1091
+ "propFront": "nesYQG_propFront",
1092
+ "floraRim": "nesYQG_floraRim",
1093
+ "neck": "nesYQG_neck",
1094
+ "keyboard": "nesYQG_keyboard",
1095
+ "table": "nesYQG_table",
1096
+ "crewShoe": "nesYQG_crewShoe",
1097
+ "team-drawer-in": "nesYQG_team-drawer-in",
1098
+ "team-person-sit": "nesYQG_team-person-sit",
1099
+ "propHandle": "nesYQG_propHandle",
1100
+ "team-bubble": "nesYQG_team-bubble",
1101
+ "cardFoot": "nesYQG_cardFoot",
1102
+ "tableEdge": "nesYQG_tableEdge",
1103
+ "clockHand": "nesYQG_clockHand",
1104
+ "drawer": "nesYQG_drawer",
1105
+ "treadmillBottle": "nesYQG_treadmillBottle",
1106
+ "doze": "nesYQG_doze",
1107
+ "noteFoot": "nesYQG_noteFoot",
1108
+ "crewSleeve": "nesYQG_crewSleeve",
1109
+ "sofaButton": "nesYQG_sofaButton",
1110
+ "chairPan": "nesYQG_chairPan",
1111
+ "chairPanTop": "nesYQG_chairPanTop",
1112
+ "coolerHandleWarm": "nesYQG_coolerHandleWarm",
1113
+ "cat": "nesYQG_cat",
1114
+ "crewGlasses": "nesYQG_crewGlasses",
1115
+ "floraStem": "nesYQG_floraStem",
1116
+ "floraPot": "nesYQG_floraPot",
1117
+ "propTray": "nesYQG_propTray",
1118
+ "coolerTap": "nesYQG_coolerTap",
1070
1119
  "sail": "nesYQG_sail",
1071
- "crewBuckle": "nesYQG_crewBuckle",
1072
- "noteKey": "nesYQG_noteKey",
1073
- "pendantRose": "nesYQG_pendantRose",
1074
- "coolerNeck": "nesYQG_coolerNeck",
1075
- "team-halo": "nesYQG_team-halo",
1076
- "skirting": "nesYQG_skirting",
1077
- "propPaperLine": "nesYQG_propPaperLine",
1078
1120
  "floraShade": "nesYQG_floraShade",
1079
- "boardTray": "nesYQG_boardTray",
1080
- "coolerFaucet": "nesYQG_coolerFaucet",
1081
- "chairLumbarKnob": "nesYQG_chairLumbarKnob",
1082
- "crewSmile": "nesYQG_crewSmile",
1083
- "crewGlasses": "nesYQG_crewGlasses",
1084
- "crewCrest": "nesYQG_crewCrest",
1121
+ "coolerCabinet": "nesYQG_coolerCabinet",
1122
+ "beam": "nesYQG_beam",
1123
+ "noteAuthor": "nesYQG_noteAuthor",
1124
+ "crewVest": "nesYQG_crewVest",
1125
+ "propPaperGauge": "nesYQG_propPaperGauge",
1126
+ "chairShellEdge": "nesYQG_chairShellEdge",
1127
+ "crewDroplet": "nesYQG_crewDroplet",
1128
+ "crewHairHighlight": "nesYQG_crewHairHighlight",
1129
+ "empty": "nesYQG_empty",
1130
+ "window": "nesYQG_window",
1131
+ "hangerBracket": "nesYQG_hangerBracket",
1132
+ "propBoxTop": "nesYQG_propBoxTop",
1133
+ "propLampLive": "nesYQG_propLampLive",
1134
+ "chairHub": "nesYQG_chairHub",
1135
+ "body": "nesYQG_body",
1136
+ "crewBuckle": "nesYQG_crewBuckle",
1137
+ "coolerDrip": "nesYQG_coolerDrip",
1138
+ "crewClip": "nesYQG_crewClip",
1139
+ "log": "nesYQG_log",
1140
+ "speech": "nesYQG_speech",
1141
+ "team-doze": "nesYQG_team-doze",
1142
+ "crewLine": "nesYQG_crewLine",
1143
+ "chairShell": "nesYQG_chairShell",
1144
+ "sofa": "nesYQG_sofa",
1145
+ "crewEyeGlintSub": "nesYQG_crewEyeGlintSub",
1146
+ "crewOpen": "nesYQG_crewOpen",
1147
+ "crewPackPocket": "nesYQG_crewPackPocket",
1085
1148
  "propInset": "nesYQG_propInset",
1086
- "treadmillStopKey": "nesYQG_treadmillStopKey",
1087
- "team-caret": "nesYQG_team-caret",
1149
+ "whiteboard": "nesYQG_whiteboard",
1150
+ "cooler": "nesYQG_cooler",
1151
+ "reveal": "nesYQG_reveal",
1152
+ "crewMelon": "nesYQG_crewMelon",
1153
+ "crewTrouserCrease": "nesYQG_crewTrouserCrease",
1154
+ "crewBlush": "nesYQG_crewBlush",
1155
+ "deskApron": "nesYQG_deskApron",
1156
+ "sofaSvg": "nesYQG_sofaSvg",
1157
+ "tableCup": "nesYQG_tableCup",
1158
+ "propDrawerHandle": "nesYQG_propDrawerHandle",
1159
+ "treadmillRail": "nesYQG_treadmillRail",
1160
+ "crewScarfPattern": "nesYQG_crewScarfPattern",
1088
1161
  "acBreeze": "nesYQG_acBreeze",
1089
- "catPupil": "nesYQG_catPupil",
1090
- "treadmillBase": "nesYQG_treadmillBase",
1091
1162
  "tableSaucer": "nesYQG_tableSaucer",
1092
- "team-steam": "nesYQG_team-steam",
1093
- "wallLeft": "nesYQG_wallLeft",
1094
- "chairArmrest": "nesYQG_chairArmrest",
1095
- "acLedPower": "nesYQG_acLedPower",
1096
- "crewLimbFront": "nesYQG_crewLimbFront",
1163
+ "crewCrest": "nesYQG_crewCrest",
1164
+ "logHead": "nesYQG_logHead",
1165
+ "propGauge": "nesYQG_propGauge",
1166
+ "floraSaucer": "nesYQG_floraSaucer",
1167
+ "figure": "nesYQG_figure",
1168
+ "crewPocket": "nesYQG_crewPocket",
1169
+ "dock": "nesYQG_dock",
1170
+ "crewSmile": "nesYQG_crewSmile",
1171
+ "papers": "nesYQG_papers",
1172
+ "load": "nesYQG_load",
1173
+ "logKind": "nesYQG_logKind",
1174
+ "team-tick": "nesYQG_team-tick",
1097
1175
  "lampShadeTop": "nesYQG_lampShadeTop",
1098
- "pendantBulb": "nesYQG_pendantBulb",
1099
- "clockHand": "nesYQG_clockHand",
1100
- "propWarmerPlate": "nesYQG_propWarmerPlate",
1176
+ "lampBulb": "nesYQG_lampBulb",
1177
+ "chairLift": "nesYQG_chairLift",
1178
+ "calendarHead": "nesYQG_calendarHead",
1179
+ "propScreen": "nesYQG_propScreen",
1180
+ "drawerClose": "nesYQG_drawerClose",
1181
+ "books": "nesYQG_books",
1182
+ "logTo": "nesYQG_logTo",
1183
+ "coolerLedCold": "nesYQG_coolerLedCold",
1184
+ "crewLimbBack": "nesYQG_crewLimbBack",
1185
+ "logText": "nesYQG_logText",
1186
+ "crewHoodFabric": "nesYQG_crewHoodFabric",
1187
+ "deskFlank": "nesYQG_deskFlank",
1101
1188
  "barTitle": "nesYQG_barTitle",
1102
- "cameoCrew": "nesYQG_cameoCrew",
1103
- "crewVest": "nesYQG_crewVest",
1104
- "crewBlowhole": "nesYQG_crewBlowhole",
1105
- "crewTrouserCrease": "nesYQG_crewTrouserCrease",
1106
- "crewKnitLine": "nesYQG_crewKnitLine",
1107
- "sofaArmTop": "nesYQG_sofaArmTop",
1189
+ "sofaPillowCool": "nesYQG_sofaPillowCool",
1190
+ "chair": "nesYQG_chair",
1191
+ "utilityCabinet": "nesYQG_utilityCabinet",
1192
+ "barIcon": "nesYQG_barIcon",
1193
+ "team-screen": "nesYQG_team-screen",
1194
+ "shelf": "nesYQG_shelf",
1195
+ "crewHood": "nesYQG_crewHood",
1196
+ "state": "nesYQG_state",
1197
+ "catTail": "nesYQG_catTail",
1198
+ "crewRib": "nesYQG_crewRib",
1199
+ "sofaLeg": "nesYQG_sofaLeg",
1200
+ "team-steam": "nesYQG_team-steam",
1201
+ "crewScarf": "nesYQG_crewScarf",
1202
+ "columns": "nesYQG_columns",
1203
+ "coolerCap": "nesYQG_coolerCap",
1204
+ "base": "nesYQG_base",
1205
+ "crewFacialGroup": "nesYQG_crewFacialGroup",
1206
+ "deskGrain": "nesYQG_deskGrain",
1207
+ "hanger": "nesYQG_hanger",
1208
+ "propBox": "nesYQG_propBox",
1209
+ "coolerShineRim": "nesYQG_coolerShineRim",
1210
+ "propSteam": "nesYQG_propSteam",
1211
+ "crewHoodRidge": "nesYQG_crewHoodRidge",
1212
+ "coolerCabinetEdge": "nesYQG_coolerCabinetEdge",
1213
+ "utilityPrinter": "nesYQG_utilityPrinter",
1214
+ "plant": "nesYQG_plant",
1215
+ "propLabelLine": "nesYQG_propLabelLine",
1216
+ "crewPlacket": "nesYQG_crewPlacket",
1217
+ "catTailTip": "nesYQG_catTailTip",
1218
+ "lampShadeBottom": "nesYQG_lampShadeBottom",
1219
+ "treadmillBase": "nesYQG_treadmillBase",
1220
+ "team-prowl": "nesYQG_team-prowl",
1221
+ "crewKnobHighlight": "nesYQG_crewKnobHighlight",
1222
+ "deskLegs": "nesYQG_deskLegs",
1223
+ "sofaSeatSeam": "nesYQG_sofaSeatSeam",
1224
+ "propTop": "nesYQG_propTop",
1225
+ "team-blink": "nesYQG_team-blink",
1226
+ "crewSpeckle": "nesYQG_crewSpeckle",
1227
+ "drawerHead": "nesYQG_drawerHead",
1228
+ "skirting": "nesYQG_skirting",
1229
+ "feedTitle": "nesYQG_feedTitle",
1108
1230
  "tableMugHandle": "nesYQG_tableMugHandle",
1109
- "treadmillKeyCord": "nesYQG_treadmillKeyCord",
1110
- "card": "nesYQG_card",
1231
+ "ceiling": "nesYQG_ceiling",
1232
+ "crewBadge": "nesYQG_crewBadge",
1233
+ "stage": "nesYQG_stage",
1234
+ "hangerPlant": "nesYQG_hangerPlant",
1235
+ "rug": "nesYQG_rug",
1236
+ "crewPackTrim": "nesYQG_crewPackTrim",
1237
+ "team-drift": "nesYQG_team-drift",
1238
+ "chairRide": "nesYQG_chairRide",
1239
+ "catLeg": "nesYQG_catLeg",
1240
+ "coolerHandleCool": "nesYQG_coolerHandleCool",
1241
+ "lampBeam": "nesYQG_lampBeam",
1242
+ "crewBelly": "nesYQG_crewBelly",
1243
+ "propSvg": "nesYQG_propSvg",
1244
+ "crewCord": "nesYQG_crewCord",
1245
+ "crewPatch": "nesYQG_crewPatch",
1246
+ "team-halo": "nesYQG_team-halo",
1247
+ "coolerGrille": "nesYQG_coolerGrille",
1248
+ "floraCactusDetails": "nesYQG_floraCactusDetails",
1249
+ "crewNeck": "nesYQG_crewNeck",
1250
+ "crewGlassesBridge": "nesYQG_crewGlassesBridge",
1251
+ "coolerDripWell": "nesYQG_coolerDripWell",
1252
+ "pendantFilament": "nesYQG_pendantFilament",
1253
+ "sofaPillowLine": "nesYQG_sofaPillowLine",
1254
+ "sofaSeatPiping": "nesYQG_sofaSeatPiping",
1111
1255
  "acGrille": "nesYQG_acGrille",
1112
- "treadmillMetrics": "nesYQG_treadmillMetrics",
1256
+ "logBody": "nesYQG_logBody",
1257
+ "feed": "nesYQG_feed",
1258
+ "boardNote": "nesYQG_boardNote",
1113
1259
  "clockProp": "nesYQG_clockProp",
1114
- "pendantGlow": "nesYQG_pendantGlow",
1115
- "floraBloomHeart": "nesYQG_floraBloomHeart",
1116
- "logHop": "nesYQG_logHop",
1117
- "crewClip": "nesYQG_crewClip",
1118
- "propLampIdle": "nesYQG_propLampIdle",
1119
- "pendantSvg": "nesYQG_pendantSvg",
1120
- "crewBadgePhoto": "nesYQG_crewBadgePhoto",
1121
- "crewSleeve": "nesYQG_crewSleeve",
1122
- "floraSoil": "nesYQG_floraSoil",
1123
- "chairPan": "nesYQG_chairPan",
1124
- "wallRight": "nesYQG_wallRight",
1125
- "sill": "nesYQG_sill",
1126
- "shell": "nesYQG_shell",
1127
- "team-blink": "nesYQG_team-blink",
1128
- "floraSaucer": "nesYQG_floraSaucer",
1129
- "chairSpine": "nesYQG_chairSpine",
1260
+ "wall": "nesYQG_wall",
1261
+ "crewShoeSole": "nesYQG_crewShoeSole",
1130
1262
  "monitor": "nesYQG_monitor",
1131
- "coolerPanel": "nesYQG_coolerPanel",
1132
- "crewCollar": "nesYQG_crewCollar",
1133
- "lamp": "nesYQG_lamp",
1134
- "sofaArm": "nesYQG_sofaArm",
1135
- "tableMagazine": "nesYQG_tableMagazine",
1136
- "dockButton": "nesYQG_dockButton",
1137
- "crewHoodFabric": "nesYQG_crewHoodFabric",
1138
- "propShade": "nesYQG_propShade",
1139
- "pendantFlex": "nesYQG_pendantFlex",
1140
- "treadmillPost": "nesYQG_treadmillPost",
1141
- "tableGrain": "nesYQG_tableGrain",
1263
+ "crewState": "nesYQG_crewState",
1264
+ "composerAway": "nesYQG_composerAway",
1142
1265
  "propScannerHandle": "nesYQG_propScannerHandle",
1143
- "crewList": "nesYQG_crewList",
1144
- "chairHub": "nesYQG_chairHub",
1145
- "wall": "nesYQG_wall",
1146
- "mullion": "nesYQG_mullion",
1147
- "team-sway": "nesYQG_team-sway",
1148
- "crewPackTrim": "nesYQG_crewPackTrim",
1149
- "crewPackZip": "nesYQG_crewPackZip",
1150
- "propHandle": "nesYQG_propHandle",
1151
- "utilityCabinet": "nesYQG_utilityCabinet",
1152
- "crewTrouser": "nesYQG_crewTrouser",
1153
- "pendantShade": "nesYQG_pendantShade",
1154
- "table": "nesYQG_table",
1155
- "deskFlank": "nesYQG_deskFlank",
1156
- "catSvg": "nesYQG_catSvg",
1157
- "team-stage-in": "nesYQG_team-stage-in",
1158
- "floor": "nesYQG_floor",
1159
- "acLedCool": "nesYQG_acLedCool",
1266
+ "crewNeckBand": "nesYQG_crewNeckBand",
1267
+ "notes": "nesYQG_notes",
1268
+ "chairSpine": "nesYQG_chairSpine",
1269
+ "crewShoeBuckle": "nesYQG_crewShoeBuckle",
1270
+ "crewLimbFront": "nesYQG_crewLimbFront",
1271
+ "coolerPanel": "nesYQG_coolerPanel",
1272
+ "crewShoeEyelet": "nesYQG_crewShoeEyelet",
1273
+ "crewArmFront": "nesYQG_crewArmFront",
1160
1274
  "floraVein": "nesYQG_floraVein",
1161
- "crewFlipperTrim": "nesYQG_crewFlipperTrim",
1162
- "propScreenGlint": "nesYQG_propScreenGlint",
1163
- "crewPlacket": "nesYQG_crewPlacket",
1275
+ "deskPlant": "nesYQG_deskPlant",
1276
+ "lampStem": "nesYQG_lampStem",
1277
+ "acSeam": "nesYQG_acSeam",
1278
+ "team-listen": "nesYQG_team-listen",
1279
+ "propSpout": "nesYQG_propSpout",
1280
+ "floraSaucerLip": "nesYQG_floraSaucerLip",
1281
+ "emptyHint": "nesYQG_emptyHint",
1164
1282
  "columnCount": "nesYQG_columnCount",
1165
- "chairMeshSpine": "nesYQG_chairMeshSpine",
1166
- "load": "nesYQG_load",
1167
- "crewBadgeLine": "nesYQG_crewBadgeLine",
1168
- "catEye": "nesYQG_catEye",
1169
- "crewSeam": "nesYQG_crewSeam",
1170
- "propPortafilter": "nesYQG_propPortafilter",
1171
- "propBean": "nesYQG_propBean",
1172
- "propPaper": "nesYQG_propPaper",
1173
- "team-person-in": "nesYQG_team-person-in",
1174
- "crewBelt": "nesYQG_crewBelt",
1175
- "figure": "nesYQG_figure",
1176
- "noteAuthor": "nesYQG_noteAuthor",
1177
- "crewScrunchie": "nesYQG_crewScrunchie",
1178
- "propSide": "nesYQG_propSide",
1283
+ "treadmillBelt": "nesYQG_treadmillBelt",
1284
+ "crewWrinkle": "nesYQG_crewWrinkle",
1285
+ "catEarInner": "nesYQG_catEarInner",
1286
+ "propCup": "nesYQG_propCup",
1179
1287
  "screenText": "nesYQG_screenText",
1180
- "shelf": "nesYQG_shelf",
1181
- "crewShoeStripe": "nesYQG_crewShoeStripe",
1182
- "crewScarfFringe": "nesYQG_crewScarfFringe",
1183
- "feed": "nesYQG_feed",
1184
- "crewLine": "nesYQG_crewLine",
1185
- "chairPanStitch": "nesYQG_chairPanStitch",
1186
- "crewEye": "nesYQG_crewEye",
1187
- "lampBulb": "nesYQG_lampBulb",
1188
- "floraStem": "nesYQG_floraStem",
1189
- "deskPlant": "nesYQG_deskPlant",
1190
- "chairShellEdge": "nesYQG_chairShellEdge",
1191
- "window": "nesYQG_window",
1192
- "crewKnobHighlight": "nesYQG_crewKnobHighlight",
1193
- "utilityPrinter": "nesYQG_utilityPrinter",
1194
- "crewTuskSpiral": "nesYQG_crewTuskSpiral",
1195
- "cardNote": "nesYQG_cardNote",
1196
- "drawerHead": "nesYQG_drawerHead",
1197
- "boardEraser": "nesYQG_boardEraser",
1198
- "tableMagPage": "nesYQG_tableMagPage",
1199
- "log": "nesYQG_log",
1200
- "floraBloomStamen": "nesYQG_floraBloomStamen",
1201
- "drawerClose": "nesYQG_drawerClose",
1202
- "crewPocket": "nesYQG_crewPocket",
1203
- "propCarafeHandle": "nesYQG_propCarafeHandle",
1204
- "team-bob": "nesYQG_team-bob",
1205
- "scene": "nesYQG_scene",
1206
- "coolerCapTop": "nesYQG_coolerCapTop",
1207
- "columnTitle": "nesYQG_columnTitle",
1288
+ "crewBadgePhoto": "nesYQG_crewBadgePhoto",
1208
1289
  "sea": "nesYQG_sea",
1209
- "listening": "nesYQG_listening",
1210
- "stage": "nesYQG_stage",
1211
- "crewBrow": "nesYQG_crewBrow",
1212
- "crewCuff": "nesYQG_crewCuff",
1213
- "mug": "nesYQG_mug",
1214
- "crewEyeGlint": "nesYQG_crewEyeGlint",
1215
- "cat": "nesYQG_cat",
1216
- "team-sail": "nesYQG_team-sail",
1217
- "tableLeg": "nesYQG_tableLeg",
1218
- "propScreen": "nesYQG_propScreen",
1219
- "sofaBackTop": "nesYQG_sofaBackTop",
1220
- "deskGrain": "nesYQG_deskGrain",
1221
- "screen": "nesYQG_screen",
1222
- "pendantMouth": "nesYQG_pendantMouth",
1223
- "papers": "nesYQG_papers",
1224
- "chairMechanism": "nesYQG_chairMechanism",
1225
- "chair": "nesYQG_chair",
1226
- "crewPackPocket": "nesYQG_crewPackPocket",
1227
- "crewHand": "nesYQG_crewHand",
1228
- "crewHairHighlight": "nesYQG_crewHairHighlight",
1229
- "crewShoeTrim": "nesYQG_crewShoeTrim",
1230
- "sofaSeatSeam": "nesYQG_sofaSeatSeam",
1231
- "propLampLive": "nesYQG_propLampLive",
1232
- "coolerRib": "nesYQG_coolerRib",
1233
- "team-bubble": "nesYQG_team-bubble",
1234
- "crewPleat": "nesYQG_crewPleat",
1235
- "crewEyeGlintSub": "nesYQG_crewEyeGlintSub",
1236
- "tableTop": "nesYQG_tableTop",
1237
- "sillTop": "nesYQG_sillTop",
1238
- "sky": "nesYQG_sky",
1290
+ "floraRimLip": "nesYQG_floraRimLip",
1291
+ "statLive": "nesYQG_statLive",
1292
+ "bookLeaning": "nesYQG_bookLeaning",
1293
+ "logAvatar": "nesYQG_logAvatar",
1239
1294
  "crewStrapBuckle": "nesYQG_crewStrapBuckle",
1240
- "crewShoe": "nesYQG_crewShoe",
1241
- "pane": "nesYQG_pane",
1242
- "crewTusk": "nesYQG_crewTusk",
1243
- "barIcon": "nesYQG_barIcon",
1244
- "crewPenClip": "nesYQG_crewPenClip",
1245
- "chairLumbar": "nesYQG_chairLumbar",
1246
- "plateMeta": "nesYQG_plateMeta",
1247
- "propSeam": "nesYQG_propSeam",
1248
- "catWhisker": "nesYQG_catWhisker",
1249
- "plateName": "nesYQG_plateName",
1250
- "propGauge": "nesYQG_propGauge",
1251
- "calendarGrid": "nesYQG_calendarGrid",
1252
- "propMugHandle": "nesYQG_propMugHandle",
1253
- "deskSurface": "nesYQG_deskSurface",
1254
- "crewHoodRidge": "nesYQG_crewHoodRidge",
1255
- "crewNose": "nesYQG_crewNose",
1256
- "boardPens": "nesYQG_boardPens",
1257
- "shelfPlant": "nesYQG_shelfPlant",
1258
- "team-tick": "nesYQG_team-tick",
1259
- "treadmillHood": "nesYQG_treadmillHood",
1260
- "treadmillScreen": "nesYQG_treadmillScreen",
1261
- "propFolder": "nesYQG_propFolder",
1262
- "cardWho": "nesYQG_cardWho",
1263
- "cameo": "nesYQG_cameo",
1264
- "lampShadeBottom": "nesYQG_lampShadeBottom",
1265
- "team-type": "nesYQG_team-type",
1266
- "treadmillHoodVent": "nesYQG_treadmillHoodVent",
1267
- "crewMouth": "nesYQG_crewMouth",
1268
- "floraCrumb": "nesYQG_floraCrumb",
1269
- "tableEdge": "nesYQG_tableEdge",
1270
- "catBody": "nesYQG_catBody",
1271
- "catNose": "nesYQG_catNose",
1272
- "chairShell": "nesYQG_chairShell",
1273
- "crewHood": "nesYQG_crewHood",
1274
- "crewPackHandle": "nesYQG_crewPackHandle",
1275
- "coolerDripWell": "nesYQG_coolerDripWell",
1276
- "crewFacialGroup": "nesYQG_crewFacialGroup",
1277
- "crewShirt": "nesYQG_crewShirt",
1295
+ "crewCollar": "nesYQG_crewCollar",
1296
+ "crewDraw": "nesYQG_crewDraw",
1297
+ "screen": "nesYQG_screen",
1298
+ "floor": "nesYQG_floor",
1278
1299
  "sofaBack": "nesYQG_sofaBack",
1279
- "base": "nesYQG_base",
1280
- "sofaSeatPiping": "nesYQG_sofaSeatPiping",
1281
- "propBox": "nesYQG_propBox",
1282
- "floraBladeDetail": "nesYQG_floraBladeDetail",
1283
- "treadmillConsole": "nesYQG_treadmillConsole",
1284
- "notes": "nesYQG_notes",
1285
- "utility": "nesYQG_utility",
1286
- "floraBloom": "nesYQG_floraBloom",
1287
- "acLouver": "nesYQG_acLouver",
1288
- "chairSvg": "nesYQG_chairSvg",
1289
- "propGlass": "nesYQG_propGlass",
1290
- "propCup": "nesYQG_propCup",
1291
- "lampShade": "nesYQG_lampShade",
1292
- "stat": "nesYQG_stat",
1293
- "treadmillSensor": "nesYQG_treadmillSensor",
1294
- "team-person-sit": "nesYQG_team-person-sit",
1295
- "propFront": "nesYQG_propFront",
1296
- "crewOpen": "nesYQG_crewOpen",
1297
- "trophy": "nesYQG_trophy",
1298
- "catLeg": "nesYQG_catLeg",
1299
- "bookLeaning": "nesYQG_bookLeaning",
1300
- "emptyHint": "nesYQG_emptyHint",
1301
- "chairCasters": "nesYQG_chairCasters",
1302
- "crewMelonHighlight": "nesYQG_crewMelonHighlight",
1303
- "crewCrossStrap": "nesYQG_crewCrossStrap",
1304
- "crewShoeEyelet": "nesYQG_crewShoeEyelet",
1300
+ "notePreview": "nesYQG_notePreview",
1301
+ "pendantNeck": "nesYQG_pendantNeck",
1302
+ "cloud": "nesYQG_cloud",
1303
+ "lampBase": "nesYQG_lampBase",
1304
+ "propGaugeNeedle": "nesYQG_propGaugeNeedle",
1305
+ "pendantRose": "nesYQG_pendantRose",
1306
+ "crewHair": "nesYQG_crewHair",
1307
+ "tableMagPage": "nesYQG_tableMagPage",
1308
+ "crewSaddle": "nesYQG_crewSaddle",
1309
+ "crewScrunchie": "nesYQG_crewScrunchie",
1310
+ "blankHint": "nesYQG_blankHint",
1311
+ "wallLeft": "nesYQG_wallLeft",
1312
+ "logHop": "nesYQG_logHop",
1313
+ "pendantFlex": "nesYQG_pendantFlex",
1314
+ "tableLeg": "nesYQG_tableLeg",
1315
+ "catNose": "nesYQG_catNose",
1316
+ "crewList": "nesYQG_crewList",
1317
+ "floraBloomHeart": "nesYQG_floraBloomHeart",
1318
+ "wallBack": "nesYQG_wallBack",
1319
+ "tableTop": "nesYQG_tableTop",
1320
+ "propTextLines": "nesYQG_propTextLines",
1321
+ "paneNote": "nesYQG_paneNote",
1322
+ "crewStripes": "nesYQG_crewStripes",
1323
+ "floraMoss": "nesYQG_floraMoss",
1305
1324
  "noteTime": "nesYQG_noteTime",
1306
- "lounge": "nesYQG_lounge",
1307
- "crewAglet": "nesYQG_crewAglet",
1308
- "floraPot": "nesYQG_floraPot",
1309
- "crewBlush": "nesYQG_crewBlush",
1310
- "floraRim": "nesYQG_floraRim",
1311
- "deskApron": "nesYQG_deskApron",
1312
- "crewWrinkle": "nesYQG_crewWrinkle",
1313
- "sofaSvg": "nesYQG_sofaSvg",
1314
- "cardFoot": "nesYQG_cardFoot",
1315
- "team-row-in": "nesYQG_team-row-in",
1316
- "tableCup": "nesYQG_tableCup",
1325
+ "propWarmerPlate": "nesYQG_propWarmerPlate",
1326
+ "team-glow": "nesYQG_team-glow",
1327
+ "floraCrumb": "nesYQG_floraCrumb",
1328
+ "acTemp": "nesYQG_acTemp",
1329
+ "mullion": "nesYQG_mullion",
1330
+ "coolerFaucet": "nesYQG_coolerFaucet",
1331
+ "propPaper": "nesYQG_propPaper",
1332
+ "team-person-in": "nesYQG_team-person-in",
1333
+ "team-sway": "nesYQG_team-sway",
1334
+ "person": "nesYQG_person",
1317
1335
  "crewPupil": "nesYQG_crewPupil",
1318
- "team-say-in": "nesYQG_team-say-in",
1319
- "paneNote": "nesYQG_paneNote",
1320
- "roomPane": "nesYQG_roomPane",
1321
- "beam": "nesYQG_beam",
1336
+ "crewHairShine": "nesYQG_crewHairShine",
1322
1337
  "flora": "nesYQG_flora",
1323
- "crewArmBack": "nesYQG_crewArmBack",
1324
- "sofaSeat": "nesYQG_sofaSeat",
1325
- "logBody": "nesYQG_logBody",
1326
- "crown": "nesYQG_crown",
1327
- "logAvatar": "nesYQG_logAvatar",
1328
- "sofa": "nesYQG_sofa",
1329
- "treadmillBelt": "nesYQG_treadmillBelt",
1330
- "propTop": "nesYQG_propTop",
1331
- "crewNeckBand": "nesYQG_crewNeckBand",
1332
- "column": "nesYQG_column",
1333
- "blankHint": "nesYQG_blankHint",
1334
- "calendarHead": "nesYQG_calendarHead",
1335
- "logText": "nesYQG_logText",
1336
- "treadmillBottle": "nesYQG_treadmillBottle",
1337
- "acEdge": "nesYQG_acEdge",
1338
- "crewGill": "nesYQG_crewGill",
1339
- "crewCansPivot": "nesYQG_crewCansPivot",
1340
- "logArrow": "nesYQG_logArrow",
1341
- "catTail": "nesYQG_catTail",
1342
- "propSteam": "nesYQG_propSteam",
1343
- "tableSvg": "nesYQG_tableSvg",
1344
- "team-screen": "nesYQG_team-screen",
1345
- "treadmillRail": "nesYQG_treadmillRail",
1346
- "sofaPillowWarm": "nesYQG_sofaPillowWarm",
1347
- "coolerLedPower": "nesYQG_coolerLedPower",
1348
- "hangerBracket": "nesYQG_hangerBracket",
1349
- "crewScarf": "nesYQG_crewScarf",
1350
- "coolerLedCold": "nesYQG_coolerLedCold",
1351
- "propSpout": "nesYQG_propSpout",
1352
- "team-glow": "nesYQG_team-glow",
1353
- "floraBlade": "nesYQG_floraBlade",
1354
- "coolerDrip": "nesYQG_coolerDrip",
1355
- "reveal": "nesYQG_reveal",
1356
- "cloud": "nesYQG_cloud",
1357
- "coolerSvg": "nesYQG_coolerSvg",
1358
- "barHint": "nesYQG_barHint",
1359
- "sofaPillowCool": "nesYQG_sofaPillowCool",
1360
- "lampSvg": "nesYQG_lampSvg",
1361
- "crewScarfPattern": "nesYQG_crewScarfPattern",
1362
- "logKind": "nesYQG_logKind",
1363
- "team-drawer-in": "nesYQG_team-drawer-in",
1364
- "clockPin": "nesYQG_clockPin",
1365
- "hanger": "nesYQG_hanger",
1366
- "cooler": "nesYQG_cooler",
1367
- "coolerCap": "nesYQG_coolerCap",
1368
1338
  "treadmill": "nesYQG_treadmill",
1369
- "floorPlane": "nesYQG_floorPlane",
1339
+ "coolerNeck": "nesYQG_coolerNeck",
1340
+ "boardInk": "nesYQG_boardInk",
1341
+ "catPupil": "nesYQG_catPupil",
1342
+ "dockButton": "nesYQG_dockButton",
1343
+ "pendant": "nesYQG_pendant",
1344
+ "sofaSeam": "nesYQG_sofaSeam",
1345
+ "logRow": "nesYQG_logRow",
1346
+ "cameo": "nesYQG_cameo",
1347
+ "stat": "nesYQG_stat",
1348
+ "lampFinial": "nesYQG_lampFinial",
1349
+ "logAuthor": "nesYQG_logAuthor",
1350
+ "crewPackZip": "nesYQG_crewPackZip",
1351
+ "plateName": "nesYQG_plateName",
1352
+ "crewName": "nesYQG_crewName",
1353
+ "catStripe": "nesYQG_catStripe",
1354
+ "treadmillScreen": "nesYQG_treadmillScreen",
1355
+ "shelfPlant": "nesYQG_shelfPlant",
1370
1356
  "glare": "nesYQG_glare",
1371
- "acSeam": "nesYQG_acSeam",
1372
- "crewDraw": "nesYQG_crewDraw",
1373
- "deskModesty": "nesYQG_deskModesty",
1374
- "tableSurface": "nesYQG_tableSurface",
1357
+ "crewTuskGroup": "nesYQG_crewTuskGroup",
1358
+ "crewBelt": "nesYQG_crewBelt",
1359
+ "column": "nesYQG_column",
1360
+ "crewCansCushion": "nesYQG_crewCansCushion",
1361
+ "coolerBubble": "nesYQG_coolerBubble",
1362
+ "blankTitle": "nesYQG_blankTitle",
1363
+ "propLabel": "nesYQG_propLabel",
1364
+ "lampSvg": "nesYQG_lampSvg",
1365
+ "propFolder": "nesYQG_propFolder",
1366
+ "propGlass": "nesYQG_propGlass",
1367
+ "desk": "nesYQG_desk",
1368
+ "chairLumbarKnob": "nesYQG_chairLumbarKnob",
1369
+ "crewTusk": "nesYQG_crewTusk",
1370
+ "crewKnob": "nesYQG_crewKnob",
1371
+ "crewShoeTrim": "nesYQG_crewShoeTrim",
1372
+ "utilityCoffee": "nesYQG_utilityCoffee",
1373
+ "chairCasters": "nesYQG_chairCasters",
1374
+ "airConditioner": "nesYQG_airConditioner",
1375
+ "propMugHandle": "nesYQG_propMugHandle",
1375
1376
  "acBody": "nesYQG_acBody",
1376
- "ceiling": "nesYQG_ceiling",
1377
- "coolerBottle": "nesYQG_coolerBottle",
1378
- "lampBeam": "nesYQG_lampBeam",
1379
- "crewHairShine": "nesYQG_crewHairShine",
1377
+ "calendarGrid": "nesYQG_calendarGrid",
1378
+ "propLampWifi": "nesYQG_propLampWifi",
1379
+ "cameoCrew": "nesYQG_cameoCrew",
1380
+ "crewJacket": "nesYQG_crewJacket",
1381
+ "dockCount": "nesYQG_dockCount",
1382
+ "treadmillHoodVent": "nesYQG_treadmillHoodVent",
1380
1383
  "crewButton": "nesYQG_crewButton",
1381
- "crewGlassesGlass": "nesYQG_crewGlassesGlass",
1382
- "logTail": "nesYQG_logTail",
1383
- "sofaPillowLine": "nesYQG_sofaPillowLine",
1384
- "pendantNeck": "nesYQG_pendantNeck",
1385
- "crewSpout": "nesYQG_crewSpout",
1386
- "composerAway": "nesYQG_composerAway",
1387
- "statLive": "nesYQG_statLive",
1388
- "sofaLeg": "nesYQG_sofaLeg",
1389
- "floraSaucerLip": "nesYQG_floraSaucerLip",
1384
+ "tableGrain": "nesYQG_tableGrain",
1385
+ "treadmillKeyCord": "nesYQG_treadmillKeyCord",
1386
+ "crewGlassesFrame": "nesYQG_crewGlassesFrame",
1387
+ "sofaArm": "nesYQG_sofaArm",
1388
+ "cardTitle": "nesYQG_cardTitle",
1389
+ "pendantMouth": "nesYQG_pendantMouth",
1390
+ "crewKnitLine": "nesYQG_crewKnitLine",
1391
+ "sofaBackTop": "nesYQG_sofaBackTop",
1392
+ "coolerWater": "nesYQG_coolerWater",
1393
+ "floraBloom": "nesYQG_floraBloom",
1394
+ "team-sail": "nesYQG_team-sail",
1395
+ "floraBlade": "nesYQG_floraBlade",
1396
+ "crewTuskSpiral": "nesYQG_crewTuskSpiral",
1397
+ "crewStitch": "nesYQG_crewStitch",
1398
+ "crewGill": "nesYQG_crewGill",
1399
+ "treadmillHood": "nesYQG_treadmillHood",
1400
+ "cardWho": "nesYQG_cardWho",
1390
1401
  "floraLeaf": "nesYQG_floraLeaf",
1391
- "screenApp": "nesYQG_screenApp",
1392
- "crewHair": "nesYQG_crewHair",
1393
- "logAuthor": "nesYQG_logAuthor",
1394
- "propSvg": "nesYQG_propSvg",
1402
+ "lounge": "nesYQG_lounge",
1403
+ "pendantShade": "nesYQG_pendantShade",
1404
+ "crewFlipperTrim": "nesYQG_crewFlipperTrim",
1405
+ "deskModesty": "nesYQG_deskModesty",
1406
+ "chairSvg": "nesYQG_chairSvg",
1407
+ "tableSurface": "nesYQG_tableSurface",
1408
+ "crewStrap": "nesYQG_crewStrap",
1409
+ "crewScarfFringe": "nesYQG_crewScarfFringe",
1410
+ "boardGhost": "nesYQG_boardGhost",
1411
+ "propSide": "nesYQG_propSide",
1412
+ "logTime": "nesYQG_logTime",
1413
+ "card": "nesYQG_card",
1414
+ "deskSurface": "nesYQG_deskSurface",
1415
+ "crewPackHandle": "nesYQG_crewPackHandle",
1416
+ "plankTop": "nesYQG_plankTop",
1417
+ "shell": "nesYQG_shell",
1418
+ "team-breeze": "nesYQG_team-breeze",
1419
+ "propSeam": "nesYQG_propSeam",
1420
+ "floraBladeLit": "nesYQG_floraBladeLit",
1395
1421
  "plank": "nesYQG_plank",
1396
- "blankTitle": "nesYQG_blankTitle",
1422
+ "crewMelonHighlight": "nesYQG_crewMelonHighlight",
1423
+ "plateMeta": "nesYQG_plateMeta",
1424
+ "crewPenClip": "nesYQG_crewPenClip",
1425
+ "sofaArmTop": "nesYQG_sofaArmTop",
1426
+ "coolerRib": "nesYQG_coolerRib",
1427
+ "pendantBulb": "nesYQG_pendantBulb",
1428
+ "treadmillConsole": "nesYQG_treadmillConsole",
1429
+ "crewPocketStitch": "nesYQG_crewPocketStitch",
1430
+ "crewCrossStrap": "nesYQG_crewCrossStrap",
1431
+ "propScreenGlint": "nesYQG_propScreenGlint",
1432
+ "crewShirt": "nesYQG_crewShirt",
1433
+ "team-swing": "nesYQG_team-swing",
1434
+ "treadmillPost": "nesYQG_treadmillPost",
1435
+ "coolerSvg": "nesYQG_coolerSvg",
1397
1436
  "coolerDoorSeam": "nesYQG_coolerDoorSeam",
1398
- "coolerWater": "nesYQG_coolerWater",
1399
- "chairRide": "nesYQG_chairRide",
1400
- "team-breeze": "nesYQG_team-breeze",
1401
- "crewGlassesFrame": "nesYQG_crewGlassesFrame",
1402
- "crewShoeBadge": "nesYQG_crewShoeBadge",
1403
- "crewSaddle": "nesYQG_crewSaddle",
1404
- "airConditioner": "nesYQG_airConditioner",
1405
- "crewCansBand": "nesYQG_crewCansBand",
1406
- "drawer": "nesYQG_drawer",
1407
- "crewBib": "nesYQG_crewBib",
1408
- "keyboard": "nesYQG_keyboard",
1409
- "propLabelLine": "nesYQG_propLabelLine",
1410
- "logTo": "nesYQG_logTo",
1411
- "propLabel": "nesYQG_propLabel",
1412
- "treadmillHoodSheen": "nesYQG_treadmillHoodSheen",
1413
- "floraMoss": "nesYQG_floraMoss",
1414
- "crewCansCushion": "nesYQG_crewCansCushion",
1415
- "chairMeshLine": "nesYQG_chairMeshLine",
1416
- "coolerGrille": "nesYQG_coolerGrille",
1417
- "floraRimLip": "nesYQG_floraRimLip",
1418
- "propTextLines": "nesYQG_propTextLines",
1419
- "plant": "nesYQG_plant",
1420
- "chairSpokes": "nesYQG_chairSpokes",
1421
- "noteFoot": "nesYQG_noteFoot",
1422
- "notePreview": "nesYQG_notePreview",
1423
- "coolerTap": "nesYQG_coolerTap",
1424
- "crewName": "nesYQG_crewName",
1425
- "crewStrap": "nesYQG_crewStrap",
1426
- "coolerShineRim": "nesYQG_coolerShineRim",
1427
- "crewShoeToe": "nesYQG_crewShoeToe",
1428
- "whiteboard": "nesYQG_whiteboard",
1429
- "coolerCabinet": "nesYQG_coolerCabinet",
1430
- "crewMelon": "nesYQG_crewMelon",
1431
- "crewBadge": "nesYQG_crewBadge",
1432
- "crewArmFront": "nesYQG_crewArmFront",
1433
- "wallBack": "nesYQG_wallBack",
1434
- "barStats": "nesYQG_barStats",
1435
- "propGaugeNeedle": "nesYQG_propGaugeNeedle",
1436
- "plate": "nesYQG_plate",
1437
- "hangerPlant": "nesYQG_hangerPlant",
1438
- "logHead": "nesYQG_logHead",
1439
- "team-chair-rise": "nesYQG_team-chair-rise",
1440
- "crewShoeBuckle": "nesYQG_crewShoeBuckle",
1441
- "team-doze": "nesYQG_team-doze",
1437
+ "crewNose": "nesYQG_crewNose",
1442
1438
  "crewRow": "nesYQG_crewRow",
1443
- "team-swing": "nesYQG_team-swing",
1444
- "catStripe": "nesYQG_catStripe",
1445
- "clockTicks": "nesYQG_clockTicks",
1446
- "treadmillSvg": "nesYQG_treadmillSvg",
1447
- "crewPatch": "nesYQG_crewPatch",
1448
- "crewLimbBack": "nesYQG_crewLimbBack",
1449
- "doze": "nesYQG_doze",
1450
- "crewJacket": "nesYQG_crewJacket",
1451
- "crewPocketStitch": "nesYQG_crewPocketStitch",
1452
- "crewFace": "nesYQG_crewFace",
1453
- "propBrew": "nesYQG_propBrew",
1454
- "acTemp": "nesYQG_acTemp",
1455
- "desk": "nesYQG_desk",
1456
- "crewCans": "nesYQG_crewCans",
1457
- "crewState": "nesYQG_crewState",
1458
- "crewStripes": "nesYQG_crewStripes",
1459
- "propLampWifi": "nesYQG_propLampWifi",
1460
- "coolerShine": "nesYQG_coolerShine",
1461
- "lampBase": "nesYQG_lampBase",
1462
- "coolerHandleWarm": "nesYQG_coolerHandleWarm",
1463
- "deskLegs": "nesYQG_deskLegs",
1464
- "treadmillTread": "nesYQG_treadmillTread",
1465
- "catTailTip": "nesYQG_catTailTip",
1466
- "propTray": "nesYQG_propTray",
1467
- "utilityCoffee": "nesYQG_utilityCoffee",
1439
+ "crewHoodOpening": "nesYQG_crewHoodOpening",
1440
+ "screenApp": "nesYQG_screenApp",
1468
1441
  "crewHoodShade": "nesYQG_crewHoodShade",
1469
- "pendantFilament": "nesYQG_pendantFilament",
1470
- "chairLift": "nesYQG_chairLift",
1471
- "crewSpeckle": "nesYQG_crewSpeckle",
1442
+ "team-stage-in": "nesYQG_team-stage-in",
1443
+ "crewBadgeLine": "nesYQG_crewBadgeLine",
1444
+ "treadmillTread": "nesYQG_treadmillTread",
1445
+ "team-caret": "nesYQG_team-caret",
1446
+ "sky": "nesYQG_sky",
1447
+ "pendantGlow": "nesYQG_pendantGlow",
1448
+ "team-say-in": "nesYQG_team-say-in",
1449
+ "acLedPower": "nesYQG_acLedPower",
1450
+ "crewBlowhole": "nesYQG_crewBlowhole",
1451
+ "treadmillHoodSheen": "nesYQG_treadmillHoodSheen",
1452
+ "boardTray": "nesYQG_boardTray",
1453
+ "catEye": "nesYQG_catEye",
1454
+ "calendar": "nesYQG_calendar",
1455
+ "crewCans": "nesYQG_crewCans",
1456
+ "crewEye": "nesYQG_crewEye",
1457
+ "acLouver": "nesYQG_acLouver",
1458
+ "crewTrouser": "nesYQG_crewTrouser",
1459
+ "paneTitle": "nesYQG_paneTitle",
1460
+ "propPortafilter": "nesYQG_propPortafilter",
1461
+ "bar": "nesYQG_bar",
1462
+ "treadmillSvg": "nesYQG_treadmillSvg",
1463
+ "deskTop": "nesYQG_deskTop",
1464
+ "drawerBody": "nesYQG_drawerBody",
1465
+ "sillTop": "nesYQG_sillTop",
1466
+ "chairMeshLine": "nesYQG_chairMeshLine",
1467
+ "lamp": "nesYQG_lamp",
1468
+ "crewHand": "nesYQG_crewHand",
1469
+ "trophy": "nesYQG_trophy",
1470
+ "crewSeam": "nesYQG_crewSeam",
1471
+ "logArrow": "nesYQG_logArrow",
1472
+ "coolerShine": "nesYQG_coolerShine",
1473
+ "propLampIdle": "nesYQG_propLampIdle",
1474
+ "chairMechanism": "nesYQG_chairMechanism",
1475
+ "treadmillStopKey": "nesYQG_treadmillStopKey",
1476
+ "crewHoodSheen": "nesYQG_crewHoodSheen",
1477
+ "sofaSeat": "nesYQG_sofaSeat",
1478
+ "catWhisker": "nesYQG_catWhisker",
1479
+ "crewMouth": "nesYQG_crewMouth",
1480
+ "crewCansPivot": "nesYQG_crewCansPivot",
1481
+ "pendantSvg": "nesYQG_pendantSvg",
1472
1482
  "note": "nesYQG_note",
1473
- "propPaperGauge": "nesYQG_propPaperGauge",
1474
- "floraBloomOuter": "nesYQG_floraBloomOuter",
1475
- "crewPack": "nesYQG_crewPack",
1476
- "crewTuskGroup": "nesYQG_crewTuskGroup",
1477
1483
  "team-chair-stretch": "nesYQG_team-chair-stretch",
1478
- "empty": "nesYQG_empty",
1479
- "propDrawerHandle": "nesYQG_propDrawerHandle",
1480
- "deskTop": "nesYQG_deskTop",
1484
+ "lampShade": "nesYQG_lampShade",
1485
+ "crewSpout": "nesYQG_crewSpout",
1486
+ "crewShoeBadge": "nesYQG_crewShoeBadge",
1487
+ "propBean": "nesYQG_propBean",
1488
+ "boardPens": "nesYQG_boardPens",
1489
+ "barHint": "nesYQG_barHint",
1490
+ "sill": "nesYQG_sill",
1491
+ "crewEyeGlint": "nesYQG_crewEyeGlint",
1492
+ "treadmillArm": "nesYQG_treadmillArm",
1493
+ "crewEar": "nesYQG_crewEar",
1494
+ "team-chair-rise": "nesYQG_team-chair-rise",
1495
+ "floraBloomStamen": "nesYQG_floraBloomStamen",
1496
+ "catBody": "nesYQG_catBody",
1497
+ "crewShoeToe": "nesYQG_crewShoeToe",
1498
+ "listening": "nesYQG_listening",
1499
+ "catSvg": "nesYQG_catSvg",
1500
+ "cameoDot": "nesYQG_cameoDot",
1501
+ "catGlint": "nesYQG_catGlint",
1502
+ "boardEraser": "nesYQG_boardEraser",
1503
+ "floraSoil": "nesYQG_floraSoil",
1504
+ "coolerPanelDepth": "nesYQG_coolerPanelDepth",
1505
+ "chairPanStitch": "nesYQG_chairPanStitch",
1506
+ "plate": "nesYQG_plate",
1507
+ "columnTitle": "nesYQG_columnTitle",
1508
+ "tableMagazine": "nesYQG_tableMagazine",
1509
+ "chairMesh": "nesYQG_chairMesh",
1510
+ "chairSpokes": "nesYQG_chairSpokes",
1511
+ "crown": "nesYQG_crown",
1512
+ "floraBladeDetail": "nesYQG_floraBladeDetail",
1513
+ "cardNote": "nesYQG_cardNote",
1514
+ "propBoxHole": "nesYQG_propBoxHole",
1515
+ "acEdge": "nesYQG_acEdge",
1516
+ "floraBloomOuter": "nesYQG_floraBloomOuter",
1517
+ "noteKey": "nesYQG_noteKey",
1518
+ "wallRight": "nesYQG_wallRight",
1519
+ "propPaperLine": "nesYQG_propPaperLine",
1520
+ "utility": "nesYQG_utility",
1521
+ "coolerBottle": "nesYQG_coolerBottle",
1481
1522
  "discGlyph": "nesYQG_discGlyph",
1482
- "plankTop": "nesYQG_plankTop",
1483
- "cardTitle": "nesYQG_cardTitle",
1484
- "catEar": "nesYQG_catEar",
1485
- "calendar": "nesYQG_calendar",
1486
- "acSvg": "nesYQG_acSvg",
1523
+ "clockTicks": "nesYQG_clockTicks",
1524
+ "floorPlane": "nesYQG_floorPlane",
1487
1525
  "floraPotShade": "nesYQG_floraPotShade",
1488
- "propFolderTab": "nesYQG_propFolderTab",
1489
1526
  "boardTrayTop": "nesYQG_boardTrayTop",
1490
- "propBoxHole": "nesYQG_propBoxHole",
1491
- "team-prowl": "nesYQG_team-prowl",
1492
- "columns": "nesYQG_columns",
1493
- "dockCount": "nesYQG_dockCount",
1494
- "coolerPanelDepth": "nesYQG_coolerPanelDepth",
1495
- "floraCactusDetails": "nesYQG_floraCactusDetails",
1496
- "feedTitle": "nesYQG_feedTitle",
1527
+ "propBrew": "nesYQG_propBrew",
1497
1528
  "crew": "nesYQG_crew",
1498
- "crewBelly": "nesYQG_crewBelly",
1499
- "logTime": "nesYQG_logTime",
1500
- "lampStem": "nesYQG_lampStem",
1501
- "sofaButton": "nesYQG_sofaButton",
1502
- "catGlint": "nesYQG_catGlint",
1503
- "team-listen": "nesYQG_team-listen",
1504
- "logRow": "nesYQG_logRow",
1505
- "crewDroplet": "nesYQG_crewDroplet",
1506
- "drawerBody": "nesYQG_drawerBody",
1507
- "floraSpine": "nesYQG_floraSpine",
1508
- "treadmillArm": "nesYQG_treadmillArm",
1509
- "state": "nesYQG_state",
1510
- "plankBracket": "nesYQG_plankBracket",
1511
- "person": "nesYQG_person",
1512
- "floraBladeLit": "nesYQG_floraBladeLit",
1513
- "body": "nesYQG_body",
1514
- "crewEar": "nesYQG_crewEar",
1515
- "crewCord": "nesYQG_crewCord",
1516
- "lampFinial": "nesYQG_lampFinial",
1517
- "bar": "nesYQG_bar",
1518
- "boardGhost": "nesYQG_boardGhost",
1519
- "boardNote": "nesYQG_boardNote",
1520
- "dock": "nesYQG_dock",
1521
- "coolerBubble": "nesYQG_coolerBubble",
1522
- "coolerHandleCool": "nesYQG_coolerHandleCool",
1523
- "crewNeck": "nesYQG_crewNeck",
1524
- "crewKnob": "nesYQG_crewKnob",
1525
- "boardInk": "nesYQG_boardInk",
1526
- "books": "nesYQG_books",
1527
- "crewHoodSheen": "nesYQG_crewHoodSheen",
1528
- "catEarInner": "nesYQG_catEarInner",
1529
+ "scene": "nesYQG_scene",
1530
+ "mug": "nesYQG_mug",
1529
1531
  "crewCansCup": "nesYQG_crewCansCup",
1530
- "crewGlassesBridge": "nesYQG_crewGlassesBridge",
1531
- "paneTitle": "nesYQG_paneTitle",
1532
- "rug": "nesYQG_rug",
1533
- "neck": "nesYQG_neck",
1534
- "cameoDot": "nesYQG_cameoDot",
1535
- "speech": "nesYQG_speech",
1536
- "coolerCabinetEdge": "nesYQG_coolerCabinetEdge",
1537
- "chairPanTop": "nesYQG_chairPanTop",
1532
+ "treadmillMetrics": "nesYQG_treadmillMetrics",
1533
+ "crewPleat": "nesYQG_crewPleat",
1534
+ "crewFace": "nesYQG_crewFace",
1535
+ "propCarafeHandle": "nesYQG_propCarafeHandle",
1536
+ "team-type": "nesYQG_team-type",
1537
+ "pane": "nesYQG_pane",
1538
+ "crewArmBack": "nesYQG_crewArmBack",
1539
+ "team-row-in": "nesYQG_team-row-in",
1540
+ "chairArmrest": "nesYQG_chairArmrest",
1541
+ "catEar": "nesYQG_catEar",
1542
+ "chairMeshSpine": "nesYQG_chairMeshSpine",
1543
+ "clockPin": "nesYQG_clockPin",
1544
+ "crewBib": "nesYQG_crewBib",
1545
+ "coolerLedPower": "nesYQG_coolerLedPower",
1546
+ "tableSvg": "nesYQG_tableSvg",
1538
1547
  "floraGlaze": "nesYQG_floraGlaze",
1539
- "crewRib": "nesYQG_crewRib",
1540
- "crewShoeSole": "nesYQG_crewShoeSole",
1541
- "crewStitch": "nesYQG_crewStitch",
1542
- "sofaSeam": "nesYQG_sofaSeam"
1548
+ "propFolderTab": "nesYQG_propFolderTab",
1549
+ "floraSpine": "nesYQG_floraSpine",
1550
+ "acSvg": "nesYQG_acSvg",
1551
+ "chairLumbar": "nesYQG_chairLumbar",
1552
+ "plankBracket": "nesYQG_plankBracket",
1553
+ "acLedCool": "nesYQG_acLedCool",
1554
+ "treadmillSensor": "nesYQG_treadmillSensor",
1555
+ "crewCuff": "nesYQG_crewCuff",
1556
+ "crewPack": "nesYQG_crewPack",
1557
+ "barStats": "nesYQG_barStats",
1558
+ "crewGlassesGlass": "nesYQG_crewGlassesGlass",
1559
+ "crewCansBand": "nesYQG_crewCansBand"
1543
1560
  };
1544
1561
  //#endregion
1545
1562
  //#region src/client/crew.tsx
1563
+ /**
1564
+ * The team's cast: one crew member per seat, and a different sea-creature
1565
+ * hood per seat, so a member is recognizable in the room before its nameplate
1566
+ * is read.
1567
+ *
1568
+ * Every character is a person — shoes, trousers, a shirt, arms at its sides —
1569
+ * wearing a whale or shark as an exquisite plush hood: the hood is drawn in
1570
+ * profile, snout forward and flukes over the back of the head, because a whale
1571
+ * reads as a whale from the side and as a blob from the front. The face looks out
1572
+ * from under its chin with delicate chibi-style catchlights and expressions.
1573
+ * Legs and arms are their own groups so the stylesheet can swing them while the
1574
+ * member walks.
1575
+ *
1576
+ * Under the hood everybody is their own person: a hairstyle, a hair colour, a
1577
+ * skin tone, an outfit, shoes and one piece of gear, all picked by seat index
1578
+ * so a member looks the same on every render and no two neighbours are twins.
1579
+ * Tone and skin ride data attributes rather than inline colours, so the theme
1580
+ * still owns the palette.
1581
+ *
1582
+ * A member at work is drawn from BEHIND: the screen faces the room, so its
1583
+ * owner faces the screen. The back view keeps the same figure and turns the
1584
+ * hood the other way — snout toward the monitor on its left — so the hood is
1585
+ * still read in profile while the human face, which nobody needs while somebody
1586
+ * is typing, is simply not there to draw.
1587
+ */
1546
1588
  /** The sea-creature hoods a seat can wear, in the order seats take them. */
1547
1589
  const MASKS = [
1548
1590
  "blue",
@@ -1846,6 +1888,10 @@ window.__ModuleLoader__.load({
1846
1888
  const HOOD_SHADE = "M13.5 21 C19.5 25 28 25 35 22 C42 19 50 14.5 59.5 11 C52 16 44.5 19 37.5 21.5 C29.5 24.2 20.5 24.8 13.5 21 Z";
1847
1889
  /** A ribbed hem across the bottom of a sweater. */
1848
1890
  const RIB_HEM = "M16 73.5 L48 73.5 L48 80.5 L16 80.5 Z";
1891
+ /** The collar of a buttoned shirt: one soft curve under the hood's chin. */
1892
+ const COLLAR = "M25 48.5 C28 52.8 36 52.8 39 48.5";
1893
+ /** The self-edge neckband of a jersey, folded back on itself. */
1894
+ const NECK_BAND = "M24.5 48 C27.5 51.8 36.5 51.8 39.5 48 C38.5 53.5 25.5 53.5 24.5 48 Z";
1849
1895
  /** A kangaroo pocket across the front of a hoodie with reinforced corner bar-tacks. */
1850
1896
  const POCKET = "M26.5 56.5 C28.5 53 35.5 53 37.5 56.5 L39 63.5 L25 63.5 Z";
1851
1897
  /** The hood fabric lying around the neck of a hoodie. */
@@ -2133,7 +2179,7 @@ window.__ModuleLoader__.load({
2133
2179
  * band runs over the head, and the plush ear cups sit naturally on both ears
2134
2180
  * under the jawline with metal pivots.
2135
2181
  */
2136
- function headGearUnder(kind, back) {
2182
+ function headGearUnder(kind) {
2137
2183
  if (kind !== "headphones") return null;
2138
2184
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("g", {
2139
2185
  className: TeamStage_module_css_default.crewCans,
@@ -2458,7 +2504,7 @@ window.__ModuleLoader__.load({
2458
2504
  className: TeamStage_module_css_default.crewHairShine,
2459
2505
  d: HAIR_SHINE_SECONDARY
2460
2506
  }),
2461
- headGearUnder(gear, back),
2507
+ headGearUnder(gear),
2462
2508
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("g", {
2463
2509
  transform: back ? "translate(64 3) scale(-1 1)" : "translate(0 3)",
2464
2510
  children: [
@@ -2534,7 +2580,7 @@ window.__ModuleLoader__.load({
2534
2580
  children: [
2535
2581
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
2536
2582
  className: TeamStage_module_css_default.crewCollar,
2537
- d: "M25 48.5 C28 52.8 36 52.8 39 48.5"
2583
+ d: COLLAR
2538
2584
  }),
2539
2585
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
2540
2586
  className: TeamStage_module_css_default.crewPlacket,
@@ -2573,7 +2619,7 @@ window.__ModuleLoader__.load({
2573
2619
  children: [
2574
2620
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
2575
2621
  className: TeamStage_module_css_default.crewCollar,
2576
- d: "M25 48.5 C28 52.8 36 52.8 39 48.5"
2622
+ d: COLLAR
2577
2623
  }),
2578
2624
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
2579
2625
  className: TeamStage_module_css_default.crewPlacket,
@@ -2603,7 +2649,7 @@ window.__ModuleLoader__.load({
2603
2649
  className: TeamStage_module_css_default.crewOutfitDetails,
2604
2650
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
2605
2651
  className: TeamStage_module_css_default.crewNeckBand,
2606
- d: "M24.5 48 C27.5 51.8 36.5 51.8 39.5 48 C38.5 53.5 25.5 53.5 24.5 48 Z"
2652
+ d: NECK_BAND
2607
2653
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
2608
2654
  className: TeamStage_module_css_default.crewStitch,
2609
2655
  d: "M17.5 67 H23.5 M40.5 67 H46.5"
@@ -2681,7 +2727,7 @@ window.__ModuleLoader__.load({
2681
2727
  children: [
2682
2728
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
2683
2729
  className: TeamStage_module_css_default.crewCollar,
2684
- d: "M25 48.5 C28 52.8 36 52.8 39 48.5"
2730
+ d: COLLAR
2685
2731
  }),
2686
2732
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
2687
2733
  className: TeamStage_module_css_default.crewVest,
@@ -2722,7 +2768,7 @@ window.__ModuleLoader__.load({
2722
2768
  className: TeamStage_module_css_default.crewOutfitDetails,
2723
2769
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
2724
2770
  className: TeamStage_module_css_default.crewNeckBand,
2725
- d: "M24.5 48 C27.5 51.8 36.5 51.8 39.5 48 C38.5 53.5 25.5 53.5 24.5 48 Z"
2771
+ d: NECK_BAND
2726
2772
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
2727
2773
  className: TeamStage_module_css_default.crewStripes,
2728
2774
  d: STRIPES
@@ -2733,7 +2779,7 @@ window.__ModuleLoader__.load({
2733
2779
  children: [
2734
2780
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
2735
2781
  className: TeamStage_module_css_default.crewNeckBand,
2736
- d: "M24.5 48 C27.5 51.8 36.5 51.8 39.5 48 C38.5 53.5 25.5 53.5 24.5 48 Z"
2782
+ d: NECK_BAND
2737
2783
  }),
2738
2784
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
2739
2785
  className: TeamStage_module_css_default.crewBib,
@@ -2810,12 +2856,13 @@ window.__ModuleLoader__.load({
2810
2856
  }
2811
2857
  }
2812
2858
  /**
2813
- * One member of the crew.
2859
+ * One member of the crew. Memoized: every prop is a primitive, and one stage
2860
+ * renders this figure per seat, per log row, per note and per task card.
2814
2861
  * @param props - the whale it wears, whether you are behind it, whether only
2815
2862
  * the head is wanted (a portrait), and everything it is dressed in.
2816
2863
  * @returns the character.
2817
2864
  */
2818
- function Crew(props) {
2865
+ const Crew = (0, react.memo)(function Crew(props) {
2819
2866
  const { kind, className, back = false, portrait = false, outfit = "shirt", shoes = "sneaker", hair = "crop", gear = "none", tone = 0, skin = 0 } = props;
2820
2867
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
2821
2868
  className: `${TeamStage_module_css_default.crew} ${className ?? ""}`,
@@ -2949,7 +2996,7 @@ window.__ModuleLoader__.load({
2949
2996
  bodyGear(gear, back)
2950
2997
  ] }), head(kind, hair, gear, back)]
2951
2998
  });
2952
- }
2999
+ });
2953
3000
  //#endregion
2954
3001
  //#region src/client/flora.tsx
2955
3002
  /** The plants the room keeps, in the order places take them. */
@@ -4931,6 +4978,12 @@ window.__ModuleLoader__.load({
4931
4978
  const SPEECH_CHARS = 44;
4932
4979
  /** How much of a message one log row carries. */
4933
4980
  const LOG_CHARS = 110;
4981
+ /** How much of a message one crew line in the feed carries. */
4982
+ const CREW_CHARS = 40;
4983
+ /** How much text one workstation screen carries. */
4984
+ const SCREEN_CHARS = 34;
4985
+ /** How much of an unknown session id a ledger shows. */
4986
+ const SHORT_ID = 6;
4934
4987
  /** How long one delivery keeps its carrier away from its own desk. */
4935
4988
  const ERRAND_MS = 9e3;
4936
4989
  /** The board's columns, left to right. */
@@ -5000,8 +5053,9 @@ window.__ModuleLoader__.load({
5000
5053
  children: Array.from({ length: APP_BARS[app] }, (_, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("i", {}, index))
5001
5054
  });
5002
5055
  }
5003
- /** A member as a tiny portrait: its own mask in its own accent. */
5004
- function Cameo(props) {
5056
+ /** A member as a tiny portrait: its own mask in its own accent. Memoized: one
5057
+ * feed renders dozens of these, and every prop is a primitive. */
5058
+ const Cameo = (0, react.memo)(function Cameo(props) {
5005
5059
  const { seat, name } = props;
5006
5060
  if (seat === void 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5007
5061
  className: TeamStage_module_css_default.discGlyph,
@@ -5021,7 +5075,7 @@ window.__ModuleLoader__.load({
5021
5075
  skin: skinOf(seat)
5022
5076
  })
5023
5077
  });
5024
- }
5078
+ });
5025
5079
  /** Where one thing stands on the floor, and how big it draws there. */
5026
5080
  function at(post, scale) {
5027
5081
  const screen = project(post);
@@ -5037,6 +5091,134 @@ window.__ModuleLoader__.load({
5037
5091
  return { "--team-chair-delay": `${-((seat + 1) % 5) * 1.35}s` };
5038
5092
  }
5039
5093
  /**
5094
+ * Where one piece of the break corner stands, and how large it draws there.
5095
+ * A piece is placed by its OWN plan rectangle — the same rectangle a walk
5096
+ * goes around — so the furniture it is drawn as and the furniture it is
5097
+ * walked around as are the same furniture, and it can never creep off the
5098
+ * floor and up a wall.
5099
+ */
5100
+ function loungePiece(rect) {
5101
+ const screen = project({
5102
+ x: rect.x + rect.w / 2,
5103
+ y: rect.y + rect.h / 2
5104
+ });
5105
+ return {
5106
+ left: `${screen.left}%`,
5107
+ top: `${screen.top}%`,
5108
+ "--team-depth": Math.round(rect.y + rect.h / 2),
5109
+ "--team-scale": Math.round(screen.scale * 1e3) / 1e3
5110
+ };
5111
+ }
5112
+ /** The rug and the floor lamp are furniture too, so they get plan rects. */
5113
+ const RUG_RECT = {
5114
+ x: 70.5,
5115
+ y: 53.5,
5116
+ w: 21,
5117
+ h: 7.5
5118
+ };
5119
+ const LAMP_RECT = {
5120
+ x: 70,
5121
+ y: 47.5,
5122
+ w: 3,
5123
+ h: 7
5124
+ };
5125
+ const [SOFA_BLOCK, TABLE_BLOCK, PLANT_BLOCK, COOLER_BLOCK] = ROOM_BLOCKS;
5126
+ /**
5127
+ * The room's fixed furniture, hoisted to module level: none of it reads the
5128
+ * roster or the ledgers, and a shared element reference is the one signal
5129
+ * React never re-renders — however often the stage re-renders around it, the
5130
+ * wall, the lounge and the props are drawn exactly once.
5131
+ */
5132
+ const WALL = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RoomWall, {});
5133
+ const PENDANT = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5134
+ className: TeamStage_module_css_default.pendant,
5135
+ style: { left: `${onWall(50)}%` },
5136
+ "aria-hidden": true,
5137
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PendantFigure, {})
5138
+ });
5139
+ const UTILITY = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5140
+ className: TeamStage_module_css_default.utility,
5141
+ style: at({
5142
+ x: 4.5,
5143
+ y: 64
5144
+ }, 1),
5145
+ "aria-hidden": true,
5146
+ children: [
5147
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5148
+ className: TeamStage_module_css_default.utilityCabinet,
5149
+ "data-prop": "cabinet",
5150
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CabinetFigure, {})
5151
+ }),
5152
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5153
+ className: TeamStage_module_css_default.utilityPrinter,
5154
+ "data-prop": "printer",
5155
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PrinterFigure, {})
5156
+ }),
5157
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5158
+ className: TeamStage_module_css_default.utilityCoffee,
5159
+ "data-prop": "coffee",
5160
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CoffeeFigure, {})
5161
+ })
5162
+ ]
5163
+ });
5164
+ const CAT = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5165
+ className: TeamStage_module_css_default.cat,
5166
+ "data-prop": "cat",
5167
+ "aria-hidden": true,
5168
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CatFigure, {})
5169
+ });
5170
+ const TREADMILL = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5171
+ className: TeamStage_module_css_default.treadmill,
5172
+ "data-prop": "treadmill",
5173
+ style: at({
5174
+ x: 93,
5175
+ y: 87
5176
+ }, 1),
5177
+ "aria-hidden": true,
5178
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TreadmillFigure, {})
5179
+ });
5180
+ const LOUNGE = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5181
+ className: TeamStage_module_css_default.lounge,
5182
+ "aria-hidden": true,
5183
+ children: [
5184
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5185
+ className: TeamStage_module_css_default.rug,
5186
+ "data-prop": "rug",
5187
+ style: loungePiece(RUG_RECT)
5188
+ }),
5189
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5190
+ className: TeamStage_module_css_default.sofa,
5191
+ "data-prop": "sofa",
5192
+ style: loungePiece(SOFA_BLOCK),
5193
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SofaFigure, {})
5194
+ }),
5195
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5196
+ className: TeamStage_module_css_default.table,
5197
+ "data-prop": "table",
5198
+ style: loungePiece(TABLE_BLOCK),
5199
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TableFigure, {})
5200
+ }),
5201
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5202
+ className: TeamStage_module_css_default.lamp,
5203
+ "data-prop": "lamp",
5204
+ style: loungePiece(LAMP_RECT),
5205
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LampFigure, {})
5206
+ }),
5207
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5208
+ className: TeamStage_module_css_default.plant,
5209
+ "data-prop": "plant",
5210
+ style: loungePiece(PLANT_BLOCK),
5211
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Plant, { kind: plantOf(0) })
5212
+ }),
5213
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5214
+ className: TeamStage_module_css_default.cooler,
5215
+ "data-prop": "cooler",
5216
+ style: loungePiece(COOLER_BLOCK),
5217
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CoolerFigure, {})
5218
+ })
5219
+ ]
5220
+ });
5221
+ /**
5040
5222
  * The delivery currently being carried across the room. One message keeps its
5041
5223
  * carrier away from its own desk for a while and then lets it walk back: the
5042
5224
  * room shows what just happened, not the whole history at once.
@@ -5066,15 +5248,16 @@ window.__ModuleLoader__.load({
5066
5248
  function TeamStage(props) {
5067
5249
  const { useTeam, useSessions, openMember, openLeader, holdComposer, t } = props;
5068
5250
  const state = useTeam((snapshot) => snapshot);
5069
- const sessions = useSessions((snapshot) => snapshot);
5251
+ const sessionsById = useSessions((snapshot) => snapshot.byId);
5070
5252
  /** The member the pointer is over, anywhere on the stage. */
5071
5253
  const [focus, setFocus] = (0, react.useState)(void 0);
5072
5254
  /** Which ledger the drawer is showing; the room stands alone by default. */
5073
5255
  const [panel, setPanel] = (0, react.useState)(void 0);
5074
5256
  const { leaderId, currentId, members, tasks, messages, board, boardAt } = state;
5075
5257
  const visit = useVisit(messages[messages.length - 1]);
5258
+ const lastId = messages.length > 0 ? messages[messages.length - 1].messageId : void 0;
5076
5259
  (0, react.useEffect)(() => holdComposer?.(), [holdComposer]);
5077
- const running = (0, react.useMemo)(() => new Set(members.filter((member) => sessions.byId[member.memberId]?.running === true).map((member) => member.memberId)), [members, sessions.byId]);
5260
+ const running = (0, react.useMemo)(() => new Set(members.filter((member) => sessionsById[member.memberId]?.running === true).map((member) => member.memberId)), [members, sessionsById]);
5078
5261
  /** The last thing the visible mailbox tail says about each member. */
5079
5262
  const touched = (0, react.useMemo)(() => {
5080
5263
  const out = /* @__PURE__ */ new Map();
@@ -5084,12 +5267,27 @@ window.__ModuleLoader__.load({
5084
5267
  }
5085
5268
  return out;
5086
5269
  }, [messages]);
5087
- /** Mail counted as read: everything that had arrived when the feed was last open. */
5088
- const seenMessages = (0, react.useRef)(messages.length);
5270
+ /**
5271
+ * Mail counted as read: the newest delivery that had arrived when the feed
5272
+ * was last open — its identity, not the count, because a bounded feed stops
5273
+ * growing exactly when the mail keeps coming, and so does a team switch,
5274
+ * which starts the next team from a clean slate.
5275
+ */
5276
+ const seen = (0, react.useRef)({
5277
+ leader: void 0,
5278
+ id: void 0
5279
+ });
5089
5280
  (0, react.useEffect)(() => {
5090
- if (panel === "feed") seenMessages.current = messages.length;
5091
- }, [panel, messages.length]);
5092
- const freshMail = panel !== "feed" && messages.length > seenMessages.current;
5281
+ if (seen.current.leader !== leaderId || panel === "feed") seen.current = {
5282
+ leader: leaderId,
5283
+ id: lastId
5284
+ };
5285
+ }, [
5286
+ panel,
5287
+ leaderId,
5288
+ lastId
5289
+ ]);
5290
+ const freshMail = panel !== "feed" && seen.current.leader === leaderId && lastId !== void 0 && lastId !== seen.current.id;
5093
5291
  if (leaderId === void 0 || members.length === 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5094
5292
  className: TeamStage_module_css_default.stage,
5095
5293
  "data-agent-team-stage": true,
@@ -5101,72 +5299,84 @@ window.__ModuleLoader__.load({
5101
5299
  children: t("stage.noTeamHint")
5102
5300
  })]
5103
5301
  });
5104
- const names = /* @__PURE__ */ new Map([[leaderId, t("member.leader")]]);
5105
- for (const member of members) names.set(member.memberId, member.name);
5106
- /** Roster seat per member id, so the ledgers can draw the same cast. */
5107
- const seats = /* @__PURE__ */ new Map([[leaderId, -1]]);
5108
- members.forEach((member, index) => seats.set(member.memberId, index));
5109
- const openOf = (memberId) => tasks.filter((task) => task.assigneeId === memberId && task.status !== "done").length;
5110
- const roster = [leaderId, ...members.map((member) => member.memberId)];
5111
- const desks = new Map(roster.map((id, index) => [id, deskOf(index, roster.length)]));
5112
- /** Where each member is standing right now: its own desk, or the break corner. */
5113
- const homes = /* @__PURE__ */ new Map();
5114
- /** Who is away from its own desk, so the desk can be drawn empty. */
5115
- const away = /* @__PURE__ */ new Set();
5116
- const stations = [];
5117
- let breaks = 0;
5118
- for (const id of roster) {
5119
- const desk = desks.get(id) ?? deskOf(0, roster.length);
5120
- const station = id === leaderId ? "desk" : stationFor(running.has(id), touched.get(id), openOf(id));
5121
- if (station === "break") away.add(id);
5122
- stations.push(station === "break" ? breakAt(breaks++) : desk);
5123
- }
5124
- const parted = spread(stations);
5125
- roster.forEach((id, index) => {
5126
- const post = stations[index];
5127
- homes.set(id, {
5128
- ...post,
5129
- ...parted[index]
5130
- });
5131
- });
5132
- /**
5133
- * Where one piece of the break corner stands, and how large it draws there.
5134
- * A piece is placed by its OWN plan rectangle — the same rectangle a walk
5135
- * goes around — so the furniture it is drawn as and the furniture it is
5136
- * walked around as are the same furniture, and it can never creep off the
5137
- * floor and up a wall.
5138
- */
5139
- const loungePiece = (rect) => {
5140
- const screen = project({
5141
- x: rect.x + rect.w / 2,
5142
- y: rect.y + rect.h / 2
5302
+ const { names, seats, openOf, roster, desks, homes, away, lines } = (0, react.useMemo)(() => {
5303
+ const names = /* @__PURE__ */ new Map([[leaderId, t("member.leader")]]);
5304
+ for (const member of members) names.set(member.memberId, member.name);
5305
+ /** Roster seat per member id, so the ledgers can draw the same cast. */
5306
+ const seats = /* @__PURE__ */ new Map([[leaderId, -1]]);
5307
+ members.forEach((member, index) => seats.set(member.memberId, index));
5308
+ const openCounts = /* @__PURE__ */ new Map();
5309
+ for (const task of tasks) {
5310
+ if (task.status === "done" || task.assigneeId === void 0) continue;
5311
+ openCounts.set(task.assigneeId, (openCounts.get(task.assigneeId) ?? 0) + 1);
5312
+ }
5313
+ const openOf = (memberId) => openCounts.get(memberId) ?? 0;
5314
+ const roster = [leaderId, ...members.map((member) => member.memberId)];
5315
+ const desks = new Map(roster.map((id, index) => [id, deskOf(index, roster.length)]));
5316
+ /** Where each member is standing right now: its own desk, or the break corner. */
5317
+ const homes = /* @__PURE__ */ new Map();
5318
+ /** Who is away from its own desk, so the desk can be drawn empty. */
5319
+ const away = /* @__PURE__ */ new Set();
5320
+ const stations = [];
5321
+ let breaks = 0;
5322
+ for (const id of roster) {
5323
+ const desk = desks.get(id) ?? deskOf(0, roster.length);
5324
+ const station = id === leaderId ? "desk" : stationFor(running.has(id), touched.get(id), openOf(id));
5325
+ if (station === "break") away.add(id);
5326
+ stations.push(station === "break" ? breakAt(breaks++) : desk);
5327
+ }
5328
+ const parted = spread(stations);
5329
+ roster.forEach((id, index) => {
5330
+ const post = stations[index];
5331
+ homes.set(id, {
5332
+ ...post,
5333
+ ...parted[index]
5334
+ });
5143
5335
  });
5336
+ /** What one member's monitor shows: its active task, or the last thing said to it. */
5337
+ const lines = /* @__PURE__ */ new Map();
5338
+ for (const id of roster) {
5339
+ const active = tasks.find((task) => task.assigneeId === id && task.status === "active") ?? tasks.find((task) => task.assigneeId === id && task.status !== "done");
5340
+ if (active !== void 0) {
5341
+ lines.set(id, short(active.title, SCREEN_CHARS));
5342
+ continue;
5343
+ }
5344
+ for (let index = messages.length - 1; index >= 0; index -= 1) {
5345
+ const message = messages[index];
5346
+ if (message?.to === id) {
5347
+ lines.set(id, short(message.text, SCREEN_CHARS));
5348
+ break;
5349
+ }
5350
+ }
5351
+ }
5144
5352
  return {
5145
- left: `${screen.left}%`,
5146
- top: `${screen.top}%`,
5147
- "--team-depth": Math.round(rect.y + rect.h / 2),
5148
- "--team-scale": Math.round(screen.scale * 1e3) / 1e3
5353
+ names,
5354
+ seats,
5355
+ openOf,
5356
+ roster,
5357
+ desks,
5358
+ homes,
5359
+ away,
5360
+ lines
5149
5361
  };
5150
- };
5151
- /** The rug and the floor lamp are furniture too, so they get plan rects. */
5152
- const rugRect = {
5153
- x: 70.5,
5154
- y: 53.5,
5155
- w: 21,
5156
- h: 7.5
5157
- };
5158
- const lampRect = {
5159
- x: 70,
5160
- y: 47.5,
5161
- w: 3,
5162
- h: 7
5163
- };
5164
- const [sofaBlock, tableBlock, plantBlock, coolerBlock] = ROOM_BLOCKS;
5362
+ }, [
5363
+ leaderId,
5364
+ members,
5365
+ tasks,
5366
+ messages,
5367
+ running,
5368
+ touched,
5369
+ t
5370
+ ]);
5165
5371
  const peers = members.filter((member) => member.relation === "peer");
5166
5372
  const openTasks = tasks.filter((task) => task.status !== "done").length;
5167
- const leaderRunning = sessions.byId[leaderId]?.running === true;
5373
+ const leaderRunning = sessionsById[leaderId]?.running === true;
5168
5374
  /** The delivery on its feet: who carries it, to whom, and where they meet. */
5169
- const errand = errandOf(visit, leaderId, homes);
5375
+ const errand = (0, react.useMemo)(() => errandOf(visit, leaderId, homes), [
5376
+ visit,
5377
+ leaderId,
5378
+ homes
5379
+ ]);
5170
5380
  const visitOf = (id) => errand !== void 0 && errand.fromId === id ? errand.meet : void 0;
5171
5381
  /** Which way the two ends of a delivery turn while they talk. */
5172
5382
  const turnOf = (id) => {
@@ -5178,6 +5388,15 @@ window.__ModuleLoader__.load({
5178
5388
  setPanel((current) => current === id ? void 0 : id);
5179
5389
  };
5180
5390
  const titleOf = (id) => id === "feed" ? t("stage.feed") : id === "workspace" ? t("stage.workspace") : t("stage.board");
5391
+ /** One stable opener for every tile: the tiles are memoized on their props. */
5392
+ const open = (0, react.useCallback)((id) => {
5393
+ if (id === leaderId) openLeader(leaderId);
5394
+ else openMember(leaderId, id);
5395
+ }, [
5396
+ leaderId,
5397
+ openLeader,
5398
+ openMember
5399
+ ]);
5181
5400
  const tileOf = (id, seat, member) => {
5182
5401
  const desk = desks.get(id) ?? deskOf(0, roster.length);
5183
5402
  const home = homes.get(id) ?? desk;
@@ -5204,10 +5423,7 @@ window.__ModuleLoader__.load({
5204
5423
  tasks: openOf(id),
5205
5424
  label: member === void 0 ? t("member.openLeader") : t("member.open", { name }),
5206
5425
  title: member === void 0 ? t("member.leader") : meta(member.name, member.role, member.model, member.effort, member.relation === "peer" ? t("relation.peer") : t("relation.managed")),
5207
- onOpen: () => {
5208
- if (member === void 0) openLeader(leaderId);
5209
- else openMember(leaderId, id);
5210
- },
5426
+ onOpen: open,
5211
5427
  onFocus: setFocus,
5212
5428
  t
5213
5429
  }, id);
@@ -5272,95 +5488,12 @@ window.__ModuleLoader__.load({
5272
5488
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: TeamStage_module_css_default.skirting })
5273
5489
  ]
5274
5490
  }),
5275
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RoomWall, {}),
5276
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5277
- className: TeamStage_module_css_default.pendant,
5278
- style: { left: `${onWall(50)}%` },
5279
- "aria-hidden": true,
5280
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PendantFigure, {})
5281
- }),
5282
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5283
- className: TeamStage_module_css_default.utility,
5284
- style: at({
5285
- x: 4.5,
5286
- y: 64
5287
- }, 1),
5288
- "aria-hidden": true,
5289
- children: [
5290
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5291
- className: TeamStage_module_css_default.utilityCabinet,
5292
- "data-prop": "cabinet",
5293
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CabinetFigure, {})
5294
- }),
5295
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5296
- className: TeamStage_module_css_default.utilityPrinter,
5297
- "data-prop": "printer",
5298
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PrinterFigure, {})
5299
- }),
5300
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5301
- className: TeamStage_module_css_default.utilityCoffee,
5302
- "data-prop": "coffee",
5303
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CoffeeFigure, {})
5304
- })
5305
- ]
5306
- }),
5307
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5308
- className: TeamStage_module_css_default.cat,
5309
- "data-prop": "cat",
5310
- "aria-hidden": true,
5311
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CatFigure, {})
5312
- }),
5313
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5314
- className: TeamStage_module_css_default.treadmill,
5315
- "data-prop": "treadmill",
5316
- style: at({
5317
- x: 93,
5318
- y: 87
5319
- }, 1),
5320
- "aria-hidden": true,
5321
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TreadmillFigure, {})
5322
- }),
5323
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5324
- className: TeamStage_module_css_default.lounge,
5325
- "aria-hidden": true,
5326
- children: [
5327
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5328
- className: TeamStage_module_css_default.rug,
5329
- "data-prop": "rug",
5330
- style: loungePiece(rugRect)
5331
- }),
5332
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5333
- className: TeamStage_module_css_default.sofa,
5334
- "data-prop": "sofa",
5335
- style: loungePiece(sofaBlock),
5336
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SofaFigure, {})
5337
- }),
5338
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5339
- className: TeamStage_module_css_default.table,
5340
- "data-prop": "table",
5341
- style: loungePiece(tableBlock),
5342
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TableFigure, {})
5343
- }),
5344
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5345
- className: TeamStage_module_css_default.lamp,
5346
- "data-prop": "lamp",
5347
- style: loungePiece(lampRect),
5348
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LampFigure, {})
5349
- }),
5350
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5351
- className: TeamStage_module_css_default.plant,
5352
- "data-prop": "plant",
5353
- style: loungePiece(plantBlock),
5354
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Plant, { kind: plantOf(0) })
5355
- }),
5356
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5357
- className: TeamStage_module_css_default.cooler,
5358
- "data-prop": "cooler",
5359
- style: loungePiece(coolerBlock),
5360
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CoolerFigure, {})
5361
- })
5362
- ]
5363
- }),
5491
+ WALL,
5492
+ PENDANT,
5493
+ UTILITY,
5494
+ CAT,
5495
+ TREADMILL,
5496
+ LOUNGE,
5364
5497
  roster.map((id, index) => {
5365
5498
  const seat = index - 1;
5366
5499
  const desk = desks.get(id) ?? deskOf(index, roster.length);
@@ -5370,7 +5503,7 @@ window.__ModuleLoader__.load({
5370
5503
  desk,
5371
5504
  seat,
5372
5505
  pose: poseFor(live, touched.get(id), openOf(id)),
5373
- line: screenLineOf(id, tasks, messages),
5506
+ line: lines.get(id),
5374
5507
  empty: away.has(id) || errand !== void 0 && errand.fromId === id,
5375
5508
  t
5376
5509
  }, `desk-${id}`);
@@ -5471,10 +5604,8 @@ window.__ModuleLoader__.load({
5471
5604
  entry,
5472
5605
  index,
5473
5606
  seats,
5474
- focus,
5475
- onFocus: (onFocus) => {
5476
- setFocus(onFocus);
5477
- }
5607
+ focused: focus === entry.authorId,
5608
+ onFocus: setFocus
5478
5609
  }, entry.key))
5479
5610
  })),
5480
5611
  panel === "tasks" && (tasks.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
@@ -5539,18 +5670,6 @@ window.__ModuleLoader__.load({
5539
5670
  };
5540
5671
  }
5541
5672
  /**
5542
- * What one member's monitor is showing: the task it is on, or the last thing
5543
- * that was said to it. A screen with nothing on it is a screen switched off.
5544
- */
5545
- function screenLineOf(memberId, tasks, messages) {
5546
- const active = tasks.find((task) => task.assigneeId === memberId && task.status === "active") ?? tasks.find((task) => task.assigneeId === memberId && task.status !== "done");
5547
- if (active !== void 0) return short(active.title, 34);
5548
- for (let index = messages.length - 1; index >= 0; index -= 1) {
5549
- const message = messages[index];
5550
- if (message?.to === memberId) return short(message.text, 34);
5551
- }
5552
- }
5553
- /**
5554
5673
  * The back wall of the room, and everything hung on it.
5555
5674
  *
5556
5675
  * Every fixture is placed by the SAME floor coordinate a member would stand at
@@ -5676,9 +5795,10 @@ window.__ModuleLoader__.load({
5676
5795
  /**
5677
5796
  * One workstation: the desk, the computer on it, the keyboard and the mug. It
5678
5797
  * belongs to the member whose desk it is and stays furnished while its owner
5679
- * is away — a member walks off, its screen keeps working.
5798
+ * is away — a member walks off, its screen keeps working. Memoized on a plan
5799
+ * that only changes when the facts do.
5680
5800
  */
5681
- function Workstation(props) {
5801
+ const Workstation = (0, react.memo)(function Workstation(props) {
5682
5802
  const { id, desk, seat, pose, line, empty, t } = props;
5683
5803
  const screen = pose === "working" ? "working" : line !== void 0 ? "reading" : "off";
5684
5804
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -5753,9 +5873,13 @@ window.__ModuleLoader__.load({
5753
5873
  "aria-hidden": true,
5754
5874
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChairFigure, {})
5755
5875
  })] });
5756
- }
5757
- /** One member of the team, standing — or walking — where its own state puts it. */
5758
- function MemberTile(props) {
5876
+ });
5877
+ /**
5878
+ * One member of the team, standing — or walking — where its own state puts it.
5879
+ * Memoized: the room re-renders whenever the pointer moves, and only the tile
5880
+ * under the pointer (or the one it left) has actually changed.
5881
+ */
5882
+ const MemberTile = (0, react.memo)(function MemberTile(props) {
5759
5883
  const { id, name, seat, home, errand, count, scale, relation, role, current, running, pose, away, focused, talking, turn, speech, tasks, label, title, onOpen, onFocus, t } = props;
5760
5884
  const obstacles = (0, react.useMemo)(() => obstaclesOf(Array.from({ length: count }, (_, index) => deskOf(index, count))), [count]);
5761
5885
  const loose = seat >= 0 && pose === "idle" && errand === void 0 && talking === void 0;
@@ -5776,7 +5900,9 @@ window.__ModuleLoader__.load({
5776
5900
  ...chairDelay(seat),
5777
5901
  ...stagger(seat + 1)
5778
5902
  },
5779
- onClick: onOpen,
5903
+ onClick: () => {
5904
+ onOpen(id);
5905
+ },
5780
5906
  onMouseEnter: () => {
5781
5907
  onFocus(id);
5782
5908
  },
@@ -5857,7 +5983,7 @@ window.__ModuleLoader__.load({
5857
5983
  })
5858
5984
  ]
5859
5985
  });
5860
- }
5986
+ });
5861
5987
  /**
5862
5988
  * The mailbox, as a log rather than a chat: a roster strip that keeps one
5863
5989
  * refreshed line per member — the newest thing it said or was told, truncated
@@ -5868,10 +5994,27 @@ window.__ModuleLoader__.load({
5868
5994
  function MessageFeed(props) {
5869
5995
  const { roster, messages, names, seats, leaderLabel, focus, onFocus, t } = props;
5870
5996
  const scroller = (0, react.useRef)(null);
5997
+ const lastId = messages.length > 0 ? messages[messages.length - 1].messageId : void 0;
5998
+ const latestOf = (0, react.useMemo)(() => {
5999
+ const out = /* @__PURE__ */ new Map();
6000
+ for (let index = messages.length - 1; index >= 0; index -= 1) {
6001
+ const message = messages[index];
6002
+ if (message === void 0) continue;
6003
+ if (message.from !== void 0 && !out.has(message.from)) out.set(message.from, {
6004
+ text: message.text,
6005
+ way: "sent"
6006
+ });
6007
+ if (message.to !== void 0 && !out.has(message.to)) out.set(message.to, {
6008
+ text: message.text,
6009
+ way: "got"
6010
+ });
6011
+ }
6012
+ return out;
6013
+ }, [messages]);
5871
6014
  (0, react.useEffect)(() => {
5872
6015
  const node = scroller.current;
5873
6016
  if (node !== null) node.scrollTop = node.scrollHeight;
5874
- }, [messages.length]);
6017
+ }, [lastId]);
5875
6018
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5876
6019
  className: TeamStage_module_css_default.feed,
5877
6020
  children: [
@@ -5879,7 +6022,7 @@ window.__ModuleLoader__.load({
5879
6022
  className: TeamStage_module_css_default.crewList,
5880
6023
  "aria-label": t("feed.crew"),
5881
6024
  children: roster.map((row) => {
5882
- const latest = latestOf(row.id, messages);
6025
+ const latest = latestOf.get(row.id);
5883
6026
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5884
6027
  className: TeamStage_module_css_default.crewRow,
5885
6028
  "data-crew-row": row.id,
@@ -5915,7 +6058,7 @@ window.__ModuleLoader__.load({
5915
6058
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5916
6059
  className: TeamStage_module_css_default.crewLine,
5917
6060
  title: latest?.text,
5918
- children: latest === void 0 ? t("feed.quiet") : `${latest.way === "got" ? "←" : "→"} ${short(latest.text, 40)}`
6061
+ children: latest === void 0 ? t("feed.quiet") : `${latest.way === "got" ? "←" : "→"} ${short(latest.text, CREW_CHARS)}`
5919
6062
  })
5920
6063
  ]
5921
6064
  }, row.id);
@@ -5931,46 +6074,35 @@ window.__ModuleLoader__.load({
5931
6074
  }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5932
6075
  className: TeamStage_module_css_default.log,
5933
6076
  ref: scroller,
5934
- children: messages.map((message, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LogRow, {
5935
- message,
5936
- index,
5937
- names,
5938
- seats,
5939
- leaderLabel,
5940
- focus,
5941
- onFocus,
5942
- t
5943
- }, message.messageId))
6077
+ children: messages.map((message, index) => {
6078
+ const partner = message.from ?? message.to;
6079
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LogRow, {
6080
+ message,
6081
+ index,
6082
+ names,
6083
+ seats,
6084
+ leaderLabel,
6085
+ focused: partner !== void 0 && focus === partner,
6086
+ onFocus,
6087
+ t
6088
+ }, message.messageId);
6089
+ })
5944
6090
  })
5945
6091
  ]
5946
6092
  });
5947
6093
  }
5948
- /** The newest traffic naming one member, and which way it went. */
5949
- function latestOf(memberId, messages) {
5950
- for (let index = messages.length - 1; index >= 0; index -= 1) {
5951
- const message = messages[index];
5952
- if (message === void 0) continue;
5953
- if (message.from === memberId) return {
5954
- text: message.text,
5955
- way: "sent"
5956
- };
5957
- if (message.to === memberId) return {
5958
- text: message.text,
5959
- way: "got"
5960
- };
5961
- }
5962
- }
5963
- /** One row of the log: who said what to whom, on one line, cut to fit. */
5964
- function LogRow(props) {
5965
- const { message, index, names, seats, leaderLabel, focus, onFocus, t } = props;
5966
- const label = (id) => id === void 0 ? leaderLabel : names.get(id) ?? id.slice(0, 6);
6094
+ /** One row of the log: who said what to whom, on one line, cut to fit. Memoized
6095
+ * so a hover re-renders the row it lit and the row it unlit, nothing else. */
6096
+ const LogRow = (0, react.memo)(function LogRow(props) {
6097
+ const { message, index, names, seats, leaderLabel, focused, onFocus, t } = props;
6098
+ const label = (id) => id === void 0 ? leaderLabel : names.get(id) ?? id.slice(0, SHORT_ID);
5967
6099
  const partner = message.from ?? message.to;
5968
6100
  const author = label(message.from);
5969
6101
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5970
6102
  className: TeamStage_module_css_default.logRow,
5971
6103
  "data-message-kind": message.kind,
5972
6104
  "data-hop": message.hop === void 0 ? void 0 : String(message.hop),
5973
- "data-focus": partner !== void 0 && focus === partner ? "true" : void 0,
6105
+ "data-focus": focused ? "true" : void 0,
5974
6106
  style: stagger(index),
5975
6107
  onMouseEnter: () => {
5976
6108
  onFocus(partner);
@@ -6031,14 +6163,15 @@ window.__ModuleLoader__.load({
6031
6163
  })
6032
6164
  ]
6033
6165
  });
6034
- }
6035
- /** One note pinned to the shared workspace, as the leader last saw it. */
6036
- function NoteCard(props) {
6037
- const { entry, index, seats, focus, onFocus } = props;
6166
+ });
6167
+ /** One note pinned to the shared workspace, as the leader last saw it. Memoized
6168
+ * like the log rows: a hover re-renders only the note it lit. */
6169
+ const NoteCard = (0, react.memo)(function NoteCard(props) {
6170
+ const { entry, index, seats, focused, onFocus } = props;
6038
6171
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6039
6172
  className: TeamStage_module_css_default.note,
6040
6173
  "data-note-key": entry.key,
6041
- "data-focus": focus === entry.authorId ? "true" : void 0,
6174
+ "data-focus": focused ? "true" : void 0,
6042
6175
  style: stagger(index),
6043
6176
  onMouseEnter: () => {
6044
6177
  onFocus(entry.authorId);
@@ -6076,7 +6209,7 @@ window.__ModuleLoader__.load({
6076
6209
  })
6077
6210
  ]
6078
6211
  });
6079
- }
6212
+ });
6080
6213
  /** One lane of the shared task board. */
6081
6214
  function TaskColumn(props) {
6082
6215
  const { status, tasks, names, seats, focus, onFocus, t } = props;
@@ -6116,7 +6249,7 @@ window.__ModuleLoader__.load({
6116
6249
  seat: seats.get(task.assigneeId),
6117
6250
  name: names.get(task.assigneeId) ?? task.assigneeId
6118
6251
  })
6119
- }), task.assigneeId === void 0 ? t("task.unassigned") : names.get(task.assigneeId) ?? task.assigneeId.slice(0, 6)]
6252
+ }), task.assigneeId === void 0 ? t("task.unassigned") : names.get(task.assigneeId) ?? task.assigneeId.slice(0, SHORT_ID)]
6120
6253
  }), task.note !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6121
6254
  className: TeamStage_module_css_default.cardNote,
6122
6255
  title: task.note,
@@ -6182,7 +6315,6 @@ window.__ModuleLoader__.load({
6182
6315
  "member.leader": "主会话",
6183
6316
  "member.open": "打开 {name} 的会话",
6184
6317
  "member.openLeader": "回到主会话",
6185
- "member.here": "你正在看这个会话",
6186
6318
  "relation.managed": "受管",
6187
6319
  "relation.peer": "同级",
6188
6320
  "status.running": "工作中",
@@ -6227,7 +6359,6 @@ window.__ModuleLoader__.load({
6227
6359
  "member.leader": "Main session",
6228
6360
  "member.open": "Open the session of {name}",
6229
6361
  "member.openLeader": "Back to the main session",
6230
- "member.here": "You are reading this session",
6231
6362
  "relation.managed": "Managed",
6232
6363
  "relation.peer": "Peer",
6233
6364
  "status.running": "Working",
@@ -6403,7 +6534,7 @@ window.__ModuleLoader__.load({
6403
6534
  try {
6404
6535
  sessions.openSubagent(address);
6405
6536
  } catch {}
6406
- });
6537
+ }, () => {});
6407
6538
  }
6408
6539
  };
6409
6540
  /**