@quilltap/theme-storybook 1.0.49 → 1.0.50

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);
@@ -1987,6 +2131,11 @@ body {
1987
2131
  --qt-chat-wardrobe-bg: color-mix(in srgb, var(--qt-chat-assistant-bg) 60%, #8a6d1b 40%);
1988
2132
  --qt-chat-wardrobe-border: #8a6d1b;
1989
2133
  --qt-chat-wardrobe-label-fg: #d4b65c;
2134
+ --qt-chat-system-bar-bg: color-mix(in srgb, var(--qt-chat-assistant-bg) 60%, var(--color-muted) 40%);
2135
+ --qt-chat-system-bar-hover-bg: color-mix(in srgb, var(--qt-chat-assistant-bg) 45%, var(--color-muted) 55%);
2136
+ --qt-chat-announcement-dot-high: #e06a52;
2137
+ --qt-chat-announcement-dot-medium: var(--color-warning, #e3a94a);
2138
+ --qt-chat-announcement-dot-low: var(--color-muted-foreground);
1990
2139
  --qt-alert-success-bg: hsl(142 76% 36% / 0.2);
1991
2140
  --qt-alert-success-fg: hsl(142 76% 65%);
1992
2141
  --qt-alert-success-border: hsl(142 76% 36% / 0.5);
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.50",
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.
@@ -2347,6 +2570,17 @@
2347
2570
  --qt-chat-wardrobe-border: #8a6d1b;
2348
2571
  --qt-chat-wardrobe-label-fg: #d4b65c;
2349
2572
 
2573
+ /* Chat: System-message collapsed bar — dark mode */
2574
+ --qt-chat-system-bar-bg: color-mix(in srgb, var(--qt-chat-assistant-bg) 60%, var(--color-muted) 40%);
2575
+ --qt-chat-system-bar-hover-bg: color-mix(in srgb, var(--qt-chat-assistant-bg) 45%, var(--color-muted) 55%);
2576
+
2577
+ /* Chat: Announcement importance dots — brighter on dark for contrast. Medium tracks
2578
+ the theme warning (themes ship brightened dark-mode warning values); the amber stays
2579
+ as a fallback. High keeps a fixed bright red so it reads on dark surfaces. */
2580
+ --qt-chat-announcement-dot-high: #e06a52;
2581
+ --qt-chat-announcement-dot-medium: var(--color-warning, #e3a94a);
2582
+ --qt-chat-announcement-dot-low: var(--color-muted-foreground);
2583
+
2350
2584
  /* Alert tokens - brighter, more saturated for dark backgrounds */
2351
2585
  --qt-alert-success-bg: hsl(142 76% 36% / 0.2);
2352
2586
  --qt-alert-success-fg: hsl(142 76% 65%);
@@ -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' }}>