camox 0.54.0 → 0.57.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 (50) hide show
  1. package/dist/features/canvas/CamoxCanvas.js +14 -11
  2. package/dist/features/canvas/CanvasLoadingScreen.js +1 -1
  3. package/dist/features/canvas/CanvasPageHeader.js +1 -1
  4. package/dist/features/canvas/canvasFrameDocument.js +13 -6
  5. package/dist/features/canvas/sidebar/CanvasViewHeader.js +1 -1
  6. package/dist/features/canvas/sidebar/{CanvasSidebar.js → ContentSidebar.js} +5 -5
  7. package/dist/features/canvas/sidebar/{CanvasSidebarFrame.js → ContentSidebarFrame.js} +4 -4
  8. package/dist/features/canvas/sidebar/{CanvasSidebarSkeleton.js → ContentSidebarSkeleton.js} +7 -7
  9. package/dist/features/preview/CamoxPreview.js +2 -2
  10. package/dist/features/preview/components/Frame.js +1 -18
  11. package/dist/features/preview/components/PreviewToolbar.js +1 -1
  12. package/dist/features/preview/components/SelectionEditor.js +2 -2
  13. package/dist/features/preview/components/SidebarStack.js +201 -116
  14. package/dist/features/preview/components/StudioEditingFallback.js +3 -3
  15. package/dist/features/preview/components/previewStyles.js +25 -1
  16. package/dist/features/renderer/RendererApp.js +55 -37
  17. package/dist/features/routes/pageRuntime.d.ts +1 -1
  18. package/dist/features/runtime/RuntimeChrome.js +4 -4
  19. package/dist/features/studio/components/AgentSidebar.js +56 -0
  20. package/dist/features/studio/components/ChatWidget.js +219 -0
  21. package/dist/features/studio/components/DraftsControl.js +17 -17
  22. package/dist/features/studio/components/Patrol.js +676 -0
  23. package/dist/features/studio/components/ReviewDraftSheet.js +38 -38
  24. package/dist/features/studio/components/Squareling.js +171 -84
  25. package/dist/features/studio/components/ThreadMessages.js +256 -136
  26. package/dist/features/studio/localeOptions.js +7 -3
  27. package/dist/features/studio/reportSentence.js +75 -0
  28. package/dist/features/studio/routes.js +2 -1
  29. package/dist/features/studio/showInCanvas.js +9 -2
  30. package/dist/features/studio/studioStore.js +5 -5
  31. package/dist/features/studio/workingSentence.js +55 -0
  32. package/dist/lib/queries.js +1 -1
  33. package/dist/lib/studio-reads.d.ts +1 -0
  34. package/dist/lib/studio-reads.js +5 -0
  35. package/dist/lib/use-thread.js +156 -190
  36. package/dist/package.js +1 -1
  37. package/dist/studio.css +1 -1
  38. package/package.json +4 -4
  39. package/skills/camox/SKILL.md +3 -10
  40. package/skills/camox/references/artifacts.md +2 -2
  41. package/skills/camox/references/block-definitions.md +1 -1
  42. package/skills/camox/references/layout-definitions.md +1 -1
  43. package/skills/camox/references/routed-layouts.md +2 -2
  44. package/skills/camox-cli/SKILL.md +15 -0
  45. package/skills/{camox → camox-cli}/references/cli-common.md +1 -1
  46. package/skills/{camox → camox-cli}/references/cli-content.md +2 -2
  47. package/skills/{camox → camox-cli}/references/cli-publishing.md +4 -4
  48. package/skills/camox-expand/SKILL.md +1 -1
  49. package/skills/camoxify/SKILL.md +1 -1
  50. package/dist/features/studio/components/ChatSidebar.js +0 -346
@@ -965,7 +965,7 @@ function _temp7(error) {
965
965
  }
966
966
  /**
967
967
  * Switches the studio to Live once its draft ended here, replacing the draft's URL entry. A
968
- * development draft never ends: publishing or discarding empties it, and dev mode stays in it.
968
+ * development draft never ends: publishing or deleting empties it, and dev mode stays in it.
969
969
  */
970
970
  function useLeaveDraft() {
971
971
  const $ = c(2);
@@ -1077,7 +1077,7 @@ function DraftNameInput(t0) {
1077
1077
  return t7;
1078
1078
  }
1079
1079
  /**
1080
- * Reviews a draft before publishing it whole, or discards it (ADR 0009). Publishing sends back
1080
+ * Reviews a draft before publishing it whole, or deletes it (ADR 0009). Publishing sends back
1081
1081
  * the token of the preview shown; when Live changed since, nothing is published and the new
1082
1082
  * preview is shown. Once the draft ends, the studio switches to Live.
1083
1083
  */
@@ -1085,7 +1085,7 @@ function ReviewDraftSheet(t0) {
1085
1085
  const $ = c(101);
1086
1086
  const { projectId, draftId, open, startRenaming: t1, onOpenChange } = t0;
1087
1087
  const startRenaming = t1 === void 0 ? false : t1;
1088
- const [confirmingDiscard, setConfirmingDiscard] = React.useState(false);
1088
+ const [confirmingDelete, setConfirmingDelete] = React.useState(false);
1089
1089
  let t2;
1090
1090
  if ($[0] !== draftId || $[1] !== projectId) {
1091
1091
  t2 = reads.publishPreview({
@@ -1391,7 +1391,7 @@ function ReviewDraftSheet(t0) {
1391
1391
  let t23;
1392
1392
  let t24;
1393
1393
  if ($[61] === Symbol.for("react.memo_cache_sentinel")) {
1394
- t23 = () => setConfirmingDiscard(true);
1394
+ t23 = () => setConfirmingDelete(true);
1395
1395
  t24 = /* @__PURE__ */ jsx(Trash2, {});
1396
1396
  $[61] = t23;
1397
1397
  $[62] = t24;
@@ -1406,7 +1406,7 @@ function ReviewDraftSheet(t0) {
1406
1406
  className: "text-destructive",
1407
1407
  disabled: busy,
1408
1408
  onClick: t23,
1409
- children: [t24, "Discard draft"]
1409
+ children: [t24, "Delete draft"]
1410
1410
  });
1411
1411
  $[63] = busy;
1412
1412
  $[64] = t25;
@@ -1506,14 +1506,14 @@ function ReviewDraftSheet(t0) {
1506
1506
  $[93] = t34;
1507
1507
  } else t34 = $[93];
1508
1508
  let t35;
1509
- if ($[94] !== confirmingDiscard || $[95] !== leave || $[96] !== projectId) {
1510
- t35 = /* @__PURE__ */ jsx(DiscardDraftDialog, {
1509
+ if ($[94] !== confirmingDelete || $[95] !== leave || $[96] !== projectId) {
1510
+ t35 = /* @__PURE__ */ jsx(DeleteDraftDialog, {
1511
1511
  projectId,
1512
- open: confirmingDiscard,
1513
- onOpenChange: setConfirmingDiscard,
1514
- onDiscarded: leave
1512
+ open: confirmingDelete,
1513
+ onOpenChange: setConfirmingDelete,
1514
+ onDeleted: leave
1515
1515
  });
1516
- $[94] = confirmingDiscard;
1516
+ $[94] = confirmingDelete;
1517
1517
  $[95] = leave;
1518
1518
  $[96] = projectId;
1519
1519
  $[97] = t35;
@@ -1527,78 +1527,78 @@ function ReviewDraftSheet(t0) {
1527
1527
  } else t36 = $[100];
1528
1528
  return t36;
1529
1529
  }
1530
- /** Asks before discarding the draft the studio is in, then discards it. */
1531
- function DiscardDraftDialog(t0) {
1530
+ /** Asks before deleting the draft the studio is in, then deletes it. */
1531
+ function DeleteDraftDialog(t0) {
1532
1532
  const $ = c(26);
1533
- const { projectId, open, onOpenChange, onDiscarded } = t0;
1533
+ const { projectId, open, onOpenChange, onDeleted } = t0;
1534
1534
  let t1;
1535
1535
  if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
1536
- t1 = draftMutations.discard();
1536
+ t1 = draftMutations.delete();
1537
1537
  $[0] = t1;
1538
1538
  } else t1 = $[0];
1539
1539
  let t2;
1540
- if ($[1] !== onDiscarded || $[2] !== onOpenChange) {
1540
+ if ($[1] !== onDeleted || $[2] !== onOpenChange) {
1541
1541
  t2 = {
1542
1542
  ...t1,
1543
1543
  onSuccess: (t3) => {
1544
1544
  const { ended } = t3;
1545
1545
  onOpenChange(false);
1546
- onDiscarded(ended);
1546
+ onDeleted(ended);
1547
1547
  },
1548
1548
  onError: _temp10
1549
1549
  };
1550
- $[1] = onDiscarded;
1550
+ $[1] = onDeleted;
1551
1551
  $[2] = onOpenChange;
1552
1552
  $[3] = t2;
1553
1553
  } else t2 = $[3];
1554
- const discard = useMutation(t2);
1554
+ const deleteDraft = useMutation(t2);
1555
1555
  let t3;
1556
- if ($[4] !== discard.isPending || $[5] !== onOpenChange) {
1556
+ if ($[4] !== deleteDraft.isPending || $[5] !== onOpenChange) {
1557
1557
  t3 = (next) => {
1558
- if (!discard.isPending) onOpenChange(next);
1558
+ if (!deleteDraft.isPending) onOpenChange(next);
1559
1559
  };
1560
- $[4] = discard.isPending;
1560
+ $[4] = deleteDraft.isPending;
1561
1561
  $[5] = onOpenChange;
1562
1562
  $[6] = t3;
1563
1563
  } else t3 = $[6];
1564
1564
  let t4;
1565
1565
  if ($[7] === Symbol.for("react.memo_cache_sentinel")) {
1566
- t4 = /* @__PURE__ */ jsxs(AlertDialogHeader, { children: [/* @__PURE__ */ jsx(AlertDialogTitle, { children: "Discard this draft?" }), /* @__PURE__ */ jsx(AlertDialogDescription, { children: "Every change in this draft is deleted for everyone. Live stays as it is. This can't be undone." })] });
1566
+ t4 = /* @__PURE__ */ jsxs(AlertDialogHeader, { children: [/* @__PURE__ */ jsx(AlertDialogTitle, { children: "Delete this draft?" }), /* @__PURE__ */ jsx(AlertDialogDescription, { children: "Every change in this draft is deleted for everyone. Live stays as it is. This can't be undone." })] });
1567
1567
  $[7] = t4;
1568
1568
  } else t4 = $[7];
1569
1569
  let t5;
1570
- if ($[8] !== discard.isPending) {
1570
+ if ($[8] !== deleteDraft.isPending) {
1571
1571
  t5 = /* @__PURE__ */ jsx(AlertDialogCancel, {
1572
1572
  variant: "outline",
1573
1573
  size: "default",
1574
- disabled: discard.isPending,
1574
+ disabled: deleteDraft.isPending,
1575
1575
  children: "Cancel"
1576
1576
  });
1577
- $[8] = discard.isPending;
1577
+ $[8] = deleteDraft.isPending;
1578
1578
  $[9] = t5;
1579
1579
  } else t5 = $[9];
1580
1580
  let t6;
1581
- if ($[10] !== discard || $[11] !== projectId) {
1582
- t6 = () => discard.mutate({ projectId });
1583
- $[10] = discard;
1581
+ if ($[10] !== deleteDraft || $[11] !== projectId) {
1582
+ t6 = () => deleteDraft.mutate({ projectId });
1583
+ $[10] = deleteDraft;
1584
1584
  $[11] = projectId;
1585
1585
  $[12] = t6;
1586
1586
  } else t6 = $[12];
1587
1587
  let t7;
1588
- if ($[13] !== discard.isPending) {
1589
- t7 = discard.isPending ? /* @__PURE__ */ jsx(Spinner, {}) : null;
1590
- $[13] = discard.isPending;
1588
+ if ($[13] !== deleteDraft.isPending) {
1589
+ t7 = deleteDraft.isPending ? /* @__PURE__ */ jsx(Spinner, {}) : null;
1590
+ $[13] = deleteDraft.isPending;
1591
1591
  $[14] = t7;
1592
1592
  } else t7 = $[14];
1593
1593
  let t8;
1594
- if ($[15] !== discard.isPending || $[16] !== t6 || $[17] !== t7) {
1594
+ if ($[15] !== deleteDraft.isPending || $[16] !== t6 || $[17] !== t7) {
1595
1595
  t8 = /* @__PURE__ */ jsxs(AlertDialogAction, {
1596
1596
  variant: "destructive",
1597
- disabled: discard.isPending,
1597
+ disabled: deleteDraft.isPending,
1598
1598
  onClick: t6,
1599
- children: [t7, "Discard draft"]
1599
+ children: [t7, "Delete draft"]
1600
1600
  });
1601
- $[15] = discard.isPending;
1601
+ $[15] = deleteDraft.isPending;
1602
1602
  $[16] = t6;
1603
1603
  $[17] = t7;
1604
1604
  $[18] = t8;
@@ -1625,8 +1625,8 @@ function DiscardDraftDialog(t0) {
1625
1625
  return t10;
1626
1626
  }
1627
1627
  function _temp10(error) {
1628
- return toast.error(error.message || "Could not discard the draft");
1628
+ return toast.error(error.message || "Could not delete the draft");
1629
1629
  }
1630
1630
 
1631
1631
  //#endregion
1632
- export { DiscardDraftDialog, ReviewDraftSheet, useLeaveDraft };
1632
+ export { DeleteDraftDialog, ReviewDraftSheet, useLeaveDraft };
@@ -4,13 +4,20 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
4
4
 
5
5
  //#region src/features/studio/components/Squareling.tsx
6
6
  /**
7
- * Camox's agent, drawn from the logo's shapes: its square, the soft corner, and the knockout as
8
- * eyes, looking right like the mark. Its face and motion say what the agent is doing. The
9
- * animations live in `studio.css`.
7
+ * A squareling, drawn from the logo's shapes, with the knockout as eyes, looking right like the
8
+ * mark. Its face and motion say what it is doing. The animations live in `studio.css`.
9
+ *
10
+ * The agent's (the default) is the logo's square with its soft corner, in emerald. Each patroller
11
+ * has its own, one family: the Translator is the logo's wide wedge, in violet, glancing across
12
+ * while it works; the SEO manager is a tall block with the small shape's soft corner, in amber,
13
+ * scanning down while it works.
10
14
  */
11
- function Squareling(t0) {
12
- const $ = c(17);
13
- const { status, className } = t0;
15
+ function Squareling(props) {
16
+ const $ = c(18);
17
+ const { status, className, ref } = props;
18
+ const variant = props.variant ?? "agent";
19
+ const look = LOOKS[variant];
20
+ const t0 = variant === "agent" ? void 0 : variant;
14
21
  let t1;
15
22
  if ($[0] !== className) {
16
23
  t1 = cn("squareling shrink-0 overflow-visible", className);
@@ -18,96 +25,176 @@ function Squareling(t0) {
18
25
  $[1] = t1;
19
26
  } else t1 = $[1];
20
27
  let t2;
21
- if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
28
+ if ($[2] !== look.body || $[3] !== look.fill) {
22
29
  t2 = /* @__PURE__ */ jsx("path", {
23
- d: "M20 12H80Q88 12 88 20V64Q88 88 64 88H20Q12 88 12 80V20Q12 12 20 12Z",
24
- className: "fill-emerald-500"
30
+ d: look.body,
31
+ className: look.fill
25
32
  });
26
- $[2] = t2;
27
- } else t2 = $[2];
33
+ $[2] = look.body;
34
+ $[3] = look.fill;
35
+ $[4] = t2;
36
+ } else t2 = $[4];
28
37
  let t3;
29
- if ($[3] !== status) {
30
- t3 = (status === "idle" || status === "thinking") && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("rect", {
31
- className: "squareling-eye",
32
- x: "50",
33
- y: "36",
34
- width: "11",
35
- height: "17"
36
- }), /* @__PURE__ */ jsx("rect", {
37
- className: "squareling-eye",
38
- x: "69",
39
- y: "36",
40
- width: "11",
41
- height: "17"
42
- })] });
43
- $[3] = status;
44
- $[4] = t3;
45
- } else t3 = $[4];
38
+ if ($[5] !== look.eyes || $[6] !== props.status || $[7] !== props.variant) {
39
+ t3 = /* @__PURE__ */ jsx("g", {
40
+ className: "squareling-eyes fill-neutral-950",
41
+ children: props.variant === void 0 || props.variant === "agent" ? /* @__PURE__ */ jsx(AgentEyes, {
42
+ eyes: look.eyes,
43
+ status: props.status
44
+ }) : /* @__PURE__ */ jsx(PatrollerEyes, {
45
+ eyes: look.eyes,
46
+ working: props.status === "working"
47
+ })
48
+ });
49
+ $[5] = look.eyes;
50
+ $[6] = props.status;
51
+ $[7] = props.variant;
52
+ $[8] = t3;
53
+ } else t3 = $[8];
46
54
  let t4;
47
- if ($[5] !== status) {
48
- t4 = status === "acting" && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("rect", {
49
- x: "50",
50
- y: "44",
51
- width: "11",
52
- height: "6"
53
- }), /* @__PURE__ */ jsx("rect", {
54
- x: "69",
55
- y: "44",
56
- width: "11",
57
- height: "6"
58
- })] });
59
- $[5] = status;
60
- $[6] = t4;
61
- } else t4 = $[6];
62
- let t5;
63
- if ($[7] !== status) {
64
- t5 = status === "fixing" && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("rect", {
65
- x: "50",
66
- y: "36",
67
- width: "11",
68
- height: "17"
69
- }), /* @__PURE__ */ jsx("rect", {
70
- x: "69",
71
- y: "44",
72
- width: "11",
73
- height: "6"
74
- })] });
75
- $[7] = status;
76
- $[8] = t5;
77
- } else t5 = $[8];
78
- let t6;
79
- if ($[9] !== t3 || $[10] !== t4 || $[11] !== t5) {
80
- t6 = /* @__PURE__ */ jsxs("g", {
55
+ if ($[9] !== t2 || $[10] !== t3) {
56
+ t4 = /* @__PURE__ */ jsxs("g", {
81
57
  className: "squareling-body",
82
- children: [t2, /* @__PURE__ */ jsxs("g", {
83
- className: "squareling-eyes fill-neutral-950",
84
- children: [
85
- t3,
86
- t4,
87
- t5
88
- ]
89
- })]
58
+ children: [t2, t3]
90
59
  });
91
- $[9] = t3;
92
- $[10] = t4;
93
- $[11] = t5;
94
- $[12] = t6;
95
- } else t6 = $[12];
96
- let t7;
97
- if ($[13] !== status || $[14] !== t1 || $[15] !== t6) {
98
- t7 = /* @__PURE__ */ jsx("svg", {
60
+ $[9] = t2;
61
+ $[10] = t3;
62
+ $[11] = t4;
63
+ } else t4 = $[11];
64
+ let t5;
65
+ if ($[12] !== ref || $[13] !== status || $[14] !== t0 || $[15] !== t1 || $[16] !== t4) {
66
+ t5 = /* @__PURE__ */ jsx("svg", {
67
+ ref,
99
68
  viewBox: "0 0 100 100",
100
69
  "aria-hidden": true,
101
70
  "data-squareling": status,
71
+ "data-squareling-variant": t0,
102
72
  className: t1,
103
- children: t6
73
+ children: t4
104
74
  });
75
+ $[12] = ref;
105
76
  $[13] = status;
106
- $[14] = t1;
107
- $[15] = t6;
108
- $[16] = t7;
109
- } else t7 = $[16];
110
- return t7;
77
+ $[14] = t0;
78
+ $[15] = t1;
79
+ $[16] = t4;
80
+ $[17] = t5;
81
+ } else t5 = $[17];
82
+ return t5;
83
+ }
84
+ const LOOKS = {
85
+ agent: {
86
+ body: "M20 12H80Q88 12 88 20V64Q88 88 64 88H20Q12 88 12 80V20Q12 12 20 12Z",
87
+ fill: "fill-emerald-500",
88
+ eyes: {
89
+ x: [50, 69],
90
+ y: 36
91
+ }
92
+ },
93
+ translator: {
94
+ body: "M14 14H86Q92 14 89.6 19.5L67.3 69.6Q60 86 42 86H14Q8 86 8 80V20Q8 14 14 14Z",
95
+ fill: "fill-violet-500",
96
+ eyes: {
97
+ x: [40, 59],
98
+ y: 28
99
+ }
100
+ },
101
+ seoManager: {
102
+ body: "M20 32Q20 8 44 8H74Q80 8 80 14V86Q80 92 74 92H26Q20 92 20 86Z",
103
+ fill: "fill-amber-500",
104
+ eyes: {
105
+ x: [44, 63],
106
+ y: 28
107
+ }
108
+ }
109
+ };
110
+ const EYE_WIDTH = 11;
111
+ const OPEN = 17;
112
+ const NARROWED = 6;
113
+ /** How far down a narrowed eye sits, from the top of the open one. */
114
+ const NARROWED_OFFSET = 8;
115
+ /**
116
+ * One eye, its left edge at `x` and its top at `y` while open: open, or narrowed on the work.
117
+ * Only an eye that blinks carries the class `studio.css` blinks.
118
+ */
119
+ function Eye(t0) {
120
+ const $ = c(5);
121
+ const { x, y, narrowed, blinks } = t0;
122
+ const t1 = blinks ? "squareling-eye" : void 0;
123
+ const t2 = narrowed ? y + NARROWED_OFFSET : y;
124
+ const t3 = narrowed ? NARROWED : OPEN;
125
+ let t4;
126
+ if ($[0] !== t1 || $[1] !== t2 || $[2] !== t3 || $[3] !== x) {
127
+ t4 = /* @__PURE__ */ jsx("rect", {
128
+ className: t1,
129
+ x,
130
+ y: t2,
131
+ width: EYE_WIDTH,
132
+ height: t3
133
+ });
134
+ $[0] = t1;
135
+ $[1] = t2;
136
+ $[2] = t3;
137
+ $[3] = x;
138
+ $[4] = t4;
139
+ } else t4 = $[4];
140
+ return t4;
141
+ }
142
+ /**
143
+ * The agent's eyes: open, blinking, while idle or thinking; both narrowed while acting; the
144
+ * right one narrowed while fixing.
145
+ */
146
+ function AgentEyes(t0) {
147
+ const $ = c(13);
148
+ const { eyes, status } = t0;
149
+ const [left, right] = eyes.x;
150
+ const blinks = status === "idle" || status === "thinking";
151
+ const t1 = status === "acting";
152
+ let t2;
153
+ if ($[0] !== blinks || $[1] !== eyes.y || $[2] !== left || $[3] !== t1) {
154
+ t2 = /* @__PURE__ */ jsx(Eye, {
155
+ x: left,
156
+ y: eyes.y,
157
+ narrowed: t1,
158
+ blinks
159
+ });
160
+ $[0] = blinks;
161
+ $[1] = eyes.y;
162
+ $[2] = left;
163
+ $[3] = t1;
164
+ $[4] = t2;
165
+ } else t2 = $[4];
166
+ const t3 = status === "acting" || status === "fixing";
167
+ let t4;
168
+ if ($[5] !== blinks || $[6] !== eyes.y || $[7] !== right || $[8] !== t3) {
169
+ t4 = /* @__PURE__ */ jsx(Eye, {
170
+ x: right,
171
+ y: eyes.y,
172
+ narrowed: t3,
173
+ blinks
174
+ });
175
+ $[5] = blinks;
176
+ $[6] = eyes.y;
177
+ $[7] = right;
178
+ $[8] = t3;
179
+ $[9] = t4;
180
+ } else t4 = $[9];
181
+ let t5;
182
+ if ($[10] !== t2 || $[11] !== t4) {
183
+ t5 = /* @__PURE__ */ jsxs(Fragment, { children: [t2, t4] });
184
+ $[10] = t2;
185
+ $[11] = t4;
186
+ $[12] = t5;
187
+ } else t5 = $[12];
188
+ return t5;
189
+ }
190
+ /** A patroller's eyes: open while idle, narrowed on the work while working. */
191
+ function PatrollerEyes({ eyes, working }) {
192
+ return eyes.x.map((x) => /* @__PURE__ */ jsx(Eye, {
193
+ x,
194
+ y: eyes.y,
195
+ narrowed: working,
196
+ blinks: true
197
+ }, x));
111
198
  }
112
199
 
113
200
  //#endregion