@gemboss/ui 0.35.7 → 0.39.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/src/auth.tsx CHANGED
@@ -37,7 +37,7 @@ const BACKDROP: Record<AuthBackdrop, string> = { facet: "", grid: "gb-auth-panel
37
37
  * The whole screen. `children` is everything inside the card below the heading: the form, then any
38
38
  * lines under it.
39
39
  */
40
- export function AuthLayout({ brand, tagline, mark, panel, backdrop = "facet", className, children }: {
40
+ export function AuthLayout({ brand, tagline, mark, panel, backdrop = "facet", art, className, children }: {
41
41
  /** The page heading (h1) in the card. */
42
42
  brand: React.ReactNode;
43
43
  /** One line under the heading; the first thing shed on a short screen. */
@@ -48,6 +48,9 @@ export function AuthLayout({ brand, tagline, mark, panel, backdrop = "facet", cl
48
48
  panel?: { eyebrow?: React.ReactNode; heading: React.ReactNode; body?: React.ReactNode };
49
49
  /** The panel's ground pattern; see `AuthBackdrop`. Only drawn where the panel is (900 wide AND 520 tall). */
50
50
  backdrop?: AuthBackdrop;
51
+ /** Drawn on the panel, under its words (16/10/2026): `AuthPageField`, or anything else that is decoration. Pair it
52
+ * with `backdrop="none"`. Only drawn where the panel is. */
53
+ art?: React.ReactNode;
51
54
  className?: string;
52
55
  children?: React.ReactNode;
53
56
  }) {
@@ -105,6 +108,7 @@ export function AuthLayout({ brand, tagline, mark, panel, backdrop = "facet", cl
105
108
  them. Nothing in it is focusable — it is decoration beside the form, not a second path. */}
106
109
  {panel ? (
107
110
  <aside className={cx("gb-auth-panel", BACKDROP[backdrop])}>
111
+ {art}
108
112
  <div className="gb-auth-panel-in">
109
113
  {panel.eyebrow ? <p className="gb-auth-eyebrow">{panel.eyebrow}</p> : null}
110
114
  <h2 className="gb-auth-panel-h">{panel.heading}</h2>
@@ -117,6 +121,65 @@ export function AuthLayout({ brand, tagline, mark, panel, backdrop = "facet", cl
117
121
  );
118
122
  }
119
123
 
124
+ /**
125
+ * "Continue with GemBoss" (16/10/2026): the internal tools' second door, above their password form (Chris, 16/10/2026: "có
126
+ * cả continue với gemboss hoặc nhập mật khẩu"). Protocol: gemboss docs/fleet-sso.md. It links to GemBoss's sign-in
127
+ * door for this `service`; GemBoss sends a person who is signed in there and on the internal list straight back, with a
128
+ * one-use token the tool redeems at its own route. Below it, "or" and the form the tool always had.
129
+ *
130
+ * Once a browser has come in through GemBoss the tool sets `gb_sso=1`, and from then on this page continues by itself,
131
+ * so a person still signed in to GemBoss never sees a form. It does not when the tool sent a reason back (`?sso=…`:
132
+ * that sign-in did not work, so the page stays and says why) or `?password=1` (the person asked for the form).
133
+ */
134
+ export const GEMBOSS_ISSUER = "https://admin.gemboss.ai";
135
+ const SSO_REASONS: Record<string, string> = {
136
+ not_member: "Your GemBoss account does not have access here. Use the password.",
137
+ invalid: "That sign-in did not go through. Try again, or use the password.",
138
+ off: "Signing in with GemBoss is not available here yet. Use the password.",
139
+ };
140
+
141
+ /** The GemBoss door for one tool, with the path on the tool to come back to. */
142
+ export function gemBossSignInUrl(service: string, next = "/", issuer = GEMBOSS_ISSUER): string {
143
+ return `${issuer}/api/auth/sso/authorize?service=${encodeURIComponent(service)}&next=${encodeURIComponent(next)}`;
144
+ }
145
+
146
+ /** Whether this visit should go to GemBoss without a click: the browser came in that way before, and nothing says stay. */
147
+ export function continuesByItself(cookie: string, search: string): boolean {
148
+ const q = new URLSearchParams(search);
149
+ if (q.has("sso") || q.get("password") === "1") return false;
150
+ return /(?:^|;\s*)gb_sso=1(?:;|$)/.test(cookie);
151
+ }
152
+
153
+ export function AuthContinueWithGemBoss({ service, next = "/", issuer = GEMBOSS_ISSUER }: {
154
+ /** This tool's id in GemBoss's list of tools that redeem (FLEET_SSO_SERVICES). */
155
+ service: string;
156
+ /** Where on this tool to land afterwards: a path. */
157
+ next?: string;
158
+ issuer?: string;
159
+ }) {
160
+ const href = gemBossSignInUrl(service, next, issuer);
161
+ const [going, setGoing] = useState(false);
162
+ const [reason, setReason] = useState<string | null>(null);
163
+ useEffect(() => {
164
+ const r = new URLSearchParams(window.location.search).get("sso");
165
+ if (r) setReason(SSO_REASONS[r] ?? SSO_REASONS.invalid);
166
+ if (continuesByItself(document.cookie, window.location.search)) {
167
+ setGoing(true);
168
+ window.location.replace(href);
169
+ }
170
+ }, [href]);
171
+ return (
172
+ <div className="gb-auth-sso">
173
+ <a className="gb-auth-sso-btn" href={href} onClick={() => setGoing(true)}>
174
+ <GemMark size={18} tile="var(--gb-mark-bg)" />
175
+ {going ? "Continuing with GemBoss…" : "Continue with GemBoss"}
176
+ </a>
177
+ {reason ? <p className="gb-auth-sso-why" role="status">{reason}</p> : null}
178
+ <p className="gb-auth-or">or use the password</p>
179
+ </div>
180
+ );
181
+ }
182
+
120
183
  export function AuthForm({ className, children, ...rest }: React.FormHTMLAttributes<HTMLFormElement>) {
121
184
  return <form className={cx("gb-auth-form", className)} {...rest}>{children}</form>;
122
185
  }
package/src/brand.tsx CHANGED
@@ -9,14 +9,19 @@
9
9
  * - gem: the logo file's paths and stroke weights, same 0.31 scale, in a 32×40 box drawn 26px tall;
10
10
  * - name: the logo's text at the same scale — 20.5 × 0.65 = 13.3px, 700, -0.13px tracking, #14151a.
11
11
  * `BrandLockup name="GemBoss"` is meant to be indistinguishable from the admin's image.
12
+ *
13
+ * `switcher` (0.36.0): the ServiceSwitcher button right after the logo, which opens every other Gem service. The logo
14
+ * still goes to `href`, as without it. Without the prop the lockup renders exactly as before. The import below brings
15
+ * service-switcher.css with this module whether or not a surface passes it (README "ServiceSwitcher").
12
16
  */
13
17
  import React from "react";
18
+ import { ServiceSwitcher, type ServiceSwitcherProps } from "./service-switcher";
14
19
 
15
20
  type AnchorProps = React.AnchorHTMLAttributes<HTMLAnchorElement>;
16
21
 
17
- export function BrandLockup({ name, href = "/", label, className, ...rest }:
18
- { name: string; label?: string } & AnchorProps) {
19
- return (
22
+ export function BrandLockup({ name, href = "/", label, className, switcher, ...rest }:
23
+ { name: string; label?: string; switcher?: Omit<ServiceSwitcherProps, "className"> } & AnchorProps) {
24
+ const link = (
20
25
  <a className={className ? `gb-brand ${className}` : "gb-brand"} href={href} aria-label={label ?? `${name} home`} {...rest}>
21
26
  <svg className="gb-brand-gem" viewBox="0 0 32 40" width="20.8" height="26" aria-hidden="true" focusable="false">
22
27
  <g transform="translate(0,0.8) scale(0.31)">
@@ -28,4 +33,5 @@ export function BrandLockup({ name, href = "/", label, className, ...rest }:
28
33
  <span className="gb-brand-name">{name}</span>
29
34
  </a>
30
35
  );
36
+ return switcher ? <>{link}<ServiceSwitcher {...switcher} /></> : link;
31
37
  }
@@ -1 +1 @@
1
- .gemboss-ec-toolbar{flex:1 0 100%;display:flex;align-items:center;gap:4px;min-width:0}.gemboss-ec-toolbar-lead{flex:1 1 auto;display:flex;align-items:center;gap:4px;min-width:0}.gemboss-ec-toolbar-lead:empty{display:none}.gemboss-ec-toolbar-lead:empty+*{margin-left:auto}.gemboss-ec-toolbar-tools{display:flex;align-items:center;gap:4px;flex:none;min-width:0}.gemboss-ec-toolbar-tools:empty{display:none}.gemboss-ec-input:has(>.gemboss-ec-toolbar>.gemboss-ec-toolbar-lead:empty){flex-wrap:nowrap;align-items:flex-end}.gemboss-ec-input:has(>.gemboss-ec-toolbar>.gemboss-ec-toolbar-lead:empty)>textarea{flex:1 1 0}.gemboss-ec-input:has(>.gemboss-ec-toolbar>.gemboss-ec-toolbar-lead:empty)>.gemboss-ec-toolbar{flex:0 0 auto}@media (pointer: coarse){.gemboss-ec-input .gemboss-ec-stop{width:44px;height:44px;min-width:44px}.gemboss-ec-input .gemboss-ec-stop-send{min-height:44px}}.gemboss-ec-stop{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;min-width:44px;border:none;border-radius:50%;background:var(--gemboss-critical, #d72c0d);color:#fff;cursor:pointer}.gemboss-ec-stop svg{width:12px;height:12px;fill:currentColor}.gemboss-ec-stop:disabled{opacity:.6;cursor:default}.gemboss-ec-stop:hover{filter:brightness(1.08)}.gemboss-ec-stop:focus-visible{outline:2px solid var(--gemboss-focus, var(--ui-focus, #5661f5));outline-offset:2px}
1
+ .gemboss-ec-toolbar{flex:1 0 100%;display:flex;align-items:center;gap:4px;min-width:0}.gemboss-ec-toolbar-lead{flex:1 1 auto;display:flex;align-items:center;gap:4px;min-width:0}.gemboss-ec-toolbar-lead:empty{display:none}.gemboss-ec-toolbar-lead:empty+*{margin-left:auto}.gemboss-ec-toolbar-tools{display:flex;align-items:center;gap:4px;flex:none;min-width:0}.gemboss-ec-toolbar-tools:empty{display:none}.gemboss-ec-input:has(>.gemboss-ec-toolbar>.gemboss-ec-toolbar-lead:empty){flex-wrap:nowrap;align-items:flex-end}.gemboss-ec-input:has(>.gemboss-ec-toolbar>.gemboss-ec-toolbar-lead:empty)>textarea{flex:1 1 0}.gemboss-ec-input:has(>.gemboss-ec-toolbar>.gemboss-ec-toolbar-lead:empty)>.gemboss-ec-toolbar{flex:0 0 auto}@media (pointer: coarse){.gemboss-ec-input .gemboss-ec-stop{width:44px;height:44px;min-width:44px}.gemboss-ec-input .gemboss-ec-stop-send{min-height:44px}}.gemboss-ec-stop{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;min-width:44px;border:none;border-radius:50%;background:var(--gemboss-danger);color:var(--gemboss-on-primary, #fff);cursor:pointer}.gemboss-ec-stop svg{width:12px;height:12px;fill:currentColor}.gemboss-ec-stop:disabled{opacity:.6;cursor:default}.gemboss-ec-stop:hover{filter:brightness(1.08)}.gemboss-ec-stop:focus-visible{outline:2px solid var(--ui-focus, #5661f5);outline-offset:2px}
package/src/chat.css CHANGED
@@ -1 +1 @@
1
- .gemboss-ec{--gemboss-ec-inset: 16px}@media (max-width: 640px){.gemboss-ec{--gemboss-ec-inset: 12px}}.gemboss-ec-head{padding:16px var(--gemboss-ec-inset, 16px);border-bottom:1px solid var(--gemboss-divider);display:flex;flex-direction:column;gap:2px}.gemboss-ec-title{font-family:var(--gemboss-serif);font-size:15px;font-weight:600}.gemboss-ec-sub{font-size:12px;color:var(--gemboss-text-muted)}.gemboss-ec-scroll{flex:1;min-height:0;overflow-y:auto;padding:var(--gemboss-ec-inset, 16px);display:flex;flex-direction:column;gap:16px;scrollbar-gutter:stable}.gemboss-ec-scroll{scrollbar-width:thin;scrollbar-color:rgba(31,30,29,.22) transparent}.gemboss-ec-scroll::-webkit-scrollbar{width:9px}.gemboss-ec-scroll::-webkit-scrollbar-track{background:transparent}.gemboss-ec-scroll::-webkit-scrollbar-thumb{background:#1f1e1d33;border-radius:6px;border:2px solid transparent;background-clip:content-box}.gemboss-ec-msg{display:flex;flex-direction:column;gap:8px;max-width:100%}.gemboss-ec-msg.user{align-items:flex-end}.gemboss-ec-msg.assistant{align-items:flex-start}.gemboss-ec-bubble{font-size:var(--gemboss-fs-body);line-height:1.5;padding:12px;border-radius:16px;max-width:min(90%,68ch);white-space:pre-wrap;word-break:break-word}.gemboss-ec-msg.user .gemboss-ec-bubble{background:var(--gemboss-primary);color:var(--gemboss-on-primary, #fff);border-bottom-right-radius:4px}.gemboss-ec-msg.assistant .gemboss-ec-bubble{background:var(--gemboss-surface);color:var(--gemboss-text);border:1px solid var(--gemboss-divider);border-bottom-left-radius:4px}.gemboss-ec-msg.user .gemboss-ec-bubble,:root[data-theme=dark] .gemboss-ec-msg.assistant .gemboss-ec-bubble{--gemboss-ec-md-ink: color-mix(in srgb, currentColor 78%, transparent);--gemboss-ec-md-line: color-mix(in srgb, currentColor 32%, transparent);--gemboss-ec-md-fill: color-mix(in srgb, currentColor 14%, transparent)}:is(.gemboss-ec-msg.user,:root[data-theme=dark] .gemboss-ec-msg.assistant) .gemboss-ec-bubble :is(.gemboss-md-h3,.gemboss-md-quote){color:var(--gemboss-ec-md-ink)}:is(.gemboss-ec-msg.user,:root[data-theme=dark] .gemboss-ec-msg.assistant) .gemboss-ec-bubble :is(.gemboss-md-quote,.gemboss-md-rule,.gemboss-md-table th,.gemboss-md-table td,.gemboss-md-codeblock,.gemboss-md-img){border-color:var(--gemboss-ec-md-line)}:is(.gemboss-ec-msg.user,:root[data-theme=dark] .gemboss-ec-msg.assistant) .gemboss-ec-bubble :is(.gemboss-md-code,.gemboss-md-table th,.gemboss-md-codeblock,.gemboss-md-img){background:var(--gemboss-ec-md-fill)}.gemboss-ec-toolbar>button[type=submit] svg{width:18px;height:18px;fill:currentColor}.gemboss-ec-pending{display:inline-flex;align-items:center;gap:8px;padding:6px 2px;font-size:var(--gemboss-fs-caption);color:var(--gemboss-text-muted)}.gemboss-ec-pending-star{color:var(--gemboss-primary);font-size:12px;line-height:1;animation:gemboss-star-pulse 1.1s ease-in-out infinite}.gemboss-ec-pending-verb{color:var(--gemboss-text);animation:gemboss-verb-in .4s ease-out}.gemboss-ec-pending-meta{font-variant-numeric:tabular-nums;opacity:.7;font-size:var(--gemboss-fs-caption)}@keyframes gemboss-star-pulse{0%,to{transform:scale(.85);opacity:.55}50%{transform:scale(1.15);opacity:1}}@keyframes gemboss-verb-in{0%{opacity:0;transform:translateY(2px)}to{opacity:1;transform:none}}.gemboss-ec-cursor{display:inline-block;width:2px;height:1.05em;margin-left:2px;vertical-align:-2px;background:var(--gemboss-primary);border-radius:2px;animation:gemboss-cursor-blink 1s steps(1) infinite}@keyframes gemboss-cursor-blink{0%,45%{opacity:1}50%,95%{opacity:.15}to{opacity:1}}@media (prefers-reduced-motion: reduce){.gemboss-ec-pending-star,.gemboss-ec-cursor{animation:none}}.gemboss-ec-md-link{color:var(--gemboss-primary-dark);font-weight:600;text-decoration:none;border-bottom:1px solid color-mix(in srgb,var(--gemboss-primary) 35%,transparent);cursor:pointer}.gemboss-ec-md-link:hover{border-bottom-color:var(--gemboss-primary)}strong>.gemboss-ec-md-link{font-weight:inherit}.gemboss-ec-md-link:focus-visible{outline:2px solid currentColor;outline-offset:2px;border-radius:2px}.gemboss-ec-msg.user .gemboss-ec-md-link{color:inherit;border-bottom-color:color-mix(in srgb,currentColor 55%,transparent)}.gemboss-ec-msg.user .gemboss-ec-md-link:hover{border-bottom-color:currentColor}.gemboss-ec-starters{display:flex;flex-wrap:wrap;gap:8px;margin-top:4px}.gemboss-ec-starter{text-align:left;font-size:13px;padding:6px 12px;border-radius:var(--gemboss-radius-full);cursor:pointer;background:var(--gemboss-surface);border:1px solid var(--gemboss-divider);color:var(--gemboss-text);white-space:nowrap;max-width:100%}.gemboss-ec-starter:hover{border-color:var(--gemboss-primary);background:#5661f50f}.gemboss-ec-input{display:flex;flex-wrap:wrap;align-items:center;gap:4px;margin:12px;padding:8px;border:1px solid var(--gemboss-divider);border-radius:16px;background:var(--gemboss-surface);transition:border-color var(--gemboss-transition-fast) ease,box-shadow var(--gemboss-transition-fast) ease}.gemboss-ec-input:focus-within{border-color:var(--gemboss-primary);box-shadow:0 0 0 3px color-mix(in srgb,var(--gemboss-primary) 12%,transparent)}.gemboss-ec-input textarea{flex:1 0 100%;min-width:0;width:100%;box-sizing:border-box;resize:none;border-radius:0;background:transparent;border:1px solid transparent;padding:6px 8px;font-size:var(--gemboss-fs-body);font-family:inherit;min-height:0;max-height:84px;line-height:1.5;overflow-y:auto;scrollbar-width:thin;scrollbar-color:rgba(31,30,29,.22) transparent}.gemboss-ec-input textarea::-webkit-scrollbar{width:7px}.gemboss-ec-input textarea::-webkit-scrollbar-track{background:transparent}.gemboss-ec-input textarea::-webkit-scrollbar-thumb{background:#1f1e1d33;border-radius:4px;border:2px solid transparent;background-clip:content-box}.gemboss-ec-input textarea:focus{outline:none}.gemboss-ec-toolbar>button[type=submit]{flex:0 0 auto;width:44px;height:44px;min-width:44px;min-height:44px;border-radius:50%;border:0;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;background:var(--gemboss-primary);color:var(--gemboss-on-primary, #fff);font-size:16px;font-weight:700;transition:background var(--gemboss-transition-fast) ease,filter var(--gemboss-transition-fast) ease}.gemboss-ec-toolbar>button[type=submit]:hover:not(:disabled){background:var(--gemboss-primary-dark)}.gemboss-ec-toolbar>button[type=submit]:active:not(:disabled){background:var(--gemboss-primary-dark);filter:brightness(.94)}.gemboss-ec-toolbar>button[type=submit]:focus-visible{outline:2px solid var(--gemboss-primary);outline-offset:2px}.gemboss-ec-toolbar>button[type=submit]:disabled{background:var(--gemboss-divider);color:var(--gemboss-text-muted);opacity:1;cursor:default}.gemboss-narr{list-style:none;margin:0;padding:8px 0 0;display:flex;flex-direction:column;gap:8px}.gemboss-narr-row{display:flex;align-items:center;gap:8px;font-size:var(--gemboss-fs-caption);color:var(--gemboss-text-muted)}.gemboss-narr-dot{width:16px;height:16px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;font-size:10px;flex:0 0 auto}.gemboss-narr-row.ok .gemboss-narr-dot{background:var(--gemboss-active-bg);color:var(--gemboss-active-fg)}.gemboss-narr-row.failed .gemboss-narr-dot{background:#fde8e6;color:var(--gemboss-danger)}.gemboss-narr-row.running .gemboss-narr-dot{background:transparent}.gemboss-narr-dot-engine{background:transparent!important;color:inherit}.gemboss-narr-row.ok .gemboss-narr-dot-engine{color:var(--gemboss-text)}.gemboss-narr-row.failed .gemboss-narr-dot-engine{color:var(--gemboss-danger)}.gemboss-narr-row.ok .gemboss-narr-text,.gemboss-narr-row.failed .gemboss-narr-text{color:var(--gemboss-text)}.gemboss-narr-row.steer .gemboss-narr-dot{background:transparent;color:var(--gemboss-text-muted)}.gemboss-narr-steer{color:var(--gemboss-text);font-weight:500;overflow-wrap:anywhere}.gemboss-narr-spin{width:11px;height:11px;border:2px solid var(--gemboss-divider-soft);border-top-color:var(--gemboss-primary);border-radius:50%;animation:gemboss-spin .7s linear infinite}@keyframes gemboss-spin{to{transform:rotate(360deg)}}.gemboss-narr-row.thinking{align-items:flex-start}.gemboss-narr-row.thinking .gemboss-narr-dot{color:var(--gemboss-text-muted);background:transparent}.gemboss-narr-thinking-live{font-style:italic;color:var(--gemboss-text-muted);white-space:pre-wrap;opacity:.9;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}.gemboss-narr-thinking{font-size:var(--gemboss-fs-caption)}.gemboss-narr-thinking>summary{cursor:pointer;color:var(--gemboss-text-muted);list-style:none;user-select:none}.gemboss-narr-thinking>summary::-webkit-details-marker{display:none}.gemboss-narr-thinking>summary:before{content:"\25b8 "}.gemboss-narr-thinking[open]>summary:before{content:"\25be "}.gemboss-narr-thinking-body{margin-top:6px;padding:8px;border-left:2px solid var(--gemboss-divider-soft);color:var(--gemboss-text-muted);font-style:italic;white-space:pre-wrap;line-height:1.5}.gemboss-narr-row.trace code{font-family:var(--gemboss-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);font-size:var(--gemboss-fs-caption);word-break:break-word}.gemboss-narr-trace-call{color:var(--gemboss-text-muted);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.gemboss-narr-trace{font-size:var(--gemboss-fs-caption);min-width:0}.gemboss-narr-trace>summary{cursor:pointer;color:var(--gemboss-text-muted);list-style:none;user-select:none;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.gemboss-narr-trace[open]>summary{display:block;overflow:visible}.gemboss-narr-trace>summary::-webkit-details-marker{display:none}.gemboss-narr-trace>summary,.gemboss-narr-thinking>summary{min-height:24px;box-sizing:border-box;padding-block:2px}.gemboss-narr-trace>summary:before{content:"\25b8 "}.gemboss-narr-trace[open]>summary:before{content:"\25be "}.gemboss-narr-trace-body{margin-top:6px;padding:8px;border-left:2px solid var(--gemboss-divider-soft);color:var(--gemboss-text-muted);white-space:pre-wrap;line-height:1.5;overflow-x:auto}@media (max-width: 640px){.gemboss-ec-input textarea{min-height:0}.gemboss-ec-scroll{padding:var(--gemboss-ec-inset, 12px)}}.gemboss-ec-chips{display:flex;flex-wrap:wrap;gap:8px;margin-top:4px}.gemboss-ec-chip{background:var(--gemboss-surface);border:1px solid var(--gemboss-divider);border-radius:var(--gemboss-radius-full);padding:8px 16px;font-size:13px;cursor:pointer;color:var(--gemboss-text);min-height:44px}.gemboss-ec-chip:hover{border-color:var(--gemboss-primary);color:var(--gemboss-active-fg)}.gemboss-ec-chip:disabled{opacity:.5;cursor:default}@media (pointer: fine){.gemboss-ec-starters{row-gap:16px}.gemboss-ec-tab,.gemboss-ec-starter,.gemboss-ec-upload,.gemboss-ec-workmode,.gemboss-ec-input .gemboss-ec-attach-btn,.gemboss-ec-stop,.gemboss-ec-stop-send,.gemboss-ec-toolbar>button[type=submit]{position:relative}.gemboss-ec-tab:after,.gemboss-ec-starter:after,.gemboss-ec-upload:after,.gemboss-ec-workmode:before,.gemboss-ec-input .gemboss-ec-attach-btn:after,.gemboss-ec-stop:after,.gemboss-ec-stop-send:after,.gemboss-ec-toolbar>button[type=submit]:after{content:"";position:absolute;left:0;right:0;top:50%;transform:translateY(-50%);height:44px;pointer-events:auto;z-index:1}}@media (pointer: coarse){.gemboss-ec-toolbar>button[type=submit]{width:44px;height:44px;font-size:17px}.gemboss-ec-starter,.gemboss-ec-opt,.gemboss-ec-input textarea{min-height:44px}}.gemboss-md-p{margin:0 0 8px}.gemboss-md-p:last-child{margin-bottom:0}.gemboss-md-h{margin:16px 0 6px;font-weight:650;line-height:1.3}.gemboss-md-h:first-child{margin-top:0}.gemboss-md-h1{font-size:17px}.gemboss-md-h2{font-size:15px}.gemboss-md-h3{font-size:var(--gemboss-fs-body);color:var(--gemboss-text-subdued, #616161)}.gemboss-md-list{margin:0 0 8px;padding-left:20px}.gemboss-md-list li{margin:2px 0}.gemboss-md-quote{margin:0 0 8px;padding:2px 0 2px 12px;border-left:3px solid var(--gemboss-border, #e3e3e3);color:var(--gemboss-text-subdued, #616161)}.gemboss-md-rule{margin:12px 0;border:0;border-top:1px solid var(--gemboss-border, #e3e3e3)}.gemboss-md-code{padding:1px 6px;border-radius:6px;background:var(--gemboss-surface-subdued, #f1f1f1);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.9em;word-break:break-word}.gemboss-md-tablewrap{margin:0 0 12px;overflow-x:auto}.gemboss-md-table{border-collapse:collapse;font-size:var(--gemboss-fs-caption);min-width:100%}.gemboss-md-table th,.gemboss-md-table td{border:1px solid var(--gemboss-border, #e3e3e3);padding:6px 8px;text-align:left;vertical-align:top;white-space:nowrap}.gemboss-md-table th{background:var(--gemboss-surface-subdued, #f7f7f7);font-weight:600}.gemboss-md-imglink{display:inline-block;max-width:100%;margin:4px 0 8px;border-radius:8px;line-height:0}.gemboss-md-imglink:focus-visible{outline:2px solid var(--gemboss-focus, var(--ui-focus, #5661f5));outline-offset:2px}.gemboss-md-img{display:block;max-width:100%;max-height:320px;height:auto;border:1px solid var(--gemboss-border, #e3e3e3);border-radius:8px;background:var(--gemboss-surface-subdued, #f7f7f7);object-fit:contain}.gemboss-md-codeblock{position:relative;margin:0 0 12px;border:1px solid var(--gemboss-border, #e3e3e3);border-radius:8px;background:var(--gemboss-surface-subdued, #f7f7f7);overflow:hidden}.gemboss-md-codelang{display:block;padding:4px 12px 0;color:var(--gemboss-text-subdued, #8a8a8a);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px}.gemboss-md-codeblock pre{margin:0;padding:8px 12px;overflow-x:auto}.gemboss-md-codeblock code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;line-height:1.5;white-space:pre}.gemboss-md-codemore{display:block;width:100%;padding:6px 12px;border:0;border-top:1px solid var(--gemboss-border, #e3e3e3);background:transparent;color:var(--gemboss-text-subdued, #616161);font-size:12px;text-align:left;cursor:pointer}.gemboss-md-codemore:hover{background:#00000008}.gemboss-narr-row.source{align-items:flex-start}.gemboss-narr-source{min-width:0;flex:1}.gemboss-narr-source-head{font-size:11px;color:var(--gemboss-text-muted, #686b71);margin-bottom:4px}.gemboss-narr-source-head code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.gemboss-narr-source-code{margin:0;padding:8px 12px;border-radius:8px;max-height:220px;overflow:auto;background:var(--gemboss-primary-soft, #f2f3f5);border:1px solid var(--gemboss-divider, #e5e7ea);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:var(--gemboss-fs-micro);line-height:17px;white-space:pre;tab-size:2}.gemboss-narr-source-code .c-com{color:#6a7a86;font-style:italic}.gemboss-narr-source-code .c-str{color:#9a3412}.gemboss-narr-source-code .c-num{color:#1d6fa5}.gemboss-narr-source-code .c-kw{color:#7c3aed;font-weight:600}.gemboss-narr-source-code .c-key{color:#0b6b3a}.gemboss-narr-source-code .c-tag{color:#b0197a}.gemboss-narr-source-code .c-attr{color:#7c3aed}.gemboss-narr-source-code .c-pun{color:#6a6d73}@media (max-width: 520px){.gemboss-narr-source-code{max-height:160px;font-size:11px}}.gemboss-narr-dot-quiet{visibility:hidden}
1
+ .gemboss-ec{--gemboss-ec-inset: 16px}@media (max-width: 640px){.gemboss-ec{--gemboss-ec-inset: 12px}}.gemboss-ec-head{padding:16px var(--gemboss-ec-inset, 16px);border-bottom:1px solid var(--gemboss-divider);display:flex;flex-direction:column;gap:2px}.gemboss-ec-title{font-family:var(--gemboss-serif);font-size:15px;font-weight:600}.gemboss-ec-sub{font-size:12px;color:var(--gemboss-text-muted)}.gemboss-ec-scroll{flex:1;min-height:0;overflow-y:auto;padding:var(--gemboss-ec-inset, 16px);display:flex;flex-direction:column;gap:16px;scrollbar-gutter:stable}.gemboss-ec-scroll{scrollbar-width:thin;scrollbar-color:rgba(31,30,29,.22) transparent}.gemboss-ec-scroll::-webkit-scrollbar{width:9px}.gemboss-ec-scroll::-webkit-scrollbar-track{background:transparent}.gemboss-ec-scroll::-webkit-scrollbar-thumb{background:#1f1e1d33;border-radius:6px;border:2px solid transparent;background-clip:content-box}.gemboss-ec-msg{display:flex;flex-direction:column;gap:8px;max-width:100%}.gemboss-ec-msg.user{align-items:flex-end}.gemboss-ec-msg.assistant{align-items:flex-start}.gemboss-ec-bubble{font-size:var(--gemboss-fs-body);line-height:1.5;padding:12px;border-radius:16px;max-width:min(90%,68ch);white-space:pre-wrap;word-break:break-word}.gemboss-ec-msg.user .gemboss-ec-bubble{background:var(--gemboss-primary);color:var(--gemboss-on-primary, #fff);border-bottom-right-radius:4px}.gemboss-ec-msg.assistant .gemboss-ec-bubble{background:var(--gemboss-surface);color:var(--gemboss-text);border:1px solid var(--gemboss-divider);border-bottom-left-radius:4px}.gemboss-ec-msg.user .gemboss-ec-bubble,:root[data-theme=dark] .gemboss-ec-msg.assistant .gemboss-ec-bubble{--gemboss-ec-md-ink: color-mix(in srgb, currentColor 78%, transparent);--gemboss-ec-md-line: color-mix(in srgb, currentColor 32%, transparent);--gemboss-ec-md-fill: color-mix(in srgb, currentColor 14%, transparent)}:is(.gemboss-ec-msg.user,:root[data-theme=dark] .gemboss-ec-msg.assistant) .gemboss-ec-bubble :is(.gemboss-md-h3,.gemboss-md-quote){color:var(--gemboss-ec-md-ink)}:is(.gemboss-ec-msg.user,:root[data-theme=dark] .gemboss-ec-msg.assistant) .gemboss-ec-bubble :is(.gemboss-md-quote,.gemboss-md-rule,.gemboss-md-table th,.gemboss-md-table td,.gemboss-md-codeblock,.gemboss-md-img){border-color:var(--gemboss-ec-md-line)}:is(.gemboss-ec-msg.user,:root[data-theme=dark] .gemboss-ec-msg.assistant) .gemboss-ec-bubble :is(.gemboss-md-code,.gemboss-md-table th,.gemboss-md-codeblock,.gemboss-md-img){background:var(--gemboss-ec-md-fill)}.gemboss-ec-toolbar>button[type=submit] svg{width:18px;height:18px;fill:currentColor}.gemboss-ec-pending{display:inline-flex;align-items:center;gap:8px;padding:6px 2px;font-size:var(--gemboss-fs-caption);color:var(--gemboss-text-muted)}.gemboss-ec-pending-star{color:var(--gemboss-primary);font-size:12px;line-height:1;animation:gemboss-star-pulse 1.1s ease-in-out infinite}.gemboss-ec-pending-verb{color:var(--gemboss-text);animation:gemboss-verb-in .4s ease-out}.gemboss-ec-pending-meta{font-variant-numeric:tabular-nums;opacity:.7;font-size:var(--gemboss-fs-caption)}@keyframes gemboss-star-pulse{0%,to{transform:scale(.85);opacity:.55}50%{transform:scale(1.15);opacity:1}}@keyframes gemboss-verb-in{0%{opacity:0;transform:translateY(2px)}to{opacity:1;transform:none}}.gemboss-ec-cursor{display:inline-block;width:2px;height:1.05em;margin-left:2px;vertical-align:-2px;background:var(--gemboss-primary);border-radius:2px;animation:gemboss-cursor-blink 1s steps(1) infinite}@keyframes gemboss-cursor-blink{0%,45%{opacity:1}50%,95%{opacity:.15}to{opacity:1}}@media (prefers-reduced-motion: reduce){.gemboss-ec-pending-star,.gemboss-ec-cursor{animation:none}}.gemboss-ec-md-link{color:var(--gemboss-primary-dark);font-weight:600;text-decoration:none;border-bottom:1px solid color-mix(in srgb,var(--gemboss-primary) 35%,transparent);cursor:pointer}.gemboss-ec-md-link:hover{border-bottom-color:var(--gemboss-primary)}strong>.gemboss-ec-md-link{font-weight:inherit}.gemboss-ec-md-link:focus-visible{outline:2px solid currentColor;outline-offset:2px;border-radius:2px}.gemboss-ec-msg.user .gemboss-ec-md-link{color:inherit;border-bottom-color:color-mix(in srgb,currentColor 55%,transparent)}.gemboss-ec-msg.user .gemboss-ec-md-link:hover{border-bottom-color:currentColor}.gemboss-ec-starters{display:flex;flex-wrap:wrap;gap:8px;margin-top:4px}.gemboss-ec-starter{text-align:left;font-size:13px;padding:6px 12px;border-radius:var(--gemboss-radius-full);cursor:pointer;background:var(--gemboss-surface);border:1px solid var(--gemboss-divider);color:var(--gemboss-text);white-space:nowrap;max-width:100%}.gemboss-ec-starter:hover{border-color:var(--gemboss-primary);background:#5661f50f}.gemboss-ec-input{display:flex;flex-wrap:wrap;align-items:center;gap:4px;margin:12px;padding:8px;border:1px solid var(--gemboss-divider);border-radius:16px;background:var(--gemboss-surface);transition:border-color var(--gemboss-transition-fast) ease,box-shadow var(--gemboss-transition-fast) ease}.gemboss-ec-input:focus-within{border-color:var(--gemboss-primary);box-shadow:0 0 0 3px color-mix(in srgb,var(--gemboss-primary) 12%,transparent)}.gemboss-ec-input textarea{flex:1 0 100%;min-width:0;width:100%;box-sizing:border-box;resize:none;border-radius:0;background:transparent;border:1px solid transparent;padding:6px 8px;font-size:var(--gemboss-fs-body);font-family:inherit;min-height:0;max-height:84px;line-height:1.5;overflow-y:auto;scrollbar-width:thin;scrollbar-color:rgba(31,30,29,.22) transparent}.gemboss-ec-input textarea::-webkit-scrollbar{width:7px}.gemboss-ec-input textarea::-webkit-scrollbar-track{background:transparent}.gemboss-ec-input textarea::-webkit-scrollbar-thumb{background:#1f1e1d33;border-radius:4px;border:2px solid transparent;background-clip:content-box}.gemboss-ec-input textarea:focus{outline:none}.gemboss-ec-toolbar>button[type=submit]{flex:0 0 auto;width:44px;height:44px;min-width:44px;min-height:44px;border-radius:50%;border:0;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;background:var(--gemboss-primary);color:var(--gemboss-on-primary, #fff);font-size:16px;font-weight:700;transition:background var(--gemboss-transition-fast) ease,filter var(--gemboss-transition-fast) ease}.gemboss-ec-toolbar>button[type=submit]:hover:not(:disabled){background:var(--gemboss-primary-dark)}.gemboss-ec-toolbar>button[type=submit]:active:not(:disabled){background:var(--gemboss-primary-dark);filter:brightness(.94)}.gemboss-ec-toolbar>button[type=submit]:focus-visible{outline:2px solid var(--gemboss-primary);outline-offset:2px}.gemboss-ec-toolbar>button[type=submit]:disabled{background:var(--gemboss-divider);color:var(--gemboss-text-muted);opacity:1;cursor:default}.gemboss-narr{list-style:none;margin:0;padding:8px 0 0;display:flex;flex-direction:column;gap:8px}.gemboss-narr-row{display:flex;align-items:center;gap:8px;font-size:var(--gemboss-fs-caption);color:var(--gemboss-text-muted)}.gemboss-narr-dot{width:16px;height:16px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;font-size:10px;flex:0 0 auto}.gemboss-narr-row.ok .gemboss-narr-dot{background:var(--gemboss-active-bg);color:var(--gemboss-active-fg)}.gemboss-narr-row.failed .gemboss-narr-dot{background:#fde8e6;color:var(--gemboss-danger)}.gemboss-narr-row.running .gemboss-narr-dot{background:transparent}.gemboss-narr-dot-engine{background:transparent!important;color:inherit}.gemboss-narr-row.ok .gemboss-narr-dot-engine{color:var(--gemboss-text)}.gemboss-narr-row.failed .gemboss-narr-dot-engine{color:var(--gemboss-danger)}.gemboss-narr-row.ok .gemboss-narr-text,.gemboss-narr-row.failed .gemboss-narr-text{color:var(--gemboss-text)}.gemboss-narr-row.steer .gemboss-narr-dot{background:transparent;color:var(--gemboss-text-muted)}.gemboss-narr-steer{color:var(--gemboss-text);font-weight:500;overflow-wrap:anywhere}.gemboss-narr-spin{width:11px;height:11px;border:2px solid var(--gemboss-divider-soft);border-top-color:var(--gemboss-primary);border-radius:50%;animation:gemboss-spin .7s linear infinite}@keyframes gemboss-spin{to{transform:rotate(360deg)}}.gemboss-narr-row.thinking{align-items:flex-start}.gemboss-narr-row.thinking .gemboss-narr-dot{color:var(--gemboss-text-muted);background:transparent}.gemboss-narr-thinking-live{font-style:italic;color:var(--gemboss-text-muted);white-space:pre-wrap;opacity:.9;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}.gemboss-narr-thinking{font-size:var(--gemboss-fs-caption)}.gemboss-narr-thinking>summary{cursor:pointer;color:var(--gemboss-text-muted);list-style:none;user-select:none}.gemboss-narr-thinking>summary::-webkit-details-marker{display:none}.gemboss-narr-thinking>summary:before{content:"\25b8 "}.gemboss-narr-thinking[open]>summary:before{content:"\25be "}.gemboss-narr-thinking-body{margin-top:6px;padding:8px;border-left:2px solid var(--gemboss-divider-soft);color:var(--gemboss-text-muted);font-style:italic;white-space:pre-wrap;line-height:1.5}.gemboss-narr-row.trace code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:var(--gemboss-fs-caption);word-break:break-word}.gemboss-narr-trace-call{color:var(--gemboss-text-muted);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.gemboss-narr-trace{font-size:var(--gemboss-fs-caption);min-width:0}.gemboss-narr-trace>summary{cursor:pointer;color:var(--gemboss-text-muted);list-style:none;user-select:none;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.gemboss-narr-trace[open]>summary{display:block;overflow:visible}.gemboss-narr-trace>summary::-webkit-details-marker{display:none}.gemboss-narr-trace>summary,.gemboss-narr-thinking>summary{min-height:24px;box-sizing:border-box;padding-block:2px}.gemboss-narr-trace>summary:before{content:"\25b8 "}.gemboss-narr-trace[open]>summary:before{content:"\25be "}.gemboss-narr-trace-body{margin-top:6px;padding:8px;border-left:2px solid var(--gemboss-divider-soft);color:var(--gemboss-text-muted);white-space:pre-wrap;line-height:1.5;overflow-x:auto}@media (max-width: 640px){.gemboss-ec-input textarea{min-height:0}.gemboss-ec-scroll{padding:var(--gemboss-ec-inset, 12px)}}.gemboss-ec-chips{display:flex;flex-wrap:wrap;gap:8px;margin-top:4px}.gemboss-ec-chip{background:var(--gemboss-surface);border:1px solid var(--gemboss-divider);border-radius:var(--gemboss-radius-full);padding:8px 16px;font-size:13px;cursor:pointer;color:var(--gemboss-text);min-height:44px}.gemboss-ec-chip:hover{border-color:var(--gemboss-primary);color:var(--gemboss-active-fg)}.gemboss-ec-chip:disabled{opacity:.5;cursor:default}@media (pointer: fine){.gemboss-ec-starters{row-gap:16px}.gemboss-ec-tab,.gemboss-ec-starter,.gemboss-ec-upload,.gemboss-ec-workmode,.gemboss-ec-input .gemboss-ec-attach-btn,.gemboss-ec-stop,.gemboss-ec-stop-send,.gemboss-ec-toolbar>button[type=submit]{position:relative}.gemboss-ec-tab:after,.gemboss-ec-starter:after,.gemboss-ec-upload:after,.gemboss-ec-workmode:before,.gemboss-ec-input .gemboss-ec-attach-btn:after,.gemboss-ec-stop:after,.gemboss-ec-stop-send:after,.gemboss-ec-toolbar>button[type=submit]:after{content:"";position:absolute;left:0;right:0;top:50%;transform:translateY(-50%);height:44px;pointer-events:auto;z-index:1}}@media (pointer: coarse){.gemboss-ec-toolbar>button[type=submit]{width:44px;height:44px;font-size:17px}.gemboss-ec-starter,.gemboss-ec-opt,.gemboss-ec-input textarea{min-height:44px}}.gemboss-md-p{margin:0 0 8px}.gemboss-md-p:last-child{margin-bottom:0}.gemboss-md-h{margin:16px 0 6px;font-weight:650;line-height:1.3}.gemboss-md-h:first-child{margin-top:0}.gemboss-md-h1{font-size:17px}.gemboss-md-h2{font-size:15px}.gemboss-md-h3{font-size:var(--gemboss-fs-body);color:var(--gemboss-text-muted)}.gemboss-md-list{margin:0 0 8px;padding-left:20px}.gemboss-md-list li{margin:2px 0}.gemboss-md-quote{margin:0 0 8px;padding:2px 0 2px 12px;border-left:3px solid var(--gemboss-divider);color:var(--gemboss-text-muted)}.gemboss-md-rule{margin:12px 0;border:0;border-top:1px solid var(--gemboss-divider)}.gemboss-md-code{padding:1px 6px;border-radius:6px;background:var(--gemboss-primary-soft);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.9em;word-break:break-word}.gemboss-md-tablewrap{margin:0 0 12px;overflow-x:auto}.gemboss-md-table{border-collapse:collapse;font-size:var(--gemboss-fs-caption);min-width:100%}.gemboss-md-table th,.gemboss-md-table td{border:1px solid var(--gemboss-divider);padding:6px 8px;text-align:left;vertical-align:top;white-space:nowrap}.gemboss-md-table th{background:var(--gemboss-primary-soft);font-weight:600}.gemboss-md-imglink{display:inline-block;max-width:100%;margin:4px 0 8px;border-radius:8px;line-height:0}.gemboss-md-imglink:focus-visible{outline:2px solid var(--ui-focus, #5661f5);outline-offset:2px}.gemboss-md-img{display:block;max-width:100%;max-height:320px;height:auto;border:1px solid var(--gemboss-divider);border-radius:8px;background:var(--gemboss-primary-soft);object-fit:contain}.gemboss-md-codeblock{position:relative;margin:0 0 12px;border:1px solid var(--gemboss-divider);border-radius:8px;background:var(--gemboss-primary-soft);overflow:hidden}.gemboss-md-codelang{display:block;padding:4px 12px 0;color:var(--gemboss-text-muted);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px}.gemboss-md-codeblock pre{margin:0;padding:8px 12px;overflow-x:auto}.gemboss-md-codeblock code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;line-height:1.5;white-space:pre}.gemboss-md-codemore{display:block;width:100%;padding:6px 12px;border:0;border-top:1px solid var(--gemboss-divider);background:transparent;color:var(--gemboss-text-muted);font-size:12px;text-align:left;cursor:pointer}.gemboss-md-codemore:hover{background:#00000008}.gemboss-narr-row.source{align-items:flex-start}.gemboss-narr-source{min-width:0;flex:1}.gemboss-narr-source-head{font-size:11px;color:var(--gemboss-text-muted, #686b71);margin-bottom:4px}.gemboss-narr-source-head code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.gemboss-narr-source-code{margin:0;padding:8px 12px;border-radius:8px;max-height:220px;overflow:auto;background:var(--gemboss-primary-soft, #f2f3f5);border:1px solid var(--gemboss-divider, #e5e7ea);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:var(--gemboss-fs-micro);line-height:17px;white-space:pre;tab-size:2}.gemboss-narr-source-code .c-com{color:#6a7a86;font-style:italic}.gemboss-narr-source-code .c-str{color:#9a3412}.gemboss-narr-source-code .c-num{color:#1d6fa5}.gemboss-narr-source-code .c-kw{color:#7c3aed;font-weight:600}.gemboss-narr-source-code .c-key{color:#0b6b3a}.gemboss-narr-source-code .c-tag{color:#b0197a}.gemboss-narr-source-code .c-attr{color:#7c3aed}.gemboss-narr-source-code .c-pun{color:#6a6d73}@media (max-width: 520px){.gemboss-narr-source-code{max-height:160px;font-size:11px}}.gemboss-narr-dot-quiet{visibility:hidden}
@@ -1 +1 @@
1
- :root{--ui-coll-head-bg: color-mix(in srgb, var(--ui-text, #1b1c1e) 3.5%, var(--ui-surface, #fff));--ui-coll-hover: color-mix(in srgb, var(--ui-text, #1b1c1e) 3.5%, var(--ui-surface, #fff));--ui-coll-selected: color-mix(in srgb, var(--ui-text, #1b1c1e) 6%, var(--ui-surface, #fff));--ui-coll-check-w: 40px}.ui-table-wrap.ui-table-wrap--flush{border:0;border-radius:0;box-shadow:none;background:transparent}.ui-table--sticky-first tr{background:var(--ui-surface)}.ui-table--sticky-first tbody tr:hover{background:var(--ui-surface-2)}.ui-table--sticky-first :is(th,td):first-child{position:sticky;left:0;z-index:1;background:inherit}@supports (animation-timeline: scroll()){.ui-table-wrap:has(>.ui-table--sticky-first){scroll-timeline:--ui-coll-x inline}.ui-table--sticky-first :is(th,td):first-child{animation:ui-coll-edge linear both;animation-timeline:--ui-coll-x;animation-range:0 24px}}@keyframes ui-coll-edge{0%{box-shadow:none}to{box-shadow:1px 0 0 var(--ui-border),6px 0 8px -6px #0000002e}}.ui-table--compact :is(td,tbody th){padding-block:6px}.ui-table--compact thead th{padding-block:6px}.ui-table__totals>tr{background:var(--ui-coll-head-bg)}.ui-table__totals>tr>:is(td,th){background:var(--ui-coll-head-bg);font-weight:650;color:var(--ui-text);border-top:1px solid var(--ui-border);border-bottom:0}.ui-table__footer{padding:8px 12px;background:var(--ui-coll-head-bg);border-top:1px solid var(--ui-border);color:var(--ui-text-muted);font-size:var(--ui-fs-body);text-align:center}.ui-table th.ui-table__rowhead{font-weight:450;color:var(--ui-text);text-align:left}.ui-table th.ui-table__rowhead:not(.is-num){white-space:normal;min-width:9.0625rem;overflow-wrap:anywhere}.ui-table th.ui-table__rowhead>a,.ui-table:where(:not(.ui-table--index)) tbody :is(td,th) li>a{display:inline-flex;align-items:center;min-height:24px}.ui-table:where(:not(.ui-table--index)) tbody :is(td,th){vertical-align:top}.ui-table:where(:not(.ui-table--index)) tbody :is(td>a,th.ui-table__rowhead>a,:is(td,th) li>a){margin-block:calc((1lh - 24px)/2)}.ui-table__sort{display:flex;width:max-content;max-width:100%;align-items:center;gap:4px;min-height:24px;margin-block:-2px;padding:0;border:0;background:none;color:inherit;font:inherit;text-align:inherit;text-decoration:none;cursor:pointer;white-space:nowrap}.ui-table__sort:hover{color:var(--ui-text)}.ui-table__sort:focus-visible{outline:2px solid var(--ui-focus);outline-offset:2px;border-radius:4px}.ui-table__sort:after{content:"";flex:none;width:16px;height:16px;background:currentColor;opacity:0;-webkit-mask:var(--ui-coll-arrow) center / 16px no-repeat;mask:var(--ui-coll-arrow) center / 16px no-repeat;--ui-coll-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M8 3.5v9M4.5 9 8 12.5 11.5 9' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E")}.ui-table__sort:is(:hover,:focus-visible):after{opacity:.45}th[aria-sort=ascending]>.ui-table__sort:after,th[aria-sort=descending]>.ui-table__sort:after{opacity:1}th[aria-sort=ascending]>.ui-table__sort:after{transform:rotate(180deg)}th[aria-sort=ascending]>.ui-table__sort,th[aria-sort=descending]>.ui-table__sort{color:var(--ui-text)}.ui-table .is-num>.ui-table__sort{flex-direction:row-reverse;margin-left:auto}.ui-trunc{display:block;max-width:var(--ui-trunc, 32ch);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ui-clamp-2{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2;overflow:hidden;white-space:normal;overflow-wrap:anywhere}.ui-index{position:relative;container:ui-index / inline-size;min-width:0}.ui-table--index{font-size:var(--ui-fs-body)}.ui-table--index tr{background:var(--ui-surface)}.ui-table.ui-table--index thead th{padding:8px 6px;background:var(--ui-coll-head-bg);color:var(--ui-text-muted);font-size:var(--ui-fs-caption);line-height:20px;font-weight:550;text-transform:none;letter-spacing:0}.ui-table.ui-table--index :is(td,tbody th){padding:6px;line-height:20px;white-space:nowrap;vertical-align:middle;border-bottom:0;border-top:1px solid var(--ui-border)}.ui-table.ui-table--index :is(th,td):where(:first-child){padding-left:var(--ui-space-3)}.ui-table.ui-table--index :is(th,td):where(:last-child){padding-right:var(--ui-space-3)}.ui-table--index tbody tr:hover{background:var(--ui-coll-hover)}.ui-table--index tbody tr:is(.is-selected,[aria-selected=true]){background:var(--ui-coll-selected)}.ui-table--index tbody tr:is([data-href],.is-linked){cursor:pointer}.ui-table--index tbody tr:has(.ui-table__title:focus-visible){outline:2px solid var(--ui-focus);outline-offset:-2px}.ui-table__title:focus-visible{outline:none}.ui-table__primary{min-width:0}.ui-table__primary-inner{display:flex;align-items:center;gap:var(--ui-space-3);min-width:0}.ui-table__primary-text{min-width:0}.ui-table__title{display:block;max-width:var(--ui-trunc, 40ch);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--ui-text);font-weight:650;text-decoration:none}a.ui-table__title:hover{text-decoration:underline}.ui-table--index .ui-table__title+.ui-sub,.ui-table--index .ui-sub{display:block;max-width:var(--ui-trunc, 40ch);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin-top:0;line-height:16px}.ui-table--index td>a.ui-table__title{display:block;min-height:0}.ui-table--index td>.ui-table__primary-inner>a.ui-table__title,.ui-table--index .ui-table__primary-text>a.ui-table__title{line-height:20px}.ui-table.ui-table--index .ui-table__check{width:var(--ui-coll-check-w);padding:6px 8px 6px 12px}.ui-table.ui-table--index thead .ui-table__check{padding:8px 8px 8px 12px}.ui-table__checkbox{display:flex;width:max-content;align-items:center;justify-content:center;min-width:24px;min-height:24px;margin:-2px 0;cursor:pointer}.ui-table__checkbox>input,.ui-list__check>input{width:16px;height:16px;margin:0;accent-color:var(--ui-accent);cursor:pointer}.ui-table__checkbox>input:focus-visible,.ui-list__check>input:focus-visible{outline:2px solid var(--ui-focus);outline-offset:2px}.ui-table--index :is(.ui-table__check,.ui-table__primary){position:sticky;z-index:1;background:inherit}.ui-table--index .ui-table__check,.ui-table--index .ui-table__primary{left:0}.ui-table--index:has(.ui-table__check) .ui-table__primary{left:var(--ui-coll-check-w)}.ui-table__actions{width:1%;text-align:right}.ui-table__actions>*{vertical-align:middle}.ui-row-actions{display:inline-flex;align-items:center;gap:var(--ui-space-2)}.ui-bulkbar{position:relative;z-index:3;display:flex;flex-wrap:wrap;align-items:center;gap:var(--ui-space-2);box-sizing:border-box;min-height:38px;margin-bottom:-38px;padding:4px 8px 4px 12px;background:var(--ui-surface);border:1px solid var(--ui-border);border-bottom-color:transparent;border-radius:var(--ui-radius-lg) var(--ui-radius-lg) 0 0;font-size:var(--ui-fs-body)}.ui-bulkbar[hidden]{display:none}.ui-bulkbar__count{flex:none;font-weight:550;font-variant-numeric:tabular-nums;white-space:nowrap}.ui-bulkbar__actions{display:inline-flex;flex-wrap:wrap;gap:var(--ui-space-2);margin-left:auto}.ui-bulkbar .ui-table__checkbox{margin-right:4px}.ui-bulkbar[data-fit=pending]{flex-wrap:nowrap}.ui-bulkbar[data-fit=pending]>.ui-bulkbar__actions{flex:0 1 auto;flex-wrap:nowrap;min-width:0;overflow:hidden}.ui-bulkbar__actions>.ui-bulkbar__more{flex:none}.ui-bulkbar__measure{position:absolute;top:0;left:0;display:inline-flex;gap:var(--ui-space-2);height:0;overflow:hidden;visibility:hidden;pointer-events:none;white-space:nowrap}.ui-bulkbar__measure>*{flex:none}.ui-index__sortbar{display:none}@container ui-index (max-width: 768px){.ui-table--index,.ui-table--index tbody{display:block;width:100%}.ui-table--index thead{display:none}.ui-table--index tbody tr{position:relative;display:flex;flex-wrap:wrap;align-items:baseline;gap:2px 12px;min-height:44px;box-sizing:border-box;padding:10px 12px;border-top:1px solid var(--ui-border)}.ui-table--index tbody tr:first-child{border-top:0}.ui-table--index tbody tr:has(>.ui-table__check){padding-left:48px}.ui-table.ui-table--index tbody :is(td,th){display:block;padding:0;border:0;position:static;background:none;white-space:nowrap}.ui-table--index tbody .ui-table__primary{flex:1 0 100%;white-space:normal}.ui-table--index tbody td:not(.ui-table__primary,.ui-table__check,.ui-table__actions){flex:none;max-width:100%;overflow:hidden;text-overflow:ellipsis;color:var(--ui-text-muted);font-size:var(--ui-fs-caption);line-height:18px}.ui-table--index tbody td[data-label]:not(.ui-table__primary):before{content:attr(data-label) " ";color:var(--ui-text-muted)}.ui-table--index tbody td:not(.ui-table__primary,.ui-table__check,.ui-table__actions) .ui-trunc{display:inline-block;vertical-align:bottom}.ui-table--index tbody td:not(.ui-table__primary,.ui-table__check,.ui-table__actions) .ui-sub{display:inline;margin-left:6px}.ui-table--index tbody td.is-num{text-align:left}.ui-table--index tbody td[data-condensed=hide]{display:none}.ui-table.ui-table--index tbody .ui-table__check{position:absolute;left:4px;top:4px;width:auto;padding:0}.ui-table.ui-table--index tbody .ui-table__actions{order:99;margin-left:auto;width:auto;padding:0;align-self:center}.ui-table--index .ui-table__checkbox{min-width:44px;min-height:44px;margin:0}.ui-table--index .ui-table__title,.ui-table--index .ui-sub,.ui-table--index .ui-table__title+.ui-sub{max-width:none}.ui-table--index tbody a.ui-table__title{position:relative;z-index:1;padding-block:2px;margin-block:-2px}.ui-index__sortbar{display:flex;flex-wrap:wrap;align-items:center;gap:var(--ui-space-2);margin:0 0 var(--ui-space-3);font-size:var(--ui-fs-caption);color:var(--ui-text-muted)}.ui-index .ui-bulkbar{margin-bottom:var(--ui-space-2);border-bottom-color:var(--ui-border);border-radius:var(--ui-radius-lg)}.ui-index .ui-table-wrap{overflow-x:visible}}.ui-list{container:ui-list / inline-size;margin:0;padding:0;list-style:none;background:var(--ui-surface);border:1px solid var(--ui-border);border-radius:var(--ui-radius-lg);box-shadow:var(--ui-card-shadow)}.ui-list--flush{border:0;border-radius:0;box-shadow:none;background:transparent}.ui-list__item{position:relative;display:flex;align-items:flex-start;gap:var(--ui-space-3);box-sizing:border-box;padding:var(--ui-space-3);min-height:44px;border-top:1px solid var(--ui-border)}.ui-list>.ui-list__item:first-child{border-top:0}.ui-list>.ui-list__item:first-child{border-top-left-radius:inherit;border-top-right-radius:inherit}.ui-list>.ui-list__item:last-child{border-bottom-left-radius:inherit;border-bottom-right-radius:inherit}.ui-list__item:has(>.ui-list__body>.ui-list__title[href]):hover{background:var(--ui-coll-hover)}.ui-list__item:is(.is-selected,[aria-selected=true]){background:var(--ui-coll-selected)}.ui-list__item:has(>.ui-list__body>.ui-list__title:focus-visible){outline:2px solid var(--ui-focus);outline-offset:-2px}.ui-list__media{flex:none;display:flex;align-items:center;min-height:40px}.ui-list__body{flex:1 1 auto;min-width:0}.ui-list__title{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--ui-text);font-size:var(--ui-fs-body);line-height:20px;font-weight:650;text-decoration:none}.ui-list__title[href]:after{content:"";position:absolute;inset:0;z-index:0}.ui-list__title:focus-visible{outline:none}.ui-list__sub{margin:0;color:var(--ui-text-muted);font-size:var(--ui-fs-body);line-height:20px;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2;overflow:hidden;overflow-wrap:anywhere}.ui-list__meta{margin:2px 0 0;color:var(--ui-text-muted);font-size:var(--ui-fs-caption);line-height:16px}.ui-list__badges{display:flex;flex-wrap:wrap;gap:4px;margin-top:4px}.ui-list__aside{flex:none;align-self:center;color:var(--ui-text);font-variant-numeric:tabular-nums;text-align:right}.ui-list__actions{flex:none;align-self:center;display:inline-flex;align-items:center;gap:var(--ui-space-2)}.ui-list__item :is(.ui-list__actions,.ui-list__aside a,.ui-list__body a:not(.ui-list__title),button,input,select,textarea,label,summary,details){position:relative;z-index:1}.ui-list__item>:is(.ui-list__actions,.ui-list__aside) a:not(.ui-btn){display:inline-flex;align-items:center;min-height:24px}@container ui-list (max-width: 400px){.ui-list:not(.ui-list--compact,.ui-skeleton--list)>.ui-list__item{display:grid;grid-template-columns:auto minmax(0,1fr) auto;grid-template-areas:"media body body" "media aside actions";gap:0;align-items:start}.ui-list:not(.ui-list--compact,.ui-skeleton--list)>.ui-list__item>.ui-list__media{grid-area:media;margin-inline-end:var(--ui-space-3)}.ui-list:not(.ui-list--compact,.ui-skeleton--list)>.ui-list__item>.ui-list__body{grid-area:body}.ui-list:not(.ui-list--compact,.ui-skeleton--list)>.ui-list__item>.ui-list__aside{grid-area:aside;justify-self:start;align-self:center;margin-top:4px;text-align:left}.ui-list:not(.ui-list--compact,.ui-skeleton--list)>.ui-list__item>.ui-list__actions{grid-area:actions;justify-self:end;align-self:center;margin:4px 0 0 var(--ui-space-3)}.ui-list:not(.ui-list--compact,.ui-skeleton--list)>.ui-list__item--disclosure>:is(.ui-list__aside,.ui-list__actions){margin-top:8px}.ui-list:not(.ui-list--compact,.ui-skeleton--list)>.ui-list__item:has(>.ui-list__body>.ui-list__title:only-child){grid-template-columns:auto minmax(0,1fr) auto auto;grid-template-areas:"media body aside actions";align-items:center}.ui-list:not(.ui-list--compact,.ui-skeleton--list)>.ui-list__item:has(>.ui-list__body>.ui-list__title:only-child)>:is(.ui-list__aside,.ui-list__actions){margin-top:0}.ui-list:not(.ui-list--compact,.ui-skeleton--list)>.ui-list__item:has(>.ui-list__body>.ui-list__title:only-child)>.ui-list__aside{margin-inline-start:var(--ui-space-3);text-align:right}.ui-list:not(.ui-list--compact,.ui-skeleton--list)>.ui-list__item>.ui-list__panel{grid-column:1 / -1}}.ui-list__item--disclosure{flex-wrap:wrap}.ui-list__toggle{display:block;flex:1 1 0;min-width:0;min-height:24px;margin:0;padding:0;border:0;border-radius:var(--ui-radius-sm, 4px);background:none;color:inherit;font:inherit;text-align:left;cursor:pointer}.ui-list__toggle:focus-visible{outline:2px solid var(--ui-focus);outline-offset:2px}.ui-list__toggle>.ui-list__meta{display:block}@media (hover: hover){.ui-list__item--disclosure:not(.is-open):has(>.ui-list__toggle:hover){background:var(--ui-coll-hover)}}.ui-list__chev{display:inline-block;width:16px;height:16px;margin:0 4px 0 -2px;vertical-align:-3px;background:var(--ui-text-muted);-webkit-mask:var(--ui-chev) center / 16px no-repeat;mask:var(--ui-chev) center / 16px no-repeat;transition:transform .15s;--ui-chev: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M6 4l4 4-4 4' fill='none' stroke='black' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E")}.ui-list__item--disclosure.is-open>.ui-list__toggle .ui-list__chev{transform:rotate(90deg)}@media (forced-colors: active){.ui-list__chev{forced-color-adjust:none;background:CanvasText}}.ui-list__panel{flex:1 0 100%;min-width:0;margin-top:var(--ui-space-2)}.ui-list__panel[hidden]{display:none}@media (pointer: coarse),(max-width: 47.9975em){.ui-list__toggle{min-height:44px}}@media (prefers-reduced-motion: reduce){.ui-list__chev{transition:none}}.ui-resource>.ui-bulkbar{margin-bottom:0;border-bottom-color:var(--ui-border)}.ui-resource>.ui-bulkbar:has(+.ui-list--flush){border-width:0 0 1px;border-radius:0}.ui-resource>.ui-list,.ui-resource>[aria-busy]>.ui-list{border-top:0;border-top-left-radius:0;border-top-right-radius:0}.ui-list__check{display:flex;flex:none;align-items:center;justify-content:center;min-width:24px;min-height:24px;cursor:pointer}.ui-list__check:not(:last-child){margin-inline-end:8px}@media (pointer: coarse),(max-width: 47.9975em){.ui-list__check{min-width:44px;min-height:44px;margin-block:-2px;margin-inline-start:-12px}.ui-list__check:not(:last-child){margin-inline-end:-2px}.ui-resource>.ui-bulkbar>.ui-table__checkbox{min-width:44px;min-height:44px;margin:-8px -8px -8px -12px}}.ui-thumb{display:block;flex:none;width:40px;height:40px;box-sizing:border-box;border:1px solid var(--ui-border);border-radius:var(--ui-radius-md);background:var(--ui-surface-2);overflow:hidden;object-fit:cover}.ui-thumb--xs{width:24px;height:24px;border-radius:var(--ui-radius-sm)}.ui-thumb--md{width:60px;height:60px}.ui-thumb--lg{width:80px;height:80px}.ui-thumb>img{display:block;width:100%;height:100%;object-fit:cover}.ui-list--compact>.ui-list__item{display:block;padding:0;min-height:0}.ui-list__row{display:flex;align-items:center;gap:var(--ui-space-2);box-sizing:border-box;width:100%;min-height:36px;padding:8px 12px;border:0;background:none;color:var(--ui-text);font:inherit;font-size:var(--ui-fs-body);line-height:20px;text-align:left;text-decoration:none;border-radius:inherit}:is(a,button).ui-list__row{cursor:pointer}:is(a,button).ui-list__row:hover{background:var(--ui-coll-hover)}:is(a,button).ui-list__row:focus-visible{outline:2px solid var(--ui-focus);outline-offset:-2px}.ui-list__row[aria-current=page],.ui-list__row.is-selected{background:var(--ui-coll-selected)}.ui-list__icon{flex:none;display:inline-flex;width:20px;height:20px;align-items:center;justify-content:center;color:var(--ui-text-muted)}.ui-list__icon>svg{width:16px;height:16px}.ui-list__label{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ui-list__row>.ui-list__meta{flex:none;margin:0;font-variant-numeric:tabular-nums}@media (pointer: coarse),(max-width: 47.9975em){.ui-list__row{min-height:44px}}.ui-list--activity>.ui-list__item{display:grid;grid-template-columns:20px minmax(0,1fr) auto;column-gap:var(--ui-space-2);align-items:start;padding:8px 12px;min-height:36px;border-top:0}.ui-list--activity>.ui-list__item:before{content:"";position:absolute;left:21.5px;top:0;bottom:0;width:1px;background:var(--ui-border)}.ui-list--activity>.ui-list__item:first-child:before{top:14px}.ui-list--activity>.ui-list__item:last-child:before{bottom:calc(100% - 14px)}.ui-list--activity>.ui-list__item:only-child:before{display:none}.ui-list__dot{position:relative;z-index:1;width:8px;height:8px;margin:6px 0 0 6px;border-radius:50%;background:var(--ui-text-muted);box-shadow:0 0 0 3px var(--ui-surface)}.ui-list__dot--success{background:var(--gemboss-success, #0a8f6a)}.ui-list__dot--warning{background:var(--gemboss-warning, #b25e09)}.ui-list__dot--critical{background:var(--gemboss-danger-strong, #c70a24)}.ui-list__dot--info{background:var(--gemboss-accent, #5661f5)}.ui-list--activity .ui-list__label{display:block;white-space:nowrap}.ui-list--activity a.ui-list__label{position:relative;color:var(--ui-text);text-decoration:none;padding-block:2px;margin-block:-2px}.ui-list--activity a.ui-list__label:hover{text-decoration:underline}.ui-list--activity a.ui-list__label:focus-visible{outline:2px solid var(--ui-focus);outline-offset:0;border-radius:4px}.ui-list--activity .ui-list__detail{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--ui-text-muted);font-size:var(--ui-fs-caption);line-height:16px}.ui-list--activity time,.ui-list--activity .ui-list__time{color:var(--ui-text-muted);font-size:var(--ui-fs-caption);line-height:20px;white-space:nowrap;font-variant-numeric:tabular-nums}.ui-list__content{margin-top:4px;color:var(--ui-text);font-size:var(--ui-fs-body);line-height:20px;overflow-wrap:anywhere}.ui-list__content>p{margin:0}.ui-list__content>p+p{margin-top:4px}.ui-list--wrap>.ui-list__item>*>:is(.ui-list__label,.ui-list__detail,.ui-list__title){white-space:normal;overflow:visible;text-overflow:clip;overflow-wrap:anywhere}.ui-list--wrap>.ui-list__item>.ui-list__row{align-items:flex-start}@media (pointer: coarse),(max-width: 47.9975em){.ui-list--wrap>.ui-list__item>.ui-list__row{padding-block:12px}}.ui-list--wrap>.ui-list__item>.ui-list__row>.ui-list__meta{line-height:20px}.ui-cardgrid{--ui-cardgrid-min: 240px;display:grid;grid-template-columns:repeat(auto-fill,minmax(min(var(--ui-cardgrid-min),100%),1fr));gap:var(--ui-space-4);margin:0;padding:0;list-style:none}.ui-cardgrid[data-min="200"]{--ui-cardgrid-min: 200px}.ui-cardgrid[data-min="320"]{--ui-cardgrid-min: 320px}.ui-cardgrid>*{min-width:0}.ui-board{display:grid;grid-auto-flow:column;grid-auto-columns:minmax(240px,1fr);gap:var(--ui-space-4);align-items:start;overflow-x:auto;overscroll-behavior-x:contain;scroll-snap-type:x mandatory;padding-bottom:4px}@media (max-width: 47.9975em){.ui-board{grid-auto-columns:78%}}.ui-board__col{display:flex;flex-direction:column;gap:var(--ui-space-2);min-width:0;padding:var(--ui-space-2);scroll-snap-align:start;background:var(--ui-coll-head-bg);border-radius:var(--ui-radius-lg)}.ui-board__head{display:flex;align-items:center;gap:var(--ui-space-2);min-height:28px;padding:0 4px;font-size:var(--ui-fs-body);font-weight:650}.ui-board__name{min-width:0;margin:0;font:inherit;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ui-board__count{margin-left:auto;color:var(--ui-text-muted);font-weight:450;font-variant-numeric:tabular-nums}.ui-board__dot{flex:none;width:8px;height:8px;border-radius:50%;background:var(--ui-text-muted)}.ui-board__dot--success{background:var(--gemboss-success, #0a8f6a)}.ui-board__dot--warning{background:var(--gemboss-warning, #b25e09)}.ui-board__dot--critical{background:var(--gemboss-danger-strong, #c70a24)}.ui-board__dot--info{background:var(--gemboss-accent, #5661f5)}.ui-board__list{display:grid;gap:var(--ui-space-2);margin:0;padding:0;list-style:none}.ui-board__list>li{min-width:0}.ui-board__empty{margin:0;padding:var(--ui-space-4) var(--ui-space-2);color:var(--ui-text-muted);font-size:var(--ui-fs-body);text-align:center;border:1px dashed var(--ui-border);border-radius:var(--ui-radius-md)}.ui-board__more>summary{list-style:none;justify-self:center;margin:4px auto 0;width:fit-content}.ui-board__more>summary::-webkit-details-marker{display:none}.ui-board__more[open]>summary{display:none}.ui-board__more{display:grid;gap:var(--ui-space-2)}.ui-board__next.ui-more{padding:4px 0 0}.ui-board__next .ui-more__error{color:var(--gemboss-danger-strong, #c70a24)}.ui-board[data-gb-move] .ui-board__list>li[data-id]{position:relative;border-radius:var(--ui-radius-lg);cursor:grab}.ui-board[data-gb-move] .ui-board__list>li[data-id]:focus-visible{outline:2px solid var(--ui-focus);outline-offset:2px}.ui-board__list>li[data-gb-lifted]{outline:2px solid var(--ui-focus);outline-offset:2px;box-shadow:var(--gemboss-shadow-md, 0 4px 12px rgba(0,0,0,.12));border-radius:var(--ui-radius-lg)}.ui-board[data-gb-dragging] .ui-board__list>li[data-gb-lifted]{outline:0;opacity:.4}.ui-board__col[data-gb-over]{background:color-mix(in srgb,var(--ui-focus) 10%,var(--ui-coll-head-bg))}.ui-board__list>li[data-gb-drop]:before{content:"";position:absolute;left:0;right:0;height:2px;border-radius:1px;background:var(--ui-focus);pointer-events:none}.ui-board__list>li[data-gb-drop=before]:before{top:-5px}.ui-board__list>li[data-gb-drop=after]:before{bottom:-5px}.ui-empty--no-match{padding-block:32px}.ui-coll-error{display:flex;flex-wrap:wrap;align-items:center;gap:var(--ui-space-2) var(--ui-space-3);margin:var(--ui-space-3)}.ui-coll-error>:first-child{flex:1 1 240px;min-width:0}.ui-coll-count{margin-left:auto;color:var(--ui-text-muted);font-size:var(--ui-fs-body);font-variant-numeric:tabular-nums;white-space:nowrap}.ui-chip__x{margin-right:-4px;font-size:14px;line-height:1;opacity:.7}:is(.ui-table-wrap,.ui-index,.ui-list,.ui-cardgrid,.ui-board)[aria-busy=true]{position:relative}:is(.ui-table-wrap,.ui-index,.ui-list,.ui-cardgrid,.ui-board)[aria-busy=true]>:not(.ui-bulkbar,.ui-coll-busy){opacity:.55;pointer-events:none;transition:opacity .15s}.ui-coll-busy{position:absolute;top:8px;right:8px;z-index:4}:is(.ui-skeleton--table,.ui-skeleton--list,.ui-skeleton--compact,.ui-skeleton--grid,.ui-skeleton--board) .ui-skeleton__line{height:8px;border-radius:4px}.ui-skeleton--table td .ui-skeleton__line{width:70%;margin-block:6px}.ui-skeleton--table td:first-child .ui-skeleton__line{width:85%}.ui-skeleton--table tbody tr:hover{background:none}.ui-skeleton__block{display:block;flex:none;width:40px;height:40px;border-radius:var(--ui-radius-md);background:var(--ui-surface-2)}.ui-skeleton__block--round{border-radius:50%;width:32px;height:32px}.ui-skeleton--list>.ui-list__item{align-items:center}.ui-skeleton--list .ui-list__body{display:grid;gap:12px}.ui-skeleton--list .ui-list__body>.ui-skeleton__line:last-child{width:60%}.ui-skeleton--compact .ui-list__row{gap:12px}.ui-skeleton--compact .ui-list__row>.ui-skeleton__line{flex:1 1 auto;max-width:60%}.ui-skeleton--grid .ui-card__body{display:grid;gap:12px;justify-items:stretch}.ui-skeleton--grid .ui-card__body>.ui-skeleton__line:last-child{width:50%}.ui-skeleton--board .ui-board__list>li{height:72px;border-radius:var(--ui-radius-md);background:var(--ui-surface)}@media (pointer: coarse){.ui-table__sort{min-height:44px;margin-block:-12px}.ui-table__checkbox{min-width:44px;min-height:44px;margin:-12px 0}}@media (pointer: coarse),(max-width: 47.9975em){.ui-table__sort{min-width:44px}}@media (prefers-reduced-motion: reduce){.ui-table--sticky-first :is(th,td):first-child{animation:none}:is(.ui-table-wrap,.ui-index,.ui-list,.ui-cardgrid,.ui-board)[aria-busy=true]>*{transition:none}.ui-board{scroll-behavior:auto}}
1
+ :root{--ui-coll-head-bg: color-mix(in srgb, var(--ui-text, #1b1c1e) 3.5%, var(--ui-surface, #fff));--ui-coll-hover: color-mix(in srgb, var(--ui-text, #1b1c1e) 3.5%, var(--ui-surface, #fff));--ui-coll-selected: color-mix(in srgb, var(--ui-text, #1b1c1e) 6%, var(--ui-surface, #fff));--ui-coll-check-w: 40px}.ui-table-wrap.ui-table-wrap--flush{border:0;border-radius:0;box-shadow:none;background:transparent}.ui-table--sticky-first tr{background:var(--ui-surface)}.ui-table--sticky-first tbody tr:hover{background:var(--ui-surface-2)}.ui-table--sticky-first :is(th,td):first-child{position:sticky;left:0;z-index:1;background:inherit}@supports (animation-timeline: scroll()){.ui-table-wrap:has(>.ui-table--sticky-first){scroll-timeline:--ui-coll-x inline}.ui-table--sticky-first :is(th,td):first-child{animation:ui-coll-edge linear both;animation-timeline:--ui-coll-x;animation-range:0 24px}}@keyframes ui-coll-edge{0%{box-shadow:none}to{box-shadow:1px 0 0 var(--ui-border),6px 0 8px -6px #0000002e}}.ui-table--compact :is(td,tbody th){padding-block:6px}.ui-table--compact thead th{padding-block:6px}.ui-table__totals>tr{background:var(--ui-coll-head-bg)}.ui-table__totals>tr>:is(td,th){background:var(--ui-coll-head-bg);font-weight:650;color:var(--ui-text);border-top:1px solid var(--ui-border);border-bottom:0}.ui-table__footer{padding:8px 12px;background:var(--ui-coll-head-bg);border-top:1px solid var(--ui-border);color:var(--ui-text-muted);font-size:var(--ui-fs-body);text-align:center}.ui-table th.ui-table__rowhead{font-weight:450;color:var(--ui-text);text-align:left}.ui-table th.ui-table__rowhead:not(.is-num){white-space:normal;min-width:9.0625rem;overflow-wrap:anywhere}.ui-table th.ui-table__rowhead>a,.ui-table:where(:not(.ui-table--index)) tbody :is(td,th) li>a{display:inline-flex;align-items:center;min-height:24px}.ui-table:where(:not(.ui-table--index)) tbody :is(td,th){vertical-align:top}.ui-table:where(:not(.ui-table--index)) tbody :is(td>a,th.ui-table__rowhead>a,:is(td,th) li>a){margin-block:calc((1lh - 24px)/2)}.ui-table__sort{display:flex;width:max-content;max-width:100%;align-items:center;gap:4px;min-height:24px;margin-block:-2px;padding:0;border:0;background:none;color:inherit;font:inherit;text-align:inherit;text-decoration:none;cursor:pointer;white-space:nowrap}.ui-table__sort:hover{color:var(--ui-text)}.ui-table__sort:focus-visible{outline:2px solid var(--ui-focus);outline-offset:2px;border-radius:4px}.ui-table__sort:after{content:"";flex:none;width:16px;height:16px;background:currentColor;opacity:0;-webkit-mask:var(--ui-coll-arrow) center / 16px no-repeat;mask:var(--ui-coll-arrow) center / 16px no-repeat;--ui-coll-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M8 3.5v9M4.5 9 8 12.5 11.5 9' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E")}.ui-table__sort:is(:hover,:focus-visible):after{opacity:.45}th[aria-sort=ascending]>.ui-table__sort:after,th[aria-sort=descending]>.ui-table__sort:after{opacity:1}th[aria-sort=ascending]>.ui-table__sort:after{transform:rotate(180deg)}th[aria-sort=ascending]>.ui-table__sort,th[aria-sort=descending]>.ui-table__sort{color:var(--ui-text)}.ui-table .is-num>.ui-table__sort{flex-direction:row-reverse;margin-left:auto}.ui-trunc{display:block;max-width:var(--ui-trunc, 32ch);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ui-clamp-2{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2;overflow:hidden;white-space:normal;overflow-wrap:anywhere}.ui-index{position:relative;container:ui-index / inline-size;min-width:0}.ui-table--index{font-size:var(--ui-fs-body)}.ui-table--index tr{background:var(--ui-surface)}.ui-table.ui-table--index thead th{padding:8px 6px;background:var(--ui-coll-head-bg);color:var(--ui-text-muted);font-size:var(--ui-fs-caption);line-height:20px;font-weight:550;text-transform:none;letter-spacing:0}.ui-table.ui-table--index :is(td,tbody th){padding:6px;line-height:20px;white-space:nowrap;vertical-align:middle;border-bottom:0;border-top:1px solid var(--ui-border)}.ui-table.ui-table--index :is(th,td):where(:first-child){padding-left:var(--ui-space-3)}.ui-table.ui-table--index :is(th,td):where(:last-child){padding-right:var(--ui-space-3)}.ui-table--index tbody tr:hover{background:var(--ui-coll-hover)}.ui-table--index tbody tr:is(.is-selected,[aria-selected=true]){background:var(--ui-coll-selected)}.ui-table--index tbody tr:is([data-href],.is-linked){cursor:pointer}.ui-table--index tbody tr:has(.ui-table__title:focus-visible){outline:2px solid var(--ui-focus);outline-offset:-2px}.ui-table__title:focus-visible{outline:none}.ui-table__primary{min-width:0}.ui-table__primary-inner{display:flex;align-items:center;gap:var(--ui-space-3);min-width:0}.ui-table__primary-text{min-width:0}.ui-table__title{display:block;max-width:var(--ui-trunc, 40ch);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--ui-text);font-weight:650;text-decoration:none}a.ui-table__title:hover{text-decoration:underline}.ui-table--index .ui-table__title+.ui-sub,.ui-table--index .ui-sub{display:block;max-width:var(--ui-trunc, 40ch);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin-top:0;line-height:16px}.ui-table--index td>a.ui-table__title{display:block;min-height:0}.ui-table--index td>.ui-table__primary-inner>a.ui-table__title,.ui-table--index .ui-table__primary-text>a.ui-table__title{line-height:20px}.ui-table.ui-table--index .ui-table__check{width:var(--ui-coll-check-w);padding:6px 8px 6px 12px}.ui-table.ui-table--index thead .ui-table__check{padding:8px 8px 8px 12px}.ui-table__checkbox{display:flex;width:max-content;align-items:center;justify-content:center;min-width:24px;min-height:24px;margin:-2px 0;cursor:pointer}.ui-table__checkbox>input,.ui-list__check>input{width:16px;height:16px;margin:0;accent-color:var(--ui-accent);cursor:pointer}.ui-table__checkbox>input:focus-visible,.ui-list__check>input:focus-visible{outline:2px solid var(--ui-focus);outline-offset:2px}.ui-table--index :is(.ui-table__check,.ui-table__primary){position:sticky;z-index:1;background:inherit}.ui-table--index .ui-table__check,.ui-table--index .ui-table__primary{left:0}.ui-table--index:has(.ui-table__check) .ui-table__primary{left:var(--ui-coll-check-w)}.ui-table__actions{width:1%;text-align:right}.ui-table__actions>*{vertical-align:middle}.ui-row-actions{display:inline-flex;align-items:center;gap:var(--ui-space-2)}.ui-bulkbar{position:relative;z-index:3;display:flex;flex-wrap:wrap;align-items:center;gap:var(--ui-space-2);box-sizing:border-box;min-height:38px;margin-bottom:-38px;padding:4px 8px 4px 12px;background:var(--ui-surface);border:1px solid var(--ui-border);border-bottom-color:transparent;border-radius:var(--ui-radius-lg) var(--ui-radius-lg) 0 0;font-size:var(--ui-fs-body)}.ui-bulkbar[hidden]{display:none}.ui-bulkbar__count{flex:none;font-weight:550;font-variant-numeric:tabular-nums;white-space:nowrap}.ui-bulkbar__actions{display:inline-flex;flex-wrap:wrap;gap:var(--ui-space-2);margin-left:auto}.ui-bulkbar .ui-table__checkbox{margin-right:4px}.ui-bulkbar[data-fit=pending]{flex-wrap:nowrap}.ui-bulkbar[data-fit=pending]>.ui-bulkbar__actions{flex:0 1 auto;flex-wrap:nowrap;min-width:0;overflow:hidden}.ui-bulkbar__actions>.ui-bulkbar__more{flex:none}.ui-bulkbar__measure{position:absolute;top:0;left:0;display:inline-flex;gap:var(--ui-space-2);height:0;overflow:hidden;visibility:hidden;pointer-events:none;white-space:nowrap}.ui-bulkbar__measure>*{flex:none}.ui-index__sortbar{display:none}@container ui-index (max-width: 768px){.ui-table--index,.ui-table--index tbody{display:block;width:100%}.ui-table--index thead{display:none}.ui-table--index tbody tr{position:relative;display:flex;flex-wrap:wrap;align-items:baseline;gap:2px 12px;min-height:44px;box-sizing:border-box;padding:10px 12px;border-top:1px solid var(--ui-border)}.ui-table--index tbody tr:first-child{border-top:0}.ui-table--index tbody tr:has(>.ui-table__check){padding-left:48px}.ui-table.ui-table--index tbody :is(td,th){display:block;padding:0;border:0;position:static;background:none;white-space:nowrap}.ui-table--index tbody .ui-table__primary{flex:1 0 100%;white-space:normal}.ui-table--index tbody td:not(.ui-table__primary,.ui-table__check,.ui-table__actions){flex:none;max-width:100%;overflow:hidden;text-overflow:ellipsis;color:var(--ui-text-muted);font-size:var(--ui-fs-caption);line-height:18px}.ui-table--index tbody td[data-label]:not(.ui-table__primary):before{content:attr(data-label) " ";color:var(--ui-text-muted)}.ui-table--index tbody td:not(.ui-table__primary,.ui-table__check,.ui-table__actions) .ui-trunc{display:inline-block;vertical-align:bottom}.ui-table--index tbody td:not(.ui-table__primary,.ui-table__check,.ui-table__actions) .ui-sub{display:inline;margin-left:6px}.ui-table--index tbody td.is-num{text-align:left}.ui-table--index tbody td[data-condensed=hide]{display:none}.ui-table.ui-table--index tbody .ui-table__check{position:absolute;left:4px;top:4px;width:auto;padding:0}.ui-table.ui-table--index tbody .ui-table__actions{order:99;margin-left:auto;width:auto;padding:0;align-self:center}.ui-table--index .ui-table__checkbox{min-width:44px;min-height:44px;margin:0}.ui-table--index .ui-table__title,.ui-table--index .ui-sub,.ui-table--index .ui-table__title+.ui-sub{max-width:none}.ui-table--index tbody a.ui-table__title{position:relative;z-index:1;padding-block:2px;margin-block:-2px}.ui-index__sortbar{display:flex;flex-wrap:wrap;align-items:center;gap:var(--ui-space-2);margin:0 0 var(--ui-space-3);font-size:var(--ui-fs-caption);color:var(--ui-text-muted)}.ui-index .ui-bulkbar{margin-bottom:var(--ui-space-2);border-bottom-color:var(--ui-border);border-radius:var(--ui-radius-lg)}.ui-index .ui-table-wrap{overflow-x:visible}}.ui-list{container:ui-list / inline-size;margin:0;padding:0;list-style:none;background:var(--ui-surface);border:1px solid var(--ui-border);border-radius:var(--ui-radius-lg);box-shadow:var(--ui-card-shadow)}.ui-list--flush{border:0;border-radius:0;box-shadow:none;background:transparent}.ui-list__item{position:relative;display:flex;align-items:flex-start;gap:var(--ui-space-3);box-sizing:border-box;padding:var(--ui-space-3);min-height:44px;border-top:1px solid var(--ui-border)}.ui-list>.ui-list__item:first-child{border-top:0}.ui-list>.ui-list__item:first-child{border-top-left-radius:inherit;border-top-right-radius:inherit}.ui-list>.ui-list__item:last-child{border-bottom-left-radius:inherit;border-bottom-right-radius:inherit}.ui-list__item:has(>.ui-list__body>.ui-list__title[href]):hover{background:var(--ui-coll-hover)}.ui-list__item:is(.is-selected,[aria-selected=true]){background:var(--ui-coll-selected)}.ui-list__item:has(>.ui-list__body>.ui-list__title:focus-visible){outline:2px solid var(--ui-focus);outline-offset:-2px}.ui-list__media{flex:none;display:flex;align-items:center;min-height:40px}.ui-list__body{flex:1 1 auto;min-width:0}.ui-list__title{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--ui-text);font-size:var(--ui-fs-body);line-height:20px;font-weight:650;text-decoration:none}.ui-list__title[href]:after{content:"";position:absolute;inset:0;z-index:0}.ui-list__title:focus-visible{outline:none}.ui-list__sub{margin:0;color:var(--ui-text-muted);font-size:var(--ui-fs-body);line-height:20px;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2;overflow:hidden;overflow-wrap:anywhere}.ui-list__meta{margin:2px 0 0;color:var(--ui-text-muted);font-size:var(--ui-fs-caption);line-height:16px}.ui-list__badges{display:flex;flex-wrap:wrap;gap:4px;margin-top:4px}.ui-list__aside{flex:none;align-self:center;color:var(--ui-text);font-variant-numeric:tabular-nums;text-align:right}.ui-list__actions{flex:none;align-self:center;display:inline-flex;align-items:center;gap:var(--ui-space-2)}.ui-list__item :is(.ui-list__actions,.ui-list__aside a,.ui-list__body a:not(.ui-list__title),button,input,select,textarea,label,summary,details){position:relative;z-index:1}.ui-list__item>:is(.ui-list__actions,.ui-list__aside) a:not(.ui-btn){display:inline-flex;align-items:center;min-height:24px}@container ui-list (max-width: 400px){.ui-list:not(.ui-list--compact,.ui-skeleton--list)>.ui-list__item{display:grid;grid-template-columns:auto minmax(0,1fr) auto;grid-template-areas:"media body body" "media aside actions";gap:0;align-items:start}.ui-list:not(.ui-list--compact,.ui-skeleton--list)>.ui-list__item>.ui-list__media{grid-area:media;margin-inline-end:var(--ui-space-3)}.ui-list:not(.ui-list--compact,.ui-skeleton--list)>.ui-list__item>.ui-list__body{grid-area:body}.ui-list:not(.ui-list--compact,.ui-skeleton--list)>.ui-list__item>.ui-list__aside{grid-area:aside;justify-self:start;align-self:center;margin-top:4px;text-align:left}.ui-list:not(.ui-list--compact,.ui-skeleton--list)>.ui-list__item>.ui-list__actions{grid-area:actions;justify-self:end;align-self:center;margin:4px 0 0 var(--ui-space-3)}.ui-list:not(.ui-list--compact,.ui-skeleton--list)>.ui-list__item--disclosure>:is(.ui-list__aside,.ui-list__actions){margin-top:8px}.ui-list:not(.ui-list--compact,.ui-skeleton--list)>.ui-list__item:has(>.ui-list__body>.ui-list__title:only-child){grid-template-columns:auto minmax(0,1fr) auto auto;grid-template-areas:"media body aside actions";align-items:center}.ui-list:not(.ui-list--compact,.ui-skeleton--list)>.ui-list__item:has(>.ui-list__body>.ui-list__title:only-child)>:is(.ui-list__aside,.ui-list__actions){margin-top:0}.ui-list:not(.ui-list--compact,.ui-skeleton--list)>.ui-list__item:has(>.ui-list__body>.ui-list__title:only-child)>.ui-list__aside{margin-inline-start:var(--ui-space-3);text-align:right}.ui-list:not(.ui-list--compact,.ui-skeleton--list)>.ui-list__item>.ui-list__panel{grid-column:1 / -1}}.ui-list__item--disclosure{flex-wrap:wrap}.ui-list__toggle{display:block;flex:1 1 0;min-width:0;min-height:24px;margin:0;padding:0;border:0;border-radius:var(--ui-radius-sm, 4px);background:none;color:inherit;font:inherit;text-align:left;cursor:pointer}.ui-list__toggle:focus-visible{outline:2px solid var(--ui-focus);outline-offset:2px}.ui-list__toggle>.ui-list__meta{display:block}@media (hover: hover){.ui-list__item--disclosure:not(.is-open):has(>.ui-list__toggle:hover){background:var(--ui-coll-hover)}}.ui-list__chev{display:inline-block;width:16px;height:16px;margin:0 4px 0 -2px;vertical-align:-3px;background:var(--ui-text-muted);-webkit-mask:var(--ui-chev) center / 16px no-repeat;mask:var(--ui-chev) center / 16px no-repeat;transition:transform .15s;--ui-chev: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M6 4l4 4-4 4' fill='none' stroke='black' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E")}.ui-list__item--disclosure.is-open>.ui-list__toggle .ui-list__chev{transform:rotate(90deg)}@media (forced-colors: active){.ui-list__chev{forced-color-adjust:none;background:CanvasText}}.ui-list__panel{flex:1 0 100%;min-width:0;margin-top:var(--ui-space-2)}.ui-list__panel[hidden]{display:none}@media (pointer: coarse),(max-width: 47.9975em){.ui-list__toggle{min-height:44px}}@media (prefers-reduced-motion: reduce){.ui-list__chev{transition:none}}.ui-resource>.ui-bulkbar{margin-bottom:0;border-bottom-color:var(--ui-border)}.ui-resource>.ui-bulkbar:has(+.ui-list--flush){border-width:0 0 1px;border-radius:0}.ui-resource>.ui-list,.ui-resource>[aria-busy]>.ui-list{border-top:0;border-top-left-radius:0;border-top-right-radius:0}.ui-list__check{display:flex;flex:none;align-items:center;justify-content:center;min-width:24px;min-height:24px;cursor:pointer}.ui-list__check:not(:last-child){margin-inline-end:8px}@media (pointer: coarse),(max-width: 47.9975em){.ui-list__check{min-width:44px;min-height:44px;margin-block:-2px;margin-inline-start:-12px}.ui-list__check:not(:last-child){margin-inline-end:-2px}.ui-resource>.ui-bulkbar>.ui-table__checkbox{min-width:44px;min-height:44px;margin:-8px -8px -8px -12px}}.ui-thumb{display:block;flex:none;width:40px;height:40px;box-sizing:border-box;border:1px solid var(--ui-border);border-radius:var(--ui-radius-md);background:var(--ui-surface-2);overflow:hidden;object-fit:cover}.ui-thumb--xs{width:24px;height:24px;border-radius:var(--ui-radius-sm)}.ui-thumb--md{width:60px;height:60px}.ui-thumb--lg{width:80px;height:80px}.ui-thumb>img{display:block;width:100%;height:100%;object-fit:cover}.ui-list--compact>.ui-list__item{display:block;padding:0;min-height:0}.ui-list__row{display:flex;align-items:center;gap:var(--ui-space-2);box-sizing:border-box;width:100%;min-height:36px;padding:8px 12px;border:0;background:none;color:var(--ui-text);font:inherit;font-size:var(--ui-fs-body);line-height:20px;text-align:left;text-decoration:none;border-radius:inherit}:is(a,button).ui-list__row{cursor:pointer}:is(a,button).ui-list__row:hover{background:var(--ui-coll-hover)}:is(a,button).ui-list__row:focus-visible{outline:2px solid var(--ui-focus);outline-offset:-2px}.ui-list__row[aria-current=page],.ui-list__row.is-selected{background:var(--ui-coll-selected)}.ui-list__icon{flex:none;display:inline-flex;width:20px;height:20px;align-items:center;justify-content:center;color:var(--ui-text-muted)}.ui-list__icon>svg{width:16px;height:16px}.ui-list__label{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ui-list__row>.ui-list__meta{flex:none;margin:0;font-variant-numeric:tabular-nums}@media (pointer: coarse),(max-width: 47.9975em){.ui-list__row{min-height:44px}}.ui-list--activity>.ui-list__item{display:grid;grid-template-columns:20px minmax(0,1fr) auto;column-gap:var(--ui-space-2);align-items:start;padding:8px 12px;min-height:36px;border-top:0}.ui-list--activity>.ui-list__item:before{content:"";position:absolute;left:21.5px;top:0;bottom:0;width:1px;background:var(--ui-border)}.ui-list--activity>.ui-list__item:first-child:before{top:14px}.ui-list--activity>.ui-list__item:last-child:before{bottom:calc(100% - 14px)}.ui-list--activity>.ui-list__item:only-child:before{display:none}.ui-list__dot{position:relative;z-index:1;width:8px;height:8px;margin:6px 0 0 6px;border-radius:50%;background:var(--ui-text-muted);box-shadow:0 0 0 3px var(--ui-surface)}.ui-list__dot--success{background:var(--gemboss-success, #0a8f6a)}.ui-list__dot--warning{background:var(--gemboss-warning, #b25e09)}.ui-list__dot--critical{background:var(--gemboss-danger-strong, #c70a24)}.ui-list__dot--info{background:var(--gemboss-accent, #5661f5)}.ui-list--activity .ui-list__label{display:block;white-space:nowrap}.ui-list--activity a.ui-list__label{position:relative;color:var(--ui-text);text-decoration:none;padding-block:2px;margin-block:-2px}.ui-list--activity a.ui-list__label:hover{text-decoration:underline}.ui-list--activity a.ui-list__label:focus-visible{outline:2px solid var(--ui-focus);outline-offset:0;border-radius:4px}.ui-list--activity .ui-list__detail{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--ui-text-muted);font-size:var(--ui-fs-caption);line-height:16px}.ui-list--activity time,.ui-list--activity .ui-list__time{color:var(--ui-text-muted);font-size:var(--ui-fs-caption);line-height:20px;white-space:nowrap;font-variant-numeric:tabular-nums}.ui-list__content{margin-top:4px;color:var(--ui-text);font-size:var(--ui-fs-body);line-height:20px;overflow-wrap:anywhere}.ui-list__content>p{margin:0}.ui-list__content>p+p{margin-top:4px}.ui-list--wrap>.ui-list__item>*>:is(.ui-list__label,.ui-list__detail,.ui-list__title){white-space:normal;overflow:visible;text-overflow:clip;overflow-wrap:anywhere}.ui-list--wrap>.ui-list__item>.ui-list__row{align-items:flex-start}@media (pointer: coarse),(max-width: 47.9975em){.ui-list--wrap>.ui-list__item>.ui-list__row{padding-block:12px}}.ui-list--wrap>.ui-list__item>.ui-list__row>.ui-list__meta{line-height:20px}.ui-cardgrid{--ui-cardgrid-min: 240px;display:grid;grid-template-columns:repeat(auto-fill,minmax(min(var(--ui-cardgrid-min),100%),1fr));gap:var(--ui-space-4);margin:0;padding:0;list-style:none}.ui-cardgrid[data-min="200"]{--ui-cardgrid-min: 200px}.ui-cardgrid[data-min="320"]{--ui-cardgrid-min: 320px}.ui-cardgrid>*{min-width:0}.ui-board{display:grid;grid-auto-flow:column;grid-auto-columns:minmax(240px,1fr);gap:var(--ui-space-4);align-items:start;overflow-x:auto;overscroll-behavior-x:contain;scroll-snap-type:x mandatory;padding-bottom:4px}@media (max-width: 47.9975em){.ui-board{grid-auto-columns:78%}}.ui-board__col{display:flex;flex-direction:column;gap:var(--ui-space-2);min-width:0;padding:var(--ui-space-2);scroll-snap-align:start;background:var(--ui-coll-head-bg);border-radius:var(--ui-radius-lg)}.ui-board__head{display:flex;align-items:center;gap:var(--ui-space-2);min-height:28px;padding:0 4px;font-size:var(--ui-fs-body);font-weight:650}.ui-board__name{min-width:0;margin:0;font:inherit;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ui-board__count{margin-left:auto;color:var(--ui-text-muted);font-weight:450;font-variant-numeric:tabular-nums}.ui-board__dot{flex:none;width:8px;height:8px;border-radius:50%;background:var(--ui-text-muted)}.ui-board__dot--success{background:var(--gemboss-success, #0a8f6a)}.ui-board__dot--warning{background:var(--gemboss-warning, #b25e09)}.ui-board__dot--critical{background:var(--gemboss-danger-strong, #c70a24)}.ui-board__dot--info{background:var(--gemboss-accent, #5661f5)}.ui-board__list{display:grid;gap:var(--ui-space-2);margin:0;padding:0;list-style:none}.ui-board__list>li{min-width:0}.ui-board__empty{margin:0;padding:var(--ui-space-4) var(--ui-space-2);color:var(--ui-text-muted);font-size:var(--ui-fs-body);text-align:center;border:1px dashed var(--ui-border);border-radius:var(--ui-radius-md)}.ui-board__more>summary{list-style:none;justify-self:center;margin:4px auto 0;width:fit-content}.ui-board__more>summary::-webkit-details-marker{display:none}.ui-board__more[open]>summary{display:none}.ui-board__more{display:grid;gap:var(--ui-space-2)}.ui-board__next.ui-more{padding:4px 0 0}.ui-board__next .ui-more__error{color:var(--gemboss-danger-strong, #c70a24)}.ui-board[data-gb-move] .ui-board__list>li[data-id]{position:relative;border-radius:var(--ui-radius-lg);cursor:grab}.ui-board[data-gb-move] .ui-board__list>li[data-id]:focus-visible{outline:2px solid var(--ui-focus);outline-offset:2px}.ui-board__list>li[data-gb-lifted]{outline:2px solid var(--ui-focus);outline-offset:2px;box-shadow:var(--gemboss-shadow-raised);border-radius:var(--ui-radius-lg)}.ui-board[data-gb-dragging] .ui-board__list>li[data-gb-lifted]{outline:0;opacity:.4}.ui-board__col[data-gb-over]{background:color-mix(in srgb,var(--ui-focus) 10%,var(--ui-coll-head-bg))}.ui-board__list>li[data-gb-drop]:before{content:"";position:absolute;left:0;right:0;height:2px;border-radius:1px;background:var(--ui-focus);pointer-events:none}.ui-board__list>li[data-gb-drop=before]:before{top:-5px}.ui-board__list>li[data-gb-drop=after]:before{bottom:-5px}.ui-empty--no-match{padding-block:32px}.ui-coll-error{display:flex;flex-wrap:wrap;align-items:center;gap:var(--ui-space-2) var(--ui-space-3);margin:var(--ui-space-3)}.ui-coll-error>:first-child{flex:1 1 240px;min-width:0}.ui-coll-count{margin-left:auto;color:var(--ui-text-muted);font-size:var(--ui-fs-body);font-variant-numeric:tabular-nums;white-space:nowrap}.ui-chip__x{margin-right:-4px;font-size:14px;line-height:1;opacity:.7}:is(.ui-table-wrap,.ui-index,.ui-list,.ui-cardgrid,.ui-board)[aria-busy=true]{position:relative}:is(.ui-table-wrap,.ui-index,.ui-list,.ui-cardgrid,.ui-board)[aria-busy=true]>:not(.ui-bulkbar,.ui-coll-busy){opacity:.55;pointer-events:none;transition:opacity .15s}.ui-coll-busy{position:absolute;top:8px;right:8px;z-index:4}:is(.ui-skeleton--table,.ui-skeleton--list,.ui-skeleton--compact,.ui-skeleton--grid,.ui-skeleton--board) .ui-skeleton__line{height:8px;border-radius:4px}.ui-skeleton--table td .ui-skeleton__line{width:70%;margin-block:6px}.ui-skeleton--table td:first-child .ui-skeleton__line{width:85%}.ui-skeleton--table tbody tr:hover{background:none}.ui-skeleton__block{display:block;flex:none;width:40px;height:40px;border-radius:var(--ui-radius-md);background:var(--ui-surface-2)}.ui-skeleton__block--round{border-radius:50%;width:32px;height:32px}.ui-skeleton--list>.ui-list__item{align-items:center}.ui-skeleton--list .ui-list__body{display:grid;gap:12px}.ui-skeleton--list .ui-list__body>.ui-skeleton__line:last-child{width:60%}.ui-skeleton--compact .ui-list__row{gap:12px}.ui-skeleton--compact .ui-list__row>.ui-skeleton__line{flex:1 1 auto;max-width:60%}.ui-skeleton--grid .ui-card__body{display:grid;gap:12px;justify-items:stretch}.ui-skeleton--grid .ui-card__body>.ui-skeleton__line:last-child{width:50%}.ui-skeleton--board .ui-board__list>li{height:72px;border-radius:var(--ui-radius-md);background:var(--ui-surface)}@media (pointer: coarse){.ui-table__sort{min-height:44px;margin-block:-12px}.ui-table__checkbox{min-width:44px;min-height:44px;margin:-12px 0}}@media (pointer: coarse),(max-width: 47.9975em){.ui-table__sort{min-width:44px}}@media (prefers-reduced-motion: reduce){.ui-table--sticky-first :is(th,td):first-child{animation:none}:is(.ui-table-wrap,.ui-index,.ui-list,.ui-cardgrid,.ui-board)[aria-busy=true]>*{transition:none}.ui-board{scroll-behavior:auto}}
@@ -11,7 +11,7 @@
11
11
  // · the edge box hands each keystroke to the caller (`onChange(side, raw)`) and says when to commit (`onCommit`, on
12
12
  // blur): the caller decides what an empty edge means, and the admin has three answers to that on purpose.
13
13
  import "../editor.css"; // its own stylesheet travels with it (0.23.0): a surface that never renders it never loads it
14
- import { useEffect, useState } from "react";
14
+ import { useEffect, useRef, useState } from "react";
15
15
  import type React from "react";
16
16
  import { cssUrl } from "./css-url";
17
17
  import { swatchState } from "./swatch";
@@ -27,6 +27,8 @@ export interface SegOption<T extends string = string> {
27
27
  value: T;
28
28
  /** Default: the value itself. */
29
29
  label?: React.ReactNode;
30
+ /** The button's own name, for a label that is a glyph (an arrow), said by a screen reader and shown on hover. */
31
+ name?: string;
30
32
  }
31
33
 
32
34
  export interface SegProps<T extends string = string> {
@@ -49,7 +51,69 @@ export interface SegProps<T extends string = string> {
49
51
  export function Seg<T extends string = string>({ options, value, onChange, disabled, label, style }: SegProps<T>) {
50
52
  return (
51
53
  <Segmented<T> fill className="gemboss-ei-seg" style={style} ariaLabel={label ?? ""} value={(value ?? "") as T | ""} onChange={onChange} disabled={disabled}
52
- options={options.map((o) => ({ value: o.value, label: o.label ?? o.value }))} />
54
+ options={options.map((o) => ({ value: o.value, label: o.label ?? o.value, ...(o.name ? { ariaLabel: o.name, title: o.name } : {}) }))} />
55
+ );
56
+ }
57
+
58
+ // ── ValueControl ────────────────────────────────────────────────────────────────────────────────────────────────────
59
+
60
+ export interface ValueControlProps {
61
+ /** The number box's id (the Field's `htmlFor`). */
62
+ id?: string;
63
+ /** The field's name: the chips are announced as "<label> presets". */
64
+ label: string;
65
+ /** The named values, smallest first, each `value` as the box would hold it ("" = none). Shown as "name · number". */
66
+ presets: ReadonlyArray<{ value: string; label: string; title?: string }>;
67
+ /** What the box holds now: the stored value or the text being typed. */
68
+ text: string;
69
+ /** What an empty box follows (another screen's value, the theme's), greyed. */
70
+ placeholder?: string;
71
+ /** The unit after the box ("px", "%", "ms"). */
72
+ suffix?: string;
73
+ /** A slider under the box, for a bounded range of ≤ ~100 stops. `value` is where its thumb sits. */
74
+ slider?: { min: number; max: number; step?: number; value: number };
75
+ /** A chip: the caller saves it at once. */
76
+ onPreset: (value: string) => void;
77
+ /** Each key typed. */
78
+ onText: (raw: string) => void;
79
+ /** The box let go (blur, Enter). */
80
+ onCommit: () => void;
81
+ /** Each move of the slider. */
82
+ onSlide?: (value: number) => void;
83
+ /** Keys in the box (↑ ↓ nudges are the caller's). */
84
+ onKeyDown?: (e: React.KeyboardEvent<HTMLInputElement>) => void;
85
+ /** A line under it (e.g. why a typed value was not kept as typed). */
86
+ note?: string;
87
+ /** The keyboard a phone shows: "decimal" (default) has no minus key on iOS, so a value that goes below 0 asks for "text". */
88
+ inputMode?: "decimal" | "text";
89
+ disabled?: boolean;
90
+ }
91
+
92
+ /**
93
+ * `.gemboss-ei-value` (0.38.0): a setting you can click, drag or type (Chris 15/10/2026: "vừa bấm được vừa nhập được, lười thì
94
+ * bấm"). The named values first, as the kit's segmented control (one lights when the box holds it; a value of its own lights
95
+ * none), then the number box with its unit and, for a bounded range, a slider. The caller owns the value: it turns chips, keys
96
+ * and moves into saves.
97
+ */
98
+ export function ValueControl({ id, label, presets, text, placeholder, suffix, slider, onPreset, onText, onCommit, onSlide, onKeyDown, note, inputMode = "decimal", disabled }: ValueControlProps) {
99
+ const lit = presets.find((p) => p.value === text.trim())?.value;
100
+ return (
101
+ // A chip pressed right after typing keeps the box's focus: its blur would save what was typed, the save locks the field, and
102
+ // the chip's click landed on a disabled chip (the spacing box's own guard, review of slice 5). The chip is the choice.
103
+ <div className="gemboss-ei-value" onMouseDown={(e) => { if ((e.target as HTMLElement).closest('[role="group"] button')) e.preventDefault(); }}>
104
+ {presets.length ? <Seg label={`${label} presets`} value={lit} disabled={disabled} onChange={onPreset}
105
+ options={presets.map((p) => ({ value: p.value, label: p.label }))} /> : null}
106
+ <div className="gemboss-ei-value-row">
107
+ <span className="gemboss-ei-value-box">
108
+ <input id={id} className="gemboss-field gemboss-field--narrow gemboss-ei-inp" inputMode={inputMode} value={text} placeholder={placeholder}
109
+ disabled={disabled} aria-label={label} onChange={(e) => onText(e.target.value)} onBlur={onCommit}
110
+ onKeyDown={(e) => { onKeyDown?.(e); if (!e.defaultPrevented) blurOnEnter(e); }} />
111
+ {suffix ? <span className="gemboss-ei-suffix">{suffix}</span> : null}
112
+ </span>
113
+ {slider && onSlide ? <RangeControl min={slider.min} max={slider.max} step={slider.step} value={slider.value} disabled={disabled} onChange={onSlide} /> : null}
114
+ </div>
115
+ {note ? <p className="gemboss-ei-hint" role="status">{note}</p> : null}
116
+ </div>
53
117
  );
54
118
  }
55
119
 
@@ -132,11 +196,26 @@ export interface EdgeBoxProps {
132
196
  narrow?: boolean;
133
197
  /** Ids for the boxes, per side. */
134
198
  ids?: Partial<Record<EdgeSide, string>>;
199
+ /**
200
+ * A side's letter dragged sideways (Figma's and Webflow's scrub, 0.37.0): `dx`, the pixels moved since the press, and the keys
201
+ * held now, for the caller to turn into a value. A mouse or a pen only: a finger on the letter scrolls the panel as before, and
202
+ * the box takes the number (its 44px under a finger is the control there). Present, each letter is a 24px drag row.
203
+ */
204
+ onScrub?: (side: EdgeSide, dx: number, keys: { shiftKey: boolean; altKey: boolean }) => void;
205
+ /** The drag let go: `moved` when it changed anything (the caller saves once, one Undo step); not moved, it was a click. */
206
+ onScrubEnd?: (side: EdgeSide, moved: boolean) => void;
135
207
  }
136
208
 
137
209
  /** `.gemboss-ei-edgebox`: four px boxes, T · R · B · L, mono and centred. */
138
- export function EdgeBox({ label, values, placeholders, onChange, onCommit, disabled, narrow = true, ids }: EdgeBoxProps) {
210
+ export function EdgeBox({ label, values, placeholders, onChange, onCommit, disabled, narrow = true, ids, onScrub, onScrubEnd }: EdgeBoxProps) {
139
211
  const cls = narrow ? "gemboss-field gemboss-field--narrow gemboss-ei-inp" : "gemboss-field gemboss-ei-inp";
212
+ const drag = useRef<{ side: EdgeSide; id: number; x: number; moved: boolean } | null>(null);
213
+ const end = (e: React.PointerEvent<HTMLSpanElement>) => {
214
+ const d = drag.current;
215
+ if (!d || d.id !== e.pointerId) return;
216
+ drag.current = null;
217
+ onScrubEnd?.(d.side, d.moved);
218
+ };
140
219
  return (
141
220
  <div className="gemboss-ei-edgebox">
142
221
  {SIDES.map((s) => (
@@ -144,7 +223,29 @@ export function EdgeBox({ label, values, placeholders, onChange, onCommit, disab
144
223
  <input className={cls} inputMode="numeric" placeholder={placeholders?.[s] ?? "0"}
145
224
  aria-label={`${label} ${SIDE_NAME[s]}`} id={ids?.[s]} value={values[s] ?? ""} disabled={disabled}
146
225
  onChange={(e) => onChange(s, e.target.value)} onBlur={onCommit} onKeyDown={blurOnEnter} />
147
- <span>{s.toUpperCase()}</span>
226
+ {onScrub ? (
227
+ // Rendered while disabled too: a field that locks in the middle of a drag (another save landing) must not drop the
228
+ // drag's handlers, or it never ends and nothing is saved (review of 3a). A drag only refuses to START when disabled.
229
+ <span className="gemboss-ei-edge-scrub" title={`Drag to change ${SIDE_NAME[s]}`} aria-disabled={disabled || undefined}
230
+ onPointerDown={(e) => {
231
+ if (disabled || e.pointerType === "touch" || e.button !== 0) return;
232
+ e.preventDefault();
233
+ e.currentTarget.setPointerCapture(e.pointerId);
234
+ drag.current = { side: s, id: e.pointerId, x: e.clientX, moved: false };
235
+ }}
236
+ onPointerMove={(e) => {
237
+ const d = drag.current;
238
+ if (!d || d.id !== e.pointerId) return;
239
+ const dx = e.clientX - d.x;
240
+ // A press that wanders a pixel is still a click.
241
+ if (!d.moved && Math.abs(dx) < 2) return;
242
+ d.moved = true;
243
+ onScrub(s, dx, { shiftKey: e.shiftKey, altKey: e.altKey });
244
+ }}
245
+ onPointerUp={end} onPointerCancel={end}
246
+ // Its own capture only (the event bubbles from nothing here, but the check is the fleet's rule).
247
+ onLostPointerCapture={(e) => { if (e.target === e.currentTarget) end(e); }}>{s.toUpperCase()}</span>
248
+ ) : <span>{s.toUpperCase()}</span>}
148
249
  </div>
149
250
  ))}
150
251
  </div>
@@ -156,20 +156,24 @@ export function EditorBack({ as: Comp = "button", label = "Back", ...rest }:
156
156
 
157
157
  /**
158
158
  * The auto-save pill: "Saving…" with a spinner while an edit is in flight, "✓ Draft saved" once it lands.
159
- * `idle` draws nothing unless `idleText` says what autosave means here (the section editor's "Autosaves", dimmed).
159
+ * `idle` draws nothing unless `idleText` says what autosave means here (the section editor's "Autosaves", muted).
160
+ * `live` (default true): "Saving…" and "✓ Draft saved" are a polite live region. `live={false}` for a surface that speaks
161
+ * through a live region of its own, one that is in the page from its first render and says only what changed (the page
162
+ * editor's save pill): the pill is then words with a title, and nothing is announced twice.
160
163
  */
161
164
  export function EditorSaveState({
162
165
  state, savedText = "✓ Draft saved", savingText = "Saving…", savingTitle = "Saving draft…",
163
- savedTitle = "Every change is saved to the draft automatically", idleText,
166
+ savedTitle = "Every change is saved to the draft automatically", idleText, live = true,
164
167
  }: {
165
168
  state: "idle" | "saving" | "saved";
166
169
  savedText?: React.ReactNode; savingText?: React.ReactNode; savingTitle?: string; savedTitle?: string; idleText?: React.ReactNode;
170
+ live?: boolean;
167
171
  }) {
168
172
  if (state === "idle") {
169
- return idleText != null && idleText !== false ? <span className="gemboss-editor-savestate" title={savedTitle} style={{ opacity: 0.55 }}>{idleText}</span> : null;
173
+ return idleText != null && idleText !== false ? <span className="gemboss-editor-savestate is-idle" title={savedTitle}>{idleText}</span> : null;
170
174
  }
171
175
  return (
172
- <span className={`gemboss-editor-savestate is-${state}`} role="status" aria-live="polite" title={state === "saving" ? savingTitle : savedTitle}>
176
+ <span className={`gemboss-editor-savestate is-${state}`} {...(live ? { role: "status", "aria-live": "polite" as const } : null)} title={state === "saving" ? savingTitle : savedTitle}>
173
177
  {state === "saving" ? <><span className="gemboss-narr-spin" aria-hidden />{savingText}</> : savedText}
174
178
  </span>
175
179
  );
@@ -36,8 +36,8 @@ export {
36
36
  type FieldProps, type InspectorGroupProps, type PanelHeaderProps, type PanelTab, type PanelTabsProps,
37
37
  } from "./panel";
38
38
  export {
39
- ChipButton, ColorControl, EdgeBox, ImageControl, RangeControl, Seg,
40
- type ColorControlProps, type EdgeBoxProps, type EdgeSide, type ImageControlProps, type RangeControlProps, type SegOption, type SegProps,
39
+ ChipButton, ColorControl, EdgeBox, ImageControl, RangeControl, Seg, ValueControl,
40
+ type ColorControlProps, type EdgeBoxProps, type EdgeSide, type ImageControlProps, type RangeControlProps, type SegOption, type SegProps, type ValueControlProps,
41
41
  } from "./controls";
42
42
  export { swatchState, type SwatchState } from "./swatch";
43
43
  export { cssUrl } from "./css-url";
@@ -48,5 +48,9 @@ export {
48
48
  EditorDrawer, LayerList, layerName,
49
49
  type EditorDrawerProps, type LayerItem, type LayerListProps,
50
50
  } from "./layers";
51
- export { SortableLayerList, type SortableLayerListProps } from "./sortable";
51
+ export { SortableLayerList, type SortableLayerListProps, useRowDrag, dropIndex } from "./sortable";
52
+ // 16/10/2026: a setting that is a list, as rows (drag, duplicate, fold); its own CSS part, editor-repeater.css.
53
+ export { RepeaterList, useKeyedRows, type RepeaterListProps, type KeyedRows } from "./repeater";
54
+ // 16/10/2026: a closed choice of shapes (an image's ratio, a layout) as picture tiles; its own CSS part, editor-tiles.css.
55
+ export { ChoiceTiles, type ChoiceTile, type ChoiceTilesProps } from "./tiles";
52
56
  export { LayerTree, type LayerTreeProps, type LayerTreeRow } from "./tree";
@@ -5,7 +5,7 @@
5
5
  // InspectorGroup's own open/closed when the caller does not hold it. Controls (Seg, Color, Range, EdgeBox, Image) are
6
6
  // controls.tsx: their own module, because only a screen that edits values draws them.
7
7
  import "../editor.css"; // its own stylesheet travels with it (0.23.0): a surface that never renders it never loads it
8
- import { useState } from "react";
8
+ import { useId, useState } from "react";
9
9
  import type React from "react";
10
10
 
11
11
  // ── PanelTabs ───────────────────────────────────────────────────────────────────────────────────────────────────────
@@ -161,29 +161,53 @@ export function InspectorGroup({ title, note, open, defaultOpen = true, onOpenCh
161
161
  // ── Field ───────────────────────────────────────────────────────────────────────────────────────────────────────────
162
162
 
163
163
  export interface FieldProps {
164
- /** 13px / 500 above the control. `undefined` / `null` draws no label (a control named by its own aria-label). */
164
+ /** 13px above the control (beside it in a `row`). `undefined` / `null` draws no label (a control named by its own aria-label). */
165
165
  label?: React.ReactNode;
166
166
  /** The control's id, so a click on the label focuses it. */
167
167
  htmlFor?: string;
168
168
  /** A value shown at the label's right edge, bold and tabular (a range's current value: `.gemboss-ei-rangeval`). */
169
169
  labelValue?: React.ReactNode;
170
- /** A muted line under the control (`p.gemboss-ei-hint`). Put it in `children` instead to place it elsewhere. */
170
+ /** The setting's help (`p.gemboss-ei-hint.gemboss-ei-help-text`). In a plugin's form a line under the control; inside an
171
+ * inspector group (`InspectorGroup`) a ? beside the label opens and closes it (0.39.0). */
171
172
  hint?: React.ReactNode;
173
+ /** A one-value setting (a number, a select, a colour, chips): inside an inspector group the label goes LEFT and the control
174
+ * right, one row (0.39.0). Outside a group nothing changes. */
175
+ row?: boolean;
172
176
  /** Added to `.gemboss-ei-fld` (the admin's `togrow`). */
173
177
  className?: string;
174
178
  style?: React.CSSProperties;
175
179
  children?: React.ReactNode;
176
180
  }
177
181
 
178
- /** One labelled row of a panel: `div.gemboss-ei-fld` › label · control · hint. 12px under each row but the last. */
179
- export function Field({ label, htmlFor, labelValue, hint, className, style, children }: FieldProps) {
182
+ /**
183
+ * One labelled setting: `div.gemboss-ei-fld` › label · control · help. 12px under each but the last.
184
+ *
185
+ * INSIDE AN INSPECTOR GROUP (0.39.0, Chris 16/10/2026: the settings panel looked bigger than the kit and Polaris; research
186
+ * `_local/gemboss/research/inspector-density-2026-10-16.md`). The controls were Polaris-sized already (field 32, chips 28);
187
+ * the panel was long: a label line over every control (70px a setting) and help text under it, 22% of a countdown's panel.
188
+ * There a `row` is label left, control right (GemPages: 52px a setting), the label is quiet (bodyMd, secondary) and the help
189
+ * is behind a ? (GemPages, PageFly). Outside a group, a plugin's settings form, a help line under a wide field is the
190
+ * Polaris form and stays.
191
+ */
192
+ export function Field({ label, htmlFor, labelValue, hint, row = false, className, style, children }: FieldProps) {
193
+ const helpId = useId();
194
+ const [helpOpen, setHelpOpen] = useState(false);
195
+ const cls = ["gemboss-ei-fld", row && label != null ? "gemboss-ei-fld--row" : "", className].filter(Boolean).join(" ");
196
+ const labelNode = label != null ? (
197
+ <label htmlFor={htmlFor}>{label}{labelValue != null ? <span className="gemboss-ei-rangeval">{labelValue}</span> : null}</label>
198
+ ) : null;
180
199
  return (
181
- <div className={className ? `gemboss-ei-fld ${className}` : "gemboss-ei-fld"} style={style}>
182
- {label != null ? (
183
- <label htmlFor={htmlFor}>{label}{labelValue != null ? <span className="gemboss-ei-rangeval">{labelValue}</span> : null}</label>
184
- ) : null}
200
+ <div className={cls} style={style}>
201
+ {/* A ? is a button, so it sits BESIDE the label, not in it (a label may hold no other labelable element). */}
202
+ {hint && labelNode ? (
203
+ <div className="gemboss-ei-lbl">
204
+ {labelNode}
205
+ <button type="button" className="gemboss-ei-help" aria-label={typeof label === "string" ? `About ${label}` : "About this setting"} aria-describedby={helpId} aria-expanded={helpOpen}
206
+ onClick={() => setHelpOpen((o) => !o)} onKeyDown={(e) => { if (e.key === "Escape") setHelpOpen(false); }}>?</button>
207
+ </div>
208
+ ) : labelNode}
185
209
  {children}
186
- {hint ? <p className="gemboss-ei-hint">{hint}</p> : null}
210
+ {hint ? <p className="gemboss-ei-hint gemboss-ei-help-text" id={helpId}>{hint}</p> : null}
187
211
  </div>
188
212
  );
189
213
  }