anentrypoint-design 1.0.9 → 1.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -133,7 +133,8 @@ onMounted(() => {
133
133
  - **multi-agent chat shell** — `WorkspaceShell`, `WorkspaceRail`, `ConversationList`, `AgentChat`, `SessionDashboard` — the flagship desktop-class chat-agent product surface (persistent rail + resizable columns + full turn/tool-call thread + live multi-session dashboard). See `COMPONENT_API.md` for the full prop contract; a runnable mock-data demo lives at `ui_kits/workspace/`; the canonical real-world wiring ships at [`agentgui`](https://github.com/AnEntrypoint/agentgui).
134
134
  - **file browser** — `FileRow`, `FileGrid`, `FileToolbar`, `FileIcon`, `DropZone`, `UploadProgress`, `EmptyState`, `BreadcrumbPath`, plus modal pieces `FileViewer`, `FilePreviewMedia`, `FilePreviewCode`, `FilePreviewText`, `ConfirmDialog`, `PromptDialog`
135
135
  - **desktop-shell (os kit)** — `createDesktopShell`, `renderWindow`, `renderDock`, plus paint surfaces `renderAboutApp`, `renderBrowserPane`, `renderFilesApp`, `renderMonitorApp`, `renderTerminal`, `createFreddieDashboard` (`src/kits/os/`, package export `ds/kits/os/index.js`). Pure visual/DOM-rendering layer — window-manager state (z-order, focus stack, drag/resize math) and app lifecycle are owned by the consumer. A runnable demo (self-contained window manager + 2 apps) lives at `ui_kits/os/`; the canonical real-world wiring — the full multi-instance web OS (per-instance filesystem/worker/POSIX-shell, the complete app catalog) — ships at [`thebird`](https://github.com/AnEntrypoint/thebird), which vendors this kit via `scripts/refresh-design.mjs`.
136
- - **ui_kits** — 21 fully-working buildless examples loading the SDK from this repo: `homepage`, `project_page`, `docs`, `blog`, `chat`, `aicat`, `file_browser`, `dashboard`, `settings`, `search`, `terminal`, `gm_inspector`, `workspace`, `community`, `community-app`, `gallery`, `signin`, `error_404`, `slide_deck`, `system_primer`, `os`. (`_template` is the scaffold source, not a kit: it holds `index.html.tmpl` — a build input full of `{{VAR}}` placeholders — and deliberately serves no page.) Each kit's stylesheet `<link>` set is declared in `ui_kits/kits.config.mjs` and emitted by the scaffold generator (`npm run generate:ui-kits`) — never hand-edit a kit's generated `index.html`; `npm run lint:ui-kits` checks them against generated output.
136
+ - **ui_kits** — 22 fully-working buildless examples loading the SDK from this repo: `homepage`, `project_page`, `docs`, `blog`, `chat`, `aicat`, `file_browser`, `dashboard`, `settings`, `search`, `terminal`, `gm_inspector`, `workspace`, `community`, `community-app`, `gallery`, `signin`, `error_404`, `slide_deck`, `system_primer`, `os`, `component_explorer`. (`_template` is the scaffold source, not a kit: it holds `index.html.tmpl` — a build input full of `{{VAR}}` placeholders — and deliberately serves no page.) Each kit's stylesheet `<link>` set is declared in `ui_kits/kits.config.mjs` and emitted by the scaffold generator (`npm run generate:ui-kits`) — never hand-edit a kit's generated `index.html`; `npm run lint:ui-kits` checks them against generated output.
137
+ - **component explorer** — an interactive, searchable, buildless alternative to Storybook (`ui_kits/component_explorer/`): lists all 271 exported components, grouped by source file, with a real generated prop table per component and a live-mounted specimen for components already proven safe to render standalone (`Btn`, `Chip`, `Badge`, `Table`). Reads `manifest.json`, generated by `npm run manifest:components` from the same `extractComponentSurface()` model `docs/component-props.md` and `types/*.d.ts` already share — a CI gate (`npm run lint:component-manifest`) fails the build if it drifts from the real signatures.
137
138
 
138
139
  The file-browser surface (rails by file type, drop-zone upload, modal preview) ships its canonical real-world wiring at [`fsbrowse`](https://github.com/AnEntrypoint/fsbrowse) — Express + busboy backend, the SDK frontend.
139
140
 
package/dist/247420.css CHANGED
@@ -1200,7 +1200,23 @@
1200
1200
  .ds-247420 .app-topbar > .brand { flex: 0 0 auto; }
1201
1201
  .ds-247420 .app-topbar > .app-search { flex: 1 1 auto; }
1202
1202
  .ds-247420 .app-topbar > nav { margin-left: auto; }
1203
- .ds-247420 .app-topbar > .app-topbar-theme { flex: 0 0 auto; }
1203
+ /* Utility cluster grouping: the theme toggle sits after the repo-info nav
1204
+ links with no visual separation between the two groups, so the row read
1205
+ as one undifferentiated strip of controls. A thin inset rule plus extra
1206
+ left gap reads as "these are a distinct utility group", matching the
1207
+ subtle divider already used between .app-status segments. */
1208
+ .ds-247420 .app-topbar > .app-topbar-theme {
1209
+ flex: 0 0 auto;
1210
+ margin-left: var(--space-2);
1211
+ padding-left: var(--space-3);
1212
+ position: relative;
1213
+ }
1214
+ .ds-247420 .app-topbar > .app-topbar-theme::before {
1215
+ content: ''; position: absolute; left: 0; top: 50%;
1216
+ transform: translateY(-50%);
1217
+ width: 1px; height: 18px;
1218
+ background: var(--rule-strong);
1219
+ }
1204
1220
  .ds-247420 .app-topbar nav { display: flex; gap: var(--space-1); font-size: var(--fs-sm); flex-wrap: wrap; }
1205
1221
  .ds-247420 .app-topbar nav a { flex: 0 0 auto; }
1206
1222
  .ds-247420 .app-topbar nav a {
@@ -1291,6 +1307,15 @@
1291
1307
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
1292
1308
  min-width: 0; flex: 0 1 auto;
1293
1309
  }
1310
+ /* Ancestor trail segments previously had no rule of their own and simply
1311
+ inherited .app-crumb's base --fg-3 — the same tone the separators sit on
1312
+ top of (before their own 0.5 opacity dims them further). That leaves only
1313
+ two visually distinct tiers in practice (dim separator, bold leaf) rather
1314
+ than three, since the ancestor tone reads as "default text colour", not a
1315
+ deliberate middle step. --fg-3 is the crumb bar's OWN base, so explicitly
1316
+ restating it here is the anchor for the 3-tier read: separator (--fg-3 at
1317
+ 0.5 opacity, dimmest) < ancestor (--fg-3, mid) < leaf (--fg bold, brightest). */
1318
+ .ds-247420 .app-crumb > span:not(.sep):not(.leaf):not(.crumb-right) { color: var(--fg-3); }
1294
1319
  .ds-247420 .app-crumb .leaf { color: var(--fg); font-weight: 600; flex: 0 1 auto; }
1295
1320
  .ds-247420 .app-crumb .crumb-right { margin-left: auto; color: var(--fg-3); flex: 0 0 auto; }
1296
1321
 
@@ -1309,6 +1334,15 @@
1309
1334
  .ds-247420 .app-side-shell {
1310
1335
  background: var(--bg); overflow-y: auto; min-height: 0;
1311
1336
  scrollbar-width: thin; scrollbar-color: var(--rule-strong) transparent;
1337
+ /* Bottom-edge fade: a rail longer than the viewport otherwise shows only
1338
+ the thin scrollbar track as its sole "there is more below" cue. Mirrors
1339
+ the horizontal fade already used by .os-instances (src/kits/os/theme.css)
1340
+ for its own overflow edge, oriented top-to-bottom for this vertical
1341
+ scroller. The top edge stays fully opaque (rows start flush under the
1342
+ topbar with no need to hint upward scroll on initial load); only the
1343
+ trailing 24px softens toward transparent. */
1344
+ -webkit-mask-image: linear-gradient(to bottom, black calc(100% - 24px), transparent);
1345
+ mask-image: linear-gradient(to bottom, black calc(100% - 24px), transparent);
1312
1346
  }
1313
1347
  .ds-247420 .app-side-shell::-webkit-scrollbar { width: 8px; }
1314
1348
  .ds-247420 .app-side-shell::-webkit-scrollbar-thumb { background: var(--rule-strong); border-radius: var(--r-pill, 999px); }
@@ -1734,6 +1768,10 @@
1734
1768
  .ds-247420 .chip.tone-flame, .ds-247420 .chip.tone-error, .ds-247420 .chip.tone-miss {
1735
1769
  background: var(--flame); color: var(--on-color);
1736
1770
  }
1771
+ .ds-247420 .chip.tone-warn {
1772
+ background: color-mix(in oklab, var(--amber) 22%, var(--bg));
1773
+ color: var(--amber);
1774
+ }
1737
1775
  .ds-247420 .chip.tone-wip, .ds-247420 .chip.tone-neutral {
1738
1776
  background: var(--bg-3); color: var(--fg-2);
1739
1777
  }
@@ -2252,7 +2290,7 @@
2252
2290
  .ds-247420 .ds-hero-accent { color: var(--accent-ink); font-weight: 700; }
2253
2291
  .ds-247420 .ds-hero-actions {
2254
2292
  display: flex; gap: var(--space-2, 10px); flex-wrap: wrap;
2255
- justify-content: flex-start; margin-top: var(--space-hair, 4px);
2293
+ justify-content: flex-start; margin-top: var(--space-4);
2256
2294
  }
2257
2295
  /* Hero CTA labels are content-driven (e.g. "GitHub", proper nouns from
2258
2296
  home.yaml) and the site's voice is deliberately all-lowercase everywhere
@@ -2595,7 +2633,7 @@
2595
2633
  /* live is a distinct hue from a plain "on" dot — see .chip.tone-live's
2596
2634
  comment for the success-vs-live rationale. */
2597
2635
  .ds-247420 .ds-dot-live { color: var(--sky); }
2598
- .ds-247420 .ds-dot-live { color: var(--green-2); }
2636
+ .ds-247420 .ds-dot-warn { color: var(--amber); }
2599
2637
  .ds-247420 .ds-dot-idle { color: var(--fg-3); }
2600
2638
 
2601
2639
  /* ============================================================
@@ -2625,6 +2663,17 @@
2625
2663
  transform: translateY(-1px);
2626
2664
  box-shadow: var(--shadow-1, 0 2px 8px rgba(0,0,0,.12));
2627
2665
  }
2666
+ /* Number+caption stack, isolated from .kpi-foot below it. Previously the
2667
+ number and label were plain block children of .kpi-card with the label's
2668
+ own margin-top providing the gap — visually fine for a single card, but
2669
+ across a row of four the caption's WRAPPED height (one line vs two, e.g.
2670
+ "requests · 24h" vs "error rate · 5xx+4xx") pushed .kpi-foot down by a
2671
+ different amount per card, so the deltas/sparklines never lined up on one
2672
+ shared baseline. A dedicated flex column groups exactly the two elements
2673
+ that must stay glued together, independent of whatever sits below. */
2674
+ .ds-247420 .kpi-stack {
2675
+ display: flex; flex-direction: column; align-items: flex-start;
2676
+ }
2628
2677
  .ds-247420 .kpi-glyph {
2629
2678
  position: absolute;
2630
2679
  top: var(--space-2);
@@ -2711,14 +2760,36 @@
2711
2760
  padding: var(--space-5);
2712
2761
  background: var(--bg-2);
2713
2762
  border-radius: var(--r-3);
2714
- }
2763
+ /* Grid's default justify-items:stretch was silently stretching the submit
2764
+ * button (a direct grid child, same as every input) to the full column
2765
+ * width -- other primary buttons elsewhere (e.g. session-ui's "new
2766
+ * session") are inline/compact by contrast, since they're not grid
2767
+ * children. justify-self:start keeps inputs/textareas at their natural
2768
+ * grid-stretched width (a form field SHOULD fill its column) while the
2769
+ * submit button sizes to its own content, matching the compact convention
2770
+ * used everywhere else primary buttons appear. */
2771
+ }
2772
+ .ds-247420 .row-form > button[type="submit"] { justify-self: start; }
2715
2773
  .ds-247420 .row-form input,
2716
2774
  .ds-247420 .row-form textarea {
2717
2775
  font-family: inherit; font-size: var(--fs-sm);
2718
2776
  padding: 12px 16px;
2719
- background: var(--bg); color: var(--fg);
2777
+ /* --bg here previously resolved to the SAME color as .row-form's own
2778
+ * --bg-2 background in the dark theme, leaving only a 14%-opacity
2779
+ * currentColor ring (var(--rule)) as the sole edge between an input and
2780
+ * the panel behind it -- effectively invisible. --bg-3 (one step darker
2781
+ * than the panel) plus a stronger border restores a real, panel-distinct
2782
+ * field surface.
2783
+ * LOAD-BEARING !important: `.row-form input` and states-interactions.css's
2784
+ * bare `input[type="text"]:where(...)` rule are both (0,1,1) specificity
2785
+ * (the :where() wrapper there is intentionally zero-specificity) --
2786
+ * states-interactions.css @imports AFTER this file in app-shell.css, so on
2787
+ * this exact tie it wins by source order and silently discarded these two
2788
+ * declarations. Only !important beats that without restructuring the
2789
+ * shared bare-input rule's own selector, which many other consumers rely on. */
2790
+ background: var(--bg-3) !important; color: var(--fg);
2720
2791
  border: 0; border-radius: var(--r-2);
2721
- box-shadow: inset 0 0 0 1px var(--rule);
2792
+ box-shadow: inset 0 0 0 1px color-mix(in oklab, currentColor 28%, transparent) !important;
2722
2793
  }
2723
2794
  .ds-247420 .row-form input:focus-visible,
2724
2795
  .ds-247420 .row-form textarea:focus-visible { box-shadow: var(--focus-ring-inset); }
@@ -4426,6 +4497,24 @@
4426
4497
  .ds-247420 .chat-reactions .rxn .n { font-family: var(--ff-mono); font-weight: 600; font-size: var(--fs-nano); color: var(--fg-2); }
4427
4498
  .ds-247420 .chat-reactions .rxn.you .n { color: var(--accent-ink); }
4428
4499
 
4500
+ /* Typing indicator renders through the same .chat-bubble container as a real
4501
+ message, but must never read as a bubble holding actual content — no
4502
+ border, no hover-lift shadow, no tail-corner cut; just a pill-shaped
4503
+ borderless dot cluster, visually lighter than any card/bubble on the page. */
4504
+ /* Double-class selector (.chat-bubble.chat-bubble-typing) deliberately, not
4505
+ bare .chat-bubble-typing: chat.css (loaded after app-shell.css on every
4506
+ kit that links both) still carries a plain `.chat-bubble { background:
4507
+ var(--bg-2) }` rule at the same (0,1,0) specificity, and cascade order
4508
+ would let that later rule win over an equal-specificity selector here. */
4509
+ .ds-247420 .chat-bubble.chat-bubble-typing {
4510
+ background: transparent;
4511
+ padding: var(--space-2) var(--space-1);
4512
+ border-radius: var(--r-pill);
4513
+ }
4514
+ .ds-247420 .chat-msg:hover .chat-bubble.chat-bubble-typing { transform: none; box-shadow: none; }
4515
+ .ds-247420 .chat-msg:not(.you) .chat-bubble.chat-bubble-typing,
4516
+ .ds-247420 .chat-msg.you .chat-bubble.chat-bubble-typing { border-bottom-left-radius: var(--r-pill); border-bottom-right-radius: var(--r-pill); }
4517
+
4429
4518
  .ds-247420 .chat-typing { display: inline-flex; gap: var(--space-1); align-items: center; }
4430
4519
  .ds-247420 .chat-typing span {
4431
4520
  width: 8px; height: 8px; border-radius: 50%; background: var(--fg-3);
@@ -4740,6 +4829,21 @@
4740
4829
  Sidebar polish: hide zero-count badges; tonal active state;
4741
4830
  monospace count chips.
4742
4831
  ============================================================ */
4832
+ /* Rail row rhythm: the sidebar rows (bins/labels) previously packed at
4833
+ --space-hair (2px) margin-bottom while the main content column reads at
4834
+ the --space-5/--space-3 outer/inner rhythm (AGENTS.md "panel rhythm").
4835
+ Bumping the inter-row gap to --space-1-5 (5px) — still a tight, dense-app
4836
+ value, but enough that adjacent rows no longer read as glued together —
4837
+ and making it density-aware via [data-density] mirrors the existing
4838
+ compact-density override pattern in files.css (.ds-file-grid[data-density]).
4839
+ [data-density="compact"] keeps the old tighter feel for long rail lists;
4840
+ [data-density="spacious"] opens it further. */
4841
+ .ds-247420 .app-side a { margin-bottom: var(--space-1-5); }
4842
+ .ds-247420 .app-side[data-density="compact"] a,
4843
+ .ds-247420 .app-side-shell[data-density="compact"] .app-side a { margin-bottom: var(--space-hair); }
4844
+ .ds-247420 .app-side[data-density="spacious"] a,
4845
+ .ds-247420 .app-side-shell[data-density="spacious"] .app-side a { margin-bottom: var(--space-2); }
4846
+
4743
4847
  .ds-247420 .app-side .count {
4744
4848
  padding: 1px 8px; font-size: var(--fs-micro); font-weight: 700;
4745
4849
  font-family: var(--ff-mono); letter-spacing: 0.04em;
@@ -6351,6 +6455,19 @@
6351
6455
  .ds-247420 .ds-filter-pill.active { background: var(--accent-tint); color: var(--fg); border-color: var(--accent); }
6352
6456
  .ds-247420 .ds-filter-pill:focus-visible { outline: var(--focus-w) solid var(--focus-color); outline-offset: var(--focus-offset); }
6353
6457
 
6458
+ .ds-247420 .ds-filter-pill[class*="tone-"]::before {
6459
+ content: '';
6460
+ display: inline-block; width: 7px; height: 7px; border-radius: 50%;
6461
+ margin-right: var(--space-1);
6462
+ background: currentColor;
6463
+ }
6464
+ .ds-247420 .ds-filter-pill.tone-accent { color: var(--accent-ink); }
6465
+ .ds-247420 .ds-filter-pill.tone-warn { color: var(--amber); }
6466
+ .ds-247420 .ds-filter-pill.tone-live { color: var(--sky); }
6467
+ .ds-247420 .ds-filter-pill.tone-sun { color: var(--sun); }
6468
+ .ds-247420 .ds-filter-pill.tone-success { color: var(--green-deep); }
6469
+ .ds-247420 .ds-filter-pill.tone-dim { color: var(--fg-3); }
6470
+
6354
6471
  /* Touch floor for the new small controls. */
6355
6472
  @media (pointer: coarse) {
6356
6473
  .ds-247420 .row-act, .ds-247420 .ds-filter-pill { min-height: 44px; }
@@ -7131,6 +7248,14 @@
7131
7248
  justify-content: flex-end; gap: var(--space-2); flex-wrap: wrap;
7132
7249
  padding: calc(var(--space-2-75) * var(--density)) calc(var(--space-3) * var(--density));
7133
7250
  background: var(--panel-2); border-radius: var(--r-1);
7251
+ /* --panel-1 (this bar's parent .panel surface) and --panel-2 are adjacent
7252
+ lightness steps that measure only ~1.1-1.5:1 apart (both themes) -- too
7253
+ close to read as a distinct nesting depth by background tone alone.
7254
+ A hairline border is the same edge-definition device .panel itself
7255
+ already uses (see the top of this file) rather than a token-lightness
7256
+ change, which would risk the fg-3-on-panel-2 text contrast that is
7257
+ already right at its AA floor in the dark theme. */
7258
+ border: var(--bw-hair) solid var(--rule);
7134
7259
  margin: calc(var(--space-5) * var(--density)) 0 var(--space-2);
7135
7260
  box-shadow: var(--shadow-2, var(--shadow-1));
7136
7261
  }
@@ -7176,13 +7301,37 @@
7176
7301
  /* .ds-auth-field-label joins the kit small-label voice above, no overrides. */
7177
7302
  .ds-247420 .ds-auth-field-input-row { position: relative; display: flex; align-items: center; }
7178
7303
  /* Reserves room for the absolutely-positioned toggle: its --space-1 inset plus
7179
- the --ds-icon-btn-sm 26px box, so the input text never sits under it. */
7304
+ the --ds-icon-btn-sm 26px box, so the input text never sits under it. This
7305
+ only holds at the pointer:fine 26px box size, though -- the coarse-pointer
7306
+ touch-floor rule (states-interactions.css) grows .ds-icon-btn-sm to a
7307
+ min-width/height of 44px without this padding following it, so on a
7308
+ touchscreen the enlarged hit target actually overlapped 14px into the
7309
+ typed password text (44 + 4 inset > 34 reserved). Reserve for the coarse
7310
+ floor too, gated behind the same media query, so clearance holds at both
7311
+ sizes instead of only the desktop one. */
7180
7312
  .ds-247420 .ds-auth-field-input-row .input { flex: 1 1 auto; padding-right: calc(26px + var(--space-2)); }
7313
+ @media (pointer: coarse) {
7314
+ .ds-247420 .ds-auth-field-input-row .input { padding-right: calc(44px + var(--space-2)); }
7315
+ }
7181
7316
  .ds-247420 .ds-auth-pw-toggle { position: absolute; right: var(--space-1); }
7182
7317
  .ds-247420 .ds-auth-row-between { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); flex-wrap: wrap; }
7183
7318
  .ds-247420 .ds-auth-remember { display: flex; align-items: center; gap: var(--space-1-75); cursor: pointer; }
7319
+ /* The native checkbox is already re-tinted site-wide via `accent-color:
7320
+ var(--accent-ink)` in states-interactions.css (that rule's own comment
7321
+ names this exact control) -- reused here rather than hand-drawing a new
7322
+ checkbox component. What that global rule doesn't cover is size: the UA
7323
+ default box renders at ~13px, which is under the 24px comfortable-tap
7324
+ floor other controls in this row (the link text, the input fields) sit
7325
+ above. Sized up on the existing --space-2-5 token, no new primitive. */
7326
+ .ds-247420 .ds-auth-remember input[type="checkbox"] { width: var(--space-2-5); height: var(--space-2-5); margin: 0; }
7184
7327
  .ds-247420 .ds-auth-remember-text { color: var(--panel-text-2); font-size: var(--fs-tiny); }
7185
- .ds-247420 .ds-auth-forgot { font-size: var(--fs-tiny); }
7328
+ /* --accent-ink, not --accent, per the design system's text-vs-fill split
7329
+ (AGENTS.md): --accent is a background/border-color lead only, --accent-ink
7330
+ is the tone actually verified for text contrast. The link was previously
7331
+ unstyled prose color at --fs-tiny, reading as inert grey next to the
7332
+ checkbox label it shares a row with. */
7333
+ .ds-247420 .ds-auth-forgot { font-size: var(--fs-tiny); color: var(--accent-ink); font-weight: 500; }
7334
+ .ds-247420 .ds-auth-forgot:hover { text-decoration: underline; }
7186
7335
  /* Error and status share layout but not color: a color-only distinction
7187
7336
  between role="alert" (something is wrong) and role="status" (informational)
7188
7337
  fails WCAG 1.4.1, so each also carries a distinct ASCII marker via ::before —
@@ -7192,6 +7341,28 @@
7192
7341
  .ds-247420 .ds-auth-error::before { content: '[!]'; flex: none; }
7193
7342
  .ds-247420 .ds-auth-status { color: var(--panel-text-2); }
7194
7343
  .ds-247420 .ds-auth-status::before { content: '[i]'; flex: none; }
7344
+ /* The shared Divider() label defaults to --fs-tiny/--panel-text-3 (editor-
7345
+ primitives.css), tuned for a dense editor toolbar rule -- inside the auth
7346
+ form it sat at the same weight as fine print two rows below it and read
7347
+ as barely-there rather than a section break between the password form and
7348
+ the OAuth row. Scoped to this form only (never edit the shared component
7349
+ sheet for one consumer): borrows the kit small-label voice above (mono,
7350
+ --fs-nano, --tr-label, uppercase) at --panel-text-2 instead of the
7351
+ dimmer -3 tier, plus the ::before/::after rule lines pushed to full
7352
+ --panel-text opacity so the break itself, not just the label, is visible. */
7353
+ .ds-247420 .ds-auth-form .ds-ep-divider-labeled { margin: var(--space-1) 0; }
7354
+ .ds-247420 .ds-auth-form .ds-ep-divider-labeled::before,
7355
+ .ds-247420 .ds-auth-form .ds-ep-divider-labeled::after {
7356
+ border-top-color: var(--panel-text-3);
7357
+ }
7358
+ .ds-247420 .ds-auth-form .ds-ep-divider-label {
7359
+ font-family: var(--ff-mono);
7360
+ font-size: var(--fs-nano);
7361
+ font-weight: 600;
7362
+ letter-spacing: var(--tr-label);
7363
+ text-transform: uppercase;
7364
+ color: var(--panel-text-2);
7365
+ }
7195
7366
  .ds-247420 .ds-auth-providers { display: flex; gap: var(--space-2); flex-wrap: wrap; }
7196
7367
  .ds-247420 .ds-auth-provider-btn { flex: 1 1 100px; min-width: 0; display: flex; align-items: center; justify-content: center; gap: var(--space-2); padding: var(--space-2-5); }
7197
7368
  .ds-247420 .ds-auth-provider-btn--loading { opacity: 0.7; pointer-events: none; }