@quilltap/theme-storybook 1.0.49 → 1.0.51

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.
@@ -1681,6 +1681,74 @@ var Chat = () => {
1681
1681
  ] }) })
1682
1682
  ] })
1683
1683
  ] }),
1684
+ /* @__PURE__ */ jsxs14("section", { style: { marginBottom: "2rem" }, children: [
1685
+ /* @__PURE__ */ jsx14("h3", { style: { fontSize: "1.125rem", fontWeight: 700, marginBottom: "1rem", borderBottom: "1px solid var(--color-border)", paddingBottom: "0.5rem" }, children: "Staff Announcements" }),
1686
+ /* @__PURE__ */ jsx14("p", { style: { color: "var(--color-muted-foreground)", marginBottom: "1rem" }, children: "Messages authored by a personified feature rather than a character. Each collapses to a one-line bar; a run of consecutive ones packs into a row of content-width chips. The leading dot carries an importance tier \u2014 filled for high and medium, hollow for low \u2014 so the eye lands on the file changes and arrivals and skims past the time calls." }),
1687
+ /* @__PURE__ */ jsxs14("div", { style: { display: "flex", flexDirection: "column", gap: "1rem", maxWidth: "32rem" }, children: [
1688
+ /* @__PURE__ */ jsxs14("button", { type: "button", className: "qt-chat-system-bar", children: [
1689
+ /* @__PURE__ */ jsx14("span", { className: "qt-chat-announcement-dot qt-chat-announcement-dot-high", "aria-hidden": "true" }),
1690
+ /* @__PURE__ */ jsx14("span", { className: "qt-chat-system-bar-sender", children: "The Librarian" }),
1691
+ /* @__PURE__ */ jsx14("span", { className: "qt-chat-system-bar-kind", children: "edited by character" }),
1692
+ /* @__PURE__ */ jsx14("span", { className: "qt-chat-system-bar-time", children: "4:12 PM" }),
1693
+ /* @__PURE__ */ jsx14("span", { className: "qt-chat-system-bar-chevron", "aria-hidden": "true", children: "\u203A" })
1694
+ ] }),
1695
+ /* @__PURE__ */ jsxs14("div", { className: "qt-chat-announcement-group", style: { width: "100%", margin: 0 }, children: [
1696
+ /* @__PURE__ */ jsxs14("button", { type: "button", className: "qt-chat-announcement-chip", children: [
1697
+ /* @__PURE__ */ jsx14("span", { className: "qt-chat-announcement-dot qt-chat-announcement-dot-high", "aria-hidden": "true" }),
1698
+ /* @__PURE__ */ jsx14("span", { className: "qt-chat-system-bar-sender", children: "The Host" }),
1699
+ /* @__PURE__ */ jsx14("span", { className: "qt-chat-system-bar-kind", children: "status change" }),
1700
+ /* @__PURE__ */ jsx14("span", { className: "qt-chat-system-bar-time", children: "4:13 PM" }),
1701
+ /* @__PURE__ */ jsx14("span", { className: "qt-chat-system-bar-chevron", "aria-hidden": "true", children: "\u203A" })
1702
+ ] }),
1703
+ /* @__PURE__ */ jsxs14("button", { type: "button", className: "qt-chat-announcement-chip", children: [
1704
+ /* @__PURE__ */ jsx14("span", { className: "qt-chat-announcement-dot qt-chat-announcement-dot-medium", "aria-hidden": "true" }),
1705
+ /* @__PURE__ */ jsx14("span", { className: "qt-chat-system-bar-sender", children: "The Lantern" }),
1706
+ /* @__PURE__ */ jsx14("span", { className: "qt-chat-system-bar-kind", children: "background" }),
1707
+ /* @__PURE__ */ jsx14("span", { className: "qt-chat-system-bar-time", children: "4:14 PM" }),
1708
+ /* @__PURE__ */ jsx14("span", { className: "qt-chat-system-bar-chevron", "aria-hidden": "true", children: "\u203A" })
1709
+ ] }),
1710
+ /* @__PURE__ */ jsxs14("button", { type: "button", className: "qt-chat-announcement-chip", children: [
1711
+ /* @__PURE__ */ jsx14("span", { className: "qt-chat-announcement-dot qt-chat-announcement-dot-low", "aria-hidden": "true" }),
1712
+ /* @__PURE__ */ jsx14("span", { className: "qt-chat-system-bar-sender", children: "Prospero" }),
1713
+ /* @__PURE__ */ jsx14("span", { className: "qt-chat-system-bar-kind", children: "project information" }),
1714
+ /* @__PURE__ */ jsx14("span", { className: "qt-chat-system-bar-time", children: "4:14 PM" }),
1715
+ /* @__PURE__ */ jsx14("span", { className: "qt-chat-system-bar-chevron", "aria-hidden": "true", children: "\u203A" })
1716
+ ] })
1717
+ ] })
1718
+ ] })
1719
+ ] }),
1720
+ /* @__PURE__ */ jsxs14("section", { style: { marginBottom: "2rem" }, children: [
1721
+ /* @__PURE__ */ jsx14("h3", { style: { fontSize: "1.125rem", fontWeight: 700, marginBottom: "1rem", borderBottom: "1px solid var(--color-border)", paddingBottom: "0.5rem" }, children: "Pascal Roll Outcomes" }),
1722
+ /* @__PURE__ */ jsxs14("p", { style: { color: "var(--color-muted-foreground)", marginBottom: "1rem" }, children: [
1723
+ "The outcome of a custom tool (pseudo-tool) roll, announced by Pascal the Croupier. The tool's author assigns each outcome a semantic state \u2014 success, partial, failure, info \u2014 and the accent follows it, on the bubble and on the announcement bar above it alike. The bar swaps its importance dot for the outcome's own state, since a success has no business wearing the red dot a high tier would give it. Built on the ",
1724
+ /* @__PURE__ */ jsx14("code", { children: "--qt-alert-*" }),
1725
+ " families: the alpha-thin",
1726
+ /* @__PURE__ */ jsx14("code", { children: " -border" }),
1727
+ " tints for the leading edge, the solid ",
1728
+ /* @__PURE__ */ jsx14("code", { children: "-fg" }),
1729
+ " for the dot."
1730
+ ] }),
1731
+ /* @__PURE__ */ jsx14("div", { style: { display: "flex", flexDirection: "column", gap: "1rem", maxWidth: "32rem" }, children: [
1732
+ ["success", "Pick the Lock", "The lock clicks open."],
1733
+ ["partial", "Pick the Lock", "The lock is giving way, but not yet."],
1734
+ ["failure", "Pick the Lock", "Still locked, and the corridor is no longer empty."],
1735
+ ["info", "Scan Hawking Radiation", "The detector reads 41 \xB5K."]
1736
+ ].map(([state, tool, message]) => /* @__PURE__ */ jsxs14("div", { children: [
1737
+ /* @__PURE__ */ jsxs14("button", { type: "button", className: `qt-chat-system-bar qt-chat-system-bar-expanded qt-pascal-result qt-pascal-result--${state}`, children: [
1738
+ /* @__PURE__ */ jsx14("span", { className: `qt-chat-announcement-dot qt-chat-announcement-dot-outcome-${state}`, "aria-hidden": "true" }),
1739
+ /* @__PURE__ */ jsx14("span", { className: "qt-chat-system-bar-sender", children: "Pascal" }),
1740
+ /* @__PURE__ */ jsx14("span", { className: "qt-chat-system-bar-kind", children: tool }),
1741
+ /* @__PURE__ */ jsx14("span", { className: "qt-chat-system-bar-time", children: "4:15 PM" }),
1742
+ /* @__PURE__ */ jsx14("span", { className: "qt-chat-system-bar-chevron", "aria-hidden": "true", children: "\u2227" })
1743
+ ] }),
1744
+ /* @__PURE__ */ jsx14("div", { className: `qt-chat-message-body qt-chat-message-assistant qt-pascal-result qt-pascal-result--${state}`, children: /* @__PURE__ */ jsxs14("p", { children: [
1745
+ "\u{1F3B2} ",
1746
+ /* @__PURE__ */ jsx14("strong", { children: tool }),
1747
+ " \u2014 ",
1748
+ message
1749
+ ] }) })
1750
+ ] }, state)) })
1751
+ ] }),
1684
1752
  /* @__PURE__ */ jsxs14("section", { style: { marginBottom: "2rem" }, children: [
1685
1753
  /* @__PURE__ */ jsx14("h3", { style: { fontSize: "1.125rem", fontWeight: 700, marginBottom: "1rem", borderBottom: "1px solid var(--color-border)", paddingBottom: "0.5rem" }, children: "Wardrobe Action Notices" }),
1686
1754
  /* @__PURE__ */ jsx14("p", { style: { color: "var(--color-muted-foreground)", marginBottom: "1rem" }, children: "Inline summaries of outfit changes (equip, unequip, gift). Distinguished from whispers (dashed purple) and silent messages (dotted teal) by a double border and warm amber/gold tones." }),
package/dist/index.css CHANGED
@@ -438,6 +438,14 @@ body {
438
438
  --qt-chat-wardrobe-fg: var(--qt-chat-assistant-fg);
439
439
  --qt-chat-wardrobe-border: #c4a24e;
440
440
  --qt-chat-wardrobe-label-fg: #9a7d2e;
441
+ --qt-chat-system-bar-bg: color-mix(in srgb, var(--qt-chat-assistant-bg) 70%, var(--color-muted) 30%);
442
+ --qt-chat-system-bar-fg: var(--color-muted-foreground);
443
+ --qt-chat-system-bar-border: var(--color-border);
444
+ --qt-chat-system-bar-hover-bg: color-mix(in srgb, var(--qt-chat-assistant-bg) 55%, var(--color-muted) 45%);
445
+ --qt-chat-system-bar-sender-fg: var(--color-foreground);
446
+ --qt-chat-announcement-dot-high: var(--color-destructive, #b4452e);
447
+ --qt-chat-announcement-dot-medium: var(--color-warning, #d08a1e);
448
+ --qt-chat-announcement-dot-low: var(--color-muted-foreground);
441
449
  --qt-chat-composer-bg: var(--color-background);
442
450
  --qt-chat-composer-border: var(--color-border);
443
451
  --qt-chat-composer-radius: var(--radius-lg);
@@ -1103,6 +1111,142 @@ body {
1103
1111
  .qt-pascal-result--info {
1104
1112
  border-left-color: var(--qt-alert-info-border);
1105
1113
  }
1114
+ .qt-chat-system-bar {
1115
+ display: flex;
1116
+ align-items: center;
1117
+ gap: 0.625rem;
1118
+ width: 100%;
1119
+ padding: 0.25rem 0.625rem;
1120
+ margin: 0.125rem 0;
1121
+ background: var(--qt-chat-system-bar-bg);
1122
+ color: var(--qt-chat-system-bar-fg);
1123
+ border: 1px solid var(--qt-chat-system-bar-border);
1124
+ border-radius: var(--radius-sm, 0.25rem);
1125
+ font-size: 0.75rem;
1126
+ line-height: 1.2;
1127
+ text-align: left;
1128
+ cursor: pointer;
1129
+ transition: background-color 120ms ease;
1130
+ }
1131
+ .qt-chat-system-bar:hover,
1132
+ .qt-chat-system-bar:focus-visible {
1133
+ background: var(--qt-chat-system-bar-hover-bg);
1134
+ outline: none;
1135
+ }
1136
+ .qt-chat-system-bar-sender {
1137
+ color: var(--qt-chat-system-bar-sender-fg);
1138
+ font-weight: 600;
1139
+ white-space: nowrap;
1140
+ }
1141
+ .qt-chat-system-bar-kind {
1142
+ flex: 1 1 auto;
1143
+ min-width: 0;
1144
+ font-style: italic;
1145
+ overflow: hidden;
1146
+ text-overflow: ellipsis;
1147
+ white-space: nowrap;
1148
+ }
1149
+ .qt-chat-system-bar-time {
1150
+ color: var(--qt-chat-system-bar-fg);
1151
+ opacity: 0.75;
1152
+ white-space: nowrap;
1153
+ }
1154
+ .qt-chat-system-bar-chevron {
1155
+ flex-shrink: 0;
1156
+ width: 0.875rem;
1157
+ height: 0.875rem;
1158
+ opacity: 0.7;
1159
+ }
1160
+ .qt-chat-system-bar-expanded {
1161
+ margin-bottom: 0.25rem;
1162
+ }
1163
+ .qt-chat-announcement-group {
1164
+ display: flex;
1165
+ flex-wrap: wrap;
1166
+ gap: 0.375rem;
1167
+ width: 95%;
1168
+ max-width: var(--qt-chat-message-row-max-width);
1169
+ margin: 1.5rem auto 0;
1170
+ align-items: flex-start;
1171
+ }
1172
+ .qt-chat-announcement-chip {
1173
+ display: inline-flex;
1174
+ align-items: center;
1175
+ gap: 0.5rem;
1176
+ flex: 0 1 auto;
1177
+ min-width: 0;
1178
+ max-width: 100%;
1179
+ padding: 0.25rem 0.625rem;
1180
+ background: var(--qt-chat-system-bar-bg);
1181
+ color: var(--qt-chat-system-bar-fg);
1182
+ border: 1px solid var(--qt-chat-system-bar-border);
1183
+ border-radius: var(--radius-sm, 0.25rem);
1184
+ font-size: 0.75rem;
1185
+ line-height: 1.2;
1186
+ text-align: left;
1187
+ cursor: pointer;
1188
+ transition: background-color 120ms ease;
1189
+ }
1190
+ .qt-chat-announcement-chip:hover,
1191
+ .qt-chat-announcement-chip:focus-visible {
1192
+ background: var(--qt-chat-system-bar-hover-bg);
1193
+ outline: none;
1194
+ }
1195
+ .qt-chat-announcement-chip .qt-chat-system-bar-kind {
1196
+ flex: 0 1 auto;
1197
+ max-width: 22ch;
1198
+ }
1199
+ .qt-chat-announcement-dot {
1200
+ flex-shrink: 0;
1201
+ width: 0.5rem;
1202
+ height: 0.5rem;
1203
+ border-radius: 9999px;
1204
+ border: 1px solid transparent;
1205
+ }
1206
+ .qt-chat-announcement-dot-high {
1207
+ background: var(--qt-chat-announcement-dot-high);
1208
+ }
1209
+ .qt-chat-announcement-dot-medium {
1210
+ background: var(--qt-chat-announcement-dot-medium);
1211
+ }
1212
+ .qt-chat-announcement-dot-low {
1213
+ background: transparent;
1214
+ border-color: var(--qt-chat-announcement-dot-low);
1215
+ }
1216
+ .qt-chat-announcement-dot-outcome-success {
1217
+ background: var(--qt-alert-success-fg);
1218
+ }
1219
+ .qt-chat-announcement-dot-outcome-partial {
1220
+ background: var(--qt-alert-warning-fg);
1221
+ }
1222
+ .qt-chat-announcement-dot-outcome-failure {
1223
+ background: var(--qt-alert-error-fg);
1224
+ }
1225
+ .qt-chat-announcement-dot-outcome-info {
1226
+ background: var(--qt-alert-info-fg);
1227
+ }
1228
+ .qt-chat-system-bar.qt-pascal-result,
1229
+ .qt-chat-announcement-chip.qt-pascal-result {
1230
+ border-left-width: 3px;
1231
+ border-left-color: var(--qt-alert-info-border);
1232
+ padding-left: 0.75rem;
1233
+ }
1234
+ .qt-chat-system-bar.qt-pascal-result--success,
1235
+ .qt-chat-announcement-chip.qt-pascal-result--success {
1236
+ border-left-color: var(--qt-alert-success-border);
1237
+ }
1238
+ .qt-chat-system-bar.qt-pascal-result--partial,
1239
+ .qt-chat-announcement-chip.qt-pascal-result--partial {
1240
+ border-left-color: var(--qt-alert-warning-border);
1241
+ }
1242
+ .qt-chat-system-bar.qt-pascal-result--failure,
1243
+ .qt-chat-announcement-chip.qt-pascal-result--failure {
1244
+ border-left-color: var(--qt-alert-error-border);
1245
+ }
1246
+ .qt-chat-system-bar.qt-pascal-result--info,
1247
+ .qt-chat-announcement-chip.qt-pascal-result--info {
1248
+ border-left-color: var(--qt-alert-info-border);
1249
+ }
1106
1250
  .qt-chat-message-silent {
1107
1251
  background: var(--qt-chat-silent-bg);
1108
1252
  color: var(--qt-chat-silent-fg);
@@ -1375,6 +1519,9 @@ body {
1375
1519
  .qt-chat-composer-input::placeholder {
1376
1520
  color: var(--color-muted-foreground);
1377
1521
  }
1522
+ .qt-text {
1523
+ color: var(--color-foreground);
1524
+ }
1378
1525
  .qt-text-primary {
1379
1526
  color: var(--color-foreground);
1380
1527
  }
@@ -1987,6 +2134,11 @@ body {
1987
2134
  --qt-chat-wardrobe-bg: color-mix(in srgb, var(--qt-chat-assistant-bg) 60%, #8a6d1b 40%);
1988
2135
  --qt-chat-wardrobe-border: #8a6d1b;
1989
2136
  --qt-chat-wardrobe-label-fg: #d4b65c;
2137
+ --qt-chat-system-bar-bg: color-mix(in srgb, var(--qt-chat-assistant-bg) 60%, var(--color-muted) 40%);
2138
+ --qt-chat-system-bar-hover-bg: color-mix(in srgb, var(--qt-chat-assistant-bg) 45%, var(--color-muted) 55%);
2139
+ --qt-chat-announcement-dot-high: #e06a52;
2140
+ --qt-chat-announcement-dot-medium: var(--color-warning, #e3a94a);
2141
+ --qt-chat-announcement-dot-low: var(--color-muted-foreground);
1990
2142
  --qt-alert-success-bg: hsl(142 76% 36% / 0.2);
1991
2143
  --qt-alert-success-fg: hsl(142 76% 65%);
1992
2144
  --qt-alert-success-border: hsl(142 76% 36% / 0.5);
@@ -2031,6 +2183,9 @@ body {
2031
2183
  .qt-bg-surface {
2032
2184
  background-color: var(--color-background);
2033
2185
  }
2186
+ .qt-bg-surface-hover {
2187
+ background-color: var(--color-muted);
2188
+ }
2034
2189
  .qt-bg-surface-alt {
2035
2190
  background-color: var(--color-muted);
2036
2191
  }
package/dist/index.js CHANGED
@@ -1791,6 +1791,74 @@ var Chat = () => {
1791
1791
  ] }) })
1792
1792
  ] })
1793
1793
  ] }),
1794
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("section", { style: { marginBottom: "2rem" }, children: [
1795
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("h3", { style: { fontSize: "1.125rem", fontWeight: 700, marginBottom: "1rem", borderBottom: "1px solid var(--color-border)", paddingBottom: "0.5rem" }, children: "Staff Announcements" }),
1796
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { style: { color: "var(--color-muted-foreground)", marginBottom: "1rem" }, children: "Messages authored by a personified feature rather than a character. Each collapses to a one-line bar; a run of consecutive ones packs into a row of content-width chips. The leading dot carries an importance tier \u2014 filled for high and medium, hollow for low \u2014 so the eye lands on the file changes and arrivals and skims past the time calls." }),
1797
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "1rem", maxWidth: "32rem" }, children: [
1798
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("button", { type: "button", className: "qt-chat-system-bar", children: [
1799
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "qt-chat-announcement-dot qt-chat-announcement-dot-high", "aria-hidden": "true" }),
1800
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "qt-chat-system-bar-sender", children: "The Librarian" }),
1801
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "qt-chat-system-bar-kind", children: "edited by character" }),
1802
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "qt-chat-system-bar-time", children: "4:12 PM" }),
1803
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "qt-chat-system-bar-chevron", "aria-hidden": "true", children: "\u203A" })
1804
+ ] }),
1805
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "qt-chat-announcement-group", style: { width: "100%", margin: 0 }, children: [
1806
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("button", { type: "button", className: "qt-chat-announcement-chip", children: [
1807
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "qt-chat-announcement-dot qt-chat-announcement-dot-high", "aria-hidden": "true" }),
1808
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "qt-chat-system-bar-sender", children: "The Host" }),
1809
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "qt-chat-system-bar-kind", children: "status change" }),
1810
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "qt-chat-system-bar-time", children: "4:13 PM" }),
1811
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "qt-chat-system-bar-chevron", "aria-hidden": "true", children: "\u203A" })
1812
+ ] }),
1813
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("button", { type: "button", className: "qt-chat-announcement-chip", children: [
1814
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "qt-chat-announcement-dot qt-chat-announcement-dot-medium", "aria-hidden": "true" }),
1815
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "qt-chat-system-bar-sender", children: "The Lantern" }),
1816
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "qt-chat-system-bar-kind", children: "background" }),
1817
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "qt-chat-system-bar-time", children: "4:14 PM" }),
1818
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "qt-chat-system-bar-chevron", "aria-hidden": "true", children: "\u203A" })
1819
+ ] }),
1820
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("button", { type: "button", className: "qt-chat-announcement-chip", children: [
1821
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "qt-chat-announcement-dot qt-chat-announcement-dot-low", "aria-hidden": "true" }),
1822
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "qt-chat-system-bar-sender", children: "Prospero" }),
1823
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "qt-chat-system-bar-kind", children: "project information" }),
1824
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "qt-chat-system-bar-time", children: "4:14 PM" }),
1825
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "qt-chat-system-bar-chevron", "aria-hidden": "true", children: "\u203A" })
1826
+ ] })
1827
+ ] })
1828
+ ] })
1829
+ ] }),
1830
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("section", { style: { marginBottom: "2rem" }, children: [
1831
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("h3", { style: { fontSize: "1.125rem", fontWeight: 700, marginBottom: "1rem", borderBottom: "1px solid var(--color-border)", paddingBottom: "0.5rem" }, children: "Pascal Roll Outcomes" }),
1832
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("p", { style: { color: "var(--color-muted-foreground)", marginBottom: "1rem" }, children: [
1833
+ "The outcome of a custom tool (pseudo-tool) roll, announced by Pascal the Croupier. The tool's author assigns each outcome a semantic state \u2014 success, partial, failure, info \u2014 and the accent follows it, on the bubble and on the announcement bar above it alike. The bar swaps its importance dot for the outcome's own state, since a success has no business wearing the red dot a high tier would give it. Built on the ",
1834
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("code", { children: "--qt-alert-*" }),
1835
+ " families: the alpha-thin",
1836
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("code", { children: " -border" }),
1837
+ " tints for the leading edge, the solid ",
1838
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("code", { children: "-fg" }),
1839
+ " for the dot."
1840
+ ] }),
1841
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: { display: "flex", flexDirection: "column", gap: "1rem", maxWidth: "32rem" }, children: [
1842
+ ["success", "Pick the Lock", "The lock clicks open."],
1843
+ ["partial", "Pick the Lock", "The lock is giving way, but not yet."],
1844
+ ["failure", "Pick the Lock", "Still locked, and the corridor is no longer empty."],
1845
+ ["info", "Scan Hawking Radiation", "The detector reads 41 \xB5K."]
1846
+ ].map(([state, tool, message]) => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { children: [
1847
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("button", { type: "button", className: `qt-chat-system-bar qt-chat-system-bar-expanded qt-pascal-result qt-pascal-result--${state}`, children: [
1848
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: `qt-chat-announcement-dot qt-chat-announcement-dot-outcome-${state}`, "aria-hidden": "true" }),
1849
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "qt-chat-system-bar-sender", children: "Pascal" }),
1850
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "qt-chat-system-bar-kind", children: tool }),
1851
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "qt-chat-system-bar-time", children: "4:15 PM" }),
1852
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "qt-chat-system-bar-chevron", "aria-hidden": "true", children: "\u2227" })
1853
+ ] }),
1854
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: `qt-chat-message-body qt-chat-message-assistant qt-pascal-result qt-pascal-result--${state}`, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("p", { children: [
1855
+ "\u{1F3B2} ",
1856
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("strong", { children: tool }),
1857
+ " \u2014 ",
1858
+ message
1859
+ ] }) })
1860
+ ] }, state)) })
1861
+ ] }),
1794
1862
  /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("section", { style: { marginBottom: "2rem" }, children: [
1795
1863
  /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("h3", { style: { fontSize: "1.125rem", fontWeight: 700, marginBottom: "1rem", borderBottom: "1px solid var(--color-border)", paddingBottom: "0.5rem" }, children: "Wardrobe Action Notices" }),
1796
1864
  /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { style: { color: "var(--color-muted-foreground)", marginBottom: "1rem" }, children: "Inline summaries of outfit changes (equip, unequip, gift). Distinguished from whispers (dashed purple) and silent messages (dotted teal) by a double border and warm amber/gold tones." }),
package/dist/index.mjs CHANGED
@@ -21,7 +21,7 @@ import {
21
21
  ThemeComparison,
22
22
  Typography,
23
23
  Workspace
24
- } from "./chunk-XE53H6OD.mjs";
24
+ } from "./chunk-TD4WYZZI.mjs";
25
25
  import "./chunk-WUKYLWAZ.mjs";
26
26
 
27
27
  // src/preview.tsx
@@ -1728,6 +1728,74 @@ var Chat = () => {
1728
1728
  ] }) })
1729
1729
  ] })
1730
1730
  ] }),
1731
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("section", { style: { marginBottom: "2rem" }, children: [
1732
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("h3", { style: { fontSize: "1.125rem", fontWeight: 700, marginBottom: "1rem", borderBottom: "1px solid var(--color-border)", paddingBottom: "0.5rem" }, children: "Staff Announcements" }),
1733
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { style: { color: "var(--color-muted-foreground)", marginBottom: "1rem" }, children: "Messages authored by a personified feature rather than a character. Each collapses to a one-line bar; a run of consecutive ones packs into a row of content-width chips. The leading dot carries an importance tier \u2014 filled for high and medium, hollow for low \u2014 so the eye lands on the file changes and arrivals and skims past the time calls." }),
1734
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "1rem", maxWidth: "32rem" }, children: [
1735
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("button", { type: "button", className: "qt-chat-system-bar", children: [
1736
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "qt-chat-announcement-dot qt-chat-announcement-dot-high", "aria-hidden": "true" }),
1737
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "qt-chat-system-bar-sender", children: "The Librarian" }),
1738
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "qt-chat-system-bar-kind", children: "edited by character" }),
1739
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "qt-chat-system-bar-time", children: "4:12 PM" }),
1740
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "qt-chat-system-bar-chevron", "aria-hidden": "true", children: "\u203A" })
1741
+ ] }),
1742
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "qt-chat-announcement-group", style: { width: "100%", margin: 0 }, children: [
1743
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("button", { type: "button", className: "qt-chat-announcement-chip", children: [
1744
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "qt-chat-announcement-dot qt-chat-announcement-dot-high", "aria-hidden": "true" }),
1745
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "qt-chat-system-bar-sender", children: "The Host" }),
1746
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "qt-chat-system-bar-kind", children: "status change" }),
1747
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "qt-chat-system-bar-time", children: "4:13 PM" }),
1748
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "qt-chat-system-bar-chevron", "aria-hidden": "true", children: "\u203A" })
1749
+ ] }),
1750
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("button", { type: "button", className: "qt-chat-announcement-chip", children: [
1751
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "qt-chat-announcement-dot qt-chat-announcement-dot-medium", "aria-hidden": "true" }),
1752
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "qt-chat-system-bar-sender", children: "The Lantern" }),
1753
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "qt-chat-system-bar-kind", children: "background" }),
1754
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "qt-chat-system-bar-time", children: "4:14 PM" }),
1755
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "qt-chat-system-bar-chevron", "aria-hidden": "true", children: "\u203A" })
1756
+ ] }),
1757
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("button", { type: "button", className: "qt-chat-announcement-chip", children: [
1758
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "qt-chat-announcement-dot qt-chat-announcement-dot-low", "aria-hidden": "true" }),
1759
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "qt-chat-system-bar-sender", children: "Prospero" }),
1760
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "qt-chat-system-bar-kind", children: "project information" }),
1761
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "qt-chat-system-bar-time", children: "4:14 PM" }),
1762
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "qt-chat-system-bar-chevron", "aria-hidden": "true", children: "\u203A" })
1763
+ ] })
1764
+ ] })
1765
+ ] })
1766
+ ] }),
1767
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("section", { style: { marginBottom: "2rem" }, children: [
1768
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("h3", { style: { fontSize: "1.125rem", fontWeight: 700, marginBottom: "1rem", borderBottom: "1px solid var(--color-border)", paddingBottom: "0.5rem" }, children: "Pascal Roll Outcomes" }),
1769
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("p", { style: { color: "var(--color-muted-foreground)", marginBottom: "1rem" }, children: [
1770
+ "The outcome of a custom tool (pseudo-tool) roll, announced by Pascal the Croupier. The tool's author assigns each outcome a semantic state \u2014 success, partial, failure, info \u2014 and the accent follows it, on the bubble and on the announcement bar above it alike. The bar swaps its importance dot for the outcome's own state, since a success has no business wearing the red dot a high tier would give it. Built on the ",
1771
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("code", { children: "--qt-alert-*" }),
1772
+ " families: the alpha-thin",
1773
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("code", { children: " -border" }),
1774
+ " tints for the leading edge, the solid ",
1775
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("code", { children: "-fg" }),
1776
+ " for the dot."
1777
+ ] }),
1778
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { style: { display: "flex", flexDirection: "column", gap: "1rem", maxWidth: "32rem" }, children: [
1779
+ ["success", "Pick the Lock", "The lock clicks open."],
1780
+ ["partial", "Pick the Lock", "The lock is giving way, but not yet."],
1781
+ ["failure", "Pick the Lock", "Still locked, and the corridor is no longer empty."],
1782
+ ["info", "Scan Hawking Radiation", "The detector reads 41 \xB5K."]
1783
+ ].map(([state, tool, message]) => /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { children: [
1784
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("button", { type: "button", className: `qt-chat-system-bar qt-chat-system-bar-expanded qt-pascal-result qt-pascal-result--${state}`, children: [
1785
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: `qt-chat-announcement-dot qt-chat-announcement-dot-outcome-${state}`, "aria-hidden": "true" }),
1786
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "qt-chat-system-bar-sender", children: "Pascal" }),
1787
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "qt-chat-system-bar-kind", children: tool }),
1788
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "qt-chat-system-bar-time", children: "4:15 PM" }),
1789
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "qt-chat-system-bar-chevron", "aria-hidden": "true", children: "\u2227" })
1790
+ ] }),
1791
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: `qt-chat-message-body qt-chat-message-assistant qt-pascal-result qt-pascal-result--${state}`, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("p", { children: [
1792
+ "\u{1F3B2} ",
1793
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("strong", { children: tool }),
1794
+ " \u2014 ",
1795
+ message
1796
+ ] }) })
1797
+ ] }, state)) })
1798
+ ] }),
1731
1799
  /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("section", { style: { marginBottom: "2rem" }, children: [
1732
1800
  /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("h3", { style: { fontSize: "1.125rem", fontWeight: 700, marginBottom: "1rem", borderBottom: "1px solid var(--color-border)", paddingBottom: "0.5rem" }, children: "Wardrobe Action Notices" }),
1733
1801
  /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { style: { color: "var(--color-muted-foreground)", marginBottom: "1rem" }, children: "Inline summaries of outfit changes (equip, unequip, gift). Distinguished from whispers (dashed purple) and silent messages (dotted teal) by a double border and warm amber/gold tones." }),
@@ -21,7 +21,7 @@ import {
21
21
  ThemeComparison,
22
22
  Typography,
23
23
  Workspace
24
- } from "../chunk-XE53H6OD.mjs";
24
+ } from "../chunk-TD4WYZZI.mjs";
25
25
  import "../chunk-WUKYLWAZ.mjs";
26
26
  export {
27
27
  Avatars,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quilltap/theme-storybook",
3
- "version": "1.0.49",
3
+ "version": "1.0.51",
4
4
  "description": "Storybook preset and stories for developing Quilltap theme plugins",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -348,6 +348,21 @@
348
348
  --qt-chat-wardrobe-border: #c4a24e;
349
349
  --qt-chat-wardrobe-label-fg: #9a7d2e;
350
350
 
351
+ /* Chat: System-message collapsed bar — thin one-line summary for Staff-authored messages */
352
+ --qt-chat-system-bar-bg: color-mix(in srgb, var(--qt-chat-assistant-bg) 70%, var(--color-muted) 30%);
353
+ --qt-chat-system-bar-fg: var(--color-muted-foreground);
354
+ --qt-chat-system-bar-border: var(--color-border);
355
+ --qt-chat-system-bar-hover-bg: color-mix(in srgb, var(--qt-chat-assistant-bg) 55%, var(--color-muted) 45%);
356
+ --qt-chat-system-bar-sender-fg: var(--color-foreground);
357
+
358
+ /* Chat: Announcement importance dots — high (red), medium (amber), low (hollow grey).
359
+ All three track theme tokens so the dots stay on-palette: high follows the theme
360
+ destructive, medium the theme warning, low the muted foreground. The hardcoded
361
+ amber/red remain as fallbacks for any theme that omits the token. */
362
+ --qt-chat-announcement-dot-high: var(--color-destructive, #b4452e);
363
+ --qt-chat-announcement-dot-medium: var(--color-warning, #d08a1e);
364
+ --qt-chat-announcement-dot-low: var(--color-muted-foreground);
365
+
351
366
  /* Chat composer variables */
352
367
  --qt-chat-composer-bg: var(--color-background);
353
368
  --qt-chat-composer-border: var(--color-border);
@@ -1191,6 +1206,214 @@
1191
1206
  border-left-color: var(--qt-alert-info-border);
1192
1207
  }
1193
1208
 
1209
+ /* ==========================================================================
1210
+ CHAT — STAFF ANNOUNCEMENTS
1211
+ Messages authored by a personified feature (the Librarian, the Host, Pascal
1212
+ the Croupier, …) rather than by a character. They summarise to a one-line
1213
+ bar, and a run of consecutive ones packs into a row of content-width chips.
1214
+ ========================================================================== */
1215
+
1216
+ /**
1217
+ * Collapsed bar for Staff-authored messages.
1218
+ * Single-line summary: dot · sender name · kind · timestamp · chevron.
1219
+ * Click to expand into the regular message body.
1220
+ */
1221
+ .qt-chat-system-bar {
1222
+ display: flex;
1223
+ align-items: center;
1224
+ gap: 0.625rem;
1225
+ width: 100%;
1226
+ padding: 0.25rem 0.625rem;
1227
+ margin: 0.125rem 0;
1228
+ background: var(--qt-chat-system-bar-bg);
1229
+ color: var(--qt-chat-system-bar-fg);
1230
+ border: 1px solid var(--qt-chat-system-bar-border);
1231
+ border-radius: var(--radius-sm, 0.25rem);
1232
+ font-size: 0.75rem;
1233
+ line-height: 1.2;
1234
+ text-align: left;
1235
+ cursor: pointer;
1236
+ transition: background-color 120ms ease;
1237
+ }
1238
+
1239
+ .qt-chat-system-bar:hover,
1240
+ .qt-chat-system-bar:focus-visible {
1241
+ background: var(--qt-chat-system-bar-hover-bg);
1242
+ outline: none;
1243
+ }
1244
+
1245
+ .qt-chat-system-bar-sender {
1246
+ color: var(--qt-chat-system-bar-sender-fg);
1247
+ font-weight: 600;
1248
+ white-space: nowrap;
1249
+ }
1250
+
1251
+ .qt-chat-system-bar-kind {
1252
+ flex: 1 1 auto;
1253
+ min-width: 0;
1254
+ font-style: italic;
1255
+ overflow: hidden;
1256
+ text-overflow: ellipsis;
1257
+ white-space: nowrap;
1258
+ }
1259
+
1260
+ .qt-chat-system-bar-time {
1261
+ color: var(--qt-chat-system-bar-fg);
1262
+ opacity: 0.75;
1263
+ white-space: nowrap;
1264
+ }
1265
+
1266
+ .qt-chat-system-bar-chevron {
1267
+ flex-shrink: 0;
1268
+ width: 0.875rem;
1269
+ height: 0.875rem;
1270
+ opacity: 0.7;
1271
+ }
1272
+
1273
+ /**
1274
+ * Variant rendered at the top of an *expanded* Staff-authored message, giving
1275
+ * the reader a prominent click target to re-collapse it.
1276
+ */
1277
+ .qt-chat-system-bar-expanded {
1278
+ margin-bottom: 0.25rem;
1279
+ }
1280
+
1281
+ /**
1282
+ * Packed announcement chips. A run of consecutive *collapsed* Staff messages
1283
+ * renders as one flex-wrapping row of content-width chips instead of a
1284
+ * full-width bar each.
1285
+ */
1286
+ .qt-chat-announcement-group {
1287
+ display: flex;
1288
+ flex-wrap: wrap;
1289
+ gap: 0.375rem;
1290
+ width: 95%;
1291
+ max-width: var(--qt-chat-message-row-max-width);
1292
+ margin: 1.5rem auto 0;
1293
+ align-items: flex-start;
1294
+ }
1295
+
1296
+ /**
1297
+ * A single collapsed announcement, sized to its content (never full width).
1298
+ * Reuses the -sender / -kind / -time / -chevron element classes above; only the
1299
+ * -kind sizing differs (see the override below).
1300
+ */
1301
+ .qt-chat-announcement-chip {
1302
+ display: inline-flex;
1303
+ align-items: center;
1304
+ gap: 0.5rem;
1305
+ flex: 0 1 auto;
1306
+ min-width: 0;
1307
+ max-width: 100%;
1308
+ padding: 0.25rem 0.625rem;
1309
+ background: var(--qt-chat-system-bar-bg);
1310
+ color: var(--qt-chat-system-bar-fg);
1311
+ border: 1px solid var(--qt-chat-system-bar-border);
1312
+ border-radius: var(--radius-sm, 0.25rem);
1313
+ font-size: 0.75rem;
1314
+ line-height: 1.2;
1315
+ text-align: left;
1316
+ cursor: pointer;
1317
+ transition: background-color 120ms ease;
1318
+ }
1319
+
1320
+ .qt-chat-announcement-chip:hover,
1321
+ .qt-chat-announcement-chip:focus-visible {
1322
+ background: var(--qt-chat-system-bar-hover-bg);
1323
+ outline: none;
1324
+ }
1325
+
1326
+ /* Inside a chip the kind must not greedily fill the row; cap it so a long kind
1327
+ doesn't dominate a packed row. */
1328
+ .qt-chat-announcement-chip .qt-chat-system-bar-kind {
1329
+ flex: 0 1 auto;
1330
+ max-width: 22ch;
1331
+ }
1332
+
1333
+ /**
1334
+ * Importance dot before the sender name. Filled for high/medium, hollow for
1335
+ * low, so the eye lands on what matters and skims past the low-noise chatter.
1336
+ */
1337
+ .qt-chat-announcement-dot {
1338
+ flex-shrink: 0;
1339
+ width: 0.5rem;
1340
+ height: 0.5rem;
1341
+ border-radius: 9999px;
1342
+ border: 1px solid transparent;
1343
+ }
1344
+
1345
+ .qt-chat-announcement-dot-high {
1346
+ background: var(--qt-chat-announcement-dot-high);
1347
+ }
1348
+
1349
+ .qt-chat-announcement-dot-medium {
1350
+ background: var(--qt-chat-announcement-dot-medium);
1351
+ }
1352
+
1353
+ .qt-chat-announcement-dot-low {
1354
+ background: transparent;
1355
+ border-color: var(--qt-chat-announcement-dot-low);
1356
+ }
1357
+
1358
+ /**
1359
+ * Outcome dot for a Pascal roll announcement, which replaces the importance dot:
1360
+ * a roll has a verdict of its own — success / partial / failure / info — and
1361
+ * that verdict is what the reader is looking for. Filled with the solid
1362
+ * --qt-alert-*-fg (the -border tints are alpha-thin and vanish at 8px); the
1363
+ * bar's leading accent below uses the -border tints, as .qt-pascal-result does.
1364
+ */
1365
+ .qt-chat-announcement-dot-outcome-success {
1366
+ background: var(--qt-alert-success-fg);
1367
+ }
1368
+
1369
+ .qt-chat-announcement-dot-outcome-partial {
1370
+ background: var(--qt-alert-warning-fg);
1371
+ }
1372
+
1373
+ .qt-chat-announcement-dot-outcome-failure {
1374
+ background: var(--qt-alert-error-fg);
1375
+ }
1376
+
1377
+ .qt-chat-announcement-dot-outcome-info {
1378
+ background: var(--qt-alert-info-fg);
1379
+ }
1380
+
1381
+ /**
1382
+ * The bar/chip of a Pascal roll wears the same .qt-pascal-result accent as the
1383
+ * outcome bubble itself, so one outcome reads identically wherever it is shown.
1384
+ *
1385
+ * These compound selectors only restate that accent: .qt-pascal-result is
1386
+ * declared above, and both wrappers set `border` and `padding` SHORTHANDS at
1387
+ * equal specificity, so the plain family would lose on source order. Nothing
1388
+ * new is styled here — change the accent itself at .qt-pascal-result.
1389
+ */
1390
+ .qt-chat-system-bar.qt-pascal-result,
1391
+ .qt-chat-announcement-chip.qt-pascal-result {
1392
+ border-left-width: 3px;
1393
+ border-left-color: var(--qt-alert-info-border);
1394
+ padding-left: 0.75rem;
1395
+ }
1396
+
1397
+ .qt-chat-system-bar.qt-pascal-result--success,
1398
+ .qt-chat-announcement-chip.qt-pascal-result--success {
1399
+ border-left-color: var(--qt-alert-success-border);
1400
+ }
1401
+
1402
+ .qt-chat-system-bar.qt-pascal-result--partial,
1403
+ .qt-chat-announcement-chip.qt-pascal-result--partial {
1404
+ border-left-color: var(--qt-alert-warning-border);
1405
+ }
1406
+
1407
+ .qt-chat-system-bar.qt-pascal-result--failure,
1408
+ .qt-chat-announcement-chip.qt-pascal-result--failure {
1409
+ border-left-color: var(--qt-alert-error-border);
1410
+ }
1411
+
1412
+ .qt-chat-system-bar.qt-pascal-result--info,
1413
+ .qt-chat-announcement-chip.qt-pascal-result--info {
1414
+ border-left-color: var(--qt-alert-info-border);
1415
+ }
1416
+
1194
1417
  /**
1195
1418
  * Silent message — inner thoughts and actions from character in silent mode.
1196
1419
  * Distinguished from whispers by a dotted border (vs dashed) and sage/teal tones.
@@ -1526,6 +1749,10 @@
1526
1749
  UTILITY CLASSES
1527
1750
  ========================================================================== */
1528
1751
 
1752
+ .qt-text {
1753
+ color: var(--color-foreground);
1754
+ }
1755
+
1529
1756
  .qt-text-primary {
1530
1757
  color: var(--color-foreground);
1531
1758
  }
@@ -2347,6 +2574,17 @@
2347
2574
  --qt-chat-wardrobe-border: #8a6d1b;
2348
2575
  --qt-chat-wardrobe-label-fg: #d4b65c;
2349
2576
 
2577
+ /* Chat: System-message collapsed bar — dark mode */
2578
+ --qt-chat-system-bar-bg: color-mix(in srgb, var(--qt-chat-assistant-bg) 60%, var(--color-muted) 40%);
2579
+ --qt-chat-system-bar-hover-bg: color-mix(in srgb, var(--qt-chat-assistant-bg) 45%, var(--color-muted) 55%);
2580
+
2581
+ /* Chat: Announcement importance dots — brighter on dark for contrast. Medium tracks
2582
+ the theme warning (themes ship brightened dark-mode warning values); the amber stays
2583
+ as a fallback. High keeps a fixed bright red so it reads on dark surfaces. */
2584
+ --qt-chat-announcement-dot-high: #e06a52;
2585
+ --qt-chat-announcement-dot-medium: var(--color-warning, #e3a94a);
2586
+ --qt-chat-announcement-dot-low: var(--color-muted-foreground);
2587
+
2350
2588
  /* Alert tokens - brighter, more saturated for dark backgrounds */
2351
2589
  --qt-alert-success-bg: hsl(142 76% 36% / 0.2);
2352
2590
  --qt-alert-success-fg: hsl(142 76% 65%);
@@ -2409,6 +2647,10 @@
2409
2647
  background-color: var(--color-background);
2410
2648
  }
2411
2649
 
2650
+ .qt-bg-surface-hover {
2651
+ background-color: var(--color-muted);
2652
+ }
2653
+
2412
2654
  .qt-bg-surface-alt {
2413
2655
  background-color: var(--color-muted);
2414
2656
  }
@@ -282,6 +282,88 @@ export const Chat: React.FC = () => {
282
282
  </div>
283
283
  </section>
284
284
 
285
+ {/* Staff Announcements */}
286
+ <section style={{ marginBottom: '2rem' }}>
287
+ <h3 style={{ fontSize: '1.125rem', fontWeight: 700, marginBottom: '1rem', borderBottom: '1px solid var(--color-border)', paddingBottom: '0.5rem' }}>
288
+ Staff Announcements
289
+ </h3>
290
+ <p style={{ color: 'var(--color-muted-foreground)', marginBottom: '1rem' }}>
291
+ Messages authored by a personified feature rather than a character. Each collapses to a one-line
292
+ bar; a run of consecutive ones packs into a row of content-width chips. The leading dot carries an
293
+ importance tier &mdash; filled for high and medium, hollow for low &mdash; so the eye lands on the
294
+ file changes and arrivals and skims past the time calls.
295
+ </p>
296
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '1rem', maxWidth: '32rem' }}>
297
+ <button type="button" className="qt-chat-system-bar">
298
+ <span className="qt-chat-announcement-dot qt-chat-announcement-dot-high" aria-hidden="true" />
299
+ <span className="qt-chat-system-bar-sender">The Librarian</span>
300
+ <span className="qt-chat-system-bar-kind">edited by character</span>
301
+ <span className="qt-chat-system-bar-time">4:12 PM</span>
302
+ <span className="qt-chat-system-bar-chevron" aria-hidden="true">&rsaquo;</span>
303
+ </button>
304
+
305
+ <div className="qt-chat-announcement-group" style={{ width: '100%', margin: 0 }}>
306
+ <button type="button" className="qt-chat-announcement-chip">
307
+ <span className="qt-chat-announcement-dot qt-chat-announcement-dot-high" aria-hidden="true" />
308
+ <span className="qt-chat-system-bar-sender">The Host</span>
309
+ <span className="qt-chat-system-bar-kind">status change</span>
310
+ <span className="qt-chat-system-bar-time">4:13 PM</span>
311
+ <span className="qt-chat-system-bar-chevron" aria-hidden="true">&rsaquo;</span>
312
+ </button>
313
+ <button type="button" className="qt-chat-announcement-chip">
314
+ <span className="qt-chat-announcement-dot qt-chat-announcement-dot-medium" aria-hidden="true" />
315
+ <span className="qt-chat-system-bar-sender">The Lantern</span>
316
+ <span className="qt-chat-system-bar-kind">background</span>
317
+ <span className="qt-chat-system-bar-time">4:14 PM</span>
318
+ <span className="qt-chat-system-bar-chevron" aria-hidden="true">&rsaquo;</span>
319
+ </button>
320
+ <button type="button" className="qt-chat-announcement-chip">
321
+ <span className="qt-chat-announcement-dot qt-chat-announcement-dot-low" aria-hidden="true" />
322
+ <span className="qt-chat-system-bar-sender">Prospero</span>
323
+ <span className="qt-chat-system-bar-kind">project information</span>
324
+ <span className="qt-chat-system-bar-time">4:14 PM</span>
325
+ <span className="qt-chat-system-bar-chevron" aria-hidden="true">&rsaquo;</span>
326
+ </button>
327
+ </div>
328
+ </div>
329
+ </section>
330
+
331
+ {/* Pascal Roll Outcomes */}
332
+ <section style={{ marginBottom: '2rem' }}>
333
+ <h3 style={{ fontSize: '1.125rem', fontWeight: 700, marginBottom: '1rem', borderBottom: '1px solid var(--color-border)', paddingBottom: '0.5rem' }}>
334
+ Pascal Roll Outcomes
335
+ </h3>
336
+ <p style={{ color: 'var(--color-muted-foreground)', marginBottom: '1rem' }}>
337
+ The outcome of a custom tool (pseudo-tool) roll, announced by Pascal the Croupier. The tool&apos;s
338
+ author assigns each outcome a semantic state &mdash; success, partial, failure, info &mdash; and the
339
+ accent follows it, on the bubble and on the announcement bar above it alike. The bar swaps its
340
+ importance dot for the outcome&apos;s own state, since a success has no business wearing the red dot a
341
+ high tier would give it. Built on the <code>--qt-alert-*</code> families: the alpha-thin
342
+ <code> -border</code> tints for the leading edge, the solid <code>-fg</code> for the dot.
343
+ </p>
344
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '1rem', maxWidth: '32rem' }}>
345
+ {([
346
+ ['success', 'Pick the Lock', 'The lock clicks open.'],
347
+ ['partial', 'Pick the Lock', 'The lock is giving way, but not yet.'],
348
+ ['failure', 'Pick the Lock', 'Still locked, and the corridor is no longer empty.'],
349
+ ['info', 'Scan Hawking Radiation', 'The detector reads 41 µK.'],
350
+ ] as const).map(([state, tool, message]) => (
351
+ <div key={state}>
352
+ <button type="button" className={`qt-chat-system-bar qt-chat-system-bar-expanded qt-pascal-result qt-pascal-result--${state}`}>
353
+ <span className={`qt-chat-announcement-dot qt-chat-announcement-dot-outcome-${state}`} aria-hidden="true" />
354
+ <span className="qt-chat-system-bar-sender">Pascal</span>
355
+ <span className="qt-chat-system-bar-kind">{tool}</span>
356
+ <span className="qt-chat-system-bar-time">4:15 PM</span>
357
+ <span className="qt-chat-system-bar-chevron" aria-hidden="true">&and;</span>
358
+ </button>
359
+ <div className={`qt-chat-message-body qt-chat-message-assistant qt-pascal-result qt-pascal-result--${state}`}>
360
+ <p>🎲 <strong>{tool}</strong> &mdash; {message}</p>
361
+ </div>
362
+ </div>
363
+ ))}
364
+ </div>
365
+ </section>
366
+
285
367
  {/* Wardrobe Action Notices */}
286
368
  <section style={{ marginBottom: '2rem' }}>
287
369
  <h3 style={{ fontSize: '1.125rem', fontWeight: 700, marginBottom: '1rem', borderBottom: '1px solid var(--color-border)', paddingBottom: '0.5rem' }}>