- Persist source/view/sort toggles via URL query params (?s=…&v=…&o=…).
Short keys keep shared URLs readable; defaults are stripped to keep
the bare URL clean. history.replaceState (no history pollution).
Init seeds toggles from URL with clamp-to-default validation.
- View class is applied BEFORE first render so renderGrid sees the
correct show-all state on direct deep-link loads.
- Add #source-note pill next to the source tag; shows
"91 ngôn ngữ — palette riêng so với GitHub" when GitLab selected,
hidden otherwise. Plus title attr on the source-toggle group with
the full GitHub-vs-GitLab disparity.
- In TIOBE view, hide cards with zero TIOBE-ranked langs (currently
KIM has 0 of 19) — all-langs view still shows every Ngũ Hành card
so the wheel stays intact.
- source-tag firstChild text-node overwrite preserves the source-note
span sibling.
Closes phase-02 of plan 260428-1003-implement-all-remaining (items
2, 3, 4).
- Drop italic on .hero .subtitle; use letter-spacing instead (Be Vietnam
Pro italic renders rough on Linux).
- Migrate anchor underlines from border-bottom dotted to native
text-decoration-style: dotted (figcaption + credit).
- Bump .card h3 to 1.2rem with thin gold rule under each Ngũ Hành
label; reduce letter-spacing 1.2px → 0.4px so Vietnamese diacritics
don't drift.
- Tighten .credit ul indent (move 1.25rem from margin to padding).
- Strengthen chip border 0.18 → 0.22 so pale chips (Rust-class) read
against the cream page bg.
- Add role="list" to .chips and role="listitem" to chip spans for
screen-reader semantics; aria-label per element bucket.
- Document 5-card-row decision (auto-fit retained) and chip contrast
policy (best-effort WCAG luminance) as inline CSS comments.
Closes phase-01 of plan 260428-1003-implement-all-remaining (items
5-10, 13, 14, 15).
Apply remaining UI/UX-review items:
- new "Sắp xếp" segmented control: Mặc định / A–Z / Cầu vồng (hue).
Re-sorts cached buckets without re-fetching.
- DRY the three toggles into one `mountSegmentedControl` helper using
ARIA `role="radiogroup"` / `role="radio"` with `aria-checked` (was
tab/tablist + aria-selected — wrong pattern, no associated tabpanels).
- element-tinted card backgrounds via color-mix(... 6%, card-bg);
count line picks up the element color too — Ngũ Hành identity
reads at a glance instead of relying on a 4 px stripe.
- chip text-shadow stroke applied only to colored chips to rescue
borderline contrast (Swift #F05138 etc.).
- mobile (<= 480 px): modern-controls stack as labeled rows,
segmented buttons hit the 44 px touch-target floor.
- show-all view caps each card's chip cloud at 60 vh w/ thin
scrollbar — HOẢ no longer pushes the page to 5700 px tall on phones.
- hero ribbon stripes 28×4 → 64×6, gap 6 → 8 — reads as a ribbon now,
not a dashed underline; clamps narrower on small phones.
- TIOBE chip emphasis: stronger inset highlight + outer hairline so
the rank-pinned chips read against any background.
- drop dead 320 px breakpoint (clamp() floor already covers it).
UI/UX review found three blockers (report at plans/reports/):
- main.js queried #panel-modern (deleted with classic page); view-toggle
silently failed to mount and legend/error sink no-op'd. Re-anchor refs
to `main .elements`.
- forced 5-col grid at 880px gave each card ~126px of inner room; long
chip names like "Mathematical Programming System" were silently
ellipsis-truncated. Switch to auto-fit minmax(220px, 1fr) and let
chips soft-wrap.
- pickTextColor luminance>0.5 threshold drove white text onto mid-tones
(Rust #dea584 → 2.14:1, Go 2.64, Swift 3.54...). Pick whichever of
black/white has higher WCAG ratio; Rust now 8.34:1.
Polish:
- move "Nguồn: GitHub Linguist" out of <h2> into its own <p class="mode-tag"> for cleaner heading semantics.
- modern-controls align-items: end → stretch (fixes label/toggle misalignment when wrapped).
- bump .card-count to 0.85rem/600 for clearer hierarchy.
- wrap original 2018 image in <details class="original-image"> spoiler again
- view-toggle becomes a 2-state segmented control (TIOBE Top 20 / Tất cả ngôn ngữ)
matching the source-toggle pattern, with arrow-key roving tabindex
- label both controls ("Nguồn màu" / "Hiển thị") for discoverability
GitLab maintains its own Linguist fork with materially different colors
(JavaScript orange instead of yellow, Go olive instead of cyan, ...).
Added a segmented GitHub | GitLab toggle next to the view toggle in the
modern panel. Switching reloads the data and re-classifies on the fly.
- data/gitlab-colors.json: 91 entries, 2.9KB, converted from gitlab-org/linguist YAML
- js/main.js: refactored render path into loadAndRender(sourceKey)
- js/render-elements.js: new mountSourceToggle helper (tablist + arrow keys)
- index.html: source-toggle slot, source-tag in h2, updated disclaimer
- style.css: pill-segmented .source-toggle styling
Default view shows only TIOBE-ranked languages (19 chips total) for a cleaner
first impression. A single button at the top of the modern panel toggles to
the full 664-language list. Card counts now read 'X TIOBE · Y khác'. Chips
of TIOBE-ranked languages get a slightly heavier border to stand out.
- js/tiobe-top.js: TIOBE Top 20 (April 2026) keyed by GH Linguist names
- js/main.js: tag entries with rank, sort TIOBE-first then alphabetical
- js/render-elements.js: chip distinction + view-toggle mount
- index.html: view-toggle slot + updated disclaimer
- style.css: .chip-tiobe / .chip-other / .view-toggle-btn rules
Classic mode reproduces the 2018 toidicodedao image and its 5 hardcoded
element cards verbatim. Modern mode renders a data-driven grid built from
GitHub Linguist colors classified into Ngũ Hành elements via a deterministic
HSL rule set. Toggle persists via URL hash; both panels coexist in DOM with
a CSS opacity fade. Includes a collapsed debug panel listing skipped (no
color) and borderline (near hue boundary) entries.
- data/github-colors.json: vendored from ozh/github-colors (722 entries)
- js/classify-element.js: pure HSL classifier (664 lang sample, 22/22 fixtures pass)
- js/mode-toggle.js: tablist with hash persistence + arrow-key nav
- js/render-elements.js: chip rendering with YIQ contrast + debug panel
- js/main.js: fetch + classify + render entry point
- style.css: segmented toggle, panel fade, chip pill, debug-panel, mobile