@gemboss/ui 0.7.1 → 0.7.2

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
@@ -390,7 +390,7 @@ import { Avatar, Dialog, Leaderboard, Podium, SearchDialog, ThemeToggle, themeSc
390
390
  - `Dialog`: the kit's native `<dialog class="ui-modal">` (see kit-plain.css) driven by `open`; a
391
391
  backdrop click closes it, focus returns to the opener.
392
392
  - `ThemeToggle` + `themeScript`: `data-theme="dark|light"` on <html>, remembered in localStorage
393
- (`gemboss-theme`), the OS's choice until then. `portal.css` redefines every `--gemboss-*` colour under
393
+ (`gemboss-theme`), the OS's choice until then. `theme-dark.css` (in `gemboss-ui.css`) redefines every `--gemboss-*` colour under
394
394
  `[data-theme="dark"]` (a test fails if a colour token is left out), so every kit class follows.
395
395
  Opt-in: a surface without it (the admin) stays light.
396
396
  - `Avatar` (24 · 32 · 40 · 56): picture or initials on one of eight tones picked from the name.
@@ -398,6 +398,16 @@ import { Avatar, Dialog, Leaderboard, Podium, SearchDialog, ThemeToggle, themeSc
398
398
  all when empty. `Podium`: the first three, second · first · third.
399
399
  - `initialsOf` moved to `initials.ts` (plain, not "use client") so server components can call it; it is
400
400
  still exported from the package and from account.tsx.
401
+ - **Without the whole kit (0.7.2):** a surface with its own skin (GemCommunity) takes only these pieces'
402
+ CSS: `@gemboss/ui/gemboss-tokens.css` (variables only, no rule) + `@gemboss/ui/portal.css`. `Avatar`,
403
+ `Leaderboard` and `Podium` read nothing but `--gemboss-*` tokens (a test holds that), so they look the
404
+ same as on GemFeedback without `gemboss-ui.css` restyling the rest of the page. `SearchDialog` and
405
+ `Dialog` still need `ui.css` (the modal). `portal.css` holds no rule on `:root`, `html` or `body`; the dark palette is its own file,
406
+ `theme-dark.css`, so a surface that uses `data-theme` for something else (GemCommunity's sign-in pages) is not
407
+ turned dark by importing the leaderboard.
408
+ - Rows take `current` (the viewer's own row: tinted, and read as "Minh, you" via `currentLabel`), `badge`
409
+ (after the name, e.g. a level) and `id` (a `#me` anchor). `title` may be left out on a page whose own
410
+ `<h1>` names the board; pass `label` then. Screen-reader text uses `.gb-sr-only`, styled in portal.css.
401
411
 
402
412
  ## Report pages (0.4.0)
403
413
 
@@ -27,7 +27,7 @@ body{margin:0;background:var(--gemboss-app-bg,#f1f1f1);color:var(--gemboss-text)
27
27
  @media (max-width:760px){.cat{grid-template-columns:1fr;padding:16px}.cat-nav{position:static;flex-direction:row;flex-wrap:wrap}}
28
28
  </style></head><body>
29
29
  <div class="cat"><nav class="cat-nav" aria-label="Mục"><a href="#tokens">Token</a><a href="#buttons">Nút</a><a href="#fields">Ô nhập</a><a href="#choice">Tab, nhóm nút, thẻ</a><a href="#surfaces">Thẻ, số liệu, bảng, trạng thái trống</a><a href="#report">Báo cáo</a><a href="#resizer">Thanh kéo giữa hai cột</a><a href="#modal">Hộp thoại, toast, menu (JS thuần)</a><a href="#shell">Khung app</a><a href="#portal">Cổng công khai: tab trên topbar, tìm kiếm, sáng / tối, người dẫn đầu</a><a href="#auth">Đăng nhập</a><a href="#chat">Thân chat</a><a href="#assistant">Trợ lý: cột phiên</a><a href="#icons">Icon</a></nav>
30
- <main><header class="cat-head"><h1>@gemboss/ui 0.7.1</h1><p>Ngôn ngữ thiết kế chung của các công cụ GemBoss. Markup dưới mỗi ví dụ là đúng thứ package render ra; bề mặt không dùng React (HTML tĩnh, Python) chép markup này và nạp <code>gemboss-ui.css</code>. Dựng từ gemboss <code>fef56e0d93ce</code>.</p></header>
30
+ <main><header class="cat-head"><h1>@gemboss/ui 0.7.2</h1><p>Ngôn ngữ thiết kế chung của các công cụ GemBoss. Markup dưới mỗi ví dụ là đúng thứ package render ra; bề mặt không dùng React (HTML tĩnh, Python) chép markup này và nạp <code>gemboss-ui.css</code>. Dựng từ gemboss <code>e66ca212d292</code>.</p></header>
31
31
  <section id="tokens"><h2>Token</h2><p>Đổi giao diện một bề mặt bằng cách đặt lại token, không viết đè class. Tên và giá trị đọc thẳng từ gemboss-ui.css.</p><div class="cat-swatches"><div class="cat-swatch"><i style="background:var(--gemboss-primary)"></i><code>--gemboss-primary</code><span>#1b1c1e</span></div><div class="cat-swatch"><i style="background:var(--gemboss-primary-dark)"></i><code>--gemboss-primary-dark</code><span>#000000</span></div><div class="cat-swatch"><i style="background:var(--gemboss-primary-soft)"></i><code>--gemboss-primary-soft</code><span>#f2f3f5</span></div><div class="cat-swatch"><i style="background:var(--gemboss-accent)"></i><code>--gemboss-accent</code><span>#5661f5</span></div><div class="cat-swatch"><i style="background:var(--gemboss-accent-strong)"></i><code>--gemboss-accent-strong</code><span>#3a44de</span></div><div class="cat-swatch"><i style="background:var(--gemboss-accent-soft)"></i><code>--gemboss-accent-soft</code><span>#eef0fe</span></div><div class="cat-swatch"><i style="background:var(--gemboss-text-strong)"></i><code>--gemboss-text-strong</code><span>#1b1c1e</span></div><div class="cat-swatch"><i style="background:var(--gemboss-text)"></i><code>--gemboss-text</code><span>#1b1c1e</span></div><div class="cat-swatch"><i style="background:var(--gemboss-text-muted)"></i><code>--gemboss-text-muted</code><span>#686b71</span></div><div class="cat-swatch"><i style="background:var(--gemboss-surface)"></i><code>--gemboss-surface</code><span>#ffffff</span></div><div class="cat-swatch"><i style="background:var(--gemboss-canvas)"></i><code>--gemboss-canvas</code><span>#ffffff</span></div><div class="cat-swatch"><i style="background:var(--gemboss-preview-canvas)"></i><code>--gemboss-preview-canvas</code><span>#eceef1</span></div><div class="cat-swatch"><i style="background:var(--gemboss-rail-bg)"></i><code>--gemboss-rail-bg</code><span>#ffffff</span></div><div class="cat-swatch"><i style="background:var(--gemboss-panel-bg)"></i><code>--gemboss-panel-bg</code><span>#ffffff</span></div><div class="cat-swatch"><i style="background:var(--gemboss-divider)"></i><code>--gemboss-divider</code><span>#e5e7ea</span></div><div class="cat-swatch"><i style="background:var(--gemboss-divider-soft)"></i><code>--gemboss-divider-soft</code><span>#edeff2</span></div><div class="cat-swatch"><i style="background:var(--gemboss-hover)"></i><code>--gemboss-hover</code><span>#eceef2</span></div><div class="cat-swatch"><i style="background:var(--gemboss-active-bg)"></i><code>--gemboss-active-bg</code><span>#f0f1f4</span></div><div class="cat-swatch"><i style="background:var(--gemboss-active-fg)"></i><code>--gemboss-active-fg</code><span>#1b1c1e</span></div><div class="cat-swatch"><i style="background:var(--gemboss-danger)"></i><code>--gemboss-danger</code><span>#d72c0d</span></div><div class="cat-swatch"><i style="background:var(--gemboss-danger-strong)"></i><code>--gemboss-danger-strong</code><span>#b42318</span></div><div class="cat-swatch"><i style="background:var(--gemboss-danger-soft)"></i><code>--gemboss-danger-soft</code><span>#fff0e9</span></div><div class="cat-swatch"><i style="background:var(--gemboss-danger-border)"></i><code>--gemboss-danger-border</code><span>#f5c9bc</span></div><div class="cat-swatch"><i style="background:var(--gemboss-success)"></i><code>--gemboss-success</code><span>#007f5f</span></div><div class="cat-swatch"><i style="background:var(--gemboss-success-strong)"></i><code>--gemboss-success-strong</code><span>#0a6a4c</span></div><div class="cat-swatch"><i style="background:var(--gemboss-success-soft)"></i><code>--gemboss-success-soft</code><span>#e3f1df</span></div><div class="cat-swatch"><i style="background:var(--gemboss-success-border)"></i><code>--gemboss-success-border</code><span>#b7dfcd</span></div><div class="cat-swatch"><i style="background:var(--gemboss-warning)"></i><code>--gemboss-warning</code><span>#9a6700</span></div><div class="cat-swatch"><i style="background:var(--gemboss-warning-soft)"></i><code>--gemboss-warning-soft</code><span>#fff8e0</span></div><div class="cat-swatch"><i style="background:var(--gemboss-warning-border)"></i><code>--gemboss-warning-border</code><span>#f5d569</span></div><div class="cat-swatch"><i style="background:var(--gemboss-dark-bg)"></i><code>--gemboss-dark-bg</code><span>#0a0a0c</span></div><div class="cat-swatch"><i style="background:var(--gemboss-dark-rail)"></i><code>--gemboss-dark-rail</code><span>#0e0e11</span></div><div class="cat-swatch"><i style="background:var(--gemboss-dark-surface)"></i><code>--gemboss-dark-surface</code><span>#16161a</span></div><div class="cat-swatch"><i style="background:var(--gemboss-dark-surface-2)"></i><code>--gemboss-dark-surface-2</code><span>#1e1e24</span></div><div class="cat-swatch"><i style="background:var(--gemboss-dark-divider)"></i><code>--gemboss-dark-divider</code><span>#2a2a31</span></div><div class="cat-swatch"><i style="background:var(--gemboss-dark-text)"></i><code>--gemboss-dark-text</code><span>#ededf0</span></div><div class="cat-swatch"><i style="background:var(--gemboss-dark-muted)"></i><code>--gemboss-dark-muted</code><span>#9a9aa4</span></div><div class="cat-swatch"><i style="background:var(--gemboss-field-bg)"></i><code>--gemboss-field-bg</code><span>#fdfdfd</span></div><div class="cat-swatch"><i style="background:var(--gemboss-field-bg-hover)"></i><code>--gemboss-field-bg-hover</code><span>#fafafa</span></div><div class="cat-swatch"><i style="background:var(--gemboss-field-ink)"></i><code>--gemboss-field-ink</code><span>#303030</span></div><div class="cat-swatch"><i style="background:var(--gemboss-field-placeholder)"></i><code>--gemboss-field-placeholder</code><span>#616161</span></div><div class="cat-swatch"><i style="background:var(--gemboss-field-line)"></i><code>--gemboss-field-line</code><span>#8a8a8a</span></div><div class="cat-swatch"><i style="background:var(--gemboss-field-line-hover)"></i><code>--gemboss-field-line-hover</code><span>#616161</span></div><div class="cat-swatch"><i style="background:var(--gemboss-field-line-active)"></i><code>--gemboss-field-line-active</code><span>#1a1a1a</span></div><div class="cat-swatch"><i style="background:var(--gemboss-chip-ink)"></i><code>--gemboss-chip-ink</code><span>#303633</span></div><div class="cat-swatch"><i style="background:var(--gemboss-chip-line)"></i><code>--gemboss-chip-line</code><span>#cfd6ce</span></div><div class="cat-swatch"><i style="background:var(--gemboss-chip-line-hover)"></i><code>--gemboss-chip-line-hover</code><span>#aab4ad</span></div><div class="cat-swatch"><i style="background:var(--gemboss-chip-bg-hover)"></i><code>--gemboss-chip-bg-hover</code><span>#f6f7f5</span></div><div class="cat-swatch"><i style="background:var(--gemboss-on-primary)"></i><code>--gemboss-on-primary</code><span>#ffffff</span></div><div class="cat-swatch"><i style="background:var(--gemboss-app-bg)"></i><code>--gemboss-app-bg</code><span>#ffffff</span></div></div><table class="ui-table cat-scale"><thead><tr><th>Token</th><th>Giá trị</th><th>Mẫu</th></tr></thead><tbody><tr><td><code>--gemboss-fs-micro</code></td><td>11px</td><td style="font-size:var(--gemboss-fs-micro)">Ngôn ngữ thiết kế chung</td></tr><tr><td><code>--gemboss-fs-caption</code></td><td>12px</td><td style="font-size:var(--gemboss-fs-caption)">Ngôn ngữ thiết kế chung</td></tr><tr><td><code>--gemboss-fs-body</code></td><td>14px</td><td style="font-size:var(--gemboss-fs-body)">Ngôn ngữ thiết kế chung</td></tr><tr><td><code>--gemboss-fs-body-lg</code></td><td>16px</td><td style="font-size:var(--gemboss-fs-body-lg)">Ngôn ngữ thiết kế chung</td></tr><tr><td><code>--gemboss-fs-h3</code></td><td>16px</td><td style="font-size:var(--gemboss-fs-h3)">Ngôn ngữ thiết kế chung</td></tr><tr><td><code>--gemboss-fs-h2</code></td><td>20px</td><td style="font-size:var(--gemboss-fs-h2)">Ngôn ngữ thiết kế chung</td></tr><tr><td><code>--gemboss-fs-h1</code></td><td>24px</td><td style="font-size:var(--gemboss-fs-h1)">Ngôn ngữ thiết kế chung</td></tr><tr><td><code>--gemboss-fs-display</code></td><td>30px</td><td style="font-size:var(--gemboss-fs-display)">Ngôn ngữ thiết kế chung</td></tr><tr><td><code>--gemboss-radius-xs</code></td><td>4px</td><td><i class="cat-radius" style="border-radius:var(--gemboss-radius-xs)"></i></td></tr><tr><td><code>--gemboss-radius-sm</code></td><td>6px</td><td><i class="cat-radius" style="border-radius:var(--gemboss-radius-sm)"></i></td></tr><tr><td><code>--gemboss-radius-md</code></td><td>8px</td><td><i class="cat-radius" style="border-radius:var(--gemboss-radius-md)"></i></td></tr><tr><td><code>--gemboss-radius-lg</code></td><td>12px</td><td><i class="cat-radius" style="border-radius:var(--gemboss-radius-lg)"></i></td></tr><tr><td><code>--gemboss-radius-xl</code></td><td>16px</td><td><i class="cat-radius" style="border-radius:var(--gemboss-radius-xl)"></i></td></tr><tr><td><code>--gemboss-radius-2xl</code></td><td>20px</td><td><i class="cat-radius" style="border-radius:var(--gemboss-radius-2xl)"></i></td></tr><tr><td><code>--gemboss-radius-full</code></td><td>999px</td><td><i class="cat-radius" style="border-radius:var(--gemboss-radius-full)"></i></td></tr><tr><td><code>--gemboss-shadow-resting</code></td><td class="cat-small">0 1px 2px rgba(31, 30, 29, 0.04), 0 2px 6px rgba(31, 30, 29, 0.06)</td><td><i class="cat-radius" style="box-shadow:var(--gemboss-shadow-resting);border:0"></i></td></tr><tr><td><code>--gemboss-shadow-raised</code></td><td class="cat-small">0 4px 16px rgba(31, 30, 29, 0.10)</td><td><i class="cat-radius" style="box-shadow:var(--gemboss-shadow-raised);border:0"></i></td></tr><tr><td><code>--gemboss-shadow-overlay</code></td><td class="cat-small">0 16px 48px rgba(31, 30, 29, 0.18)</td><td><i class="cat-radius" style="box-shadow:var(--gemboss-shadow-overlay);border:0"></i></td></tr></tbody></table></section>
32
32
  <section id="buttons"><h2>Nút</h2><p>Một lớp <code>ui-btn</code>, ba biến thể, tông đỏ, một cỡ nhỏ. Cao 32px dưới chuột (bằng ô nhập và ô chọn), 44px dưới ngón tay và ở khổ điện thoại, cỡ nhỏ cũng vậy. Dùng được trên <code>&lt;button&gt;</code> lẫn <code>&lt;a&gt;</code> (căn giữa sẵn).</p><figure class="cat-demo"><figcaption>Mặc định · chính · ghost · nhỏ · tắt</figcaption><div class="cat-live"><div class="cat-row"><button type="button" class="ui-btn">Lưu nháp</button><button type="button" class="ui-btn ui-btn--primary">Xuất bản</button><button type="button" class="ui-btn ui-btn--ghost">Huỷ</button><button type="button" class="ui-btn ui-btn--sm">Nhỏ</button><button type="button" class="ui-btn ui-btn--primary" disabled>Đang lưu…</button><a class="ui-btn" href="#buttons">Link dạng nút</a></div></div><details class="cat-code"><summary>Markup</summary><pre><code>&lt;div class=&quot;cat-row&quot;&gt;
33
33
  &lt;button type=&quot;button&quot; class=&quot;ui-btn&quot;&gt;Lưu nháp&lt;/button&gt;
@@ -715,7 +715,7 @@ body{margin:0;background:var(--gemboss-app-bg,#f1f1f1);color:var(--gemboss-text)
715
715
  &lt;/div&gt;
716
716
  &lt;/main&gt;
717
717
  &lt;/div&gt;</code></pre></details></figure></section>
718
- <section id="portal"><h2>Cổng công khai: tab trên topbar, tìm kiếm, sáng / tối, người dẫn đầu</h2><p>Cho bề mặt công khai kiểu bảng Featurebase (GemFeedback) và cộng đồng (GemCommunity). <code>TopbarNav</code> đặt tab mục ngay trên topbar cạnh logo; <code>SearchDialog</code> là popup tìm (⌘K, gõ là ra); <code>ThemeToggle</code> + <code>themeScript</code> bật bảng màu tối (chỉ đổi token, mọi class theo); <code>Avatar</code> ảnh hoặc chữ viết tắt trên một tông lấy theo tên; <code>Leaderboard</code> huy chương 1–3 rồi thứ hạng; <code>Podium</code> ba người đầu.</p><figure class="cat-demo cat-screen"><figcaption>TopbarNav + SearchDialog + ThemeToggle, sáng</figcaption><iframe title="TopbarNav + SearchDialog + ThemeToggle, sáng" style="height:360px" srcdoc="&lt;!doctype html&gt;&lt;html&gt;&lt;head&gt;&lt;meta charset=&quot;utf-8&quot;&gt;&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot;&gt;&lt;link rel=&quot;stylesheet&quot; href=&quot;../gemboss-ui.css&quot;&gt;&lt;/head&gt;&lt;body&gt;&lt;div class=&quot;gemboss-platform-shell&quot;&gt;&lt;header class=&quot;gemboss-platform-topbar&quot;&gt;&lt;div class=&quot;gemboss-topbar-start&quot;&gt;&lt;a class=&quot;gb-brand&quot; href=&quot;/&quot; aria-label=&quot;GemFeedback home&quot;&gt;&lt;svg class=&quot;gb-brand-gem&quot; viewBox=&quot;0 0 32 40&quot; width=&quot;20.8&quot; height=&quot;26&quot; aria-hidden=&quot;true&quot; focusable=&quot;false&quot;&gt;&lt;g transform=&quot;translate(0,0.8) scale(0.31)&quot;&gt;&lt;polygon points=&quot;26,14 74,14 66,50 34,50&quot; fill=&quot;#5661F5&quot; fill-opacity=&quot;0.92&quot;&gt;&lt;/polygon&gt;&lt;path d=&quot;M26,14 74,14 96,50 50,110 4,50Z&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;8.75&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M4,50H96M26,14 34,50M74,14 66,50M34,50 50,110M66,50 50,110&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;5.45&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;/path&gt;&lt;/g&gt;&lt;/svg&gt;&lt;span class=&quot;gb-brand-name&quot;&gt;GemFeedback&lt;/span&gt;&lt;/a&gt;&lt;nav class=&quot;gb-topnav&quot; aria-label=&quot;Sections&quot;&gt;&lt;div class=&quot;gb-topnav-row&quot;&gt;&lt;a href=&quot;#portal&quot; class=&quot;gb-topnav-link&quot; aria-current=&quot;page&quot;&gt;Feedback&lt;/a&gt;&lt;a href=&quot;#portal&quot; class=&quot;gb-topnav-link&quot;&gt;Roadmap&lt;/a&gt;&lt;a href=&quot;#portal&quot; class=&quot;gb-topnav-link&quot;&gt;Changelog&lt;/a&gt;&lt;/div&gt;&lt;details class=&quot;gb-topnav-fold&quot;&gt;&lt;summary class=&quot;gb-topnav-link gb-topnav-fold-btn&quot; aria-current=&quot;page&quot;&gt;Feedback&lt;svg class=&quot;gb-topnav-chevron&quot; width=&quot;12&quot; height=&quot;12&quot; viewBox=&quot;0 0 12 12&quot; aria-hidden=&quot;true&quot; focusable=&quot;false&quot;&gt;&lt;path d=&quot;M3 4.5 6 7.5 9 4.5&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/summary&gt;&lt;div class=&quot;gb-topnav-pop gemboss-popover-surface&quot;&gt;&lt;a href=&quot;#portal&quot; class=&quot;gb-topnav-item&quot; aria-current=&quot;page&quot;&gt;Feedback&lt;/a&gt;&lt;a href=&quot;#portal&quot; class=&quot;gb-topnav-item&quot;&gt;Roadmap&lt;/a&gt;&lt;a href=&quot;#portal&quot; class=&quot;gb-topnav-item&quot;&gt;Changelog&lt;/a&gt;&lt;/div&gt;&lt;/details&gt;&lt;/nav&gt;&lt;/div&gt;&lt;div class=&quot;gemboss-topbar-center&quot;&gt;&lt;/div&gt;&lt;div class=&quot;gemboss-topbar-end&quot;&gt;&lt;a class=&quot;gb-search-trigger&quot; href=&quot;#portal&quot; aria-label=&quot;Search&quot; aria-haspopup=&quot;dialog&quot;&gt;&lt;svg viewBox=&quot;0 0 20 20&quot; width=&quot;18&quot; height=&quot;18&quot; aria-hidden=&quot;true&quot; focusable=&quot;false&quot;&gt;&lt;g fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.5&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;circle cx=&quot;8.8&quot; cy=&quot;8.8&quot; r=&quot;5.3&quot;&gt;&lt;/circle&gt;&lt;path d=&quot;M12.8 12.8 17 17&quot;&gt;&lt;/path&gt;&lt;/g&gt;&lt;/svg&gt;&lt;/a&gt;&lt;dialog class=&quot;ui-modal gb-search&quot; aria-label=&quot;Search&quot;&gt;&lt;div class=&quot;gb-search-box&quot;&gt;&lt;svg viewBox=&quot;0 0 20 20&quot; width=&quot;18&quot; height=&quot;18&quot; class=&quot;gb-search-icon&quot; aria-hidden=&quot;true&quot; focusable=&quot;false&quot;&gt;&lt;g fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.5&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;circle cx=&quot;8.8&quot; cy=&quot;8.8&quot; r=&quot;5.3&quot;&gt;&lt;/circle&gt;&lt;path d=&quot;M12.8 12.8 17 17&quot;&gt;&lt;/path&gt;&lt;/g&gt;&lt;/svg&gt;&lt;input class=&quot;gb-search-input&quot; type=&quot;search&quot; placeholder=&quot;Search…&quot; aria-label=&quot;Search&quot; role=&quot;combobox&quot; aria-expanded=&quot;true&quot; aria-controls=&quot;:Rt:&quot; autoComplete=&quot;off&quot; value=&quot;&quot;/&gt;&lt;/div&gt;&lt;p class=&quot;gb-search-empty&quot; aria-live=&quot;polite&quot;&gt;&lt;/p&gt;&lt;div class=&quot;gb-search-results&quot; id=&quot;:Rt:&quot; role=&quot;listbox&quot; aria-busy=&quot;false&quot;&gt;&lt;/div&gt;&lt;div class=&quot;gb-search-foot&quot; aria-hidden=&quot;true&quot;&gt;&lt;span&gt;↵ open&lt;/span&gt;&lt;span&gt;↑↓ move&lt;/span&gt;&lt;span&gt;esc&lt;/span&gt;&lt;/div&gt;&lt;/dialog&gt;&lt;button type=&quot;button&quot; class=&quot;gb-theme-toggle&quot; aria-label=&quot;Switch to dark mode&quot; title=&quot;Switch to dark mode&quot;&gt;&lt;svg viewBox=&quot;0 0 20 20&quot; width=&quot;18&quot; height=&quot;18&quot; aria-hidden=&quot;true&quot; focusable=&quot;false&quot;&gt;&lt;g fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.5&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M15.6 12.4A6.2 6.2 0 0 1 7.6 4.4a6.2 6.2 0 1 0 8 8Z&quot;&gt;&lt;/path&gt;&lt;/g&gt;&lt;/svg&gt;&lt;/button&gt;&lt;a class=&quot;ui-btn ui-btn--primary&quot; href=&quot;#portal&quot;&gt;Sign in&lt;/a&gt;&lt;/div&gt;&lt;/header&gt;&lt;div&gt;&lt;div style=&quot;padding:72px 24px 24px;display:grid;grid-template-columns:minmax(0,1fr) 260px;gap:24px&quot;&gt;&lt;div class=&quot;ui-card&quot;&gt;&lt;b&gt;Have something to say?&lt;/b&gt;&lt;p class=&quot;ui-muted&quot;&gt;Tell us what to build next.&lt;/p&gt;&lt;/div&gt;&lt;section class=&quot;gb-leaderboard&quot; aria-labelledby=&quot;gb-lb-most-helpful-1wqxo9r&quot;&gt;&lt;h2 class=&quot;gb-leaderboard-title&quot; id=&quot;gb-lb-most-helpful-1wqxo9r&quot;&gt;Most helpful&lt;/h2&gt;&lt;p class=&quot;gb-leaderboard-caption&quot;&gt;By votes on their comments.&lt;/p&gt;&lt;ol class=&quot;gb-leaderboard-list&quot;&gt;&lt;li class=&quot;gb-leaderboard-row is-first&quot;&gt;&lt;a href=&quot;#portal&quot; class=&quot;gb-leaderboard-link&quot;&gt;&lt;span class=&quot;gb-leaderboard-rank&quot;&gt;&lt;span aria-hidden=&quot;true&quot;&gt;🥇&lt;/span&gt;&lt;span class=&quot;ui-sr-only&quot;&gt;Rank 1: &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gb-avatar gb-avatar--24&quot; data-tone=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;LN&lt;/span&gt;&lt;span class=&quot;gb-leaderboard-name&quot;&gt;Lucas Nguyen&lt;/span&gt;&lt;span class=&quot;gb-leaderboard-value&quot;&gt;163&lt;span class=&quot;ui-sr-only&quot;&gt; votes&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;&lt;li class=&quot;gb-leaderboard-row&quot;&gt;&lt;a href=&quot;#portal&quot; class=&quot;gb-leaderboard-link&quot;&gt;&lt;span class=&quot;gb-leaderboard-rank&quot;&gt;&lt;span aria-hidden=&quot;true&quot;&gt;🥈&lt;/span&gt;&lt;span class=&quot;ui-sr-only&quot;&gt;Rank 2: &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gb-avatar gb-avatar--24&quot; data-tone=&quot;0&quot; aria-hidden=&quot;true&quot;&gt;DC&lt;/span&gt;&lt;span class=&quot;gb-leaderboard-name&quot;&gt;Dima Chernyshov&lt;/span&gt;&lt;span class=&quot;gb-leaderboard-value&quot;&gt;56&lt;span class=&quot;ui-sr-only&quot;&gt; votes&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;&lt;li class=&quot;gb-leaderboard-row&quot;&gt;&lt;a href=&quot;#portal&quot; class=&quot;gb-leaderboard-link&quot;&gt;&lt;span class=&quot;gb-leaderboard-rank&quot;&gt;&lt;span aria-hidden=&quot;true&quot;&gt;🥉&lt;/span&gt;&lt;span class=&quot;ui-sr-only&quot;&gt;Rank 3: &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gb-avatar gb-avatar--24&quot; data-tone=&quot;5&quot; aria-hidden=&quot;true&quot;&gt;AR&lt;/span&gt;&lt;span class=&quot;gb-leaderboard-name&quot;&gt;Artjom&lt;/span&gt;&lt;span class=&quot;gb-leaderboard-value&quot;&gt;55&lt;span class=&quot;ui-sr-only&quot;&gt; votes&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;&lt;li class=&quot;gb-leaderboard-row&quot;&gt;&lt;a href=&quot;#portal&quot; class=&quot;gb-leaderboard-link&quot;&gt;&lt;span class=&quot;gb-leaderboard-rank is-number&quot;&gt;&lt;span aria-hidden=&quot;true&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;ui-sr-only&quot;&gt;Rank 4: &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gb-avatar gb-avatar--24&quot; data-tone=&quot;4&quot; aria-hidden=&quot;true&quot;&gt;GU&lt;/span&gt;&lt;span class=&quot;gb-leaderboard-name&quot;&gt;GutBrush&lt;/span&gt;&lt;span class=&quot;gb-leaderboard-value&quot;&gt;34&lt;span class=&quot;ui-sr-only&quot;&gt; votes&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;&lt;li class=&quot;gb-leaderboard-row&quot;&gt;&lt;a href=&quot;#portal&quot; class=&quot;gb-leaderboard-link&quot;&gt;&lt;span class=&quot;gb-leaderboard-rank is-number&quot;&gt;&lt;span aria-hidden=&quot;true&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;ui-sr-only&quot;&gt;Rank 5: &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gb-avatar gb-avatar--24&quot; data-tone=&quot;5&quot; aria-hidden=&quot;true&quot;&gt;WO&lt;/span&gt;&lt;span class=&quot;gb-leaderboard-name&quot;&gt;Wondercraft&lt;/span&gt;&lt;span class=&quot;gb-leaderboard-value&quot;&gt;30&lt;span class=&quot;ui-sr-only&quot;&gt; votes&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/section&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/body&gt;&lt;/html&gt;"></iframe><details class="cat-code"><summary>Markup</summary><pre><code>&lt;div class=&quot;gemboss-platform-shell&quot;&gt;
718
+ <section id="portal"><h2>Cổng công khai: tab trên topbar, tìm kiếm, sáng / tối, người dẫn đầu</h2><p>Cho bề mặt công khai kiểu bảng Featurebase (GemFeedback) và cộng đồng (GemCommunity). <code>TopbarNav</code> đặt tab mục ngay trên topbar cạnh logo; <code>SearchDialog</code> là popup tìm (⌘K, gõ là ra); <code>ThemeToggle</code> + <code>themeScript</code> bật bảng màu tối (chỉ đổi token, mọi class theo); <code>Avatar</code> ảnh hoặc chữ viết tắt trên một tông lấy theo tên; <code>Leaderboard</code> huy chương 1–3 rồi thứ hạng; <code>Podium</code> ba người đầu.</p><figure class="cat-demo cat-screen"><figcaption>TopbarNav + SearchDialog + ThemeToggle, sáng</figcaption><iframe title="TopbarNav + SearchDialog + ThemeToggle, sáng" style="height:360px" srcdoc="&lt;!doctype html&gt;&lt;html&gt;&lt;head&gt;&lt;meta charset=&quot;utf-8&quot;&gt;&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot;&gt;&lt;link rel=&quot;stylesheet&quot; href=&quot;../gemboss-ui.css&quot;&gt;&lt;/head&gt;&lt;body&gt;&lt;div class=&quot;gemboss-platform-shell&quot;&gt;&lt;header class=&quot;gemboss-platform-topbar&quot;&gt;&lt;div class=&quot;gemboss-topbar-start&quot;&gt;&lt;a class=&quot;gb-brand&quot; href=&quot;/&quot; aria-label=&quot;GemFeedback home&quot;&gt;&lt;svg class=&quot;gb-brand-gem&quot; viewBox=&quot;0 0 32 40&quot; width=&quot;20.8&quot; height=&quot;26&quot; aria-hidden=&quot;true&quot; focusable=&quot;false&quot;&gt;&lt;g transform=&quot;translate(0,0.8) scale(0.31)&quot;&gt;&lt;polygon points=&quot;26,14 74,14 66,50 34,50&quot; fill=&quot;#5661F5&quot; fill-opacity=&quot;0.92&quot;&gt;&lt;/polygon&gt;&lt;path d=&quot;M26,14 74,14 96,50 50,110 4,50Z&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;8.75&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M4,50H96M26,14 34,50M74,14 66,50M34,50 50,110M66,50 50,110&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;5.45&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;/path&gt;&lt;/g&gt;&lt;/svg&gt;&lt;span class=&quot;gb-brand-name&quot;&gt;GemFeedback&lt;/span&gt;&lt;/a&gt;&lt;nav class=&quot;gb-topnav&quot; aria-label=&quot;Sections&quot;&gt;&lt;div class=&quot;gb-topnav-row&quot;&gt;&lt;a href=&quot;#portal&quot; class=&quot;gb-topnav-link&quot; aria-current=&quot;page&quot;&gt;Feedback&lt;/a&gt;&lt;a href=&quot;#portal&quot; class=&quot;gb-topnav-link&quot;&gt;Roadmap&lt;/a&gt;&lt;a href=&quot;#portal&quot; class=&quot;gb-topnav-link&quot;&gt;Changelog&lt;/a&gt;&lt;/div&gt;&lt;details class=&quot;gb-topnav-fold&quot;&gt;&lt;summary class=&quot;gb-topnav-link gb-topnav-fold-btn&quot; aria-current=&quot;page&quot;&gt;Feedback&lt;svg class=&quot;gb-topnav-chevron&quot; width=&quot;12&quot; height=&quot;12&quot; viewBox=&quot;0 0 12 12&quot; aria-hidden=&quot;true&quot; focusable=&quot;false&quot;&gt;&lt;path d=&quot;M3 4.5 6 7.5 9 4.5&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/summary&gt;&lt;div class=&quot;gb-topnav-pop gemboss-popover-surface&quot;&gt;&lt;a href=&quot;#portal&quot; class=&quot;gb-topnav-item&quot; aria-current=&quot;page&quot;&gt;Feedback&lt;/a&gt;&lt;a href=&quot;#portal&quot; class=&quot;gb-topnav-item&quot;&gt;Roadmap&lt;/a&gt;&lt;a href=&quot;#portal&quot; class=&quot;gb-topnav-item&quot;&gt;Changelog&lt;/a&gt;&lt;/div&gt;&lt;/details&gt;&lt;/nav&gt;&lt;/div&gt;&lt;div class=&quot;gemboss-topbar-center&quot;&gt;&lt;/div&gt;&lt;div class=&quot;gemboss-topbar-end&quot;&gt;&lt;a class=&quot;gb-search-trigger&quot; href=&quot;#portal&quot; aria-label=&quot;Search&quot; aria-haspopup=&quot;dialog&quot;&gt;&lt;svg viewBox=&quot;0 0 20 20&quot; width=&quot;18&quot; height=&quot;18&quot; aria-hidden=&quot;true&quot; focusable=&quot;false&quot;&gt;&lt;g fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.5&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;circle cx=&quot;8.8&quot; cy=&quot;8.8&quot; r=&quot;5.3&quot;&gt;&lt;/circle&gt;&lt;path d=&quot;M12.8 12.8 17 17&quot;&gt;&lt;/path&gt;&lt;/g&gt;&lt;/svg&gt;&lt;/a&gt;&lt;dialog class=&quot;ui-modal gb-search&quot; aria-label=&quot;Search&quot;&gt;&lt;div class=&quot;gb-search-box&quot;&gt;&lt;svg viewBox=&quot;0 0 20 20&quot; width=&quot;18&quot; height=&quot;18&quot; class=&quot;gb-search-icon&quot; aria-hidden=&quot;true&quot; focusable=&quot;false&quot;&gt;&lt;g fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.5&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;circle cx=&quot;8.8&quot; cy=&quot;8.8&quot; r=&quot;5.3&quot;&gt;&lt;/circle&gt;&lt;path d=&quot;M12.8 12.8 17 17&quot;&gt;&lt;/path&gt;&lt;/g&gt;&lt;/svg&gt;&lt;input class=&quot;gb-search-input&quot; type=&quot;search&quot; placeholder=&quot;Search…&quot; aria-label=&quot;Search&quot; role=&quot;combobox&quot; aria-expanded=&quot;true&quot; aria-controls=&quot;:Rt:&quot; autoComplete=&quot;off&quot; value=&quot;&quot;/&gt;&lt;/div&gt;&lt;p class=&quot;gb-search-empty&quot; aria-live=&quot;polite&quot;&gt;&lt;/p&gt;&lt;div class=&quot;gb-search-results&quot; id=&quot;:Rt:&quot; role=&quot;listbox&quot; aria-busy=&quot;false&quot;&gt;&lt;/div&gt;&lt;div class=&quot;gb-search-foot&quot; aria-hidden=&quot;true&quot;&gt;&lt;span&gt;↵ open&lt;/span&gt;&lt;span&gt;↑↓ move&lt;/span&gt;&lt;span&gt;esc&lt;/span&gt;&lt;/div&gt;&lt;/dialog&gt;&lt;button type=&quot;button&quot; class=&quot;gb-theme-toggle&quot; aria-label=&quot;Switch to dark mode&quot; title=&quot;Switch to dark mode&quot;&gt;&lt;svg viewBox=&quot;0 0 20 20&quot; width=&quot;18&quot; height=&quot;18&quot; aria-hidden=&quot;true&quot; focusable=&quot;false&quot;&gt;&lt;g fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.5&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M15.6 12.4A6.2 6.2 0 0 1 7.6 4.4a6.2 6.2 0 1 0 8 8Z&quot;&gt;&lt;/path&gt;&lt;/g&gt;&lt;/svg&gt;&lt;/button&gt;&lt;a class=&quot;ui-btn ui-btn--primary&quot; href=&quot;#portal&quot;&gt;Sign in&lt;/a&gt;&lt;/div&gt;&lt;/header&gt;&lt;div&gt;&lt;div style=&quot;padding:72px 24px 24px;display:grid;grid-template-columns:minmax(0,1fr) 260px;gap:24px&quot;&gt;&lt;div class=&quot;ui-card&quot;&gt;&lt;b&gt;Have something to say?&lt;/b&gt;&lt;p class=&quot;ui-muted&quot;&gt;Tell us what to build next.&lt;/p&gt;&lt;/div&gt;&lt;section class=&quot;gb-leaderboard&quot; aria-labelledby=&quot;gb-lb-most-helpful-1wqxo9r&quot;&gt;&lt;h2 class=&quot;gb-leaderboard-title&quot; id=&quot;gb-lb-most-helpful-1wqxo9r&quot;&gt;Most helpful&lt;/h2&gt;&lt;p class=&quot;gb-leaderboard-caption&quot;&gt;By votes on their comments.&lt;/p&gt;&lt;ol class=&quot;gb-leaderboard-list&quot;&gt;&lt;li class=&quot;gb-leaderboard-row is-first&quot;&gt;&lt;a href=&quot;#portal&quot; class=&quot;gb-leaderboard-link&quot;&gt;&lt;span class=&quot;gb-leaderboard-rank&quot;&gt;&lt;span aria-hidden=&quot;true&quot;&gt;🥇&lt;/span&gt;&lt;span class=&quot;gb-sr-only&quot;&gt;Rank 1: &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gb-avatar gb-avatar--24&quot; data-tone=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;LN&lt;/span&gt;&lt;span class=&quot;gb-leaderboard-name&quot;&gt;Lucas Nguyen&lt;/span&gt;&lt;span class=&quot;gb-leaderboard-value&quot;&gt;163&lt;span class=&quot;gb-sr-only&quot;&gt; votes&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;&lt;li class=&quot;gb-leaderboard-row&quot;&gt;&lt;a href=&quot;#portal&quot; class=&quot;gb-leaderboard-link&quot;&gt;&lt;span class=&quot;gb-leaderboard-rank&quot;&gt;&lt;span aria-hidden=&quot;true&quot;&gt;🥈&lt;/span&gt;&lt;span class=&quot;gb-sr-only&quot;&gt;Rank 2: &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gb-avatar gb-avatar--24&quot; data-tone=&quot;0&quot; aria-hidden=&quot;true&quot;&gt;DC&lt;/span&gt;&lt;span class=&quot;gb-leaderboard-name&quot;&gt;Dima Chernyshov&lt;/span&gt;&lt;span class=&quot;gb-leaderboard-value&quot;&gt;56&lt;span class=&quot;gb-sr-only&quot;&gt; votes&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;&lt;li class=&quot;gb-leaderboard-row&quot;&gt;&lt;a href=&quot;#portal&quot; class=&quot;gb-leaderboard-link&quot;&gt;&lt;span class=&quot;gb-leaderboard-rank&quot;&gt;&lt;span aria-hidden=&quot;true&quot;&gt;🥉&lt;/span&gt;&lt;span class=&quot;gb-sr-only&quot;&gt;Rank 3: &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gb-avatar gb-avatar--24&quot; data-tone=&quot;5&quot; aria-hidden=&quot;true&quot;&gt;AR&lt;/span&gt;&lt;span class=&quot;gb-leaderboard-name&quot;&gt;Artjom&lt;/span&gt;&lt;span class=&quot;gb-leaderboard-value&quot;&gt;55&lt;span class=&quot;gb-sr-only&quot;&gt; votes&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;&lt;li class=&quot;gb-leaderboard-row&quot;&gt;&lt;a href=&quot;#portal&quot; class=&quot;gb-leaderboard-link&quot;&gt;&lt;span class=&quot;gb-leaderboard-rank is-number&quot;&gt;&lt;span aria-hidden=&quot;true&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;gb-sr-only&quot;&gt;Rank 4: &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gb-avatar gb-avatar--24&quot; data-tone=&quot;4&quot; aria-hidden=&quot;true&quot;&gt;GU&lt;/span&gt;&lt;span class=&quot;gb-leaderboard-name&quot;&gt;GutBrush&lt;/span&gt;&lt;span class=&quot;gb-leaderboard-value&quot;&gt;34&lt;span class=&quot;gb-sr-only&quot;&gt; votes&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;&lt;li class=&quot;gb-leaderboard-row&quot;&gt;&lt;a href=&quot;#portal&quot; class=&quot;gb-leaderboard-link&quot;&gt;&lt;span class=&quot;gb-leaderboard-rank is-number&quot;&gt;&lt;span aria-hidden=&quot;true&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;gb-sr-only&quot;&gt;Rank 5: &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gb-avatar gb-avatar--24&quot; data-tone=&quot;5&quot; aria-hidden=&quot;true&quot;&gt;WO&lt;/span&gt;&lt;span class=&quot;gb-leaderboard-name&quot;&gt;Wondercraft&lt;/span&gt;&lt;span class=&quot;gb-leaderboard-value&quot;&gt;30&lt;span class=&quot;gb-sr-only&quot;&gt; votes&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/section&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/body&gt;&lt;/html&gt;"></iframe><details class="cat-code"><summary>Markup</summary><pre><code>&lt;div class=&quot;gemboss-platform-shell&quot;&gt;
719
719
  &lt;header class=&quot;gemboss-platform-topbar&quot;&gt;
720
720
  &lt;div class=&quot;gemboss-topbar-start&quot;&gt;
721
721
  &lt;a class=&quot;gb-brand&quot; href=&quot;/&quot; aria-label=&quot;GemFeedback home&quot;&gt;
@@ -811,11 +811,11 @@ body{margin:0;background:var(--gemboss-app-bg,#f1f1f1);color:var(--gemboss-text)
811
811
  &lt;a href=&quot;#portal&quot; class=&quot;gb-leaderboard-link&quot;&gt;
812
812
  &lt;span class=&quot;gb-leaderboard-rank&quot;&gt;
813
813
  &lt;span aria-hidden=&quot;true&quot;&gt;🥇&lt;/span&gt;
814
- &lt;span class=&quot;ui-sr-only&quot;&gt;Rank 1: &lt;/span&gt;
814
+ &lt;span class=&quot;gb-sr-only&quot;&gt;Rank 1: &lt;/span&gt;
815
815
  &lt;/span&gt;
816
816
  &lt;span class=&quot;gb-avatar gb-avatar--24&quot; data-tone=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;LN&lt;/span&gt;
817
817
  &lt;span class=&quot;gb-leaderboard-name&quot;&gt;Lucas Nguyen&lt;/span&gt;
818
- &lt;span class=&quot;gb-leaderboard-value&quot;&gt;163&lt;span class=&quot;ui-sr-only&quot;&gt; votes&lt;/span&gt;
818
+ &lt;span class=&quot;gb-leaderboard-value&quot;&gt;163&lt;span class=&quot;gb-sr-only&quot;&gt; votes&lt;/span&gt;
819
819
  &lt;/span&gt;
820
820
  &lt;/a&gt;
821
821
  &lt;/li&gt;
@@ -823,11 +823,11 @@ body{margin:0;background:var(--gemboss-app-bg,#f1f1f1);color:var(--gemboss-text)
823
823
  &lt;a href=&quot;#portal&quot; class=&quot;gb-leaderboard-link&quot;&gt;
824
824
  &lt;span class=&quot;gb-leaderboard-rank&quot;&gt;
825
825
  &lt;span aria-hidden=&quot;true&quot;&gt;🥈&lt;/span&gt;
826
- &lt;span class=&quot;ui-sr-only&quot;&gt;Rank 2: &lt;/span&gt;
826
+ &lt;span class=&quot;gb-sr-only&quot;&gt;Rank 2: &lt;/span&gt;
827
827
  &lt;/span&gt;
828
828
  &lt;span class=&quot;gb-avatar gb-avatar--24&quot; data-tone=&quot;0&quot; aria-hidden=&quot;true&quot;&gt;DC&lt;/span&gt;
829
829
  &lt;span class=&quot;gb-leaderboard-name&quot;&gt;Dima Chernyshov&lt;/span&gt;
830
- &lt;span class=&quot;gb-leaderboard-value&quot;&gt;56&lt;span class=&quot;ui-sr-only&quot;&gt; votes&lt;/span&gt;
830
+ &lt;span class=&quot;gb-leaderboard-value&quot;&gt;56&lt;span class=&quot;gb-sr-only&quot;&gt; votes&lt;/span&gt;
831
831
  &lt;/span&gt;
832
832
  &lt;/a&gt;
833
833
  &lt;/li&gt;
@@ -835,11 +835,11 @@ body{margin:0;background:var(--gemboss-app-bg,#f1f1f1);color:var(--gemboss-text)
835
835
  &lt;a href=&quot;#portal&quot; class=&quot;gb-leaderboard-link&quot;&gt;
836
836
  &lt;span class=&quot;gb-leaderboard-rank&quot;&gt;
837
837
  &lt;span aria-hidden=&quot;true&quot;&gt;🥉&lt;/span&gt;
838
- &lt;span class=&quot;ui-sr-only&quot;&gt;Rank 3: &lt;/span&gt;
838
+ &lt;span class=&quot;gb-sr-only&quot;&gt;Rank 3: &lt;/span&gt;
839
839
  &lt;/span&gt;
840
840
  &lt;span class=&quot;gb-avatar gb-avatar--24&quot; data-tone=&quot;5&quot; aria-hidden=&quot;true&quot;&gt;AR&lt;/span&gt;
841
841
  &lt;span class=&quot;gb-leaderboard-name&quot;&gt;Artjom&lt;/span&gt;
842
- &lt;span class=&quot;gb-leaderboard-value&quot;&gt;55&lt;span class=&quot;ui-sr-only&quot;&gt; votes&lt;/span&gt;
842
+ &lt;span class=&quot;gb-leaderboard-value&quot;&gt;55&lt;span class=&quot;gb-sr-only&quot;&gt; votes&lt;/span&gt;
843
843
  &lt;/span&gt;
844
844
  &lt;/a&gt;
845
845
  &lt;/li&gt;
@@ -847,11 +847,11 @@ body{margin:0;background:var(--gemboss-app-bg,#f1f1f1);color:var(--gemboss-text)
847
847
  &lt;a href=&quot;#portal&quot; class=&quot;gb-leaderboard-link&quot;&gt;
848
848
  &lt;span class=&quot;gb-leaderboard-rank is-number&quot;&gt;
849
849
  &lt;span aria-hidden=&quot;true&quot;&gt;4&lt;/span&gt;
850
- &lt;span class=&quot;ui-sr-only&quot;&gt;Rank 4: &lt;/span&gt;
850
+ &lt;span class=&quot;gb-sr-only&quot;&gt;Rank 4: &lt;/span&gt;
851
851
  &lt;/span&gt;
852
852
  &lt;span class=&quot;gb-avatar gb-avatar--24&quot; data-tone=&quot;4&quot; aria-hidden=&quot;true&quot;&gt;GU&lt;/span&gt;
853
853
  &lt;span class=&quot;gb-leaderboard-name&quot;&gt;GutBrush&lt;/span&gt;
854
- &lt;span class=&quot;gb-leaderboard-value&quot;&gt;34&lt;span class=&quot;ui-sr-only&quot;&gt; votes&lt;/span&gt;
854
+ &lt;span class=&quot;gb-leaderboard-value&quot;&gt;34&lt;span class=&quot;gb-sr-only&quot;&gt; votes&lt;/span&gt;
855
855
  &lt;/span&gt;
856
856
  &lt;/a&gt;
857
857
  &lt;/li&gt;
@@ -859,11 +859,11 @@ body{margin:0;background:var(--gemboss-app-bg,#f1f1f1);color:var(--gemboss-text)
859
859
  &lt;a href=&quot;#portal&quot; class=&quot;gb-leaderboard-link&quot;&gt;
860
860
  &lt;span class=&quot;gb-leaderboard-rank is-number&quot;&gt;
861
861
  &lt;span aria-hidden=&quot;true&quot;&gt;5&lt;/span&gt;
862
- &lt;span class=&quot;ui-sr-only&quot;&gt;Rank 5: &lt;/span&gt;
862
+ &lt;span class=&quot;gb-sr-only&quot;&gt;Rank 5: &lt;/span&gt;
863
863
  &lt;/span&gt;
864
864
  &lt;span class=&quot;gb-avatar gb-avatar--24&quot; data-tone=&quot;5&quot; aria-hidden=&quot;true&quot;&gt;WO&lt;/span&gt;
865
865
  &lt;span class=&quot;gb-leaderboard-name&quot;&gt;Wondercraft&lt;/span&gt;
866
- &lt;span class=&quot;gb-leaderboard-value&quot;&gt;30&lt;span class=&quot;ui-sr-only&quot;&gt; votes&lt;/span&gt;
866
+ &lt;span class=&quot;gb-leaderboard-value&quot;&gt;30&lt;span class=&quot;gb-sr-only&quot;&gt; votes&lt;/span&gt;
867
867
  &lt;/span&gt;
868
868
  &lt;/a&gt;
869
869
  &lt;/li&gt;
@@ -871,7 +871,7 @@ body{margin:0;background:var(--gemboss-app-bg,#f1f1f1);color:var(--gemboss-text)
871
871
  &lt;/section&gt;
872
872
  &lt;/div&gt;
873
873
  &lt;/div&gt;
874
- &lt;/div&gt;</code></pre></details></figure><figure class="cat-demo cat-screen"><figcaption>Cùng trang, tối (data-theme=&quot;dark&quot;)</figcaption><iframe title="Cùng trang, tối (data-theme=&quot;dark&quot;)" style="height:360px" srcdoc="&lt;!doctype html&gt;&lt;html data-theme=&quot;dark&quot;&gt;&lt;head&gt;&lt;meta charset=&quot;utf-8&quot;&gt;&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot;&gt;&lt;link rel=&quot;stylesheet&quot; href=&quot;../gemboss-ui.css&quot;&gt;&lt;/head&gt;&lt;body&gt;&lt;div class=&quot;gemboss-platform-shell&quot;&gt;&lt;header class=&quot;gemboss-platform-topbar&quot;&gt;&lt;div class=&quot;gemboss-topbar-start&quot;&gt;&lt;a class=&quot;gb-brand&quot; href=&quot;/&quot; aria-label=&quot;GemFeedback home&quot;&gt;&lt;svg class=&quot;gb-brand-gem&quot; viewBox=&quot;0 0 32 40&quot; width=&quot;20.8&quot; height=&quot;26&quot; aria-hidden=&quot;true&quot; focusable=&quot;false&quot;&gt;&lt;g transform=&quot;translate(0,0.8) scale(0.31)&quot;&gt;&lt;polygon points=&quot;26,14 74,14 66,50 34,50&quot; fill=&quot;#5661F5&quot; fill-opacity=&quot;0.92&quot;&gt;&lt;/polygon&gt;&lt;path d=&quot;M26,14 74,14 96,50 50,110 4,50Z&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;8.75&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M4,50H96M26,14 34,50M74,14 66,50M34,50 50,110M66,50 50,110&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;5.45&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;/path&gt;&lt;/g&gt;&lt;/svg&gt;&lt;span class=&quot;gb-brand-name&quot;&gt;GemFeedback&lt;/span&gt;&lt;/a&gt;&lt;nav class=&quot;gb-topnav&quot; aria-label=&quot;Sections&quot;&gt;&lt;div class=&quot;gb-topnav-row&quot;&gt;&lt;a href=&quot;#portal&quot; class=&quot;gb-topnav-link&quot; aria-current=&quot;page&quot;&gt;Feedback&lt;/a&gt;&lt;a href=&quot;#portal&quot; class=&quot;gb-topnav-link&quot;&gt;Roadmap&lt;/a&gt;&lt;a href=&quot;#portal&quot; class=&quot;gb-topnav-link&quot;&gt;Changelog&lt;/a&gt;&lt;/div&gt;&lt;details class=&quot;gb-topnav-fold&quot;&gt;&lt;summary class=&quot;gb-topnav-link gb-topnav-fold-btn&quot; aria-current=&quot;page&quot;&gt;Feedback&lt;svg class=&quot;gb-topnav-chevron&quot; width=&quot;12&quot; height=&quot;12&quot; viewBox=&quot;0 0 12 12&quot; aria-hidden=&quot;true&quot; focusable=&quot;false&quot;&gt;&lt;path d=&quot;M3 4.5 6 7.5 9 4.5&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/summary&gt;&lt;div class=&quot;gb-topnav-pop gemboss-popover-surface&quot;&gt;&lt;a href=&quot;#portal&quot; class=&quot;gb-topnav-item&quot; aria-current=&quot;page&quot;&gt;Feedback&lt;/a&gt;&lt;a href=&quot;#portal&quot; class=&quot;gb-topnav-item&quot;&gt;Roadmap&lt;/a&gt;&lt;a href=&quot;#portal&quot; class=&quot;gb-topnav-item&quot;&gt;Changelog&lt;/a&gt;&lt;/div&gt;&lt;/details&gt;&lt;/nav&gt;&lt;/div&gt;&lt;div class=&quot;gemboss-topbar-center&quot;&gt;&lt;/div&gt;&lt;div class=&quot;gemboss-topbar-end&quot;&gt;&lt;a class=&quot;gb-search-trigger&quot; href=&quot;#portal&quot; aria-label=&quot;Search&quot; aria-haspopup=&quot;dialog&quot;&gt;&lt;svg viewBox=&quot;0 0 20 20&quot; width=&quot;18&quot; height=&quot;18&quot; aria-hidden=&quot;true&quot; focusable=&quot;false&quot;&gt;&lt;g fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.5&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;circle cx=&quot;8.8&quot; cy=&quot;8.8&quot; r=&quot;5.3&quot;&gt;&lt;/circle&gt;&lt;path d=&quot;M12.8 12.8 17 17&quot;&gt;&lt;/path&gt;&lt;/g&gt;&lt;/svg&gt;&lt;/a&gt;&lt;dialog class=&quot;ui-modal gb-search&quot; aria-label=&quot;Search&quot;&gt;&lt;div class=&quot;gb-search-box&quot;&gt;&lt;svg viewBox=&quot;0 0 20 20&quot; width=&quot;18&quot; height=&quot;18&quot; class=&quot;gb-search-icon&quot; aria-hidden=&quot;true&quot; focusable=&quot;false&quot;&gt;&lt;g fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.5&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;circle cx=&quot;8.8&quot; cy=&quot;8.8&quot; r=&quot;5.3&quot;&gt;&lt;/circle&gt;&lt;path d=&quot;M12.8 12.8 17 17&quot;&gt;&lt;/path&gt;&lt;/g&gt;&lt;/svg&gt;&lt;input class=&quot;gb-search-input&quot; type=&quot;search&quot; placeholder=&quot;Search…&quot; aria-label=&quot;Search&quot; role=&quot;combobox&quot; aria-expanded=&quot;true&quot; aria-controls=&quot;:Rt:&quot; autoComplete=&quot;off&quot; value=&quot;&quot;/&gt;&lt;/div&gt;&lt;p class=&quot;gb-search-empty&quot; aria-live=&quot;polite&quot;&gt;&lt;/p&gt;&lt;div class=&quot;gb-search-results&quot; id=&quot;:Rt:&quot; role=&quot;listbox&quot; aria-busy=&quot;false&quot;&gt;&lt;/div&gt;&lt;div class=&quot;gb-search-foot&quot; aria-hidden=&quot;true&quot;&gt;&lt;span&gt;↵ open&lt;/span&gt;&lt;span&gt;↑↓ move&lt;/span&gt;&lt;span&gt;esc&lt;/span&gt;&lt;/div&gt;&lt;/dialog&gt;&lt;button type=&quot;button&quot; class=&quot;gb-theme-toggle&quot; aria-label=&quot;Switch to dark mode&quot; title=&quot;Switch to dark mode&quot;&gt;&lt;svg viewBox=&quot;0 0 20 20&quot; width=&quot;18&quot; height=&quot;18&quot; aria-hidden=&quot;true&quot; focusable=&quot;false&quot;&gt;&lt;g fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.5&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M15.6 12.4A6.2 6.2 0 0 1 7.6 4.4a6.2 6.2 0 1 0 8 8Z&quot;&gt;&lt;/path&gt;&lt;/g&gt;&lt;/svg&gt;&lt;/button&gt;&lt;a class=&quot;ui-btn ui-btn--primary&quot; href=&quot;#portal&quot;&gt;Sign in&lt;/a&gt;&lt;/div&gt;&lt;/header&gt;&lt;div&gt;&lt;div style=&quot;padding:72px 24px 24px;display:grid;grid-template-columns:minmax(0,1fr) 260px;gap:24px&quot;&gt;&lt;div class=&quot;ui-card&quot;&gt;&lt;b&gt;Have something to say?&lt;/b&gt;&lt;p class=&quot;ui-muted&quot;&gt;Tell us what to build next.&lt;/p&gt;&lt;/div&gt;&lt;section class=&quot;gb-leaderboard&quot; aria-labelledby=&quot;gb-lb-most-helpful-1wqxo9r&quot;&gt;&lt;h2 class=&quot;gb-leaderboard-title&quot; id=&quot;gb-lb-most-helpful-1wqxo9r&quot;&gt;Most helpful&lt;/h2&gt;&lt;p class=&quot;gb-leaderboard-caption&quot;&gt;By votes on their comments.&lt;/p&gt;&lt;ol class=&quot;gb-leaderboard-list&quot;&gt;&lt;li class=&quot;gb-leaderboard-row is-first&quot;&gt;&lt;a href=&quot;#portal&quot; class=&quot;gb-leaderboard-link&quot;&gt;&lt;span class=&quot;gb-leaderboard-rank&quot;&gt;&lt;span aria-hidden=&quot;true&quot;&gt;🥇&lt;/span&gt;&lt;span class=&quot;ui-sr-only&quot;&gt;Rank 1: &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gb-avatar gb-avatar--24&quot; data-tone=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;LN&lt;/span&gt;&lt;span class=&quot;gb-leaderboard-name&quot;&gt;Lucas Nguyen&lt;/span&gt;&lt;span class=&quot;gb-leaderboard-value&quot;&gt;163&lt;span class=&quot;ui-sr-only&quot;&gt; votes&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;&lt;li class=&quot;gb-leaderboard-row&quot;&gt;&lt;a href=&quot;#portal&quot; class=&quot;gb-leaderboard-link&quot;&gt;&lt;span class=&quot;gb-leaderboard-rank&quot;&gt;&lt;span aria-hidden=&quot;true&quot;&gt;🥈&lt;/span&gt;&lt;span class=&quot;ui-sr-only&quot;&gt;Rank 2: &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gb-avatar gb-avatar--24&quot; data-tone=&quot;0&quot; aria-hidden=&quot;true&quot;&gt;DC&lt;/span&gt;&lt;span class=&quot;gb-leaderboard-name&quot;&gt;Dima Chernyshov&lt;/span&gt;&lt;span class=&quot;gb-leaderboard-value&quot;&gt;56&lt;span class=&quot;ui-sr-only&quot;&gt; votes&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;&lt;li class=&quot;gb-leaderboard-row&quot;&gt;&lt;a href=&quot;#portal&quot; class=&quot;gb-leaderboard-link&quot;&gt;&lt;span class=&quot;gb-leaderboard-rank&quot;&gt;&lt;span aria-hidden=&quot;true&quot;&gt;🥉&lt;/span&gt;&lt;span class=&quot;ui-sr-only&quot;&gt;Rank 3: &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gb-avatar gb-avatar--24&quot; data-tone=&quot;5&quot; aria-hidden=&quot;true&quot;&gt;AR&lt;/span&gt;&lt;span class=&quot;gb-leaderboard-name&quot;&gt;Artjom&lt;/span&gt;&lt;span class=&quot;gb-leaderboard-value&quot;&gt;55&lt;span class=&quot;ui-sr-only&quot;&gt; votes&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;&lt;li class=&quot;gb-leaderboard-row&quot;&gt;&lt;a href=&quot;#portal&quot; class=&quot;gb-leaderboard-link&quot;&gt;&lt;span class=&quot;gb-leaderboard-rank is-number&quot;&gt;&lt;span aria-hidden=&quot;true&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;ui-sr-only&quot;&gt;Rank 4: &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gb-avatar gb-avatar--24&quot; data-tone=&quot;4&quot; aria-hidden=&quot;true&quot;&gt;GU&lt;/span&gt;&lt;span class=&quot;gb-leaderboard-name&quot;&gt;GutBrush&lt;/span&gt;&lt;span class=&quot;gb-leaderboard-value&quot;&gt;34&lt;span class=&quot;ui-sr-only&quot;&gt; votes&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;&lt;li class=&quot;gb-leaderboard-row&quot;&gt;&lt;a href=&quot;#portal&quot; class=&quot;gb-leaderboard-link&quot;&gt;&lt;span class=&quot;gb-leaderboard-rank is-number&quot;&gt;&lt;span aria-hidden=&quot;true&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;ui-sr-only&quot;&gt;Rank 5: &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gb-avatar gb-avatar--24&quot; data-tone=&quot;5&quot; aria-hidden=&quot;true&quot;&gt;WO&lt;/span&gt;&lt;span class=&quot;gb-leaderboard-name&quot;&gt;Wondercraft&lt;/span&gt;&lt;span class=&quot;gb-leaderboard-value&quot;&gt;30&lt;span class=&quot;ui-sr-only&quot;&gt; votes&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/section&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/body&gt;&lt;/html&gt;"></iframe><details class="cat-code"><summary>Markup</summary><pre><code>&lt;div class=&quot;gemboss-platform-shell&quot;&gt;
874
+ &lt;/div&gt;</code></pre></details></figure><figure class="cat-demo cat-screen"><figcaption>Cùng trang, tối (data-theme=&quot;dark&quot;)</figcaption><iframe title="Cùng trang, tối (data-theme=&quot;dark&quot;)" style="height:360px" srcdoc="&lt;!doctype html&gt;&lt;html data-theme=&quot;dark&quot;&gt;&lt;head&gt;&lt;meta charset=&quot;utf-8&quot;&gt;&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot;&gt;&lt;link rel=&quot;stylesheet&quot; href=&quot;../gemboss-ui.css&quot;&gt;&lt;/head&gt;&lt;body&gt;&lt;div class=&quot;gemboss-platform-shell&quot;&gt;&lt;header class=&quot;gemboss-platform-topbar&quot;&gt;&lt;div class=&quot;gemboss-topbar-start&quot;&gt;&lt;a class=&quot;gb-brand&quot; href=&quot;/&quot; aria-label=&quot;GemFeedback home&quot;&gt;&lt;svg class=&quot;gb-brand-gem&quot; viewBox=&quot;0 0 32 40&quot; width=&quot;20.8&quot; height=&quot;26&quot; aria-hidden=&quot;true&quot; focusable=&quot;false&quot;&gt;&lt;g transform=&quot;translate(0,0.8) scale(0.31)&quot;&gt;&lt;polygon points=&quot;26,14 74,14 66,50 34,50&quot; fill=&quot;#5661F5&quot; fill-opacity=&quot;0.92&quot;&gt;&lt;/polygon&gt;&lt;path d=&quot;M26,14 74,14 96,50 50,110 4,50Z&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;8.75&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M4,50H96M26,14 34,50M74,14 66,50M34,50 50,110M66,50 50,110&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;5.45&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;/path&gt;&lt;/g&gt;&lt;/svg&gt;&lt;span class=&quot;gb-brand-name&quot;&gt;GemFeedback&lt;/span&gt;&lt;/a&gt;&lt;nav class=&quot;gb-topnav&quot; aria-label=&quot;Sections&quot;&gt;&lt;div class=&quot;gb-topnav-row&quot;&gt;&lt;a href=&quot;#portal&quot; class=&quot;gb-topnav-link&quot; aria-current=&quot;page&quot;&gt;Feedback&lt;/a&gt;&lt;a href=&quot;#portal&quot; class=&quot;gb-topnav-link&quot;&gt;Roadmap&lt;/a&gt;&lt;a href=&quot;#portal&quot; class=&quot;gb-topnav-link&quot;&gt;Changelog&lt;/a&gt;&lt;/div&gt;&lt;details class=&quot;gb-topnav-fold&quot;&gt;&lt;summary class=&quot;gb-topnav-link gb-topnav-fold-btn&quot; aria-current=&quot;page&quot;&gt;Feedback&lt;svg class=&quot;gb-topnav-chevron&quot; width=&quot;12&quot; height=&quot;12&quot; viewBox=&quot;0 0 12 12&quot; aria-hidden=&quot;true&quot; focusable=&quot;false&quot;&gt;&lt;path d=&quot;M3 4.5 6 7.5 9 4.5&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/summary&gt;&lt;div class=&quot;gb-topnav-pop gemboss-popover-surface&quot;&gt;&lt;a href=&quot;#portal&quot; class=&quot;gb-topnav-item&quot; aria-current=&quot;page&quot;&gt;Feedback&lt;/a&gt;&lt;a href=&quot;#portal&quot; class=&quot;gb-topnav-item&quot;&gt;Roadmap&lt;/a&gt;&lt;a href=&quot;#portal&quot; class=&quot;gb-topnav-item&quot;&gt;Changelog&lt;/a&gt;&lt;/div&gt;&lt;/details&gt;&lt;/nav&gt;&lt;/div&gt;&lt;div class=&quot;gemboss-topbar-center&quot;&gt;&lt;/div&gt;&lt;div class=&quot;gemboss-topbar-end&quot;&gt;&lt;a class=&quot;gb-search-trigger&quot; href=&quot;#portal&quot; aria-label=&quot;Search&quot; aria-haspopup=&quot;dialog&quot;&gt;&lt;svg viewBox=&quot;0 0 20 20&quot; width=&quot;18&quot; height=&quot;18&quot; aria-hidden=&quot;true&quot; focusable=&quot;false&quot;&gt;&lt;g fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.5&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;circle cx=&quot;8.8&quot; cy=&quot;8.8&quot; r=&quot;5.3&quot;&gt;&lt;/circle&gt;&lt;path d=&quot;M12.8 12.8 17 17&quot;&gt;&lt;/path&gt;&lt;/g&gt;&lt;/svg&gt;&lt;/a&gt;&lt;dialog class=&quot;ui-modal gb-search&quot; aria-label=&quot;Search&quot;&gt;&lt;div class=&quot;gb-search-box&quot;&gt;&lt;svg viewBox=&quot;0 0 20 20&quot; width=&quot;18&quot; height=&quot;18&quot; class=&quot;gb-search-icon&quot; aria-hidden=&quot;true&quot; focusable=&quot;false&quot;&gt;&lt;g fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.5&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;circle cx=&quot;8.8&quot; cy=&quot;8.8&quot; r=&quot;5.3&quot;&gt;&lt;/circle&gt;&lt;path d=&quot;M12.8 12.8 17 17&quot;&gt;&lt;/path&gt;&lt;/g&gt;&lt;/svg&gt;&lt;input class=&quot;gb-search-input&quot; type=&quot;search&quot; placeholder=&quot;Search…&quot; aria-label=&quot;Search&quot; role=&quot;combobox&quot; aria-expanded=&quot;true&quot; aria-controls=&quot;:Rt:&quot; autoComplete=&quot;off&quot; value=&quot;&quot;/&gt;&lt;/div&gt;&lt;p class=&quot;gb-search-empty&quot; aria-live=&quot;polite&quot;&gt;&lt;/p&gt;&lt;div class=&quot;gb-search-results&quot; id=&quot;:Rt:&quot; role=&quot;listbox&quot; aria-busy=&quot;false&quot;&gt;&lt;/div&gt;&lt;div class=&quot;gb-search-foot&quot; aria-hidden=&quot;true&quot;&gt;&lt;span&gt;↵ open&lt;/span&gt;&lt;span&gt;↑↓ move&lt;/span&gt;&lt;span&gt;esc&lt;/span&gt;&lt;/div&gt;&lt;/dialog&gt;&lt;button type=&quot;button&quot; class=&quot;gb-theme-toggle&quot; aria-label=&quot;Switch to dark mode&quot; title=&quot;Switch to dark mode&quot;&gt;&lt;svg viewBox=&quot;0 0 20 20&quot; width=&quot;18&quot; height=&quot;18&quot; aria-hidden=&quot;true&quot; focusable=&quot;false&quot;&gt;&lt;g fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.5&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M15.6 12.4A6.2 6.2 0 0 1 7.6 4.4a6.2 6.2 0 1 0 8 8Z&quot;&gt;&lt;/path&gt;&lt;/g&gt;&lt;/svg&gt;&lt;/button&gt;&lt;a class=&quot;ui-btn ui-btn--primary&quot; href=&quot;#portal&quot;&gt;Sign in&lt;/a&gt;&lt;/div&gt;&lt;/header&gt;&lt;div&gt;&lt;div style=&quot;padding:72px 24px 24px;display:grid;grid-template-columns:minmax(0,1fr) 260px;gap:24px&quot;&gt;&lt;div class=&quot;ui-card&quot;&gt;&lt;b&gt;Have something to say?&lt;/b&gt;&lt;p class=&quot;ui-muted&quot;&gt;Tell us what to build next.&lt;/p&gt;&lt;/div&gt;&lt;section class=&quot;gb-leaderboard&quot; aria-labelledby=&quot;gb-lb-most-helpful-1wqxo9r&quot;&gt;&lt;h2 class=&quot;gb-leaderboard-title&quot; id=&quot;gb-lb-most-helpful-1wqxo9r&quot;&gt;Most helpful&lt;/h2&gt;&lt;p class=&quot;gb-leaderboard-caption&quot;&gt;By votes on their comments.&lt;/p&gt;&lt;ol class=&quot;gb-leaderboard-list&quot;&gt;&lt;li class=&quot;gb-leaderboard-row is-first&quot;&gt;&lt;a href=&quot;#portal&quot; class=&quot;gb-leaderboard-link&quot;&gt;&lt;span class=&quot;gb-leaderboard-rank&quot;&gt;&lt;span aria-hidden=&quot;true&quot;&gt;🥇&lt;/span&gt;&lt;span class=&quot;gb-sr-only&quot;&gt;Rank 1: &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gb-avatar gb-avatar--24&quot; data-tone=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;LN&lt;/span&gt;&lt;span class=&quot;gb-leaderboard-name&quot;&gt;Lucas Nguyen&lt;/span&gt;&lt;span class=&quot;gb-leaderboard-value&quot;&gt;163&lt;span class=&quot;gb-sr-only&quot;&gt; votes&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;&lt;li class=&quot;gb-leaderboard-row&quot;&gt;&lt;a href=&quot;#portal&quot; class=&quot;gb-leaderboard-link&quot;&gt;&lt;span class=&quot;gb-leaderboard-rank&quot;&gt;&lt;span aria-hidden=&quot;true&quot;&gt;🥈&lt;/span&gt;&lt;span class=&quot;gb-sr-only&quot;&gt;Rank 2: &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gb-avatar gb-avatar--24&quot; data-tone=&quot;0&quot; aria-hidden=&quot;true&quot;&gt;DC&lt;/span&gt;&lt;span class=&quot;gb-leaderboard-name&quot;&gt;Dima Chernyshov&lt;/span&gt;&lt;span class=&quot;gb-leaderboard-value&quot;&gt;56&lt;span class=&quot;gb-sr-only&quot;&gt; votes&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;&lt;li class=&quot;gb-leaderboard-row&quot;&gt;&lt;a href=&quot;#portal&quot; class=&quot;gb-leaderboard-link&quot;&gt;&lt;span class=&quot;gb-leaderboard-rank&quot;&gt;&lt;span aria-hidden=&quot;true&quot;&gt;🥉&lt;/span&gt;&lt;span class=&quot;gb-sr-only&quot;&gt;Rank 3: &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gb-avatar gb-avatar--24&quot; data-tone=&quot;5&quot; aria-hidden=&quot;true&quot;&gt;AR&lt;/span&gt;&lt;span class=&quot;gb-leaderboard-name&quot;&gt;Artjom&lt;/span&gt;&lt;span class=&quot;gb-leaderboard-value&quot;&gt;55&lt;span class=&quot;gb-sr-only&quot;&gt; votes&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;&lt;li class=&quot;gb-leaderboard-row&quot;&gt;&lt;a href=&quot;#portal&quot; class=&quot;gb-leaderboard-link&quot;&gt;&lt;span class=&quot;gb-leaderboard-rank is-number&quot;&gt;&lt;span aria-hidden=&quot;true&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;gb-sr-only&quot;&gt;Rank 4: &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gb-avatar gb-avatar--24&quot; data-tone=&quot;4&quot; aria-hidden=&quot;true&quot;&gt;GU&lt;/span&gt;&lt;span class=&quot;gb-leaderboard-name&quot;&gt;GutBrush&lt;/span&gt;&lt;span class=&quot;gb-leaderboard-value&quot;&gt;34&lt;span class=&quot;gb-sr-only&quot;&gt; votes&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;&lt;li class=&quot;gb-leaderboard-row&quot;&gt;&lt;a href=&quot;#portal&quot; class=&quot;gb-leaderboard-link&quot;&gt;&lt;span class=&quot;gb-leaderboard-rank is-number&quot;&gt;&lt;span aria-hidden=&quot;true&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;gb-sr-only&quot;&gt;Rank 5: &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gb-avatar gb-avatar--24&quot; data-tone=&quot;5&quot; aria-hidden=&quot;true&quot;&gt;WO&lt;/span&gt;&lt;span class=&quot;gb-leaderboard-name&quot;&gt;Wondercraft&lt;/span&gt;&lt;span class=&quot;gb-leaderboard-value&quot;&gt;30&lt;span class=&quot;gb-sr-only&quot;&gt; votes&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/section&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/body&gt;&lt;/html&gt;"></iframe><details class="cat-code"><summary>Markup</summary><pre><code>&lt;div class=&quot;gemboss-platform-shell&quot;&gt;
875
875
  &lt;header class=&quot;gemboss-platform-topbar&quot;&gt;
876
876
  &lt;div class=&quot;gemboss-topbar-start&quot;&gt;
877
877
  &lt;a class=&quot;gb-brand&quot; href=&quot;/&quot; aria-label=&quot;GemFeedback home&quot;&gt;
@@ -967,11 +967,11 @@ body{margin:0;background:var(--gemboss-app-bg,#f1f1f1);color:var(--gemboss-text)
967
967
  &lt;a href=&quot;#portal&quot; class=&quot;gb-leaderboard-link&quot;&gt;
968
968
  &lt;span class=&quot;gb-leaderboard-rank&quot;&gt;
969
969
  &lt;span aria-hidden=&quot;true&quot;&gt;🥇&lt;/span&gt;
970
- &lt;span class=&quot;ui-sr-only&quot;&gt;Rank 1: &lt;/span&gt;
970
+ &lt;span class=&quot;gb-sr-only&quot;&gt;Rank 1: &lt;/span&gt;
971
971
  &lt;/span&gt;
972
972
  &lt;span class=&quot;gb-avatar gb-avatar--24&quot; data-tone=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;LN&lt;/span&gt;
973
973
  &lt;span class=&quot;gb-leaderboard-name&quot;&gt;Lucas Nguyen&lt;/span&gt;
974
- &lt;span class=&quot;gb-leaderboard-value&quot;&gt;163&lt;span class=&quot;ui-sr-only&quot;&gt; votes&lt;/span&gt;
974
+ &lt;span class=&quot;gb-leaderboard-value&quot;&gt;163&lt;span class=&quot;gb-sr-only&quot;&gt; votes&lt;/span&gt;
975
975
  &lt;/span&gt;
976
976
  &lt;/a&gt;
977
977
  &lt;/li&gt;
@@ -979,11 +979,11 @@ body{margin:0;background:var(--gemboss-app-bg,#f1f1f1);color:var(--gemboss-text)
979
979
  &lt;a href=&quot;#portal&quot; class=&quot;gb-leaderboard-link&quot;&gt;
980
980
  &lt;span class=&quot;gb-leaderboard-rank&quot;&gt;
981
981
  &lt;span aria-hidden=&quot;true&quot;&gt;🥈&lt;/span&gt;
982
- &lt;span class=&quot;ui-sr-only&quot;&gt;Rank 2: &lt;/span&gt;
982
+ &lt;span class=&quot;gb-sr-only&quot;&gt;Rank 2: &lt;/span&gt;
983
983
  &lt;/span&gt;
984
984
  &lt;span class=&quot;gb-avatar gb-avatar--24&quot; data-tone=&quot;0&quot; aria-hidden=&quot;true&quot;&gt;DC&lt;/span&gt;
985
985
  &lt;span class=&quot;gb-leaderboard-name&quot;&gt;Dima Chernyshov&lt;/span&gt;
986
- &lt;span class=&quot;gb-leaderboard-value&quot;&gt;56&lt;span class=&quot;ui-sr-only&quot;&gt; votes&lt;/span&gt;
986
+ &lt;span class=&quot;gb-leaderboard-value&quot;&gt;56&lt;span class=&quot;gb-sr-only&quot;&gt; votes&lt;/span&gt;
987
987
  &lt;/span&gt;
988
988
  &lt;/a&gt;
989
989
  &lt;/li&gt;
@@ -991,11 +991,11 @@ body{margin:0;background:var(--gemboss-app-bg,#f1f1f1);color:var(--gemboss-text)
991
991
  &lt;a href=&quot;#portal&quot; class=&quot;gb-leaderboard-link&quot;&gt;
992
992
  &lt;span class=&quot;gb-leaderboard-rank&quot;&gt;
993
993
  &lt;span aria-hidden=&quot;true&quot;&gt;🥉&lt;/span&gt;
994
- &lt;span class=&quot;ui-sr-only&quot;&gt;Rank 3: &lt;/span&gt;
994
+ &lt;span class=&quot;gb-sr-only&quot;&gt;Rank 3: &lt;/span&gt;
995
995
  &lt;/span&gt;
996
996
  &lt;span class=&quot;gb-avatar gb-avatar--24&quot; data-tone=&quot;5&quot; aria-hidden=&quot;true&quot;&gt;AR&lt;/span&gt;
997
997
  &lt;span class=&quot;gb-leaderboard-name&quot;&gt;Artjom&lt;/span&gt;
998
- &lt;span class=&quot;gb-leaderboard-value&quot;&gt;55&lt;span class=&quot;ui-sr-only&quot;&gt; votes&lt;/span&gt;
998
+ &lt;span class=&quot;gb-leaderboard-value&quot;&gt;55&lt;span class=&quot;gb-sr-only&quot;&gt; votes&lt;/span&gt;
999
999
  &lt;/span&gt;
1000
1000
  &lt;/a&gt;
1001
1001
  &lt;/li&gt;
@@ -1003,11 +1003,11 @@ body{margin:0;background:var(--gemboss-app-bg,#f1f1f1);color:var(--gemboss-text)
1003
1003
  &lt;a href=&quot;#portal&quot; class=&quot;gb-leaderboard-link&quot;&gt;
1004
1004
  &lt;span class=&quot;gb-leaderboard-rank is-number&quot;&gt;
1005
1005
  &lt;span aria-hidden=&quot;true&quot;&gt;4&lt;/span&gt;
1006
- &lt;span class=&quot;ui-sr-only&quot;&gt;Rank 4: &lt;/span&gt;
1006
+ &lt;span class=&quot;gb-sr-only&quot;&gt;Rank 4: &lt;/span&gt;
1007
1007
  &lt;/span&gt;
1008
1008
  &lt;span class=&quot;gb-avatar gb-avatar--24&quot; data-tone=&quot;4&quot; aria-hidden=&quot;true&quot;&gt;GU&lt;/span&gt;
1009
1009
  &lt;span class=&quot;gb-leaderboard-name&quot;&gt;GutBrush&lt;/span&gt;
1010
- &lt;span class=&quot;gb-leaderboard-value&quot;&gt;34&lt;span class=&quot;ui-sr-only&quot;&gt; votes&lt;/span&gt;
1010
+ &lt;span class=&quot;gb-leaderboard-value&quot;&gt;34&lt;span class=&quot;gb-sr-only&quot;&gt; votes&lt;/span&gt;
1011
1011
  &lt;/span&gt;
1012
1012
  &lt;/a&gt;
1013
1013
  &lt;/li&gt;
@@ -1015,11 +1015,11 @@ body{margin:0;background:var(--gemboss-app-bg,#f1f1f1);color:var(--gemboss-text)
1015
1015
  &lt;a href=&quot;#portal&quot; class=&quot;gb-leaderboard-link&quot;&gt;
1016
1016
  &lt;span class=&quot;gb-leaderboard-rank is-number&quot;&gt;
1017
1017
  &lt;span aria-hidden=&quot;true&quot;&gt;5&lt;/span&gt;
1018
- &lt;span class=&quot;ui-sr-only&quot;&gt;Rank 5: &lt;/span&gt;
1018
+ &lt;span class=&quot;gb-sr-only&quot;&gt;Rank 5: &lt;/span&gt;
1019
1019
  &lt;/span&gt;
1020
1020
  &lt;span class=&quot;gb-avatar gb-avatar--24&quot; data-tone=&quot;5&quot; aria-hidden=&quot;true&quot;&gt;WO&lt;/span&gt;
1021
1021
  &lt;span class=&quot;gb-leaderboard-name&quot;&gt;Wondercraft&lt;/span&gt;
1022
- &lt;span class=&quot;gb-leaderboard-value&quot;&gt;30&lt;span class=&quot;ui-sr-only&quot;&gt; votes&lt;/span&gt;
1022
+ &lt;span class=&quot;gb-leaderboard-value&quot;&gt;30&lt;span class=&quot;gb-sr-only&quot;&gt; votes&lt;/span&gt;
1023
1023
  &lt;/span&gt;
1024
1024
  &lt;/a&gt;
1025
1025
  &lt;/li&gt;
@@ -1033,14 +1033,14 @@ body{margin:0;background:var(--gemboss-app-bg,#f1f1f1);color:var(--gemboss-text)
1033
1033
  &lt;span class=&quot;gb-avatar gb-avatar--40&quot; data-tone=&quot;0&quot; aria-hidden=&quot;true&quot;&gt;GT&lt;/span&gt;
1034
1034
  &lt;span class=&quot;gb-avatar gb-avatar--56&quot; data-tone=&quot;1&quot; aria-hidden=&quot;true&quot;&gt;LA&lt;/span&gt;
1035
1035
  &lt;span class=&quot;gb-avatar gb-avatar--40&quot; data-tone=&quot;0&quot; aria-hidden=&quot;true&quot;&gt;BA&lt;/span&gt;
1036
- &lt;/div&gt;</code></pre></details></figure><figure class="cat-demo"><figcaption>Leaderboard: huy chương 1–3, rồi thứ hạng; số của người đầu màu vàng</figcaption><div class="cat-live"><section class="gb-leaderboard" aria-labelledby="gb-lb-top-contributors-1tvkcn7"><h2 class="gb-leaderboard-title" id="gb-lb-top-contributors-1tvkcn7">Top contributors</h2><ol class="gb-leaderboard-list"><li class="gb-leaderboard-row is-first"><a href="#portal" class="gb-leaderboard-link"><span class="gb-leaderboard-rank"><span aria-hidden="true">🥇</span><span class="ui-sr-only">Rank 1: </span></span><span class="gb-avatar gb-avatar--24" data-tone="2" aria-hidden="true">LN</span><span class="gb-leaderboard-name">Lucas Nguyen</span><span class="gb-leaderboard-value">163</span></a></li><li class="gb-leaderboard-row"><a href="#portal" class="gb-leaderboard-link"><span class="gb-leaderboard-rank"><span aria-hidden="true">🥈</span><span class="ui-sr-only">Rank 2: </span></span><span class="gb-avatar gb-avatar--24" data-tone="0" aria-hidden="true">DC</span><span class="gb-leaderboard-name">Dima Chernyshov</span><span class="gb-leaderboard-value">56</span></a></li><li class="gb-leaderboard-row"><a href="#portal" class="gb-leaderboard-link"><span class="gb-leaderboard-rank"><span aria-hidden="true">🥉</span><span class="ui-sr-only">Rank 3: </span></span><span class="gb-avatar gb-avatar--24" data-tone="5" aria-hidden="true">AR</span><span class="gb-leaderboard-name">Artjom</span><span class="gb-leaderboard-value">55</span></a></li><li class="gb-leaderboard-row"><a href="#portal" class="gb-leaderboard-link"><span class="gb-leaderboard-rank is-number"><span aria-hidden="true">4</span><span class="ui-sr-only">Rank 4: </span></span><span class="gb-avatar gb-avatar--24" data-tone="4" aria-hidden="true">GU</span><span class="gb-leaderboard-name">GutBrush</span><span class="gb-leaderboard-value">34</span></a></li><li class="gb-leaderboard-row"><a href="#portal" class="gb-leaderboard-link"><span class="gb-leaderboard-rank is-number"><span aria-hidden="true">5</span><span class="ui-sr-only">Rank 5: </span></span><span class="gb-avatar gb-avatar--24" data-tone="5" aria-hidden="true">WO</span><span class="gb-leaderboard-name">Wondercraft</span><span class="gb-leaderboard-value">30</span></a></li></ol><a href="#portal" class="gb-leaderboard-all">View all</a></section></div><details class="cat-code"><summary>Markup</summary><pre><code>&lt;section class=&quot;gb-leaderboard&quot; aria-labelledby=&quot;gb-lb-top-contributors-1tvkcn7&quot;&gt;
1036
+ &lt;/div&gt;</code></pre></details></figure><figure class="cat-demo"><figcaption>Leaderboard: huy chương 1–3, rồi thứ hạng; số của người đầu màu vàng</figcaption><div class="cat-live"><section class="gb-leaderboard" aria-labelledby="gb-lb-top-contributors-1tvkcn7"><h2 class="gb-leaderboard-title" id="gb-lb-top-contributors-1tvkcn7">Top contributors</h2><ol class="gb-leaderboard-list"><li class="gb-leaderboard-row is-first"><a href="#portal" class="gb-leaderboard-link"><span class="gb-leaderboard-rank"><span aria-hidden="true">🥇</span><span class="gb-sr-only">Rank 1: </span></span><span class="gb-avatar gb-avatar--24" data-tone="2" aria-hidden="true">LN</span><span class="gb-leaderboard-name">Lucas Nguyen</span><span class="gb-leaderboard-value">163</span></a></li><li class="gb-leaderboard-row"><a href="#portal" class="gb-leaderboard-link"><span class="gb-leaderboard-rank"><span aria-hidden="true">🥈</span><span class="gb-sr-only">Rank 2: </span></span><span class="gb-avatar gb-avatar--24" data-tone="0" aria-hidden="true">DC</span><span class="gb-leaderboard-name">Dima Chernyshov</span><span class="gb-leaderboard-value">56</span></a></li><li class="gb-leaderboard-row"><a href="#portal" class="gb-leaderboard-link"><span class="gb-leaderboard-rank"><span aria-hidden="true">🥉</span><span class="gb-sr-only">Rank 3: </span></span><span class="gb-avatar gb-avatar--24" data-tone="5" aria-hidden="true">AR</span><span class="gb-leaderboard-name">Artjom</span><span class="gb-leaderboard-value">55</span></a></li><li class="gb-leaderboard-row"><a href="#portal" class="gb-leaderboard-link"><span class="gb-leaderboard-rank is-number"><span aria-hidden="true">4</span><span class="gb-sr-only">Rank 4: </span></span><span class="gb-avatar gb-avatar--24" data-tone="4" aria-hidden="true">GU</span><span class="gb-leaderboard-name">GutBrush</span><span class="gb-leaderboard-value">34</span></a></li><li class="gb-leaderboard-row"><a href="#portal" class="gb-leaderboard-link"><span class="gb-leaderboard-rank is-number"><span aria-hidden="true">5</span><span class="gb-sr-only">Rank 5: </span></span><span class="gb-avatar gb-avatar--24" data-tone="5" aria-hidden="true">WO</span><span class="gb-leaderboard-name">Wondercraft</span><span class="gb-leaderboard-value">30</span></a></li></ol><a href="#portal" class="gb-leaderboard-all">View all</a></section></div><details class="cat-code"><summary>Markup</summary><pre><code>&lt;section class=&quot;gb-leaderboard&quot; aria-labelledby=&quot;gb-lb-top-contributors-1tvkcn7&quot;&gt;
1037
1037
  &lt;h2 class=&quot;gb-leaderboard-title&quot; id=&quot;gb-lb-top-contributors-1tvkcn7&quot;&gt;Top contributors&lt;/h2&gt;
1038
1038
  &lt;ol class=&quot;gb-leaderboard-list&quot;&gt;
1039
1039
  &lt;li class=&quot;gb-leaderboard-row is-first&quot;&gt;
1040
1040
  &lt;a href=&quot;#portal&quot; class=&quot;gb-leaderboard-link&quot;&gt;
1041
1041
  &lt;span class=&quot;gb-leaderboard-rank&quot;&gt;
1042
1042
  &lt;span aria-hidden=&quot;true&quot;&gt;🥇&lt;/span&gt;
1043
- &lt;span class=&quot;ui-sr-only&quot;&gt;Rank 1: &lt;/span&gt;
1043
+ &lt;span class=&quot;gb-sr-only&quot;&gt;Rank 1: &lt;/span&gt;
1044
1044
  &lt;/span&gt;
1045
1045
  &lt;span class=&quot;gb-avatar gb-avatar--24&quot; data-tone=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;LN&lt;/span&gt;
1046
1046
  &lt;span class=&quot;gb-leaderboard-name&quot;&gt;Lucas Nguyen&lt;/span&gt;
@@ -1051,7 +1051,7 @@ body{margin:0;background:var(--gemboss-app-bg,#f1f1f1);color:var(--gemboss-text)
1051
1051
  &lt;a href=&quot;#portal&quot; class=&quot;gb-leaderboard-link&quot;&gt;
1052
1052
  &lt;span class=&quot;gb-leaderboard-rank&quot;&gt;
1053
1053
  &lt;span aria-hidden=&quot;true&quot;&gt;🥈&lt;/span&gt;
1054
- &lt;span class=&quot;ui-sr-only&quot;&gt;Rank 2: &lt;/span&gt;
1054
+ &lt;span class=&quot;gb-sr-only&quot;&gt;Rank 2: &lt;/span&gt;
1055
1055
  &lt;/span&gt;
1056
1056
  &lt;span class=&quot;gb-avatar gb-avatar--24&quot; data-tone=&quot;0&quot; aria-hidden=&quot;true&quot;&gt;DC&lt;/span&gt;
1057
1057
  &lt;span class=&quot;gb-leaderboard-name&quot;&gt;Dima Chernyshov&lt;/span&gt;
@@ -1062,7 +1062,7 @@ body{margin:0;background:var(--gemboss-app-bg,#f1f1f1);color:var(--gemboss-text)
1062
1062
  &lt;a href=&quot;#portal&quot; class=&quot;gb-leaderboard-link&quot;&gt;
1063
1063
  &lt;span class=&quot;gb-leaderboard-rank&quot;&gt;
1064
1064
  &lt;span aria-hidden=&quot;true&quot;&gt;🥉&lt;/span&gt;
1065
- &lt;span class=&quot;ui-sr-only&quot;&gt;Rank 3: &lt;/span&gt;
1065
+ &lt;span class=&quot;gb-sr-only&quot;&gt;Rank 3: &lt;/span&gt;
1066
1066
  &lt;/span&gt;
1067
1067
  &lt;span class=&quot;gb-avatar gb-avatar--24&quot; data-tone=&quot;5&quot; aria-hidden=&quot;true&quot;&gt;AR&lt;/span&gt;
1068
1068
  &lt;span class=&quot;gb-leaderboard-name&quot;&gt;Artjom&lt;/span&gt;
@@ -1073,7 +1073,7 @@ body{margin:0;background:var(--gemboss-app-bg,#f1f1f1);color:var(--gemboss-text)
1073
1073
  &lt;a href=&quot;#portal&quot; class=&quot;gb-leaderboard-link&quot;&gt;
1074
1074
  &lt;span class=&quot;gb-leaderboard-rank is-number&quot;&gt;
1075
1075
  &lt;span aria-hidden=&quot;true&quot;&gt;4&lt;/span&gt;
1076
- &lt;span class=&quot;ui-sr-only&quot;&gt;Rank 4: &lt;/span&gt;
1076
+ &lt;span class=&quot;gb-sr-only&quot;&gt;Rank 4: &lt;/span&gt;
1077
1077
  &lt;/span&gt;
1078
1078
  &lt;span class=&quot;gb-avatar gb-avatar--24&quot; data-tone=&quot;4&quot; aria-hidden=&quot;true&quot;&gt;GU&lt;/span&gt;
1079
1079
  &lt;span class=&quot;gb-leaderboard-name&quot;&gt;GutBrush&lt;/span&gt;
@@ -1084,7 +1084,7 @@ body{margin:0;background:var(--gemboss-app-bg,#f1f1f1);color:var(--gemboss-text)
1084
1084
  &lt;a href=&quot;#portal&quot; class=&quot;gb-leaderboard-link&quot;&gt;
1085
1085
  &lt;span class=&quot;gb-leaderboard-rank is-number&quot;&gt;
1086
1086
  &lt;span aria-hidden=&quot;true&quot;&gt;5&lt;/span&gt;
1087
- &lt;span class=&quot;ui-sr-only&quot;&gt;Rank 5: &lt;/span&gt;
1087
+ &lt;span class=&quot;gb-sr-only&quot;&gt;Rank 5: &lt;/span&gt;
1088
1088
  &lt;/span&gt;
1089
1089
  &lt;span class=&quot;gb-avatar gb-avatar--24&quot; data-tone=&quot;5&quot; aria-hidden=&quot;true&quot;&gt;WO&lt;/span&gt;
1090
1090
  &lt;span class=&quot;gb-leaderboard-name&quot;&gt;Wondercraft&lt;/span&gt;
@@ -1093,12 +1093,12 @@ body{margin:0;background:var(--gemboss-app-bg,#f1f1f1);color:var(--gemboss-text)
1093
1093
  &lt;/li&gt;
1094
1094
  &lt;/ol&gt;
1095
1095
  &lt;a href=&quot;#portal&quot; class=&quot;gb-leaderboard-all&quot;&gt;View all&lt;/a&gt;
1096
- &lt;/section&gt;</code></pre></details></figure><figure class="cat-demo"><figcaption>Podium: nhì · nhất · ba</figcaption><div class="cat-live"><ol class="gb-podium" aria-label="Top three"><li class="gb-podium-slot gb-podium-slot--2"><a href="#portal" class="gb-podium-link"><span class="gb-podium-medal"><span aria-hidden="true">🥈</span><span class="ui-sr-only">Rank 2: </span></span><span class="gb-avatar gb-avatar--56" data-tone="0" aria-hidden="true">DC</span><span class="gb-podium-name">Dima Chernyshov</span><span class="gb-podium-value">56<span class="gb-podium-unit"> pts</span></span></a></li><li class="gb-podium-slot gb-podium-slot--1"><a href="#portal" class="gb-podium-link"><span class="gb-podium-medal"><span aria-hidden="true">🥇</span><span class="ui-sr-only">Rank 1: </span></span><span class="gb-avatar gb-avatar--56" data-tone="2" aria-hidden="true">LN</span><span class="gb-podium-name">Lucas Nguyen</span><span class="gb-podium-value">163<span class="gb-podium-unit"> pts</span></span></a></li><li class="gb-podium-slot gb-podium-slot--3"><a href="#portal" class="gb-podium-link"><span class="gb-podium-medal"><span aria-hidden="true">🥉</span><span class="ui-sr-only">Rank 3: </span></span><span class="gb-avatar gb-avatar--56" data-tone="5" aria-hidden="true">AR</span><span class="gb-podium-name">Artjom</span><span class="gb-podium-value">55<span class="gb-podium-unit"> pts</span></span></a></li></ol></div><details class="cat-code"><summary>Markup</summary><pre><code>&lt;ol class=&quot;gb-podium&quot; aria-label=&quot;Top three&quot;&gt;
1096
+ &lt;/section&gt;</code></pre></details></figure><figure class="cat-demo"><figcaption>Podium: nhì · nhất · ba</figcaption><div class="cat-live"><ol class="gb-podium" aria-label="Top three"><li class="gb-podium-slot gb-podium-slot--2"><a href="#portal" class="gb-podium-link"><span class="gb-podium-medal"><span aria-hidden="true">🥈</span><span class="gb-sr-only">Rank 2: </span></span><span class="gb-avatar gb-avatar--56" data-tone="0" aria-hidden="true">DC</span><span class="gb-podium-name">Dima Chernyshov</span><span class="gb-podium-value">56<span class="gb-podium-unit"> pts</span></span></a></li><li class="gb-podium-slot gb-podium-slot--1"><a href="#portal" class="gb-podium-link"><span class="gb-podium-medal"><span aria-hidden="true">🥇</span><span class="gb-sr-only">Rank 1: </span></span><span class="gb-avatar gb-avatar--56" data-tone="2" aria-hidden="true">LN</span><span class="gb-podium-name">Lucas Nguyen</span><span class="gb-podium-value">163<span class="gb-podium-unit"> pts</span></span></a></li><li class="gb-podium-slot gb-podium-slot--3"><a href="#portal" class="gb-podium-link"><span class="gb-podium-medal"><span aria-hidden="true">🥉</span><span class="gb-sr-only">Rank 3: </span></span><span class="gb-avatar gb-avatar--56" data-tone="5" aria-hidden="true">AR</span><span class="gb-podium-name">Artjom</span><span class="gb-podium-value">55<span class="gb-podium-unit"> pts</span></span></a></li></ol></div><details class="cat-code"><summary>Markup</summary><pre><code>&lt;ol class=&quot;gb-podium&quot; aria-label=&quot;Top three&quot;&gt;
1097
1097
  &lt;li class=&quot;gb-podium-slot gb-podium-slot--2&quot;&gt;
1098
1098
  &lt;a href=&quot;#portal&quot; class=&quot;gb-podium-link&quot;&gt;
1099
1099
  &lt;span class=&quot;gb-podium-medal&quot;&gt;
1100
1100
  &lt;span aria-hidden=&quot;true&quot;&gt;🥈&lt;/span&gt;
1101
- &lt;span class=&quot;ui-sr-only&quot;&gt;Rank 2: &lt;/span&gt;
1101
+ &lt;span class=&quot;gb-sr-only&quot;&gt;Rank 2: &lt;/span&gt;
1102
1102
  &lt;/span&gt;
1103
1103
  &lt;span class=&quot;gb-avatar gb-avatar--56&quot; data-tone=&quot;0&quot; aria-hidden=&quot;true&quot;&gt;DC&lt;/span&gt;
1104
1104
  &lt;span class=&quot;gb-podium-name&quot;&gt;Dima Chernyshov&lt;/span&gt;
@@ -1110,7 +1110,7 @@ body{margin:0;background:var(--gemboss-app-bg,#f1f1f1);color:var(--gemboss-text)
1110
1110
  &lt;a href=&quot;#portal&quot; class=&quot;gb-podium-link&quot;&gt;
1111
1111
  &lt;span class=&quot;gb-podium-medal&quot;&gt;
1112
1112
  &lt;span aria-hidden=&quot;true&quot;&gt;🥇&lt;/span&gt;
1113
- &lt;span class=&quot;ui-sr-only&quot;&gt;Rank 1: &lt;/span&gt;
1113
+ &lt;span class=&quot;gb-sr-only&quot;&gt;Rank 1: &lt;/span&gt;
1114
1114
  &lt;/span&gt;
1115
1115
  &lt;span class=&quot;gb-avatar gb-avatar--56&quot; data-tone=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;LN&lt;/span&gt;
1116
1116
  &lt;span class=&quot;gb-podium-name&quot;&gt;Lucas Nguyen&lt;/span&gt;
@@ -1122,7 +1122,7 @@ body{margin:0;background:var(--gemboss-app-bg,#f1f1f1);color:var(--gemboss-text)
1122
1122
  &lt;a href=&quot;#portal&quot; class=&quot;gb-podium-link&quot;&gt;
1123
1123
  &lt;span class=&quot;gb-podium-medal&quot;&gt;
1124
1124
  &lt;span aria-hidden=&quot;true&quot;&gt;🥉&lt;/span&gt;
1125
- &lt;span class=&quot;ui-sr-only&quot;&gt;Rank 3: &lt;/span&gt;
1125
+ &lt;span class=&quot;gb-sr-only&quot;&gt;Rank 3: &lt;/span&gt;
1126
1126
  &lt;/span&gt;
1127
1127
  &lt;span class=&quot;gb-avatar gb-avatar--56&quot; data-tone=&quot;5&quot; aria-hidden=&quot;true&quot;&gt;AR&lt;/span&gt;
1128
1128
  &lt;span class=&quot;gb-podium-name&quot;&gt;Artjom&lt;/span&gt;
package/gemboss-ui.css CHANGED
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  * GemBoss admin design system — GENERATED — do not edit; regenerate from gemboss:
3
3
  * node apps/admin/scripts/export-ui-css.mjs --out <path> (npm run export:ui-css)
4
- * gemboss commit: fef56e0d93ce96cce6e59613fc62f8f68a739cd2
4
+ * gemboss commit: e66ca212d292e091348613340ba69cff77c159fc
5
5
  * sources sha256: 518302cf7e7a5abd3c1c2157f2b0993b9578c9e030d25ee90cd5ef36b898eec2
6
6
  * contents: 1 allow-listed rule from apps/admin/src/app/globals.css + packages/ui/src/gemboss-tokens.css
7
7
  * (verbatim) + packages/ui/src/ui.css (verbatim) + packages/ui/src/gemboss-field.css (verbatim)
@@ -4299,9 +4299,9 @@ button.ui-metric:focus-visible { outline: 2px solid var(--ui-focus); outline-off
4299
4299
 
4300
4300
  /* ═══ @gemboss/ui src/portal.css ═══ */
4301
4301
  /* ═══ Portal pieces — @gemboss/ui 0.7.0 (04/10/2026) ════════════════════════════════════════════
4302
- TopbarNav, Avatar, Leaderboard, Podium (portal.tsx), SearchDialog (dialog.tsx), ThemeToggle and the
4303
- dark palette (theme.tsx). Tokens only: every colour comes from --gemboss-* / --ui-*, so the dark
4304
- palette at the end reaches these too. */
4302
+ TopbarNav, Avatar, Leaderboard, Podium (portal.tsx), SearchDialog (dialog.tsx), ThemeToggle (theme.tsx).
4303
+ Component rules only, no rule on :root, html or body (a test holds that): a surface with its own skin
4304
+ can take this file with gemboss-tokens.css alone. The dark palette is theme-dark.css. */
4305
4305
 
4306
4306
  /* ── TopbarNav: section tabs in the topbar, after the brand (Featurebase's "Feedback · Roadmap"). The
4307
4307
  active tab is underlined on the topbar's bottom edge. 44px targets under a finger, 36 under a mouse
@@ -4347,6 +4347,11 @@ button.ui-metric:focus-visible { outline: 2px solid var(--ui-focus); outline-off
4347
4347
  }
4348
4348
  @media (prefers-reduced-motion: reduce) { .gb-topnav-chevron { transition: none; } }
4349
4349
 
4350
+ /* Text for screen readers only ("Rank 1:", ", you"). Its own rule, not ui.css's .ui-sr-only: a surface that
4351
+ takes portal.css without the rest of the kit (GemCommunity) would otherwise print it on the page. */
4352
+ .gb-sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0);
4353
+ white-space: nowrap; border: 0; }
4354
+
4350
4355
  /* ── Avatar: picture or initials on one of eight tones picked from the name. */
4351
4356
  .gb-avatar { display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; border-radius: 50%; overflow: hidden;
4352
4357
  font-weight: 700; line-height: 1; letter-spacing: .01em; user-select: none; }
@@ -4383,6 +4388,9 @@ a.gb-leaderboard-link:focus-visible { outline: 2px solid var(--gemboss-accent);
4383
4388
  .gb-leaderboard-name { flex: 1 1 auto; min-width: 0; font-size: 13px; font-weight: 560; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
4384
4389
  .gb-leaderboard-value { flex: 0 0 auto; font-size: 13px; font-weight: 650; color: var(--gemboss-text-muted); font-variant-numeric: tabular-nums; }
4385
4390
  .gb-leaderboard-row.is-first .gb-leaderboard-value { color: #8a5a00; font-weight: 750; }
4391
+ /* The viewer's own row and podium slot: the selected tint, never a colour of its own. */
4392
+ .gb-leaderboard-row.is-current > .gb-leaderboard-link { background: var(--gemboss-active-bg); }
4393
+ .gb-leaderboard-badge { flex: 0 1 auto; min-width: 0; overflow: hidden; }
4386
4394
  .gb-leaderboard-all { justify-self: center; display: inline-flex; align-items: center; min-height: 24px; font-size: 12px; font-weight: 600;
4387
4395
  color: var(--gemboss-text-muted); text-decoration: none; }
4388
4396
  .gb-leaderboard-all:hover { color: var(--gemboss-text-strong); text-decoration: underline; }
@@ -4393,6 +4401,8 @@ a.gb-leaderboard-link:focus-visible { outline: 2px solid var(--gemboss-accent);
4393
4401
  background: var(--gemboss-surface); color: var(--gemboss-text); text-decoration: none; text-align: center; }
4394
4402
  a.gb-podium-link:hover { background: var(--gemboss-hover); }
4395
4403
  .gb-podium-slot { min-width: 0; }
4404
+ /* A podium with fewer than three people keeps its place: second and third stay empty columns. */
4405
+ .gb-podium-slot.is-empty { visibility: hidden; }
4396
4406
  .gb-podium-slot--1 .gb-podium-link { padding-top: 22px; padding-bottom: 20px; border-color: color-mix(in srgb, #d4a017 45%, var(--gemboss-divider)); }
4397
4407
  .gb-podium-slot--2 .gb-podium-link { padding-bottom: 12px; }
4398
4408
  .gb-podium-slot--3 .gb-podium-link { padding-bottom: 8px; }
@@ -4401,6 +4411,7 @@ a.gb-podium-link:hover { background: var(--gemboss-hover); }
4401
4411
  .gb-podium-value { font-size: 15px; font-weight: 750; font-variant-numeric: tabular-nums; }
4402
4412
  .gb-podium-slot--1 .gb-podium-value { color: #8a5a00; }
4403
4413
  .gb-podium-unit { font-size: 11px; font-weight: 500; color: var(--gemboss-text-muted); }
4414
+ .gb-podium-slot.is-current .gb-podium-link { border-color: var(--gemboss-text-strong); background: var(--gemboss-active-bg); }
4404
4415
 
4405
4416
  /* ── SearchDialog: the topbar's search button, and the popup (640 wide, near the top, like Featurebase's). */
4406
4417
  .gb-search-trigger, .gb-theme-toggle { display: inline-flex; align-items: center; justify-content: center; width: 36px; height: 36px; flex: 0 0 auto;
@@ -4427,7 +4438,15 @@ dialog.ui-modal.gb-search { width: min(640px, 100%); margin-top: 8vh; max-height
4427
4438
  font-size: 12px; color: var(--ui-text-muted); }
4428
4439
  @media (max-width: 760px) { dialog.ui-modal.gb-search { margin-top: 12px; } .gb-search-foot { display: none; } }
4429
4440
 
4430
- /* ── Dark palette. `ThemeToggle` / `themeScript` set data-theme on <html>; a surface without them stays
4441
+ /* ═══ @gemboss/ui src/theme-dark.css ═══ */
4442
+ /* ═══ Dark palette — @gemboss/ui 0.7.2 ═══════════════════════════════════════════════════════════════
4443
+ Split out of portal.css (04/10/2026). `ThemeToggle` / `themeScript` set data-theme on <html>, and this
4444
+ file turns every --gemboss-* colour dark under it. It lives apart so that a surface which takes only
4445
+ the leaderboard (gemboss-tokens.css + portal.css) does not inherit it: GemCommunity sets
4446
+ data-theme="dark" for its own sign-in pages and remembers it, and the rule
4447
+ `:root[data-theme="dark"] body` here outranks its body rule, so a member who once picked dark there
4448
+ would get a dark page behind light cards. gemboss-ui.css still carries this file. */
4449
+ /* Dark palette. `ThemeToggle` / `themeScript` set data-theme on <html>; a surface without them stays
4431
4450
  light. Only colours change: the components above and every kit class read these tokens. */
4432
4451
  :root[data-theme="dark"] {
4433
4452
  color-scheme: dark;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gemboss/ui",
3
- "version": "0.7.1",
3
+ "version": "0.7.2",
4
4
  "description": "GemBoss design system for every surface in the fleet: the admin shell (topbar + rail + drawer) as React components, and the admin stylesheet exported as one CSS file.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
@@ -26,6 +26,8 @@
26
26
  "./assistant": "./src/assistant/index.ts",
27
27
  "./assistant/dock": "./src/assistant/dock.ts",
28
28
  "./assistant.css": "./src/assistant.css",
29
+ "./portal.css": "./src/portal.css",
30
+ "./theme-dark.css": "./src/theme-dark.css",
29
31
  "./icon.svg": "./src/icon.svg"
30
32
  },
31
33
  "files": [
package/src/portal.css CHANGED
@@ -1,7 +1,7 @@
1
1
  /* ═══ Portal pieces — @gemboss/ui 0.7.0 (04/10/2026) ════════════════════════════════════════════
2
- TopbarNav, Avatar, Leaderboard, Podium (portal.tsx), SearchDialog (dialog.tsx), ThemeToggle and the
3
- dark palette (theme.tsx). Tokens only: every colour comes from --gemboss-* / --ui-*, so the dark
4
- palette at the end reaches these too. */
2
+ TopbarNav, Avatar, Leaderboard, Podium (portal.tsx), SearchDialog (dialog.tsx), ThemeToggle (theme.tsx).
3
+ Component rules only, no rule on :root, html or body (a test holds that): a surface with its own skin
4
+ can take this file with gemboss-tokens.css alone. The dark palette is theme-dark.css. */
5
5
 
6
6
  /* ── TopbarNav: section tabs in the topbar, after the brand (Featurebase's "Feedback · Roadmap"). The
7
7
  active tab is underlined on the topbar's bottom edge. 44px targets under a finger, 36 under a mouse
@@ -47,6 +47,11 @@
47
47
  }
48
48
  @media (prefers-reduced-motion: reduce) { .gb-topnav-chevron { transition: none; } }
49
49
 
50
+ /* Text for screen readers only ("Rank 1:", ", you"). Its own rule, not ui.css's .ui-sr-only: a surface that
51
+ takes portal.css without the rest of the kit (GemCommunity) would otherwise print it on the page. */
52
+ .gb-sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0);
53
+ white-space: nowrap; border: 0; }
54
+
50
55
  /* ── Avatar: picture or initials on one of eight tones picked from the name. */
51
56
  .gb-avatar { display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; border-radius: 50%; overflow: hidden;
52
57
  font-weight: 700; line-height: 1; letter-spacing: .01em; user-select: none; }
@@ -83,6 +88,9 @@ a.gb-leaderboard-link:focus-visible { outline: 2px solid var(--gemboss-accent);
83
88
  .gb-leaderboard-name { flex: 1 1 auto; min-width: 0; font-size: 13px; font-weight: 560; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
84
89
  .gb-leaderboard-value { flex: 0 0 auto; font-size: 13px; font-weight: 650; color: var(--gemboss-text-muted); font-variant-numeric: tabular-nums; }
85
90
  .gb-leaderboard-row.is-first .gb-leaderboard-value { color: #8a5a00; font-weight: 750; }
91
+ /* The viewer's own row and podium slot: the selected tint, never a colour of its own. */
92
+ .gb-leaderboard-row.is-current > .gb-leaderboard-link { background: var(--gemboss-active-bg); }
93
+ .gb-leaderboard-badge { flex: 0 1 auto; min-width: 0; overflow: hidden; }
86
94
  .gb-leaderboard-all { justify-self: center; display: inline-flex; align-items: center; min-height: 24px; font-size: 12px; font-weight: 600;
87
95
  color: var(--gemboss-text-muted); text-decoration: none; }
88
96
  .gb-leaderboard-all:hover { color: var(--gemboss-text-strong); text-decoration: underline; }
@@ -93,6 +101,8 @@ a.gb-leaderboard-link:focus-visible { outline: 2px solid var(--gemboss-accent);
93
101
  background: var(--gemboss-surface); color: var(--gemboss-text); text-decoration: none; text-align: center; }
94
102
  a.gb-podium-link:hover { background: var(--gemboss-hover); }
95
103
  .gb-podium-slot { min-width: 0; }
104
+ /* A podium with fewer than three people keeps its place: second and third stay empty columns. */
105
+ .gb-podium-slot.is-empty { visibility: hidden; }
96
106
  .gb-podium-slot--1 .gb-podium-link { padding-top: 22px; padding-bottom: 20px; border-color: color-mix(in srgb, #d4a017 45%, var(--gemboss-divider)); }
97
107
  .gb-podium-slot--2 .gb-podium-link { padding-bottom: 12px; }
98
108
  .gb-podium-slot--3 .gb-podium-link { padding-bottom: 8px; }
@@ -101,6 +111,7 @@ a.gb-podium-link:hover { background: var(--gemboss-hover); }
101
111
  .gb-podium-value { font-size: 15px; font-weight: 750; font-variant-numeric: tabular-nums; }
102
112
  .gb-podium-slot--1 .gb-podium-value { color: #8a5a00; }
103
113
  .gb-podium-unit { font-size: 11px; font-weight: 500; color: var(--gemboss-text-muted); }
114
+ .gb-podium-slot.is-current .gb-podium-link { border-color: var(--gemboss-text-strong); background: var(--gemboss-active-bg); }
104
115
 
105
116
  /* ── SearchDialog: the topbar's search button, and the popup (640 wide, near the top, like Featurebase's). */
106
117
  .gb-search-trigger, .gb-theme-toggle { display: inline-flex; align-items: center; justify-content: center; width: 36px; height: 36px; flex: 0 0 auto;
@@ -126,62 +137,3 @@ dialog.ui-modal.gb-search { width: min(640px, 100%); margin-top: 8vh; max-height
126
137
  .gb-search-foot { display: flex; gap: 16px; justify-content: flex-end; padding: 8px 14px; border-top: 1px solid var(--ui-border);
127
138
  font-size: 12px; color: var(--ui-text-muted); }
128
139
  @media (max-width: 760px) { dialog.ui-modal.gb-search { margin-top: 12px; } .gb-search-foot { display: none; } }
129
-
130
- /* ── Dark palette. `ThemeToggle` / `themeScript` set data-theme on <html>; a surface without them stays
131
- light. Only colours change: the components above and every kit class read these tokens. */
132
- :root[data-theme="dark"] {
133
- color-scheme: dark;
134
- --gemboss-primary: #f2f3f5;
135
- --gemboss-primary-dark: #ffffff;
136
- --gemboss-primary-soft: #23242a;
137
- --gemboss-on-primary: #0d0d12;
138
- --gemboss-accent: #7c84ff;
139
- --gemboss-accent-strong: #a3a9ff;
140
- --gemboss-accent-soft: #1f2140;
141
- --gemboss-text-strong: #f2f3f5;
142
- --gemboss-text: #e3e4e8;
143
- --gemboss-text-muted: #9a9ca6;
144
- --gemboss-surface: #16171d;
145
- --gemboss-canvas: #0d0d12;
146
- --gemboss-app-bg: #0d0d12;
147
- --gemboss-rail-bg: #0d0d12;
148
- --gemboss-panel-bg: #16171d;
149
- --gemboss-topbar-bg: rgba(13, 13, 18, 0.96);
150
- --gemboss-nav-bg: #0d0d12;
151
- --gemboss-nav-hover: rgba(255, 255, 255, 0.06);
152
- --gemboss-divider: #2a2b33;
153
- --gemboss-divider-soft: #22232a;
154
- --gemboss-hover: #22232b;
155
- --gemboss-active-bg: #262833;
156
- --gemboss-active-fg: #f2f3f5;
157
- --gemboss-field-bg: #121318;
158
- --gemboss-field-bg-hover: #17181e;
159
- --gemboss-field-ink: #e3e4e8;
160
- --gemboss-field-placeholder: #8a8c96;
161
- --gemboss-field-line: #3a3c46;
162
- --gemboss-field-line-hover: #50525e;
163
- --gemboss-field-line-active: #c9cbd3;
164
- --gemboss-chip-ink: #d6d8de;
165
- --gemboss-chip-line: #3a3c46;
166
- --gemboss-chip-line-hover: #50525e;
167
- --gemboss-chip-bg-hover: #22232b;
168
- --gemboss-success: #34c38f;
169
- --gemboss-success-strong: #5fd6a8;
170
- --gemboss-success-soft: #13291f;
171
- --gemboss-success-border: #22533e;
172
- --gemboss-warning: #e0b341;
173
- --gemboss-warning-soft: #2b2412;
174
- --gemboss-warning-border: #5a4a1d;
175
- --gemboss-danger: #ff6b5a;
176
- --gemboss-danger-strong: #ff8a7c;
177
- --gemboss-danger-soft: #2e1714;
178
- --gemboss-danger-border: #5c2a24;
179
- --ui-accent-fg: #0d0d12;
180
- --ui-warning-fg: #e8c063;
181
- --gb-brand-ink: #f2f3f5;
182
- }
183
- /* Avatar initials in dark: the tone's light end, so the text clears 4.5:1 on its tinted disc. */
184
- :root[data-theme="dark"] .gb-avatar[data-tone] { background: color-mix(in srgb, var(--gb-tone) 30%, #16171d); color: color-mix(in srgb, var(--gb-tone) 35%, #ffffff); }
185
- :root[data-theme="dark"] body { background: var(--gemboss-app-bg); color: var(--gemboss-text); }
186
- :root[data-theme="dark"] .gb-leaderboard-row.is-first .gb-leaderboard-value,
187
- :root[data-theme="dark"] .gb-podium-slot--1 .gb-podium-value { color: #e0b341; }
package/src/portal.tsx CHANGED
@@ -80,7 +80,15 @@ export function Avatar({ name, src, size = 24, className }: { name: string; src?
80
80
  );
81
81
  }
82
82
 
83
- export type LeaderRow = { key: string | number; name: string; value: number; avatar?: string | null; href?: string };
83
+ export type LeaderRow = {
84
+ key: string | number; name: string; value: number; avatar?: string | null; href?: string;
85
+ /** Shown after the name: a level, a role (GemCommunity's "Lv2 · Builder"). */
86
+ badge?: React.ReactNode;
87
+ /** The viewer's own row: tinted, and announced. */
88
+ current?: boolean;
89
+ /** The row's element id, for a "#me" link that scrolls to it. */
90
+ id?: string;
91
+ };
84
92
 
85
93
  const MEDALS = ["🥇", "🥈", "🥉"];
86
94
  const PODIUM_SLOT = ["gb-podium-slot--1", "gb-podium-slot--2", "gb-podium-slot--3"];
@@ -90,40 +98,44 @@ const PODIUM_SLOT = ["gb-podium-slot--1", "gb-podium-slot--2", "gb-podium-slot--
90
98
  * screen readers ("163 votes") and can be shown with `showUnit`. Empty → nothing (a "top" list of
91
99
  * zeros looks dead; GemCommunity hides it the same way).
92
100
  */
93
- export function Leaderboard({ title, caption, rows, unit, showUnit = false, viewAll, as: L = "a", className, headingLevel = 2, id }: {
94
- title: React.ReactNode; caption?: React.ReactNode; rows: LeaderRow[]; unit?: string; showUnit?: boolean;
101
+ export function Leaderboard({ title, label, caption, rows, unit, showUnit = false, viewAll, as: L = "a", className, headingLevel = 2, id, currentLabel = "you" }: {
102
+ /** The visible heading. Leave it out on a page whose own <h1> already names the board; give `label`. */
103
+ title?: React.ReactNode; label?: string; caption?: React.ReactNode; rows: LeaderRow[]; unit?: string; showUnit?: boolean;
95
104
  viewAll?: { href: string; label: React.ReactNode }; as?: LinkLike; className?: string; headingLevel?: 2 | 3;
96
105
  /** The heading's id. Pass one when two leaderboards share a page or the title is not plain text. */
97
106
  id?: string;
107
+ /** Read by screen readers after the viewer's own name ("Minh, you"). "" when the name already says it on screen. */
108
+ currentLabel?: string;
98
109
  }) {
99
110
  if (!rows.length) return null;
100
111
  const H = `h${headingLevel}` as "h2" | "h3";
101
112
  // From the title's letters (any script) and a hash of it, so "Most helpful" and a Vietnamese or
102
113
  // Chinese title each get their own; two boards with the same title need `id`.
103
- const text = typeof title === "string" ? title : "leaderboard";
114
+ const text = typeof title === "string" ? title : label ?? "leaderboard";
104
115
  let h = 0;
105
116
  for (const ch of text) h = (h * 31 + ch.codePointAt(0)!) >>> 0;
106
117
  const headingId = id ?? `gb-lb-${text.toLowerCase().replace(/[^\p{L}\p{N}]+/gu, "-").replace(/^-|-$/g, "")}-${h.toString(36)}`;
107
118
  return (
108
- <section className={cx("gb-leaderboard", className)} aria-labelledby={headingId}>
109
- <H className="gb-leaderboard-title" id={headingId}>{title}</H>
119
+ <section className={cx("gb-leaderboard", className)} aria-labelledby={title ? headingId : undefined} aria-label={title ? undefined : label}>
120
+ {title ? <H className="gb-leaderboard-title" id={headingId}>{title}</H> : null}
110
121
  {caption ? <p className="gb-leaderboard-caption">{caption}</p> : null}
111
122
  <ol className="gb-leaderboard-list">
112
123
  {rows.map((r, i) => {
113
124
  const inner = (
114
125
  <>
115
126
  <span className={cx("gb-leaderboard-rank", !MEDALS[i] && "is-number")}>
116
- <span aria-hidden="true">{MEDALS[i] ?? i + 1}</span><span className="ui-sr-only">Rank {i + 1}: </span>
127
+ <span aria-hidden="true">{MEDALS[i] ?? i + 1}</span><span className="gb-sr-only">Rank {i + 1}: </span>
117
128
  </span>
118
129
  <Avatar name={r.name} src={r.avatar} />
119
- <span className="gb-leaderboard-name">{r.name}</span>
130
+ <span className="gb-leaderboard-name">{r.name}{r.current && currentLabel ? <span className="gb-sr-only">, {currentLabel}</span> : null}</span>
131
+ {r.badge ? <span className="gb-leaderboard-badge">{r.badge}</span> : null}
120
132
  <span className="gb-leaderboard-value">
121
- {r.value}{unit ? (showUnit ? <> {unit}</> : <span className="ui-sr-only"> {unit}</span>) : null}
133
+ {r.value}{unit ? (showUnit ? <> {unit}</> : <span className="gb-sr-only"> {unit}</span>) : null}
122
134
  </span>
123
135
  </>
124
136
  );
125
137
  return (
126
- <li key={r.key} className={cx("gb-leaderboard-row", i === 0 && "is-first")}>
138
+ <li key={r.key} id={r.id} className={cx("gb-leaderboard-row", i === 0 && "is-first", r.current && "is-current")}>
127
139
  {r.href ? <L href={r.href} className="gb-leaderboard-link">{inner}</L> : <div className="gb-leaderboard-link">{inner}</div>}
128
140
  </li>
129
141
  );
@@ -144,14 +156,14 @@ export function Podium({ rows, unit, as: L = "a", className }: { rows: LeaderRow
144
156
  if (!r) return <li key={idx} className="gb-podium-slot is-empty" aria-hidden="true" />;
145
157
  const body = (
146
158
  <>
147
- <span className="gb-podium-medal"><span aria-hidden="true">{MEDALS[idx]}</span><span className="ui-sr-only">Rank {idx + 1}: </span></span>
159
+ <span className="gb-podium-medal"><span aria-hidden="true">{MEDALS[idx]}</span><span className="gb-sr-only">Rank {idx + 1}: </span></span>
148
160
  <Avatar name={r.name} src={r.avatar} size={56} />
149
161
  <span className="gb-podium-name">{r.name}</span>
150
162
  <span className="gb-podium-value">{r.value}{unit ? <span className="gb-podium-unit"> {unit}</span> : null}</span>
151
163
  </>
152
164
  );
153
165
  return (
154
- <li key={r.key} className={cx("gb-podium-slot", PODIUM_SLOT[idx])}>
166
+ <li key={r.key} className={cx("gb-podium-slot", PODIUM_SLOT[idx], r.current && "is-current")}>
155
167
  {r.href ? <L href={r.href} className="gb-podium-link">{body}</L> : <div className="gb-podium-link">{body}</div>}
156
168
  </li>
157
169
  );
@@ -0,0 +1,65 @@
1
+ /* ═══ Dark palette — @gemboss/ui 0.7.2 ═══════════════════════════════════════════════════════════════
2
+ Split out of portal.css (04/10/2026). `ThemeToggle` / `themeScript` set data-theme on <html>, and this
3
+ file turns every --gemboss-* colour dark under it. It lives apart so that a surface which takes only
4
+ the leaderboard (gemboss-tokens.css + portal.css) does not inherit it: GemCommunity sets
5
+ data-theme="dark" for its own sign-in pages and remembers it, and the rule
6
+ `:root[data-theme="dark"] body` here outranks its body rule, so a member who once picked dark there
7
+ would get a dark page behind light cards. gemboss-ui.css still carries this file. */
8
+ /* Dark palette. `ThemeToggle` / `themeScript` set data-theme on <html>; a surface without them stays
9
+ light. Only colours change: the components above and every kit class read these tokens. */
10
+ :root[data-theme="dark"] {
11
+ color-scheme: dark;
12
+ --gemboss-primary: #f2f3f5;
13
+ --gemboss-primary-dark: #ffffff;
14
+ --gemboss-primary-soft: #23242a;
15
+ --gemboss-on-primary: #0d0d12;
16
+ --gemboss-accent: #7c84ff;
17
+ --gemboss-accent-strong: #a3a9ff;
18
+ --gemboss-accent-soft: #1f2140;
19
+ --gemboss-text-strong: #f2f3f5;
20
+ --gemboss-text: #e3e4e8;
21
+ --gemboss-text-muted: #9a9ca6;
22
+ --gemboss-surface: #16171d;
23
+ --gemboss-canvas: #0d0d12;
24
+ --gemboss-app-bg: #0d0d12;
25
+ --gemboss-rail-bg: #0d0d12;
26
+ --gemboss-panel-bg: #16171d;
27
+ --gemboss-topbar-bg: rgba(13, 13, 18, 0.96);
28
+ --gemboss-nav-bg: #0d0d12;
29
+ --gemboss-nav-hover: rgba(255, 255, 255, 0.06);
30
+ --gemboss-divider: #2a2b33;
31
+ --gemboss-divider-soft: #22232a;
32
+ --gemboss-hover: #22232b;
33
+ --gemboss-active-bg: #262833;
34
+ --gemboss-active-fg: #f2f3f5;
35
+ --gemboss-field-bg: #121318;
36
+ --gemboss-field-bg-hover: #17181e;
37
+ --gemboss-field-ink: #e3e4e8;
38
+ --gemboss-field-placeholder: #8a8c96;
39
+ --gemboss-field-line: #3a3c46;
40
+ --gemboss-field-line-hover: #50525e;
41
+ --gemboss-field-line-active: #c9cbd3;
42
+ --gemboss-chip-ink: #d6d8de;
43
+ --gemboss-chip-line: #3a3c46;
44
+ --gemboss-chip-line-hover: #50525e;
45
+ --gemboss-chip-bg-hover: #22232b;
46
+ --gemboss-success: #34c38f;
47
+ --gemboss-success-strong: #5fd6a8;
48
+ --gemboss-success-soft: #13291f;
49
+ --gemboss-success-border: #22533e;
50
+ --gemboss-warning: #e0b341;
51
+ --gemboss-warning-soft: #2b2412;
52
+ --gemboss-warning-border: #5a4a1d;
53
+ --gemboss-danger: #ff6b5a;
54
+ --gemboss-danger-strong: #ff8a7c;
55
+ --gemboss-danger-soft: #2e1714;
56
+ --gemboss-danger-border: #5c2a24;
57
+ --ui-accent-fg: #0d0d12;
58
+ --ui-warning-fg: #e8c063;
59
+ --gb-brand-ink: #f2f3f5;
60
+ }
61
+ /* Avatar initials in dark: the tone's light end, so the text clears 4.5:1 on its tinted disc. */
62
+ :root[data-theme="dark"] .gb-avatar[data-tone] { background: color-mix(in srgb, var(--gb-tone) 30%, #16171d); color: color-mix(in srgb, var(--gb-tone) 35%, #ffffff); }
63
+ :root[data-theme="dark"] body { background: var(--gemboss-app-bg); color: var(--gemboss-text); }
64
+ :root[data-theme="dark"] .gb-leaderboard-row.is-first .gb-leaderboard-value,
65
+ :root[data-theme="dark"] .gb-podium-slot--1 .gb-podium-value { color: #e0b341; }