@gemboss/ui 0.48.0 → 0.50.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 +260 -0
- package/README.md +127 -11
- package/catalog/editor.html +1 -1
- package/catalog/index.html +10 -10
- package/gemboss-ui.css +3 -3
- package/package.json +22 -2
- package/parts/components.css +3 -3
- package/parts/core.css +1 -1
- package/parts/shell.css +2 -2
- package/src/app-shell.css +1 -1
- package/src/assistant/chat.tsx +50 -6
- package/src/assistant/host.tsx +19 -7
- package/src/assistant/index.ts +1 -1
- package/src/assistant/sessions.tsx +2 -1
- package/src/assistant-chat.css +1 -1
- package/src/assistant.css +1 -1
- package/src/auth-signin-plain.js +1 -0
- package/src/auth-sso-plain.js +1 -1
- package/src/auth.tsx +105 -8
- package/src/briefing-card.css +1 -1
- package/src/collections.css +1 -1
- package/src/create-shell.css +1 -0
- package/src/create-shell.tsx +221 -0
- package/src/editor-insert.css +1 -0
- package/src/editor.css +1 -1
- package/src/empty-stage.css +1 -0
- package/src/empty-stage.tsx +31 -0
- package/src/icons.tsx +2 -0
- package/src/index-table.tsx +7 -4
- package/src/index.ts +16 -2
- package/src/kit-plain.css +1 -1
- package/src/kit-plain.js +1 -1
- package/src/language-switcher.tsx +10 -41
- package/src/list-page.css +1 -0
- package/src/list-page.tsx +239 -0
- package/src/menu-extras.css +1 -0
- package/src/menu-keys.ts +199 -0
- package/src/menu-layer.ts +2 -1
- package/src/menu-plain.js +1 -0
- package/src/menu.css +1 -0
- package/src/menu.tsx +83 -35
- package/src/pager-extras.css +1 -0
- package/src/pager.css +1 -0
- package/src/pager.tsx +88 -0
- package/src/portal.css +1 -1
- package/src/segmented.tsx +12 -2
- package/src/selection.tsx +3 -1
- package/src/session-rail-plain.js +1 -1
- package/src/settings-dialog.tsx +29 -2
- package/src/shell.css +1 -1
- package/src/stage-path.css +1 -0
- package/src/stage-path.tsx +89 -0
- package/src/stage.css +1 -0
- package/src/stage.tsx +52 -0
- package/src/starting-point.css +1 -0
- package/src/starting-point.tsx +93 -0
- package/src/status-list.css +1 -0
- package/src/status-list.tsx +65 -0
- package/src/status-matrix.css +1 -0
- package/src/status-matrix.tsx +131 -0
- package/src/team-chat.css +1 -1
- package/src/translation-row.css +1 -0
- package/src/translation-row.tsx +113 -0
- package/src/ui.css +1 -1
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Status matrix — @gemboss/ui, unreleased (after 0.49.0). Rows × columns of status cells: GemPress's language map (redesign approved
|
|
3
|
+
* by Chris 23/10/2026), one row per collection, one column per language, each cell "how many are live of how many there are, and
|
|
4
|
+
* what waits". GemPress drew it with its own classes (`gp-cov`); GemNews and GemCommunity translations will want the same map, and
|
|
5
|
+
* nothing in it is about languages: any "N things × M targets, each partly done" fits (stores × channels, pages × locales).
|
|
6
|
+
*
|
|
7
|
+
* The contract it draws, which every surface keeps:
|
|
8
|
+
* - a cell says "**live** / total", and under it what waits: "5 draft · 2 changed" (and "N missing" when the surface counts them);
|
|
9
|
+
* - its tone is ALL LIVE (green number) or HAS DRAFTS (amber number), nothing else: a cell part live with nothing waiting is plain.
|
|
10
|
+
* Colour never stands alone, there is always the number and the words (`statusMatrixTone` is the rule, pure, for a plain page);
|
|
11
|
+
* - a cell with nothing to count (`null`, absent, or a row whose `total` is 0) is "—", never "0 / 0";
|
|
12
|
+
* - each row's name is its header (`th scope="row"`), a link when it has `href`; the column heads are the surface's words.
|
|
13
|
+
*
|
|
14
|
+
* Built on the kit table (`ui-table-wrap` + `ui-table`, `is-num` for the numbers, all in the core): this entry only adds the cells,
|
|
15
|
+
* the row header and the caption. Presentational and server-renderable: no state, no effect; the colours are tokens, so the dark
|
|
16
|
+
* palette follows. `status-matrix.css` is its own entry; a plain-HTML surface links `@gemboss/ui/status-matrix.css` and writes the
|
|
17
|
+
* classes listed at the top of that file.
|
|
18
|
+
*/
|
|
19
|
+
import "./status-matrix.css";
|
|
20
|
+
import React, { type ReactNode } from "react";
|
|
21
|
+
|
|
22
|
+
const cx = (...p: Array<string | false | null | undefined>) => p.filter(Boolean).join(" ");
|
|
23
|
+
const whole = (n: unknown) => (typeof n === "number" && Number.isFinite(n) ? Math.max(Math.round(n), 0) : 0);
|
|
24
|
+
|
|
25
|
+
/** One cell: how many are live, and what waits. */
|
|
26
|
+
export interface StatusMatrixCell {
|
|
27
|
+
live: number;
|
|
28
|
+
draft: number;
|
|
29
|
+
/** Live, but its source changed since (it needs another look). */
|
|
30
|
+
changed?: number;
|
|
31
|
+
/** Not started. Printed only when the surface counts it. */
|
|
32
|
+
missing?: number;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface StatusMatrixColumn {
|
|
36
|
+
key: string;
|
|
37
|
+
label: ReactNode;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface StatusMatrixRow {
|
|
41
|
+
key: string;
|
|
42
|
+
label: ReactNode;
|
|
43
|
+
href?: string;
|
|
44
|
+
/** How many there are in the row; every cell counts against it. */
|
|
45
|
+
total: number;
|
|
46
|
+
/** By column key. `null` or absent: nothing to count in that column ("—"). */
|
|
47
|
+
cells: Readonly<Record<string, StatusMatrixCell | null | undefined>>;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface StatusMatrixLabels {
|
|
51
|
+
draft?: (n: string) => string;
|
|
52
|
+
changed?: (n: string) => string;
|
|
53
|
+
missing?: (n: string) => string;
|
|
54
|
+
/** A cell with nothing to count (default "—"). */
|
|
55
|
+
none?: ReactNode;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface StatusMatrixProps {
|
|
59
|
+
columns: readonly StatusMatrixColumn[];
|
|
60
|
+
rows: readonly StatusMatrixRow[];
|
|
61
|
+
/** What the numbers mean, under the table: "Live / published. Nothing goes live until a person approves it." */
|
|
62
|
+
caption?: ReactNode;
|
|
63
|
+
/** The heading over the rows' names ("Collection"). */
|
|
64
|
+
rowHeading?: ReactNode;
|
|
65
|
+
/** When set, a column after the names with each row's total under this heading ("EN": the source has them all). */
|
|
66
|
+
totalHeading?: ReactNode;
|
|
67
|
+
/** A number as the surface writes it ("1,204"). Default `String`. */
|
|
68
|
+
format?: (n: number) => string;
|
|
69
|
+
labels?: StatusMatrixLabels;
|
|
70
|
+
className?: string;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export type StatusMatrixTone = "live" | "draft" | null;
|
|
74
|
+
|
|
75
|
+
/** A cell's tone: every one live, or something waiting (drafts or changed), or neither. Nothing to count has no tone. */
|
|
76
|
+
export function statusMatrixTone(cell: StatusMatrixCell | null | undefined, total: number): StatusMatrixTone {
|
|
77
|
+
const t = whole(total);
|
|
78
|
+
if (!cell || !t) return null;
|
|
79
|
+
if (whole(cell.live) >= t) return "live";
|
|
80
|
+
return whole(cell.draft) + whole(cell.changed) > 0 ? "draft" : null;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function StatusMatrix({ columns, rows, caption, rowHeading, totalHeading, format = String, labels, className }: StatusMatrixProps) {
|
|
84
|
+
if (!rows.length) return null; // the surface says why the map is empty; an empty grid of headers says nothing
|
|
85
|
+
const words = {
|
|
86
|
+
draft: labels?.draft ?? ((n: string) => `${n} draft`),
|
|
87
|
+
changed: labels?.changed ?? ((n: string) => `${n} changed`),
|
|
88
|
+
missing: labels?.missing ?? ((n: string) => `${n} missing`),
|
|
89
|
+
};
|
|
90
|
+
const none = labels?.none ?? "—";
|
|
91
|
+
const cell = (row: StatusMatrixRow, col: StatusMatrixColumn) => {
|
|
92
|
+
const c = row.cells[col.key];
|
|
93
|
+
const total = whole(row.total);
|
|
94
|
+
if (!c || !total) return <td key={col.key} className="is-num ui-matrix__cell">{none}</td>;
|
|
95
|
+
const tone = statusMatrixTone(c, total);
|
|
96
|
+
const waits = [
|
|
97
|
+
whole(c.draft) ? words.draft(format(whole(c.draft))) : "",
|
|
98
|
+
whole(c.changed) ? words.changed(format(whole(c.changed))) : "",
|
|
99
|
+
whole(c.missing) ? words.missing(format(whole(c.missing))) : "",
|
|
100
|
+
].filter(Boolean);
|
|
101
|
+
return (
|
|
102
|
+
<td key={col.key} className={cx("is-num ui-matrix__cell", tone === "live" && "ui-matrix__cell--live", tone === "draft" && "ui-matrix__cell--draft")}>
|
|
103
|
+
<b className="ui-matrix__live">{format(Math.min(whole(c.live), total))}</b>{` / ${format(total)}`}
|
|
104
|
+
{waits.length ? <span className="ui-matrix__sub">{waits.join(" · ")}</span> : null}
|
|
105
|
+
</td>
|
|
106
|
+
);
|
|
107
|
+
};
|
|
108
|
+
return (
|
|
109
|
+
<div className="ui-table-wrap">
|
|
110
|
+
<table className={cx("ui-table ui-matrix", className)}>
|
|
111
|
+
{caption ? <caption className="ui-matrix__caption">{caption}</caption> : null}
|
|
112
|
+
<thead>
|
|
113
|
+
<tr>
|
|
114
|
+
<th scope="col">{rowHeading}</th>
|
|
115
|
+
{totalHeading ? <th scope="col" className="is-num">{totalHeading}</th> : null}
|
|
116
|
+
{columns.map((c) => <th scope="col" className="is-num" key={c.key}>{c.label}</th>)}
|
|
117
|
+
</tr>
|
|
118
|
+
</thead>
|
|
119
|
+
<tbody>
|
|
120
|
+
{rows.map((r) => (
|
|
121
|
+
<tr key={r.key}>
|
|
122
|
+
<th scope="row" className="ui-matrix__row">{r.href ? <a href={r.href}>{r.label}</a> : r.label}</th>
|
|
123
|
+
{totalHeading ? <td className="is-num">{format(whole(r.total))}</td> : null}
|
|
124
|
+
{columns.map((c) => cell(r, c))}
|
|
125
|
+
</tr>
|
|
126
|
+
))}
|
|
127
|
+
</tbody>
|
|
128
|
+
</table>
|
|
129
|
+
</div>
|
|
130
|
+
);
|
|
131
|
+
}
|
package/src/team-chat.css
CHANGED
|
@@ -1 +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-avatar.gb-tc-channel__av{width:20px;height:20px;font-size:8px}.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-avatar.gb-tc-head__av{flex:none;margin-right:2px}.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{position:relative;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__emoji,.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 .gb-tc-composer__emoji[aria-expanded=true]{background:var(--gemboss-accent-soft);color:var(--gemboss-accent-strong)}.gb-tc-composer__emoji-pop{position:absolute;right:0;bottom:calc(100% + 6px);z-index:4}.gb-tc-composer__emoji-pop .ui-reaction-picker__body{max-height:min(300px,40vh)}.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}}@container gb-tc (max-width: 359px){.gb-tc-composer__box{gap:0}}@media (prefers-reduced-motion: no-preference){.gb-tc-msg{transition:background-color .15s linear}.gb-tc-acts{transition:opacity .1s linear}}
|
|
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;left:0;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-avatar.gb-tc-channel__av{width:20px;height:20px;font-size:8px}.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-avatar.gb-tc-head__av{flex:none;margin-right:2px}.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{position:relative;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__emoji,.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 .gb-tc-composer__emoji[aria-expanded=true]{background:var(--gemboss-accent-soft);color:var(--gemboss-accent-strong)}.gb-tc-composer__emoji-pop{position:absolute;right:0;bottom:calc(100% + 6px);z-index:4}.gb-tc-composer__emoji-pop .ui-reaction-picker__body{max-height:min(300px,40vh)}.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}}@container gb-tc (max-width: 359px){.gb-tc-composer__box{gap:0}}@media (prefers-reduced-motion: no-preference){.gb-tc-msg{transition:background-color .15s linear}.gb-tc-acts{transition:opacity .1s linear}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.ui-translation{container-type:inline-size;display:grid;gap:var(--ui-space-2);padding:var(--ui-space-3);border:1px solid var(--ui-border);border-radius:var(--ui-radius-lg);background:var(--ui-surface)}.ui-translation--current{border-color:var(--gemboss-primary);box-shadow:inset 3px 0 0 var(--gemboss-primary)}.ui-translation:focus-visible{outline:2px solid var(--ui-focus);outline-offset:2px}.ui-translation--current:focus{outline:none}.ui-translation__head,.ui-translation__foot{display:flex;flex-wrap:wrap;align-items:center;gap:var(--ui-space-2);font-size:var(--ui-fs-caption);line-height:16px;color:var(--ui-text-muted)}.ui-translation__key{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:var(--ui-fs-caption);color:var(--ui-text-strong);overflow-wrap:anywhere}.ui-translation__state{flex:none}.ui-translation__by{min-width:0;overflow-wrap:anywhere}.ui-translation__body{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:var(--ui-space-2) var(--ui-space-4)}.ui-translation__source{margin:0;padding-top:6px;font-size:var(--ui-fs-body);line-height:20px;color:var(--ui-text-muted);white-space:pre-wrap;overflow-wrap:anywhere}.ui-translation__target{display:grid;min-width:0}.ui-translation__checks{min-width:0;overflow-wrap:anywhere}.ui-translation__checks--ok{color:var(--gemboss-success-strong)}.ui-translation__checks--warn{font-weight:600;color:var(--gemboss-warning)}.ui-translation__action{display:inline-flex;gap:var(--ui-space-2);margin-left:auto}@media (max-width: 900px){.ui-translation__body{grid-template-columns:minmax(0,1fr)}}@container (max-width: 600px){.ui-translation__body{grid-template-columns:minmax(0,1fr)}}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Translation row — @gemboss/ui, unreleased (after 0.49.0). One translatable string under review: GemPress's review screen
|
|
3
|
+
* (redesign approved by Chris 23/10/2026) shows a page's strings one under the other, the source beside its translation, and a
|
|
4
|
+
* person walks them with J / K, fixes what the checks flag and approves. GemPress drew it with its own CSS (`gp-str`); GemNews and
|
|
5
|
+
* GemCommunity translations will review strings the same way, so the row lives here.
|
|
6
|
+
*
|
|
7
|
+
* The contract it draws, which every surface keeps:
|
|
8
|
+
* - a head: the string's key (code), its state as a badge (`draft` "To review", `approved`, `stale` "Source changed", `missing`
|
|
9
|
+
* "Not translated"; the words are the surface's with `stateLabel`), and who wrote it (`by`: the model, or "edited by a person");
|
|
10
|
+
* - the source and the target SIDE BY SIDE, read across like a translation tool; one column under 900px, or when the row itself
|
|
11
|
+
* is narrower than 600px (beside a pinned panel);
|
|
12
|
+
* - a foot: what the checks found on the left (green "✓ Numbers and tags match", or the problems in amber words; colour never
|
|
13
|
+
* alone), the surface's `action` on the right (Approve, Save and approve);
|
|
14
|
+
* - `current`: an ink border and a 3px ink bar on the left, the row the keys act on (`aria-current`). The row is focusable
|
|
15
|
+
* (`tabIndex={-1}`, never a Tab stop) so a keyboard-driven list can move focus to it; pass `id` to find it.
|
|
16
|
+
*
|
|
17
|
+
* Presentational and server-renderable: no state, no effect. The editable control is the SURFACE's (it owns the value, the save,
|
|
18
|
+
* the keys): pass it as `target`, a node, or a function that gets the ids of the source and the checks so the control can say
|
|
19
|
+
* `aria-describedby` (a screen reader then hears the source and the problems with the field). Other attributes (`onFocus`,
|
|
20
|
+
* `data-*`) go on the row. `translation-row.css` is its own entry; a plain-HTML surface links `@gemboss/ui/translation-row.css`
|
|
21
|
+
* and writes the classes listed at the top of that file.
|
|
22
|
+
*/
|
|
23
|
+
import "./translation-row.css";
|
|
24
|
+
import React, { type HTMLAttributes, type ReactNode } from "react";
|
|
25
|
+
|
|
26
|
+
const cx = (...p: Array<string | false | null | undefined>) => p.filter(Boolean).join(" ");
|
|
27
|
+
|
|
28
|
+
export type TranslationState = "draft" | "approved" | "stale" | "missing";
|
|
29
|
+
|
|
30
|
+
/** The badge's words by default (GemPress's). */
|
|
31
|
+
export const TRANSLATION_STATE_LABELS: Readonly<Record<TranslationState, string>> = {
|
|
32
|
+
draft: "To review",
|
|
33
|
+
approved: "Approved",
|
|
34
|
+
stale: "Source changed",
|
|
35
|
+
missing: "Not translated",
|
|
36
|
+
};
|
|
37
|
+
/** The kit badge tone for each state (kit-plain.css). Not translated is the plain badge: nothing to review yet. */
|
|
38
|
+
const TONE: Readonly<Record<TranslationState, string | null>> = {
|
|
39
|
+
draft: "ui-badge--info",
|
|
40
|
+
approved: "ui-badge--success",
|
|
41
|
+
stale: "ui-badge--warning",
|
|
42
|
+
missing: null,
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/** The ids a `target` function gets: the key, the source and the checks line, for `aria-describedby`. */
|
|
46
|
+
export interface TranslationRowIds {
|
|
47
|
+
key: string;
|
|
48
|
+
source: string;
|
|
49
|
+
checks: string;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface TranslationRowProps extends Omit<HTMLAttributes<HTMLElement>, "children" | "className" | "id" | "tabIndex"> {
|
|
53
|
+
/** The string's key: "hero.title". */
|
|
54
|
+
keyName: string;
|
|
55
|
+
state: TranslationState;
|
|
56
|
+
source: ReactNode;
|
|
57
|
+
/** The source's language (`lang` on it), so it is read in the right voice. */
|
|
58
|
+
sourceLang?: string;
|
|
59
|
+
/** The editable control, owned by the surface: a node, or a function given the ids it can point `aria-describedby` at. */
|
|
60
|
+
target: ReactNode | ((ids: TranslationRowIds) => ReactNode);
|
|
61
|
+
/** What the checks found: `ok` with what matched, or not with the problems. Absent: no line (an approved string). */
|
|
62
|
+
checks?: { ok: boolean; text: ReactNode } | null;
|
|
63
|
+
/** Who wrote it: the model's name, or "edited by a person". */
|
|
64
|
+
by?: ReactNode;
|
|
65
|
+
/** The surface's button(s), at the end of the foot. */
|
|
66
|
+
action?: ReactNode;
|
|
67
|
+
/** The row the keys act on. */
|
|
68
|
+
current?: boolean;
|
|
69
|
+
/** The badge's words, when the surface's are not the defaults (another language). */
|
|
70
|
+
stateLabel?: ReactNode;
|
|
71
|
+
/** The row's id, and the base of the ids inside it. Default from `keyName`; pass one when a key shows twice on a page. */
|
|
72
|
+
id?: string;
|
|
73
|
+
/** `li` inside the surface's `<ol>` (default `div`). */
|
|
74
|
+
as?: "div" | "li";
|
|
75
|
+
className?: string;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** The base of a row's ids when the surface gives none: "hero.title" → "ui-tr-hero-title". */
|
|
79
|
+
export function translationRowId(keyName: string): string {
|
|
80
|
+
return `ui-tr-${keyName.replace(/[^\w-]+/g, "-").replace(/^-+|-+$/g, "") || "row"}`;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function TranslationRow({
|
|
84
|
+
keyName, state, source, sourceLang, target, checks, by, action, current, stateLabel, id, as = "div", className, ...rest
|
|
85
|
+
}: TranslationRowProps) {
|
|
86
|
+
const base = id ?? translationRowId(keyName);
|
|
87
|
+
const ids: TranslationRowIds = { key: `${base}-key`, source: `${base}-src`, checks: `${base}-checks` };
|
|
88
|
+
const Tag = as;
|
|
89
|
+
return (
|
|
90
|
+
<Tag {...rest} id={id} className={cx("ui-translation", current && "ui-translation--current", className)} data-state={state} tabIndex={-1}
|
|
91
|
+
aria-current={current ? "true" : undefined}>
|
|
92
|
+
<div className="ui-translation__head">
|
|
93
|
+
<code className="ui-translation__key" id={ids.key}>{keyName}</code>
|
|
94
|
+
<span className={cx("ui-badge", TONE[state], "ui-translation__state")}>{stateLabel ?? TRANSLATION_STATE_LABELS[state] ?? state}</span>
|
|
95
|
+
{by ? <span className="ui-translation__by">{by}</span> : null}
|
|
96
|
+
</div>
|
|
97
|
+
<div className="ui-translation__body">
|
|
98
|
+
<p className="ui-translation__source" id={ids.source} lang={sourceLang}>{source}</p>
|
|
99
|
+
<div className="ui-translation__target">{typeof target === "function" ? target(ids) : target}</div>
|
|
100
|
+
</div>
|
|
101
|
+
{checks || action ? (
|
|
102
|
+
<div className="ui-translation__foot">
|
|
103
|
+
{checks ? (
|
|
104
|
+
<span className={cx("ui-translation__checks", checks.ok ? "ui-translation__checks--ok" : "ui-translation__checks--warn")} id={ids.checks}>
|
|
105
|
+
{checks.ok ? <span aria-hidden="true">✓ </span> : null}{checks.text}
|
|
106
|
+
</span>
|
|
107
|
+
) : null}
|
|
108
|
+
{action ? <span className="ui-translation__action">{action}</span> : null}
|
|
109
|
+
</div>
|
|
110
|
+
) : null}
|
|
111
|
+
</Tag>
|
|
112
|
+
);
|
|
113
|
+
}
|
package/src/ui.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
:root{--ui-surface: #ffffff;--ui-surface: var(--gemboss-surface, #ffffff);--ui-surface-2: var(--gemboss-hover, #eceef2);--ui-text: var(--gemboss-text, #1b1c1e);--ui-text-muted: var(--gemboss-text-muted, #686b71);--ui-border: var(--gemboss-divider, #e5e7ea);--ui-accent: var(--gemboss-primary, #1b1c1e);--ui-accent-hover: var(--gemboss-primary-dark, #000000);--ui-accent-fg: #ffffff;--ui-accent-soft: var(--gemboss-active-bg, #f0f1f4);--ui-accent-strong: var(--gemboss-active-fg, #1b1c1e);--ui-text-strong: var(--gemboss-text-strong, #1b1c1e);--ui-success-fg: var(--gemboss-success);--ui-warning-fg: var(--gemboss-primary-dark);--ui-danger-fg: var(--gemboss-danger-strong);--ui-focus: var(--gemboss-accent, #5661f5);--ui-radius-sm: 6px;--ui-radius-md: 8px;--ui-radius-lg: 12px;--ui-space-1: 4px;--ui-space-2: 8px;--ui-space-3: 12px;--ui-space-4: 16px;--ui-control-h: 32px;--ui-btn-h: 28px;--ui-card-shadow: 0 1px 0 rgba(26,26,26,.07);--ui-fs-body: 13px;--ui-fs-caption: 12px;--ui-content-max: 900px}.gemboss-admin-shell{--ui-surface: var(--adm-surface);--ui-surface-2: var(--adm-surface-2);--ui-text: var(--adm-text);--ui-text-muted: var(--adm-muted);--ui-border: var(--adm-divider);--ui-accent: var(--adm-accent);--ui-accent-hover: var(--gemboss-primary-dark, #000000);--ui-accent-fg: #ffffff;--ui-accent-soft: var(--adm-accent-soft);--ui-accent-strong: var(--adm-accent-fg);--ui-text-strong: var(--adm-text-strong);--ui-success-fg: color-mix(in srgb, var(--gemboss-success) 70%, #ffffff);--ui-warning-fg: color-mix(in srgb, #c99a2e 70%, #ffffff);--ui-danger-fg: color-mix(in srgb, var(--gemboss-danger-strong) 70%, #ffffff);--ui-focus: var(--adm-accent);--ui-card-shadow: none}.ui-btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--ui-space-2);height:var(--ui-btn-h);padding:0 var(--ui-space-3);box-sizing:border-box;line-height:1;white-space:nowrap;vertical-align:middle;border-radius:var(--ui-radius-md);font-family:inherit;font-size:var(--ui-fs-caption);font-weight:550;cursor:pointer;text-decoration:none;user-select:none;border:1px solid var(--ui-border);background:transparent;color:var(--ui-text);transition:background .12s ease,border-color .12s ease}.ui-btn:hover{background:var(--ui-surface-2);text-decoration:none}.ui-btn:focus-visible{outline:2px solid var(--ui-focus);outline-offset:2px}.ui-btn[disabled],.ui-btn[aria-disabled=true]{opacity:.5;cursor:not-allowed}.ui-btn--primary{background:var(--ui-accent);border-color:var(--ui-accent);color:var(--ui-accent-fg)}.ui-btn--primary:hover{background:var(--ui-accent-hover);border-color:var(--ui-accent-hover)}.ui-btn--ghost{border-color:transparent;background:transparent;color:var(--ui-text-muted)}.ui-btn--ghost:hover{background:var(--ui-surface-2);color:var(--ui-text)}.ui-btn--on,.ui-btn--on:hover{background:var(--ui-accent-soft);border-color:var(--ui-accent);color:var(--ui-accent-strong)}.ui-card{background:var(--ui-surface);border:1px solid var(--ui-border);border-radius:var(--ui-radius-lg);box-shadow:var(--ui-card-shadow);padding:var(--ui-space-4);color:var(--ui-text)}.ui-card__title{font-size:14px;line-height:20px;font-weight:650;margin:0 0 var(--ui-space-2)}.ui-card__head{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--ui-space-2);margin-bottom:var(--ui-space-2)}.ui-card__head>.ui-card__title{margin:0}.ui-card__head>:last-child:not(.ui-card__title){display:flex;flex-wrap:wrap;gap:var(--ui-space-2)}.ui-select{height:var(--ui-control-h);padding:0 32px 0 12px;max-width:100%;background:var(--p-color-input-bg-surface, var(--gemboss-field-bg)) url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 20 20'><path fill='%239a9aa4' d='M5 7l5 5 5-5z'/></svg>") no-repeat right 10px center;border:1px solid var(--p-color-input-border, var(--gemboss-field-line));border-radius:var(--ui-radius-md);color:var(--p-color-text, var(--gemboss-field-ink));font-family:inherit;font-size:var(--ui-fs-body);font-weight:450;appearance:none;-webkit-appearance:none;cursor:pointer}.ui-select:hover:not(:disabled){border-color:var(--p-color-input-border-hover, var(--gemboss-field-line-hover));background-color:var(--p-color-input-bg-surface-hover, var(--gemboss-field-bg-hover))}.ui-select:focus{outline:none}.ui-select:focus-visible:not(:disabled){outline:2px solid var(--p-color-border-focus, var(--ui-focus));outline-offset:1px;border-color:var(--p-color-input-border-active, var(--gemboss-field-line-active))}.ui-select:disabled{opacity:.5;cursor:not-allowed}.ui-select--slim{height:30px;font-size:var(--ui-fs-caption)}.ui-tag{display:inline-flex;align-items:center;gap:6px;font-size:var(--ui-fs-caption);line-height:20px;font-weight:450;padding:0 6px;border-radius:var(--ui-radius-md);background:var(--ui-surface-2);color:var(--ui-text-muted)}.ui-tag--accent{background:var(--adm-accent-soft, rgba(20,22,26,.05));color:var(--adm-accent-fg, var(--ui-accent))}.ui-tag--chip{text-transform:none;letter-spacing:0;font-size:11px;font-weight:500;padding:2px 8px;background:transparent;border:1px solid var(--ui-border);font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.ui-tag--chip.ui-tag--accent{color:var(--adm-accent-fg, var(--ui-accent));border-color:var(--ui-accent);background:transparent}.ui-chips{display:flex;flex-wrap:wrap;gap:var(--ui-space-2, 8px);margin:0;padding:0;list-style:none}.ui-chips>a.ui-tag--chip{min-height:28px;padding:4px 12px;border-radius:var(--ui-radius-md, 8px);font-family:inherit;font-size:var(--gemboss-fs-caption, 12px);color:var(--ui-text);text-decoration:none}.ui-chips>a.ui-tag--chip:hover{background:var(--ui-surface-2);border-color:var(--ui-text-muted)}.ui-chips>a.ui-tag--chip:focus-visible{outline:2px solid var(--p-color-border-focus, var(--ui-focus));outline-offset:1px}.ui-chips>a.ui-tag--chip[aria-current=page]{background:var(--ui-accent-soft);border-color:var(--ui-accent);color:var(--ui-accent-strong);font-weight:600}.ui-tag--success{background:var(--gemboss-success-soft);color:var(--gemboss-success-strong, var(--gemboss-success))}.ui-tag--warning{background:var(--gemboss-warning-soft);color:var(--gemboss-warning)}.ui-tag--danger{background:var(--gemboss-danger-soft);color:var(--gemboss-danger-strong, var(--gemboss-danger))}.ui-muted{color:var(--ui-text-muted);font-size:var(--ui-fs-caption)}.ui-page-head{margin-bottom:20px}.ui-page-head h1{color:var(--ui-text-strong);font-size:20px;line-height:24px;font-weight:700;letter-spacing:-.01em}.ui-page-head p{color:var(--ui-text-muted);font-size:var(--ui-fs-body);margin-top:4px}.ui-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:12px;margin-bottom:20px}.ui-metrics{display:flex;flex-wrap:wrap;gap:8px;margin:2px 0}.ui-metric{display:flex;flex-direction:column;gap:1px;min-width:78px;padding:8px 12px;background:var(--ui-surface);border:1px solid var(--ui-border);border-radius:12px}a.ui-metric{text-decoration:none;color:inherit}a.ui-metric:hover{border-color:var(--ui-text-muted)}a.ui-metric:focus-visible{outline:2px solid var(--ui-focus);outline-offset:1px}.ui-metric__val{font-size:17px;font-weight:700;color:var(--ui-text);font-variant-numeric:tabular-nums;line-height:1.15}.ui-metric__lbl{font-size:var(--ui-fs-caption);font-weight:500;color:var(--ui-text-muted)}.ui-metric--success{border-color:color-mix(in srgb,var(--gemboss-success) 40%,transparent)}.ui-metric--success .ui-metric__val{color:var(--ui-success-fg)}.ui-metric--warning{border-color:color-mix(in srgb,#c99a2e 40%,transparent)}.ui-metric--warning .ui-metric__val{color:var(--ui-warning-fg)}.ui-metric--danger{border-color:color-mix(in srgb,var(--gemboss-danger-strong) 40%,transparent)}.ui-metric--danger .ui-metric__val{color:var(--ui-danger-fg)}.ui-dl{display:grid;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:12px 16px;margin:0}.ui-dl>div{min-width:0}.ui-dl dt{font-size:var(--ui-fs-caption);color:var(--ui-text-muted)}.ui-dl dd{margin:4px 0 0;font-weight:600;color:var(--ui-text);overflow-wrap:anywhere}.ui-notice{padding:12px 16px;border-radius:var(--ui-radius-md);border:1px solid var(--ui-border);background:var(--ui-surface-2);color:var(--ui-text);font-size:var(--ui-fs-body);overflow-wrap:anywhere}.ui-notice--warning{background:var(--gemboss-warning-soft);border-color:var(--gemboss-warning-border);color:var(--gemboss-warning)}.ui-notice--danger{background:var(--gemboss-danger-soft);border-color:var(--gemboss-danger-border);color:var(--gemboss-danger-strong)}.ui-notice--success{background:var(--gemboss-success-soft);border-color:var(--gemboss-success-border);color:var(--gemboss-success-strong)}.ui-pager{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:16px 0}.ui-pager>a{display:inline-flex;align-items:center;min-height:32px;padding:0 12px;border:1px solid var(--ui-border);border-radius:var(--ui-radius-md);color:var(--ui-text);text-decoration:none;font-size:var(--ui-fs-body)}.ui-pager>a:hover{background:var(--ui-surface-2)}.ui-pager>a:focus-visible{outline:2px solid var(--p-color-border-focus, var(--ui-focus));outline-offset:1px}.ui-pager>[aria-current=page]{color:var(--ui-text-muted);font-size:var(--ui-fs-caption)}.ui-badge{display:inline-flex;align-items:center;gap:4px;font-size:var(--ui-fs-caption);line-height:16px;font-weight:450;white-space:nowrap;padding:2px 8px;border-radius:var(--ui-radius-md);background:color-mix(in srgb,var(--ui-text) 8%,transparent);color:var(--ui-text-muted)}.ui-overlay{position:fixed;inset:0;z-index:500;background:#00000080;display:grid;place-items:center;padding:20px}.ui-modal{width:min(460px,100%);background:var(--ui-surface);border:1px solid var(--ui-border);border-radius:16px;box-shadow:var(--gemboss-shadow-overlay, 0 20px 60px rgba(0, 0, 0, .4));overflow:hidden}.ui-modal:focus{outline:none}.ui-modal__head{display:flex;align-items:center;gap:12px;padding:12px 16px;border-bottom:1px solid var(--ui-border);font-size:14px;line-height:20px;font-weight:650;color:var(--ui-text)}.ui-modal__title{min-width:0;flex:1 1 auto}.ui-modal__close{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;border:0;border-radius:var(--ui-radius-md, 8px);background:transparent;color:var(--ui-text-muted);cursor:pointer}.ui-modal__close svg{width:20px;height:20px}.ui-modal__close:hover{background:var(--ui-surface-2);color:var(--ui-text)}.ui-modal__close:focus-visible{outline:2px solid var(--ui-focus);outline-offset:-2px}.ui-modal__body{padding:16px}.ui-modal__foot{display:flex;flex-wrap:wrap;gap:8px;justify-content:flex-end;padding:12px 16px;border-top:1px solid var(--ui-border)}@media (pointer: coarse),(max-width: 47.9975em){.ui-modal__close{width:44px;height:44px;margin:-8px -8px -8px 0}:is(.ui-modal__head,.ui-modal__foot) .ui-btn{min-height:44px}}.ui-modal--lg{position:relative}.ui-textarea{width:100%;min-height:96px;resize:vertical;box-sizing:border-box;background:var(--p-color-input-bg-surface, var(--gemboss-field-bg));border:1px solid var(--p-color-input-border, var(--gemboss-field-line));border-radius:var(--ui-radius-md);padding:12px;color:var(--p-color-text, var(--gemboss-field-ink));font-size:var(--ui-fs-body);line-height:1.5;font-family:inherit}.ui-textarea::placeholder{color:var(--p-color-text-secondary, var(--gemboss-field-placeholder))}.ui-textarea:hover:not(:disabled){border-color:var(--p-color-input-border-hover, var(--gemboss-field-line-hover));background-color:var(--p-color-input-bg-surface-hover, var(--gemboss-field-bg-hover))}.ui-textarea:focus{outline:none}.ui-textarea:focus-visible:not(:disabled){outline:2px solid var(--p-color-border-focus, var(--ui-focus));outline-offset:1px;border-color:var(--p-color-input-border-active, var(--gemboss-field-line-active))}.ui-textarea:disabled{opacity:.5;cursor:not-allowed}@media (max-width: 47.9975em){.ui-select.ui-select,.ui-textarea{font-size:16px}.ui-select:not(.ui-select--slim){min-height:44px}}.ui-seg{display:inline-flex;border:1px solid var(--ui-border);border-radius:var(--ui-radius-md);overflow:hidden;overflow:clip;min-width:0}.ui-seg :is(button,a){display:inline-grid;place-items:center;width:calc(var(--ui-btn-h) - 2px);height:calc(var(--ui-btn-h) - 2px);border:0;background:transparent;color:var(--ui-text-muted);cursor:pointer;font-family:inherit}.ui-seg :is(button,a).is-text{width:auto;padding:0 12px;font-size:var(--ui-fs-caption);font-weight:550;grid-auto-flow:column;column-gap:2px}.ui-seg :is(button,a)+:is(button,a){border-left:1px solid var(--ui-border)}.ui-seg :is(button,a):hover{background:var(--ui-surface-2);color:var(--ui-text)}.ui-seg :is(button,a):focus-visible{outline:2px solid var(--ui-focus);outline-offset:-2px}.ui-seg a{display:inline-flex;align-items:center;justify-content:center;text-decoration:none;color:var(--ui-text-muted)}.ui-seg a[aria-current=page],.ui-seg button.active{background:var(--ui-accent-soft);color:var(--ui-accent-strong)}.ui-seg svg{width:16px;height:16px;fill:currentColor}.ui-seg svg[fill=none]{fill:none}.ui-seg :is(button,a):is(:disabled,[aria-disabled=true]){opacity:.45;cursor:not-allowed}.ui-seg :is(button,a):is(:disabled,[aria-disabled=true]):not(.active):hover{background:transparent;color:var(--ui-text-muted)}.ui-seg--fill{display:flex;width:100%}.ui-seg.ui-seg--fill>:is(button,a).is-text{flex:1 1 0;min-width:0}.ui-seg-n{margin-left:6px;font-variant-numeric:tabular-nums;color:var(--ui-text-muted);font-weight:450}.ui-stats{display:flex;flex-wrap:wrap;gap:var(--ui-space-2);margin-bottom:24px}.ui-stat{display:inline-flex;align-items:center;gap:var(--ui-space-2);padding:6px 12px;border-radius:999px;font-family:inherit;background:var(--ui-surface);border:1px solid var(--ui-border);font-size:var(--ui-fs-caption);color:var(--ui-text-muted)}.ui-stat b{color:var(--ui-text-strong);font-weight:650}.ui-stat.is-clickable{cursor:pointer;transition:border-color .14s ease,background-color .14s ease}.ui-stat.is-clickable:hover{border-color:var(--ui-text-muted);background:var(--ui-surface-2)}.ui-stat.is-clickable.active{border-color:var(--ui-accent);background:var(--ui-accent-soft);color:var(--ui-accent-strong)}.ui-stat.is-clickable.active b{color:var(--ui-accent-strong)}.gemboss-toast-viewport{position:fixed;left:50%;bottom:24px;transform:translate(-50%);z-index:2147483000;display:flex;flex-direction:column;align-items:center;gap:12px;width:max-content;max-width:min(560px,calc(100vw - 32px));pointer-events:none}.gemboss-toast{pointer-events:auto;display:flex;align-items:center;gap:12px;min-width:220px;max-width:100%;padding:12px 12px 12px 16px;background:var(--ui-text-strong, #1a1917);color:var(--gemboss-on-primary, #fff);border-radius:12px;font-size:var(--ui-fs-body, 13px);line-height:1.4;font-weight:500;box-shadow:var(--gemboss-shadow-overlay, 0 8px 28px rgba(0, 0, 0, .24));animation:gemboss-toast-in .24s cubic-bezier(.16,1,.3,1)}.gemboss-toast.is-error{background:var(--gemboss-danger, #d72c0d)}.gemboss-toast-text{flex:1 1 auto;min-width:0}.gemboss-toast-action{flex:0 0 auto;border:0;background:transparent;color:var(--gemboss-on-primary, #fff);cursor:pointer;padding:4px 8px;border-radius:8px;font:inherit;font-weight:650;text-decoration:underline;text-underline-offset:2px;transition:background .14s ease}.gemboss-toast-action:hover{background:#ffffff29}.gemboss-toast-dismiss{flex:0 0 auto;display:inline-grid;place-items:center;width:24px;height:24px;border:0;border-radius:8px;cursor:pointer;background:#ffffff1f;color:var(--gemboss-on-primary, #fff);transition:background .14s ease}.gemboss-toast-dismiss:hover{background:#ffffff42}.gemboss-toast-action:focus-visible,.gemboss-toast-dismiss:focus-visible{outline:2px solid var(--gemboss-on-primary, #fff);outline-offset:2px}@keyframes gemboss-toast-in{0%{opacity:0;transform:translateY(12px)}to{opacity:1;transform:translateY(0)}}@media (prefers-reduced-motion: reduce){.gemboss-toast{animation:none}}@media (max-width: 47.9975em){.ui-btn:not(.ui-btn--sm),.ui-seg :is(button,a){min-height:44px}.ui-seg :is(button,a):not(.is-text){min-width:44px}}@media (pointer: coarse){.ui-btn:not(.ui-btn--sm),.ui-stat.is-clickable,.ui-chips>a.ui-tag--chip,.ui-pager>a,.ui-seg :is(button,a){min-height:44px}.ui-stat.is-clickable{min-width:44px;justify-content:center}.ui-chips>a.ui-tag--chip{min-width:44px;justify-content:center}.ui-select.ui-select,.ui-select--slim.ui-select--slim{min-height:44px}.ui-seg :is(button,a){min-width:44px}}.ui-skeleton{display:flex;flex-direction:column;gap:var(--ui-space-2)}.ui-skeleton__line{display:block;height:12px;border-radius:6px;background:linear-gradient(90deg,var(--ui-surface-2) 25%,var(--ui-border) 37%,var(--ui-surface-2) 63%);background-size:400% 100%;animation:ui-skeleton-sheen 1.4s ease-in-out infinite}@keyframes ui-skeleton-sheen{0%{background-position:100% 50%}to{background-position:0 50%}}@media (prefers-reduced-motion: reduce){.ui-skeleton__line{animation:none;background:var(--ui-surface-2)}}.ui-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}.ui-resizer{cursor:col-resize;position:relative;touch-action:none;outline:none}.ui-resizer:before{content:"";position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:4px;height:44px;border-radius:var(--gemboss-radius-full);background:var(--gemboss-primary);opacity:0;transition:opacity .14s ease,height .14s ease}.ui-resizer:hover:before,.ui-resizer:focus-visible:before,.ui-resizer.dragging:before,body.ui-resizing .ui-resizer:before{opacity:1;height:52px}@media (pointer: coarse){.ui-resizer:after{content:"";position:absolute;inset:0 -14px;touch-action:none;z-index:2}}body.ui-resizing,body.ui-resizing *{cursor:col-resize!important;user-select:none!important}body.ui-resizing:after{content:"";position:fixed;inset:0;z-index:9999;cursor:col-resize}.ui-tabs{display:flex;gap:var(--ui-space-2);border-bottom:1px solid var(--ui-border);overflow-x:auto;scrollbar-width:none}.ui-tabs>button,.ui-tabs>a{position:relative;flex:0 0 auto;display:inline-flex;align-items:center;gap:var(--ui-space-2);min-height:var(--ui-btn-h);padding:0 var(--ui-space-3);border:0;background:transparent;cursor:pointer;border-radius:var(--ui-radius-sm) var(--ui-radius-sm) 0 0;font-family:inherit;font-size:var(--ui-fs-caption);font-weight:550;white-space:nowrap;color:var(--ui-text-muted);transition:color var(--gemboss-transition-fast) ease,background-color var(--gemboss-transition-fast) ease}.ui-tabs>button:hover,.ui-tabs>a:hover{color:var(--ui-text);background:var(--ui-surface-2)}.ui-tabs>button:focus-visible,.ui-tabs>a:focus-visible{outline:2px solid var(--ui-focus);outline-offset:-2px}.ui-tabs>a{text-decoration:none}.ui-tabs>a[aria-current=page],.ui-tabs>button[aria-selected=true]{color:var(--ui-text-strong)}.ui-tabs>a[aria-current=page]:after,.ui-tabs>button[aria-selected=true]:after{content:"";position:absolute;left:var(--ui-space-3);right:var(--ui-space-3);bottom:0;height:2px;border-radius:var(--gemboss-radius-full);background:var(--ui-accent)}.ui-tabs>button:disabled{opacity:.5;cursor:not-allowed}@media (pointer: coarse),(max-width: 47.9975em){.ui-tabs>:is(button,a){min-height:44px}}.ui-table-wrap{overflow-x:auto;max-width:100%;background:var(--ui-surface);border:1px solid var(--ui-border);border-radius:var(--ui-radius-lg);box-shadow:var(--ui-card-shadow)}.ui-table{width:100%;border-collapse:collapse;font-size:var(--ui-fs-body);color:var(--ui-text)}.ui-table th,.ui-table td{padding:var(--ui-space-2) 6px;text-align:left;vertical-align:middle;border-bottom:1px solid var(--ui-border)}.ui-table :is(th,td):where(:first-child){padding-left:var(--ui-space-3)}.ui-table :is(th,td):where(:last-child){padding-right:var(--ui-space-3)}.ui-table th{font-weight:450;color:var(--ui-text-muted);white-space:nowrap}.ui-table thead th{padding-block:var(--ui-space-3)}.ui-table tbody tr:last-child>:is(td,th){border-bottom:0}.ui-table tbody tr:hover{background:var(--ui-surface-2)}.ui-table .is-num{text-align:right;font-variant-numeric:tabular-nums;white-space:nowrap}.ui-table td>a{display:inline-flex;align-items:center;min-height:24px}.ui-table .ui-sub{display:block;margin-top:2px;font-size:var(--ui-fs-caption);color:var(--ui-text-muted);font-weight:400}.ui-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--ui-space-2);padding:var(--ui-space-4);padding-block:40px;text-align:center;color:var(--ui-text-muted);font-size:var(--ui-fs-body)}.ui-empty__title{margin:0;font-size:14px;line-height:20px;font-weight:650;color:var(--ui-text-strong)}.ui-empty__body{margin:0;max-width:48ch;line-height:1.5}.ui-empty>.ui-btn{margin-top:var(--ui-space-2)}
|
|
1
|
+
:root{--ui-surface: #ffffff;--ui-surface: var(--gemboss-surface, #ffffff);--ui-surface-2: var(--gemboss-hover, #eceef2);--ui-text: var(--gemboss-text, #1b1c1e);--ui-text-muted: var(--gemboss-text-muted, #686b71);--ui-border: var(--gemboss-divider, #e5e7ea);--ui-accent: var(--gemboss-primary, #1b1c1e);--ui-accent-hover: var(--gemboss-primary-dark, #000000);--ui-accent-fg: #ffffff;--ui-accent-soft: var(--gemboss-active-bg, #f0f1f4);--ui-accent-strong: var(--gemboss-active-fg, #1b1c1e);--ui-text-strong: var(--gemboss-text-strong, #1b1c1e);--ui-success-fg: var(--gemboss-success);--ui-warning-fg: var(--gemboss-primary-dark);--ui-danger-fg: var(--gemboss-danger-strong);--ui-focus: var(--gemboss-accent, #5661f5);--ui-radius-sm: 6px;--ui-radius-md: 8px;--ui-radius-lg: 12px;--ui-space-1: 4px;--ui-space-2: 8px;--ui-space-3: 12px;--ui-space-4: 16px;--ui-control-h: 32px;--ui-btn-h: 28px;--ui-card-shadow: 0 1px 0 rgba(26,26,26,.07);--ui-fs-body: 13px;--ui-fs-caption: 12px;--ui-content-max: 900px}.gemboss-admin-shell{--ui-surface: var(--adm-surface);--ui-surface-2: var(--adm-surface-2);--ui-text: var(--adm-text);--ui-text-muted: var(--adm-muted);--ui-border: var(--adm-divider);--ui-accent: var(--adm-accent);--ui-accent-hover: var(--gemboss-primary-dark, #000000);--ui-accent-fg: #ffffff;--ui-accent-soft: var(--adm-accent-soft);--ui-accent-strong: var(--adm-accent-fg);--ui-text-strong: var(--adm-text-strong);--ui-success-fg: color-mix(in srgb, var(--gemboss-success) 70%, #ffffff);--ui-warning-fg: color-mix(in srgb, #c99a2e 70%, #ffffff);--ui-danger-fg: color-mix(in srgb, var(--gemboss-danger-strong) 70%, #ffffff);--ui-focus: var(--adm-accent);--ui-card-shadow: none}.ui-btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--ui-space-2);height:var(--ui-btn-h);padding:0 var(--ui-space-3);box-sizing:border-box;line-height:1;white-space:nowrap;vertical-align:middle;border-radius:var(--ui-radius-md);font-family:inherit;font-size:var(--ui-fs-caption);font-weight:550;cursor:pointer;text-decoration:none;user-select:none;border:1px solid var(--ui-border);background:transparent;color:var(--ui-text);transition:background .12s ease,border-color .12s ease}.ui-btn:hover{background:var(--ui-surface-2);text-decoration:none}.ui-btn:focus-visible{outline:2px solid var(--ui-focus);outline-offset:2px}.ui-btn[disabled],.ui-btn[aria-disabled=true]{opacity:.5;cursor:not-allowed}.ui-btn--primary{background:var(--ui-accent);border-color:var(--ui-accent);color:var(--ui-accent-fg)}.ui-btn--primary:hover{background:var(--ui-accent-hover);border-color:var(--ui-accent-hover)}.ui-btn--ghost{border-color:transparent;background:transparent;color:var(--ui-text-muted)}.ui-btn--ghost:hover{background:var(--ui-surface-2);color:var(--ui-text)}.ui-btn--on,.ui-btn--on:hover{background:var(--ui-accent-soft);border-color:var(--ui-accent);color:var(--ui-accent-strong)}.ui-card{background:var(--ui-surface);border:1px solid var(--ui-border);border-radius:var(--ui-radius-lg);box-shadow:var(--ui-card-shadow);padding:var(--ui-space-4);color:var(--ui-text)}.ui-card__title{font-size:14px;line-height:20px;font-weight:650;margin:0 0 var(--ui-space-2)}.ui-card__head{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--ui-space-2);margin-bottom:var(--ui-space-2)}.ui-card__head>.ui-card__title{margin:0}.ui-card__head>:last-child:not(.ui-card__title){display:flex;flex-wrap:wrap;gap:var(--ui-space-2)}.ui-select{height:var(--ui-control-h);padding:0 32px 0 12px;max-width:100%;background:var(--p-color-input-bg-surface, var(--gemboss-field-bg)) url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 20 20'><path fill='%239a9aa4' d='M5 7l5 5 5-5z'/></svg>") no-repeat right 10px center;border:1px solid var(--p-color-input-border, var(--gemboss-field-line));border-radius:var(--ui-radius-md);color:var(--p-color-text, var(--gemboss-field-ink));font-family:inherit;font-size:var(--ui-fs-body);font-weight:450;appearance:none;-webkit-appearance:none;cursor:pointer}.ui-select:hover:not(:disabled){border-color:var(--p-color-input-border-hover, var(--gemboss-field-line-hover));background-color:var(--p-color-input-bg-surface-hover, var(--gemboss-field-bg-hover))}.ui-select:focus{outline:none}.ui-select:focus-visible:not(:disabled){outline:2px solid var(--p-color-border-focus, var(--ui-focus));outline-offset:1px;border-color:var(--p-color-input-border-active, var(--gemboss-field-line-active))}.ui-select:disabled{opacity:.5;cursor:not-allowed}.ui-select--slim{height:30px;font-size:var(--ui-fs-caption)}.ui-tag{display:inline-flex;align-items:center;gap:6px;font-size:var(--ui-fs-caption);line-height:20px;font-weight:450;padding:0 6px;border-radius:var(--ui-radius-md);background:var(--ui-surface-2);color:var(--ui-text-muted)}.ui-tag--accent{background:var(--adm-accent-soft, rgba(20,22,26,.05));color:var(--adm-accent-fg, var(--ui-accent))}.ui-tag--chip{text-transform:none;letter-spacing:0;font-size:11px;font-weight:500;padding:2px 8px;background:transparent;border:1px solid var(--ui-border);font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.ui-tag--chip.ui-tag--accent{color:var(--adm-accent-fg, var(--ui-accent));border-color:var(--ui-accent);background:transparent}.ui-chips{display:flex;flex-wrap:wrap;gap:var(--ui-space-2, 8px);margin:0;padding:0;list-style:none}.ui-chips>a.ui-tag--chip{min-height:28px;padding:4px 12px;border-radius:var(--ui-radius-md, 8px);font-family:inherit;font-size:var(--gemboss-fs-caption, 12px);color:var(--ui-text);text-decoration:none}.ui-chips>a.ui-tag--chip:hover{background:var(--ui-surface-2);border-color:var(--ui-text-muted)}.ui-chips>a.ui-tag--chip:focus-visible{outline:2px solid var(--p-color-border-focus, var(--ui-focus));outline-offset:1px}.ui-chips>a.ui-tag--chip[aria-current=page]{background:var(--ui-accent-soft);border-color:var(--ui-accent);color:var(--ui-accent-strong);font-weight:600}.ui-tag--success{background:var(--gemboss-success-soft);color:var(--gemboss-success-strong, var(--gemboss-success))}.ui-tag--warning{background:var(--gemboss-warning-soft);color:var(--gemboss-warning)}.ui-tag--danger{background:var(--gemboss-danger-soft);color:var(--gemboss-danger-strong, var(--gemboss-danger))}.ui-muted{color:var(--ui-text-muted);font-size:var(--ui-fs-caption)}.ui-page-head{margin-bottom:20px}.ui-page-head h1{color:var(--ui-text-strong);font-size:20px;line-height:24px;font-weight:700;letter-spacing:-.01em}.ui-page-head p{color:var(--ui-text-muted);font-size:var(--ui-fs-body);margin-top:4px}.ui-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:12px;margin-bottom:20px}.ui-metrics{display:flex;flex-wrap:wrap;gap:8px;margin:2px 0}.ui-metric{display:flex;flex-direction:column;gap:1px;min-width:78px;padding:8px 12px;background:var(--ui-surface);border:1px solid var(--ui-border);border-radius:12px}a.ui-metric{text-decoration:none;color:inherit}a.ui-metric:hover{border-color:var(--ui-text-muted)}a.ui-metric:focus-visible{outline:2px solid var(--ui-focus);outline-offset:1px}.ui-metric__val{font-size:17px;font-weight:700;color:var(--ui-text);font-variant-numeric:tabular-nums;line-height:1.15}.ui-metric__lbl{font-size:var(--ui-fs-caption);font-weight:500;color:var(--ui-text-muted)}.ui-metric--success{border-color:color-mix(in srgb,var(--gemboss-success) 40%,transparent)}.ui-metric--success .ui-metric__val{color:var(--ui-success-fg)}.ui-metric--warning{border-color:color-mix(in srgb,#c99a2e 40%,transparent)}.ui-metric--warning .ui-metric__val{color:var(--ui-warning-fg)}.ui-metric--danger{border-color:color-mix(in srgb,var(--gemboss-danger-strong) 40%,transparent)}.ui-metric--danger .ui-metric__val{color:var(--ui-danger-fg)}.ui-dl{display:grid;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:12px 16px;margin:0}.ui-dl>div{min-width:0}.ui-dl dt{font-size:var(--ui-fs-caption);color:var(--ui-text-muted)}.ui-dl dd{margin:4px 0 0;font-weight:600;color:var(--ui-text);overflow-wrap:anywhere}.ui-notice{padding:12px 16px;border-radius:var(--ui-radius-md);border:1px solid var(--ui-border);background:var(--ui-surface-2);color:var(--ui-text);font-size:var(--ui-fs-body);overflow-wrap:anywhere}.ui-notice--warning{background:var(--gemboss-warning-soft);border-color:var(--gemboss-warning-border);color:var(--gemboss-warning)}.ui-notice--danger{background:var(--gemboss-danger-soft);border-color:var(--gemboss-danger-border);color:var(--gemboss-danger-strong)}.ui-notice--success{background:var(--gemboss-success-soft);border-color:var(--gemboss-success-border);color:var(--gemboss-success-strong)}.ui-pager{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:16px 0}.ui-pager>a{display:inline-flex;align-items:center;min-height:32px;padding:0 12px;border:1px solid var(--ui-border);border-radius:var(--ui-radius-md);color:var(--ui-text);text-decoration:none;font-size:var(--ui-fs-body)}.ui-pager>a:hover{background:var(--ui-surface-2)}.ui-pager>a:focus-visible{outline:2px solid var(--p-color-border-focus, var(--ui-focus));outline-offset:1px}.ui-pager>[aria-current=page]{color:var(--ui-text-muted);font-size:var(--ui-fs-caption)}.ui-badge{display:inline-flex;align-items:center;gap:4px;font-size:var(--ui-fs-caption);line-height:16px;font-weight:450;white-space:nowrap;padding:2px 8px;border-radius:var(--ui-radius-md);background:color-mix(in srgb,var(--ui-text) 8%,transparent);color:var(--ui-text-muted)}.ui-overlay{position:fixed;inset:0;z-index:500;background:#00000080;display:grid;place-items:center;padding:20px}.ui-modal{width:min(460px,100%);background:var(--ui-surface);border:1px solid var(--ui-border);border-radius:16px;box-shadow:var(--gemboss-shadow-overlay, 0 20px 60px rgba(0, 0, 0, .4));overflow:hidden}.ui-modal:focus{outline:none}.ui-modal__head{display:flex;align-items:center;gap:12px;padding:12px 16px;border-bottom:1px solid var(--ui-border);font-size:14px;line-height:20px;font-weight:650;color:var(--ui-text)}.ui-modal__title{min-width:0;flex:1 1 auto}.ui-modal__subtitle{display:block;margin-top:2px;font-size:var(--ui-fs-caption);line-height:16px;font-weight:450;color:var(--ui-text-muted);overflow-wrap:anywhere}.ui-modal__actions{flex:none;display:flex;flex-wrap:wrap;align-items:center;gap:var(--ui-space-2)}.ui-modal__close{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;border:0;border-radius:var(--ui-radius-md, 8px);background:transparent;color:var(--ui-text-muted);cursor:pointer}.ui-modal__close svg{width:20px;height:20px}.ui-modal__close:hover{background:var(--ui-surface-2);color:var(--ui-text)}.ui-modal__close:focus-visible{outline:2px solid var(--ui-focus);outline-offset:-2px}.ui-modal__body{padding:16px}.ui-modal__foot{display:flex;flex-wrap:wrap;gap:8px;justify-content:flex-end;padding:12px 16px;border-top:1px solid var(--ui-border)}@media (pointer: coarse),(max-width: 47.9975em){.ui-modal__close{width:44px;height:44px;margin:-8px -8px -8px 0}:is(.ui-modal__head,.ui-modal__foot) .ui-btn{min-height:44px}}.ui-modal--lg{position:relative}.ui-textarea{width:100%;min-height:96px;resize:vertical;box-sizing:border-box;background:var(--p-color-input-bg-surface, var(--gemboss-field-bg));border:1px solid var(--p-color-input-border, var(--gemboss-field-line));border-radius:var(--ui-radius-md);padding:12px;color:var(--p-color-text, var(--gemboss-field-ink));font-size:var(--ui-fs-body);line-height:1.5;font-family:inherit}.ui-textarea::placeholder{color:var(--p-color-text-secondary, var(--gemboss-field-placeholder))}.ui-textarea:hover:not(:disabled){border-color:var(--p-color-input-border-hover, var(--gemboss-field-line-hover));background-color:var(--p-color-input-bg-surface-hover, var(--gemboss-field-bg-hover))}.ui-textarea:focus{outline:none}.ui-textarea:focus-visible:not(:disabled){outline:2px solid var(--p-color-border-focus, var(--ui-focus));outline-offset:1px;border-color:var(--p-color-input-border-active, var(--gemboss-field-line-active))}.ui-textarea:disabled{opacity:.5;cursor:not-allowed}@media (max-width: 47.9975em){.ui-select.ui-select,.ui-textarea{font-size:16px}.ui-select:not(.ui-select--slim){min-height:44px}}.ui-seg{display:inline-flex;border:1px solid var(--ui-border);border-radius:var(--ui-radius-md);overflow:hidden;overflow:clip;min-width:0}.ui-seg :is(button,a){display:inline-grid;place-items:center;width:calc(var(--ui-btn-h) - 2px);height:calc(var(--ui-btn-h) - 2px);border:0;background:transparent;color:var(--ui-text-muted);cursor:pointer;font-family:inherit}.ui-seg :is(button,a).is-text{width:auto;padding:0 12px;font-size:var(--ui-fs-caption);font-weight:550;grid-auto-flow:column;column-gap:2px}.ui-seg :is(button,a)+:is(button,a){border-left:1px solid var(--ui-border)}.ui-seg :is(button,a):hover{background:var(--ui-surface-2);color:var(--ui-text)}.ui-seg :is(button,a):focus-visible{outline:2px solid var(--ui-focus);outline-offset:-2px}.ui-seg a{display:inline-flex;align-items:center;justify-content:center;text-decoration:none;color:var(--ui-text-muted)}.ui-seg a[aria-current=page],.ui-seg button.active{background:var(--ui-accent-soft);color:var(--ui-accent-strong)}.ui-seg svg{width:16px;height:16px;fill:currentColor}.ui-seg svg[fill=none]{fill:none}.ui-seg :is(button,a):is(:disabled,[aria-disabled=true]){opacity:.45;cursor:not-allowed}.ui-seg :is(button,a):is(:disabled,[aria-disabled=true]):not(.active):hover{background:transparent;color:var(--ui-text-muted)}.ui-seg--fill{display:flex;width:100%}.ui-seg.ui-seg--fill>:is(button,a).is-text{flex:1 1 0;min-width:0}.ui-seg-n{margin-left:6px;font-variant-numeric:tabular-nums;color:var(--ui-text-muted);font-weight:450}.ui-stats{display:flex;flex-wrap:wrap;gap:var(--ui-space-2);margin-bottom:24px}.ui-stat{display:inline-flex;align-items:center;gap:var(--ui-space-2);padding:6px 12px;border-radius:999px;font-family:inherit;background:var(--ui-surface);border:1px solid var(--ui-border);font-size:var(--ui-fs-caption);color:var(--ui-text-muted)}.ui-stat b{color:var(--ui-text-strong);font-weight:650}.ui-stat.is-clickable{cursor:pointer;transition:border-color .14s ease,background-color .14s ease}.ui-stat.is-clickable:hover{border-color:var(--ui-text-muted);background:var(--ui-surface-2)}.ui-stat.is-clickable.active{border-color:var(--ui-accent);background:var(--ui-accent-soft);color:var(--ui-accent-strong)}.ui-stat.is-clickable.active b{color:var(--ui-accent-strong)}.gemboss-toast-viewport{position:fixed;left:50%;bottom:24px;transform:translate(-50%);z-index:2147483000;display:flex;flex-direction:column;align-items:center;gap:12px;width:max-content;max-width:min(560px,calc(100vw - 32px));pointer-events:none}.gemboss-toast{pointer-events:auto;display:flex;align-items:center;gap:12px;min-width:220px;max-width:100%;padding:12px 12px 12px 16px;background:var(--ui-text-strong, #1a1917);color:var(--gemboss-on-primary, #fff);border-radius:12px;font-size:var(--ui-fs-body, 13px);line-height:1.4;font-weight:500;box-shadow:var(--gemboss-shadow-overlay, 0 8px 28px rgba(0, 0, 0, .24));animation:gemboss-toast-in .24s cubic-bezier(.16,1,.3,1)}.gemboss-toast.is-error{background:var(--gemboss-danger, #d72c0d)}.gemboss-toast-text{flex:1 1 auto;min-width:0}.gemboss-toast-action{flex:0 0 auto;border:0;background:transparent;color:var(--gemboss-on-primary, #fff);cursor:pointer;padding:4px 8px;border-radius:8px;font:inherit;font-weight:650;text-decoration:underline;text-underline-offset:2px;transition:background .14s ease}.gemboss-toast-action:hover{background:#ffffff29}.gemboss-toast-dismiss{flex:0 0 auto;display:inline-grid;place-items:center;width:24px;height:24px;border:0;border-radius:8px;cursor:pointer;background:#ffffff1f;color:var(--gemboss-on-primary, #fff);transition:background .14s ease}.gemboss-toast-dismiss:hover{background:#ffffff42}.gemboss-toast-action:focus-visible,.gemboss-toast-dismiss:focus-visible{outline:2px solid var(--gemboss-on-primary, #fff);outline-offset:2px}@keyframes gemboss-toast-in{0%{opacity:0;transform:translateY(12px)}to{opacity:1;transform:translateY(0)}}@media (prefers-reduced-motion: reduce){.gemboss-toast{animation:none}}@media (max-width: 47.9975em){.ui-btn:not(.ui-btn--sm),.ui-seg :is(button,a){min-height:44px}.ui-seg :is(button,a):not(.is-text){min-width:44px}}@media (pointer: coarse){.ui-btn:not(.ui-btn--sm),.ui-stat.is-clickable,.ui-chips>a.ui-tag--chip,.ui-pager>a,.ui-seg :is(button,a){min-height:44px}.ui-stat.is-clickable{min-width:44px;justify-content:center}.ui-chips>a.ui-tag--chip{min-width:44px;justify-content:center}.ui-select.ui-select,.ui-select--slim.ui-select--slim{min-height:44px}.ui-seg :is(button,a){min-width:44px}}.ui-skeleton{display:flex;flex-direction:column;gap:var(--ui-space-2)}.ui-skeleton__line{display:block;height:12px;border-radius:6px;background:linear-gradient(90deg,var(--ui-surface-2) 25%,var(--ui-border) 37%,var(--ui-surface-2) 63%);background-size:400% 100%;animation:ui-skeleton-sheen 1.4s ease-in-out infinite}@keyframes ui-skeleton-sheen{0%{background-position:100% 50%}to{background-position:0 50%}}@media (prefers-reduced-motion: reduce){.ui-skeleton__line{animation:none;background:var(--ui-surface-2)}}.ui-sr-only{position:absolute;left:0;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}.ui-resizer{cursor:col-resize;position:relative;touch-action:none;outline:none}.ui-resizer:before{content:"";position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:4px;height:44px;border-radius:var(--gemboss-radius-full);background:var(--gemboss-primary);opacity:0;transition:opacity .14s ease,height .14s ease}.ui-resizer:hover:before,.ui-resizer:focus-visible:before,.ui-resizer.dragging:before,body.ui-resizing .ui-resizer:before{opacity:1;height:52px}@media (pointer: coarse){.ui-resizer:after{content:"";position:absolute;inset:0 -14px;touch-action:none;z-index:2}}body.ui-resizing,body.ui-resizing *{cursor:col-resize!important;user-select:none!important}body.ui-resizing:after{content:"";position:fixed;inset:0;z-index:9999;cursor:col-resize}.ui-tabs{display:flex;gap:var(--ui-space-2);border-bottom:1px solid var(--ui-border);overflow-x:auto;scrollbar-width:none}.ui-tabs>button,.ui-tabs>a{position:relative;flex:0 0 auto;display:inline-flex;align-items:center;gap:var(--ui-space-2);min-height:var(--ui-btn-h);padding:0 var(--ui-space-3);border:0;background:transparent;cursor:pointer;border-radius:var(--ui-radius-sm) var(--ui-radius-sm) 0 0;font-family:inherit;font-size:var(--ui-fs-caption);font-weight:550;white-space:nowrap;color:var(--ui-text-muted);transition:color var(--gemboss-transition-fast) ease,background-color var(--gemboss-transition-fast) ease}.ui-tabs>button:hover,.ui-tabs>a:hover{color:var(--ui-text);background:var(--ui-surface-2)}.ui-tabs>button:focus-visible,.ui-tabs>a:focus-visible{outline:2px solid var(--ui-focus);outline-offset:-2px}.ui-tabs>a{text-decoration:none}.ui-tabs>a[aria-current=page],.ui-tabs>button[aria-selected=true]{color:var(--ui-text-strong)}.ui-tabs>a[aria-current=page]:after,.ui-tabs>button[aria-selected=true]:after{content:"";position:absolute;left:var(--ui-space-3);right:var(--ui-space-3);bottom:0;height:2px;border-radius:var(--gemboss-radius-full);background:var(--ui-accent)}.ui-tabs>button:disabled{opacity:.5;cursor:not-allowed}@media (pointer: coarse),(max-width: 47.9975em){.ui-tabs>:is(button,a){min-height:44px}}.ui-table-wrap{overflow-x:auto;max-width:100%;background:var(--ui-surface);border:1px solid var(--ui-border);border-radius:var(--ui-radius-lg);box-shadow:var(--ui-card-shadow)}.ui-table{width:100%;border-collapse:collapse;font-size:var(--ui-fs-body);color:var(--ui-text)}.ui-table th,.ui-table td{padding:var(--ui-space-2) 6px;text-align:left;vertical-align:middle;border-bottom:1px solid var(--ui-border)}.ui-table :is(th,td):where(:first-child){padding-left:var(--ui-space-3)}.ui-table :is(th,td):where(:last-child){padding-right:var(--ui-space-3)}.ui-table th{font-weight:450;color:var(--ui-text-muted);white-space:nowrap}.ui-table thead th{padding-block:var(--ui-space-3)}.ui-table tbody tr:last-child>:is(td,th){border-bottom:0}.ui-table tbody tr:hover{background:var(--ui-surface-2)}.ui-table .is-num{text-align:right;font-variant-numeric:tabular-nums;white-space:nowrap}.ui-table td>a{display:inline-flex;align-items:center;min-height:24px}.ui-table .ui-sub{display:block;margin-top:2px;font-size:var(--ui-fs-caption);color:var(--ui-text-muted);font-weight:400}.ui-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--ui-space-2);padding:var(--ui-space-4);padding-block:40px;text-align:center;color:var(--ui-text-muted);font-size:var(--ui-fs-body)}.ui-empty__title{margin:0;font-size:14px;line-height:20px;font-weight:650;color:var(--ui-text-strong)}.ui-empty__body{margin:0;max-width:48ch;line-height:1.5}.ui-empty>.ui-btn{margin-top:var(--ui-space-2)}
|