viberoom 0.5.8 โ 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -0
- package/dist/agent-health.js +52 -0
- package/dist/context.js +6 -0
- package/dist/duration.js +12 -0
- package/dist/hub.js +13 -2
- package/dist/launcher.js +19 -2
- package/dist/main.js +77 -34
- package/dist/mcp-skills-server.js +143 -0
- package/dist/persona.js +167 -46
- package/dist/quotes.js +41 -0
- package/dist/recipes.js +28 -1
- package/dist/room-design.js +205 -0
- package/dist/room.js +388 -150
- package/dist/rows.js +19 -0
- package/dist/server.js +304 -27
- package/dist/skills.js +28 -2
- package/dist/templates.js +17 -0
- package/dist/update.js +32 -2
- package/dist/viewer.js +69 -2
- package/dist/ws.js +175 -0
- package/package.json +2 -1
- package/ui/app.css +348 -246
- package/ui/app.js +1422 -345
- package/ui/avatars.js +131 -30
- package/ui/components.css +140 -0
- package/ui/components.js +342 -0
- package/ui/icons.js +11 -0
- package/ui/index.html +58 -36
- package/ui/theme.css +457 -180
- package/ui/tokens.js +620 -0
- package/ui/ui.js +113 -0
package/ui/avatars.js
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
(() => {
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
|
+
const tokens = () => globalThis.VIBEROOM_TOKENS.current.elements.participant;
|
|
6
|
+
|
|
5
7
|
function hash(text) {
|
|
6
8
|
let h = 2166136261;
|
|
7
9
|
for (const ch of String(text)) {
|
|
@@ -36,8 +38,8 @@
|
|
|
36
38
|
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${s} ${s}" width="${s}" height="${s}" role="img" aria-label="${escapeAttr(name)}">
|
|
37
39
|
<defs><linearGradient id="${id}" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="${c1}"/><stop offset="1" stop-color="${c2}"/></linearGradient></defs>
|
|
38
40
|
<circle cx="${s / 2}" cy="${s / 2}" r="${s / 2}" fill="url(#${id})"/>
|
|
39
|
-
<circle cx="${s / 2}" cy="${s * 0.36}" r="${s * 0.34}" fill="
|
|
40
|
-
<text x="50%" y="53%" dominant-baseline="middle" text-anchor="middle" font-family="system-ui, 'Segoe UI Emoji', sans-serif" font-size="${fontSize}" font-weight="700" fill="
|
|
41
|
+
<circle cx="${s / 2}" cy="${s * 0.36}" r="${s * 0.34}" fill="${tokens().avatarGloss}" opacity="0.10"/>
|
|
42
|
+
<text x="50%" y="53%" dominant-baseline="middle" text-anchor="middle" font-family="system-ui, 'Segoe UI Emoji', sans-serif" font-size="${fontSize}" font-weight="700" fill="${tokens().avatarLabelInk}">${escapeText(label)}</text>
|
|
41
43
|
</svg>`;
|
|
42
44
|
}
|
|
43
45
|
|
|
@@ -50,13 +52,13 @@
|
|
|
50
52
|
|
|
51
53
|
function avatarHtml(participant, size, options) {
|
|
52
54
|
const opts = options || {};
|
|
53
|
-
const color = participant.color ||
|
|
55
|
+
const color = participant.color || tokens().avatarDefault;
|
|
54
56
|
const s = size || 40;
|
|
55
57
|
const emoji = participant.avatar;
|
|
56
58
|
const label = emoji ? emoji : initials(participant.name);
|
|
57
59
|
const fontSize = Math.round(emoji ? s * 0.56 : s * 0.38);
|
|
58
60
|
const radius = Math.round(s * 0.32);
|
|
59
|
-
const svg = `<span class="av-tile" role="img" aria-label="${escapeAttr(participant.name)}" style="background:color-mix(in srgb, ${escapeAttr(color)} 16%,
|
|
61
|
+
const svg = `<span class="av-tile" role="img" aria-label="${escapeAttr(participant.name)}" style="background:color-mix(in srgb, ${escapeAttr(color)} 16%, ${tokens().avatarBlend});color:${escapeAttr(color)};font-size:${fontSize}px;border-radius:${radius}px">${escapeText(label)}</span>`;
|
|
60
62
|
const status = opts.status ? `<span class="avatar-status status-${escapeAttr(participant.status || "idle")}"></span>` : "";
|
|
61
63
|
let badge = "";
|
|
62
64
|
if (opts.vendor && participant.kind === "agent") {
|
|
@@ -67,6 +69,7 @@
|
|
|
67
69
|
? `<span class="avatar-badge" title="${title}"><img src="${escapeAttr(recipe.icon)}" alt="" onerror="this.replaceWith(document.createTextNode('${letter}'))"></span>`
|
|
68
70
|
: `<span class="avatar-badge" title="${title}">${letter}</span>`;
|
|
69
71
|
}
|
|
72
|
+
if (opts.muted && participant.kind === "agent" && window.Icons) badge = `<span class="avatar-badge muted" title="muted: receives no prompts">${window.Icons.svg("mute")}</span>`;
|
|
70
73
|
return `<span class="avatar" style="width:${size}px;height:${size}px">${svg}${badge}${status}</span>`;
|
|
71
74
|
}
|
|
72
75
|
|
|
@@ -77,37 +80,135 @@
|
|
|
77
80
|
"๐", "โญ", "๐ฅ", "๐", "๐ต", "๐", "๐ง", "๐ธ", "๐", "๐ธ", "๐ง ", "๐ฏ", "๐งฉ", "๐", "๐", "โ",
|
|
78
81
|
];
|
|
79
82
|
|
|
80
|
-
|
|
83
|
+
const EMOJI_NAMES = {
|
|
84
|
+
"๐ญ": "theatre masks drama roles", "๐": "rocket launch ship", "๐งช": "test tube experiment lab", "๐ ๏ธ": "hammer and wrench tools",
|
|
85
|
+
"๐จ": "palette art design paint", "๐": "books library docs", "๐ง ": "brain mind thinking", "๐ฌ": "speech bubble chat talk",
|
|
86
|
+
"๐ฌ": "microscope science research", "๐ฏ": "target goal focus aim", "๐": "octopus github", "โ": "coffee cup break cafe",
|
|
87
|
+
"๐": "rainbow colors", "๐๏ธ": "construction crane building site", "๐ฎ": "game controller gaming play", "๐ฅ": "fire hot flame",
|
|
88
|
+
"๐งฉ": "puzzle piece", "๐": "chart up growth trending", "๐บ๏ธ": "world map", "๐ง": "headphones audio music",
|
|
89
|
+
"๐ฑ": "seedling plant grow sprout", "๐ ": "house home", "๐ธ": "flying saucer ufo", "๐งญ": "compass navigate direction",
|
|
90
|
+
"๐งโ๐ป": "technologist developer coder programmer laptop", "โ๏ธ": "hammer and pick tools forge", "๐จ": "hammer build", "๐ง": "wrench fix repair",
|
|
91
|
+
"๐ฉ": "nut and bolt hardware", "โ๏ธ": "gear settings cog", "๐งฐ": "toolbox tools kit", "๐ช": "screwdriver",
|
|
92
|
+
"๐งฑ": "brick wall", "๐ญ": "factory plant", "๐": "electric plug power", "๐ฅ๏ธ": "desktop computer monitor screen",
|
|
93
|
+
"๐ป": "laptop computer", "โจ๏ธ": "keyboard typing", "๐ค": "robot bot ai", "๐": "bug insect caterpillar",
|
|
94
|
+
"๐": "lady beetle ladybug bug", "โก": "lightning bolt zap fast electric", "๐": "battery energy charge", "๐": "bar chart data statistics",
|
|
95
|
+
"๐": "chart down decline", "๐งฎ": "abacus math calculate", "๐": "magnifying glass search find zoom", "๐ญ": "telescope explore astronomy",
|
|
96
|
+
"๐งฌ": "dna genetics biology", "โ๏ธ": "alembic chemistry", "๐งฒ": "magnet attract", "๐ก": "satellite antenna signal radar",
|
|
97
|
+
"๐ฐ๏ธ": "satellite space orbit", "๐๏ธ": "file cabinet archive storage", "๐พ": "floppy disk save storage", "๐๏ธ": "card file box archive",
|
|
98
|
+
"๐": "globe web internet network", "๐": "link chain url", "โ๏ธ": "cloud weather sky", "โ๏ธ": "writing hand write author",
|
|
99
|
+
"๐": "memo note pencil notes", "๐": "open book read", "๐ฐ": "newspaper news", "๐": "scroll document parchment",
|
|
100
|
+
"๐": "paperclip attach", "๐": "pushpin pin", "๐๏ธ": "card index dividers files folders", "๐ท๏ธ": "label tag price",
|
|
101
|
+
"โ๏ธ": "envelope mail email letter", "๐ฃ": "megaphone announce loud", "๐ฃ๏ธ": "speaking head talk speech", "๐ค": "handshake deal agreement",
|
|
102
|
+
"๐ฅ": "busts silhouette people team group", "๐๏ธ": "paintbrush paint brush", "๐ผ๏ธ": "framed picture image painting", "๐ท": "camera photo",
|
|
103
|
+
"๐ฌ": "clapper board movie film", "๐ฅ": "movie camera video", "๐ต": "musical note music", "๐น": "piano keys music",
|
|
104
|
+
"๐ธ": "guitar music rock", "๐ค": "microphone sing karaoke", "๐ฒ": "game die dice random", "โ๏ธ": "chess pawn strategy",
|
|
105
|
+
"๐งธ": "teddy bear toy", "๐ช": "circus tent", "๐": "gift present wrapped", "๐
": "calendar date schedule",
|
|
106
|
+
"โฐ": "alarm clock time", "โณ": "hourglass waiting time sand", "๐ณ๏ธ": "ballot box vote election", "โ๏ธ": "balance scale justice law",
|
|
107
|
+
"๐งพ": "receipt invoice bill", "๐ฐ": "money bag budget cash", "๐ฆ": "package box parcel delivery", "๐": "delivery truck shipping",
|
|
108
|
+
"๐": "shopping cart", "๐ฆ": "bank finance", "๐ข": "office building company", "๐": "graduation cap learn study",
|
|
109
|
+
"๐ซ": "school", "๐": "chequered flag finish race", "๐": "trophy win award cup", "๐": "gem stone diamond",
|
|
110
|
+
"๐": "locked with key security", "๐": "key access password", "๐ก๏ธ": "shield protect security defense", "๐จ": "police light alarm alert siren",
|
|
111
|
+
"๐ฆ": "traffic light", "๐งฏ": "fire extinguisher", "๐ฉบ": "stethoscope health doctor medical", "๐งน": "broom clean sweep",
|
|
112
|
+
"โป๏ธ": "recycle recycling", "๐งโ๐ณ": "cook chef kitchen", "๐งโ๐ฌ": "scientist lab", "๐งโ๐จ": "artist painter",
|
|
113
|
+
"๐งโ๐ซ": "teacher", "๐งโ๐": "astronaut space", "๐ต๏ธ": "detective spy investigate", "๐ง": "mage wizard magic",
|
|
114
|
+
"๐ฆ": "owl wise night bird", "๐ฆ": "fox", "๐ผ": "panda", "๐": "honeybee bee",
|
|
115
|
+
"๐ข": "turtle slow tortoise", "๐ฌ": "dolphin", "๐ฆ": "unicorn", "๐ฒ": "dragon face",
|
|
116
|
+
"๐": "earth globe world europe africa", "๐": "crescent moon night", "โญ": "star", "๐": "water wave ocean sea",
|
|
117
|
+
"๐๏ธ": "snow capped mountain", "๐๏ธ": "desert island beach", "๐ฒ": "evergreen tree forest pine", "๐": "four leaf clover luck",
|
|
118
|
+
"๐ธ": "cherry blossom flower spring", "๐": "pizza", "๐": "red apple fruit", "โจ": "sparkles magic shiny",
|
|
119
|
+
"๐ก": "light bulb idea", "๐ฎ": "crystal ball fortune", "๐ช": "magic wand", "โค๏ธ": "red heart love",
|
|
120
|
+
"๐ฏ": "tiger face", "๐ธ": "frog face", "๐ฉโ๐ป": "woman technologist developer coder", "๐บ": "wolf face",
|
|
121
|
+
"๐ง": "penguin", "๐ฆ": "lion face", "๐จ": "koala", "๐พ": "alien monster space invader pixel",
|
|
122
|
+
"๐ฑ": "cat face", "๐ถ": "dog face", "๐ฆ": "raccoon", "๐ฆ": "butterfly",
|
|
123
|
+
"๐ฆฉ": "flamingo", "๐ฆ": "t-rex dinosaur", "๐ณ": "spouting whale", "๐ฆญ": "seal",
|
|
124
|
+
"๐น": "hamster", "๐ฆ": "hedgehog", "๐ป": "bear face", "๐ฎ": "cow face",
|
|
125
|
+
"๐ต": "monkey face", "๐งโ๐": "firefighter", "๐งโโ๏ธ": "health worker doctor nurse", "๐งโโ๏ธ": "pilot",
|
|
126
|
+
"๐ง": "vampire", "๐ง": "merperson mermaid", "๐ง": "genie", "๐ฆธ": "superhero",
|
|
127
|
+
"๐ฅท": "ninja", "๐ค ": "cowboy hat face", "๐ฝ": "alien", "๐ป": "ghost",
|
|
128
|
+
"๐": "jack-o-lantern pumpkin halloween", "๐ต": "cactus",
|
|
129
|
+
"๐": "grinning face smile happy", "๐": "grinning face smiling eyes happy", "๐": "face with tears of joy laugh lol", "๐": "slightly smiling face",
|
|
130
|
+
"๐": "winking face wink", "๐": "smiling face heart eyes love", "๐ค": "thinking face hmm", "๐": "smiling face sunglasses cool",
|
|
131
|
+
"๐ฅณ": "partying face party celebrate", "๐
": "grinning face sweat nervous", "๐ข": "crying face sad tear", "๐ก": "pouting face angry mad",
|
|
132
|
+
"๐": "thumbs up yes like ok", "๐": "thumbs down no dislike", "๐": "waving hand hello bye", "๐": "folded hands thanks please pray",
|
|
133
|
+
"๐": "clapping hands applause bravo", "๐ช": "flexed biceps strong muscle", "๐": "party popper celebrate tada", "๐": "purple heart",
|
|
134
|
+
"โ
": "check mark button done yes", "โ": "cross mark no wrong", "โ ๏ธ": "warning caution", "๐คซ": "shushing face quiet hush",
|
|
135
|
+
};
|
|
136
|
+
function emojiName(emoji) {
|
|
137
|
+
return EMOJI_NAMES[emoji] || "";
|
|
138
|
+
}
|
|
139
|
+
function emojiMatches(emoji, query) {
|
|
140
|
+
return emoji === query || emojiName(emoji).includes(query);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function searchableGrid(list, current, onPick, none) {
|
|
81
144
|
const wrap = document.createElement("div");
|
|
82
|
-
wrap.className = "
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
145
|
+
wrap.className = "emoji-pick";
|
|
146
|
+
const search = document.createElement("input");
|
|
147
|
+
search.type = "search";
|
|
148
|
+
search.className = "emoji-search";
|
|
149
|
+
search.placeholder = "Search by nameโฆ";
|
|
150
|
+
search.autocomplete = "off";
|
|
151
|
+
search.spellcheck = false;
|
|
152
|
+
search.setAttribute("aria-label", "Search emoji by name");
|
|
153
|
+
const grid = document.createElement("div");
|
|
154
|
+
grid.className = "avatar-picker";
|
|
155
|
+
let value = current || "";
|
|
156
|
+
const button = (text, title, cls, onClick) => {
|
|
157
|
+
const b = document.createElement("button");
|
|
158
|
+
b.type = "button";
|
|
159
|
+
b.textContent = text;
|
|
160
|
+
if (title) b.title = title;
|
|
161
|
+
b.className = cls;
|
|
162
|
+
b.addEventListener("click", onClick);
|
|
163
|
+
return b;
|
|
164
|
+
};
|
|
165
|
+
const render = () => {
|
|
166
|
+
grid.innerHTML = "";
|
|
167
|
+
const q = search.value.trim().toLowerCase();
|
|
168
|
+
if (none && !q) {
|
|
169
|
+
grid.appendChild(button(none.label, none.title, "none" + (!value ? " selected" : ""), () => {
|
|
170
|
+
value = "";
|
|
171
|
+
onPick("");
|
|
172
|
+
render();
|
|
173
|
+
}));
|
|
174
|
+
}
|
|
175
|
+
const shown = q ? list.filter((e) => emojiMatches(e, q)) : list;
|
|
176
|
+
for (const e of shown) {
|
|
177
|
+
grid.appendChild(button(e, emojiName(e), e === value ? "selected" : "", () => {
|
|
178
|
+
value = e;
|
|
101
179
|
onPick(e);
|
|
102
|
-
render(
|
|
103
|
-
});
|
|
104
|
-
wrap.appendChild(b);
|
|
180
|
+
render();
|
|
181
|
+
}));
|
|
105
182
|
}
|
|
183
|
+
if (!shown.length) {
|
|
184
|
+
const empty = document.createElement("div");
|
|
185
|
+
empty.className = "emoji-none";
|
|
186
|
+
empty.textContent = `No emoji called "${q}" here.`;
|
|
187
|
+
grid.appendChild(empty);
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
for (const type of ["input", "change"]) {
|
|
191
|
+
search.addEventListener(type, (e) => {
|
|
192
|
+
e.stopPropagation();
|
|
193
|
+
if (type === "input") render();
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
search.addEventListener("keydown", (e) => {
|
|
197
|
+
e.stopPropagation();
|
|
198
|
+
if (e.key === "Enter") e.preventDefault();
|
|
199
|
+
});
|
|
200
|
+
wrap.append(search, grid);
|
|
201
|
+
render();
|
|
202
|
+
wrap.setValue = (v) => {
|
|
203
|
+
value = v || "";
|
|
204
|
+
render();
|
|
106
205
|
};
|
|
107
|
-
render(current || "");
|
|
108
|
-
wrap.setValue = render;
|
|
109
206
|
return wrap;
|
|
110
207
|
}
|
|
111
208
|
|
|
112
|
-
|
|
209
|
+
function pickerElement(current, onPick) {
|
|
210
|
+
return searchableGrid(GALLERY, current, onPick, { label: "Aa", title: "Initials" });
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
window.Avatars = { avatarSvg, avatarHtml, initials, pickerElement, searchableGrid, emojiName, GALLERY };
|
|
113
214
|
})();
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/* viberoom - Copyright (c) 2026 Todor Rusev - AGPL-3.0-or-later; see LICENSE */
|
|
2
|
+
[data-ui="row-button"] { display: inline-grid; place-items: center; width: var(--row-button-size); height: var(--row-button-size); padding: 0; border: 0; border-radius: var(--row-button-radius); background: var(--row-button-bg); color: var(--row-button-ink); cursor: pointer; transition: background var(--t-fast), color var(--t-fast), opacity var(--t-fast); }
|
|
3
|
+
[data-ui="row-button"] .i { width: var(--row-button-icon); height: var(--row-button-icon); }
|
|
4
|
+
[data-ui="row-button"]:is(:hover, [data-state="hover"]):not(:disabled) { background: var(--row-button-hover-bg); color: var(--row-button-hover-ink); }
|
|
5
|
+
[data-ui="row-button"]:is(:active, [data-state="active"]):not(:disabled) { transform: translateY(1px); }
|
|
6
|
+
[data-ui="row-button"]:is(:disabled, [data-state="disabled"]) { opacity: var(--row-button-disabled-opacity); cursor: default; }
|
|
7
|
+
[data-ui="hub-row"] { display: inline-flex; flex-direction: row; align-items: center; gap: 8px; max-width: 80%; padding: 2px 10px; border: 0; background: none; color: var(--hub-row-ink); font: inherit; font-size: var(--fs-xs); font-weight: 700; text-align: left; }
|
|
8
|
+
[data-ui="hub-row"] .hush-face { font-size: var(--hub-row-face-size); line-height: 1; }
|
|
9
|
+
[data-ui="hub-row"][data-tone="attention"], [data-ui="hub-row"][data-tone="hush"] { color: var(--hub-row-attention-ink); font-weight: 800; }
|
|
10
|
+
[data-ui="hub-row"][data-tone="error"] { color: var(--hub-row-error-ink); font-weight: 800; }
|
|
11
|
+
[data-ui="hub-row"][data-ref] { padding: 6px 14px 6px 8px; border-radius: var(--r-pill); background: var(--hub-row-action-bg); color: var(--hub-row-action-ink); font-size: var(--fs-sm); font-weight: 800; cursor: pointer; box-shadow: var(--edge); transition: background var(--t-fast); }
|
|
12
|
+
[data-ui="hub-row"][data-ref]:is(:hover, [data-state="hover"]) { background: var(--hub-row-action-hover-bg); }
|
|
13
|
+
[data-ui="button"] { display: inline-flex; align-items: center; justify-content: center; gap: 8px; border: 0; background: var(--btn-bg); color: var(--btn-ink); border-radius: var(--r-sm); height: var(--btn-h); padding: 0 16px; font-weight: 800; font-size: var(--btn-fs); line-height: 1; white-space: nowrap; cursor: pointer; transition: background var(--t-fast), color var(--t-fast), transform var(--t-fast) var(--ease-out), box-shadow var(--t-fast); }
|
|
14
|
+
[data-ui="button"] .i { width: 16px; height: 16px; }
|
|
15
|
+
[data-ui="button"]:is(:hover, [data-state="hover"]):not(:disabled) { background: var(--btn-hover-bg); color: var(--btn-hover-ink); }
|
|
16
|
+
[data-ui="button"]:is(:active, [data-state="active"]):not(:disabled) { transform: translateY(1px); }
|
|
17
|
+
[data-ui="button"]:is(:disabled, [data-state="disabled"]) { opacity: var(--btn-disabled-opacity); cursor: default; }
|
|
18
|
+
[data-ui="button"][data-kind="primary"] { background: var(--grad-primary); color: var(--btn-on-primary); box-shadow: var(--shadow-primary); }
|
|
19
|
+
[data-ui="button"][data-kind="primary"]:is(:hover, [data-state="hover"]):not(:disabled) { background: var(--grad-primary); color: var(--btn-on-primary); filter: brightness(1.05); transform: translateY(-1px); }
|
|
20
|
+
[data-ui="button"][data-kind="primary"]:is(:active, [data-state="active"]):not(:disabled) { transform: translateY(1px); }
|
|
21
|
+
[data-ui="button"][data-kind="secondary"] { background: var(--btn-secondary-bg); color: var(--btn-ink); box-shadow: var(--shadow-tile); }
|
|
22
|
+
[data-ui="button"][data-kind="secondary"]:is(:hover, [data-state="hover"]):not(:disabled) { background: var(--btn-secondary-bg); color: var(--btn-hover-ink); }
|
|
23
|
+
[data-ui="button"][data-kind="soft"] { background: var(--btn-soft-bg); color: var(--btn-hover-ink); }
|
|
24
|
+
[data-ui="button"][data-kind="soft"]:is(:hover, [data-state="hover"]):not(:disabled) { background: var(--btn-soft-hover-bg); }
|
|
25
|
+
[data-ui="button"][data-kind="ghost"] { background: transparent; color: var(--btn-ghost-ink); font-weight: 700; }
|
|
26
|
+
[data-ui="button"][data-kind="ghost"]:is(:hover, [data-state="hover"]):not(:disabled) { background: var(--btn-ghost-hover-bg); color: var(--btn-hover-ink); }
|
|
27
|
+
[data-ui="button"][data-kind="danger"] { background: var(--btn-danger-bg); color: var(--btn-danger-ink); }
|
|
28
|
+
[data-ui="button"][data-kind="danger"]:is(:hover, [data-state="hover"]):not(:disabled) { background: var(--btn-danger-hover-bg); color: var(--btn-danger-ink); }
|
|
29
|
+
[data-ui="button"][data-kind="danger-solid"] { background: var(--btn-danger-ink); color: var(--btn-danger-solid-ink); box-shadow: var(--btn-danger-solid-shadow); }
|
|
30
|
+
[data-ui="button"][data-kind="danger-solid"]:is(:hover, [data-state="hover"]):not(:disabled) { background: var(--btn-danger-solid-hover-bg); color: var(--btn-danger-solid-ink); }
|
|
31
|
+
[data-ui="button"][data-kind="dark"] { background: var(--btn-dark-bg); color: var(--btn-dark-ink); border-radius: 7px; }
|
|
32
|
+
[data-ui="button"][data-kind="dark"]:is(:hover, [data-state="hover"]):not(:disabled) { background: var(--btn-dark-hover-bg); color: var(--btn-dark-ink); }
|
|
33
|
+
[data-ui="button"][data-kind="warn"] { background: transparent; color: var(--btn-warn-ink); letter-spacing: 0.02em; border-radius: var(--r-pill); }
|
|
34
|
+
[data-ui="button"][data-kind="warn"]:is(:hover, [data-state="hover"]):not(:disabled) { background: var(--btn-warn-hover-bg); color: var(--btn-warn-ink); }
|
|
35
|
+
[data-ui="button"][data-kind="inverse"] { background: var(--btn-inverse-bg); color: var(--btn-inverse-ink); border-radius: 10px; }
|
|
36
|
+
[data-ui="button"][data-kind="inverse"]:is(:hover, [data-state="hover"]):not(:disabled) { background: var(--btn-inverse-hover-bg); color: var(--btn-inverse-ink); }
|
|
37
|
+
[data-ui="button"][data-kind="link"] { background: none; color: var(--btn-link-ink); height: auto; padding: 2px 0; border-radius: 0; }
|
|
38
|
+
[data-ui="button"][data-kind="link"]:is(:hover, [data-state="hover"]):not(:disabled) { background: none; color: var(--btn-link-ink); text-decoration: underline; }
|
|
39
|
+
[data-ui="button"][data-kind="ok"] { background: var(--btn-ok-bg); color: var(--btn-ok-ink); border-radius: 10px; }
|
|
40
|
+
[data-ui="button"][data-kind="ok"]:is(:hover, [data-state="hover"]):not(:disabled) { background: var(--btn-ok-hover-bg); color: var(--btn-ok-ink); transform: translateY(-1px); }
|
|
41
|
+
[data-ui="button"][data-kind="paper"] { background: var(--btn-paper-bg); color: var(--btn-paper-ink); border-radius: 10px; }
|
|
42
|
+
[data-ui="button"][data-kind="paper"]:is(:hover, [data-state="hover"]):not(:disabled) { background: var(--btn-paper-hover-bg); color: var(--btn-paper-ink); transform: translateY(-1px); }
|
|
43
|
+
[data-ui="button"][data-size="sm"] { height: var(--btn-h-sm); padding: 0 12px; font-size: var(--btn-fs-sm); border-radius: 10px; }
|
|
44
|
+
[data-ui="button"][data-size="sm"] .i { width: 15px; height: 15px; }
|
|
45
|
+
[data-ui="button"][data-size="xs"] { height: var(--btn-h-xs); padding: 0 9px; font-size: var(--fs-xs); border-radius: 7px; }
|
|
46
|
+
[data-ui="button"][data-size="xs"] .i { width: 13px; height: 13px; }
|
|
47
|
+
[data-ui="button"][data-size="lg"] { height: var(--btn-h-lg); padding: 0 22px; font-size: var(--btn-fs-lg); border-radius: 14px; }
|
|
48
|
+
[data-ui="button"][data-size="cta"] { height: var(--btn-h-cta); border-radius: var(--r-md); font-size: var(--btn-fs-cta); padding: 0 18px; }
|
|
49
|
+
[data-ui="button"][data-full] { width: 100%; }
|
|
50
|
+
[data-ui="button"][data-pill] { border-radius: var(--r-pill); }
|
|
51
|
+
[data-ui="button"][data-state="loading"] { position: relative; color: transparent !important; pointer-events: none; }
|
|
52
|
+
[data-ui="button"][data-state="loading"]::after { content: ""; position: absolute; width: 15px; height: 15px; border-radius: 50%; border: 2px solid var(--btn-spinner-track); border-top-color: var(--btn-spinner-head); animation: spin 0.8s linear infinite; }
|
|
53
|
+
[data-ui="button"][data-state="loading"]:not([data-kind="primary"]):not([data-kind="danger-solid"])::after { border-color: var(--btn-spinner-track-quiet); border-top-color: var(--btn-spinner-head-quiet); }
|
|
54
|
+
[data-ui="icon-button"] { width: var(--icon-button-size); height: var(--icon-button-size); border-radius: 12px; border: 0; background: transparent; color: var(--icon-button-ink); display: inline-flex; align-items: center; justify-content: center; padding: 0; flex: none; cursor: pointer; transition: background var(--t-fast), color var(--t-fast), transform var(--t-fast) var(--ease-out); }
|
|
55
|
+
[data-ui="icon-button"] .i { width: var(--icon-button-icon); height: var(--icon-button-icon); }
|
|
56
|
+
[data-ui="icon-button"]:is(:hover, [data-state="hover"]):not(:disabled) { background: var(--icon-button-hover-bg); color: var(--icon-button-hover-ink); }
|
|
57
|
+
[data-ui="icon-button"]:is(:active, [data-state="active"]):not(:disabled) { transform: translateY(1px); }
|
|
58
|
+
[data-ui="icon-button"]:is(:disabled, [data-state="disabled"]) { opacity: var(--icon-button-disabled-opacity); cursor: default; }
|
|
59
|
+
[data-ui="icon-button"][data-size="sm"] { width: var(--icon-button-size-sm); height: var(--icon-button-size-sm); border-radius: 10px; }
|
|
60
|
+
[data-ui="icon-button"][data-size="sm"] .i { width: var(--icon-button-icon-sm); height: var(--icon-button-icon-sm); }
|
|
61
|
+
[data-ui="icon-button"][data-kind="primary"] { width: var(--icon-button-size-primary); height: var(--icon-button-size-primary); border-radius: 14px; background: var(--grad-primary); color: var(--btn-on-primary); box-shadow: var(--shadow-primary); }
|
|
62
|
+
[data-ui="icon-button"][data-kind="primary"]:is(:hover, [data-state="hover"]):not(:disabled) { color: var(--btn-on-primary); background: var(--grad-primary); filter: brightness(1.05); }
|
|
63
|
+
[data-ui="icon-button"][data-kind="danger"] { color: var(--btn-danger-ink); }
|
|
64
|
+
[data-ui="icon-button"][data-kind="danger"]:is(:hover, [data-state="hover"]):not(:disabled) { background: var(--btn-danger-bg); color: var(--btn-danger-ink); }
|
|
65
|
+
[data-ui="icon-button"][data-size="xs"] { width: var(--icon-button-size-xs); height: var(--icon-button-size-xs); border-radius: 6px; }
|
|
66
|
+
[data-ui="icon-button"][data-size="xs"] .i { width: var(--icon-button-icon-xs); height: var(--icon-button-icon-xs); }
|
|
67
|
+
[data-ui="icon-button"][data-kind="ghost"] { background: transparent; color: var(--icon-button-ghost-ink); }
|
|
68
|
+
[data-ui="icon-button"][data-kind="inline"] { background: var(--icon-button-inline-bg); color: var(--icon-button-inline-ink); vertical-align: middle; position: relative; top: -1px; margin-left: 5px; }
|
|
69
|
+
[data-ui="icon-button"][data-kind="inline"]:is(:hover, [data-state="hover"]):not(:disabled) { background: var(--icon-button-hover-bg-strong); color: var(--btn-on-primary); }
|
|
70
|
+
[data-ui="icon-button"][data-kind="inline"][data-state="on"] { background: var(--icon-button-inline-on-bg); color: var(--icon-button-inline-on-ink); }
|
|
71
|
+
[data-ui="choice"] { display: inline-flex; align-items: center; gap: 6px; border: 2px solid transparent; background: var(--choice-bg); color: var(--choice-ink); border-radius: var(--r-pill); padding: 0 12px; height: var(--choice-h); font: inherit; font-size: var(--fs-sm); font-weight: 800; white-space: nowrap; max-width: 100%; overflow: hidden; text-overflow: ellipsis; cursor: pointer; transition: background var(--t-fast), color var(--t-fast), border-color var(--t-fast); }
|
|
72
|
+
[data-ui="choice"]:is(:hover, [data-state="hover"]) { background: var(--choice-hover-bg); color: var(--choice-on-ink); }
|
|
73
|
+
[data-ui="choice"][data-state="on"] { background: var(--choice-hover-bg); color: var(--choice-on-ink); border-color: var(--choice-on-border); }
|
|
74
|
+
[data-ui="choice"][data-quiet] { color: var(--choice-quiet-ink); font-weight: 700; }
|
|
75
|
+
[data-ui="badge"] { display: inline-flex; align-items: center; gap: 4px; font-size: var(--fs-xs); padding: 3px 10px; border-radius: var(--r-pill); background: var(--badge-bg); color: var(--badge-ink); font-weight: 800; white-space: nowrap; vertical-align: middle; }
|
|
76
|
+
[data-ui="badge"] .dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
|
|
77
|
+
[data-ui="badge"][data-tone="ready"] { background: var(--st-ready); color: var(--st-ready-ink); }
|
|
78
|
+
[data-ui="badge"][data-tone="waiting"] { background: var(--st-waiting); color: var(--st-waiting-ink); }
|
|
79
|
+
[data-ui="badge"][data-tone="thinking"] { background: var(--st-thinking); color: var(--st-thinking-ink); }
|
|
80
|
+
[data-ui="badge"][data-tone="writing"] { background: var(--st-writing); color: var(--st-writing-ink); }
|
|
81
|
+
[data-ui="badge"][data-tone="error"] { background: var(--st-error); color: var(--st-error-ink); }
|
|
82
|
+
[data-ui="badge"][data-tone="asleep"] { background: var(--st-asleep); color: var(--st-asleep-ink); }
|
|
83
|
+
[data-ui="badge"][data-tone="attention"] { background: var(--badge-attention-bg); color: var(--badge-attention-ink); }
|
|
84
|
+
[data-ui="badge"][data-tone="muted"] { background: var(--badge-muted-bg); color: var(--badge-muted-ink); }
|
|
85
|
+
[data-ui="badge"][data-tone="outline"] { background: transparent; border: 2px solid var(--badge-outline-border); color: var(--badge-outline-ink); }
|
|
86
|
+
[data-ui="badge"]:is([data-tone="thinking"], [data-tone="writing"]) .dot { animation: pulse 1.2s ease-in-out infinite; }
|
|
87
|
+
[data-ui="badge"][data-size="xs"] { font-size: var(--badge-fs-xs); padding: 1px 7px; }
|
|
88
|
+
[data-ui="chip"] { display: inline-flex; align-items: center; gap: 5px; font: inherit; font-size: var(--fs-xs); font-weight: 800; background: var(--chip-bg); color: var(--chip-ink); border: 0; border-radius: var(--r-pill); padding: 4px 10px; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: middle; text-align: left; }
|
|
89
|
+
[data-ui="chip"] .i { width: 13px; height: 13px; flex: none; }
|
|
90
|
+
[data-ui="chip"][data-tone="ready"] { background: var(--st-ready); color: var(--st-ready-ink); }
|
|
91
|
+
[data-ui="chip"][data-tone="error"] { background: var(--st-error); color: var(--st-error-ink); }
|
|
92
|
+
[data-ui="chip"][data-tone="thinking"] { background: var(--st-thinking); color: var(--st-thinking-ink); }
|
|
93
|
+
[data-ui="chip"][data-tone="waiting"] { background: var(--st-waiting); color: var(--st-waiting-ink); }
|
|
94
|
+
[data-ui="chip"][data-button] { cursor: pointer; transition: background var(--t-fast); }
|
|
95
|
+
[data-ui="chip"][data-button]:not([data-tone]):is(:hover, [data-state="hover"]) { background: var(--chip-hover-bg); }
|
|
96
|
+
[data-ui="file-card"] { border-radius: 12px; overflow: hidden; background: var(--file-card-bg); box-shadow: var(--edge); }
|
|
97
|
+
[data-ui="file-card"] > .head { display: flex; align-items: center; gap: 8px; padding: 6px 10px; background: var(--file-card-head-bg); color: var(--file-card-head-ink); font-size: var(--fs-xs); font-weight: 800; }
|
|
98
|
+
[data-ui="file-card"] > .head .name { display: inline-flex; align-items: center; gap: 5px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
99
|
+
[data-ui="file-card"] > .head .name .i { width: 13px; height: 13px; flex: none; }
|
|
100
|
+
[data-ui="file-card"] > .head .lines { color: var(--file-card-head-meta); font-weight: 700; }
|
|
101
|
+
[data-ui="file-card"] > .head [data-ui="button"] { margin-left: auto; }
|
|
102
|
+
[data-ui="file-card"] > .body { background: transparent; color: var(--file-card-ink); }
|
|
103
|
+
[data-ui="file-card"] > .body .code-view { border-radius: 0; max-height: 320px; }
|
|
104
|
+
[data-ui="file-card"] > .body .note { margin: 8px 10px; color: var(--file-card-note-ink); font-size: var(--fs-sm); font-weight: 700; line-height: 1.45; }
|
|
105
|
+
[data-ui="file-card"][data-kind="image"] > .body { padding: 8px 10px 10px; background: var(--file-card-image-body-bg); }
|
|
106
|
+
[data-ui="file-card"][data-kind="image"] > .body img { display: block; margin: 0 auto; max-width: 100%; max-height: 420px; border-radius: 8px; cursor: zoom-in; background: var(--file-card-image-bg); }
|
|
107
|
+
[data-ui="tool-call"] { display: inline-flex; flex-direction: column; max-width: 100%; min-width: 0; }
|
|
108
|
+
[data-ui="tool-call"] > [data-ui="chip"]::after { content: "โพ"; margin-left: auto; padding-left: 8px; opacity: 0.55; transition: transform var(--t-fast); }
|
|
109
|
+
[data-ui="tool-call"][data-state="open"] { flex-basis: 100%; }
|
|
110
|
+
[data-ui="tool-call"][data-state="open"] > [data-ui="chip"] { width: 100%; border-radius: 12px 12px 0 0; padding: 6px 12px; white-space: normal; }
|
|
111
|
+
[data-ui="tool-call"][data-state="open"] > [data-ui="chip"]::after { transform: rotate(180deg); }
|
|
112
|
+
[data-ui="tool-call"] > .body { margin: 0; padding: 8px 10px 10px; background: var(--tool-call-body-bg); border: 2px solid var(--tool-call-pending-bg); border-top: 0; border-radius: 0 0 12px 12px; font-size: var(--tool-call-fs); max-height: 340px; overflow: auto; }
|
|
113
|
+
[data-ui="tool-call"][data-status="completed"] > .body { border-color: var(--tool-call-ready-bg); }
|
|
114
|
+
[data-ui="tool-call"][data-status="failed"] > .body { border-color: var(--tool-call-error-bg); }
|
|
115
|
+
[data-ui="tool-call"][data-status="in_progress"] > .body { border-color: var(--tool-call-thinking-bg); }
|
|
116
|
+
[data-ui="tool-call"] .sec + .sec { margin-top: 8px; }
|
|
117
|
+
[data-ui="tool-call"] .sec b { display: block; font-size: var(--tool-call-label-fs); font-weight: 800; letter-spacing: 0.04em; text-transform: uppercase; color: var(--tool-call-pending-ink); }
|
|
118
|
+
[data-ui="tool-call"][data-status="completed"] .sec b { color: var(--tool-call-ready-ink); }
|
|
119
|
+
[data-ui="tool-call"][data-status="failed"] .sec b { color: var(--tool-call-error-ink); }
|
|
120
|
+
[data-ui="tool-call"][data-status="in_progress"] .sec b { color: var(--tool-call-thinking-ink); }
|
|
121
|
+
[data-ui="tool-call"] .sec.quiet { color: var(--tool-call-quiet-ink); font-style: italic; }
|
|
122
|
+
[data-ui="tool-call"] .sec pre { margin: 3px 0 0; padding: 6px 8px; border-radius: 8px; background: var(--tool-call-pre-bg); color: var(--tool-call-pre-ink); white-space: pre-wrap; word-break: break-word; font-size: var(--tool-call-pre-fs); line-height: 1.45; }
|
|
123
|
+
[data-ui="tool-fold"] { flex-basis: 100%; min-width: 0; }
|
|
124
|
+
[data-ui="tool-fold"] > summary { list-style: none; display: inline-flex; align-items: center; gap: 6px; cursor: pointer; user-select: none; font-size: var(--tool-fold-fs); font-weight: 800; color: var(--tool-fold-ink); background: var(--tool-fold-bg); border-radius: var(--r-pill); padding: 4px 12px; transition: background var(--t-fast), color var(--t-fast); }
|
|
125
|
+
[data-ui="tool-fold"] > summary::-webkit-details-marker { display: none; }
|
|
126
|
+
[data-ui="tool-fold"] > summary:hover, [data-ui="tool-fold"][data-state="hover"] > summary { background: var(--tool-fold-hover-bg); color: var(--tool-fold-hover-ink); }
|
|
127
|
+
[data-ui="tool-fold"] > summary .i { width: 13px; height: 13px; }
|
|
128
|
+
[data-ui="tool-fold"] > summary::after { content: "โพ"; opacity: 0.55; transition: transform var(--t-fast); }
|
|
129
|
+
[data-ui="tool-fold"][open] > summary::after { transform: rotate(180deg); }
|
|
130
|
+
[data-ui="tool-fold"] > summary .failed { color: var(--tool-fold-failed-ink); }
|
|
131
|
+
[data-ui="tool-fold"] > .list { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
|
|
132
|
+
[data-ui="ask-card"] { background: var(--ask-card-bg); color: var(--ask-card-ink); border-radius: 12px; padding: 10px 12px; font-size: var(--ask-card-fs); font-weight: 600; }
|
|
133
|
+
[data-ui="ask-card"][data-state="resolved"] { opacity: var(--ask-card-resolved-opacity); }
|
|
134
|
+
[data-ui="ask-card"] > .title .kind { font-size: var(--ask-card-kind-fs); color: var(--ask-card-quiet-ink); }
|
|
135
|
+
[data-ui="ask-card"] > .input { margin: 6px 0; max-height: 160px; overflow: auto; font-size: var(--ask-card-input-fs); }
|
|
136
|
+
[data-ui="ask-card"] > .choices { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 6px; }
|
|
137
|
+
[data-ui="ask-card"] > .choices .outcome { color: var(--ask-card-quiet-ink); font-size: var(--ask-card-outcome-fs); }
|
|
138
|
+
[data-ui="reply-note"] { display: flex; align-items: flex-start; gap: 6px; font-size: var(--reply-note-fs); font-weight: 700; color: var(--reply-note-ink); background: var(--reply-note-bg); border-radius: 10px; padding: 5px 10px; }
|
|
139
|
+
[data-ui="reply-note"] .i { width: 14px; height: 14px; flex: none; margin-top: 1px; }
|
|
140
|
+
[data-ui="reply-note"][data-tone="attention"] { color: var(--reply-note-attention-ink); background: var(--reply-note-attention-bg); }
|