@gemboss/ui 0.39.0 → 0.41.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/CHANGELOG.md +285 -0
- package/README.md +638 -3
- package/catalog/editor.html +15 -13
- package/catalog/index.html +5235 -1145
- package/gemboss-ui.css +3 -3
- package/package.json +8 -2
- package/parts/components.css +2 -2
- package/parts/core.css +1 -1
- package/parts/shell.css +2 -2
- package/src/assistant/chat-markdown.ts +7 -4
- package/src/assistant.css +1 -1
- package/src/brand-gem.tsx +19 -0
- package/src/brand.tsx +4 -7
- package/src/chat-plain.js +2 -2
- package/src/editor/controls.tsx +50 -14
- package/src/editor/index.ts +3 -3
- package/src/editor/panel.tsx +10 -4
- package/src/editor/repeater.tsx +113 -27
- package/src/editor/swatch.ts +20 -0
- package/src/editor-plain.js +1 -1
- package/src/editor-repeater.css +1 -1
- package/src/editor.css +1 -1
- package/src/gemboss-field.css +1 -1
- package/src/icons.tsx +11 -0
- package/src/index.ts +12 -1
- package/src/reader-dialog.css +1 -0
- package/src/reader-dialog.tsx +26 -0
- package/src/service-switcher.css +1 -1
- package/src/service-switcher.tsx +108 -31
- package/src/shell.css +1 -1
- package/src/site.css +1 -0
- package/src/site.tsx +50 -0
- package/src/team-chat-data.ts +79 -0
- package/src/team-chat-plain.js +1 -0
- package/src/team-chat.css +1 -0
- package/src/team-chat.tsx +825 -0
- package/src/ui.css +1 -1
package/src/service-switcher.tsx
CHANGED
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
import "./service-switcher.css";
|
|
23
23
|
import React, { useEffect, useId, useMemo, useRef, useState } from "react";
|
|
24
24
|
import { useModalDialog } from "./dialog";
|
|
25
|
-
import { Icon } from "./icons";
|
|
26
|
-
import { GEM_SERVICES,
|
|
25
|
+
import { Icon, type IconName } from "./icons";
|
|
26
|
+
import { GEM_SERVICES, SERVICE_GROUPS, type GemService, type ServiceId, type ServiceTint } from "./services";
|
|
27
27
|
|
|
28
28
|
/** GemFactory's services page: every service and its health. */
|
|
29
29
|
export const SERVICES_HEALTH_URL = "https://gemfactory.ops.gemboss.ai/services";
|
|
@@ -56,6 +56,50 @@ export interface ServiceSwitcherProps {
|
|
|
56
56
|
className?: string;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
/**
|
|
60
|
+
* One tile of a `Switcher` (0.40.0). The service tiles are a mark (an icon) + a name + a line; a tile with `media` is a
|
|
61
|
+
* card with an illustration on top (a community, a workspace: Chris 20/10/2026, "kèm hình ảnh minh hoạ, tên và
|
|
62
|
+
* description … full popup như các dịch vụ gemboss").
|
|
63
|
+
*/
|
|
64
|
+
export interface SwitcherItem {
|
|
65
|
+
id: string;
|
|
66
|
+
name: string;
|
|
67
|
+
/** One short plain sentence under the name (two lines at most are shown). */
|
|
68
|
+
description?: string;
|
|
69
|
+
/** Opened in the same tab. */
|
|
70
|
+
href: string;
|
|
71
|
+
/** A `groups` id; an item whose group is not listed goes in a last group without a heading. */
|
|
72
|
+
group?: string;
|
|
73
|
+
/** An illustration on top of the tile: an image (`src`), or, without one, `glyph` (an emoji, two letters) drawn big
|
|
74
|
+
* on a panel tinted with `tint`. */
|
|
75
|
+
media?: { src?: string | null; glyph?: string };
|
|
76
|
+
/** The small mark of a tile without `media`: a kit icon … */
|
|
77
|
+
icon?: IconName;
|
|
78
|
+
/** … or a short text / emoji. */
|
|
79
|
+
glyph?: string;
|
|
80
|
+
/** The hue of the mark or the illustration panel (SERVICE_TINTS). Default slate. */
|
|
81
|
+
tint?: ServiceTint;
|
|
82
|
+
/** A chip after the name: "Apply", "New". */
|
|
83
|
+
badge?: string;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export interface SwitcherProps {
|
|
87
|
+
items: readonly SwitcherItem[];
|
|
88
|
+
/** The groups, in their order. Absent: one group without a heading. */
|
|
89
|
+
groups?: ReadonlyArray<{ id: string; title: string }>;
|
|
90
|
+
/** The item this page belongs to: `aria-current="page"` and the accent ring. */
|
|
91
|
+
current?: string;
|
|
92
|
+
labels?: ServiceSwitcherLabels;
|
|
93
|
+
/** The foot: a link (`allHref`, worded `labels.all`) … */
|
|
94
|
+
allHref?: string | null;
|
|
95
|
+
/** … or the app's own foot (actions: "Create a community"). Wins over `allHref`. */
|
|
96
|
+
foot?: React.ReactNode;
|
|
97
|
+
search?: boolean;
|
|
98
|
+
/** The button's glyph. Default the nine-dot "apps". */
|
|
99
|
+
triggerIcon?: IconName;
|
|
100
|
+
className?: string;
|
|
101
|
+
}
|
|
102
|
+
|
|
59
103
|
const LABELS: Required<ServiceSwitcherLabels> = {
|
|
60
104
|
trigger: "Switch service", title: "Gem services", close: "Close", search: "Find a service",
|
|
61
105
|
noMatch: "No service matches “{query}”.", all: "All services and their health",
|
|
@@ -85,25 +129,39 @@ function rowStep(tiles: HTMLElement[], i: number, dir: 1 | -1): number {
|
|
|
85
129
|
return best;
|
|
86
130
|
}
|
|
87
131
|
|
|
88
|
-
|
|
132
|
+
/** The groups to draw, in order, after a search: each with the items it holds (an unlisted group's items last, untitled). */
|
|
133
|
+
function groupItems(items: readonly SwitcherItem[], groups: SwitcherProps["groups"], q: string) {
|
|
134
|
+
const order = groups ?? [];
|
|
135
|
+
const known = new Set(order.map((g) => g.id));
|
|
136
|
+
const all = [...order.map((g) => ({ id: g.id, title: g.title, items: items.filter((s) => s.group === g.id) })),
|
|
137
|
+
{ id: "", title: "", items: items.filter((s) => !s.group || !known.has(s.group)) }];
|
|
138
|
+
return all
|
|
139
|
+
.map((g) => ({ ...g, items: q ? g.items.filter((s) => `${s.name} ${s.description ?? ""} ${s.id} ${g.title}`.toLowerCase().includes(q)) : g.items }))
|
|
140
|
+
.filter((g) => g.items.length > 0);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Switcher (0.40.0): the nine-dot button and its panel, for any list — ServiceSwitcher is this with the Gem services.
|
|
145
|
+
* Same dialog, search, groups, keyboard and phone sheet; a tile is either the service kind (mark + name + line) or, with
|
|
146
|
+
* `media`, a card with an illustration on top. GemCommunity opens its groups with it.
|
|
147
|
+
*/
|
|
148
|
+
export function Switcher({ items, groups, current, labels, allHref = null, foot, search = true, triggerIcon = "apps", className }: SwitcherProps) {
|
|
89
149
|
const L = { ...LABELS, ...labels };
|
|
90
150
|
const [open, setOpen] = useState(false);
|
|
91
151
|
const [query, setQuery] = useState("");
|
|
92
|
-
const [roving, setRoving] = useState<
|
|
152
|
+
const [roving, setRoving] = useState<string | undefined>(current);
|
|
93
153
|
const button = useRef<HTMLButtonElement>(null);
|
|
94
154
|
const field = useRef<HTMLInputElement>(null);
|
|
95
|
-
// Each opening starts with every
|
|
155
|
+
// Each opening starts with every item shown (cleared on close: SettingsDialog's review #4073).
|
|
96
156
|
const { ref, onClick, onPointerDown } = useModalDialog(open, () => { setOpen(false); setQuery(""); });
|
|
97
157
|
const id = useId();
|
|
98
158
|
const panelId = `${id}svc`, titleId = `${id}svc-t`;
|
|
99
159
|
|
|
100
160
|
const q = query.trim().toLowerCase();
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
const
|
|
105
|
-
// The one tile in the Tab order: the last one focused, else the current service, else the first shown.
|
|
106
|
-
const tabStop = shown.includes(roving) ? roving : shown.includes(current) ? current : shown[0];
|
|
161
|
+
const shownGroups = useMemo(() => groupItems(items, groups, q), [items, groups, q]);
|
|
162
|
+
const shown = shownGroups.flatMap((g) => g.items.map((s) => s.id));
|
|
163
|
+
// The one tile in the Tab order: the last one focused, else the current item, else the first shown.
|
|
164
|
+
const tabStop = roving && shown.includes(roving) ? roving : current && shown.includes(current) ? current : shown[0];
|
|
107
165
|
|
|
108
166
|
/** Under the bar that holds the button, from the brand's left edge (the logo link before the button; the button itself
|
|
109
167
|
* without one). The bar is the closest `BAR` around the button (0.37.1: a surface's own `<header>` too, not only the
|
|
@@ -122,7 +180,7 @@ export function ServiceSwitcher({ current, services = GEM_SERVICES, labels, allH
|
|
|
122
180
|
};
|
|
123
181
|
useEffect(() => {
|
|
124
182
|
if (!open) return undefined;
|
|
125
|
-
// After useModalDialog's showModal (effects run in order): the current
|
|
183
|
+
// After useModalDialog's showModal (effects run in order): the current item's tile (the first one when the list
|
|
126
184
|
// has no current), not the corner ✕ the browser picks, and not the search box (on a phone it would pull up the
|
|
127
185
|
// keyboard over the grid).
|
|
128
186
|
setRoving(current);
|
|
@@ -172,7 +230,7 @@ export function ServiceSwitcher({ current, services = GEM_SERVICES, labels, allH
|
|
|
172
230
|
<>
|
|
173
231
|
<button ref={button} type="button" className={cx("gb-svc-trigger", className)} aria-haspopup="dialog" aria-expanded={open}
|
|
174
232
|
aria-controls={panelId} aria-label={L.trigger} title={L.trigger} onClick={() => { place(); setOpen(true); }}>
|
|
175
|
-
<Icon name=
|
|
233
|
+
<Icon name={triggerIcon} size={20} />
|
|
176
234
|
</button>
|
|
177
235
|
<dialog ref={ref} id={panelId} className="gb-svc" aria-labelledby={titleId} onClick={onClick} onPointerDown={onPointerDown}>
|
|
178
236
|
<div className="gb-svc__head">
|
|
@@ -193,25 +251,36 @@ export function ServiceSwitcher({ current, services = GEM_SERVICES, labels, allH
|
|
|
193
251
|
</div>
|
|
194
252
|
) : null}
|
|
195
253
|
<div className="gb-svc__body" onKeyDown={onGridKey}>
|
|
196
|
-
{
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
<
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
254
|
+
{shownGroups.length === 0 ? <p className="gb-svc__empty" role="status">{L.noMatch.replace("{query}", query.trim())}</p> : shownGroups.map((g) => {
|
|
255
|
+
const hid = `${id}svc-${g.id || "rest"}`;
|
|
256
|
+
const media = g.items.some((s) => s.media);
|
|
257
|
+
return (
|
|
258
|
+
<div key={g.id || "rest"} className="gb-svc__group" role="group" {...(g.title ? { "aria-labelledby": hid } : { "aria-label": L.title })}>
|
|
259
|
+
{g.title ? <h3 className="gb-svc__heading" id={hid}>{g.title}</h3> : null}
|
|
260
|
+
<ul className={cx("gb-svc__grid", media && "gb-svc__grid--media")} role="list">
|
|
261
|
+
{g.items.map((s) => (
|
|
262
|
+
<li key={s.id}>
|
|
263
|
+
<a className={cx("gb-svc__tile", s.media && "gb-svc__tile--media")} href={s.href} data-tint={s.tint}
|
|
264
|
+
aria-current={s.id === current ? "page" : undefined}
|
|
265
|
+
tabIndex={s.id === tabStop ? 0 : -1} onFocus={() => setRoving(s.id)} onClick={onTileClick}>
|
|
266
|
+
{s.media ? (
|
|
267
|
+
<span className="gb-svc__media" aria-hidden="true">
|
|
268
|
+
{s.media.src ? <img src={s.media.src} alt="" loading="lazy" decoding="async" /> : <span className="gb-svc__media-glyph">{s.media.glyph}</span>}
|
|
269
|
+
</span>
|
|
270
|
+
) : (
|
|
271
|
+
<span className="gb-svc__mark" aria-hidden="true">{s.icon ? <Icon name={s.icon} size={22} /> : <span className="gb-svc__glyph">{s.glyph}</span>}</span>
|
|
272
|
+
)}
|
|
273
|
+
<span className="gb-svc__name">{s.name}{s.badge ? <span className="gb-svc__badge">{s.badge}</span> : null}</span>
|
|
274
|
+
{s.description ? <span className="gb-svc__purpose">{s.description}</span> : null}
|
|
275
|
+
</a>
|
|
276
|
+
</li>
|
|
277
|
+
))}
|
|
278
|
+
</ul>
|
|
279
|
+
</div>
|
|
280
|
+
);
|
|
281
|
+
})}
|
|
213
282
|
</div>
|
|
214
|
-
{allHref ? (
|
|
283
|
+
{foot ? <div className="gb-svc__foot">{foot}</div> : allHref ? (
|
|
215
284
|
<div className="gb-svc__foot">
|
|
216
285
|
<a className="gb-svc__all" href={allHref} onClick={onTileClick}>{L.all}<span aria-hidden="true">→</span></a>
|
|
217
286
|
</div>
|
|
@@ -220,3 +289,11 @@ export function ServiceSwitcher({ current, services = GEM_SERVICES, labels, allH
|
|
|
220
289
|
</>
|
|
221
290
|
);
|
|
222
291
|
}
|
|
292
|
+
|
|
293
|
+
/** The Gem services: `Switcher` with GEM_SERVICES in the groups of SERVICE_GROUPS, the service's own mark and tint. */
|
|
294
|
+
export function ServiceSwitcher({ current, services = GEM_SERVICES, labels, allHref = SERVICES_HEALTH_URL, search = true, className }: ServiceSwitcherProps) {
|
|
295
|
+
const items = useMemo(() => services.map((s): SwitcherItem => ({
|
|
296
|
+
id: s.id, name: s.name, description: s.purpose, href: s.url, group: s.group, icon: s.icon, tint: s.tint,
|
|
297
|
+
})), [services]);
|
|
298
|
+
return <Switcher items={items} groups={SERVICE_GROUPS} current={current} labels={labels} allHref={allHref} search={search} className={className} />;
|
|
299
|
+
}
|
package/src/shell.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.gemboss-popover-surface{background:var(--gemboss-surface);background:color-mix(in srgb,var(--gemboss-surface) 93%,transparent);-webkit-backdrop-filter:blur(14px) saturate(1.4);backdrop-filter:blur(14px) saturate(1.4);border:1px solid var(--gemboss-divider);border-radius:var(--gemboss-radius-lg);box-shadow:var(--gemboss-shadow-raised)}@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))){.gemboss-popover-surface{background:var(--gemboss-surface)}}.icon-nav{position:fixed;top:56px;left:0;z-index:200;width:72px;height:calc(100dvh - 56px);background:var(--gemboss-rail-bg);border-right:1px solid var(--gemboss-divider);display:flex;flex-direction:column;padding-top:8px;overflow:hidden}.gemboss-account-menu{position:absolute;top:calc(100% + 6px);right:0;min-width:220px;z-index:320;overflow:hidden}.gemboss-account-menu-item,.ui-menu__item{display:block;width:100%;min-height:44px;padding:12px 16px;border:0;background:transparent;font:inherit;font-size:13px;color:var(--gemboss-text);text-align:left;text-decoration:none;cursor:pointer;transition:background var(--gemboss-transition-fast) ease,color var(--gemboss-transition-fast) ease}.gemboss-account-menu-item:hover,.ui-menu__item:hover{background:var(--gemboss-hover)}.gemboss-account-menu-item:focus-visible,.ui-menu__item:focus-visible{outline:2px solid var(--gemboss-primary);outline-offset:-2px;background:var(--gemboss-hover)}.gemboss-account-menu-item.danger,.ui-menu__item--danger{color:var(--gemboss-danger-strong)}.gemboss-account-chip{width:30px;height:30px;border:1px solid #cfd6ce;border-radius:var(--gemboss-radius-full);background:#f5f7f4;color:#303633;display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;font-size:11px;font-weight:700;cursor:pointer}.gemboss-platform-main{box-sizing:border-box;min-height:100dvh;margin-left:72px;padding-top:56px;background:var(--gemboss-app-bg)}.icon-nav{top:56px;height:calc(100dvh - 56px);background:var(--gemboss-nav-bg);border-right-color:var(--gemboss-divider)}@media (max-width: 1040px){.gemboss-platform-topbar{grid-template-columns:minmax(120px,1fr) minmax(220px,520px) minmax(120px,1fr)}}@media (max-width: 760px){.gemboss-platform-main{margin-left:0}}.gemboss-account-chip{width:32px;height:32px;border-radius:50%;background:var(--gemboss-primary);color:#fff;font-weight:600;font-size:12px;display:inline-flex;align-items:center;justify-content:center;border:none;cursor:pointer;transition:transform var(--gemboss-transition-base) ease}.gemboss-account-chip:hover{transform:scale(1.05)}.gemboss-account-chip:focus-visible{outline:2px solid var(--gemboss-primary);outline-offset:2px}.gemboss-platform-main{margin-top:56px;margin-left:72px;min-height:calc(100vh - 56px);padding:24px;background:#fafafb}@media (max-width: 768px){.gemboss-platform-main{margin-left:0;padding:16px}}.gemboss-platform-shell{display:block;min-height:100vh;background:var(--gemboss-app-bg)}.gemboss-platform-topbar{position:fixed;inset:0 0 auto;z-index:300;height:56px;border-bottom:1px solid var(--gemboss-divider);background:var(--gemboss-topbar-bg);display:grid;grid-template-columns:minmax(200px,1fr) minmax(280px,560px) minmax(200px,1fr);align-items:center;gap:16px;padding:0 16px;box-shadow:var(--gemboss-shadow-resting)}:root:has(.gemboss-platform-topbar){scroll-padding-top:64px}.gemboss-account-chip{width:32px;height:32px;border:1px solid var(--gemboss-chip-line);border-radius:var(--gemboss-radius-full);background:var(--gemboss-surface);color:var(--gemboss-chip-ink);display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;font-size:11px;font-weight:700;cursor:pointer;transition:border-color var(--gemboss-transition-base) ease,background-color var(--gemboss-transition-base) ease}.gemboss-account-chip:hover{border-color:var(--gemboss-chip-line-hover);background:var(--gemboss-chip-bg-hover);transform:none}.icon-nav{position:fixed;top:56px;left:0;z-index:200;width:72px;height:calc(100dvh - 56px);border-right:1px solid var(--gemboss-divider);background:var(--gemboss-nav-bg);padding-top:12px}.gemboss-platform-main{min-height:calc(100vh - 56px);margin-top:56px;margin-left:72px;background:var(--gemboss-app-bg);padding:24px}@media (max-width: 1120px){.gemboss-platform-topbar{grid-template-columns:220px minmax(220px,1fr) auto;gap:12px}}@media (max-width: 760px){.gemboss-platform-topbar{height:auto;min-height:56px;grid-template-columns:minmax(0,1fr) auto;padding:12px}.gemboss-account-chip,.icon-nav{display:none}.gemboss-platform-main{margin-left:0;padding:104px 16px 16px}}.gnav-scroll{scrollbar-width:thin;scrollbar-color:rgba(31,30,29,.22) transparent}.gemboss-assistant-railfoot.is-button{width:100%;border:none;background:none;cursor:pointer;text-align:left;font:inherit;border-radius:8px;transition:background .12s ease,color .12s ease}.gemboss-assistant-railfoot.is-button:hover{background:var(--gemboss-primary-soft);color:var(--gemboss-primary-dark)}.gemboss-assistant-empty{padding:24px 20px;color:var(--gemboss-text-muted);font-size:13px}@media (max-width: 760px){.gemboss-platform-topbar{display:flex;align-items:center;gap:8px;height:56px;min-height:56px;padding:0 12px}.gemboss-account-chip{display:inline-flex}.gemboss-platform-main{padding-top:56px;padding-bottom:calc(56px + env(safe-area-inset-bottom))}}@media (pointer: coarse){.gemboss-account-chip{width:44px;height:44px}.gnav-item{min-height:44px}.gemboss-assistant-collapse,.gemboss-assistant-newchat{min-height:44px;min-width:44px}}.icon-nav{width:240px;padding:12px 0 0;overflow:hidden;background:var(--gemboss-nav-bg);display:flex;flex-direction:column}.gnav-scroll{flex:1;overflow-y:auto;overflow-x:hidden;padding-inline:12px}.gnav-bottom{padding:0 12px 12px}.gnav-item{display:flex;align-items:center;gap:12px;width:100%;padding:8px 12px;margin:1px 0;border:0;background:transparent;cursor:pointer;text-align:left;border-radius:var(--gemboss-radius-md);text-decoration:none;font-family:inherit;color:var(--gemboss-text);font-size:var(--gemboss-fs-body);font-weight:500;line-height:1.2;transition:background-color var(--gemboss-transition-fast) ease,color var(--gemboss-transition-fast) ease}.gnav-item:hover{background:var(--gemboss-nav-hover)}.gnav-item:focus-visible{outline:2px solid var(--gemboss-accent);outline-offset:-2px}.gnav-item.active{color:var(--gemboss-active-fg);font-weight:600}.gnav-group:not(.has-active-child)>.gnav-item.active{background:var(--gemboss-active-bg)}.gnav-group:not(.has-active-child)>.gnav-item.active:hover{background:var(--gemboss-active-bg)}.gnav-group.has-active-child>.gnav-item.active:hover{background:var(--gemboss-nav-hover)}.gnav-ico{flex:0 0 20px;width:20px;height:20px;display:grid;place-items:center}.gnav-ico svg{width:20px;height:20px;fill:currentColor}.gnav-label{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.gnav-sub{list-style:none;margin:1px 0 6px;padding:0}.gnav-subitem{position:relative;display:flex;align-items:center;justify-content:space-between;gap:8px;padding:6px 12px 6px 44px;margin:1px 0;border-radius:var(--gemboss-radius-sm);color:var(--gemboss-text-muted);font-size:13px;line-height:1.2;text-decoration:none;white-space:nowrap;transition:background-color var(--gemboss-transition-fast) ease,color var(--gemboss-transition-fast) ease}@media (pointer: coarse){.gnav-subitem{min-height:44px}}.gnav-subitem:hover{background:var(--gemboss-nav-hover);color:var(--gemboss-text)}.gnav-subitem.active{color:var(--gemboss-active-fg);font-weight:600;background:var(--gemboss-active-bg)}.gnav-subitem.active:hover{background:var(--gemboss-active-bg);color:var(--gemboss-active-fg)}.gnav-subitem.active:before{content:"";position:absolute;left:20px;top:50%;transform:translateY(-50%);width:3px;height:15px;border-radius:2px;background:var(--gemboss-primary)}.gnav-subitem.is-soon{opacity:.5;cursor:default}.gnav-subitem em{font-style:normal;font-size:var(--gemboss-fs-micro);font-weight:600;letter-spacing:.04em;text-transform:uppercase;border:1px solid var(--gemboss-divider);border-radius:var(--gemboss-radius-sm);padding:1px 6px}.gnav-sep{height:1px;background:var(--gemboss-divider);margin:8px 6px}.gnav-item.gnav-assistant{color:var(--gemboss-accent-strong);font-weight:600;background:var(--gemboss-accent-soft)}.gnav-item.gnav-assistant .gnav-ico svg{fill:var(--gemboss-accent)}.gnav-item.gnav-assistant:hover{background:color-mix(in srgb,var(--gemboss-accent) 16%,var(--gemboss-surface))}.gnav-item.gnav-assistant.active{background:var(--gemboss-active-bg);color:var(--gemboss-active-fg)}.gnav-item.gnav-assistant.active .gnav-ico svg{fill:var(--gemboss-active-fg)}.gemboss-platform-main{margin-left:240px}.gemboss-mobile-menu-btn,.gemboss-mobile-nav-backdrop{display:none}@media (max-width: 760px){.gemboss-platform-main{margin-left:0;padding-bottom:env(safe-area-inset-bottom)}.gemboss-mobile-menu-btn{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;width:38px;height:38px;margin-left:-2px;border:0;border-radius:8px;background:transparent;cursor:pointer;color:var(--gemboss-text)}.gemboss-mobile-menu-btn:active{background:var(--gemboss-hover)}.icon-nav{display:flex;width:min(82vw,300px);transform:translate(-100%);transition:transform .26s cubic-bezier(.4,0,.2,1),box-shadow .26s cubic-bezier(.4,0,.2,1);z-index:1000;box-shadow:none}.gemboss-platform-shell.is-mobile-nav-open .icon-nav{transform:translate(0);box-shadow:2px 0 26px #1f1e1d33}.gemboss-mobile-nav-backdrop{display:block;position:fixed;inset:56px 0 0;width:100%;border:0;padding:0;background:#14131261;opacity:0;pointer-events:none;transition:opacity .22s ease;z-index:999}.gemboss-platform-shell.is-mobile-nav-open .gemboss-mobile-nav-backdrop{opacity:1;pointer-events:auto}}@media (max-width: 305.98px){.gemboss-platform-topbar{padding:0 8px}}@media (min-width: 306px) and (max-width: 460px){.gemboss-platform-topbar{padding:0 8px}.gemboss-mobile-menu-btn,.gemboss-account-chip{width:44px;height:44px}}.gemboss-assistant-chatslot{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;min-width:0}.gemboss-assistant-chatslot[hidden]{display:none}.gemboss-assistant-page>.gemboss-assistant-tabs{flex:0 0 auto;display:flex;align-items:center;gap:4px;padding:4px 8px 0;overflow-x:auto;scrollbar-width:none}.gemboss-assistant-tabs::-webkit-scrollbar{display:none}.gemboss-assistant-tab{display:flex;align-items:center;flex:0 1 auto;min-width:0;max-width:190px;border:1px solid var(--gemboss-divider);border-radius:var(--gemboss-radius-md);background:transparent}.gemboss-assistant-tab.active{background:var(--gemboss-active-bg);border-color:var(--gemboss-active-bg)}.gemboss-assistant-tab-main{display:flex;align-items:center;gap:6px;min-width:0;min-height:44px;padding:0 4px 0 8px;border:0;background:transparent;font:inherit;font-size:var(--gemboss-fs-caption);color:var(--gemboss-text-muted);cursor:pointer}.gemboss-assistant-tab.active .gemboss-assistant-tab-main{color:var(--gemboss-text-strong)}.gemboss-assistant-tab-title{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.gemboss-assistant-tab-dot{flex:0 0 auto;width:6px;height:6px;border-radius:var(--gemboss-radius-full);background:var(--gemboss-divider)}.gemboss-assistant-tab-dot.is-running{background:var(--gemboss-primary);animation:gemboss-assistant-pulse 1.4s ease-in-out infinite}.gemboss-assistant-tab-close{flex:0 0 auto;width:44px;height:44px;display:grid;place-items:center;border:0;background:transparent;color:var(--gemboss-text-muted);cursor:pointer;padding:0}.gemboss-assistant-tab-close:hover{color:var(--gemboss-text-strong)}.gemboss-assistant-tab-close svg{width:14px;height:14px}.gemboss-assistant-sronly{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}.gemboss-assistant-thread-running{flex:0 0 auto;width:6px;height:6px;border-radius:var(--gemboss-radius-full);background:var(--gemboss-primary);animation:gemboss-assistant-pulse 1.4s ease-in-out infinite}@media (prefers-reduced-motion: reduce){.gemboss-assistant-tab-dot.is-running,.gemboss-assistant-thread-running{animation:none}}.gemboss-assistant-route-claim{display:block;height:100%}.gemboss-assistant-layout.is-dock{height:auto;min-height:0}.gemboss-assistant-layout.is-dock .gemboss-assistant-page{height:auto;max-width:none;padding:4px 0 8px}.gnav-item.gnav-assistant{position:relative}body.gemboss-assistant-busy .gnav-item.gnav-assistant:after,body.gemboss-assistant-unread .gnav-item.gnav-assistant:after{content:"";position:absolute;top:6px;left:26px;width:8px;height:8px;border-radius:50%;border:2px solid var(--gemboss-surface)}body.gemboss-assistant-busy .gnav-item.gnav-assistant:after{background:var(--gemboss-primary);animation:gemboss-assistant-pulse 1.4s ease-in-out infinite}body.gemboss-assistant-unread .gnav-item.gnav-assistant:after{background:var(--gemboss-success-strong)}@media (prefers-reduced-motion: reduce){body.gemboss-assistant-busy .gnav-item.gnav-assistant:after{animation:none}}.gemboss-assistant-layout{display:flex;height:calc(100dvh - 56px);width:100%;min-height:0}.gemboss-assistant-rail{flex:0 0 264px;width:264px;display:flex;flex-direction:column;min-height:0;border-right:1px solid var(--gemboss-divider);background:transparent;padding:16px 12px 12px;gap:12px;transition:flex-basis .18s ease,width .18s ease}.gemboss-assistant-rail-top{display:flex;align-items:center;gap:6px}.gemboss-assistant-newchat{display:flex;align-items:center;gap:8px;flex:1 1 auto;min-width:0;padding:12px;border:1px solid var(--gemboss-divider);border-radius:12px;background:transparent;color:var(--gemboss-text);font-size:var(--gemboss-fs-body);font-weight:600;cursor:pointer;transition:background .12s ease,border-color .12s ease}.gemboss-assistant-newchat:hover{background:#00000009;border-color:var(--gemboss-text-muted)}.gemboss-assistant-newchat svg{width:17px;height:17px;fill:currentColor;flex:0 0 auto}.gemboss-assistant-newchat span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:1 1 auto}.gemboss-assistant-kbd{flex:0 0 auto;font-size:var(--gemboss-fs-micro);font-weight:600;line-height:1;padding:4px 6px;border:1px solid var(--gemboss-divider);border-radius:6px;background:transparent;color:var(--gemboss-text-muted);font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.gemboss-assistant-search:focus-within .gemboss-assistant-kbd{display:none}.gemboss-assistant-collapse{flex:0 0 auto;display:grid;place-items:center;width:34px;height:34px;border:0;border-radius:8px;background:transparent;color:var(--gemboss-text-muted);cursor:pointer;transition:background .12s ease,color .12s ease}.gemboss-assistant-collapse:hover{background:#0000000d;color:var(--gemboss-text)}.gemboss-assistant-collapse svg{width:16px;height:16px;fill:currentColor}.gemboss-assistant-search{gap:6px}.gemboss-assistant-search>svg{width:15px;height:15px;fill:var(--gemboss-text-muted);flex:0 0 auto}.gemboss-assistant-search-clear{display:grid;place-items:center;width:20px;height:20px;border:0;border-radius:6px;background:transparent;color:var(--gemboss-text-muted);cursor:pointer}.gemboss-assistant-search-clear:hover{background:#00000012;color:var(--gemboss-text)}.gemboss-assistant-search-clear svg{width:13px;height:13px;fill:currentColor}.gemboss-assistant-railfoot{flex:0 0 auto;display:flex;align-items:center;gap:6px;padding:8px 12px 2px;border-top:1px solid var(--gemboss-divider);margin-top:4px;color:var(--gemboss-text-muted);font-size:var(--gemboss-fs-caption);line-height:1.35}.gemboss-assistant-railfoot svg{width:13px;height:13px;flex:0 0 auto;fill:currentColor;opacity:.8}.gemboss-assistant-threads{flex:1 1 auto;min-height:0;overflow-y:auto;display:flex;flex-direction:column;gap:2px}.gemboss-assistant-threads-empty{padding:16px 8px;color:var(--gemboss-text-muted);font-size:var(--gemboss-fs-caption)}.gemboss-assistant-group{display:flex;flex-direction:column;gap:2px}.gemboss-assistant-group+.gemboss-assistant-group{margin-top:12px}.gemboss-assistant-group-label{padding:4px 12px;font-size:11px;font-weight:600;letter-spacing:.02em;color:var(--gemboss-text-muted);text-transform:uppercase}.gemboss-assistant-thread{position:relative;display:flex;align-items:center;border-radius:8px;transition:background .12s ease}.gemboss-assistant-thread:hover{background:var(--gemboss-hover, rgba(0,0,0,.04))}.gemboss-assistant-thread.active{background:#00000012}.gemboss-assistant-thread-main{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;align-items:flex-start;gap:2px;padding:8px 12px;border:0;background:transparent;text-align:left;cursor:pointer}.gemboss-assistant-thread-titlerow{display:flex;align-items:center;gap:6px;width:100%;min-width:0}.gemboss-assistant-pin-dot{width:12px;height:12px;flex:0 0 auto;fill:var(--gemboss-text-muted)}.gemboss-assistant-thread-title{flex:1 1 auto;min-width:0;font-size:13px;font-weight:500;color:var(--gemboss-text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.gemboss-assistant-thread-meta{font-size:var(--gemboss-fs-caption);color:var(--gemboss-text-muted)}.gemboss-assistant-thread.menu-open{background:#00000012}.gemboss-assistant-thread.menu-open .gemboss-assistant-thread-actions{opacity:1}.gemboss-assistant-menu{z-index:60;width:184px;padding:6px;display:flex;flex-direction:column}.gemboss-assistant-menu-confirm{padding:8px 12px 6px;font-size:var(--gemboss-fs-caption);font-weight:600;color:var(--gemboss-text)}.gemboss-assistant-menu button{display:flex;align-items:center;gap:8px;width:100%;padding:8px 12px;border:0;border-radius:8px;background:transparent;text-align:left;font-size:13px;color:var(--gemboss-text);cursor:pointer}.gemboss-assistant-menu button:hover{background:var(--gemboss-hover, rgba(0,0,0,.05))}.gemboss-assistant-menu button.danger{color:var(--gemboss-danger-strong)}.gemboss-assistant-menu button svg{width:15px;height:15px;fill:currentColor;flex:0 0 auto}.gemboss-assistant-thread-actions{position:absolute;right:6px;display:flex;gap:2px;opacity:0;transition:opacity .12s ease}.gemboss-assistant-thread:hover .gemboss-assistant-thread-actions,.gemboss-assistant-thread:focus-within .gemboss-assistant-thread-actions{opacity:1}.gemboss-assistant-thread-act{display:grid;place-items:center;width:26px;height:26px;border:0;border-radius:8px;background:transparent;color:var(--gemboss-text-muted);cursor:pointer;transition:background .12s ease,color .12s ease}.gemboss-assistant-thread-act:hover{background:#00000012;color:var(--gemboss-text)}.gemboss-assistant-thread-act.danger:hover{color:var(--gemboss-danger-strong)}.gemboss-assistant-thread-act svg{width:15px;height:15px;fill:currentColor}.gemboss-assistant-thread.editing{background:#00000012}.gemboss-assistant-thread-edit{display:flex;align-items:center;gap:2px;width:100%;padding:6px}.gemboss-assistant-thread-edit input{flex:1 1 auto;min-width:0}.gemboss-assistant-layout .gemboss-assistant-page{height:100%;max-width:820px;flex:1 1 auto;min-width:0;padding-top:16px}.gemboss-assistant-layout .gemboss-assistant-page.is-switching{opacity:.55;transition:opacity .12s ease;pointer-events:none}.gemboss-assistant-rail.is-collapsed{flex-basis:60px;width:60px;padding:16px 8px 12px}.gemboss-assistant-rail.is-collapsed .gemboss-assistant-rail-top{flex-direction:column;gap:8px}.gemboss-assistant-rail.is-collapsed .gemboss-assistant-newchat{justify-content:center;padding:8px;flex:0 0 auto}.gemboss-assistant-rail.is-collapsed .gemboss-assistant-newchat span,.gemboss-assistant-rail.is-collapsed .gemboss-assistant-search,.gemboss-assistant-rail.is-collapsed .gemboss-assistant-railfoot,.gemboss-assistant-rail.is-collapsed .gemboss-assistant-threads{display:none}@media (max-width: 760px){.gemboss-assistant-rail{flex-basis:60px;width:60px;padding:16px 8px 12px}.gemboss-assistant-rail .gemboss-assistant-rail-top{flex-direction:column;gap:8px}.gemboss-assistant-newchat{justify-content:center;padding:8px;flex:0 0 auto}.gemboss-assistant-newchat span,.gemboss-assistant-search,.gemboss-assistant-railfoot,.gemboss-assistant-threads,.gemboss-assistant-collapse{display:none}}.gemboss-assistant-page{height:calc(100dvh - 56px);width:100%;max-width:760px;margin:0 auto;padding:24px 0 16px;display:flex;flex-direction:column;min-height:0}.gemboss-assistant-page>*{flex:1 1 auto;min-height:0}.gemboss-assistant-empty{flex:1;display:grid;place-items:center;color:var(--gemboss-text-muted);font-size:14px}.gemboss-platform-shell{display:flow-root}.gemboss-platform-main{padding-bottom:calc(24px + var(--gemboss-invite-h, 0px))}@keyframes gemboss-assistant-pulse{0%,to{opacity:1}50%{opacity:.35}}.gb-account{position:relative}.gb-account>summary{list-style:none}.gb-account>summary::-webkit-details-marker{display:none}.gb-account-head{padding:12px 16px;border-bottom:1px solid var(--gemboss-divider)}.gb-account-name{font-size:13px;font-weight:600;color:var(--gemboss-text-strong)}.gb-account-email{font-size:12px;color:var(--gemboss-text-muted)}.gb-account-role{display:inline-block;margin-top:4px;padding:1px 6px;border-radius:4px;font-size:11px;font-weight:600;color:var(--gemboss-active-fg);background:var(--gemboss-active-bg)}.gb-account-form{margin:0}.gnav-scroll::-webkit-scrollbar{width:9px}.gnav-scroll::-webkit-scrollbar-track{background:transparent}.gnav-scroll::-webkit-scrollbar-thumb{background:#1f1e1d33;border-radius:6px;border:2px solid transparent;background-clip:content-box}
|
|
1
|
+
.gemboss-popover-surface{background:var(--gemboss-surface);background:color-mix(in srgb,var(--gemboss-surface) 93%,transparent);-webkit-backdrop-filter:blur(14px) saturate(1.4);backdrop-filter:blur(14px) saturate(1.4);border:1px solid var(--gemboss-divider);border-radius:var(--gemboss-radius-lg);box-shadow:var(--gemboss-shadow-raised)}@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))){.gemboss-popover-surface{background:var(--gemboss-surface)}}.icon-nav{position:fixed;top:56px;left:0;z-index:200;height:calc(100dvh - 56px);background:var(--gemboss-rail-bg);border-right:1px solid var(--gemboss-divider);display:flex;flex-direction:column;padding-top:8px;overflow:hidden}.gemboss-account-menu{position:absolute;top:calc(100% + 6px);right:0;min-width:220px;z-index:320;overflow:hidden}.gemboss-account-menu-item,.ui-menu__item{display:block;width:100%;min-height:44px;padding:12px 16px;border:0;background:transparent;font:inherit;font-size:13px;color:var(--gemboss-text);text-align:left;text-decoration:none;cursor:pointer;transition:background var(--gemboss-transition-fast) ease,color var(--gemboss-transition-fast) ease}.gemboss-account-menu-item:hover,.ui-menu__item:hover{background:var(--gemboss-hover)}.gemboss-account-menu-item:focus-visible,.ui-menu__item:focus-visible{outline:2px solid var(--gemboss-primary);outline-offset:-2px;background:var(--gemboss-hover)}.gemboss-account-menu-item.danger,.ui-menu__item--danger{color:var(--gemboss-danger-strong)}.gemboss-account-chip{width:30px;height:30px;border:1px solid #cfd6ce;border-radius:var(--gemboss-radius-full);background:#f5f7f4;color:#303633;display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;font-size:11px;font-weight:700;cursor:pointer}.gemboss-platform-main{box-sizing:border-box;min-height:100dvh;padding-top:56px;background:var(--gemboss-app-bg)}.icon-nav{top:56px;height:calc(100dvh - 56px);background:var(--gemboss-nav-bg);border-right-color:var(--gemboss-divider)}@media (max-width: 1040px){.gemboss-platform-topbar{grid-template-columns:minmax(120px,1fr) minmax(220px,520px) minmax(120px,1fr)}}@media (max-width: 760px){.gemboss-platform-main{margin-left:0}}.gemboss-account-chip{width:32px;height:32px;border-radius:50%;background:var(--gemboss-primary);color:#fff;font-weight:600;font-size:12px;display:inline-flex;align-items:center;justify-content:center;border:none;cursor:pointer;transition:transform var(--gemboss-transition-base) ease}.gemboss-account-chip:hover{transform:scale(1.05)}.gemboss-account-chip:focus-visible{outline:2px solid var(--gemboss-primary);outline-offset:2px}.gemboss-platform-main{margin-top:56px;min-height:calc(100vh - 56px);padding:24px;background:#fafafb}@media (max-width: 768px){.gemboss-platform-main{margin-left:0;padding:16px}}.gemboss-platform-shell{display:block;min-height:100vh;background:var(--gemboss-app-bg)}.gemboss-platform-topbar{position:fixed;inset:0 0 auto;z-index:300;height:56px;border-bottom:1px solid var(--gemboss-divider);background:var(--gemboss-topbar-bg);display:grid;grid-template-columns:minmax(200px,1fr) minmax(280px,560px) minmax(200px,1fr);align-items:center;gap:16px;padding:0 16px;box-shadow:var(--gemboss-shadow-resting)}:root:has(.gemboss-platform-topbar){scroll-padding-top:64px}.gemboss-account-chip{width:32px;height:32px;border:1px solid var(--gemboss-chip-line);border-radius:var(--gemboss-radius-full);background:var(--gemboss-surface);color:var(--gemboss-chip-ink);display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;font-size:11px;font-weight:700;cursor:pointer;transition:border-color var(--gemboss-transition-base) ease,background-color var(--gemboss-transition-base) ease}.gemboss-account-chip:hover{border-color:var(--gemboss-chip-line-hover);background:var(--gemboss-chip-bg-hover);transform:none}.icon-nav{position:fixed;top:56px;left:0;z-index:200;height:calc(100dvh - 56px);border-right:1px solid var(--gemboss-divider);background:var(--gemboss-nav-bg);padding-top:12px}.gemboss-platform-main{min-height:calc(100vh - 56px);margin-top:56px;background:var(--gemboss-app-bg);padding:24px}@media (max-width: 1120px){.gemboss-platform-topbar{grid-template-columns:220px minmax(220px,1fr) auto;gap:12px}}@media (max-width: 760px){.gemboss-platform-topbar{height:auto;min-height:56px;grid-template-columns:minmax(0,1fr) auto;padding:12px}.gemboss-account-chip,.icon-nav{display:none}.gemboss-platform-main{margin-left:0;padding:16px}}.gnav-scroll{scrollbar-width:thin;scrollbar-color:rgba(31,30,29,.22) transparent}.gemboss-assistant-railfoot.is-button{width:100%;border:none;background:none;cursor:pointer;text-align:left;font:inherit;border-radius:8px;transition:background .12s ease,color .12s ease}.gemboss-assistant-railfoot.is-button:hover{background:var(--gemboss-primary-soft);color:var(--gemboss-primary-dark)}.gemboss-assistant-empty{padding:24px 20px;color:var(--gemboss-text-muted);font-size:13px}@media (max-width: 760px){.gemboss-platform-topbar{display:flex;align-items:center;gap:8px;height:56px;min-height:56px;padding:0 12px}.gemboss-account-chip{display:inline-flex}.gemboss-platform-main{padding-top:16px;padding-bottom:calc(56px + env(safe-area-inset-bottom))}}@media (pointer: coarse){.gemboss-account-chip{width:44px;height:44px}.gnav-item{min-height:44px}.gemboss-assistant-collapse,.gemboss-assistant-newchat{min-height:44px;min-width:44px}}.icon-nav{width:240px;padding:12px 0 0;overflow:hidden;background:var(--gemboss-nav-bg);display:flex;flex-direction:column}.gnav-scroll{flex:1;overflow-y:auto;overflow-x:hidden;padding-inline:12px}.gnav-bottom{padding:0 12px 12px}.gnav-item{display:flex;align-items:center;gap:12px;width:100%;padding:8px 12px;margin:1px 0;border:0;background:transparent;cursor:pointer;text-align:left;border-radius:var(--gemboss-radius-md);text-decoration:none;font-family:inherit;color:var(--gemboss-text);font-size:var(--gemboss-fs-body);font-weight:500;line-height:1.2;transition:background-color var(--gemboss-transition-fast) ease,color var(--gemboss-transition-fast) ease}.gnav-item:hover{background:var(--gemboss-nav-hover)}.gnav-item:focus-visible{outline:2px solid var(--gemboss-accent);outline-offset:-2px}.gnav-item.active{color:var(--gemboss-active-fg);font-weight:600}.gnav-group:not(.has-active-child)>.gnav-item.active{background:var(--gemboss-active-bg)}.gnav-group:not(.has-active-child)>.gnav-item.active:hover{background:var(--gemboss-active-bg)}.gnav-group.has-active-child>.gnav-item.active:hover{background:var(--gemboss-nav-hover)}.gnav-ico{flex:0 0 20px;width:20px;height:20px;display:grid;place-items:center}.gnav-ico svg{width:20px;height:20px;fill:currentColor}.gnav-label{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.gnav-sub{list-style:none;margin:1px 0 6px;padding:0}.gnav-subitem{position:relative;display:flex;align-items:center;justify-content:space-between;gap:8px;padding:6px 12px 6px 44px;margin:1px 0;border-radius:var(--gemboss-radius-sm);color:var(--gemboss-text-muted);font-size:13px;line-height:1.2;text-decoration:none;white-space:nowrap;transition:background-color var(--gemboss-transition-fast) ease,color var(--gemboss-transition-fast) ease}@media (pointer: coarse){.gnav-subitem{min-height:44px}}.gnav-subitem:hover{background:var(--gemboss-nav-hover);color:var(--gemboss-text)}.gnav-subitem.active{color:var(--gemboss-active-fg);font-weight:600;background:var(--gemboss-active-bg)}.gnav-subitem.active:hover{background:var(--gemboss-active-bg);color:var(--gemboss-active-fg)}.gnav-subitem.active:before{content:"";position:absolute;left:20px;top:50%;transform:translateY(-50%);width:3px;height:15px;border-radius:2px;background:var(--gemboss-primary)}.gnav-subitem.is-soon{opacity:.5;cursor:default}.gnav-subitem em{font-style:normal;font-size:var(--gemboss-fs-micro);font-weight:600;letter-spacing:.04em;text-transform:uppercase;border:1px solid var(--gemboss-divider);border-radius:var(--gemboss-radius-sm);padding:1px 6px}.gnav-sep{height:1px;background:var(--gemboss-divider);margin:8px 6px}.gnav-item.gnav-assistant{color:var(--gemboss-accent-strong);font-weight:600;background:var(--gemboss-accent-soft)}.gnav-item.gnav-assistant .gnav-ico svg{fill:var(--gemboss-accent)}.gnav-item.gnav-assistant:hover{background:color-mix(in srgb,var(--gemboss-accent) 16%,var(--gemboss-surface))}.gnav-item.gnav-assistant.active{background:var(--gemboss-active-bg);color:var(--gemboss-active-fg)}.gnav-item.gnav-assistant.active .gnav-ico svg{fill:var(--gemboss-active-fg)}.gemboss-platform-main{margin-left:240px}.gemboss-mobile-menu-btn,.gemboss-mobile-nav-backdrop{display:none}@media (max-width: 760px){.gemboss-platform-main{margin-left:0;padding-bottom:env(safe-area-inset-bottom)}.gemboss-mobile-menu-btn{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;width:38px;height:38px;margin-left:-2px;border:0;border-radius:8px;background:transparent;cursor:pointer;color:var(--gemboss-text)}.gemboss-mobile-menu-btn:active{background:var(--gemboss-hover)}.icon-nav{display:flex;width:min(82vw,300px);transform:translate(-100%);transition:transform .26s cubic-bezier(.4,0,.2,1),box-shadow .26s cubic-bezier(.4,0,.2,1);z-index:1000;box-shadow:none}.gemboss-platform-shell.is-mobile-nav-open .icon-nav{transform:translate(0);box-shadow:2px 0 26px #1f1e1d33}.gemboss-mobile-nav-backdrop{display:block;position:fixed;inset:56px 0 0;width:100%;border:0;padding:0;background:#14131261;opacity:0;pointer-events:none;transition:opacity .22s ease;z-index:999}.gemboss-platform-shell.is-mobile-nav-open .gemboss-mobile-nav-backdrop{opacity:1;pointer-events:auto}}@media (max-width: 305.98px){.gemboss-platform-topbar{padding:0 8px}}@media (min-width: 306px) and (max-width: 460px){.gemboss-platform-topbar{padding:0 8px}.gemboss-mobile-menu-btn,.gemboss-account-chip{width:44px;height:44px}}.gemboss-assistant-chatslot{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;min-width:0}.gemboss-assistant-chatslot[hidden]{display:none}.gemboss-assistant-page>.gemboss-assistant-tabs{flex:0 0 auto;display:flex;align-items:center;gap:4px;padding:4px 8px 0;overflow-x:auto;scrollbar-width:none}.gemboss-assistant-tabs::-webkit-scrollbar{display:none}.gemboss-assistant-tab{display:flex;align-items:center;flex:0 1 auto;min-width:0;max-width:190px;border:1px solid var(--gemboss-divider);border-radius:var(--gemboss-radius-md);background:transparent}.gemboss-assistant-tab.active{background:var(--gemboss-active-bg);border-color:var(--gemboss-active-bg)}.gemboss-assistant-tab-main{display:flex;align-items:center;gap:6px;min-width:0;min-height:44px;padding:0 4px 0 8px;border:0;background:transparent;font:inherit;font-size:var(--gemboss-fs-caption);color:var(--gemboss-text-muted);cursor:pointer}.gemboss-assistant-tab.active .gemboss-assistant-tab-main{color:var(--gemboss-text-strong)}.gemboss-assistant-tab-title{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.gemboss-assistant-tab-dot{flex:0 0 auto;width:6px;height:6px;border-radius:var(--gemboss-radius-full);background:var(--gemboss-divider)}.gemboss-assistant-tab-dot.is-running{background:var(--gemboss-primary);animation:gemboss-assistant-pulse 1.4s ease-in-out infinite}.gemboss-assistant-tab-close{flex:0 0 auto;width:44px;height:44px;display:grid;place-items:center;border:0;background:transparent;color:var(--gemboss-text-muted);cursor:pointer;padding:0}.gemboss-assistant-tab-close:hover{color:var(--gemboss-text-strong)}.gemboss-assistant-tab-close svg{width:14px;height:14px}.gemboss-assistant-sronly{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}.gemboss-assistant-thread-running{flex:0 0 auto;width:6px;height:6px;border-radius:var(--gemboss-radius-full);background:var(--gemboss-primary);animation:gemboss-assistant-pulse 1.4s ease-in-out infinite}@media (prefers-reduced-motion: reduce){.gemboss-assistant-tab-dot.is-running,.gemboss-assistant-thread-running{animation:none}}.gemboss-assistant-route-claim{display:block;height:100%}.gemboss-assistant-layout.is-dock{height:auto;min-height:0}.gemboss-assistant-layout.is-dock .gemboss-assistant-page{height:auto;max-width:none;padding:4px 0 8px}.gnav-item.gnav-assistant{position:relative}body.gemboss-assistant-busy .gnav-item.gnav-assistant:after,body.gemboss-assistant-unread .gnav-item.gnav-assistant:after{content:"";position:absolute;top:6px;left:26px;width:8px;height:8px;border-radius:50%;border:2px solid var(--gemboss-surface)}body.gemboss-assistant-busy .gnav-item.gnav-assistant:after{background:var(--gemboss-primary);animation:gemboss-assistant-pulse 1.4s ease-in-out infinite}body.gemboss-assistant-unread .gnav-item.gnav-assistant:after{background:var(--gemboss-success-strong)}@media (prefers-reduced-motion: reduce){body.gemboss-assistant-busy .gnav-item.gnav-assistant:after{animation:none}}.gemboss-assistant-layout{display:flex;height:calc(100dvh - 56px);width:100%;min-height:0}.gemboss-assistant-rail{flex:0 0 264px;width:264px;display:flex;flex-direction:column;min-height:0;border-right:1px solid var(--gemboss-divider);background:transparent;padding:16px 12px 12px;gap:12px;transition:flex-basis .18s ease,width .18s ease}.gemboss-assistant-rail-top{display:flex;align-items:center;gap:6px}.gemboss-assistant-newchat{display:flex;align-items:center;gap:8px;flex:1 1 auto;min-width:0;padding:12px;border:1px solid var(--gemboss-divider);border-radius:12px;background:transparent;color:var(--gemboss-text);font-size:var(--gemboss-fs-body);font-weight:600;cursor:pointer;transition:background .12s ease,border-color .12s ease}.gemboss-assistant-newchat:hover{background:#00000009;border-color:var(--gemboss-text-muted)}.gemboss-assistant-newchat svg{width:17px;height:17px;fill:currentColor;flex:0 0 auto}.gemboss-assistant-newchat span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:1 1 auto}.gemboss-assistant-kbd{flex:0 0 auto;font-size:var(--gemboss-fs-micro);font-weight:600;line-height:1;padding:4px 6px;border:1px solid var(--gemboss-divider);border-radius:6px;background:transparent;color:var(--gemboss-text-muted);font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.gemboss-assistant-search:focus-within .gemboss-assistant-kbd{display:none}.gemboss-assistant-collapse{flex:0 0 auto;display:grid;place-items:center;width:34px;height:34px;border:0;border-radius:8px;background:transparent;color:var(--gemboss-text-muted);cursor:pointer;transition:background .12s ease,color .12s ease}.gemboss-assistant-collapse:hover{background:#0000000d;color:var(--gemboss-text)}.gemboss-assistant-collapse svg{width:16px;height:16px;fill:currentColor}.gemboss-assistant-search{gap:6px}.gemboss-assistant-search>svg{width:15px;height:15px;fill:var(--gemboss-text-muted);flex:0 0 auto}.gemboss-assistant-search-clear{display:grid;place-items:center;width:20px;height:20px;border:0;border-radius:6px;background:transparent;color:var(--gemboss-text-muted);cursor:pointer}.gemboss-assistant-search-clear:hover{background:#00000012;color:var(--gemboss-text)}.gemboss-assistant-search-clear svg{width:13px;height:13px;fill:currentColor}.gemboss-assistant-railfoot{flex:0 0 auto;display:flex;align-items:center;gap:6px;padding:8px 12px 2px;border-top:1px solid var(--gemboss-divider);margin-top:4px;color:var(--gemboss-text-muted);font-size:var(--gemboss-fs-caption);line-height:1.35}.gemboss-assistant-railfoot svg{width:13px;height:13px;flex:0 0 auto;fill:currentColor;opacity:.8}.gemboss-assistant-threads{flex:1 1 auto;min-height:0;overflow-y:auto;display:flex;flex-direction:column;gap:2px}.gemboss-assistant-threads-empty{padding:16px 8px;color:var(--gemboss-text-muted);font-size:var(--gemboss-fs-caption)}.gemboss-assistant-group{display:flex;flex-direction:column;gap:2px}.gemboss-assistant-group+.gemboss-assistant-group{margin-top:12px}.gemboss-assistant-group-label{padding:4px 12px;font-size:11px;font-weight:600;letter-spacing:.02em;color:var(--gemboss-text-muted);text-transform:uppercase}.gemboss-assistant-thread{position:relative;display:flex;align-items:center;border-radius:8px;transition:background .12s ease}.gemboss-assistant-thread:hover{background:var(--gemboss-hover, rgba(0,0,0,.04))}.gemboss-assistant-thread.active{background:#00000012}.gemboss-assistant-thread-main{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;align-items:flex-start;gap:2px;padding:8px 12px;border:0;background:transparent;text-align:left;cursor:pointer}.gemboss-assistant-thread-titlerow{display:flex;align-items:center;gap:6px;width:100%;min-width:0}.gemboss-assistant-pin-dot{width:12px;height:12px;flex:0 0 auto;fill:var(--gemboss-text-muted)}.gemboss-assistant-thread-title{flex:1 1 auto;min-width:0;font-size:13px;font-weight:500;color:var(--gemboss-text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.gemboss-assistant-thread-meta{font-size:var(--gemboss-fs-caption);color:var(--gemboss-text-muted)}.gemboss-assistant-thread.menu-open{background:#00000012}.gemboss-assistant-thread.menu-open .gemboss-assistant-thread-actions{opacity:1}.gemboss-assistant-menu{z-index:60;width:184px;padding:6px;display:flex;flex-direction:column}.gemboss-assistant-menu-confirm{padding:8px 12px 6px;font-size:var(--gemboss-fs-caption);font-weight:600;color:var(--gemboss-text)}.gemboss-assistant-menu button{display:flex;align-items:center;gap:8px;width:100%;padding:8px 12px;border:0;border-radius:8px;background:transparent;text-align:left;font-size:13px;color:var(--gemboss-text);cursor:pointer}.gemboss-assistant-menu button:hover{background:var(--gemboss-hover, rgba(0,0,0,.05))}.gemboss-assistant-menu button.danger{color:var(--gemboss-danger-strong)}.gemboss-assistant-menu button svg{width:15px;height:15px;fill:currentColor;flex:0 0 auto}.gemboss-assistant-thread-actions{position:absolute;right:6px;display:flex;gap:2px;opacity:0;transition:opacity .12s ease}.gemboss-assistant-thread:hover .gemboss-assistant-thread-actions,.gemboss-assistant-thread:focus-within .gemboss-assistant-thread-actions{opacity:1}.gemboss-assistant-thread-act{display:grid;place-items:center;width:26px;height:26px;border:0;border-radius:8px;background:transparent;color:var(--gemboss-text-muted);cursor:pointer;transition:background .12s ease,color .12s ease}.gemboss-assistant-thread-act:hover{background:#00000012;color:var(--gemboss-text)}.gemboss-assistant-thread-act.danger:hover{color:var(--gemboss-danger-strong)}.gemboss-assistant-thread-act svg{width:15px;height:15px;fill:currentColor}.gemboss-assistant-thread.editing{background:#00000012}.gemboss-assistant-thread-edit{display:flex;align-items:center;gap:2px;width:100%;padding:6px}.gemboss-assistant-thread-edit input{flex:1 1 auto;min-width:0}.gemboss-assistant-layout .gemboss-assistant-page{height:100%;max-width:820px;flex:1 1 auto;min-width:0;padding-top:16px}.gemboss-assistant-layout .gemboss-assistant-page.is-switching{opacity:.55;transition:opacity .12s ease;pointer-events:none}.gemboss-assistant-rail.is-collapsed{flex-basis:60px;width:60px;padding:16px 8px 12px}.gemboss-assistant-rail.is-collapsed .gemboss-assistant-rail-top{flex-direction:column;gap:8px}.gemboss-assistant-rail.is-collapsed .gemboss-assistant-newchat{justify-content:center;padding:8px;flex:0 0 auto}.gemboss-assistant-rail.is-collapsed .gemboss-assistant-newchat span,.gemboss-assistant-rail.is-collapsed .gemboss-assistant-search,.gemboss-assistant-rail.is-collapsed .gemboss-assistant-railfoot,.gemboss-assistant-rail.is-collapsed .gemboss-assistant-threads{display:none}@media (max-width: 760px){.gemboss-assistant-rail{flex-basis:60px;width:60px;padding:16px 8px 12px}.gemboss-assistant-rail .gemboss-assistant-rail-top{flex-direction:column;gap:8px}.gemboss-assistant-newchat{justify-content:center;padding:8px;flex:0 0 auto}.gemboss-assistant-newchat span,.gemboss-assistant-search,.gemboss-assistant-railfoot,.gemboss-assistant-threads,.gemboss-assistant-collapse{display:none}}.gemboss-assistant-page{height:calc(100dvh - 56px);width:100%;max-width:760px;margin:0 auto;padding:24px 0 16px;display:flex;flex-direction:column;min-height:0}.gemboss-assistant-page>*{flex:1 1 auto;min-height:0}.gemboss-assistant-empty{flex:1;display:grid;place-items:center;color:var(--gemboss-text-muted);font-size:14px}.gemboss-platform-shell{display:flow-root}.gemboss-platform-main{padding-bottom:calc(24px + var(--gemboss-invite-h, 0px))}@keyframes gemboss-assistant-pulse{0%,to{opacity:1}50%{opacity:.35}}.gb-account{position:relative}.gb-account>summary{list-style:none}.gb-account>summary::-webkit-details-marker{display:none}.gb-account-head{padding:12px 16px;border-bottom:1px solid var(--gemboss-divider)}.gb-account-name{font-size:13px;font-weight:600;color:var(--gemboss-text-strong)}.gb-account-email{font-size:12px;color:var(--gemboss-text-muted)}.gb-account-role{display:inline-block;margin-top:4px;padding:1px 6px;border-radius:4px;font-size:11px;font-weight:600;color:var(--gemboss-active-fg);background:var(--gemboss-active-bg)}.gb-account-form{margin:0}.gnav-scroll::-webkit-scrollbar{width:9px}.gnav-scroll::-webkit-scrollbar-track{background:transparent}.gnav-scroll::-webkit-scrollbar-thumb{background:#1f1e1d33;border-radius:6px;border:2px solid transparent;background-clip:content-box}
|
package/src/site.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.gb-site-wrap{width:min(100% - 32px,1132px);margin-inline:auto}.gb-site-header{position:sticky;top:0;z-index:50;background:var(--gemboss-surface);border-bottom:1px solid var(--gemboss-divider)}.gb-site-header__in{display:flex;align-items:center;gap:32px;height:64px;width:min(100% - 32px,1132px);margin-inline:auto;padding:0 24px}.gb-brand.gb-brand--site{display:inline-flex;align-items:center;gap:8px;height:44px;flex:0 0 auto;min-width:0;margin:0;padding:0 8px;border-radius:var(--gemboss-radius-md);color:var(--gb-brand-ink, var(--gemboss-text-strong));text-decoration:none;transition:background-color var(--gemboss-transition-fast) ease}.gb-brand.gb-brand--site:hover{background:var(--gemboss-hover);text-decoration:none}.gb-brand.gb-brand--site:focus-visible{outline:2px solid var(--gemboss-primary);outline-offset:2px}.gb-brand--site .gb-brand-gem{display:block;flex:0 0 auto}.gb-brand--site .gb-brand-name{min-width:0;font-family:Inter,var(--gemboss-font-sans);font-size:18px;font-weight:700;letter-spacing:-.02em;line-height:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}@media (max-width: 460px){.gb-brand.gb-brand--site{justify-content:flex-start}.gb-brand--site .gb-brand-name{display:inline}}.gb-site-nav{display:flex;align-items:center;gap:4px;min-width:0}.gb-site-link{display:inline-flex;align-items:center;min-height:36px;padding:8px 12px;border-radius:var(--gemboss-radius-md);color:var(--gemboss-text);font-size:var(--gemboss-fs-body);font-weight:500;line-height:20px;text-decoration:none;white-space:nowrap;transition:background-color var(--gemboss-transition-fast) ease,color var(--gemboss-transition-fast) ease}.gb-site-link:hover{background:var(--gemboss-hover);color:var(--gemboss-text-strong);text-decoration:none}.gb-site-link[aria-current=page]{color:var(--gemboss-text-strong);font-weight:600}.gb-site-link:focus-visible{outline:2px solid var(--gemboss-accent);outline-offset:2px}.gb-site-actions{display:flex;align-items:center;gap:4px;margin-left:auto}.gb-site-btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;height:40px;padding:0 20px;border:1px solid transparent;border-radius:var(--gemboss-radius-md);font-family:var(--gemboss-font-sans);font-size:var(--gemboss-fs-body);font-weight:600;line-height:1;letter-spacing:0;text-decoration:none;white-space:nowrap;cursor:pointer;transition:transform var(--gemboss-transition-fast) ease,box-shadow var(--gemboss-transition-fast) ease,border-color var(--gemboss-transition-fast) ease}.gb-site-btn:hover{text-decoration:none}.gb-site-btn:focus-visible{outline:2px solid var(--gemboss-accent);outline-offset:2px}.gb-site-btn--primary{background:var(--gemboss-primary);color:var(--gemboss-on-primary)}.gb-site-btn--primary:hover{transform:translateY(-1px);box-shadow:var(--gemboss-shadow-resting)}.gb-site-btn--secondary{background:transparent;color:var(--gemboss-text-strong);border-color:var(--gemboss-chip-line)}.gb-site-btn--secondary:hover{border-color:var(--gemboss-text-strong)}.gb-site-header .gb-site-btn{height:36px;padding:0 16px;margin-left:8px}@media (pointer: coarse),(max-width: 768px){.gb-site-btn,.gb-site-header .gb-site-btn,.gb-site-link{min-height:44px}}@media (max-width: 900px){.gb-site-header__in{gap:12px;padding:0 16px}.gb-site-nav{display:none}}@media (max-width: 640px){.gb-site-header__in{width:100%;padding:0 12px}}@media (max-width: 380px){.gb-site-actions .gb-site-link{display:none}}.gb-site-footer{padding:64px 0 32px;border-top:1px solid var(--gemboss-divider);color:var(--gemboss-text-muted);font-size:var(--gemboss-fs-body)}.gb-site-footer__grid{display:grid;grid-template-columns:minmax(0,1.5fr) repeat(auto-fit,minmax(140px,1fr));gap:32px}.gb-site-footer__col h4{margin:0 0 12px;font-size:13px;font-weight:600;color:var(--gemboss-text-strong)}.gb-site-footer__col a{display:block;padding:6px 0;color:var(--gemboss-text-muted);line-height:20px;text-decoration:none}.gb-site-footer__col a:hover{color:var(--gemboss-text-strong)}.gb-site-footer__bottom{display:flex;flex-wrap:wrap;justify-content:space-between;gap:12px 24px;margin-top:32px;padding-top:24px;border-top:1px solid var(--gemboss-divider);font-size:13px}.gb-site-footer__bottom a{color:inherit;text-decoration:none}.gb-site-footer__bottom a:hover{color:var(--gemboss-text-strong)}@media (max-width: 560px){.gb-site-footer__grid{grid-template-columns:1fr}}
|
package/src/site.tsx
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The public site layer (0.40.0): the top bar and the lockup of a PUBLIC page (gemboss.ai, the docs, news, a product's
|
|
3
|
+
* home page), as opposed to an app surface (the admin, a portal behind sign-in), which keeps `Topbar` + `BrandLockup`.
|
|
4
|
+
*
|
|
5
|
+
* Why it exists (Chris 20/10/2026, "có gemboss ui thì có gemboss website ui"): every public page drew its own bar, and
|
|
6
|
+
* the same detail drifted across them. Measured 20/10/2026: the logo name was 18px on gemboss.ai and the docs, 16px on
|
|
7
|
+
* news, 13.3px on the community home; the bar 65 / 57 / 69 / 56px tall. Chris's call the same day: TWO lockup sizes,
|
|
8
|
+
* site 18px and app 13.3px. This module is the site size, plus the bar, its links and buttons, and the footer.
|
|
9
|
+
*
|
|
10
|
+
* The values are gemboss.ai's own (website/assets/styles.css): bar 64px with a 1132px column, name 18px/700 with the
|
|
11
|
+
* docs' tracking, nav links 14px/500, "Start free" 36px in the bar and 40px elsewhere, footer columns 13px headings and
|
|
12
|
+
* 14px links. A plain-HTML page writes the same markup and links site.css (README "The public site layer").
|
|
13
|
+
*
|
|
14
|
+
* `SiteBrand` draws the gem from brand-gem.tsx and NOT through BrandLockup: brand.tsx brings the ServiceSwitcher, whose
|
|
15
|
+
* panel names internal tools and their admin URLs, and a public page must not carry it.
|
|
16
|
+
*/
|
|
17
|
+
import React from "react";
|
|
18
|
+
import "./site.css";
|
|
19
|
+
import { BrandGem } from "./brand-gem";
|
|
20
|
+
|
|
21
|
+
type AnchorProps = React.AnchorHTMLAttributes<HTMLAnchorElement>;
|
|
22
|
+
const cx = (...c: (string | false | null | undefined)[]) => c.filter(Boolean).join(" ");
|
|
23
|
+
|
|
24
|
+
/** The lockup at the site size: the same gem as BrandLockup, the name at 18px. */
|
|
25
|
+
export function SiteBrand({ name, href = "/", label, className, ...rest }: { name: string; label?: string } & AnchorProps) {
|
|
26
|
+
return (
|
|
27
|
+
<a className={cx("gb-brand gb-brand--site", className)} href={href} aria-label={label ?? `${name} home`} {...rest}>
|
|
28
|
+
<BrandGem />
|
|
29
|
+
<span className="gb-brand-name">{name}</span>
|
|
30
|
+
</a>
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* The public site's top bar. `brand`: a `SiteBrand`. `nav`: links (`<a className="gb-site-link">`), hidden at ≤900px.
|
|
36
|
+
* `actions`: the right side, e.g. a "Sign in" `gb-site-link` and a `gb-site-btn gb-site-btn--primary`.
|
|
37
|
+
*/
|
|
38
|
+
export function SiteHeader({ brand, nav, navLabel = "Main", actions, className, children }:
|
|
39
|
+
{ brand: React.ReactNode; nav?: React.ReactNode; navLabel?: string; actions?: React.ReactNode; className?: string; children?: React.ReactNode }) {
|
|
40
|
+
return (
|
|
41
|
+
<header className={cx("gb-site-header", className)}>
|
|
42
|
+
<div className="gb-site-header__in">
|
|
43
|
+
{brand}
|
|
44
|
+
{nav ? <nav className="gb-site-nav" aria-label={navLabel}>{nav}</nav> : null}
|
|
45
|
+
{actions ? <div className="gb-site-actions">{actions}</div> : null}
|
|
46
|
+
{children}
|
|
47
|
+
</div>
|
|
48
|
+
</header>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The team chat's row rules, as plain data (no React, no DOM): which messages start a new turn, where a day separator
|
|
3
|
+
* goes, where the "New messages" line goes. GemCare's chat had these rules in `renderChatMessages`
|
|
4
|
+
* (public/assets/inbox.js); they live here so GemCare and GemCommunity break a conversation into turns the same way,
|
|
5
|
+
* and an upgrade to them happens in one place. The components (team-chat.tsx) only draw what this returns.
|
|
6
|
+
*
|
|
7
|
+
* The rules (GemCare origin/main, 20/10/2026):
|
|
8
|
+
* - A message is GROUPED under the one before it (no avatar, no name line) when the same person wrote both, on the same
|
|
9
|
+
* day, less than 5 minutes apart, and it is not a reply (a reply starts a turn of its own: it answers someone else).
|
|
10
|
+
* - A day separator comes before the first message and before the first message of each new day (local time of the
|
|
11
|
+
* viewer). A new day also breaks a group: two lines either side of midnight are two turns.
|
|
12
|
+
* - The "New messages" line comes before the first message someone ELSE wrote that the viewer has not read. The
|
|
13
|
+
* viewer's own messages after the mark are not "new". The line also breaks a group, so the first new message
|
|
14
|
+
* always shows who wrote it.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
export type ChatRowMessage = {
|
|
18
|
+
id: string | number;
|
|
19
|
+
/** Who wrote it. Null/undefined: someone who has left (never grouped). */
|
|
20
|
+
authorId?: string | number | null;
|
|
21
|
+
/** When it was written: an ISO string, epoch ms, or a Date. */
|
|
22
|
+
at: string | number | Date;
|
|
23
|
+
/** The message it answers, if any. A reply is never grouped. */
|
|
24
|
+
replyToId?: string | number | null;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export type ChatRow<M> =
|
|
28
|
+
| { kind: "day"; key: string; date: Date }
|
|
29
|
+
| { kind: "new" }
|
|
30
|
+
| { kind: "message"; message: M; grouped: boolean };
|
|
31
|
+
|
|
32
|
+
export type ChatRowOptions<M> = {
|
|
33
|
+
/** The viewer: their own messages never get the "New messages" line. */
|
|
34
|
+
meId?: string | number | null;
|
|
35
|
+
/** True for a message the viewer has not read yet (e.g. `m.id > readUpTo`). No predicate, no line. */
|
|
36
|
+
isUnread?: (message: M) => boolean;
|
|
37
|
+
/** Messages closer than this are one turn. Default 5 minutes, as GemCare. */
|
|
38
|
+
groupWithinMs?: number;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const toDate = (at: string | number | Date) => (at instanceof Date ? at : new Date(at));
|
|
42
|
+
|
|
43
|
+
/** The viewer's local calendar day, as a key: two dates with the same key are the same day. */
|
|
44
|
+
export function chatDayKey(at: string | number | Date): string {
|
|
45
|
+
const d = toDate(at);
|
|
46
|
+
return `${d.getFullYear()}-${d.getMonth() + 1}-${d.getDate()}`;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** "Today", "Yesterday", or null (the caller formats older days with its own locale, e.g. "Mon, Sep 28"). */
|
|
50
|
+
export function chatDayWord(at: string | number | Date, now: Date = new Date()): "Today" | "Yesterday" | null {
|
|
51
|
+
const key = chatDayKey(at);
|
|
52
|
+
if (key === chatDayKey(now)) return "Today";
|
|
53
|
+
const y = new Date(now);
|
|
54
|
+
y.setDate(y.getDate() - 1);
|
|
55
|
+
return key === chatDayKey(y) ? "Yesterday" : null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** The rows to draw, in order: day separators, the "New messages" line, and each message with its `grouped` flag. */
|
|
59
|
+
export function teamChatRows<M extends ChatRowMessage>(messages: readonly M[], opts: ChatRowOptions<M> = {}): ChatRow<M>[] {
|
|
60
|
+
const within = opts.groupWithinMs ?? 5 * 60 * 1000;
|
|
61
|
+
const firstNew = opts.isUnread
|
|
62
|
+
? messages.findIndex((m) => opts.isUnread!(m) && (opts.meId == null || m.authorId !== opts.meId))
|
|
63
|
+
: -1;
|
|
64
|
+
const rows: ChatRow<M>[] = [];
|
|
65
|
+
messages.forEach((m, i) => {
|
|
66
|
+
const prev = i > 0 ? messages[i - 1] : undefined;
|
|
67
|
+
const at = toDate(m.at);
|
|
68
|
+
const newDay = !prev || chatDayKey(prev.at) !== chatDayKey(at);
|
|
69
|
+
if (newDay) rows.push({ kind: "day", key: chatDayKey(at), date: at });
|
|
70
|
+
const isFirstNew = i === firstNew;
|
|
71
|
+
if (isFirstNew) rows.push({ kind: "new" });
|
|
72
|
+
const grouped = Boolean(
|
|
73
|
+
prev && !newDay && !isFirstNew && m.authorId != null && prev.authorId === m.authorId && m.replyToId == null
|
|
74
|
+
&& at.getTime() - toDate(prev.at).getTime() < within,
|
|
75
|
+
);
|
|
76
|
+
rows.push({ kind: "message", message: m, grouped });
|
|
77
|
+
});
|
|
78
|
+
return rows;
|
|
79
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(function(v){"use strict";var j=v.gembossUI||(v.gembossUI={});if(j.teamChat)return;var H={reaction:'<path d="M16.5 10a6.5 6.5 0 1 1-6.5-6.5"/><path d="M7.5 11.8s.9 1.2 2.5 1.2 2.5-1.2 2.5-1.2"/><path d="M7.8 8.2h.01M12.2 8.2h.01"/><path d="M15 2.5v4M13 4.5h4"/>',reply:'<path d="M8 13.5 3.5 9 8 4.5M3.5 9h8a5 5 0 0 1 5 5v2"/>',thread:'<path d="M3 4.5h14v9H8.5L5 16.5v-3H3z"/><path d="M6.5 8h7M6.5 10.5h4.5"/>',chevronsDown:'<path d="M6 5.5l4 4 4-4M6 10.5l4 4 4-4"/>',hash:'<path d="M8 3.5 6.5 16.5M13.5 3.5 12 16.5M4 7.5h12.5M3.5 12.5H16"/>',lock:'<rect x="4.5" y="9" width="11" height="8" rx="1.5"/><path d="M7 9V6.5a3 3 0 0 1 6 0V9"/>',user:'<circle cx="10" cy="7" r="3.2"/><path d="M3.8 16.5c.8-2.8 3.3-4.5 6.2-4.5s5.4 1.7 6.2 4.5"/>',more:'<circle cx="4.5" cy="10" r="1"/><circle cx="10" cy="10" r="1"/><circle cx="15.5" cy="10" r="1"/>'},L=["\u{1F44D}","\u2705"],D=[["Smileys",[["\u{1F600}","grin smile happy"],["\u{1F603}","smile happy"],["\u{1F604}","smile laugh happy"],["\u{1F601}","grin beam"],["\u{1F606}","laugh squint"],["\u{1F605}","sweat smile relief"],["\u{1F602}","joy tears laugh lol"],["\u{1F923}","rofl rolling laugh"],["\u{1F60A}","blush smile"],["\u{1F607}","innocent halo"],["\u{1F642}","slight smile ok"],["\u{1F609}","wink"],["\u{1F60D}","heart eyes love"],["\u{1F970}","love hearts"],["\u{1F618}","kiss"],["\u{1F60B}","yum tasty"],["\u{1F61C}","wink tongue"],["\u{1F92A}","zany crazy"],["\u{1F917}","hug"],["\u{1F92D}","oops giggle"],["\u{1F914}","think hmm"],["\u{1F928}","raised eyebrow doubt"],["\u{1F610}","neutral"],["\u{1F636}","no words"],["\u{1F644}","eye roll"],["\u{1F60F}","smirk"],["\u{1F62C}","grimace awkward"],["\u{1F60C}","relieved"],["\u{1F634}","sleep tired"],["\u{1F637}","mask sick"],["\u{1F92F}","mind blown"],["\u{1F973}","party celebrate"],["\u{1F60E}","cool sunglasses"],["\u{1F913}","nerd"],["\u{1F615}","confused"],["\u{1F61F}","worried"],["\u{1F62E}","wow surprised"],["\u{1F632}","astonished"],["\u{1F633}","flushed embarrassed"],["\u{1F97A}","pleading please"],["\u{1F622}","cry sad"],["\u{1F62D}","sob crying"],["\u{1F631}","scream shock"],["\u{1F624}","huff frustrated"],["\u{1F621}","angry mad"],["\u{1F92C}","swear"],["\u{1F480}","dead skull"],["\u{1FAE0}","melting"],["\u{1FAE1}","salute"]]],["Hands",[["\u{1F44D}","like thumbs up yes ok"],["\u{1F44E}","dislike thumbs down no"],["\u{1F44C}","ok perfect"],["\u270C\uFE0F","peace victory"],["\u{1F91E}","fingers crossed luck"],["\u{1F91F}","love you"],["\u{1F918}","rock"],["\u{1F44F}","clap applause"],["\u{1F64C}","raise hands hooray"],["\u{1F450}","open hands"],["\u{1F91D}","handshake deal"],["\u{1F64F}","thanks please pray"],["\u{1F4AA}","strong muscle"],["\u{1F440}","eyes looking"],["\u{1FAF6}","heart hands"],["\u270D\uFE0F","writing"],["\u{1F44B}","wave hi bye"],["\u261D\uFE0F","point up"],["\u{1F447}","point down"],["\u{1F449}","point right"],["\u{1F448}","point left"],["\u{1F919}","call me"],["\u{1F590}\uFE0F","stop hand"],["\u{1F90C}","pinched"]]],["Marks",[["\u2764\uFE0F","heart love red"],["\u{1F9E1}","orange heart"],["\u{1F49B}","yellow heart"],["\u{1F49A}","green heart"],["\u{1F499}","blue heart"],["\u{1F49C}","purple heart"],["\u{1F5A4}","black heart"],["\u{1F4AF}","hundred perfect"],["\u2705","done check yes"],["\u2611\uFE0F","checked box"],["\u2714\uFE0F","check mark"],["\u274C","no cross wrong"],["\u2757","important exclamation"],["\u2753","question"],["\u26A0\uFE0F","warning"],["\u{1F525}","fire hot lit"],["\u2B50","star"],["\u2728","sparkles new"],["\u{1F4A1}","idea"],["\u{1F4CC}","pin"],["\u{1F680}","rocket ship launch"],["\u{1F3AF}","target goal"],["\u{1F197}","ok button"],["\u{1F195}","new"],["\u{1F534}","red circle urgent"],["\u{1F7E2}","green circle"],["\u{1F7E1}","yellow circle"],["\u2795","plus one add"]]],["Work",[["\u{1F389}","party tada celebrate"],["\u{1F38A}","confetti"],["\u{1F3C6}","trophy win"],["\u{1F947}","gold medal first"],["\u{1F381}","gift"],["\u2615","coffee"],["\u{1F37B}","cheers beer"],["\u{1F355}","pizza"],["\u{1F4C8}","chart up growth"],["\u{1F4C9}","chart down"],["\u{1F4B0}","money"],["\u{1F6D2}","cart shop"],["\u{1F4E6}","package order shipping"],["\u{1F9FE}","receipt invoice"],["\u{1F4DD}","note memo"],["\u{1F4C5}","calendar date"],["\u23F0","alarm time"],["\u23F3","waiting hourglass"],["\u{1F527}","fix wrench"],["\u{1F41B}","bug"],["\u{1F9EA}","test"],["\u{1F50D}","search look"],["\u{1F4AC}","comment chat"],["\u{1F4DE}","call phone"],["\u{1F4E7}","email"],["\u{1F512}","lock private"],["\u{1F517}","link"],["\u{1F5BC}\uFE0F","image picture"],["\u{1F4BB}","laptop computer"],["\u{1F4F1}","phone mobile"],["\u{1F648}","see no evil oops"],["\u{1F649}","hear no evil"],["\u{1F916}","robot bot ai"],["\u{1F9E0}","brain"],["\u{1F451}","crown vip"],["\u{1F48E}","gem diamond"]]]],A={channels:"Channels",conversation:"Conversation",back:"Back to channels",members:"Members",hideMembers:"Hide members",showMembers:"Show members",thread:"Thread",closeThread:"Close thread",replies:function(e){return e===1?"1 reply":e+" replies"},newMessages:"New messages",edited:"(edited)",someone:"Someone who has left",actionsFor:function(e){return"Actions for the message from "+e},react:function(e,t,n){return(n?"Remove":"Add")+" "+e+" on the message from "+t},moreReactions:function(e){return"More reactions for the message from "+e},reply:"Reply",replyTo:function(e){return"Reply to the message from "+e},replyInThread:"Reply in thread",replyInThreadTo:function(e){return"Reply in thread to the message from "+e},openThread:function(e,t){return"Open the thread, "+(e===1?"1 reply":e+" replies")+(t?", "+t:"")},jump:"Jump to the latest message",jumpNew:function(e){return"Jump to the latest message, "+e+" new"},message:"Message",send:"Send",attach:"Attach a file",stopReplying:"Stop replying",privateChannel:"private channel",directMessage:"direct message",mentioningYou:function(e){return e+" mentioning you"},unread:function(e){return e+" unread"},online:"Online",away:"Away",offline:"Offline"},T=Object.prototype.hasOwnProperty;function M(e){if(!e)return A;var t={},n;for(n in A)t[n]=A[n];for(n in e)T.call(e,n)&&(t[n]=e[n]);return t}var P=function(e){return typeof Node<"u"&&e instanceof Node},S=function(){return[].filter.call(arguments,Boolean).join(" ")};function a(e,t,n){var r=document.createElement(e),i;for(i in t)t[i]!==void 0&&t[i]!==null&&t[i]!==!1&&r.setAttribute(i,String(t[i]));return E(r,n)}function E(e,t){if(t==null||typeof t=="boolean"||t==="")return e;if(Array.isArray(t)){for(var n=0;n<t.length;n++)E(e,t[n]);return e}return e.appendChild(P(t)?t:document.createTextNode(String(t))),e}var ie=function(e){return e==null?void 0:String(e)},m=function(e,t){return t&&e.addEventListener("click",t),e},W=0;function _(e,t){var n=Number(t)||20,r=document.createElement("template");return r.innerHTML='<svg viewBox="0 0 20 20" width="'+n+'" height="'+n+'" aria-hidden="true" focusable="false"><g fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">'+(T.call(H,e)?H[e]:"")+"</g></svg>",r.content.firstChild}function x(e,t){var n=document.createElementNS("http://www.w3.org/2000/svg",e);for(var r in t)n.setAttribute(r,t[r]);return n}var le=function(){try{return new RegExp("^\\p{L}","u")}catch{return/^[A-Za-zÀ-ɏͰ-ϿЀ-ӿ]/}}();function F(e){var t=String(e).trim().split(/\s+/).filter(Boolean),n=t.filter(function(i){return le.test(i)}),r=n.length?n:t;return r.length?(r.length===1?r[0].slice(0,2):r[0][0]+r[r.length-1][0]).toUpperCase():"?"}function Y(e){var t=0,n=String(e),r,i,l;for(r=0;r<n.length;r++)i=n.charCodeAt(r),i>=55296&&i<=56319&&r+1<n.length&&(l=n.charCodeAt(r+1),l>=56320&&l<=57343&&(i=(i-55296)*1024+(l-56320)+65536,r++)),t=t*31+i>>>0;return t%8}var se={24:"gb-avatar--24",32:"gb-avatar--32",40:"gb-avatar--40",56:"gb-avatar--56"};function I(e,t,n,r){return n=n===void 0?24:n,a("span",{class:S("gb-avatar",se[n],r),"data-tone":Y(e),"aria-hidden":"true"},t?a("img",{class:"gb-avatar-img",src:t,alt:"",loading:"lazy",width:n,height:n}):F(e))}var R={},B=[];D.forEach(function(e){e[1].forEach(function(t){R[t[0]]=t[1],B.push(t[0])})});var ce=function(e){return typeof e=="string"&&T.call(R,e)},O=function(e){return T.call(R,e)?R[e]:""};function z(e){var t=String(e).trim().toLowerCase();return t?B.filter(function(n){return R[n].indexOf(t)>-1}):B.slice()}function V(e){return e.length>2?e.slice(0,2).join(", ")+" +"+(e.length-2):e.join(", ")}var Z="gemboss-ui:reactions-recent",G=9;function Q(){try{var e=JSON.parse(v.localStorage&&v.localStorage.getItem(Z)||"[]");return Array.isArray(e)?e.filter(function(t){return typeof t=="string"&&O(t)!==""}).slice(0,G):[]}catch{return[]}}function oe(e){try{var t=[e].concat(Q().filter(function(n){return n!==e})).slice(0,G);v.localStorage&&v.localStorage.setItem(Z,JSON.stringify(t))}catch{}}var q=function(e,t){return e.some(function(n){return n.emoji===t&&n.mine})};function U(e){var t=e.items||[],n=Q();n.length||(n=L.slice());var r=function(c){var u=q(t,c);return m(a("button",{type:"button",class:"ui-reaction-picker__btn",title:O(c).split(" ")[0]||c,"aria-label":((u?"Remove":"Add")+" "+c+" "+O(c)).trim(),"aria-pressed":String(u)},c),function(){e.onPick(c)})},i=function(c){return a("div",{class:"ui-reaction-picker__grid"},c.map(r))},l=function(c){return a("p",{class:"ui-reaction-picker__head"},c)},d=a("input",{type:"search",class:"gemboss-field ui-reaction-picker__search",placeholder:"Search emoji","aria-label":"Search emoji",autocomplete:"off",value:""}),o=a("div",{class:"ui-reaction-picker__body"}),h=function(){var c=d.value,u=c.trim()?z(c):null,s=[];u?s.push(u.length?i(u):a("p",{class:"ui-reaction-picker__empty"},"No emoji matches.")):(s.push(l("Frequently used"),i(n)),D.forEach(function(b){s.push(l(b[0]),i(b[1].map(function(y){return y[0]})))})),o.replaceChildren.apply(o,s)},g=a("div",{id:e.id,class:"ui-reaction-picker",role:"group","aria-label":"Pick a reaction"},[d,o]);return d.addEventListener("input",h),g.addEventListener("keydown",function(c){if(c.key==="Escape"){c.preventDefault(),c.stopPropagation(),e.onClose();return}var u=[].slice.call(o.querySelectorAll(".ui-reaction-picker__btn"));if(c.target===d){c.key==="Enter"&&(c.preventDefault(),u[0]&&u[0].click()),c.key==="ArrowDown"&&(c.preventDefault(),u[0]&&u[0].focus());return}var s=u.indexOf(document.activeElement);if(!(s<0)){var b=o.querySelector(".ui-reaction-picker__grid"),y=Math.max(1,Math.round((b?b.getBoundingClientRect().width:44)/44)),p={ArrowRight:1,ArrowLeft:-1,ArrowDown:y,ArrowUp:-y}[c.key];if(p){if(c.preventDefault(),s+p<0){d.focus();return}u[Math.min(u.length-1,s+p)]&&u[Math.min(u.length-1,s+p)].focus()}}}),h(),g}function X(e){var t=e.items||[],n=e.target===void 0?"this":e.target,r=e.canReact===void 0?!0:e.canReact;if(!t.length&&!r)return null;var i=!1,l=null,d="gb-tc-rp"+ ++W,o=null,h=function(s){if(!r){e.onSignIn&&e.onSignIn();return}q(t,s)||oe(s),e.onToggle&&e.onToggle(s)},g=a("div",{class:"ui-reactions__row"},t.map(function(s){return m(a("button",{type:"button",class:"ui-reaction"+(s.mine?" is-mine":""),"aria-pressed":ie(s.mine),title:s.names.join(", "),"aria-label":s.emoji+", "+s.names.join(", ")+". "+(s.mine?"Remove yours":"Add yours")},[a("span",{class:"ui-reaction__emoji"},s.emoji),a("span",{class:"ui-reaction__names"},V(s.names))]),function(){h(s.emoji)})})),c=a("div",{class:S("ui-reactions",e.className)},g),u=function(s,b){i=s,o.setAttribute("aria-expanded",String(i)),i?(o.setAttribute("aria-controls",d),l=U({id:d,items:t,onPick:function(y){u(!1,!0),h(y),o.focus()},onClose:function(){u(!1,!0),o.focus()}}),c.appendChild(l),b&&l.firstChild.focus()):(o.removeAttribute("aria-controls"),l&&l.remove(),l=null),b&&e.onOpenChange&&e.onOpenChange(i)};return r&&(o=a("button",{type:"button",class:"ui-reaction-add",title:"Add reaction","aria-label":"Add a reaction to "+n,"aria-expanded":"false"},_("reaction",18)),g.appendChild(m(o,function(){u(!i,!0)})),e.open&&u(!0,!1)),c}function ue(e){var t=e.read,n=e.of;if(n<=0)return null;var r=t>=n,i=Math.min(t,n)/n*Math.PI*2,l=x("svg",{viewBox:"0 0 14 14",width:"14",height:"14","aria-hidden":"true",focusable:"false"});return l.appendChild(x("circle",{cx:"7",cy:"7",r:"6",fill:r?"currentColor":"none",stroke:"currentColor","stroke-width":"1.4"})),r?l.appendChild(x("path",{class:"gb-tc-receipt__tick",d:"M4.2 7.2l1.9 1.9 3.7-4",fill:"none","stroke-width":"1.6","stroke-linecap":"round","stroke-linejoin":"round"})):t>0&&l.appendChild(x("path",{d:"M7 7 L7 1 A6 6 0 "+(i>Math.PI?1:0)+" 1 "+(7+6*Math.sin(i)).toFixed(2)+" "+(7-6*Math.cos(i)).toFixed(2)+" Z",fill:"currentColor"})),a("span",{class:S("gb-tc-receipt",r&&"gb-tc-receipt--all"),role:"img","aria-label":e.label,title:e.label},l)}function de(e){var t={ArrowRight:1,ArrowLeft:-1}[e.key],n=[].slice.call(e.currentTarget.querySelectorAll("button:not([disabled]), summary, a[href]")).filter(function(l){return l.offsetParent!==null}),r=n.indexOf(document.activeElement);if(!(r<0)){var i=t?n[(r+t+n.length)%n.length]:e.key==="Home"?n[0]:e.key==="End"?n[n.length-1]:null;i&&(e.preventDefault(),i.focus())}}function pe(e){var t=M(e.labels),n=e.author||t.someone,r=e.reactions||[],i=e.editor!=null,l=!!(e.picking&&e.onReact),d=null,o=null,h=!1,g=function(){var f=e.time;return P(f)&&h?f.cloneNode(!0):(h=!0,f)},c=function(){return S("gb-tc-msg",e.grouped&&"gb-tc-msg--grouped",e.mentionsMe&&"gb-tc-msg--mention",e.highlight&&"gb-tc-msg--highlight",e.sending&&"gb-tc-msg--sending",e.failed&&"gb-tc-msg--failed",l&&"gb-tc-msg--active",i&&"gb-tc-msg--editing",e.className)},u=a("li",{id:e.id,class:c(),"data-msg-id":e.messageId,tabindex:"-1"},e.grouped?a("time",{class:"gb-tc-msg__hover-time",datetime:e.dateTime},g()):e.avatar!=null?e.avatar:I(n,e.avatarSrc,32,"gb-tc-msg__av")),s=a("div",{class:"gb-tc-msg__main"});e.replyTo&&s.appendChild(m(a("button",{type:"button",class:"gb-tc-quote","aria-busy":e.replyTo.busy||void 0},[a("span",{class:"gb-tc-quote__who"},e.replyTo.author||t.someone),a("span",{class:"gb-tc-quote__text"},e.replyTo.excerpt)]),e.replyTo.onOpen)),s.appendChild(e.grouped?a("span",{class:"gb-tc-sr"},[n,", ",g(),": "]):a("div",{class:"gb-tc-msg__who"},[a("span",{class:"gb-tc-msg__name"},n),e.badges,a("time",{class:"gb-tc-msg__time",datetime:e.dateTime},g())])),i?s.appendChild(a("div",{class:"gb-tc-msg__editor"},e.editor)):(e.body!=null||e.edited||e.receipt)&&s.appendChild(a("div",{class:"gb-tc-msg__body"},[e.body,e.edited?a("span",{class:"gb-tc-msg__edited"},t.edited):null,e.receipt])),e.status&&s.appendChild(a("p",{class:"gb-tc-msg__status",role:e.failed?"alert":void 0},e.status)),e.attachments&&s.appendChild(a("div",{class:"gb-tc-msg__files"},e.attachments)),e.extra&&s.appendChild(a("div",{class:"gb-tc-msg__extra"},e.extra));var b=function(f,C){e.onPickingChange&&e.onPickingChange(f,C)},y=r.length?X({items:r,onToggle:e.onReact,canReact:!!e.onReact,target:"the message from "+n,open:e.reactionsPicking,onOpenChange:function(f){b("reactions",f)}}):null,p=e.thread,K=null;p&&p.count>0&&(K=m(a("button",{type:"button",class:"gb-tc-threadprev","aria-label":t.openThread(p.count,p.last==null?"":p.last)},[p.repliers&&p.repliers.length?a("span",{class:"gb-tc-threadprev__faces","aria-hidden":"true"},p.repliers.slice(0,3).map(function(f){return I(f.name,f.src,24)})):null,a("span",{class:"gb-tc-threadprev__count"},t.replies(p.count)),p.last?a("span",{class:"gb-tc-threadprev__last"},p.last):null]),p.onOpen)),E(s,[y,K]),u.appendChild(s);var N=function(f,C){l=f,u.className=c(),o&&o.setAttribute("aria-expanded",String(l)),l?(d=U({items:r,onPick:function(ke){N(!1,!0),e.onReact(ke),o.focus()},onClose:function(){N(!1,!0),o.focus()}}),s.insertBefore(d,y||K),C&&d.firstChild.focus()):d&&(d.remove(),d=null),C&&b("bar",l)};if(!i&&!e.sending&&(e.onReact||e.onReply||e.onOpenThread||e.moreActions)){var w=a("div",{class:"gb-tc-acts",role:"toolbar","aria-label":t.actionsFor(n)});e.onReact&&(L.forEach(function(f){var C=q(r,f);w.appendChild(m(a("button",{type:"button",class:"gb-tc-act gb-tc-act--quick","aria-pressed":String(C),"aria-label":t.react(f,n,C)},f),function(){e.onReact(f)}))}),o=a("button",{type:"button",class:"gb-tc-act","aria-expanded":String(l),"aria-label":t.moreReactions(n),title:"Add reaction"},_("reaction",18)),w.appendChild(m(o,function(){N(!l,!0)}))),e.onReply&&w.appendChild(m(a("button",{type:"button",class:"gb-tc-act","aria-label":t.replyTo(n),title:t.reply},_("reply",18)),e.onReply)),e.onOpenThread&&w.appendChild(m(a("button",{type:"button",class:"gb-tc-act","aria-label":t.replyInThreadTo(n),title:t.replyInThread},_("thread",18)),e.onOpenThread)),E(w,e.moreActions),w.addEventListener("keydown",de),u.appendChild(w)}return l&&N(!0,!1),u}function fe(e,t){return a("li",{class:"gb-tc-day"},t?a("time",{class:"gb-tc-day__label",datetime:t},e):a("span",{class:"gb-tc-day__label"},e))}function he(e){var t=M(e);return a("li",{class:"gb-tc-new"},a("span",{class:"gb-tc-new__label",role:"separator","aria-label":t.newMessages},t.newMessages))}function ge(e){return e=e||{},$(m(a("button",{type:"button",class:"gb-tc-jump"},_("chevronsDown",20)),e.onJump),e)}function $(e,t){t=t||{};var n=M(t.labels),r=t.count===void 0?0:t.count,i=e.querySelector(".gb-tc-jump__n");return t.visible===void 0||t.visible?e.removeAttribute("hidden"):e.setAttribute("hidden",""),e.setAttribute("aria-label",r?n.jumpNew(r):n.jump),r?(i||(i=e.appendChild(a("span",{class:"gb-tc-jump__n","aria-hidden":"true"}))),i.textContent=r>99?"99+":String(r),e):(i&&i.remove(),e)}var me={channel:"hash",private:"lock",dm:"user"},ee={online:"gb-tc-presence gb-tc-presence--online",away:"gb-tc-presence gb-tc-presence--away",offline:"gb-tc-presence gb-tc-presence--offline"};function te(e){var t=M(e.labels),n=e.kind===void 0?"channel":e.kind,r=e.unread===void 0?0:e.unread,i=e.mentions===void 0?0:e.mentions,l=[e.name,n==="private"?t.privateChannel:n==="dm"?t.directMessage:null,i?t.mentioningYou(i):null,r?t.unread(r):null].filter(Boolean).join(", "),d=[a("span",{class:"gb-tc-channel__glyph","aria-hidden":"true"},[_(me[n],16),n==="dm"&&e.online!==void 0?a("span",{class:ee[e.online?"online":"offline"]}):null]),a("span",{class:"gb-tc-channel__name"},e.name),i?a("span",{class:"gb-tc-badge gb-tc-badge--mention","aria-hidden":"true"},"@"+i):null,r?a("span",{class:"gb-tc-badge","aria-hidden":"true"},r):null],o=S("gb-tc-channel",r>0&&"gb-tc-channel--unread");return a("li",null,m(e.href!==void 0?a("a",{class:o,href:e.href,"aria-current":e.active?"page":void 0,"aria-label":l},d):a("button",{type:"button",class:o,"aria-current":e.active?"true":void 0,"aria-label":l},d),e.onOpen))}function ne(e,t,n,r){var i=(e.id==null?"gb-tc-s"+ ++W:e.id)+"-h";return a("div",{class:t[0],role:"group","aria-labelledby":i},[a("h3",{class:t[1],id:i},n),a("ul",{class:t[2]},(e.items||[]).map(function(l){return l&&!P(l)?r(l):l}))])}function be(e){return ne(e,["gb-tc-rail__section","gb-tc-rail__heading","gb-tc-rail__list"],e.label,te)}function ve(e){return ne(e,["gb-tc-people__section","gb-tc-people__heading","gb-tc-people__list"],[e.label,e.count!==void 0?" \u2014 "+e.count:null],ae)}function ae(e){var t=M(e.labels),n=[a("span",{class:"gb-tc-person__av"},[e.avatar!=null?e.avatar:I(e.name,e.src,32),e.presence?a("span",{class:ee[e.presence]},a("span",{class:"gb-tc-sr"},t[e.presence])):null]),a("span",{class:"gb-tc-person__text"},[a("span",{class:"gb-tc-person__name"},e.name),e.subtitle?a("span",{class:"gb-tc-person__sub"},e.subtitle):null]),e.role?a("span",{class:"gb-tc-person__role"},e.role):null],r=S("gb-tc-person",e.presence==="offline"&&"gb-tc-person--offline");return a("li",null,m(e.href!==void 0?a("a",{class:r,href:e.href,title:e.name},n):e.onSelect?a("button",{type:"button",class:r,title:e.name},n):a("div",{class:r,title:e.name},n),e.onSelect))}var J=function(e){return e instanceof Date?e:new Date(e)};function k(e){var t=J(e);return t.getFullYear()+"-"+(t.getMonth()+1)+"-"+t.getDate()}function ye(e,t){t=t===void 0?new Date:t;var n=k(e),r=new Date(t);return n===k(t)?"Today":(r.setDate(r.getDate()-1),n===k(r)?"Yesterday":null)}function _e(e,t){t=t||{};var n=t.groupWithinMs==null?5*60*1e3:t.groupWithinMs,r=-1,i=[],l;if(t.isUnread){for(l=0;l<e.length;l++)if(t.isUnread(e[l])&&(t.meId==null||e[l].authorId!==t.meId)){r=l;break}}return e.forEach(function(d,o){var h=o>0?e[o-1]:void 0,g=J(d.at),c=!h||k(h.at)!==k(g);c&&i.push({kind:"day",key:k(g),date:g}),o===r&&i.push({kind:"new"}),i.push({kind:"message",message:d,grouped:!!(h&&!c&&o!==r&&d.authorId!=null&&h.authorId===d.authorId&&d.replyToId==null&&g.getTime()-J(h.at).getTime()<n)})}),i}j.teamChat={message:pe,readReceipt:ue,daySeparator:fe,newMessagesLine:he,jumpToLatest:ge,updateJump:$,channelSection:be,channelItem:te,peopleSection:ve,personRow:ae,reactions:X,reactionPicker:U,avatar:function(e){return I(e.name,e.src,e.size,e.className)},icon:_,rows:_e,dayKey:k,dayWord:ye,LABELS:A,initialsOf:F,avatarTone:Y,isReactionEmoji:ce,reactionWords:O,searchReactions:z,reactionLabel:V,QUICK_REACTIONS:L,REACTION_GROUPS:D};function re(){!j.openModal&&v.console&&document.querySelector('script[src*="kit-plain"]')&&v.console.error("@gemboss/ui team-chat-plain.js: load it after kit-plain.js (kit-plain.js defines nothing when gembossUI exists)")}v.document&&(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",re,{once:!0}):re())})(typeof globalThis<"u"?globalThis:this);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.gb-tc{container:gb-tc / inline-size;position:relative;display:grid;grid-template-columns:auto minmax(0,1fr) auto;grid-template-rows:minmax(0,1fr);height:100%;min-height:0;overflow:hidden;box-sizing:border-box;background:var(--gemboss-surface);color:var(--gemboss-text);font-size:var(--gemboss-fs-body)}.gb-tc>.gb-tc-rail{grid-column:1;grid-row:1}.gb-tc>.gb-tc-main{grid-column:2;grid-row:1}.gb-tc>.gb-tc-thread,.gb-tc>.gb-tc-people{grid-column:3;grid-row:1;height:auto}.gb-tc-main,.gb-tc-rail,.gb-tc-thread,.gb-tc-people{display:flex;flex-direction:column;min-width:0;min-height:0}.gb-tc-main{position:relative}.gb-tc-main>*,.gb-tc-rail>*,.gb-tc-thread>*,.gb-tc-people>*{flex:none}.gb-tc-main>.gb-tc-body,.gb-tc-thread>.gb-tc-body,.gb-tc-rail>.gb-tc-rail__scroll,.gb-tc-people>.gb-tc-people__body{flex:1 1 0;min-height:0}.gb-tc-body,.gb-tc-composer,.gb-tc-rail__list,.gb-tc-people__list{grid-template-columns:minmax(0,1fr)}.gb-tc-scrim{display:none}.gb-tc :is(.gb-tc-thread,.gb-tc-people,.gb-tc-scrim,.gb-tc-replying,.gb-tc-jump,.gb-tc-composer__files,.gb-tc-composer__picker)[hidden]{display:none}.gb-tc-sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}.gb-tc-rail{width:var(--gb-tc-rail-w, 240px);box-sizing:border-box;border-right:1px solid var(--gemboss-divider);background:var(--gemboss-rail-bg)}.gb-tc-rail__head,.gb-tc-head,.gb-tc-panel-head{display:flex;align-items:center;gap:8px;min-height:56px;min-width:0;box-sizing:border-box;border-bottom:1px solid var(--gemboss-divider)}.gb-tc-rail__head{justify-content:space-between;padding:8px 8px 8px 16px}.gb-tc-rail__title,.gb-tc-panel-head__title{margin:0;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--gemboss-fs-h3);font-weight:650;line-height:1.3;color:var(--gemboss-text-strong)}.gb-tc-rail__actions,.gb-tc-head__actions,.gb-tc-panel-head__actions{flex:none;display:flex;align-items:center;gap:4px}.gb-tc-rail__scroll{overflow-y:auto;overscroll-behavior:contain;padding:8px 8px 16px}.gb-tc-rail__section+.gb-tc-rail__section{margin-top:16px}.gb-tc-rail__heading,.gb-tc-people__heading{margin:0 8px 4px;font-size:var(--gemboss-fs-caption);font-weight:650;line-height:20px;color:var(--gemboss-text-muted)}.gb-tc-rail__list,.gb-tc-people__list{list-style:none;margin:0;padding:0;display:grid;gap:1px}.gb-tc-channel{display:flex;align-items:center;gap:8px;width:100%;min-width:0;min-height:32px;padding:0 8px;box-sizing:border-box;border:0;border-radius:var(--gemboss-radius-md);background:none;cursor:pointer;text-align:left;text-decoration:none;font:inherit;font-size:var(--gemboss-fs-body);color:var(--gemboss-text-muted)}.gb-tc-channel:hover{background:var(--gemboss-hover);color:var(--gemboss-text-strong)}.gb-tc-channel:focus-visible{outline:2px solid var(--gemboss-accent);outline-offset:-2px}.gb-tc-channel--unread{color:var(--gemboss-text-strong);font-weight:650}.gb-tc-channel[aria-current]{background:var(--gemboss-accent-soft);color:var(--gemboss-accent-strong);font-weight:650}.gb-tc-channel__glyph{position:relative;flex:none;display:inline-grid;place-items:center;width:20px;height:20px}.gb-tc-channel__glyph>.gb-tc-presence{right:-3px;bottom:-2px;width:7px;height:7px;border-color:var(--gemboss-rail-bg)}.gb-tc-channel__name{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.gb-tc-badge{flex:none;min-width:20px;height:18px;padding:0 6px;box-sizing:border-box;border-radius:var(--gemboss-radius-full);background:var(--gemboss-accent);color:var(--gemboss-on-primary);font-size:var(--gemboss-fs-micro);font-weight:700;line-height:18px;text-align:center;font-variant-numeric:tabular-nums}.gb-tc-badge--mention{background:var(--gemboss-warning-soft);color:var(--gemboss-warning);box-shadow:inset 0 0 0 1px var(--gemboss-warning-border)}.gb-tc-head{padding:8px 12px 8px 16px}.gb-tc .gb-tc-head__back{display:none}.gb-tc-head__text,.gb-tc-panel-head__text{flex:1 1 auto;min-width:0}.gb-tc-head__title{margin:0;display:flex;align-items:center;gap:6px;min-width:0;font-size:var(--gemboss-fs-h3);font-weight:650;line-height:1.3;color:var(--gemboss-text-strong)}.gb-tc-head__glyph{flex:none;display:inline-flex;color:var(--gemboss-text-muted)}.gb-tc-head__name{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.gb-tc-head__sub,.gb-tc-panel-head__sub{margin:2px 0 0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--gemboss-fs-caption);line-height:16px;color:var(--gemboss-text-muted)}.gb-tc .gb-tc-head__members{gap:6px;padding:0 8px}.gb-tc .gb-tc-head__members[aria-expanded=true]{background:var(--gemboss-accent-soft);color:var(--gemboss-accent-strong)}.gb-tc-head__count{font-variant-numeric:tabular-nums}.gb-tc-body{position:relative;display:grid;grid-template-rows:minmax(0,1fr);min-width:0;min-height:0}.gb-tc-log{container:gb-tc-log / inline-size;min-height:0;overflow-y:auto;overscroll-behavior:contain}.gb-tc-log:focus-visible{outline:2px solid var(--gemboss-accent);outline-offset:-2px}.gb-tc-list{list-style:none;margin:0;padding:8px 0 16px;display:flex;flex-direction:column}.gb-tc-list>*{flex-shrink:0}.gb-tc-older,.gb-tc-empty,.gb-tc-status{display:flex;justify-content:center;padding:8px 16px;color:var(--gemboss-text-muted);font-size:var(--gemboss-fs-caption)}.gb-tc-empty{padding-block:32px;font-size:var(--gemboss-fs-body)}.gb-tc-status{justify-content:flex-start;padding-left:60px}.gb-tc-day{position:sticky;top:0;z-index:1;display:flex;justify-content:center;margin:4px 0 0;padding:4px 0;background:var(--gemboss-surface);pointer-events:none}.gb-tc-day__label{padding:1px 12px;border:1px solid var(--gemboss-divider);border-radius:var(--gemboss-radius-full);background:var(--gemboss-surface);box-shadow:var(--gemboss-shadow-resting);font-size:var(--gemboss-fs-caption);font-weight:600;line-height:20px;color:var(--gemboss-text)}.gb-tc-new{display:flex;align-items:center;gap:8px;margin:6px 16px;color:var(--gemboss-accent)}.gb-tc-new:before,.gb-tc-new:after{content:"";flex:1;height:1px;background:currentColor}.gb-tc-new__label{font-size:var(--gemboss-fs-caption);font-weight:650;line-height:16px}.gb-tc-msg{position:relative;display:grid;grid-template-columns:36px minmax(0,1fr);column-gap:8px;align-items:start;padding:8px 16px 4px}.gb-tc-msg:focus{outline:none}.gb-tc-msg:focus-visible{outline:2px solid var(--gemboss-accent);outline-offset:-2px}.gb-tc-msg--grouped{padding-block:2px}.gb-tc-msg>.gb-avatar,.gb-tc-msg>.gb-tc-msg__hover-time{grid-column:1;grid-row:1}.gb-tc-msg>.gb-tc-msg__main{grid-column:2;grid-row:1;min-width:0}.gb-avatar.gb-tc-msg__av{width:36px;height:36px;font-size:13px;margin-top:2px}.gb-tc-msg:hover,.gb-tc-msg--active,.gb-tc-msg--editing{background:var(--gemboss-divider-soft)}.gb-tc-msg:has(:focus-visible){background:var(--gemboss-divider-soft)}.gb-tc-msg__hover-time{justify-self:end;opacity:0;white-space:nowrap;font-variant-numeric:tabular-nums;font-size:var(--gemboss-fs-micro);line-height:20px;color:var(--gemboss-text-muted)}.gb-tc-msg:hover>.gb-tc-msg__hover-time,.gb-tc-msg:focus-within>.gb-tc-msg__hover-time{opacity:1}.gb-tc-msg__who{display:flex;flex-wrap:wrap;align-items:baseline;column-gap:8px;min-width:0;line-height:20px}.gb-tc-msg__name{font-weight:650;color:var(--gemboss-text-strong);overflow-wrap:anywhere}.gb-tc-msg__time{font-size:var(--gemboss-fs-caption);color:var(--gemboss-text-muted);font-variant-numeric:tabular-nums}.gb-tc-msg__body{white-space:pre-wrap;overflow-wrap:anywhere;line-height:20px;color:var(--gemboss-text)}.gb-tc-msg__edited{margin-left:4px;font-size:var(--gemboss-fs-caption);color:var(--gemboss-text-muted);white-space:nowrap}.gb-tc-msg__status{margin:2px 0 0;font-size:var(--gemboss-fs-caption);color:var(--gemboss-text-muted)}.gb-tc-msg--failed .gb-tc-msg__status{color:var(--gemboss-danger)}.gb-tc-msg--sending>.gb-tc-msg__main{opacity:.6}.gb-tc-msg__files,.gb-tc-msg__extra{margin-top:4px;min-width:0}.gb-tc-msg__editor{display:grid;gap:6px;margin-top:2px}.gb-tc-msg--mention{box-shadow:inset 2px 0 0 var(--gemboss-warning)}.gb-tc-msg--highlight{background:var(--gemboss-accent-soft)}.gb-tc-quote{display:flex;align-items:baseline;gap:6px;max-width:100%;min-height:28px;margin:0 0 4px;padding:4px 8px;box-sizing:border-box;border:0;border-left:2px solid var(--gemboss-divider);border-radius:0 var(--gemboss-radius-sm) var(--gemboss-radius-sm) 0;background:none;cursor:pointer;text-align:left;font:inherit;font-size:var(--gemboss-fs-caption);color:var(--gemboss-text-muted)}.gb-tc-quote:hover{background:var(--gemboss-hover)}.gb-tc-quote:focus-visible{outline:2px solid var(--gemboss-accent);outline-offset:1px}.gb-tc-quote[aria-busy=true]{opacity:.55;cursor:progress}.gb-tc-quote__who{flex:none;font-weight:650;color:var(--gemboss-text)}.gb-tc-quote__text{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.gb-tc-msg .ui-reactions{margin-top:2px}.gb-tc-msg .ui-reaction-picker{margin:4px 0;max-width:calc(100cqi - 64px)}.gb-tc-threadprev{display:flex;align-items:center;gap:8px;max-width:100%;min-height:32px;margin-top:4px;padding:4px 8px 4px 4px;box-sizing:border-box;border:1px solid transparent;border-radius:var(--gemboss-radius-md);background:none;cursor:pointer;text-align:left;font:inherit;font-size:var(--gemboss-fs-caption)}.gb-tc-threadprev:hover{border-color:var(--gemboss-divider);background:var(--gemboss-surface)}.gb-tc-threadprev:focus-visible{outline:2px solid var(--gemboss-accent);outline-offset:1px}.gb-tc-threadprev__faces{flex:none;display:flex;gap:2px}.gb-tc-threadprev__faces>.gb-avatar{width:22px;height:22px;font-size:9px;border-radius:var(--gemboss-radius-xs)}.gb-tc-threadprev__count{flex:none;font-weight:650;color:var(--gemboss-accent-strong)}.gb-tc-threadprev__last{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--gemboss-text-muted)}.gb-tc-receipt{display:inline-flex;margin-left:6px;vertical-align:-2px;color:var(--gemboss-text-muted)}.gb-tc-receipt--all{color:var(--gemboss-success)}.gb-tc-receipt__tick{stroke:var(--gemboss-surface)}.gb-tc-acts{position:absolute;top:-14px;right:16px;z-index:2;display:flex;align-items:center;gap:0;padding:2px;border:1px solid var(--gemboss-divider);border-radius:var(--gemboss-radius-md);background:var(--gemboss-surface);box-shadow:var(--gemboss-shadow-raised);white-space:nowrap;opacity:0;pointer-events:none}.gb-tc-list>.gb-tc-msg:first-child>.gb-tc-acts{top:2px}.gb-tc-msg:hover>.gb-tc-acts,.gb-tc-msg--active>.gb-tc-acts,.gb-tc-acts:focus-within{opacity:1;pointer-events:auto}.gb-tc-act{display:inline-grid;place-items:center;min-width:32px;height:32px;padding:0 6px;box-sizing:border-box;border:0;border-radius:var(--gemboss-radius-sm);background:transparent;cursor:pointer;font:inherit;font-size:16px;line-height:1;color:var(--gemboss-text-muted)}.gb-tc-act:hover{background:var(--gemboss-hover);color:var(--gemboss-text-strong)}.gb-tc-act:focus-visible{outline:2px solid var(--gemboss-accent);outline-offset:-2px}.gb-tc-act[aria-pressed=true],.gb-tc-act[aria-expanded=true]{background:var(--gemboss-accent-soft);color:var(--gemboss-accent-strong)}@container gb-tc-log (max-width: 560px){.gb-tc-act--quick{display:none}.gb-tc-acts{right:8px}.gb-tc-msg{padding-inline:12px}.gb-tc-status{padding-left:56px}}@media (hover: none){.gb-tc-msg:focus-within{background:var(--gemboss-divider-soft)}.gb-tc-msg:focus-within>.gb-tc-acts{opacity:1;pointer-events:auto}.gb-tc-act--quick{display:none}.gb-tc-acts{top:-22px}}.gb-tc-jump{position:absolute;right:16px;bottom:16px;z-index:3;display:grid;place-items:center;width:40px;height:40px;padding:0;border:1px solid var(--gemboss-divider);border-radius:50%;background:var(--gemboss-surface);color:var(--gemboss-text-strong);box-shadow:var(--gemboss-shadow-raised);cursor:pointer}.gb-tc-jump[hidden]{display:none}.gb-tc-jump:hover{background:var(--gemboss-hover)}.gb-tc-jump:focus-visible{outline:2px solid var(--gemboss-accent);outline-offset:2px}.gb-tc-jump__n{position:absolute;top:-6px;right:-6px;min-width:20px;height:20px;padding:0 4px;box-sizing:border-box;border-radius:var(--gemboss-radius-full);background:var(--gemboss-accent);color:var(--gemboss-on-primary);font-size:var(--gemboss-fs-micro);font-weight:700;line-height:20px;text-align:center;font-variant-numeric:tabular-nums}.gb-tc-composer{display:grid;gap:6px;min-width:0;padding:8px 16px 16px}.gb-tc-composer__box{display:flex;align-items:flex-end;gap:4px;min-width:0;padding:4px;box-sizing:border-box;border:1px solid var(--gemboss-field-line);border-radius:var(--gemboss-radius-lg);background:var(--gemboss-field-bg)}.gb-tc-composer__box:hover{border-color:var(--gemboss-field-line-hover)}.gb-tc-composer__box:focus-within{border-color:var(--gemboss-field-line-active);box-shadow:0 0 0 1px var(--gemboss-field-line-active)}.gb-tc-composer__input{flex:1 1 auto;min-width:0;min-height:32px;max-height:40vh;margin:0;padding:6px 4px;box-sizing:border-box;border:0;background:transparent;resize:none;outline:none;field-sizing:content;font:inherit;font-size:var(--gemboss-fs-body);line-height:20px;color:var(--gemboss-field-ink)}.gb-tc-composer__input::placeholder{color:var(--gemboss-field-placeholder)}.gb-tc-composer__input:disabled{cursor:not-allowed}.gb-tc-composer__box>.ui-btn--icon{width:32px;height:32px}.gb-tc .gb-tc-composer__attach,.gb-tc .gb-tc-composer__send,.gb-tc .gb-tc-panel-head__close,.gb-tc .gb-tc-people__toggle{flex:none}.gb-tc .gb-tc-composer__send:disabled{opacity:.35}.gb-tc-replying{display:flex;align-items:center;gap:8px;min-width:0;padding:2px 2px 2px 8px;box-sizing:border-box;border-left:2px solid var(--gemboss-accent);border-radius:var(--gemboss-radius-sm);background:var(--gemboss-accent-soft)}.gb-tc-replying__text{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--gemboss-fs-caption);color:var(--gemboss-text)}.gb-tc-composer__files,.gb-tc-composer__picker{min-width:0}.gb-tc-composer__picker{max-height:240px;overflow-y:auto;overscroll-behavior:contain}.gb-tc-composer__also{justify-self:start}.gb-tc-composer__error{margin:0;font-size:var(--gemboss-fs-caption);color:var(--gemboss-danger)}.gb-tc-thread,.gb-tc-people{height:100%;box-sizing:border-box;border-left:1px solid var(--gemboss-divider);background:var(--gemboss-surface);color:var(--gemboss-text)}.gb-tc-thread:focus,.gb-tc-people:focus{outline:none}.gb-tc-panel-head{padding:8px 8px 8px 16px}.gb-tc-thread{width:var(--gb-tc-thread-w, 380px)}.gb-tc-thread__note{margin:8px 16px 0;font-size:var(--gemboss-fs-caption);color:var(--gemboss-text-muted)}.gb-tc-thread__note--error{color:var(--gemboss-danger-strong, var(--gemboss-danger))}.gb-tc-thread__count{display:flex;align-items:center;gap:8px;margin:8px 16px 4px;font-size:var(--gemboss-fs-caption);color:var(--gemboss-text-muted)}.gb-tc-thread__count:after{content:"";flex:1;border-top:1px solid var(--gemboss-divider)}.gb-tc-people{width:var(--gb-tc-people-w, 260px)}.gb-tc-people__body{overflow-y:auto;overscroll-behavior:contain;padding:8px 8px 16px}.gb-tc-people__section+.gb-tc-people__section{margin-top:16px}.gb-tc-person{display:flex;align-items:center;gap:8px;width:100%;min-width:0;min-height:40px;padding:4px 8px;box-sizing:border-box;border:0;border-radius:var(--gemboss-radius-md);background:none;text-align:left;text-decoration:none;font:inherit;color:inherit}:is(a,button).gb-tc-person{cursor:pointer}:is(a,button).gb-tc-person:hover{background:var(--gemboss-hover)}.gb-tc-person:focus-visible{outline:2px solid var(--gemboss-accent);outline-offset:-2px}.gb-tc-person__av{position:relative;flex:none;display:inline-flex}.gb-tc-person__text{flex:1 1 auto;min-width:0;display:grid}.gb-tc-person__name,.gb-tc-person__sub{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.gb-tc-person__name{font-weight:550;line-height:20px;color:var(--gemboss-text-strong)}.gb-tc-person__sub{font-size:var(--gemboss-fs-caption);line-height:16px;color:var(--gemboss-text-muted)}.gb-tc-person__role{flex:none;padding:0 6px;border:1px solid var(--gemboss-divider);border-radius:var(--gemboss-radius-full);font-size:var(--gemboss-fs-micro);font-weight:650;line-height:18px;color:var(--gemboss-text-muted)}.gb-tc-person--offline .gb-tc-person__name{color:var(--gemboss-text-muted)}.gb-tc-person--offline .gb-avatar{opacity:.55}.gb-tc-presence{position:absolute;right:-1px;bottom:-1px;width:8px;height:8px;border-radius:50%;border:2px solid var(--gemboss-surface);background:var(--gemboss-success)}.gb-tc-presence--away{background:var(--gemboss-warning)}.gb-tc-presence--offline{background:var(--gemboss-surface);box-shadow:inset 0 0 0 1.5px var(--gemboss-text-muted)}.gb-tc-presence--online{background:var(--gemboss-success)}.gb-tc-people[data-collapsed]{width:56px}.gb-tc-people[data-collapsed] .gb-tc-panel-head{justify-content:center;padding:8px 0}.gb-tc-people[data-collapsed] .gb-tc-panel-head__actions{display:none}.gb-tc-people[data-collapsed] :is(.gb-tc-panel-head__text,.gb-tc-people__heading,.gb-tc-person__text,.gb-tc-person__role){position:absolute;width:1px;height:1px;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}.gb-tc-people[data-collapsed] .gb-tc-people__body{padding:8px 4px}.gb-tc-people[data-collapsed] .gb-tc-people__section+.gb-tc-people__section{margin-top:8px;padding-top:8px;border-top:1px solid var(--gemboss-divider)}.gb-tc-people[data-collapsed] .gb-tc-person{justify-content:center;padding:4px 0}@media (pointer: coarse),(max-width: 47.9975em){.gb-tc-channel,.gb-tc-person,.gb-tc-quote,.gb-tc-threadprev{min-height:44px}.gb-tc-act{min-width:44px;height:44px}.gb-tc-jump{width:48px;height:48px}.gb-tc-composer__input{font-size:16px;min-height:44px;padding-block:12px}.gb-tc-composer__box>.ui-btn--icon{width:44px;height:44px}}@container gb-tc (max-width: 1100px){.gb-tc>.gb-tc-thread,.gb-tc>.gb-tc-people,.gb-tc>.gb-tc-scrim{grid-area:1 / 1 / -1 / -1}.gb-tc>.gb-tc-thread,.gb-tc>.gb-tc-people{position:absolute;top:0;right:0;bottom:0;z-index:5;width:min(var(--gb-tc-thread-w, 380px),100%);box-shadow:var(--gemboss-shadow-overlay)}.gb-tc>.gb-tc-people{width:min(var(--gb-tc-people-w, 260px) + 40px,100%)}.gb-tc>.gb-tc-people[data-collapsed]{display:none}.gb-tc>.gb-tc-scrim{display:block;position:absolute;inset:0;z-index:4;background:color-mix(in srgb,var(--gemboss-dark-bg) 32%,transparent)}}@container gb-tc (max-width: 760px){.gb-tc>.gb-tc-rail{grid-column:1 / -1;width:auto;border-right:0}.gb-tc>.gb-tc-main{grid-column:1 / -1}.gb-tc:not([data-view=list])>.gb-tc-rail,.gb-tc[data-view=list]>:is(.gb-tc-main,.gb-tc-scrim,.gb-tc-thread,.gb-tc-people){display:none}.gb-tc>.gb-tc-thread,.gb-tc>.gb-tc-people{left:0;width:auto;border-left:0;box-shadow:none}.gb-tc>.gb-tc-scrim{display:none}.gb-tc .gb-tc-head__back{display:inline-flex;margin-left:-8px}.gb-tc-head{padding-left:12px}.gb-tc-composer{padding:8px 12px 12px}}@media (prefers-reduced-motion: no-preference){.gb-tc-msg{transition:background-color .15s linear}.gb-tc-acts{transition:opacity .1s linear}}
|