diff --git a/.gitignore b/.gitignore index 771f8d2..4681b20 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,12 @@ playwright-report/ tests/*-chromium/ tests/*-firefox/ tests/*-webkit/ + +# Markdown hanya boleh online di root repo (README, CHANGELOG, dst.) dan di +# .github/ (template). Dokumen kerja di subfolder — mis. docs/masterplan_*.md, +# docs/architecture_*.md — disimpan LOKAL saja, tidak dipublikasikan. +*.md +*.MD +!/*.md +!/*.MD +!/.github/**/*.md diff --git a/CLAUDE.md b/CLAUDE.md index 6a87a99..6ddb4c5 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -7,10 +7,12 @@ perbarui di akhir setiap sesi (bagian "Status & lanjutan"). - Repo `codinglombok/LombokCSS`, katalog ekosistem **01.01**, tingkat **L0**, status 🟢 LIVE, versi **0.1.9**, lisensi **MIT**. - Acuan normatif: **MASTERPLAN_UTAMA v3.4** (2026-09-29) — Prinsip #11 "Universal tanpa klaim aplikasi", **ADR-019**, 9 dimensi D1–D9, 12 dokumen standar per repo. -- Dokumen standar repo: `docs/*_LombokCSS_v0.1.9.md` (masterplan, architecture, changelog, map, structure_repo, full_summary_project, guide_how_to_use, how_to_dist, development_ide, API, Lang, SPEC). +- Dokumen standar repo: `docs/*_LombokCSS_v0.1.9.md` (masterplan, architecture, changelog, map, structure_repo, full_summary_project, guide_how_to_use, how_to_dist, development_ide, API, Lang, SPEC) — **LOKAL SAJA**, tidak di-commit. ## Aturan wajib (v3.4) +- **Markdown (keputusan pemilik):** hanya `*.md` di root repo (README, CHANGELOG, CONTRIBUTING, dst.) dan `.github/` yang boleh online. Semua `*.md` di subfolder (mis. `docs/masterplan_*.md`) di-`.gitignore` dan disimpan lokal saja. Jangan pernah `git add -f` berkas itu. (Kasus sama pernah terjadi di LombokCompress.) + - DILARANG di README/manifest/dokumen: "Part of Lombok", "Library #…", "component of …", "for LombokRAG/PDF/Agentic". Yang boleh: "Part of Lombok Ecosystem", "Dipakai oleh X" (bagian terpisah). - Audit cepat: `grep -n -i -E "part of Lombok[A-Z]|library #|component of|for Lombok(RAG|PDF|Agentic)" README.md package.json composer.json bower.json lombokcss.gemspec` - README wajib punya "Why this library? (Mengapa library ini?)" dan "Standards implemented". @@ -26,7 +28,7 @@ npm run lint # Prettier cp dist/lombok.js docs/assets/lombok.js # sinkron aset situs bila JS berubah ``` -- `CHANGELOG.md` ditulis release-please — jangan diedit tangan; catatan masterplan masuk ke `docs/changelog_LombokCSS_v.md`. +- `CHANGELOG.md` ditulis release-please — jangan diedit tangan; catatan masterplan masuk ke `docs/changelog_LombokCSS_v.md` (lokal). - Perubahan perilaku JS: perbarui `docs/SPEC_…` + test di `tests/behavior.spec.js`. ## Status & lanjutan @@ -38,11 +40,16 @@ Sesi 2026-09-30 (branch `claude/affectionate-sagan-o4rxmx`) — penyelarasan v3. - [x] Deskripsi manifest npm/Composer/Bower/gem/NuGet/Maven + "Part of Lombok Ecosystem" - [x] `lombok.js`: sortir tabel via `Intl.Collator` dari `lang` terdekat (+2 test) +Sesi 2026-09-30 lanjutan — PR #36 di-merge; lalu: + +- [x] C-03: folder `package/` dihapus +- [x] `docs/*.md` dicabut dari git + `.gitignore` (`*.md`, kecuali root dan `.github/`) + Belum selesai (lanjutkan di sesi berikut): - [ ] Pemilik: ubah deskripsi GitHub About (teks ada di `docs/masterplan_…` §6) +- [ ] Pemilik: perbaiki model Copilot untuk check `github-advanced-security` (gagal: "model not supported") - [ ] C-02: email kontak nyata di `SECURITY.md` (masih placeholder) — butuh keputusan pemilik -- [ ] C-03: hapus folder `package/` (salinan lama, tidak dipublikasikan) - [ ] C-04: SBOM + provenance npm di workflow rilis (target 0.2.0) - [ ] C-06: rename `docs/*_v0.1.9.md` saat versi minor naik - [ ] D8: tooltip & validasi form opsional; D5 → ✅ setelah C-02 + C-04 diff --git a/docs/API_LombokCSS_v0.1.9.md b/docs/API_LombokCSS_v0.1.9.md deleted file mode 100644 index 51dca4c..0000000 --- a/docs/API_LombokCSS_v0.1.9.md +++ /dev/null @@ -1,61 +0,0 @@ -# API Reference — LombokCSS v0.1.9 - -| Atribut | Nilai | -| --- | --- | -| Repo | [codinglombok/LombokCSS](https://github.com/codinglombok/LombokCSS) | -| Versi library | 0.1.9 | -| Tingkat / cluster | L0 · 01 Frontend, UI & Visualisasi Data (katalog 01.01) | -| Acuan | MASTERPLAN_UTAMA v3.4 (2026-09-29) · ARCHITECTURE_UTAMA v3.4 · ADR-019 | -| Tanggal dokumen | 2026-09-30 | -| Lisensi | MIT (kebijakan §10: framework CSS) | - -Dokumen standar: [Masterplan](masterplan_LombokCSS_v0.1.9.md) · [Architecture](architecture_LombokCSS_v0.1.9.md) · [Changelog](changelog_LombokCSS_v0.1.9.md) · [Map](map_LombokCSS_v0.1.9.md) · [Structure Repo](structure_repo_LombokCSS_v0.1.9.md) · [Full Summary Project](full_summary_project_LombokCSS_v0.1.9.md) · [Guide How to Use](guide_how_to_use_LombokCSS_v0.1.9.md) · [How to Dist](how_to_dist_LombokCSS_v0.1.9.md) · [Development Ide](development_ide_LombokCSS_v0.1.9.md) · [API Reference](API_LombokCSS_v0.1.9.md) · [Bahasa (i18n)](Lang_LombokCSS_v0.1.9.md) · [Behavioral Specification](SPEC_LombokCSS_v0.1.9.md) - ---- - -## 1. Atribut global - -| Atribut | Elemen | Nilai | -| --- | --- | --- | -| `data-style` | `` atau kontainer | `modern-corporate-flat` · `resonant-stark` · `neo-brutalism` · `semantic-minimalist` · `glassmorphism` | -| `data-theme` | `` atau kontainer | `light` · `dark` | -| `dir` | `` | `ltr` · `rtl` | -| `lang` | elemen mana pun | Tag BCP 47 (collation sortir tabel) | - -## 2. Token (CSS custom properties) - -| Kelompok | Token | -| --- | --- | -| Warna permukaan & teks | `--lc-bg` `--lc-surface` `--lc-surface-2` `--lc-text` `--lc-text-muted` `--lc-text-faint` `--lc-border` `--lc-border-strong` `--lc-border-width` | -| Aksen | `--lc-accent` `--lc-accent-hover` `--lc-accent-active` `--lc-accent-text` `--lc-accent-soft` `--lc-accent-soft-text` `--lc-ring` | -| Status | `--lc-{success,warning,danger,info}` + `-soft` + `-text` | -| Bentuk & efek | `--lc-radius-sm` `--lc-radius` `--lc-radius-lg` `--lc-radius-full` `--lc-shadow-sm` `--lc-shadow` `--lc-shadow-lg` `--lc-shadow-hard` `--lc-blur` `--lc-glass-tint` `--lc-glass-border` `--lc-transition` | -| Tipografi | `--lc-font-sans` `--lc-font-display` `--lc-font-mono` `--lc-text-{xs,sm,base,lg,xl,2xl,3xl,4xl}` `--lc-weight-{normal,medium,semibold,bold}` `--lc-leading-{tight,normal,relaxed}` `--lc-tracking` | -| Ruang & tata letak | `--lc-space-{0,1,2,3,4,5,6,8,10,12}` `--lc-container` `--lc-navbar-h` | -| Lapisan | `--lc-z-{base,dropdown,sticky,modal,toast,tooltip}` | - -## 3. Kelas komponen - -Lihat [Full Summary](full_summary_project_LombokCSS_v0.1.9.md) §2 dan situs docs -(`components.html`, `forms.html`, `utilities.html`). Status visual: `.is-open`, `.is-active`, `.is-valid`, `.is-invalid`. - -## 4. JavaScript (`dist/lombok.js`) - -| Hook | Perilaku | -| --- | --- | -| `[data-dropdown-toggle]` dalam `.dropdown` | Toggle `.is-open`, `aria-expanded`; Esc & klik luar menutup | -| `[role=tablist] [role=tab][aria-controls]` | `aria-selected`, panel `hidden` | -| `[data-modal-open="id"]` / `[data-modal-close]` | `showModal()` / `close()` pada ``; klik backdrop menutup | -| `[data-drawer-open="id"]` / `[data-drawer-close]` | Drawer/offcanvas | -| `[data-popover-toggle]` dalam `.popover` | Toggle `.is-open`; Esc menutup | -| `.navbar-toggle` dalam `.navbar` | Toggle `.is-open` | -| `.carousel` (`.carousel-track`, `.carousel-prev/next`, `.carousel-dots`) | Geser per slide, sadar RTL | -| `table.table thead th[aria-sort]` | Sortir kolom: angka numerik, teks via `Intl.Collator(lang terdekat, {numeric:true})` | - -```ts -Lombok.toast(msg: string, opts?: { variant?: "success"|"warning"|"danger"|"info"; timeout?: number /* ms, default 3500 */ }): HTMLElement -``` - -## 5. Ekspor paket npm - -`lombokcss` → `dist/lombok.js` · `lombokcss/css` → `dist/lombok.min.css` · `lombokcss/css-full` → `dist/lombok.css` · `lombokcss/js` · `lombokcss/src/*`. diff --git a/docs/Lang_LombokCSS_v0.1.9.md b/docs/Lang_LombokCSS_v0.1.9.md deleted file mode 100644 index 320751c..0000000 --- a/docs/Lang_LombokCSS_v0.1.9.md +++ /dev/null @@ -1,39 +0,0 @@ -# Bahasa (i18n) — LombokCSS v0.1.9 - -| Atribut | Nilai | -| --- | --- | -| Repo | [codinglombok/LombokCSS](https://github.com/codinglombok/LombokCSS) | -| Versi library | 0.1.9 | -| Tingkat / cluster | L0 · 01 Frontend, UI & Visualisasi Data (katalog 01.01) | -| Acuan | MASTERPLAN_UTAMA v3.4 (2026-09-29) · ARCHITECTURE_UTAMA v3.4 · ADR-019 | -| Tanggal dokumen | 2026-09-30 | -| Lisensi | MIT (kebijakan §10: framework CSS) | - -Dokumen standar: [Masterplan](masterplan_LombokCSS_v0.1.9.md) · [Architecture](architecture_LombokCSS_v0.1.9.md) · [Changelog](changelog_LombokCSS_v0.1.9.md) · [Map](map_LombokCSS_v0.1.9.md) · [Structure Repo](structure_repo_LombokCSS_v0.1.9.md) · [Full Summary Project](full_summary_project_LombokCSS_v0.1.9.md) · [Guide How to Use](guide_how_to_use_LombokCSS_v0.1.9.md) · [How to Dist](how_to_dist_LombokCSS_v0.1.9.md) · [Development Ide](development_ide_LombokCSS_v0.1.9.md) · [API Reference](API_LombokCSS_v0.1.9.md) · [Bahasa (i18n)](Lang_LombokCSS_v0.1.9.md) · [Behavioral Specification](SPEC_LombokCSS_v0.1.9.md) - ---- - -## 1. Ringkasan i18n - -LombokCSS **tidak mengirim string UI sendiri**: semua teks (label tombol, isi toast, -judul) ditulis pemakai di HTML/JS. Karena itu katalog pesan Core-20 (Prinsip #6) tidak -berlaku untuk library ini; yang berlaku adalah dukungan tata tulis dan urutan bahasa. - -| Kemampuan | Status | -| --- | --- | -| Arah tulisan RTL (Arab, Ibrani, Persia, Urdu) | ✅ CSS logical properties; carousel sadar `dir` | -| Urutan alfabet per bahasa (sortir tabel) | ✅ `Intl.Collator` dari atribut `lang` terdekat (BCP 47) | -| Angka dalam teks ("Item 2" < "Item 10") | ✅ `numeric: true` | -| Font skrip non-Latin | ⏳ pakai `--lc-font-sans`; tidak ada font bawaan | -| Katalog pesan | N/A — tidak ada pesan bawaan | - -## 2. Contoh - -```html - -…
-``` - -## 3. Aturan fallback - -Tag `lang` kosong, tidak ada, atau tidak valid → collation default runtime (tidak melempar error). diff --git a/docs/SPEC_LombokCSS_v0.1.9.md b/docs/SPEC_LombokCSS_v0.1.9.md deleted file mode 100644 index f225de7..0000000 --- a/docs/SPEC_LombokCSS_v0.1.9.md +++ /dev/null @@ -1,32 +0,0 @@ -# Behavioral Specification — LombokCSS v0.1.9 - -| Atribut | Nilai | -| --- | --- | -| Repo | [codinglombok/LombokCSS](https://github.com/codinglombok/LombokCSS) | -| Versi library | 0.1.9 | -| Tingkat / cluster | L0 · 01 Frontend, UI & Visualisasi Data (katalog 01.01) | -| Acuan | MASTERPLAN_UTAMA v3.4 (2026-09-29) · ARCHITECTURE_UTAMA v3.4 · ADR-019 | -| Tanggal dokumen | 2026-09-30 | -| Lisensi | MIT (kebijakan §10: framework CSS) | - -Dokumen standar: [Masterplan](masterplan_LombokCSS_v0.1.9.md) · [Architecture](architecture_LombokCSS_v0.1.9.md) · [Changelog](changelog_LombokCSS_v0.1.9.md) · [Map](map_LombokCSS_v0.1.9.md) · [Structure Repo](structure_repo_LombokCSS_v0.1.9.md) · [Full Summary Project](full_summary_project_LombokCSS_v0.1.9.md) · [Guide How to Use](guide_how_to_use_LombokCSS_v0.1.9.md) · [How to Dist](how_to_dist_LombokCSS_v0.1.9.md) · [Development Ide](development_ide_LombokCSS_v0.1.9.md) · [API Reference](API_LombokCSS_v0.1.9.md) · [Bahasa (i18n)](Lang_LombokCSS_v0.1.9.md) · [Behavioral Specification](SPEC_LombokCSS_v0.1.9.md) - ---- - -Kontrak normatif perilaku `dist/lombok.js` (ADR-015). Kata **HARUS/TIDAK BOLEH** bersifat -normatif. Setiap butir diuji di `tests/behavior.spec.js` (kolom Test = blok `describe`). - -| ID | Aturan | Test | -| --- | --- | --- | -| S-01 | Mengimpor skrip tanpa `document` (SSR) TIDAK BOLEH melempar dan TIDAK BOLEH menyentuh API browser | `scripts/ssr-check.mjs` | -| S-02 | Skrip TIDAK BOLEH melakukan permintaan jaringan atau memakai storage | tinjauan kode | -| S-03 | Dropdown: klik `[data-dropdown-toggle]` HARUS men-toggle `.is-open` pada `.dropdown` terdekat dan menyetel `aria-expanded`; klik di luar dan `Escape` HARUS menutup | dropdown | -| S-04 | Tabs: klik tab HARUS menyetel `aria-selected="true"` padanya, `"false"` pada lainnya, dan hanya panel `aria-controls`-nya yang tidak `hidden` | tabs | -| S-05 | Modal: `[data-modal-open=id]` HARUS memanggil `showModal()` pada ``; `[data-modal-close]` dan klik backdrop HARUS menutup | modal | -| S-06 | Drawer, popover, navbar: toggle `.is-open` pada kontainer terdekat; popover HARUS tertutup oleh `Escape` | drawer / popover / navbar | -| S-07 | Carousel HARUS bergerak ke indeks slide target (bukan delta), dibatasi [0, n−1], dan membalik arah bila `dir="rtl"` | carousel | -| S-08 | Sortir tabel: klik `th[aria-sort]` HARUS mengurutkan `tBodies[0]` naik, klik kedua turun; `th` lain direset ke `none`; sel satu baris tetap bersama | table sort | -| S-09 | Sortir tabel: bila kedua nilai numerik HARUS dibandingkan sebagai angka; selain itu HARUS memakai `Intl.Collator` untuk `lang` terdekat dengan `numeric: true` | table sort | -| S-10 | Tag `lang` tidak valid TIDAK BOLEH melempar; HARUS jatuh ke collation default | table sort | -| S-11 | `Lombok.toast(msg, opts)` HARUS membuat `.toast-region[aria-live=polite]` bila belum ada, menambah elemen `role=status` berisi `msg` sebagai teks (bukan HTML), dan menghapusnya setelah `opts.timeout` (default 3500 ms) | toast | -| S-12 | Tidak ada exception tak tertangkap selama interaksi mana pun | `afterEach` global | diff --git a/docs/architecture_LombokCSS_v0.1.9.md b/docs/architecture_LombokCSS_v0.1.9.md deleted file mode 100644 index be8664c..0000000 --- a/docs/architecture_LombokCSS_v0.1.9.md +++ /dev/null @@ -1,64 +0,0 @@ -# Architecture — LombokCSS v0.1.9 - -| Atribut | Nilai | -| --- | --- | -| Repo | [codinglombok/LombokCSS](https://github.com/codinglombok/LombokCSS) | -| Versi library | 0.1.9 | -| Tingkat / cluster | L0 · 01 Frontend, UI & Visualisasi Data (katalog 01.01) | -| Acuan | MASTERPLAN_UTAMA v3.4 (2026-09-29) · ARCHITECTURE_UTAMA v3.4 · ADR-019 | -| Tanggal dokumen | 2026-09-30 | -| Lisensi | MIT (kebijakan §10: framework CSS) | - -Dokumen standar: [Masterplan](masterplan_LombokCSS_v0.1.9.md) · [Architecture](architecture_LombokCSS_v0.1.9.md) · [Changelog](changelog_LombokCSS_v0.1.9.md) · [Map](map_LombokCSS_v0.1.9.md) · [Structure Repo](structure_repo_LombokCSS_v0.1.9.md) · [Full Summary Project](full_summary_project_LombokCSS_v0.1.9.md) · [Guide How to Use](guide_how_to_use_LombokCSS_v0.1.9.md) · [How to Dist](how_to_dist_LombokCSS_v0.1.9.md) · [Development Ide](development_ide_LombokCSS_v0.1.9.md) · [API Reference](API_LombokCSS_v0.1.9.md) · [Bahasa (i18n)](Lang_LombokCSS_v0.1.9.md) · [Behavioral Specification](SPEC_LombokCSS_v0.1.9.md) - ---- - -## 1. Prinsip - -- **Token dulu:** komponen hanya membaca token semantik (`--lc-surface`, `--lc-text`, `--lc-accent`, …). Gaya desain = kumpulan nilai token. -- **Tiga sumbu independen:** `data-style` (identitas), `data-theme` (terang/gelap), `dir` (LTR/RTL). Semua kombinasi valid. -- **Zero dependency runtime** (Prinsip #7); JS opsional dan degradasi mulus. -- **Dependensi searah & tanpa klaim** (Prinsip #9, #11): L0, tidak bergantung pada library, framework, maupun aplikasi apa pun. - -## 2. Lapisan sumber - -Urutan konkatenasi di `scripts/build-css.mjs` (urutan = kaskade): - -| # | Berkas | Isi | -| --- | --- | --- | -| 1 | `src/variables.css` | Token primitif & semantik, default terang, `prefers-color-scheme` | -| 2 | `src/core.css` | Reset, tipografi classless, fokus, `prefers-reduced-motion` | -| 3 | `src/themes.css` | Lima gaya desain + override gelap per gaya | -| 4 | `src/components.css` | Komponen (hanya membaca token) | -| 5 | `src/utilities.css` | Kelas utilitas | -| 6 | `src/print.css` | Lapisan cetak | - -`dist/lombok.css` = konkatenasi; `dist/lombok.min.css` = minifikasi `lightningcss` (Node API). -`src/lombok.js` disalin apa adanya ke `dist/lombok.js`. - -## 3. JavaScript opsional - -IIFE tanpa dependensi; keluar lebih awal bila `document` tidak ada (aman untuk SSR). -Dua pola wiring: - -- **Delegasi di `document`** (bekerja untuk markup yang ditambahkan kemudian): dropdown, modal, drawer, popover, navbar. -- **Sekali saat parse** (`querySelectorAll`): tabs, carousel, sortir tabel, backdrop dialog. - -API global satu-satunya: `window.Lombok.toast()`. - -## 4. Anggaran & kualitas - -| Gerbang | Alat | Batas | -| --- | --- | --- | -| Ukuran | `scripts/size-check.mjs` | CSS ≤ 15 KB gzip, JS ≤ 4 KB gzip | -| SSR | `scripts/ssr-check.mjs` | Impor tanpa DOM tidak melempar | -| Perilaku | `tests/behavior.spec.js` (Playwright) | 44 test | -| Visual | `tests/visual.spec.js` | Baseline per gaya × tema | -| Lint | Super-Linter, Prettier | CSS, JS, JSON, YAML, Markdown | - -## 5. Keputusan arsitektur yang relevan - -| ADR | Dampak pada LombokCSS | -| --- | --- | -| ADR-015 | Perilaku JS dinormatifkan di [SPEC](SPEC_LombokCSS_v0.1.9.md) dan diuji `behavior.spec.js` | -| ADR-019 | README/manifest tanpa klaim kepemilikan aplikasi; checklist D1–D9 di masterplan | diff --git a/docs/changelog_LombokCSS_v0.1.9.md b/docs/changelog_LombokCSS_v0.1.9.md deleted file mode 100644 index 0326b13..0000000 --- a/docs/changelog_LombokCSS_v0.1.9.md +++ /dev/null @@ -1,28 +0,0 @@ -# Changelog — LombokCSS v0.1.9 - -| Atribut | Nilai | -| --- | --- | -| Repo | [codinglombok/LombokCSS](https://github.com/codinglombok/LombokCSS) | -| Versi library | 0.1.9 | -| Tingkat / cluster | L0 · 01 Frontend, UI & Visualisasi Data (katalog 01.01) | -| Acuan | MASTERPLAN_UTAMA v3.4 (2026-09-29) · ARCHITECTURE_UTAMA v3.4 · ADR-019 | -| Tanggal dokumen | 2026-09-30 | -| Lisensi | MIT (kebijakan §10: framework CSS) | - -Dokumen standar: [Masterplan](masterplan_LombokCSS_v0.1.9.md) · [Architecture](architecture_LombokCSS_v0.1.9.md) · [Changelog](changelog_LombokCSS_v0.1.9.md) · [Map](map_LombokCSS_v0.1.9.md) · [Structure Repo](structure_repo_LombokCSS_v0.1.9.md) · [Full Summary Project](full_summary_project_LombokCSS_v0.1.9.md) · [Guide How to Use](guide_how_to_use_LombokCSS_v0.1.9.md) · [How to Dist](how_to_dist_LombokCSS_v0.1.9.md) · [Development Ide](development_ide_LombokCSS_v0.1.9.md) · [API Reference](API_LombokCSS_v0.1.9.md) · [Bahasa (i18n)](Lang_LombokCSS_v0.1.9.md) · [Behavioral Specification](SPEC_LombokCSS_v0.1.9.md) - ---- - -Catatan rilis resmi yang ditulis release-please ada di [`CHANGELOG.md`](../CHANGELOG.md). -Dokumen ini mencatat perubahan terkait masterplan, entri terbaru di depan. - -## Belum dirilis — penyelarasan MASTERPLAN_UTAMA v3.4 - -- `docs/`: 12 dokumen standar `*_LombokCSS_v0.1.9.md` (§5.1) dengan checklist universalitas D1–D9, skor 6/9 (§5.2). -- README: bagian "Why this library? (Mengapa library ini?)", "Standards implemented", label ekosistem sebagai peer (ADR-019). -- Manifest (`package.json`, `composer.json`, `bower.json`, `lombokcss.gemspec`, NuGet/Maven di `publish-packages.yml`): "Part of Lombok Ecosystem". -- `lombok.js`: sortir tabel memakai `Intl.Collator` dari atribut `lang` terdekat (BCP 47), `numeric: true`, fallback aman; +2 test perilaku. - -## 0.1.9 — 2026-08-24 - -- Sinkronisasi pipeline publish semua registry GitHub Packages. diff --git a/docs/development_ide_LombokCSS_v0.1.9.md b/docs/development_ide_LombokCSS_v0.1.9.md deleted file mode 100644 index d281fa0..0000000 --- a/docs/development_ide_LombokCSS_v0.1.9.md +++ /dev/null @@ -1,38 +0,0 @@ -# Development Ide / Arah Pengembangan — LombokCSS v0.1.9 - -| Atribut | Nilai | -| --- | --- | -| Repo | [codinglombok/LombokCSS](https://github.com/codinglombok/LombokCSS) | -| Versi library | 0.1.9 | -| Tingkat / cluster | L0 · 01 Frontend, UI & Visualisasi Data (katalog 01.01) | -| Acuan | MASTERPLAN_UTAMA v3.4 (2026-09-29) · ARCHITECTURE_UTAMA v3.4 · ADR-019 | -| Tanggal dokumen | 2026-09-30 | -| Lisensi | MIT (kebijakan §10: framework CSS) | - -Dokumen standar: [Masterplan](masterplan_LombokCSS_v0.1.9.md) · [Architecture](architecture_LombokCSS_v0.1.9.md) · [Changelog](changelog_LombokCSS_v0.1.9.md) · [Map](map_LombokCSS_v0.1.9.md) · [Structure Repo](structure_repo_LombokCSS_v0.1.9.md) · [Full Summary Project](full_summary_project_LombokCSS_v0.1.9.md) · [Guide How to Use](guide_how_to_use_LombokCSS_v0.1.9.md) · [How to Dist](how_to_dist_LombokCSS_v0.1.9.md) · [Development Ide](development_ide_LombokCSS_v0.1.9.md) · [API Reference](API_LombokCSS_v0.1.9.md) · [Bahasa (i18n)](Lang_LombokCSS_v0.1.9.md) · [Behavioral Specification](SPEC_LombokCSS_v0.1.9.md) - ---- - -## 1. Lingkungan - -- Node ≥ 18, npm; Python 3 untuk `build_docs.py`. -- Editor: `.editorconfig` + Prettier (`npm run format`). -- Chromium Playwright untuk test (`npx playwright test`). - -## 2. Konvensi - -- Komponen **hanya** membaca token semantik `--lc-*`; nilai mentah hanya di `variables.css`/`themes.css`. -- Pakai logical properties (`margin-inline-start`, bukan `margin-left`) agar RTL gratis. -- Gaya gelap wajib meng-override token status `*-soft` dan `*-text`. -- Perilaku JS baru wajib: tercatat di [SPEC](SPEC_LombokCSS_v0.1.9.md), punya test di `behavior.spec.js`, muat anggaran 4 KB. -- Commit: Conventional Commits. - -## 3. Arah pengembangan - -| Arah | Alasan (dimensi) | -| --- | --- | -| SBOM + provenance npm di rilis | D5, Prinsip #8 | -| Paket token W3C Design Tokens (JSON) | D3/D4 — alat desain & library lain (mis. LombokCharts) dapat membaca token yang sama | -| Tooltip, validasi form opsional | D8 — menutup gap vs Bootstrap | -| Gaya ke-6 bertema aksesibilitas kontras tinggi (`forced-colors`) | D9 | -| Hapus folder `package/` | Kebersihan repo (C-03) | diff --git a/docs/full_summary_project_LombokCSS_v0.1.9.md b/docs/full_summary_project_LombokCSS_v0.1.9.md deleted file mode 100644 index 9584e1b..0000000 --- a/docs/full_summary_project_LombokCSS_v0.1.9.md +++ /dev/null @@ -1,58 +0,0 @@ -# Full Summary Project — LombokCSS v0.1.9 - -| Atribut | Nilai | -| --- | --- | -| Repo | [codinglombok/LombokCSS](https://github.com/codinglombok/LombokCSS) | -| Versi library | 0.1.9 | -| Tingkat / cluster | L0 · 01 Frontend, UI & Visualisasi Data (katalog 01.01) | -| Acuan | MASTERPLAN_UTAMA v3.4 (2026-09-29) · ARCHITECTURE_UTAMA v3.4 · ADR-019 | -| Tanggal dokumen | 2026-09-30 | -| Lisensi | MIT (kebijakan §10: framework CSS) | - -Dokumen standar: [Masterplan](masterplan_LombokCSS_v0.1.9.md) · [Architecture](architecture_LombokCSS_v0.1.9.md) · [Changelog](changelog_LombokCSS_v0.1.9.md) · [Map](map_LombokCSS_v0.1.9.md) · [Structure Repo](structure_repo_LombokCSS_v0.1.9.md) · [Full Summary Project](full_summary_project_LombokCSS_v0.1.9.md) · [Guide How to Use](guide_how_to_use_LombokCSS_v0.1.9.md) · [How to Dist](how_to_dist_LombokCSS_v0.1.9.md) · [Development Ide](development_ide_LombokCSS_v0.1.9.md) · [API Reference](API_LombokCSS_v0.1.9.md) · [Bahasa (i18n)](Lang_LombokCSS_v0.1.9.md) · [Behavioral Specification](SPEC_LombokCSS_v0.1.9.md) - ---- - -## 1. Ringkasan - -LombokCSS menggabungkan pendekatan komponen (seperti Bootstrap) dengan theming berbasis -token (seperti design system) dalam paket kecil (seperti Pico). Satu atribut mengganti -identitas visual seluruh halaman tanpa menyentuh HTML. - -| Metrik | Nilai | -| --- | --- | -| Versi | 0.1.9 | -| CSS min + gzip | ~9,7 KB (anggaran 15 KB) | -| JS gzip | ~3,1 KB (anggaran 4 KB) | -| Dependensi runtime | 0 | -| Gaya desain | 5 | -| Test perilaku | 44 (Playwright) | -| Skor universalitas | 6/9 | - -## 2. Fitur - -Komponen: accordion, alert, avatar, badge, breadcrumb, button (+group), card, carousel, -checkbox/switch, drawer/offcanvas, dropdown, field/input/select/textarea/file, input-group, -list-group, modal (``), navbar, pagination, popover, progress, sidebar, skeleton, -spinner, stat, steps, table (striped/hover/bordered/sortable), tabs, timeline, toast. -Ditambah utilitas, mode classless, lapisan cetak, mode gelap, RTL. - -## 3. Tabel gap vs pembanding - -| Kemampuan | LombokCSS | Bootstrap 5 | Pico | Bulma | DaisyUI | -| --- | --- | --- | --- | --- | --- | -| Ganti identitas visual tanpa ubah HTML | ✅ 5 gaya | ❌ | ❌ | ❌ | ✅ (butuh Tailwind build) | -| Mode gelap | ✅ | ✅ | ✅ | ✅ | ✅ | -| RTL tanpa build terpisah | ✅ logical props | ❌ (CSS RTL terpisah) | ✅ | ❌ | ✅ | -| Tanpa build step | ✅ | ✅ | ✅ | ✅ | ❌ | -| Ukuran gzip | ~10 KB | ~25 KB + JS | ~10 KB | ~25 KB | tergantung | -| Tooltip JS | ❌ (popover saja) | ✅ | ❌ | ❌ | ✅ CSS | -| Scrollspy | ❌ | ✅ | ❌ | ❌ | ❌ | -| Validasi form JS | ❌ (state CSS saja) | ✅ | ❌ | ❌ | ❌ | -| Sortir tabel sadar-bahasa | ✅ | ❌ | ❌ | ❌ | ❌ | -| Lapisan cetak | ✅ | sebagian | ❌ | ❌ | ❌ | - -## 4. Status - -🟢 LIVE di npm dan GitHub Packages; kepatuhan MASTERPLAN_UTAMA v3.4 diselaraskan pada -branch ini. Temuan terbuka: lihat [Masterplan](masterplan_LombokCSS_v0.1.9.md) §5. diff --git a/docs/guide_how_to_use_LombokCSS_v0.1.9.md b/docs/guide_how_to_use_LombokCSS_v0.1.9.md deleted file mode 100644 index d4494d5..0000000 --- a/docs/guide_how_to_use_LombokCSS_v0.1.9.md +++ /dev/null @@ -1,75 +0,0 @@ -# Guide How to Use — LombokCSS v0.1.9 - -| Atribut | Nilai | -| --- | --- | -| Repo | [codinglombok/LombokCSS](https://github.com/codinglombok/LombokCSS) | -| Versi library | 0.1.9 | -| Tingkat / cluster | L0 · 01 Frontend, UI & Visualisasi Data (katalog 01.01) | -| Acuan | MASTERPLAN_UTAMA v3.4 (2026-09-29) · ARCHITECTURE_UTAMA v3.4 · ADR-019 | -| Tanggal dokumen | 2026-09-30 | -| Lisensi | MIT (kebijakan §10: framework CSS) | - -Dokumen standar: [Masterplan](masterplan_LombokCSS_v0.1.9.md) · [Architecture](architecture_LombokCSS_v0.1.9.md) · [Changelog](changelog_LombokCSS_v0.1.9.md) · [Map](map_LombokCSS_v0.1.9.md) · [Structure Repo](structure_repo_LombokCSS_v0.1.9.md) · [Full Summary Project](full_summary_project_LombokCSS_v0.1.9.md) · [Guide How to Use](guide_how_to_use_LombokCSS_v0.1.9.md) · [How to Dist](how_to_dist_LombokCSS_v0.1.9.md) · [Development Ide](development_ide_LombokCSS_v0.1.9.md) · [API Reference](API_LombokCSS_v0.1.9.md) · [Bahasa (i18n)](Lang_LombokCSS_v0.1.9.md) · [Behavioral Specification](SPEC_LombokCSS_v0.1.9.md) - ---- - -## 1. Pasang - -```html - - -``` - -```bash -npm install lombokcss # atau: composer require codinglombok/lombokcss -``` - -```js -import "lombokcss/css"; -import "lombokcss"; // opsional, komponen interaktif -``` - -## 2. Pilih gaya, tema, arah - -```html - -``` - -| Atribut | Nilai | -| --- | --- | -| `data-style` | `modern-corporate-flat` (default) · `resonant-stark` · `neo-brutalism` · `semantic-minimalist` · `glassmorphism` | -| `data-theme` | `light` · `dark` (tanpa atribut: ikuti `prefers-color-scheme`) | -| `dir` | `ltr` · `rtl` | -| `lang` | Tag BCP 47; dipakai sortir tabel untuk urutan alfabet bahasa tersebut | - -## 3. Komponen dasar - -```html - -
Tersimpan.
-

Judul

-``` - -## 4. Rebrand dengan token - -```css -:root { --lc-accent: #0f766e; --lc-radius: 0.25rem; --lc-font-sans: "Inter", system-ui; } -``` - -## 5. Komponen interaktif (butuh `lombok.js`) - -```html - - - - - - -
Nama
Äpple
Zebra
-``` - -```js -Lombok.toast("Tersimpan", { variant: "success", timeout: 3000 }); -``` - -Dokumentasi lengkap: . diff --git a/docs/how_to_dist_LombokCSS_v0.1.9.md b/docs/how_to_dist_LombokCSS_v0.1.9.md deleted file mode 100644 index 4d41aa9..0000000 --- a/docs/how_to_dist_LombokCSS_v0.1.9.md +++ /dev/null @@ -1,48 +0,0 @@ -# How to Dist — LombokCSS v0.1.9 - -| Atribut | Nilai | -| --- | --- | -| Repo | [codinglombok/LombokCSS](https://github.com/codinglombok/LombokCSS) | -| Versi library | 0.1.9 | -| Tingkat / cluster | L0 · 01 Frontend, UI & Visualisasi Data (katalog 01.01) | -| Acuan | MASTERPLAN_UTAMA v3.4 (2026-09-29) · ARCHITECTURE_UTAMA v3.4 · ADR-019 | -| Tanggal dokumen | 2026-09-30 | -| Lisensi | MIT (kebijakan §10: framework CSS) | - -Dokumen standar: [Masterplan](masterplan_LombokCSS_v0.1.9.md) · [Architecture](architecture_LombokCSS_v0.1.9.md) · [Changelog](changelog_LombokCSS_v0.1.9.md) · [Map](map_LombokCSS_v0.1.9.md) · [Structure Repo](structure_repo_LombokCSS_v0.1.9.md) · [Full Summary Project](full_summary_project_LombokCSS_v0.1.9.md) · [Guide How to Use](guide_how_to_use_LombokCSS_v0.1.9.md) · [How to Dist](how_to_dist_LombokCSS_v0.1.9.md) · [Development Ide](development_ide_LombokCSS_v0.1.9.md) · [API Reference](API_LombokCSS_v0.1.9.md) · [Bahasa (i18n)](Lang_LombokCSS_v0.1.9.md) · [Behavioral Specification](SPEC_LombokCSS_v0.1.9.md) - ---- - -## 1. Alur rilis - -```text -commit Conventional (fix:/feat:) → push main → release-please membuka PR rilis - → merge → GitHub Release + tag lombokcss-vX.Y.Z - → npm-publish.yml → npmjs.org (jsDelivr/unpkg otomatis) - → publish-packages.yml → GitHub Packages: npm, RubyGems, NuGet, Maven, Container - → pages.yml → situs docs (build + build:docs) -``` - -Panduan langkah demi langkah (secret, branch protection, Pages): [`GITHUB_SETUP.md`](../GITHUB_SETUP.md). - -## 2. Pemeriksaan sebelum rilis - -```bash -npm ci -npm run build # dist/ dari src/ -npm test # anggaran ukuran + SSR guard -npm run test:behavior # 44 test perilaku -npm run test:visual # baseline visual (container Playwright v1.56.0-noble) -npm run lint # Prettier -``` - -## 3. Versi - -Versi tunggal di `package.json`, `composer.json`, `lib/lombokcss/version.rb` dan -`.release-please-manifest.json` — dinaikkan oleh release-please. -Saat versi minor naik, rename manual `docs/*_LombokCSS_v.md` (temuan C-06). - -## 4. Deskripsi registry (ADR-019) - -Semua field deskripsi menyebut fungsi universal + "Part of Lombok Ecosystem" dan tidak -boleh menyebut aplikasi/framework sebagai pemilik. diff --git a/docs/map_LombokCSS_v0.1.9.md b/docs/map_LombokCSS_v0.1.9.md deleted file mode 100644 index 1c9727a..0000000 --- a/docs/map_LombokCSS_v0.1.9.md +++ /dev/null @@ -1,57 +0,0 @@ -# Map — LombokCSS v0.1.9 - -| Atribut | Nilai | -| --- | --- | -| Repo | [codinglombok/LombokCSS](https://github.com/codinglombok/LombokCSS) | -| Versi library | 0.1.9 | -| Tingkat / cluster | L0 · 01 Frontend, UI & Visualisasi Data (katalog 01.01) | -| Acuan | MASTERPLAN_UTAMA v3.4 (2026-09-29) · ARCHITECTURE_UTAMA v3.4 · ADR-019 | -| Tanggal dokumen | 2026-09-30 | -| Lisensi | MIT (kebijakan §10: framework CSS) | - -Dokumen standar: [Masterplan](masterplan_LombokCSS_v0.1.9.md) · [Architecture](architecture_LombokCSS_v0.1.9.md) · [Changelog](changelog_LombokCSS_v0.1.9.md) · [Map](map_LombokCSS_v0.1.9.md) · [Structure Repo](structure_repo_LombokCSS_v0.1.9.md) · [Full Summary Project](full_summary_project_LombokCSS_v0.1.9.md) · [Guide How to Use](guide_how_to_use_LombokCSS_v0.1.9.md) · [How to Dist](how_to_dist_LombokCSS_v0.1.9.md) · [Development Ide](development_ide_LombokCSS_v0.1.9.md) · [API Reference](API_LombokCSS_v0.1.9.md) · [Bahasa (i18n)](Lang_LombokCSS_v0.1.9.md) · [Behavioral Specification](SPEC_LombokCSS_v0.1.9.md) - ---- - -## 1. Posisi di peta ekosistem - -```text -A Aplikasi ── boleh menyatakan "menggunakan LombokCSS" -P Framework ── boleh menyatakan "menggunakan LombokCSS" -L1 LombokUI ── dependensi wajib: LombokCSS, LombokIcons, LombokAnimate -══ BATAS KLAIM (ADR-019) ══ -L0 LombokCSS ── tanpa dependensi; tidak mengaku milik entitas di atasnya -``` - -## 2. Dependensi - -| Jenis | Daftar | -| --- | --- | -| Wajib (runtime) | — (nol) | -| Opsional (runtime) | — | -| Dev | `lightningcss`, `prettier`, `@playwright/test` | -| Peer yang bekerja berdampingan | LombokIcons, LombokAnimate, LombokCharts, LombokTableSheet (tanpa integrasi kode) | - -## 3. Contoh dependen (bukan pemilik) - -| Repo | Tingkat | Hubungan | -| --- | --- | --- | -| LombokUI | L1 | Katalog v3.4 mencantumkan LombokCSS sebagai dependensi wajib | - -## 4. Peta distribusi - -| Kanal | Nama | -| --- | --- | -| npm | `lombokcss` | -| CDN | jsDelivr / unpkg `lombokcss` | -| Packagist | `codinglombok/lombokcss` | -| RubyGems (GPR) | `lombokcss` | -| Bower | `lombokcss` | -| NuGet (GPR) | `codinglombok.LombokCSS` | -| Maven (GPR) | `com.github.codinglombok:lombokcss` | -| Container (GHCR) | `ghcr.io/codinglombok/lombokcss` | -| SourceForge | mirror `lombokcss` | - -## 5. Peta platform - -Browser desktop/mobile evergreen · WebView iOS/Android · Electron/Tauri · SSR (Node) · panel web perangkat embedded (kiosk, router, gateway IoT). diff --git a/docs/masterplan_LombokCSS_v0.1.9.md b/docs/masterplan_LombokCSS_v0.1.9.md deleted file mode 100644 index 58ddb1d..0000000 --- a/docs/masterplan_LombokCSS_v0.1.9.md +++ /dev/null @@ -1,94 +0,0 @@ -# Masterplan — LombokCSS v0.1.9 - -| Atribut | Nilai | -| --- | --- | -| Repo | [codinglombok/LombokCSS](https://github.com/codinglombok/LombokCSS) | -| Versi library | 0.1.9 | -| Tingkat / cluster | L0 · 01 Frontend, UI & Visualisasi Data (katalog 01.01) | -| Acuan | MASTERPLAN_UTAMA v3.4 (2026-09-29) · ARCHITECTURE_UTAMA v3.4 · ADR-019 | -| Tanggal dokumen | 2026-09-30 | -| Lisensi | MIT (kebijakan §10: framework CSS) | - -Dokumen standar: [Masterplan](masterplan_LombokCSS_v0.1.9.md) · [Architecture](architecture_LombokCSS_v0.1.9.md) · [Changelog](changelog_LombokCSS_v0.1.9.md) · [Map](map_LombokCSS_v0.1.9.md) · [Structure Repo](structure_repo_LombokCSS_v0.1.9.md) · [Full Summary Project](full_summary_project_LombokCSS_v0.1.9.md) · [Guide How to Use](guide_how_to_use_LombokCSS_v0.1.9.md) · [How to Dist](how_to_dist_LombokCSS_v0.1.9.md) · [Development Ide](development_ide_LombokCSS_v0.1.9.md) · [API Reference](API_LombokCSS_v0.1.9.md) · [Bahasa (i18n)](Lang_LombokCSS_v0.1.9.md) · [Behavioral Specification](SPEC_LombokCSS_v0.1.9.md) - ---- - -## 1. Identitas & posisi - -**LombokCSS** adalah framework CSS komponen berbasis token yang universal: satu markup, -lima gaya desain (`modern-corporate-flat`, `resonant-stark`, `neo-brutalism`, -`semantic-minimalist`, `glassmorphism`), mode gelap dan RTL sebagai sumbu independen. -Ukuran ~9,7 KB gzip (CSS) + JS opsional ~3 KB gzip; nol dependensi runtime. - -Posisi (netral-domain): lapisan presentasi untuk UI berbasis mesin browser apa pun. -LombokCSS adalah produk mandiri — **bukan komponen dari aplikasi atau framework mana pun** -(Prinsip #11, ADR-019). Aplikasi/framework yang memakainya dicatat hanya sebagai -*contoh pemakai* di [Map](map_LombokCSS_v0.1.9.md). - -## 2. Skenario pemakaian (Prinsip #1) - -| # | Skenario | Pemakai | -| --- | --- | --- | -| 1 | Situs landing/marketing & dokumentasi statis tanpa build step (CDN) | Indie developer, agensi | -| 2 | Dasbor SaaS / panel admin dengan rebrand via token dan mode gelap | Startup, tim produk | -| 3 | Formulir layanan publik bilingual, termasuk bahasa RTL (Arab) | E-government | -| 4 | Panel web perangkat (router, gateway IoT, kiosk/HMI) yang disajikan dari flash terbatas | Pembuat hardware | -| 5 | Aplikasi hibrid di WebView iOS/Android, Electron/Tauri | Tim mobile/desktop | -| 6 | Design system perusahaan: satu set komponen, beberapa merek (gaya kustom) | Enterprise | -| 7 | Dokumen cetak (invoice, laporan) lewat lapisan `print.css` | Semua | - -## 3. Checklist Universalitas (ADR-019) - -| Dimensi | Status | Keterangan | -| --- | --- | --- | -| D1 — Multi-kebutuhan | ✅ | 7 skenario di §2: landing, dasbor, e-gov RTL, panel perangkat, WebView, design system, cetak | -| D2 — Multi-platform | ✅ | Browser desktop & mobile evergreen, WebView iOS/Android, Electron/Tauri, SSR (Next/Nuxt/Astro/SvelteKit — impor aman tanpa DOM, diuji `scripts/ssr-check.mjs`), panel web perangkat embedded | -| D3 — Multi-bahasa | ✅ | Aset CSS/JS bahasa-agnostik; distribusi identik (byte sama) lewat npm, Composer, RubyGems, Bower, NuGet & Maven (GitHub Packages), container, CDN jsDelivr/unpkg | -| D4 — Ekosistem Lombok | N/A | L0 zero-dependency by design; tidak memakai library Lombok lain. Bekerja berdampingan (peer opsional) dengan LombokIcons, LombokAnimate, LombokCharts, LombokTableSheet | -| D5 — Keamanan | ⏳ | CodeQL, OSSAR, Defender for DevOps, dependency-review, action di-pin SHA, JS tanpa jaringan/storage. Belum ada SBOM rilis; kontak email di `SECURITY.md` masih placeholder (temuan C-02) | -| D6 — Keunikan (SOTA) | ✅ | Satu markup → lima gaya desain via satu atribut `data-style`, dikomposisi dengan `data-theme` dan `dir`; pembanding (Bootstrap, Bulma, Pico, DaisyUI) mengikat tampilan ke komponen atau ke build step | -| D7 — Skala pengguna | ✅ | Indie (CDN satu baris) → startup (npm) → enterprise (override token/gaya kustom, paket GitHub Packages) | -| D8 — Kelengkapan | ⏳ | 40+ komponen, utilitas, mode classless, lapisan cetak, tabel sortir sadar-bahasa. Gap vs Bootstrap: tooltip JS, scrollspy, validasi form JS, date picker (lihat [Full Summary](full_summary_project_LombokCSS_v0.1.9.md) §3) | -| D9 — Standar internasional | ✅ | WCAG 2.2 AA (kontras gaya bawaan), WAI-ARIA 1.2 + APG (tabs, dialog, disclosure, sortable table), CSS Logical Properties, Media Queries L5, BCP 47 (`lang` → `Intl.Collator`), WHATWG HTML (``, `
`) | - -Skor: **6/9 ✅** (D1, D2, D3, D6, D7, D9) — memenuhi ambang rilis registry publik (≥6/9). -Penilaian mandiri; belum ada review independen. - -## 4. Kepatuhan dokumen & README (MASTERPLAN_UTAMA v3.4 §5) - -| Syarat | Status | -| --- | --- | -| 12 dokumen standar (§5.1) | ✅ `docs/*_LombokCSS_v0.1.9.md` | -| Checklist universalitas (§5.2) | ✅ §3 dokumen ini | -| README "Why this library? (Mengapa library ini?)" (§5.3) | ✅ | -| README "Standards implemented" | ✅ | -| README "Lombok Ecosystem" berlabel peer, bukan pemilik | ✅ | -| Deskripsi manifest (npm, Composer, gem, Bower, NuGet, Maven) tanpa klaim aplikasi + "Part of Lombok Ecosystem" | ✅ | -| Deskripsi GitHub (About) | ⏳ Perlu diubah manual oleh pemilik (lihat §6) | -| Audit pola terlarang (ARCHITECTURE v3.4 §4) | ✅ nol kecocokan (`part of Lombok[A-Z]`, `library #`, `component of`, `for Lombok(RAG\|PDF\|Agentic)`) | - -## 5. Temuan audit repo (v3.4) - -| ID | Temuan | Severity | Status | -| --- | --- | --- | --- | -| C-01 | README belum memuat bagian "Mengapa library ini?" & "Standar" (U-004) | 🟡 Rendah | ✅ Diperbaiki | -| C-02 | `SECURITY.md` memakai email placeholder `security@your-domain.example` | 🟠 Sedang | ❌ OPEN — pemilik perlu menetapkan alamat nyata | -| C-03 | Folder `package/` adalah salinan lama (README & dist tidak sinkron dengan root) dan tidak dipakai `files` npm | 🟡 Rendah | ❌ OPEN — usul dihapus | -| C-04 | Belum ada SBOM di rilis (Prinsip #8) | 🟡 Rendah | ❌ OPEN — target 0.2.0 | -| C-05 | Sortir tabel memakai `localeCompare()` tanpa locale → urutan tidak sesuai bahasa halaman (Prinsip #6, D9) | 🟡 Rendah | ✅ Diperbaiki: `Intl.Collator` dari `lang` terdekat, `numeric: true`, fallback aman untuk tag rusak (+2 test) | -| C-06 | Nama dokumen standar mengikat versi; release-please tidak mengganti nama berkas | 🟡 Rendah | ❌ OPEN — rename manual saat rilis minor | - -## 6. Tindakan manual pemilik - -1. GitHub → Settings → About, deskripsi: - `Universal token-first CSS framework — one markup, five design styles, dark mode + RTL, ~10 KB gzip, zero dependencies. Part of Lombok Ecosystem. MIT.` -2. Isi alamat kontak keamanan nyata di `SECURITY.md` (C-02). - -## 7. Roadmap - -| Versi | Fokus | -| --- | --- | -| 0.1.x | Kepatuhan v3.4 (dokumen, README, manifest), perbaikan bug | -| 0.2.0 | SBOM + provenance di rilis; hapus `package/`; tooltip & validasi form opsional; dokumen di-rename ke v0.2.0 | -| 0.3.0 | Paket token (JSON, W3C Design Tokens format) untuk dikonsumsi alat desain & library lain | -| 1.0.0 | API kelas & token dibekukan (semver penuh) | diff --git a/docs/structure_repo_LombokCSS_v0.1.9.md b/docs/structure_repo_LombokCSS_v0.1.9.md deleted file mode 100644 index 3b415a6..0000000 --- a/docs/structure_repo_LombokCSS_v0.1.9.md +++ /dev/null @@ -1,35 +0,0 @@ -# Structure Repo — LombokCSS v0.1.9 - -| Atribut | Nilai | -| --- | --- | -| Repo | [codinglombok/LombokCSS](https://github.com/codinglombok/LombokCSS) | -| Versi library | 0.1.9 | -| Tingkat / cluster | L0 · 01 Frontend, UI & Visualisasi Data (katalog 01.01) | -| Acuan | MASTERPLAN_UTAMA v3.4 (2026-09-29) · ARCHITECTURE_UTAMA v3.4 · ADR-019 | -| Tanggal dokumen | 2026-09-30 | -| Lisensi | MIT (kebijakan §10: framework CSS) | - -Dokumen standar: [Masterplan](masterplan_LombokCSS_v0.1.9.md) · [Architecture](architecture_LombokCSS_v0.1.9.md) · [Changelog](changelog_LombokCSS_v0.1.9.md) · [Map](map_LombokCSS_v0.1.9.md) · [Structure Repo](structure_repo_LombokCSS_v0.1.9.md) · [Full Summary Project](full_summary_project_LombokCSS_v0.1.9.md) · [Guide How to Use](guide_how_to_use_LombokCSS_v0.1.9.md) · [How to Dist](how_to_dist_LombokCSS_v0.1.9.md) · [Development Ide](development_ide_LombokCSS_v0.1.9.md) · [API Reference](API_LombokCSS_v0.1.9.md) · [Bahasa (i18n)](Lang_LombokCSS_v0.1.9.md) · [Behavioral Specification](SPEC_LombokCSS_v0.1.9.md) - ---- - -```text -LombokCSS/ -├── README.md · CHANGELOG.md · LICENSE (MIT) · SECURITY.md · SUPPORT.md -├── CONTRIBUTING.md · CODE_OF_CONDUCT.md · GITHUB_SETUP.md · CLAUDE.md (memori sesi) -├── package.json · package-lock.json · composer.json · bower.json -├── lombokcss.gemspec · lib/lombokcss(.rb, /version.rb) # RubyGem -├── release-please-config.json · .release-please-manifest.json -├── playwright.config.js · build_docs.py (generator situs docs/) -├── src/ variables · core · themes · components · utilities · print (.css) · lombok.js -├── dist/ lombok.css · lombok.min.css · lombok.js (hasil build, di-commit) -├── scripts/ build-css.mjs · size-check.mjs · ssr-check.mjs -├── tests/ behavior.spec.js · visual.spec.js · visual.spec.js-snapshots/ -├── docs/ situs GitHub Pages (*.html, assets/) + 12 dokumen standar *_LombokCSS_v0.1.9.md -├── examples/ demo.html -├── package/ salinan lama paket (tidak dipublikasikan; temuan C-03) -└── .github/ workflows/ · linters/ · ISSUE_TEMPLATE/ · dependabot.yml · CODEOWNERS -``` - -Catatan: `demo.html` di root adalah halaman demo mandiri; `docs/assets/lombok.js` dan -`docs/assets/lombok.min.css` disinkronkan dari `dist/` oleh `npm run build:docs`. diff --git a/package/LICENSE b/package/LICENSE deleted file mode 100644 index d447392..0000000 --- a/package/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2026 codinglombok - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/package/README.md b/package/README.md deleted file mode 100644 index 9c5ef3d..0000000 --- a/package/README.md +++ /dev/null @@ -1,488 +0,0 @@ -# LombokCSS - -> **Switch the look, not the HTML.** -> A modern, **token-first** component CSS framework. Drop a class, get a working -> component — like Bootstrap. Re-theme everything by changing **one attribute** — -> like a design system. Ships at **~9.7 KB gzipped** (full build, minified). - -```text -Component-based (Bootstrap) + Token-driven theming (design systems) + Tiny (Pico/UnoCSS) -``` - ---- - -## GitHub - -[![CI](https://github.com/codinglombok/lombokcss/actions/workflows/ci.yml/badge.svg)](https://github.com/codinglombok/lombokcss/actions/workflows/ci.yml) -[![Deploy docs](https://github.com/codinglombok/lombokcss/actions/workflows/pages.yml/badge.svg)](https://github.com/codinglombok/lombokcss/actions/workflows/pages.yml) -[![license](https://img.shields.io/npm/l/lombokcss.svg)](LICENSE) - ---- - -## NPM - -[![npm version](https://img.shields.io/npm/v/lombokcss.svg)](https://www.npmjs.com/package/lombokcss) -[![npm downloads](https://img.shields.io/npm/dm/lombokcss.svg)](https://www.npmjs.com/package/lombokcss) -[![jsDelivr hits](https://img.shields.io/jsdelivr/npm/hm/lombokcss.svg)](https://www.jsdelivr.com/package/npm/lombokcss) -![gzip size](https://img.shields.io/badge/gzip-9.7%20KB-success.svg) - ---- - -## Sourceforge.net - -[![Download LombokCSS](https://a.fsdn.com/con/app/sf-download-button)](https://sourceforge.net/projects/lombokcss/files/latest/download) -[![Download LombokCSS](https://img.shields.io/sourceforge/dm/lombokcss.svg)](https://sourceforge.net/projects/lombokcss/files/latest/download) -[![Download LombokCSS](https://img.shields.io/sourceforge/dw/lombokcss.svg)](https://sourceforge.net/projects/lombokcss/files/latest/download) -[![Download LombokCSS](https://img.shields.io/sourceforge/dd/lombokcss.svg)](https://sourceforge.net/projects/lombokcss/files/latest/download) -[![Download LombokCSS](https://img.shields.io/sourceforge/dt/lombokcss.svg)](https://sourceforge.net/projects/lombokcss/files/latest/download) - ---- - -[![LombokCSS Preview](docs/assets/social-preview-hd.webp)](https://codinglombok.github.io/LombokCSS/) -[![LombokCSS Preview](docs/assets/preview.png)](https://codinglombok.github.io/LombokCSS/) - ---- - -## Documentation - -| | | -| ----------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | -| **Overview** | **Getting Started** | -| [![Overview](docs/assets/index-resonant-stark-quarter.webp)](https://codinglombok.github.io/LombokCSS/index.html) | [![Getting Started](docs/assets/getting-started-modern-corporate-flat-quarter.webp)](https://codinglombok.github.io/LombokCSS/getting-started.html) | -| **Migration from Bootstrap** | **Theming & Styles** | -| [![Migration from Bootstrap](docs/assets/migration-resonant-stark-quarter.webp)](https://codinglombok.github.io/LombokCSS/migration.html) | [![Theming & Styles](docs/assets/theming-modern-corporate-flat-quarter.webp)](https://codinglombok.github.io/LombokCSS/theming.html) | -| **Components** | **Forms** | -| [![Components](docs/assets/components-neo-brutalism-quarter.webp)](https://codinglombok.github.io/LombokCSS/components.html) | [![Forms](docs/assets/forms-glassmorphism-quarter.webp)](https://codinglombok.github.io/LombokCSS/forms.html) | -| **Utilities** | **Accessibility** | -| [![Utilities](docs/assets/utilities-semantic-minimalist-quarter.webp)](https://codinglombok.github.io/LombokCSS/utilities.html) | [![Accessibility](docs/assets/accessibility-semantic-minimalist-quarter.webp)](https://codinglombok.github.io/LombokCSS/accessibility.html) | - ---- - -## Why it's different - -Most frameworks bake their look into each component, so changing the visual -style means overriding hundreds of rules. LombokCSS inverts that: - -- **Components read only semantic tokens** (`--lc-surface`, `--lc-text`, `--lc-radius`, `--lc-shadow`, `--lc-accent`, …). -- **A "design style" is just a different set of token values.** Switching it never touches component CSS or your HTML. - -```html - - - - - - - - - - -``` - -Dark mode (`data-theme`) and RTL (`dir`) are **independent** axes that compose -with any style. - ---- - -## Install - -**CDN (jsDelivr)** — fastest start: - -```html - - -``` - -**npm:** - -```bash -npm install lombokcss -# or: yarn add lombokcss / pnpm add lombokcss -``` - -```js -import "lombokcss/dist/lombok.min.css"; -import "lombokcss/dist/lombok.js"; // optional, only for interactive components -``` - -Pin a version for production (jsDelivr): - -```html - -``` - -**Download:** grab `dist/lombok.min.css` (+ optional `dist/lombok.js`) and link them directly. - -The JS is **optional**. Accordions, modals and `` work natively without -it; the script only adds dropdown/tab/toast/table-sort/navbar-toggle behavior. - ---- - -**Other registries.** Also distributed via Composer (`composer require codinglombok/lombokcss`), -RubyGems (`gem "lombokcss"` → `Lombokcss.assets_path` for Sprockets), and Bower -(legacy: `bower install lombokcss`, prefer npm). Works with any bundler -(Vite/Webpack/Parcel) and framework (Vue/React/Svelte) — just import the CSS. -See the **Getting started** docs for per-tool snippets. - -## Documentation site - -A full multi-page docs site lives in `docs/` (Overview, Getting started, Theming -& styles, Components, Utilities). Open `docs/index.html` in a browser. The style -/ dark / RTL switchers at the top apply live and **follow you across pages** via -the URL query string. A single-file interactive playground is at -`examples/demo.html`. - -## Architecture - -```text -src/ - variables.css → token architecture (the contract every component depends on) - core.css → reset/reboot + base element styles (= classless mode) - themes.css → token value sets per design preset (data-style) - components.css → all components (read tokens only, RTL-safe, glass-aware) - utilities.css → atomic utilities + responsive prefixes -dist/ - lombok.css → bundled, unminified (readable) - lombok.min.css → bundled + minified (ship this) - lombok.js → optional interactive behaviors -``` - -### Token layers - -1. **Primitives & scale** — spacing, font sizes, raw palette. -2. **Semantic tokens** — `--lc-surface`, `--lc-text`, `--lc-border`, `--lc-accent`, `--lc-radius`, `--lc-shadow`, `--lc-blur`, status colors. **Components only ever reference these.** -3. **Style presets** (`[data-style="…"]`) re-map the semantic tokens. -4. **Dark overlay** (`[data-theme="dark"]` / `prefers-color-scheme`) re-maps color tokens; composes with presets via `[data-style][data-theme]` pairs. - -Glassmorphism support is built into the contract: every surface component -applies `backdrop-filter: var(--lc-blur)`. `--lc-blur` is `none` everywhere -except the glass preset, so the property is inert until a glass theme turns it -on — no per-component glass code. - ---- - -## The five design styles - -| `data-style` | Character | -| ----------------------- | ------------------------------------------------------------------------------------------- | -| `modern-corporate-flat` | Clean, flat, neutral + one brand color, medium radius, soft shadows (default) | -| `resonant-stark` | Linear-style dark: high contrast, subtle borders, tight type, violet accent | -| `neo-brutalism` | Thick black borders, hard offset shadows, bold blocks, zero radius | -| `semantic-minimalist` | Minimal, neutral, generous spacing, serif display, readability-first | -| `glassmorphism` | Frosted glass over a gradient; translucent surfaces, glowing borders (with opaque fallback) | - ---- - -## Theming guide - -Everything is a CSS variable. Override on `:root` (or a scope) to customize: - -```css -:root { - --lc-accent: #e11d48; /* brand color */ - --lc-accent-hover: #be123c; - --lc-radius: 4px; /* tighter corners */ - --lc-font-sans: "Inter", system-ui, sans-serif; - --lc-space-4: 1.1rem; /* rescale spacing */ -} -``` - -**Dark mode** — three ways, they all work together: - -```html - - - - - - - - - -``` - -**RTL** — set the document direction; all components use logical properties: - -```html - -``` - -**Make your own style** — add a token block, no component edits: - -```css -[data-style="sunset"] { - --lc-bg: #1a0f0f; - --lc-surface: #2a1818; - --lc-text: #ffe; - --lc-accent: #ff7849; - --lc-radius: 14px; - --lc-shadow: 0 8px 24px rgba(0, 0, 0, 0.4); -} -``` - ---- - -## Component usage - -```html - - - - - - - - -
-
-

Title

-

Body copy.

-
- -
- - -
-
- - - We never share it. - Enter a valid email. -
- -
- - -
-
-
Saved
- All good. -
-
-new - - -
- - -
-
…
- - - -
-
- Q -
A
-
-
- - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
NameMRR
Nadia49
-
- - - - - - - - - - -
- -
-
Title
-

Rich content.

-
-
- - - - - -
    -
  • -
    09:00
    -
    Event
    -

    Detail.

    -
  • -
-``` - -Other components included: `navbar` (+ mobile toggle), `breadcrumb`, -`pagination`, `avatar`/`avatar-group`, `progress`, `spinner`, `skeleton`, -`stat`, `list-group`, `steps`, CSS-only tooltip (`data-tip="…"`), `kbd`, `code`/`pre`. - -### Utilities - -Layout (`flex`, `grid`, `items-*`, `justify-*`, `gap-*`, `grid-cols-1..12`), -spacing (`p-*`, `m-*`, logical), sizing (`w-full`, `max-w-*`, `min-h-screen`), -type (`text-sm..3xl`, `font-*`, `text-start/center/end`), color -(`bg-surface`, `text-muted`, `border`), radius/shadow, position/z-index, plus -responsive prefixes `sm: md: lg: xl:` (e.g. `md:grid-cols-3`). - -### Classless mode - -Plain semantic HTML is styled with zero classes — headings, paragraphs, links, -lists, `blockquote`, `table`, form inputs, `code`/`pre`/`kbd`. Good for prose -and quick prototypes. - ---- - -## Build process - -The dist files are produced with **Lightning CSS**: - -```bash -# bundle the modules in order -cat src/variables.css src/core.css src/themes.css \ - src/components.css src/utilities.css > dist/lombok.css - -# minify (autoprefix + dead-code removal) -npx lightningcss --minify --bundle dist/lombok.css -o dist/lombok.min.css -``` - -PostCSS equivalent: `postcss-import` + `autoprefixer` + `cssnano`. - -### Shrinking further - -- **Split core vs full:** ship `variables + core + themes + components` and add - `utilities.css` only if you use utility classes. -- **Purge unused utilities** with your bundler's CSS purge step keyed on your - templates. -- Drop presets you don't use from `themes.css`. - ---- - -## Browser support & accessibility - -Modern CSS used with graceful fallbacks: `:has()`, `:user-invalid`, -`accent-color`, `backdrop-filter` (opaque fallback via `@supports`), logical -properties, native ``/`
`. Components ship with visible -`:focus-visible` rings, ARIA hooks, and respect `prefers-reduced-motion`. - -## Testing - -Visual-regression tests (Playwright) screenshot the buttons block across all -five styles plus dark/RTL, and the form validation state, comparing against -committed baselines in `tests/**-snapshots/`. - -```bash -npm run test:visual # compare against baselines -npm run test:visual:update # refresh baselines after an intentional change -``` - -Baselines are browser-specific. CI runs in a pinned Playwright container -(`mcr.microsoft.com/playwright:v1.56.0-noble`) so pixels match. When you change -visuals on purpose, refresh baselines **inside that image** so they match CI: - -```bash -docker run --rm -v "$PWD":/work -w /work mcr.microsoft.com/playwright:v1.56.0-noble \ - bash -c "npm ci && npm run build && npm run build:docs && npm run test:visual:update" -``` - -A failing run uploads a `playwright-report` artifact with side-by-side diffs. - -## Publishing (maintainers) - -> Full step-by-step setup (repo creation, branch protection, secrets, Pages, -> release-please flow, npm/CDN, troubleshooting) is in **[GITHUB_SETUP.md](GITHUB_SETUP.md)**. - -The package ships only `dist/`, `src/`, `README.md` and `LICENSE` (see the -`files` field). `prepublishOnly` rebuilds the bundle and enforces the size -budget, so a broken or oversized build can never be published. - -**Automated (recommended).** Two GitHub Actions workflows are included: - -- `.github/workflows/ci.yml` — on every push/PR: `npm ci`, `npm run build`, - size-budget check, and a guard that fails if committed `dist/` is stale. -- `.github/workflows/publish.yml` — on a published GitHub Release: builds and - runs `npm publish --provenance --access public`. Add an `NPM_TOKEN` repo - secret (an npm automation token); provenance uses the workflow's OIDC token. - -Release flow: - -```bash -npm version patch # or minor / major — bumps package.json + git tag -git push --follow-tags -# then create a GitHub Release for that tag -> publish workflow runs -``` - -**Manual:** - -```bash -npm run build -npm publish --access public -``` - -**CDN is automatic.** Once on npm, jsDelivr and unpkg serve it with no extra -step: `https://cdn.jsdelivr.net/npm/lombokcss@/dist/lombok.min.css`. -The `jsdelivr` / `unpkg` fields point both CDNs at the minified CSS by default. - -**Docs hosting (GitHub Pages).** `.github/workflows/pages.yml` rebuilds the -docs and deploys `docs/` to Pages on every push to `main`. Enable it once in -repo **Settings → Pages → Source: GitHub Actions**. Site goes live at -`https://codinglombok.github.io/LombokCSS/`. - -Need help? See **[SUPPORT.md](SUPPORT.md)**. - -## License - -MIT. diff --git a/package/dist/lombok.css b/package/dist/lombok.css deleted file mode 100644 index 95db3f3..0000000 --- a/package/dist/lombok.css +++ /dev/null @@ -1,3353 +0,0 @@ -/* ========================================================================== - LombokCSS — variables.css - Token architecture. Every component reads SEMANTIC tokens only. - Themes (data-style) and dark mode (data-theme) just re-map these tokens. - -------------------------------------------------------------------------- - Naming: all tokens are namespaced `--lc-*` to avoid collisions. - ========================================================================== */ - -:root { - /* ---- Color primitives (raw palette) ---- */ - --lc-white: #ffffff; - --lc-black: #0a0a0a; - - /* ---- Semantic surface & text (LIGHT default = corporate-flat) ---- */ - --lc-bg: #f6f7f9; /* page background */ - --lc-surface: #ffffff; /* cards, modals, inputs */ - --lc-surface-2: #f1f3f5; /* subtle raised / hover */ - --lc-text: #1a1d21; /* primary text */ - --lc-text-muted: #5b6470; /* secondary text */ - --lc-text-faint: #8a93a0; /* placeholders, captions */ - --lc-border: #e2e6ea; /* hairline borders */ - --lc-border-strong: #c8cfd6; - - /* ---- Brand / accent ---- */ - --lc-accent: #3b82f6; - --lc-accent-hover: #2f6fe0; - --lc-accent-active: #2861c9; - --lc-accent-text: #ffffff; /* text on accent surface */ - --lc-accent-soft: #e8f0fe; /* soft accent background */ - --lc-accent-soft-text: #1f5fd1; - --lc-ring: rgba(59, 130, 246, 0.45); /* focus ring color */ - - /* ---- Status colors (bg / text / soft) ---- */ - --lc-success: #16a34a; - --lc-success-soft: #e7f6ec; - --lc-success-text: #0f7a37; - --lc-warning: #d97706; - --lc-warning-soft: #fdf0dd; - --lc-warning-text: #a85d05; - --lc-danger: #dc2626; - --lc-danger-soft: #fde8e8; - --lc-danger-text: #b21d1d; - --lc-info: #0ea5e9; - --lc-info-soft: #e3f5fd; - --lc-info-text: #0b7fb4; - - /* ---- Typography ---- */ - --lc-font-sans: system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; - --lc-font-mono: ui-monospace, "SF Mono", "JetBrains Mono", "Fira Code", Menlo, Consolas, monospace; - --lc-font-display: var(--lc-font-sans); - - --lc-text-xs: 0.75rem; - --lc-text-sm: 0.875rem; - --lc-text-base: 1rem; - --lc-text-lg: 1.125rem; - --lc-text-xl: 1.25rem; - --lc-text-2xl: 1.5rem; - --lc-text-3xl: 1.875rem; - --lc-text-4xl: 2.25rem; - - --lc-leading-tight: 1.2; - --lc-leading-normal: 1.55; - --lc-leading-relaxed: 1.75; - - --lc-weight-normal: 400; - --lc-weight-medium: 500; - --lc-weight-semibold: 600; - --lc-weight-bold: 700; - --lc-tracking: 0; /* letter-spacing for body */ - - /* ---- Spacing scale (used by utilities + components) ---- */ - --lc-space-0: 0; - --lc-space-1: 0.25rem; - --lc-space-2: 0.5rem; - --lc-space-3: 0.75rem; - --lc-space-4: 1rem; - --lc-space-5: 1.25rem; - --lc-space-6: 1.5rem; - --lc-space-8: 2rem; - --lc-space-10: 2.5rem; - --lc-space-12: 3rem; - - /* ---- Radius ---- */ - --lc-radius-sm: 6px; - --lc-radius: 10px; - --lc-radius-lg: 16px; - --lc-radius-full: 9999px; - - /* ---- Borders ---- */ - --lc-border-width: 1px; - - /* ---- Shadows ---- */ - --lc-shadow-sm: 0 1px 2px rgba(16, 24, 40, 0.06); - --lc-shadow: 0 4px 12px rgba(16, 24, 40, 0.08); - --lc-shadow-lg: 0 12px 32px rgba(16, 24, 40, 0.12); - /* hard-offset shadow only used by neo-brutalism, kept here for consistency */ - --lc-shadow-hard: none; - - /* ---- Glass tokens (inert unless a glass theme turns blur on) ---- */ - --lc-blur: none; /* backdrop-filter value */ - --lc-glass-tint: var(--lc-surface); - --lc-glass-border: var(--lc-border); - - /* ---- Motion ---- */ - --lc-transition: 160ms cubic-bezier(0.4, 0, 0.2, 1); - - /* ---- Layout ---- */ - --lc-container: 1120px; - --lc-navbar-h: 60px; - --lc-z-base: 1; - --lc-z-dropdown: 1000; - --lc-z-sticky: 1020; - --lc-z-modal: 1050; - --lc-z-toast: 1080; - --lc-z-tooltip: 1090; -} - -/* ========================================================================== - DARK MODE (color-token overlay) — applies to default + corporate + glass. - Themes that are intrinsically dark (resonant-stark) set their own values. - ========================================================================== */ -@media (prefers-color-scheme: dark) { - :root:not([data-theme="light"]) { - --lc-bg: #0f1115; - --lc-surface: #171a21; - --lc-surface-2: #1f242d; - --lc-text: #e7eaee; - --lc-text-muted: #9aa4b2; - --lc-text-faint: #6b7480; - --lc-border: #2a2f3a; - --lc-border-strong: #3a404d; - --lc-accent-soft: #16263f; - --lc-accent-soft-text: #8ab4ff; - --lc-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4); - --lc-shadow: 0 4px 12px rgba(0, 0, 0, 0.45); - --lc-shadow-lg: 0 12px 32px rgba(0, 0, 0, 0.55); - --lc-success-soft: #10241a; - --lc-warning-soft: #2a1f0d; - --lc-danger-soft: #2a1414; - --lc-info-soft: #0c2530; - --lc-success-text: #6ee7a0; - --lc-warning-text: #fbbf24; - --lc-danger-text: #fca5a5; - --lc-info-text: #67d3f7; - } -} -[data-theme="dark"] { - --lc-bg: #0f1115; - --lc-surface: #171a21; - --lc-surface-2: #1f242d; - --lc-text: #e7eaee; - --lc-text-muted: #9aa4b2; - --lc-text-faint: #6b7480; - --lc-border: #2a2f3a; - --lc-border-strong: #3a404d; - --lc-accent-soft: #16263f; - --lc-accent-soft-text: #8ab4ff; - --lc-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4); - --lc-shadow: 0 4px 12px rgba(0, 0, 0, 0.45); - --lc-shadow-lg: 0 12px 32px rgba(0, 0, 0, 0.55); - --lc-success-soft: #10241a; - --lc-warning-soft: #2a1f0d; - --lc-danger-soft: #2a1414; - --lc-info-soft: #0c2530; - --lc-success-text: #6ee7a0; - --lc-warning-text: #fbbf24; - --lc-danger-text: #fca5a5; - --lc-info-text: #67d3f7; -} -/* ========================================================================== - LombokCSS — core.css - Reset/reboot + base element styling. Base styling doubles as CLASSLESS mode: - plain semantic HTML is readable with zero classes. - ========================================================================== */ - -*, -*::before, -*::after { - box-sizing: border-box; -} -* { - margin: 0; -} - -html { - -webkit-text-size-adjust: 100%; - -moz-tab-size: 4; - tab-size: 4; - scroll-behavior: smooth; -} -@media (prefers-reduced-motion: reduce) { - html { - scroll-behavior: auto; - } - *, - *::before, - *::after { - animation-duration: 0.001ms !important; - transition-duration: 0.001ms !important; - } -} - -body { - margin: 0; - font-family: var(--lc-font-sans); - font-size: var(--lc-text-base); - line-height: var(--lc-leading-normal); - letter-spacing: var(--lc-tracking); - color: var(--lc-text); - background-color: var(--lc-bg); - -webkit-font-smoothing: antialiased; - text-rendering: optimizeLegibility; - transition: - background-color var(--lc-transition), - color var(--lc-transition); -} - -img, -picture, -video, -canvas, -svg { - display: block; - max-inline-size: 100%; - height: auto; -} -input, -button, -textarea, -select { - font: inherit; - color: inherit; -} -p, -h1, -h2, -h3, -h4, -h5, -h6 { - overflow-wrap: break-word; -} - -/* ---- Typography (classless) ---- */ -h1, -h2, -h3, -h4, -h5, -h6 { - font-family: var(--lc-font-display); - line-height: var(--lc-leading-tight); - font-weight: var(--lc-weight-semibold); - margin-block: 0 var(--lc-space-3); - text-wrap: balance; -} -h1 { - font-size: var(--lc-text-3xl); -} -h2 { - font-size: var(--lc-text-2xl); -} -h3 { - font-size: var(--lc-text-xl); -} -h4 { - font-size: var(--lc-text-lg); -} -h5 { - font-size: var(--lc-text-base); -} -h6 { - font-size: var(--lc-text-sm); - text-transform: uppercase; - letter-spacing: 0.06em; - color: var(--lc-text-muted); -} - -p { - margin-block: 0 var(--lc-space-4); -} -.lead { - font-size: var(--lc-text-lg); - color: var(--lc-text-muted); -} -small, -.caption { - font-size: var(--lc-text-sm); - color: var(--lc-text-muted); -} - -a { - color: var(--lc-accent); - text-decoration: none; - text-underline-offset: 3px; - transition: color var(--lc-transition); -} -a:hover { - color: var(--lc-accent-hover); - text-decoration: underline; -} - -strong, -b { - font-weight: var(--lc-weight-semibold); -} - -ul, -ol { - margin-block: 0 var(--lc-space-4); - padding-inline-start: 1.4em; -} -li { - margin-block-end: var(--lc-space-1); -} - -blockquote { - margin-block: 0 var(--lc-space-4); - padding-inline-start: var(--lc-space-4); - border-inline-start: 3px solid var(--lc-border-strong); - color: var(--lc-text-muted); -} - -hr, -.divider { - border: 0; - border-block-start: var(--lc-border-width) solid var(--lc-border); - margin-block: var(--lc-space-6); -} -.divider-vertical { - border: 0; - border-inline-start: var(--lc-border-width) solid var(--lc-border); - block-size: 1.2em; - margin-inline: var(--lc-space-3); - display: inline-block; -} - -code, -kbd, -samp, -pre { - font-family: var(--lc-font-mono); - font-size: 0.9em; -} -code { - background: var(--lc-surface-2); - padding: 0.15em 0.4em; - border-radius: var(--lc-radius-sm); - border: var(--lc-border-width) solid var(--lc-border); -} -pre { - background: var(--lc-surface-2); - border: var(--lc-border-width) solid var(--lc-border); - border-radius: var(--lc-radius); - padding: var(--lc-space-4); - overflow: auto; - margin-block: 0 var(--lc-space-4); -} -pre code { - background: none; - border: 0; - padding: 0; -} - -.kbd, -kbd { - display: inline-block; - font-family: var(--lc-font-mono); - font-size: var(--lc-text-xs); - line-height: 1; - padding: 0.35em 0.5em; - color: var(--lc-text); - background: var(--lc-surface); - border: var(--lc-border-width) solid var(--lc-border-strong); - border-block-end-width: 2px; - border-radius: var(--lc-radius-sm); -} - -::selection { - background: var(--lc-accent); - color: var(--lc-accent-text); -} - -:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible { - outline: 2px solid var(--lc-accent); - outline-offset: 2px; - border-radius: var(--lc-radius-sm); -} - -/* ---- Container & section helpers ---- */ -.container { - inline-size: 100%; - max-inline-size: var(--lc-container); - margin-inline: auto; - padding-inline: var(--lc-space-4); -} -.section { - padding-block: var(--lc-space-12); -} -/* ========================================================================== - LombokCSS — themes.css - Design-trend presets. Switch with data-style="..." on or . - Each preset ONLY re-maps tokens; component structure never changes. - Works alongside data-theme="dark|light". - ========================================================================== */ - -/* -------------------------------------------------------------------------- - 1) modern-corporate-flat (also the :root default) - Clean, flat, neutral + one brand color, medium radius, soft shadow. - Colors are inherited from :root / dark overlay, so we only confirm look. - -------------------------------------------------------------------------- */ -[data-style="modern-corporate-flat"] { - --lc-accent: #3b82f6; - --lc-accent-hover: #2f6fe0; - --lc-accent-active: #2861c9; - --lc-radius-sm: 6px; - --lc-radius: 10px; - --lc-radius-lg: 16px; - --lc-border-width: 1px; - --lc-shadow-sm: 0 1px 2px rgba(16, 24, 40, 0.06); - --lc-shadow: 0 4px 12px rgba(16, 24, 40, 0.08); - --lc-shadow-lg: 0 12px 32px rgba(16, 24, 40, 0.12); - --lc-shadow-hard: none; - --lc-blur: none; -} - -/* -------------------------------------------------------------------------- - 2) resonant-stark (Linear-style) — intrinsically dark, high contrast. - -------------------------------------------------------------------------- */ -[data-style="resonant-stark"] { - --lc-bg: #08090c; - --lc-surface: #101218; - --lc-surface-2: #171a22; - --lc-text: #f3f5f8; - --lc-text-muted: #a3acba; - --lc-text-faint: #6c7585; - --lc-border: #23262f; - --lc-border-strong: #333845; - --lc-accent: #7c6cff; - --lc-accent-hover: #8d7fff; - --lc-accent-active: #6b5af0; - --lc-accent-text: #ffffff; - --lc-accent-soft: #1b1830; - --lc-accent-soft-text: #bcb2ff; - --lc-ring: rgba(124, 108, 255, 0.5); - /* dark-appropriate status colors (soft backgrounds + readable text) */ - --lc-success-soft: #11271b; - --lc-success-text: #6ee7a0; - --lc-warning-soft: #2a1f0d; - --lc-warning-text: #fbbf24; - --lc-danger-soft: #2a1414; - --lc-danger-text: #fca5a5; - --lc-info-soft: #0c2530; - --lc-info-text: #67d3f7; - --lc-radius-sm: 5px; - --lc-radius: 7px; - --lc-radius-lg: 11px; - --lc-border-width: 1px; - --lc-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.5); - --lc-shadow: 0 2px 10px rgba(0, 0, 0, 0.55); - --lc-shadow-lg: 0 10px 36px rgba(0, 0, 0, 0.65); - --lc-shadow-hard: none; - --lc-blur: none; - --lc-tracking: -0.01em; - --lc-font-display: var(--lc-font-sans); - --lc-weight-semibold: 600; -} - -/* -------------------------------------------------------------------------- - 3) neo-brutalism — thick black borders, hard offset shadow, bold blocks. - -------------------------------------------------------------------------- */ -[data-style="neo-brutalism"] { - --lc-bg: #fdf6e3; - --lc-surface: #ffffff; - --lc-surface-2: #fff3c4; - --lc-text: #0a0a0a; - --lc-text-muted: #33312b; - --lc-text-faint: #6b6760; - --lc-border: #0a0a0a; - --lc-border-strong: #0a0a0a; - --lc-accent: #ff4f00; - --lc-accent-hover: #e84700; - --lc-accent-active: #cc3f00; - --lc-accent-text: #ffffff; - --lc-accent-soft: #ffe1cc; - --lc-accent-soft-text: #0a0a0a; - --lc-ring: rgba(10, 10, 10, 0.9); - --lc-success: #1f9e4d; - --lc-warning: #e0a400; - --lc-danger: #e3342f; - --lc-info: #2563eb; - --lc-success-soft: #d9f5e2; - --lc-warning-soft: #fff0c4; - --lc-danger-soft: #ffd9d7; - --lc-info-soft: #d7e3ff; - --lc-radius-sm: 0px; - --lc-radius: 0px; - --lc-radius-lg: 0px; - --lc-border-width: 2.5px; - --lc-shadow-sm: 3px 3px 0 #0a0a0a; - --lc-shadow: 5px 5px 0 #0a0a0a; - --lc-shadow-lg: 8px 8px 0 #0a0a0a; - --lc-shadow-hard: 5px 5px 0 #0a0a0a; - --lc-blur: none; - --lc-weight-medium: 700; - --lc-weight-semibold: 800; - --lc-weight-bold: 900; -} -[data-style="neo-brutalism"][data-theme="dark"] { - --lc-bg: #16140f; - --lc-surface: #1f1c14; - --lc-surface-2: #2a2517; - --lc-text: #fdf6e3; - --lc-text-muted: #cfc7ad; - --lc-text-faint: #8f8a72; - --lc-border: #fdf6e3; - --lc-border-strong: #fdf6e3; - --lc-shadow-sm: 3px 3px 0 #fdf6e3; - --lc-shadow: 5px 5px 0 #fdf6e3; - --lc-shadow-lg: 8px 8px 0 #fdf6e3; - --lc-shadow-hard: 5px 5px 0 #fdf6e3; - --lc-accent-soft: #3a2a1c; - --lc-accent-soft-text: #fdf6e3; - /* The light block above sets these; without dark values they win by source - order over the dark defaults in variables.css and leave pale panels under - light text. Dropped by 5f39ab5, restored here. */ - --lc-success-soft: #11271b; - --lc-success-text: #6ee7a0; - --lc-warning-soft: #2a1f0d; - --lc-warning-text: #fbbf24; - --lc-danger-soft: #2a1414; - --lc-danger-text: #fca5a5; - --lc-info-soft: #0c2530; - --lc-info-text: #67d3f7; -} - -/* -------------------------------------------------------------------------- - 4) semantic-minimalist — minimal, neutral, generous spacing, readable. - -------------------------------------------------------------------------- */ -[data-style="semantic-minimalist"] { - --lc-bg: #fbfbfa; - --lc-surface: #ffffff; - --lc-surface-2: #f4f4f2; - --lc-text: #23211e; - --lc-text-muted: #6a665f; - --lc-text-faint: #9a958c; - --lc-border: #e8e6e1; - --lc-border-strong: #d4d1c9; - --lc-accent: #1f6f5c; - --lc-accent-hover: #1a5e4e; - --lc-accent-active: #164f42; - --lc-accent-text: #ffffff; - --lc-accent-soft: #e4f0ec; - --lc-accent-soft-text: #155446; - --lc-ring: rgba(31, 111, 92, 0.4); - --lc-radius-sm: 4px; - --lc-radius: 6px; - --lc-radius-lg: 8px; - --lc-border-width: 1px; - --lc-shadow-sm: none; - --lc-shadow: 0 1px 3px rgba(0, 0, 0, 0.05); - --lc-shadow-lg: 0 6px 18px rgba(0, 0, 0, 0.07); - --lc-shadow-hard: none; - --lc-blur: none; - --lc-leading-normal: 1.7; - --lc-leading-relaxed: 1.85; - --lc-font-display: Georgia, "Times New Roman", serif; /* characterful display, restrained */ -} -[data-style="semantic-minimalist"][data-theme="dark"] { - --lc-bg: #16150f; - --lc-surface: #1d1c15; - --lc-surface-2: #26241b; - --lc-text: #ece9df; - --lc-text-muted: #a7a394; - --lc-text-faint: #777262; - --lc-border: #2c2a20; - --lc-border-strong: #3a3729; - --lc-accent-soft: #163029; -} - -/* -------------------------------------------------------------------------- - 5) glassmorphism — frosted glass; semi-transparent surfaces + backdrop blur. - Page sits on a gradient so the blur reads. Fallback below for no support. - -------------------------------------------------------------------------- */ -[data-style="glassmorphism"] { - --lc-bg: #0b1020; - --lc-bg-gradient: - radial-gradient(1200px 600px at 12% -10%, #6d28d9 0%, transparent 55%), - radial-gradient(900px 500px at 100% 0%, #0ea5e9 0%, transparent 50%), - radial-gradient(800px 600px at 50% 120%, #db2777 0%, transparent 55%); - --lc-surface: rgba(255, 255, 255, 0.1); - --lc-surface-2: rgba(255, 255, 255, 0.16); - --lc-text: #f4f6ff; - --lc-text-muted: #c4cbe6; - --lc-text-faint: #9aa2c4; - --lc-border: rgba(255, 255, 255, 0.22); - --lc-border-strong: rgba(255, 255, 255, 0.35); - --lc-accent: #a78bfa; - --lc-accent-hover: #b9a4fb; - --lc-accent-active: #9170f7; - --lc-accent-text: #13102a; - --lc-accent-soft: rgba(167, 139, 250, 0.22); - --lc-accent-soft-text: #e3dbff; - --lc-ring: rgba(167, 139, 250, 0.5); - --lc-success-soft: rgba(34, 197, 94, 0.2); - --lc-warning-soft: rgba(217, 119, 6, 0.22); - --lc-danger-soft: rgba(220, 38, 38, 0.22); - --lc-info-soft: rgba(14, 165, 233, 0.22); - --lc-radius-sm: 10px; - --lc-radius: 16px; - --lc-radius-lg: 22px; - --lc-border-width: 1px; - --lc-shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.25); - --lc-shadow: 0 8px 32px rgba(0, 0, 0, 0.32); - --lc-shadow-lg: 0 20px 60px rgba(0, 0, 0, 0.4); - --lc-shadow-hard: none; - --lc-blur: blur(14px) saturate(140%); - --lc-glass-tint: rgba(255, 255, 255, 0.1); - --lc-glass-border: rgba(255, 255, 255, 0.28); -} -[data-style="glassmorphism"] body { - background-image: var(--lc-bg-gradient); - background-attachment: fixed; -} - -/* Fallback: if backdrop-filter is unsupported, make glass surfaces opaque - so content stays legible (no see-through mud). */ -@supports not (backdrop-filter: blur(1px)) { - [data-style="glassmorphism"] { - --lc-surface: #1b2138; - --lc-surface-2: #232a44; - --lc-border: rgba(255, 255, 255, 0.18); - --lc-blur: none; - } -} -/* ========================================================================== - LombokCSS — components.css - Semantic component classes. All read tokens only -> auto-restyle per theme. - Logical properties (inline/block) everywhere for RTL safety. - Glass-aware surfaces apply backdrop-filter:var(--lc-blur) (inert when none). - ========================================================================== */ - -/* ---------- BUTTON ---------- */ -.btn { - --_bg: var(--lc-surface); - --_fg: var(--lc-text); - --_bd: var(--lc-border-strong); - display: inline-flex; - align-items: center; - justify-content: center; - gap: var(--lc-space-2); - font: inherit; - font-weight: var(--lc-weight-medium); - line-height: 1; - text-decoration: none; - white-space: nowrap; - cursor: pointer; - padding-block: 0.62em; - padding-inline: 1.05em; - color: var(--_fg); - background: var(--_bg); - border: var(--lc-border-width) solid var(--_bd); - border-radius: var(--lc-radius); - box-shadow: var(--lc-shadow-hard); - transition: - transform var(--lc-transition), - background-color var(--lc-transition), - border-color var(--lc-transition), - box-shadow var(--lc-transition), - color var(--lc-transition); - user-select: none; -} -.btn:hover { - background: var(--lc-surface-2); -} -.btn:active { - transform: translateY(1px); -} -.btn:disabled, -.btn[aria-disabled="true"] { - opacity: 0.55; - cursor: not-allowed; - pointer-events: none; -} - -.btn-primary { - --_bg: var(--lc-accent); - --_fg: var(--lc-accent-text); - --_bd: var(--lc-accent); -} -.btn-primary:hover { - background: var(--lc-accent-hover); - border-color: var(--lc-accent-hover); -} -.btn-secondary { - --_bg: var(--lc-surface-2); - --_fg: var(--lc-text); - --_bd: var(--lc-border-strong); -} -.btn-outline { - --_bg: transparent; - --_fg: var(--lc-accent); - --_bd: var(--lc-accent); -} -.btn-outline:hover { - background: var(--lc-accent-soft); -} -.btn-ghost { - --_bg: transparent; - --_fg: var(--lc-text); - --_bd: transparent; - box-shadow: none; -} -.btn-ghost:hover { - background: var(--lc-surface-2); -} -.btn-soft { - --_bg: var(--lc-accent-soft); - --_fg: var(--lc-accent-soft-text); - --_bd: transparent; - box-shadow: none; -} -.btn-link { - --_bg: transparent; - --_fg: var(--lc-accent); - --_bd: transparent; - box-shadow: none; - padding-inline: 0.25em; -} -.btn-link:hover { - text-decoration: underline; - background: transparent; -} -.btn-danger { - --_bg: var(--lc-danger); - --_fg: #fff; - --_bd: var(--lc-danger); -} - -.btn-sm { - padding-block: 0.4em; - padding-inline: 0.75em; - font-size: var(--lc-text-sm); -} -.btn-lg { - padding-block: 0.78em; - padding-inline: 1.4em; - font-size: var(--lc-text-lg); -} -.btn-block { - display: flex; - inline-size: 100%; -} -.btn-icon { - padding: 0.55em; - aspect-ratio: 1; -} -.btn-rounded { - border-radius: var(--lc-radius-full); -} - -.btn-group { - display: inline-flex; -} -.btn-group .btn { - border-radius: 0; - margin-inline-start: calc(var(--lc-border-width) * -1); -} -.btn-group .btn:first-child { - border-start-start-radius: var(--lc-radius); - border-end-start-radius: var(--lc-radius); - margin-inline-start: 0; -} -.btn-group .btn:last-child { - border-start-end-radius: var(--lc-radius); - border-end-end-radius: var(--lc-radius); -} - -/* ---------- CARD ---------- */ -.card { - background: var(--lc-surface); - -webkit-backdrop-filter: var(--lc-blur); - backdrop-filter: var(--lc-blur); - border: var(--lc-border-width) solid var(--lc-border); - border-radius: var(--lc-radius-lg); - box-shadow: var(--lc-shadow); - overflow: hidden; -} -.card-body { - padding: var(--lc-space-6); -} -.card-header { - padding: var(--lc-space-4) var(--lc-space-6); - border-block-end: var(--lc-border-width) solid var(--lc-border); - font-weight: var(--lc-weight-semibold); -} -.card-footer { - padding: var(--lc-space-4) var(--lc-space-6); - border-block-start: var(--lc-border-width) solid var(--lc-border); -} -.card-title { - font-size: var(--lc-text-lg); - font-weight: var(--lc-weight-semibold); - margin-block-end: var(--lc-space-1); -} -.card-text { - color: var(--lc-text-muted); - margin: 0; -} - -/* ---------- BADGE / PILL ---------- */ -.badge { - display: inline-flex; - align-items: center; - gap: 0.4em; - font-size: var(--lc-text-xs); - font-weight: var(--lc-weight-semibold); - line-height: 1; - padding: 0.4em 0.65em; - color: var(--lc-text); - background: var(--lc-surface-2); - border: var(--lc-border-width) solid var(--lc-border); - border-radius: var(--lc-radius-sm); -} -.badge-pill { - border-radius: var(--lc-radius-full); -} -.badge-primary { - background: var(--lc-accent-soft); - color: var(--lc-accent-soft-text); - border-color: transparent; -} -.badge-success { - background: var(--lc-success-soft); - color: var(--lc-success-text); - border-color: transparent; -} -.badge-warning { - background: var(--lc-warning-soft); - color: var(--lc-warning-text); - border-color: transparent; -} -.badge-danger { - background: var(--lc-danger-soft); - color: var(--lc-danger-text); - border-color: transparent; -} -.badge-info { - background: var(--lc-info-soft); - color: var(--lc-info-text); - border-color: transparent; -} -.badge-solid { - background: var(--lc-accent); - color: var(--lc-accent-text); - border-color: transparent; -} - -/* ---------- ALERT ---------- */ -.alert { - display: flex; - gap: var(--lc-space-3); - align-items: flex-start; - padding: var(--lc-space-4); - background: var(--lc-surface); - -webkit-backdrop-filter: var(--lc-blur); - backdrop-filter: var(--lc-blur); - border: var(--lc-border-width) solid var(--lc-border); - border-inline-start-width: 4px; - border-radius: var(--lc-radius); -} -.alert-title { - font-weight: var(--lc-weight-semibold); - margin-block-end: 0.15em; -} -.alert-success { - border-inline-start-color: var(--lc-success); - background: var(--lc-success-soft); -} -.alert-warning { - border-inline-start-color: var(--lc-warning); - background: var(--lc-warning-soft); -} -.alert-danger { - border-inline-start-color: var(--lc-danger); - background: var(--lc-danger-soft); -} -.alert-info { - border-inline-start-color: var(--lc-info); - background: var(--lc-info-soft); -} - -/* ---------- FORM ---------- */ -.field { - margin-block-end: var(--lc-space-4); -} -.label { - display: inline-block; - font-size: var(--lc-text-sm); - font-weight: var(--lc-weight-medium); - margin-block-end: var(--lc-space-2); -} -.help { - display: block; - font-size: var(--lc-text-sm); - color: var(--lc-text-muted); - margin-block-start: var(--lc-space-1); -} -.error-text { - display: none; - font-size: var(--lc-text-sm); - color: var(--lc-danger-text); - margin-block-start: var(--lc-space-1); -} - -.input, -.textarea, -.select, -input:where( - [type]:not([type="checkbox"], [type="radio"], [type="range"], [type="file"], [type="button"], [type="submit"]) -), -textarea, -select { - inline-size: 100%; - padding-block: 0.6em; - padding-inline: 0.8em; - color: var(--lc-text); - background: var(--lc-surface); - -webkit-backdrop-filter: var(--lc-blur); - backdrop-filter: var(--lc-blur); - border: var(--lc-border-width) solid var(--lc-border-strong); - border-radius: var(--lc-radius); - transition: - border-color var(--lc-transition), - box-shadow var(--lc-transition); - appearance: none; -} -.textarea, -textarea { - min-block-size: 6em; - resize: vertical; -} -.input::placeholder, -textarea::placeholder { - color: var(--lc-text-faint); -} - -.input:focus, -.textarea:focus, -.select:focus, -input:focus, -textarea:focus, -select:focus { - outline: none; - border-color: var(--lc-accent); - box-shadow: 0 0 0 3px var(--lc-ring); -} -.input:disabled, -textarea:disabled, -select:disabled { - background: var(--lc-surface-2); - opacity: 0.7; - cursor: not-allowed; -} - -/* native select caret (logical-aware) */ -.select, -select { - background-image: - linear-gradient(45deg, transparent 50%, var(--lc-text-muted) 50%), - linear-gradient(135deg, var(--lc-text-muted) 50%, transparent 50%); - background-position: - calc(100% - 18px) center, - calc(100% - 13px) center; - background-size: - 5px 5px, - 5px 5px; - background-repeat: no-repeat; - padding-inline-end: 2.2em; -} -[dir="rtl"] .select, -[dir="rtl"] select { - background-position: - 18px center, - 13px center; - padding-inline: 2.2em 0.8em; -} - -/* checkbox / radio use accent-color for native theming */ -input[type="checkbox"], -input[type="radio"] { - inline-size: 1.1em; - block-size: 1.1em; - accent-color: var(--lc-accent); - margin-inline-end: var(--lc-space-2); - vertical-align: -2px; - cursor: pointer; -} -.check { - display: flex; - align-items: center; - gap: var(--lc-space-2); - margin-block-end: var(--lc-space-2); -} -.check label { - cursor: pointer; -} - -/* switch / toggle */ -.switch { - position: relative; - display: inline-flex; - align-items: center; - cursor: pointer; - gap: var(--lc-space-2); -} -.switch input { - position: absolute; - opacity: 0; - inline-size: 0; - block-size: 0; -} -.switch .track { - inline-size: 40px; - block-size: 22px; - border-radius: var(--lc-radius-full); - background: var(--lc-border-strong); - transition: background var(--lc-transition); - position: relative; - flex: none; -} -.switch .track::after { - content: ""; - position: absolute; - inset-block-start: 2px; - inset-inline-start: 2px; - inline-size: 18px; - block-size: 18px; - border-radius: 50%; - background: #fff; - transition: inset-inline-start var(--lc-transition); -} -.switch input:checked + .track { - background: var(--lc-accent); -} -.switch input:checked + .track::after { - inset-inline-start: 20px; -} -.switch input:focus-visible + .track { - box-shadow: 0 0 0 3px var(--lc-ring); -} - -/* file upload */ -.file { - display: inline-flex; -} -input[type="file"] { - font-size: var(--lc-text-sm); -} -input[type="file"]::file-selector-button { - font: inherit; - cursor: pointer; - margin-inline-end: var(--lc-space-3); - padding: 0.5em 0.9em; - color: var(--lc-text); - background: var(--lc-surface-2); - border: var(--lc-border-width) solid var(--lc-border-strong); - border-radius: var(--lc-radius); -} - -/* VALIDATION — works with native :user-invalid and a .is-invalid hook */ -.input:user-invalid, -.input.is-invalid, -input:user-invalid, -textarea:user-invalid, -select:user-invalid, -.is-invalid { - border-color: var(--lc-danger); -} -.input:user-invalid:focus, -.is-invalid:focus { - box-shadow: 0 0 0 3px var(--lc-danger-soft); -} -.input:user-valid, -.is-valid, -input:user-valid { - border-color: var(--lc-success); -} - -/* show error text when field is invalid (modern :has) */ -.field:has(:user-invalid) .error-text, -.field.is-invalid .error-text { - display: block; -} -.field:has(:user-invalid) .help { - display: none; -} - -/* input sizes */ -.input-sm, -.select-sm { - padding-block: 0.4em; - padding-inline: 0.6em; - font-size: var(--lc-text-sm); -} -.input-lg, -.select-lg { - padding-block: 0.75em; - padding-inline: 1em; - font-size: var(--lc-text-lg); -} - -/* input group: join an input with leading/trailing addons or buttons */ -.input-group { - display: flex; - align-items: stretch; - inline-size: 100%; -} -.input-group > .input, -.input-group > .select, -.input-group > input, -.input-group > select { - inline-size: auto; - flex: 1 1 auto; - min-inline-size: 0; - border-radius: 0; -} -.input-group > :first-child { - border-start-start-radius: var(--lc-radius); - border-end-start-radius: var(--lc-radius); -} -.input-group > :last-child { - border-start-end-radius: var(--lc-radius); - border-end-end-radius: var(--lc-radius); -} -.input-group > * + * { - margin-inline-start: calc(var(--lc-border-width) * -1); -} -.input-group .input-addon { - display: inline-flex; - align-items: center; - white-space: nowrap; - padding-inline: 0.8em; - color: var(--lc-text-muted); - background: var(--lc-surface-2); - border: var(--lc-border-width) solid var(--lc-border-strong); -} -.input-group .btn { - border-radius: 0; -} -.input-group:focus-within > .input, -.input-group:focus-within > input { - border-color: var(--lc-accent); -} - -/* ---------- TABLE ---------- */ -.table { - inline-size: 100%; - border-collapse: collapse; - font-size: var(--lc-text-sm); -} -.table th, -.table td { - padding: var(--lc-space-3) var(--lc-space-4); - text-align: start; - border-block-end: var(--lc-border-width) solid var(--lc-border); -} -.table thead th { - font-weight: var(--lc-weight-semibold); - color: var(--lc-text-muted); - border-block-end: 2px solid var(--lc-border-strong); - white-space: nowrap; -} -.table-striped tbody tr:nth-child(even) { - background: var(--lc-surface-2); -} -.table-hover tbody tr:hover { - background: var(--lc-surface-2); -} -.table-bordered, -.table-bordered th, -.table-bordered td { - border: var(--lc-border-width) solid var(--lc-border); -} -/* sortable header affordance */ -.table th[aria-sort] { - cursor: pointer; - user-select: none; -} -.table th[aria-sort]::after { - content: "↕"; - opacity: 0.35; - margin-inline-start: 0.4em; - font-size: 0.85em; -} -.table th[aria-sort="ascending"]::after { - content: "↑"; - opacity: 1; -} -.table th[aria-sort="descending"]::after { - content: "↓"; - opacity: 1; -} -.table-wrap { - overflow-x: auto; - border-radius: var(--lc-radius); -} - -/* ---------- AVATAR ---------- */ -.avatar { - --_s: 40px; - display: inline-flex; - align-items: center; - justify-content: center; - inline-size: var(--_s); - block-size: var(--_s); - border-radius: var(--lc-radius-full); - background: var(--lc-accent-soft); - color: var(--lc-accent-soft-text); - font-weight: var(--lc-weight-semibold); - overflow: hidden; - flex: none; - border: var(--lc-border-width) solid var(--lc-border); -} -.avatar img { - inline-size: 100%; - block-size: 100%; - object-fit: cover; -} -.avatar-sm { - --_s: 28px; - font-size: var(--lc-text-xs); -} -.avatar-lg { - --_s: 56px; - font-size: var(--lc-text-lg); -} -.avatar-group { - display: inline-flex; -} -.avatar-group .avatar { - margin-inline-start: -10px; - box-shadow: 0 0 0 2px var(--lc-surface); -} -.avatar-group .avatar:first-child { - margin-inline-start: 0; -} - -/* ---------- PROGRESS ---------- */ -.progress { - inline-size: 100%; - block-size: 8px; - background: var(--lc-surface-2); - border-radius: var(--lc-radius-full); - overflow: hidden; -} -.progress > .bar { - block-size: 100%; - background: var(--lc-accent); - border-radius: inherit; - transition: inline-size var(--lc-transition); -} - -/* ---------- SPINNER ---------- */ -.spinner { - display: inline-block; - inline-size: 1.2em; - block-size: 1.2em; - vertical-align: -0.2em; - border: 2px solid var(--lc-border-strong); - border-block-start-color: var(--lc-accent); - border-radius: 50%; - animation: lc-spin 0.7s linear infinite; -} -@keyframes lc-spin { - to { - transform: rotate(360deg); - } -} - -/* ---------- SKELETON ---------- */ -.skeleton { - background: linear-gradient(90deg, var(--lc-surface-2) 25%, var(--lc-border) 37%, var(--lc-surface-2) 63%); - background-size: 400% 100%; - animation: lc-sk 1.4s ease infinite; - border-radius: var(--lc-radius-sm); - block-size: 1em; -} -@keyframes lc-sk { - 0% { - background-position: 100% 0; - } - 100% { - background-position: -100% 0; - } -} - -/* ---------- STAT ---------- */ -.stat { - padding: var(--lc-space-4); -} -.stat-label { - font-size: var(--lc-text-sm); - color: var(--lc-text-muted); -} -.stat-value { - font-size: var(--lc-text-3xl); - font-weight: var(--lc-weight-bold); - line-height: 1.1; -} - -/* ---------- LIST GROUP ---------- */ -.list-group { - border: var(--lc-border-width) solid var(--lc-border); - border-radius: var(--lc-radius); - overflow: hidden; -} -.list-group > * { - display: block; - padding: var(--lc-space-3) var(--lc-space-4); - border-block-end: var(--lc-border-width) solid var(--lc-border); - background: var(--lc-surface); -} -.list-group > *:last-child { - border-block-end: 0; -} -a.list-group-item:hover, -.list-group-item.is-active { - background: var(--lc-surface-2); -} - -/* ---------- BREADCRUMB ---------- */ -.breadcrumb { - display: flex; - flex-wrap: wrap; - gap: var(--lc-space-2); - list-style: none; - padding: 0; - margin: 0; - font-size: var(--lc-text-sm); -} -.breadcrumb li { - display: flex; - align-items: center; - gap: var(--lc-space-2); - margin: 0; -} -.breadcrumb li:not(:last-child)::after { - content: "/"; - color: var(--lc-text-faint); -} -[dir="rtl"] .breadcrumb li:not(:last-child)::after { - content: "\\"; -} -.breadcrumb a { - color: var(--lc-text-muted); -} -.breadcrumb [aria-current] { - color: var(--lc-text); - font-weight: var(--lc-weight-medium); -} - -/* ---------- PAGINATION ---------- */ -.pagination { - display: flex; - gap: var(--lc-space-1); - list-style: none; - padding: 0; - margin: 0; -} -.pagination li { - margin: 0; -} -.pagination a, -.pagination button { - display: inline-flex; - align-items: center; - justify-content: center; - min-inline-size: 2.2em; - block-size: 2.2em; - padding-inline: 0.6em; - border: var(--lc-border-width) solid var(--lc-border); - border-radius: var(--lc-radius-sm); - background: var(--lc-surface); - color: var(--lc-text); - cursor: pointer; - text-decoration: none; -} -.pagination a:hover { - background: var(--lc-surface-2); -} -.pagination .is-active a, -.pagination .is-active button { - background: var(--lc-accent); - color: var(--lc-accent-text); - border-color: var(--lc-accent); -} - -/* ---------- NAVBAR ---------- */ -.navbar { - display: flex; - align-items: center; - gap: var(--lc-space-4); - min-block-size: var(--lc-navbar-h); - padding-inline: var(--lc-space-4); - background: var(--lc-surface); - -webkit-backdrop-filter: var(--lc-blur); - backdrop-filter: var(--lc-blur); - border-block-end: var(--lc-border-width) solid var(--lc-border); - position: sticky; - inset-block-start: 0; - z-index: var(--lc-z-sticky); -} -.navbar-brand { - font-weight: var(--lc-weight-bold); - font-size: var(--lc-text-lg); - color: var(--lc-text); - text-decoration: none; -} -.navbar-nav { - display: flex; - align-items: center; - gap: var(--lc-space-2); - margin-inline-start: auto; - list-style: none; - padding: 0; - margin-block: 0; -} -.navbar-nav li { - margin: 0; -} -.navbar-nav a { - color: var(--lc-text-muted); - padding: 0.5em 0.75em; - border-radius: var(--lc-radius-sm); - text-decoration: none; -} -.navbar-nav a:hover, -.navbar-nav a[aria-current] { - color: var(--lc-text); - background: var(--lc-surface-2); -} -.navbar-toggle { - display: none; -} -@media (max-width: 768px) { - .navbar-toggle { - display: inline-flex; - margin-inline-start: auto; - } - .navbar-nav { - display: none; - } - .navbar:has(.navbar-toggle:checked) .navbar-nav, - .navbar.is-open .navbar-nav { - display: flex; - position: absolute; - inset-block-start: var(--lc-navbar-h); - inset-inline: 0; - flex-direction: column; - align-items: stretch; - padding: var(--lc-space-2); - background: var(--lc-surface); - border-block-end: var(--lc-border-width) solid var(--lc-border); - -webkit-backdrop-filter: var(--lc-blur); - backdrop-filter: var(--lc-blur); - } -} - -/* ---------- TABS ---------- */ -.tabs { - border-block-end: var(--lc-border-width) solid var(--lc-border); - display: flex; - gap: var(--lc-space-1); -} -.tabs button, -.tabs .tab { - font: inherit; - cursor: pointer; - background: none; - border: 0; - color: var(--lc-text-muted); - padding: var(--lc-space-3) var(--lc-space-4); - border-block-end: 2px solid transparent; - margin-block-end: -1px; -} -.tabs button:hover { - color: var(--lc-text); -} -.tabs button[aria-selected="true"], -.tabs .tab.is-active { - color: var(--lc-accent); - border-block-end-color: var(--lc-accent); - font-weight: var(--lc-weight-medium); -} -.tab-panel { - padding-block: var(--lc-space-4); -} -.tab-panel[hidden] { - display: none; -} - -/* ---------- ACCORDION (native details/summary) ---------- */ -.accordion { - border: var(--lc-border-width) solid var(--lc-border); - border-radius: var(--lc-radius); - overflow: hidden; -} -.accordion details { - border-block-end: var(--lc-border-width) solid var(--lc-border); -} -.accordion details:last-child { - border-block-end: 0; -} -.accordion summary { - cursor: pointer; - padding: var(--lc-space-3) var(--lc-space-4); - font-weight: var(--lc-weight-medium); - list-style: none; - display: flex; - align-items: center; - justify-content: space-between; - background: var(--lc-surface); -} -.accordion summary::-webkit-details-marker { - display: none; -} -.accordion summary::after { - content: "+"; - color: var(--lc-text-muted); - font-size: 1.2em; - line-height: 1; -} -.accordion details[open] summary::after { - content: "\2212"; -} -.accordion .accordion-body { - padding: 0 var(--lc-space-4) var(--lc-space-4); - color: var(--lc-text-muted); -} - -/* ---------- DROPDOWN / MENU ---------- */ -.dropdown { - position: relative; - display: inline-block; -} -.dropdown-menu { - position: absolute; - inset-block-start: calc(100% + 6px); - inset-inline-start: 0; - z-index: var(--lc-z-dropdown); - min-inline-size: 12rem; - padding: var(--lc-space-1); - background: var(--lc-surface); - -webkit-backdrop-filter: var(--lc-blur); - backdrop-filter: var(--lc-blur); - border: var(--lc-border-width) solid var(--lc-border); - border-radius: var(--lc-radius); - box-shadow: var(--lc-shadow-lg); - opacity: 0; - visibility: hidden; - transform: translateY(-4px); - transition: all var(--lc-transition); -} -.dropdown.is-open > .dropdown-menu, -.dropdown:has(> [aria-expanded="true"]) > .dropdown-menu { - opacity: 1; - visibility: visible; - transform: none; -} -.dropdown-item { - display: block; - inline-size: 100%; - text-align: start; - padding: 0.5em 0.75em; - border-radius: var(--lc-radius-sm); - color: var(--lc-text); - background: none; - border: 0; - cursor: pointer; - font: inherit; - text-decoration: none; -} -.dropdown-item:hover { - background: var(--lc-surface-2); -} -.dropdown-divider { - block-size: var(--lc-border-width); - background: var(--lc-border); - margin: var(--lc-space-1) 0; -} -/* navbar dropdowns sit near the inline-end, so open toward start to avoid overflow */ -.navbar .dropdown-menu, -.dropdown-menu.dropdown-end { - inset-inline: auto 0; -} - -/* ---------- TOOLTIP (CSS-only via data-tip) ---------- */ -[data-tip] { - position: relative; -} -[data-tip]::after { - content: attr(data-tip); - position: absolute; - inset-block-end: calc(100% + 6px); - inset-inline-start: 50%; - transform: translateX(-50%) translateY(4px); - padding: 0.35em 0.6em; - font-size: var(--lc-text-xs); - white-space: nowrap; - color: var(--lc-bg); - background: var(--lc-text); - border-radius: var(--lc-radius-sm); - opacity: 0; - pointer-events: none; - transition: all var(--lc-transition); - z-index: var(--lc-z-tooltip); -} -[dir="rtl"] [data-tip]::after { - transform: translateX(50%) translateY(4px); -} -[data-tip]:hover::after, -[data-tip]:focus-visible::after { - opacity: 1; - transform: translateX(-50%) translateY(0); -} -[dir="rtl"] [data-tip]:hover::after { - transform: translateX(50%) translateY(0); -} - -/* ---------- MODAL / DIALOG (native ) ---------- */ -dialog.modal { - padding: 0; - border: 0; - background: transparent; - max-inline-size: min(92vw, 520px); - inline-size: 100%; - color: var(--lc-text); - margin: auto; -} -dialog.modal::backdrop { - background: rgba(8, 10, 18, 0.55); - backdrop-filter: blur(2px); -} -.modal-card { - background: var(--lc-surface); - -webkit-backdrop-filter: var(--lc-blur); - backdrop-filter: var(--lc-blur); - border: var(--lc-border-width) solid var(--lc-border); - border-radius: var(--lc-radius-lg); - box-shadow: var(--lc-shadow-lg); - overflow: hidden; -} -.modal-header { - padding: var(--lc-space-4) var(--lc-space-6); - border-block-end: var(--lc-border-width) solid var(--lc-border); - font-weight: var(--lc-weight-semibold); - display: flex; - justify-content: space-between; - align-items: center; - gap: var(--lc-space-4); -} -.modal-body { - padding: var(--lc-space-6); -} -.modal-footer { - padding: var(--lc-space-4) var(--lc-space-6); - border-block-start: var(--lc-border-width) solid var(--lc-border); - display: flex; - gap: var(--lc-space-2); - justify-content: flex-end; -} - -/* ---------- TOAST ---------- */ -.toast-region { - position: fixed; - inset-block-end: var(--lc-space-6); - inset-inline-end: var(--lc-space-6); - z-index: var(--lc-z-toast); - display: flex; - flex-direction: column; - gap: var(--lc-space-2); -} -.toast { - display: flex; - align-items: flex-start; - gap: var(--lc-space-3); - min-inline-size: 16rem; - max-inline-size: 24rem; - padding: var(--lc-space-3) var(--lc-space-4); - background: var(--lc-surface); - -webkit-backdrop-filter: var(--lc-blur); - backdrop-filter: var(--lc-blur); - border: var(--lc-border-width) solid var(--lc-border); - border-radius: var(--lc-radius); - box-shadow: var(--lc-shadow-lg); - animation: lc-toast-in var(--lc-transition); -} -@keyframes lc-toast-in { - from { - opacity: 0; - transform: translateY(8px); - } -} - -/* ---------- STEPS / STEPPER ---------- */ -.steps { - display: flex; - gap: var(--lc-space-2); - list-style: none; - padding: 0; - margin: 0; - counter-reset: step; -} -.steps li { - flex: 1; - display: flex; - flex-direction: column; - gap: var(--lc-space-2); - align-items: center; - text-align: center; - font-size: var(--lc-text-sm); - color: var(--lc-text-muted); - position: relative; -} -.steps li::before { - counter-increment: step; - content: counter(step); - display: flex; - align-items: center; - justify-content: center; - inline-size: 2em; - block-size: 2em; - border-radius: 50%; - border: var(--lc-border-width) solid var(--lc-border-strong); - background: var(--lc-surface); -} -.steps li.is-active::before, -.steps li.is-done::before { - background: var(--lc-accent); - color: var(--lc-accent-text); - border-color: var(--lc-accent); -} -.steps li.is-active { - color: var(--lc-text); - font-weight: var(--lc-weight-medium); -} - -/* ---------- SIDEBAR ---------- */ -.sidebar { - display: flex; - flex-direction: column; - gap: var(--lc-space-1); - inline-size: 240px; - flex: none; - padding: var(--lc-space-3); - background: var(--lc-surface); - -webkit-backdrop-filter: var(--lc-blur); - backdrop-filter: var(--lc-blur); - border-inline-end: var(--lc-border-width) solid var(--lc-border); -} -.sidebar-title { - font-size: var(--lc-text-xs); - text-transform: uppercase; - letter-spacing: 0.08em; - color: var(--lc-text-faint); - padding: var(--lc-space-2) var(--lc-space-3); - margin-block-start: var(--lc-space-2); -} -.sidebar-link { - display: flex; - align-items: center; - gap: var(--lc-space-2); - padding: 0.55em 0.75em; - border-radius: var(--lc-radius-sm); - color: var(--lc-text-muted); - text-decoration: none; - font-weight: var(--lc-weight-medium); -} -.sidebar-link:hover { - background: var(--lc-surface-2); - color: var(--lc-text); -} -.sidebar-link.is-active, -.sidebar-link[aria-current] { - background: var(--lc-accent-soft); - color: var(--lc-accent-soft-text); -} - -/* ---------- DRAWER / OFFCANVAS ---------- */ -.drawer-overlay { - position: fixed; - inset: 0; - z-index: var(--lc-z-modal); - background: rgba(8, 10, 18, 0.5); - backdrop-filter: blur(1px); - opacity: 0; - visibility: hidden; - transition: - opacity var(--lc-transition), - visibility var(--lc-transition); -} -.drawer { - position: fixed; - inset-block: 0; - inset-inline-start: 0; - z-index: calc(var(--lc-z-modal) + 1); - inline-size: min(86vw, 320px); - max-inline-size: 100%; - display: flex; - flex-direction: column; - background: var(--lc-surface); - -webkit-backdrop-filter: var(--lc-blur); - backdrop-filter: var(--lc-blur); - border-inline-end: var(--lc-border-width) solid var(--lc-border); - box-shadow: var(--lc-shadow-lg); - transform: translateX(-100%); - transition: transform var(--lc-transition); -} -.drawer-end { - inset-inline: auto 0; - border-inline: 0; - border-inline-start: var(--lc-border-width) solid var(--lc-border); - transform: translateX(100%); -} -[dir="rtl"] .drawer { - transform: translateX(100%); -} -[dir="rtl"] .drawer-end { - transform: translateX(-100%); -} -.drawer.is-open { - transform: none; -} -.drawer.is-open ~ .drawer-overlay, -.drawer-overlay.is-open { - opacity: 1; - visibility: visible; -} -.drawer-header { - padding: var(--lc-space-4); - border-block-end: var(--lc-border-width) solid var(--lc-border); - display: flex; - justify-content: space-between; - align-items: center; - gap: var(--lc-space-3); - font-weight: var(--lc-weight-semibold); -} -.drawer-body { - padding: var(--lc-space-4); - overflow-y: auto; - flex: 1; -} - -/* ---------- POPOVER ---------- */ -.popover { - position: relative; - display: inline-block; -} -.popover-panel { - position: absolute; - inset-block-start: calc(100% + 8px); - inset-inline-start: 0; - z-index: var(--lc-z-dropdown); - inline-size: max-content; - max-inline-size: 18rem; - padding: var(--lc-space-4); - background: var(--lc-surface); - -webkit-backdrop-filter: var(--lc-blur); - backdrop-filter: var(--lc-blur); - border: var(--lc-border-width) solid var(--lc-border); - border-radius: var(--lc-radius); - box-shadow: var(--lc-shadow-lg); - opacity: 0; - visibility: hidden; - transform: translateY(-4px); - transition: all var(--lc-transition); -} -.popover.is-open > .popover-panel, -.popover:has(> [aria-expanded="true"]) > .popover-panel { - opacity: 1; - visibility: visible; - transform: none; -} -.popover-title { - font-weight: var(--lc-weight-semibold); - margin-block-end: var(--lc-space-1); -} -.popover-panel::before { - content: ""; - position: absolute; - inset-block-start: -5px; - inset-inline-start: 16px; - inline-size: 9px; - block-size: 9px; - background: var(--lc-surface); - border-inline-start: var(--lc-border-width) solid var(--lc-border); - border-block-start: var(--lc-border-width) solid var(--lc-border); - transform: rotate(45deg); -} - -/* ---------- CAROUSEL / SLIDER (CSS scroll-snap + optional JS controls) ---------- */ -.carousel { - position: relative; -} -.carousel-track { - display: flex; - gap: var(--lc-space-4); - overflow-x: auto; - scroll-snap-type: x mandatory; - scroll-behavior: smooth; - padding-block-end: var(--lc-space-2); - scrollbar-width: thin; - overscroll-behavior-inline: contain; -} -.carousel-slide { - flex: 0 0 100%; - scroll-snap-align: start; - border-radius: var(--lc-radius-lg); -} -@media (min-width: 768px) { - .carousel-slide.is-third { - flex-basis: calc((100% - var(--lc-space-4) * 2) / 3); - } -} -.carousel-track::-webkit-scrollbar { - block-size: 8px; -} -.carousel-track::-webkit-scrollbar-thumb { - background: var(--lc-border-strong); - border-radius: var(--lc-radius-full); -} -.carousel-btn { - position: absolute; - inset-block-start: 50%; - transform: translateY(-50%); - z-index: 2; - inline-size: 2.4em; - block-size: 2.4em; - padding: 0; - display: inline-flex; - align-items: center; - justify-content: center; - border-radius: var(--lc-radius-full); - cursor: pointer; - color: var(--lc-text); - background: var(--lc-surface); - border: var(--lc-border-width) solid var(--lc-border); - box-shadow: var(--lc-shadow); -} -.carousel-btn:hover { - background: var(--lc-surface-2); -} -.carousel-prev { - inset-inline-start: calc(var(--lc-space-2) * -1); -} -.carousel-next { - inset-inline-end: calc(var(--lc-space-2) * -1); -} -[dir="rtl"] .carousel-prev { - transform: translateY(-50%) scaleX(-1); -} -[dir="rtl"] .carousel-next { - transform: translateY(-50%) scaleX(-1); -} -.carousel-dots { - display: flex; - gap: var(--lc-space-2); - justify-content: center; - margin-block-start: var(--lc-space-3); -} -.carousel-dots > * { - inline-size: 8px; - block-size: 8px; - border-radius: 50%; - background: var(--lc-border-strong); - border: 0; - padding: 0; - cursor: pointer; - transition: background var(--lc-transition); -} -.carousel-dots > .is-active { - background: var(--lc-accent); - inline-size: 20px; - border-radius: var(--lc-radius-full); -} - -/* ---------- TIMELINE ---------- */ -.timeline { - list-style: none; - padding: 0; - margin: 0; - position: relative; -} -.timeline > li { - position: relative; - padding-inline-start: var(--lc-space-8); - padding-block-end: var(--lc-space-6); - margin: 0; -} -.timeline > li::before { - /* line */ - content: ""; - position: absolute; - inset-block: 0.4em 0; - inset-inline-start: 7px; - inline-size: 2px; - background: var(--lc-border); -} -.timeline > li:last-child::before { - display: none; -} -.timeline > li::after { - /* dot */ - content: ""; - position: absolute; - inset-block-start: 0.35em; - inset-inline-start: 0; - inline-size: 16px; - block-size: 16px; - border-radius: 50%; - background: var(--lc-surface); - border: 3px solid var(--lc-accent); -} -.timeline .timeline-time { - font-size: var(--lc-text-sm); - color: var(--lc-text-muted); -} -.timeline .timeline-title { - font-weight: var(--lc-weight-semibold); - margin-block: 0.1em 0.25em; -} -/* ========================================================================== - LombokCSS — utilities.css - Atomic helpers. RTL-safe via logical properties. Responsive: sm/md/lg/xl. - ========================================================================== */ - -/* ---- Display ---- */ -.block { - display: block; -} -.inline-block { - display: inline-block; -} -.inline { - display: inline; -} -.hidden { - display: none; -} -.flex { - display: flex; -} -.inline-flex { - display: inline-flex; -} -.grid { - display: grid; -} -.inline-grid { - display: inline-grid; -} - -/* ---- Flexbox ---- */ -.flex-row { - flex-direction: row; -} -.flex-col { - flex-direction: column; -} -.flex-wrap { - flex-wrap: wrap; -} -.flex-1 { - flex: 1 1 0%; -} -.flex-auto { - flex: 1 1 auto; -} -.flex-none { - flex: none; -} -.items-start { - align-items: flex-start; -} -.items-center { - align-items: center; -} -.items-end { - align-items: flex-end; -} -.items-stretch { - align-items: stretch; -} -.items-baseline { - align-items: baseline; -} -.justify-start { - justify-content: flex-start; -} -.justify-center { - justify-content: center; -} -.justify-end { - justify-content: flex-end; -} -.justify-between { - justify-content: space-between; -} -.justify-around { - justify-content: space-around; -} -.justify-evenly { - justify-content: space-evenly; -} -.self-start { - align-self: flex-start; -} -.self-center { - align-self: center; -} -.self-end { - align-self: flex-end; -} - -/* ---- Grid ---- */ -.grid-cols-1 { - grid-template-columns: repeat(1, 1fr); -} -.grid-cols-2 { - grid-template-columns: repeat(2, 1fr); -} -.grid-cols-3 { - grid-template-columns: repeat(3, 1fr); -} -.grid-cols-4 { - grid-template-columns: repeat(4, 1fr); -} -.grid-cols-5 { - grid-template-columns: repeat(5, 1fr); -} -.grid-cols-6 { - grid-template-columns: repeat(6, 1fr); -} -.grid-cols-12 { - grid-template-columns: repeat(12, 1fr); -} -.col-span-2 { - grid-column: span 2; -} -.col-span-3 { - grid-column: span 3; -} -.col-span-4 { - grid-column: span 4; -} -.col-span-6 { - grid-column: span 6; -} -.col-span-full { - grid-column: 1 / -1; -} - -/* ---- Gap (uses spacing scale) ---- */ -.gap-0 { - gap: 0; -} -.gap-1 { - gap: var(--lc-space-1); -} -.gap-2 { - gap: var(--lc-space-2); -} -.gap-3 { - gap: var(--lc-space-3); -} -.gap-4 { - gap: var(--lc-space-4); -} -.gap-6 { - gap: var(--lc-space-6); -} -.gap-8 { - gap: var(--lc-space-8); -} - -/* ---- Spacing: padding (logical) ---- */ -.p-0 { - padding: 0; -} -.p-1 { - padding: var(--lc-space-1); -} -.p-2 { - padding: var(--lc-space-2); -} -.p-3 { - padding: var(--lc-space-3); -} -.p-4 { - padding: var(--lc-space-4); -} -.p-6 { - padding: var(--lc-space-6); -} -.p-8 { - padding: var(--lc-space-8); -} -.px-2 { - padding-inline: var(--lc-space-2); -} -.px-3 { - padding-inline: var(--lc-space-3); -} -.px-4 { - padding-inline: var(--lc-space-4); -} -.px-6 { - padding-inline: var(--lc-space-6); -} -.py-1 { - padding-block: var(--lc-space-1); -} -.py-2 { - padding-block: var(--lc-space-2); -} -.py-3 { - padding-block: var(--lc-space-3); -} -.py-4 { - padding-block: var(--lc-space-4); -} -.py-6 { - padding-block: var(--lc-space-6); -} -.pt-4 { - padding-block-start: var(--lc-space-4); -} -.pb-4 { - padding-block-end: var(--lc-space-4); -} - -/* ---- Spacing: margin (logical) ---- */ -.m-0 { - margin: 0; -} -.m-auto { - margin: auto; -} -.m-1 { - margin: var(--lc-space-1); -} -.m-2 { - margin: var(--lc-space-2); -} -.m-4 { - margin: var(--lc-space-4); -} -.mx-auto { - margin-inline: auto; -} -.my-2 { - margin-block: var(--lc-space-2); -} -.my-4 { - margin-block: var(--lc-space-4); -} -.my-6 { - margin-block: var(--lc-space-6); -} -.mt-2 { - margin-block-start: var(--lc-space-2); -} -.mt-4 { - margin-block-start: var(--lc-space-4); -} -.mt-6 { - margin-block-start: var(--lc-space-6); -} -.mb-0 { - margin-block-end: 0; -} -.mb-2 { - margin-block-end: var(--lc-space-2); -} -.mb-4 { - margin-block-end: var(--lc-space-4); -} -.mb-6 { - margin-block-end: var(--lc-space-6); -} -.ms-auto { - margin-inline-start: auto; -} -.me-auto { - margin-inline-end: auto; -} - -/* ---- Sizing ---- */ -.w-full { - inline-size: 100%; -} -.w-auto { - inline-size: auto; -} -.w-screen { - inline-size: 100vw; -} -.w-fit { - inline-size: fit-content; -} -.h-full { - block-size: 100%; -} -.h-screen { - block-size: 100vh; -} -.min-h-screen { - min-block-size: 100vh; -} -.max-w-xs { - max-inline-size: 20rem; -} -.max-w-sm { - max-inline-size: 24rem; -} -.max-w-md { - max-inline-size: 28rem; -} -.max-w-lg { - max-inline-size: 32rem; -} -.max-w-xl { - max-inline-size: 36rem; -} -.max-w-2xl { - max-inline-size: 42rem; -} -.max-w-7xl { - max-inline-size: 80rem; -} - -/* ---- Typography ---- */ -.text-xs { - font-size: var(--lc-text-xs); -} -.text-sm { - font-size: var(--lc-text-sm); -} -.text-base { - font-size: var(--lc-text-base); -} -.text-lg { - font-size: var(--lc-text-lg); -} -.text-xl { - font-size: var(--lc-text-xl); -} -.text-2xl { - font-size: var(--lc-text-2xl); -} -.text-3xl { - font-size: var(--lc-text-3xl); -} -.font-light { - font-weight: 300; -} -.font-normal { - font-weight: var(--lc-weight-normal); -} -.font-medium { - font-weight: var(--lc-weight-medium); -} -.font-semibold { - font-weight: var(--lc-weight-semibold); -} -.font-bold { - font-weight: var(--lc-weight-bold); -} -.text-start { - text-align: start; -} -.text-center { - text-align: center; -} -.text-end { - text-align: end; -} -.text-justify { - text-align: justify; -} -.leading-tight { - line-height: var(--lc-leading-tight); -} -.leading-normal { - line-height: var(--lc-leading-normal); -} -.leading-relaxed { - line-height: var(--lc-leading-relaxed); -} -.tracking-tight { - letter-spacing: -0.02em; -} -.tracking-wide { - letter-spacing: 0.04em; -} -.uppercase { - text-transform: uppercase; -} -.capitalize { - text-transform: capitalize; -} -.truncate { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} -.font-mono { - font-family: var(--lc-font-mono); -} - -/* ---- Colors ---- */ -.text-primary { - color: var(--lc-accent); -} -.text-muted { - color: var(--lc-text-muted); -} -.text-faint { - color: var(--lc-text-faint); -} -.text-success { - color: var(--lc-success-text); -} -.text-danger { - color: var(--lc-danger-text); -} -.text-warning { - color: var(--lc-warning-text); -} -.bg-bg { - background: var(--lc-bg); -} -.bg-surface { - background: var(--lc-surface); -} -.bg-surface-2 { - background: var(--lc-surface-2); -} -.bg-primary { - background: var(--lc-accent); - color: var(--lc-accent-text); -} -.bg-soft { - background: var(--lc-accent-soft); - color: var(--lc-accent-soft-text); -} -.border { - border: var(--lc-border-width) solid var(--lc-border); -} -.border-strong { - border-color: var(--lc-border-strong); -} -.border-0 { - border: 0; -} -.border-t { - border-block-start: var(--lc-border-width) solid var(--lc-border); -} -.border-b { - border-block-end: var(--lc-border-width) solid var(--lc-border); -} - -/* ---- Radius ---- */ -.rounded-none { - border-radius: 0; -} -.rounded-sm { - border-radius: var(--lc-radius-sm); -} -.rounded { - border-radius: var(--lc-radius); -} -.rounded-lg { - border-radius: var(--lc-radius-lg); -} -.rounded-full { - border-radius: var(--lc-radius-full); -} - -/* ---- Effects ---- */ -.shadow-none { - box-shadow: none; -} -.shadow-sm { - box-shadow: var(--lc-shadow-sm); -} -.shadow { - box-shadow: var(--lc-shadow); -} -.shadow-lg { - box-shadow: var(--lc-shadow-lg); -} -.backdrop-blur { - -webkit-backdrop-filter: blur(8px); - backdrop-filter: blur(8px); -} -.opacity-50 { - opacity: 0.5; -} -.opacity-75 { - opacity: 0.75; -} - -/* ---- Position ---- */ -.relative { - position: relative; -} -.absolute { - position: absolute; -} -.fixed { - position: fixed; -} -.sticky { - position: sticky; -} -.inset-0 { - inset: 0; -} -.top-0 { - inset-block-start: 0; -} -.bottom-0 { - inset-block-end: 0; -} -.start-0 { - inset-inline-start: 0; -} -.end-0 { - inset-inline-end: 0; -} -.z-10 { - z-index: 10; -} -.z-20 { - z-index: 20; -} -.z-30 { - z-index: 30; -} -.z-50 { - z-index: 50; -} - -/* ---- Misc ---- */ -.overflow-hidden { - overflow: hidden; -} -.overflow-auto { - overflow: auto; -} -.overflow-x-auto { - overflow-x: auto; -} -.cursor-pointer { - cursor: pointer; -} -.cursor-default { - cursor: default; -} -.select-none { - user-select: none; -} -.transition { - transition: all var(--lc-transition); -} -.sr-only { - position: absolute; - inline-size: 1px; - block-size: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - white-space: nowrap; - border: 0; -} -.aspect-square { - aspect-ratio: 1; -} -.aspect-video { - aspect-ratio: 16/9; -} - -/* ---- Status colors (solid / soft / text / border) ---- */ -.text-info { - color: var(--lc-info-text); -} -.bg-success { - background: var(--lc-success); - color: #fff; -} -.bg-warning { - background: var(--lc-warning); - color: #fff; -} -.bg-danger { - background: var(--lc-danger); - color: #fff; -} -.bg-info { - background: var(--lc-info); - color: #fff; -} -.bg-success-soft { - background: var(--lc-success-soft); - color: var(--lc-success-text); -} -.bg-warning-soft { - background: var(--lc-warning-soft); - color: var(--lc-warning-text); -} -.bg-danger-soft { - background: var(--lc-danger-soft); - color: var(--lc-danger-text); -} -.bg-info-soft { - background: var(--lc-info-soft); - color: var(--lc-info-text); -} -.border-success { - border-color: var(--lc-success); -} -.border-warning { - border-color: var(--lc-warning); -} -.border-danger { - border-color: var(--lc-danger); -} -.border-info { - border-color: var(--lc-info); -} -.border-primary { - border-color: var(--lc-accent); -} - -/* ---- Full gap scale + directional gaps ---- */ -.gap-5 { - gap: var(--lc-space-5); -} -.gap-10 { - gap: var(--lc-space-10); -} -.gap-12 { - gap: var(--lc-space-12); -} -.gap-x-2 { - column-gap: var(--lc-space-2); -} -.gap-x-4 { - column-gap: var(--lc-space-4); -} -.gap-x-6 { - column-gap: var(--lc-space-6); -} -.gap-y-2 { - row-gap: var(--lc-space-2); -} -.gap-y-4 { - row-gap: var(--lc-space-4); -} -.gap-y-6 { - row-gap: var(--lc-space-6); -} -/* ---- Full col-span scale ---- */ -.col-span-1 { - grid-column: span 1; -} -.col-span-5 { - grid-column: span 5; -} -.col-span-7 { - grid-column: span 7; -} -.col-span-8 { - grid-column: span 8; -} -.col-span-9 { - grid-column: span 9; -} -.col-span-10 { - grid-column: span 10; -} -.col-span-11 { - grid-column: span 11; -} -.col-span-12 { - grid-column: span 12; -} - -/* ========================================================================== - Responsive prefixes (mobile-first), full scale: sm 640 / md 768 / lg 1024 / xl 1280 - ========================================================================== */ -@media (min-width: 640px) { - .sm\:block { - display: block; - } - .sm\:inline-block { - display: inline-block; - } - .sm\:flex { - display: flex; - } - .sm\:inline-flex { - display: inline-flex; - } - .sm\:grid { - display: grid; - } - .sm\:inline-grid { - display: inline-grid; - } - .sm\:hidden { - display: none; - } - .sm\:flex-row { - flex-direction: row; - } - .sm\:flex-col { - flex-direction: column; - } - .sm\:flex-wrap { - flex-wrap: wrap; - } - .sm\:items-start { - align-items: flex-start; - } - .sm\:items-center { - align-items: center; - } - .sm\:items-end { - align-items: flex-end; - } - .sm\:justify-start { - justify-content: flex-start; - } - .sm\:justify-center { - justify-content: center; - } - .sm\:justify-end { - justify-content: flex-end; - } - .sm\:justify-between { - justify-content: space-between; - } - .sm\:grid-cols-1 { - grid-template-columns: repeat(1, 1fr); - } - .sm\:grid-cols-2 { - grid-template-columns: repeat(2, 1fr); - } - .sm\:grid-cols-3 { - grid-template-columns: repeat(3, 1fr); - } - .sm\:grid-cols-4 { - grid-template-columns: repeat(4, 1fr); - } - .sm\:grid-cols-5 { - grid-template-columns: repeat(5, 1fr); - } - .sm\:grid-cols-6 { - grid-template-columns: repeat(6, 1fr); - } - .sm\:grid-cols-12 { - grid-template-columns: repeat(12, 1fr); - } - .sm\:col-span-1 { - grid-column: span 1; - } - .sm\:col-span-2 { - grid-column: span 2; - } - .sm\:col-span-3 { - grid-column: span 3; - } - .sm\:col-span-4 { - grid-column: span 4; - } - .sm\:col-span-5 { - grid-column: span 5; - } - .sm\:col-span-6 { - grid-column: span 6; - } - .sm\:col-span-full { - grid-column: 1 / -1; - } - .sm\:gap-0 { - gap: 0; - } - .sm\:gap-1 { - gap: var(--lc-space-1); - } - .sm\:gap-2 { - gap: var(--lc-space-2); - } - .sm\:gap-3 { - gap: var(--lc-space-3); - } - .sm\:gap-4 { - gap: var(--lc-space-4); - } - .sm\:gap-5 { - gap: var(--lc-space-5); - } - .sm\:gap-6 { - gap: var(--lc-space-6); - } - .sm\:gap-8 { - gap: var(--lc-space-8); - } - .sm\:text-start { - text-align: start; - } - .sm\:text-center { - text-align: center; - } - .sm\:text-end { - text-align: end; - } -} -@media (min-width: 768px) { - .md\:block { - display: block; - } - .md\:inline-block { - display: inline-block; - } - .md\:flex { - display: flex; - } - .md\:inline-flex { - display: inline-flex; - } - .md\:grid { - display: grid; - } - .md\:inline-grid { - display: inline-grid; - } - .md\:hidden { - display: none; - } - .md\:flex-row { - flex-direction: row; - } - .md\:flex-col { - flex-direction: column; - } - .md\:flex-wrap { - flex-wrap: wrap; - } - .md\:items-start { - align-items: flex-start; - } - .md\:items-center { - align-items: center; - } - .md\:items-end { - align-items: flex-end; - } - .md\:justify-start { - justify-content: flex-start; - } - .md\:justify-center { - justify-content: center; - } - .md\:justify-end { - justify-content: flex-end; - } - .md\:justify-between { - justify-content: space-between; - } - .md\:grid-cols-1 { - grid-template-columns: repeat(1, 1fr); - } - .md\:grid-cols-2 { - grid-template-columns: repeat(2, 1fr); - } - .md\:grid-cols-3 { - grid-template-columns: repeat(3, 1fr); - } - .md\:grid-cols-4 { - grid-template-columns: repeat(4, 1fr); - } - .md\:grid-cols-5 { - grid-template-columns: repeat(5, 1fr); - } - .md\:grid-cols-6 { - grid-template-columns: repeat(6, 1fr); - } - .md\:grid-cols-12 { - grid-template-columns: repeat(12, 1fr); - } - .md\:col-span-1 { - grid-column: span 1; - } - .md\:col-span-2 { - grid-column: span 2; - } - .md\:col-span-3 { - grid-column: span 3; - } - .md\:col-span-4 { - grid-column: span 4; - } - .md\:col-span-5 { - grid-column: span 5; - } - .md\:col-span-6 { - grid-column: span 6; - } - .md\:col-span-full { - grid-column: 1 / -1; - } - .md\:gap-0 { - gap: 0; - } - .md\:gap-1 { - gap: var(--lc-space-1); - } - .md\:gap-2 { - gap: var(--lc-space-2); - } - .md\:gap-3 { - gap: var(--lc-space-3); - } - .md\:gap-4 { - gap: var(--lc-space-4); - } - .md\:gap-5 { - gap: var(--lc-space-5); - } - .md\:gap-6 { - gap: var(--lc-space-6); - } - .md\:gap-8 { - gap: var(--lc-space-8); - } - .md\:text-start { - text-align: start; - } - .md\:text-center { - text-align: center; - } - .md\:text-end { - text-align: end; - } -} -@media (min-width: 1024px) { - .lg\:block { - display: block; - } - .lg\:inline-block { - display: inline-block; - } - .lg\:flex { - display: flex; - } - .lg\:inline-flex { - display: inline-flex; - } - .lg\:grid { - display: grid; - } - .lg\:inline-grid { - display: inline-grid; - } - .lg\:hidden { - display: none; - } - .lg\:flex-row { - flex-direction: row; - } - .lg\:flex-col { - flex-direction: column; - } - .lg\:flex-wrap { - flex-wrap: wrap; - } - .lg\:items-start { - align-items: flex-start; - } - .lg\:items-center { - align-items: center; - } - .lg\:items-end { - align-items: flex-end; - } - .lg\:justify-start { - justify-content: flex-start; - } - .lg\:justify-center { - justify-content: center; - } - .lg\:justify-end { - justify-content: flex-end; - } - .lg\:justify-between { - justify-content: space-between; - } - .lg\:grid-cols-1 { - grid-template-columns: repeat(1, 1fr); - } - .lg\:grid-cols-2 { - grid-template-columns: repeat(2, 1fr); - } - .lg\:grid-cols-3 { - grid-template-columns: repeat(3, 1fr); - } - .lg\:grid-cols-4 { - grid-template-columns: repeat(4, 1fr); - } - .lg\:grid-cols-5 { - grid-template-columns: repeat(5, 1fr); - } - .lg\:grid-cols-6 { - grid-template-columns: repeat(6, 1fr); - } - .lg\:grid-cols-12 { - grid-template-columns: repeat(12, 1fr); - } - .lg\:col-span-1 { - grid-column: span 1; - } - .lg\:col-span-2 { - grid-column: span 2; - } - .lg\:col-span-3 { - grid-column: span 3; - } - .lg\:col-span-4 { - grid-column: span 4; - } - .lg\:col-span-5 { - grid-column: span 5; - } - .lg\:col-span-6 { - grid-column: span 6; - } - .lg\:col-span-full { - grid-column: 1 / -1; - } - .lg\:gap-0 { - gap: 0; - } - .lg\:gap-1 { - gap: var(--lc-space-1); - } - .lg\:gap-2 { - gap: var(--lc-space-2); - } - .lg\:gap-3 { - gap: var(--lc-space-3); - } - .lg\:gap-4 { - gap: var(--lc-space-4); - } - .lg\:gap-5 { - gap: var(--lc-space-5); - } - .lg\:gap-6 { - gap: var(--lc-space-6); - } - .lg\:gap-8 { - gap: var(--lc-space-8); - } - .lg\:text-start { - text-align: start; - } - .lg\:text-center { - text-align: center; - } - .lg\:text-end { - text-align: end; - } -} -@media (min-width: 1280px) { - .xl\:block { - display: block; - } - .xl\:inline-block { - display: inline-block; - } - .xl\:flex { - display: flex; - } - .xl\:inline-flex { - display: inline-flex; - } - .xl\:grid { - display: grid; - } - .xl\:inline-grid { - display: inline-grid; - } - .xl\:hidden { - display: none; - } - .xl\:flex-row { - flex-direction: row; - } - .xl\:flex-col { - flex-direction: column; - } - .xl\:flex-wrap { - flex-wrap: wrap; - } - .xl\:items-start { - align-items: flex-start; - } - .xl\:items-center { - align-items: center; - } - .xl\:items-end { - align-items: flex-end; - } - .xl\:justify-start { - justify-content: flex-start; - } - .xl\:justify-center { - justify-content: center; - } - .xl\:justify-end { - justify-content: flex-end; - } - .xl\:justify-between { - justify-content: space-between; - } - .xl\:grid-cols-1 { - grid-template-columns: repeat(1, 1fr); - } - .xl\:grid-cols-2 { - grid-template-columns: repeat(2, 1fr); - } - .xl\:grid-cols-3 { - grid-template-columns: repeat(3, 1fr); - } - .xl\:grid-cols-4 { - grid-template-columns: repeat(4, 1fr); - } - .xl\:grid-cols-5 { - grid-template-columns: repeat(5, 1fr); - } - .xl\:grid-cols-6 { - grid-template-columns: repeat(6, 1fr); - } - .xl\:grid-cols-12 { - grid-template-columns: repeat(12, 1fr); - } - .xl\:col-span-1 { - grid-column: span 1; - } - .xl\:col-span-2 { - grid-column: span 2; - } - .xl\:col-span-3 { - grid-column: span 3; - } - .xl\:col-span-4 { - grid-column: span 4; - } - .xl\:col-span-5 { - grid-column: span 5; - } - .xl\:col-span-6 { - grid-column: span 6; - } - .xl\:col-span-full { - grid-column: 1 / -1; - } - .xl\:gap-0 { - gap: 0; - } - .xl\:gap-1 { - gap: var(--lc-space-1); - } - .xl\:gap-2 { - gap: var(--lc-space-2); - } - .xl\:gap-3 { - gap: var(--lc-space-3); - } - .xl\:gap-4 { - gap: var(--lc-space-4); - } - .xl\:gap-5 { - gap: var(--lc-space-5); - } - .xl\:gap-6 { - gap: var(--lc-space-6); - } - .xl\:gap-8 { - gap: var(--lc-space-8); - } - .xl\:text-start { - text-align: start; - } - .xl\:text-center { - text-align: center; - } - .xl\:text-end { - text-align: end; - } -} -/* ============================================================ - Print styles - Token-first: remap tokens to ink-friendly, high-contrast values - (overriding any data-style / data-theme), then tidy the chrome so - pages and PDFs are always legible. Utilities: .no-print, .print-only. - ============================================================ */ - -.print-only { - display: none; -} - -@media print { - /* Force a light, high-contrast palette regardless of the active style/theme. - html[data-style]/html[data-theme] (0,1,1) outrank the [data-style] blocks. */ - :root, - html[data-style], - html[data-theme] { - --lc-bg: #fff; - --lc-surface: #fff; - --lc-surface-2: #fff; - --lc-text: #000; - --lc-text-muted: #333; - --lc-text-faint: #555; - --lc-border: #bbb; - --lc-border-strong: #888; - --lc-accent: #111; - --lc-accent-hover: #000; - --lc-accent-active: #000; - --lc-accent-text: #fff; - --lc-accent-soft: #eee; - --lc-accent-soft-text: #000; - --lc-success: #137a3a; - --lc-danger: #b42318; - --lc-warning: #8a6100; - --lc-info: #0b5cad; - --lc-success-soft: #fff; - --lc-danger-soft: #fff; - --lc-warning-soft: #fff; - --lc-info-soft: #fff; - --lc-success-text: #0f5c2c; - --lc-danger-text: #8a1c14; - --lc-warning-text: #6b4b00; - --lc-info-text: #0a4a86; - --lc-shadow-sm: none; - --lc-shadow: none; - --lc-shadow-lg: none; - --lc-shadow-hard: none; - --lc-blur: none; - --lc-bg-gradient: none; - --lc-ring: transparent; - } - - html, - body { - background: #fff !important; - color: #000 !important; - } - *, - *::before, - *::after { - box-shadow: none !important; - text-shadow: none !important; - } - - /* Let content flow: no sticky/fixed chrome on paper */ - .navbar, - .sidebar { - position: static !important; - } - - /* Hide purely interactive or decorative chrome */ - .navbar-toggle, - .drawer, - .drawer-overlay, - dialog.modal, - .toast-region, - .tooltip, - .popover, - .dropdown-menu, - .carousel-nav, - .carousel-dots, - .spinner, - .skeleton, - .no-print { - display: none !important; - } - .print-only { - display: revert !important; - } - - /* Keep structure readable in ink */ - .card, - .alert { - border: 1px solid #ccc !important; - } - .table th, - .table td { - border: 1px solid #ccc !important; - } - thead { - display: table-header-group; - } - - /* Reveal link targets (skip buttons/badges) */ - a { - text-decoration: underline; - } - a:not(.btn, .badge)[href^="http"]::after { - content: " (" attr(href) ")"; - font-size: 0.85em; - color: #555; - word-break: break-all; - } - - /* Page-break hygiene */ - h1, - h2, - h3, - h4 { - break-after: avoid; - } - p, - li, - blockquote { - orphans: 3; - widows: 3; - } - img, - pre, - blockquote, - table, - tr, - .card, - .alert { - break-inside: avoid; - } -} diff --git a/package/dist/lombok.js b/package/dist/lombok.js deleted file mode 100644 index 983ce31..0000000 --- a/package/dist/lombok.js +++ /dev/null @@ -1,244 +0,0 @@ -/* LombokCSS — lombok.js (optional, ~1.5KB). Zero dependencies. - Enhances: dropdowns, tabs, modals, toasts, table sort, navbar toggle. - Everything degrades gracefully if JS is off (details/dialog are native). */ -(function () { - "use strict"; - - /* Bail out where there is no DOM. The package sets "type": "module" and - points main/exports["."] here, so SSR frameworks (Next, Nuxt, Astro, - SvelteKit) evaluate this file on the server. Without this guard the - import throws ReferenceError: document is not defined. */ - if (typeof document === "undefined") return; - - var d = document; - - /* Collapse a container and tell assistive tech its trigger is closed. */ - function collapse(el, toggleSelector) { - el.classList.remove("is-open"); - var b = el.querySelector(toggleSelector); - if (b) b.setAttribute("aria-expanded", "false"); - } - - /* Dropdowns: toggle [data-dropdown] -> nearest .dropdown gets .is-open */ - d.addEventListener("click", function (e) { - var t = e.target.closest("[data-dropdown-toggle]"); - var open = d.querySelector(".dropdown.is-open"); - if (open && (!t || !open.contains(t))) collapse(open, "[data-dropdown-toggle]"); - if (t) { - e.preventDefault(); - var dd = t.closest(".dropdown"); - if (dd) { - dd.classList.toggle("is-open"); - t.setAttribute("aria-expanded", dd.classList.contains("is-open")); - } - } - }); - d.addEventListener("keydown", function (e) { - if (e.key === "Escape") { - var o = d.querySelector(".dropdown.is-open"); - if (o) collapse(o, "[data-dropdown-toggle]"); - } - }); - - /* Tabs: [role=tablist] with buttons whose aria-controls -> panel id */ - d.querySelectorAll('[role="tablist"]').forEach(function (list) { - var tabs = list.querySelectorAll('[role="tab"]'); - tabs.forEach(function (tab) { - tab.addEventListener("click", function () { - tabs.forEach(function (x) { - x.setAttribute("aria-selected", "false"); - var p = d.getElementById(x.getAttribute("aria-controls")); - if (p) p.hidden = true; - }); - tab.setAttribute("aria-selected", "true"); - var panel = d.getElementById(tab.getAttribute("aria-controls")); - if (panel) panel.hidden = false; - }); - }); - }); - - /* Modal: [data-modal-open="id"] / [data-modal-close]; uses native */ - d.addEventListener("click", function (e) { - var op = e.target.closest("[data-modal-open]"); - if (op) { - var m = d.getElementById(op.getAttribute("data-modal-open")); - if (m && m.showModal) m.showModal(); - } - var cl = e.target.closest("[data-modal-close]"); - if (cl) { - var dlg = cl.closest("dialog"); - if (dlg) dlg.close(); - } - }); - /* click on backdrop closes */ - d.querySelectorAll("dialog.modal").forEach(function (dlg) { - dlg.addEventListener("click", function (e) { - if (e.target === dlg) dlg.close(); - }); - }); - - /* Navbar toggle (.navbar-toggle button toggles .is-open on .navbar) */ - d.addEventListener("click", function (e) { - var b = e.target.closest(".navbar-toggle"); - if (b) { - var nav = b.closest(".navbar"); - if (nav) nav.classList.toggle("is-open"); - } - }); - - /* Drawer / Offcanvas: [data-drawer-open="id"] / [data-drawer-close] */ - function closeDrawer(dr) { - dr.classList.remove("is-open"); - var ov = d.getElementById(dr.id + "-overlay") || dr.nextElementSibling; - if (ov && ov.classList.contains("drawer-overlay")) ov.classList.remove("is-open"); - } - d.addEventListener("click", function (e) { - var op = e.target.closest("[data-drawer-open]"); - if (op) { - var dr = d.getElementById(op.getAttribute("data-drawer-open")); - if (dr) { - dr.classList.add("is-open"); - var ov = d.getElementById(dr.id + "-overlay") || dr.nextElementSibling; - if (ov && ov.classList.contains("drawer-overlay")) ov.classList.add("is-open"); - } - } - var cl = e.target.closest("[data-drawer-close], .drawer-overlay"); - if (cl) { - var open = d.querySelector(".drawer.is-open"); - if (open) closeDrawer(open); - } - }); - - /* Popover: [data-popover-toggle] -> nearest .popover gets .is-open */ - d.addEventListener("click", function (e) { - var t = e.target.closest("[data-popover-toggle]"); - var open = d.querySelector(".popover.is-open"); - if (open && (!t || !open.contains(t))) collapse(open, "[data-popover-toggle]"); - if (t) { - e.preventDefault(); - var pop = t.closest(".popover"); - if (pop) { - pop.classList.toggle("is-open"); - t.setAttribute("aria-expanded", pop.classList.contains("is-open")); - } - } - }); - d.addEventListener("keydown", function (e) { - if (e.key === "Escape") { - var dr = d.querySelector(".drawer.is-open"); - if (dr) closeDrawer(dr); - var po = d.querySelector(".popover.is-open"); - if (po) collapse(po, "[data-popover-toggle]"); - } - }); - - /* Toast API: Lombok.toast("msg", {variant:"success", timeout:3000}) */ - window.Lombok = window.Lombok || {}; - window.Lombok.toast = function (msg, opts) { - opts = opts || {}; - var region = d.querySelector(".toast-region"); - if (!region) { - region = d.createElement("div"); - region.className = "toast-region"; - region.setAttribute("aria-live", "polite"); - d.body.appendChild(region); - } - var el = d.createElement("div"); - el.className = "toast" + (opts.variant ? " alert-" + opts.variant : ""); - el.setAttribute("role", "status"); - el.textContent = msg; - region.appendChild(el); - setTimeout(function () { - el.remove(); - }, opts.timeout || 3500); - return el; - }; - - /* Carousel: prev/next buttons + dots; scroll by one slide width */ - d.querySelectorAll(".carousel").forEach(function (c) { - var track = c.querySelector(".carousel-track"); - if (!track) return; - function step() { - var slide = track.querySelector(".carousel-slide"); - var gap = - parseFloat(getComputedStyle(track).columnGap || getComputedStyle(track).gap || 16) || 16; - return slide ? slide.getBoundingClientRect().width + gap : track.clientWidth; - } - function last() { - var n = track.querySelectorAll(".carousel-slide").length; - return n ? n - 1 : Math.round((track.scrollWidth - track.clientWidth) / step()); - } - var dir = d.documentElement.getAttribute("dir") === "rtl" ? -1 : 1; - /* Move to a tracked target index, never by a delta. scrollBy is relative to - wherever an in-flight smooth scroll currently is, so two quick clicks used - to advance from mid-animation and leave the track between slides. */ - var index = 0; - var settle; - function go(i) { - /* A re-sync armed by the previous animation must not land on top of the - target we are about to set; the events this scroll emits will arm a - fresh one. Without this, a click arriving between the end of one - animation and its 120ms re-sync moves from the stale index. */ - clearTimeout(settle); - index = Math.max(0, Math.min(i, last())); - track.scrollTo({ left: step() * index * dir, behavior: "smooth" }); - } - var prev = c.querySelector(".carousel-prev"), - next = c.querySelector(".carousel-next"); - if (prev) - prev.addEventListener("click", function () { - go(index - 1); - }); - if (next) - next.addEventListener("click", function () { - go(index + 1); - }); - var dots = c.querySelectorAll(".carousel-dots > *"); - dots.forEach(function (dot, i) { - dot.addEventListener("click", function () { - go(i); - }); - }); - track.addEventListener( - "scroll", - function () { - var idx = Math.round(Math.abs(track.scrollLeft) / step()); - dots.forEach(function (x, i) { - x.classList.toggle("is-active", i === idx); - }); - /* Re-sync the target after a drag or swipe, once the track stops. */ - clearTimeout(settle); - settle = setTimeout(function () { - index = Math.max(0, Math.min(idx, last())); - }, 120); - }, - { passive: true }, - ); - }); - - /* Table sort: click sorts its column (string/number aware) */ - d.querySelectorAll("table.table thead th[aria-sort]").forEach(function (th) { - th.addEventListener("click", function () { - var table = th.closest("table"), - tbody = table.tBodies[0]; - var idx = Array.prototype.indexOf.call(th.parentNode.children, th); - var asc = th.getAttribute("aria-sort") !== "ascending"; - th.parentNode.querySelectorAll("th[aria-sort]").forEach(function (o) { - o.setAttribute("aria-sort", "none"); - }); - th.setAttribute("aria-sort", asc ? "ascending" : "descending"); - var rows = Array.prototype.slice.call(tbody.rows); - rows.sort(function (a, b) { - var x = a.cells[idx].textContent.trim(), - y = b.cells[idx].textContent.trim(); - var nx = parseFloat(x), - ny = parseFloat(y); - var r = !isNaN(nx) && !isNaN(ny) ? nx - ny : x.localeCompare(y); - return asc ? r : -r; - }); - rows.forEach(function (r) { - tbody.appendChild(r); - }); - }); - }); -})(); diff --git a/package/dist/lombok.min.css b/package/dist/lombok.min.css deleted file mode 100644 index ecde4b6..0000000 --- a/package/dist/lombok.min.css +++ /dev/null @@ -1 +0,0 @@ -:root{--lc-white:#fff;--lc-black:#0a0a0a;--lc-bg:#f6f7f9;--lc-surface:#fff;--lc-surface-2:#f1f3f5;--lc-text:#1a1d21;--lc-text-muted:#5b6470;--lc-text-faint:#8a93a0;--lc-border:#e2e6ea;--lc-border-strong:#c8cfd6;--lc-accent:#3b82f6;--lc-accent-hover:#2f6fe0;--lc-accent-active:#2861c9;--lc-accent-text:#fff;--lc-accent-soft:#e8f0fe;--lc-accent-soft-text:#1f5fd1;--lc-ring:#3b82f673;--lc-success:#16a34a;--lc-success-soft:#e7f6ec;--lc-success-text:#0f7a37;--lc-warning:#d97706;--lc-warning-soft:#fdf0dd;--lc-warning-text:#a85d05;--lc-danger:#dc2626;--lc-danger-soft:#fde8e8;--lc-danger-text:#b21d1d;--lc-info:#0ea5e9;--lc-info-soft:#e3f5fd;--lc-info-text:#0b7fb4;--lc-font-sans:system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;--lc-font-mono:ui-monospace, "SF Mono", "JetBrains Mono", "Fira Code", Menlo, Consolas, monospace;--lc-font-display:var(--lc-font-sans);--lc-text-xs:.75rem;--lc-text-sm:.875rem;--lc-text-base:1rem;--lc-text-lg:1.125rem;--lc-text-xl:1.25rem;--lc-text-2xl:1.5rem;--lc-text-3xl:1.875rem;--lc-text-4xl:2.25rem;--lc-leading-tight:1.2;--lc-leading-normal:1.55;--lc-leading-relaxed:1.75;--lc-weight-normal:400;--lc-weight-medium:500;--lc-weight-semibold:600;--lc-weight-bold:700;--lc-tracking:0;--lc-space-0:0;--lc-space-1:.25rem;--lc-space-2:.5rem;--lc-space-3:.75rem;--lc-space-4:1rem;--lc-space-5:1.25rem;--lc-space-6:1.5rem;--lc-space-8:2rem;--lc-space-10:2.5rem;--lc-space-12:3rem;--lc-radius-sm:6px;--lc-radius:10px;--lc-radius-lg:16px;--lc-radius-full:9999px;--lc-border-width:1px;--lc-shadow-sm:0 1px 2px #1018280f;--lc-shadow:0 4px 12px #10182814;--lc-shadow-lg:0 12px 32px #1018281f;--lc-shadow-hard:none;--lc-blur:none;--lc-glass-tint:var(--lc-surface);--lc-glass-border:var(--lc-border);--lc-transition:.16s cubic-bezier(.4, 0, .2, 1);--lc-container:1120px;--lc-navbar-h:60px;--lc-z-base:1;--lc-z-dropdown:1000;--lc-z-sticky:1020;--lc-z-modal:1050;--lc-z-toast:1080;--lc-z-tooltip:1090}@media (prefers-color-scheme:dark){:root:not([data-theme=light]){--lc-bg:#0f1115;--lc-surface:#171a21;--lc-surface-2:#1f242d;--lc-text:#e7eaee;--lc-text-muted:#9aa4b2;--lc-text-faint:#6b7480;--lc-border:#2a2f3a;--lc-border-strong:#3a404d;--lc-accent-soft:#16263f;--lc-accent-soft-text:#8ab4ff;--lc-shadow-sm:0 1px 2px #0006;--lc-shadow:0 4px 12px #00000073;--lc-shadow-lg:0 12px 32px #0000008c;--lc-success-soft:#10241a;--lc-warning-soft:#2a1f0d;--lc-danger-soft:#2a1414;--lc-info-soft:#0c2530;--lc-success-text:#6ee7a0;--lc-warning-text:#fbbf24;--lc-danger-text:#fca5a5;--lc-info-text:#67d3f7}}[data-theme=dark]{--lc-bg:#0f1115;--lc-surface:#171a21;--lc-surface-2:#1f242d;--lc-text:#e7eaee;--lc-text-muted:#9aa4b2;--lc-text-faint:#6b7480;--lc-border:#2a2f3a;--lc-border-strong:#3a404d;--lc-accent-soft:#16263f;--lc-accent-soft-text:#8ab4ff;--lc-shadow-sm:0 1px 2px #0006;--lc-shadow:0 4px 12px #00000073;--lc-shadow-lg:0 12px 32px #0000008c;--lc-success-soft:#10241a;--lc-warning-soft:#2a1f0d;--lc-danger-soft:#2a1414;--lc-info-soft:#0c2530;--lc-success-text:#6ee7a0;--lc-warning-text:#fbbf24;--lc-danger-text:#fca5a5;--lc-info-text:#67d3f7}*,:before,:after{box-sizing:border-box}*{margin:0}html{-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;scroll-behavior:smooth}@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}*,:before,:after{transition-duration:.001ms!important;animation-duration:.001ms!important}}body{font-family:var(--lc-font-sans);font-size:var(--lc-text-base);line-height:var(--lc-leading-normal);letter-spacing:var(--lc-tracking);color:var(--lc-text);background-color:var(--lc-bg);-webkit-font-smoothing:antialiased;text-rendering:optimizelegibility;transition:background-color var(--lc-transition), color var(--lc-transition);margin:0}img,picture,video,canvas,svg{max-inline-size:100%;height:auto;display:block}input,button,textarea,select{font:inherit;color:inherit}p,h1,h2,h3,h4,h5,h6{overflow-wrap:break-word}h1,h2,h3,h4,h5,h6{font-family:var(--lc-font-display);line-height:var(--lc-leading-tight);font-weight:var(--lc-weight-semibold);margin-block:0 var(--lc-space-3);text-wrap:balance}h1{font-size:var(--lc-text-3xl)}h2{font-size:var(--lc-text-2xl)}h3{font-size:var(--lc-text-xl)}h4{font-size:var(--lc-text-lg)}h5{font-size:var(--lc-text-base)}h6{font-size:var(--lc-text-sm);text-transform:uppercase;letter-spacing:.06em;color:var(--lc-text-muted)}p{margin-block:0 var(--lc-space-4)}.lead{font-size:var(--lc-text-lg);color:var(--lc-text-muted)}small,.caption{font-size:var(--lc-text-sm);color:var(--lc-text-muted)}a{color:var(--lc-accent);text-underline-offset:3px;transition:color var(--lc-transition);text-decoration:none}a:hover{color:var(--lc-accent-hover);text-decoration:underline}strong,b{font-weight:var(--lc-weight-semibold)}ul,ol{margin-block:0 var(--lc-space-4);padding-inline-start:1.4em}li{margin-block-end:var(--lc-space-1)}blockquote{margin-block:0 var(--lc-space-4);border-inline-start:3px solid var(--lc-border-strong);color:var(--lc-text-muted);padding-inline-start:var(--lc-space-4)}hr,.divider{border:0;border-block-start:var(--lc-border-width) solid var(--lc-border);margin-block:var(--lc-space-6)}.divider-vertical{border:0;border-inline-start:var(--lc-border-width) solid var(--lc-border);block-size:1.2em;margin-inline:var(--lc-space-3);display:inline-block}code,kbd,samp,pre{font-family:var(--lc-font-mono);font-size:.9em}code{background:var(--lc-surface-2);border-radius:var(--lc-radius-sm);border:var(--lc-border-width) solid var(--lc-border);padding:.15em .4em}pre{background:var(--lc-surface-2);border:var(--lc-border-width) solid var(--lc-border);border-radius:var(--lc-radius);padding:var(--lc-space-4);margin-block:0 var(--lc-space-4);overflow:auto}pre code{background:0 0;border:0;padding:0}.kbd,kbd{font-family:var(--lc-font-mono);font-size:var(--lc-text-xs);color:var(--lc-text);background:var(--lc-surface);border:var(--lc-border-width) solid var(--lc-border-strong);border-radius:var(--lc-radius-sm);border-block-end-width:2px;padding:.35em .5em;line-height:1;display:inline-block}::selection{background:var(--lc-accent);color:var(--lc-accent-text)}:where(a,button,input,select,textarea,summary,[tabindex]):focus-visible{outline:2px solid var(--lc-accent);outline-offset:2px;border-radius:var(--lc-radius-sm)}.container{inline-size:100%;max-inline-size:var(--lc-container);padding-inline:var(--lc-space-4);margin-inline:auto}.section{padding-block:var(--lc-space-12)}[data-style=modern-corporate-flat]{--lc-accent:#3b82f6;--lc-accent-hover:#2f6fe0;--lc-accent-active:#2861c9;--lc-radius-sm:6px;--lc-radius:10px;--lc-radius-lg:16px;--lc-border-width:1px;--lc-shadow-sm:0 1px 2px #1018280f;--lc-shadow:0 4px 12px #10182814;--lc-shadow-lg:0 12px 32px #1018281f;--lc-shadow-hard:none;--lc-blur:none}[data-style=resonant-stark]{--lc-bg:#08090c;--lc-surface:#101218;--lc-surface-2:#171a22;--lc-text:#f3f5f8;--lc-text-muted:#a3acba;--lc-text-faint:#6c7585;--lc-border:#23262f;--lc-border-strong:#333845;--lc-accent:#7c6cff;--lc-accent-hover:#8d7fff;--lc-accent-active:#6b5af0;--lc-accent-text:#fff;--lc-accent-soft:#1b1830;--lc-accent-soft-text:#bcb2ff;--lc-ring:#7c6cff80;--lc-success-soft:#11271b;--lc-success-text:#6ee7a0;--lc-warning-soft:#2a1f0d;--lc-warning-text:#fbbf24;--lc-danger-soft:#2a1414;--lc-danger-text:#fca5a5;--lc-info-soft:#0c2530;--lc-info-text:#67d3f7;--lc-radius-sm:5px;--lc-radius:7px;--lc-radius-lg:11px;--lc-border-width:1px;--lc-shadow-sm:0 1px 2px #00000080;--lc-shadow:0 2px 10px #0000008c;--lc-shadow-lg:0 10px 36px #000000a6;--lc-shadow-hard:none;--lc-blur:none;--lc-tracking:-.01em;--lc-font-display:var(--lc-font-sans);--lc-weight-semibold:600}[data-style=neo-brutalism]{--lc-bg:#fdf6e3;--lc-surface:#fff;--lc-surface-2:#fff3c4;--lc-text:#0a0a0a;--lc-text-muted:#33312b;--lc-text-faint:#6b6760;--lc-border:#0a0a0a;--lc-border-strong:#0a0a0a;--lc-accent:#ff4f00;--lc-accent-hover:#e84700;--lc-accent-active:#cc3f00;--lc-accent-text:#fff;--lc-accent-soft:#ffe1cc;--lc-accent-soft-text:#0a0a0a;--lc-ring:#0a0a0ae6;--lc-success:#1f9e4d;--lc-warning:#e0a400;--lc-danger:#e3342f;--lc-info:#2563eb;--lc-success-soft:#d9f5e2;--lc-warning-soft:#fff0c4;--lc-danger-soft:#ffd9d7;--lc-info-soft:#d7e3ff;--lc-radius-sm:0px;--lc-radius:0px;--lc-radius-lg:0px;--lc-border-width:2.5px;--lc-shadow-sm:3px 3px 0 #0a0a0a;--lc-shadow:5px 5px 0 #0a0a0a;--lc-shadow-lg:8px 8px 0 #0a0a0a;--lc-shadow-hard:5px 5px 0 #0a0a0a;--lc-blur:none;--lc-weight-medium:700;--lc-weight-semibold:800;--lc-weight-bold:900}[data-style=neo-brutalism][data-theme=dark]{--lc-bg:#16140f;--lc-surface:#1f1c14;--lc-surface-2:#2a2517;--lc-text:#fdf6e3;--lc-text-muted:#cfc7ad;--lc-text-faint:#8f8a72;--lc-border:#fdf6e3;--lc-border-strong:#fdf6e3;--lc-shadow-sm:3px 3px 0 #fdf6e3;--lc-shadow:5px 5px 0 #fdf6e3;--lc-shadow-lg:8px 8px 0 #fdf6e3;--lc-shadow-hard:5px 5px 0 #fdf6e3;--lc-accent-soft:#3a2a1c;--lc-accent-soft-text:#fdf6e3;--lc-success-soft:#11271b;--lc-success-text:#6ee7a0;--lc-warning-soft:#2a1f0d;--lc-warning-text:#fbbf24;--lc-danger-soft:#2a1414;--lc-danger-text:#fca5a5;--lc-info-soft:#0c2530;--lc-info-text:#67d3f7}[data-style=semantic-minimalist]{--lc-bg:#fbfbfa;--lc-surface:#fff;--lc-surface-2:#f4f4f2;--lc-text:#23211e;--lc-text-muted:#6a665f;--lc-text-faint:#9a958c;--lc-border:#e8e6e1;--lc-border-strong:#d4d1c9;--lc-accent:#1f6f5c;--lc-accent-hover:#1a5e4e;--lc-accent-active:#164f42;--lc-accent-text:#fff;--lc-accent-soft:#e4f0ec;--lc-accent-soft-text:#155446;--lc-ring:#1f6f5c66;--lc-radius-sm:4px;--lc-radius:6px;--lc-radius-lg:8px;--lc-border-width:1px;--lc-shadow-sm:none;--lc-shadow:0 1px 3px #0000000d;--lc-shadow-lg:0 6px 18px #00000012;--lc-shadow-hard:none;--lc-blur:none;--lc-leading-normal:1.7;--lc-leading-relaxed:1.85;--lc-font-display:Georgia, "Times New Roman", serif}[data-style=semantic-minimalist][data-theme=dark]{--lc-bg:#16150f;--lc-surface:#1d1c15;--lc-surface-2:#26241b;--lc-text:#ece9df;--lc-text-muted:#a7a394;--lc-text-faint:#777262;--lc-border:#2c2a20;--lc-border-strong:#3a3729;--lc-accent-soft:#163029}[data-style=glassmorphism]{--lc-bg:#0b1020;--lc-bg-gradient:radial-gradient(1200px 600px at 12% -10%, #6d28d9 0%, transparent 55%), radial-gradient(900px 500px at 100% 0%, #0ea5e9 0%, transparent 50%), radial-gradient(800px 600px at 50% 120%, #db2777 0%, transparent 55%);--lc-surface:#ffffff1a;--lc-surface-2:#ffffff29;--lc-text:#f4f6ff;--lc-text-muted:#c4cbe6;--lc-text-faint:#9aa2c4;--lc-border:#ffffff38;--lc-border-strong:#ffffff59;--lc-accent:#a78bfa;--lc-accent-hover:#b9a4fb;--lc-accent-active:#9170f7;--lc-accent-text:#13102a;--lc-accent-soft:#a78bfa38;--lc-accent-soft-text:#e3dbff;--lc-ring:#a78bfa80;--lc-success-soft:#22c55e33;--lc-warning-soft:#d9770638;--lc-danger-soft:#dc262638;--lc-info-soft:#0ea5e938;--lc-radius-sm:10px;--lc-radius:16px;--lc-radius-lg:22px;--lc-border-width:1px;--lc-shadow-sm:0 2px 8px #00000040;--lc-shadow:0 8px 32px #00000052;--lc-shadow-lg:0 20px 60px #0006;--lc-shadow-hard:none;--lc-blur:blur(14px) saturate(140%);--lc-glass-tint:#ffffff1a;--lc-glass-border:#ffffff47}[data-style=glassmorphism] body{background-image:var(--lc-bg-gradient);background-attachment:fixed}@supports not (backdrop-filter:blur(1px)){[data-style=glassmorphism]{--lc-surface:#1b2138;--lc-surface-2:#232a44;--lc-border:#ffffff2e;--lc-blur:none}}.btn{--_bg:var(--lc-surface);--_fg:var(--lc-text);--_bd:var(--lc-border-strong);justify-content:center;align-items:center;gap:var(--lc-space-2);font:inherit;font-weight:var(--lc-weight-medium);white-space:nowrap;cursor:pointer;color:var(--_fg);background:var(--_bg);border:var(--lc-border-width) solid var(--_bd);border-radius:var(--lc-radius);box-shadow:var(--lc-shadow-hard);transition:transform var(--lc-transition), background-color var(--lc-transition), border-color var(--lc-transition), box-shadow var(--lc-transition), color var(--lc-transition);user-select:none;padding-block:.62em;padding-inline:1.05em;line-height:1;text-decoration:none;display:inline-flex}.btn:hover{background:var(--lc-surface-2)}.btn:active{transform:translateY(1px)}.btn:disabled,.btn[aria-disabled=true]{opacity:.55;cursor:not-allowed;pointer-events:none}.btn-primary{--_bg:var(--lc-accent);--_fg:var(--lc-accent-text);--_bd:var(--lc-accent)}.btn-primary:hover{background:var(--lc-accent-hover);border-color:var(--lc-accent-hover)}.btn-secondary{--_bg:var(--lc-surface-2);--_fg:var(--lc-text);--_bd:var(--lc-border-strong)}.btn-outline{--_bg:transparent;--_fg:var(--lc-accent);--_bd:var(--lc-accent)}.btn-outline:hover{background:var(--lc-accent-soft)}.btn-ghost{--_bg:transparent;--_fg:var(--lc-text);--_bd:transparent;box-shadow:none}.btn-ghost:hover{background:var(--lc-surface-2)}.btn-soft{--_bg:var(--lc-accent-soft);--_fg:var(--lc-accent-soft-text);--_bd:transparent;box-shadow:none}.btn-link{--_bg:transparent;--_fg:var(--lc-accent);--_bd:transparent;box-shadow:none;padding-inline:.25em}.btn-link:hover{background:0 0;text-decoration:underline}.btn-danger{--_bg:var(--lc-danger);--_fg:#fff;--_bd:var(--lc-danger)}.btn-sm{font-size:var(--lc-text-sm);padding-block:.4em;padding-inline:.75em}.btn-lg{font-size:var(--lc-text-lg);padding-block:.78em;padding-inline:1.4em}.btn-block{inline-size:100%;display:flex}.btn-icon{aspect-ratio:1;padding:.55em}.btn-rounded{border-radius:var(--lc-radius-full)}.btn-group{display:inline-flex}.btn-group .btn{border-radius:0;margin-inline-start:calc(var(--lc-border-width) * -1)}.btn-group .btn:first-child{border-start-start-radius:var(--lc-radius);border-end-start-radius:var(--lc-radius);margin-inline-start:0}.btn-group .btn:last-child{border-start-end-radius:var(--lc-radius);border-end-end-radius:var(--lc-radius)}.card{background:var(--lc-surface);backdrop-filter:var(--lc-blur);border:var(--lc-border-width) solid var(--lc-border);border-radius:var(--lc-radius-lg);box-shadow:var(--lc-shadow);overflow:hidden}.card-body{padding:var(--lc-space-6)}.card-header{padding:var(--lc-space-4) var(--lc-space-6);border-block-end:var(--lc-border-width) solid var(--lc-border);font-weight:var(--lc-weight-semibold)}.card-footer{padding:var(--lc-space-4) var(--lc-space-6);border-block-start:var(--lc-border-width) solid var(--lc-border)}.card-title{font-size:var(--lc-text-lg);font-weight:var(--lc-weight-semibold);margin-block-end:var(--lc-space-1)}.card-text{color:var(--lc-text-muted);margin:0}.badge{font-size:var(--lc-text-xs);font-weight:var(--lc-weight-semibold);color:var(--lc-text);background:var(--lc-surface-2);border:var(--lc-border-width) solid var(--lc-border);border-radius:var(--lc-radius-sm);align-items:center;gap:.4em;padding:.4em .65em;line-height:1;display:inline-flex}.badge-pill{border-radius:var(--lc-radius-full)}.badge-primary{background:var(--lc-accent-soft);color:var(--lc-accent-soft-text);border-color:#0000}.badge-success{background:var(--lc-success-soft);color:var(--lc-success-text);border-color:#0000}.badge-warning{background:var(--lc-warning-soft);color:var(--lc-warning-text);border-color:#0000}.badge-danger{background:var(--lc-danger-soft);color:var(--lc-danger-text);border-color:#0000}.badge-info{background:var(--lc-info-soft);color:var(--lc-info-text);border-color:#0000}.badge-solid{background:var(--lc-accent);color:var(--lc-accent-text);border-color:#0000}.alert{gap:var(--lc-space-3);padding:var(--lc-space-4);background:var(--lc-surface);backdrop-filter:var(--lc-blur);border:var(--lc-border-width) solid var(--lc-border);border-radius:var(--lc-radius);border-inline-start-width:4px;align-items:flex-start;display:flex}.alert-title{font-weight:var(--lc-weight-semibold);margin-block-end:.15em}.alert-success{border-inline-start-color:var(--lc-success);background:var(--lc-success-soft)}.alert-warning{border-inline-start-color:var(--lc-warning);background:var(--lc-warning-soft)}.alert-danger{border-inline-start-color:var(--lc-danger);background:var(--lc-danger-soft)}.alert-info{border-inline-start-color:var(--lc-info);background:var(--lc-info-soft)}.field{margin-block-end:var(--lc-space-4)}.label{font-size:var(--lc-text-sm);font-weight:var(--lc-weight-medium);margin-block-end:var(--lc-space-2);display:inline-block}.help{font-size:var(--lc-text-sm);color:var(--lc-text-muted);margin-block-start:var(--lc-space-1);display:block}.error-text{font-size:var(--lc-text-sm);color:var(--lc-danger-text);margin-block-start:var(--lc-space-1);display:none}.input,.textarea,.select,input:where([type]:not([type=checkbox],[type=radio],[type=range],[type=file],[type=button],[type=submit])),textarea,select{inline-size:100%;color:var(--lc-text);background:var(--lc-surface);backdrop-filter:var(--lc-blur);border:var(--lc-border-width) solid var(--lc-border-strong);border-radius:var(--lc-radius);transition:border-color var(--lc-transition), box-shadow var(--lc-transition);appearance:none;padding-block:.6em;padding-inline:.8em}.textarea,textarea{resize:vertical;min-block-size:6em}.input::placeholder,textarea::placeholder{color:var(--lc-text-faint)}.input:focus,.textarea:focus,.select:focus,input:focus,textarea:focus,select:focus{border-color:var(--lc-accent);box-shadow:0 0 0 3px var(--lc-ring);outline:none}.input:disabled,textarea:disabled,select:disabled{background:var(--lc-surface-2);opacity:.7;cursor:not-allowed}.select,select{background-image:linear-gradient(45deg, transparent 50%, var(--lc-text-muted) 50%), linear-gradient(135deg, var(--lc-text-muted) 50%, transparent 50%);background-position:calc(100% - 18px),calc(100% - 13px);background-repeat:no-repeat;background-size:5px 5px,5px 5px;padding-inline-end:2.2em}[dir=rtl] .select,[dir=rtl] select{background-position:18px,13px;padding-inline:2.2em .8em}input[type=checkbox],input[type=radio]{block-size:1.1em;inline-size:1.1em;accent-color:var(--lc-accent);vertical-align:-2px;cursor:pointer;margin-inline-end:var(--lc-space-2)}.check{align-items:center;gap:var(--lc-space-2);margin-block-end:var(--lc-space-2);display:flex}.check label{cursor:pointer}.switch{cursor:pointer;align-items:center;gap:var(--lc-space-2);display:inline-flex;position:relative}.switch input{opacity:0;block-size:0;inline-size:0;position:absolute}.switch .track{border-radius:var(--lc-radius-full);background:var(--lc-border-strong);block-size:22px;inline-size:40px;transition:background var(--lc-transition);flex:none;position:relative}.switch .track:after{content:"";block-size:18px;inline-size:18px;transition:inset-inline-start var(--lc-transition);background:#fff;border-radius:50%;position:absolute;inset-block-start:2px;inset-inline-start:2px}.switch input:checked+.track{background:var(--lc-accent)}.switch input:checked+.track:after{inset-inline-start:20px}.switch input:focus-visible+.track{box-shadow:0 0 0 3px var(--lc-ring)}.file{display:inline-flex}input[type=file]{font-size:var(--lc-text-sm)}input[type=file]::file-selector-button{font:inherit;cursor:pointer;color:var(--lc-text);background:var(--lc-surface-2);border:var(--lc-border-width) solid var(--lc-border-strong);border-radius:var(--lc-radius);margin-inline-end:var(--lc-space-3);padding:.5em .9em}.input:user-invalid,.input.is-invalid,input:user-invalid,textarea:user-invalid,select:user-invalid,.is-invalid{border-color:var(--lc-danger)}.input:user-invalid:focus,.is-invalid:focus{box-shadow:0 0 0 3px var(--lc-danger-soft)}.input:user-valid,.is-valid,input:user-valid{border-color:var(--lc-success)}.field:has(:user-invalid) .error-text,.field.is-invalid .error-text{display:block}.field:has(:user-invalid) .help{display:none}.input-sm,.select-sm{font-size:var(--lc-text-sm);padding-block:.4em;padding-inline:.6em}.input-lg,.select-lg{font-size:var(--lc-text-lg);padding-block:.75em;padding-inline:1em}.input-group{align-items:stretch;inline-size:100%;display:flex}.input-group>.input,.input-group>.select,.input-group>input,.input-group>select{border-radius:0;flex:auto;inline-size:auto;min-inline-size:0}.input-group>:first-child{border-start-start-radius:var(--lc-radius);border-end-start-radius:var(--lc-radius)}.input-group>:last-child{border-start-end-radius:var(--lc-radius);border-end-end-radius:var(--lc-radius)}.input-group>*+*{margin-inline-start:calc(var(--lc-border-width) * -1)}.input-group .input-addon{white-space:nowrap;color:var(--lc-text-muted);background:var(--lc-surface-2);border:var(--lc-border-width) solid var(--lc-border-strong);align-items:center;padding-inline:.8em;display:inline-flex}.input-group .btn{border-radius:0}.input-group:focus-within>.input,.input-group:focus-within>input{border-color:var(--lc-accent)}.table{border-collapse:collapse;inline-size:100%;font-size:var(--lc-text-sm)}.table th,.table td{padding:var(--lc-space-3) var(--lc-space-4);text-align:start;border-block-end:var(--lc-border-width) solid var(--lc-border)}.table thead th{font-weight:var(--lc-weight-semibold);color:var(--lc-text-muted);border-block-end:2px solid var(--lc-border-strong);white-space:nowrap}.table-striped tbody tr:nth-child(2n),.table-hover tbody tr:hover{background:var(--lc-surface-2)}.table-bordered,.table-bordered th,.table-bordered td{border:var(--lc-border-width) solid var(--lc-border)}.table th[aria-sort]{cursor:pointer;user-select:none}.table th[aria-sort]:after{content:"↕";opacity:.35;margin-inline-start:.4em;font-size:.85em}.table th[aria-sort=ascending]:after{content:"↑";opacity:1}.table th[aria-sort=descending]:after{content:"↓";opacity:1}.table-wrap{border-radius:var(--lc-radius);overflow-x:auto}.avatar{--_s:40px;inline-size:var(--_s);block-size:var(--_s);border-radius:var(--lc-radius-full);background:var(--lc-accent-soft);color:var(--lc-accent-soft-text);font-weight:var(--lc-weight-semibold);border:var(--lc-border-width) solid var(--lc-border);flex:none;justify-content:center;align-items:center;display:inline-flex;overflow:hidden}.avatar img{object-fit:cover;block-size:100%;inline-size:100%}.avatar-sm{--_s:28px;font-size:var(--lc-text-xs)}.avatar-lg{--_s:56px;font-size:var(--lc-text-lg)}.avatar-group{display:inline-flex}.avatar-group .avatar{box-shadow:0 0 0 2px var(--lc-surface);margin-inline-start:-10px}.avatar-group .avatar:first-child{margin-inline-start:0}.progress{background:var(--lc-surface-2);border-radius:var(--lc-radius-full);block-size:8px;inline-size:100%;overflow:hidden}.progress>.bar{background:var(--lc-accent);border-radius:inherit;block-size:100%;transition:inline-size var(--lc-transition)}.spinner{vertical-align:-.2em;border:2px solid var(--lc-border-strong);border-block-start-color:var(--lc-accent);border-radius:50%;block-size:1.2em;inline-size:1.2em;animation:.7s linear infinite lc-spin;display:inline-block}@keyframes lc-spin{to{transform:rotate(360deg)}}.skeleton{background:linear-gradient(90deg, var(--lc-surface-2) 25%, var(--lc-border) 37%, var(--lc-surface-2) 63%);border-radius:var(--lc-radius-sm);background-size:400% 100%;block-size:1em;animation:1.4s infinite lc-sk}@keyframes lc-sk{0%{background-position:100% 0}to{background-position:-100% 0}}.stat{padding:var(--lc-space-4)}.stat-label{font-size:var(--lc-text-sm);color:var(--lc-text-muted)}.stat-value{font-size:var(--lc-text-3xl);font-weight:var(--lc-weight-bold);line-height:1.1}.list-group{border:var(--lc-border-width) solid var(--lc-border);border-radius:var(--lc-radius);overflow:hidden}.list-group>*{padding:var(--lc-space-3) var(--lc-space-4);border-block-end:var(--lc-border-width) solid var(--lc-border);background:var(--lc-surface);display:block}.list-group>:last-child{border-block-end:0}a.list-group-item:hover,.list-group-item.is-active{background:var(--lc-surface-2)}.breadcrumb{gap:var(--lc-space-2);font-size:var(--lc-text-sm);flex-wrap:wrap;margin:0;padding:0;list-style:none;display:flex}.breadcrumb li{align-items:center;gap:var(--lc-space-2);margin:0;display:flex}.breadcrumb li:not(:last-child):after{content:"/";color:var(--lc-text-faint)}[dir=rtl] .breadcrumb li:not(:last-child):after{content:"\\"}.breadcrumb a{color:var(--lc-text-muted)}.breadcrumb [aria-current]{color:var(--lc-text);font-weight:var(--lc-weight-medium)}.pagination{gap:var(--lc-space-1);margin:0;padding:0;list-style:none;display:flex}.pagination li{margin:0}.pagination a,.pagination button{border:var(--lc-border-width) solid var(--lc-border);border-radius:var(--lc-radius-sm);background:var(--lc-surface);block-size:2.2em;min-inline-size:2.2em;color:var(--lc-text);cursor:pointer;justify-content:center;align-items:center;padding-inline:.6em;text-decoration:none;display:inline-flex}.pagination a:hover{background:var(--lc-surface-2)}.pagination .is-active a,.pagination .is-active button{background:var(--lc-accent);color:var(--lc-accent-text);border-color:var(--lc-accent)}.navbar{align-items:center;gap:var(--lc-space-4);min-block-size:var(--lc-navbar-h);padding-inline:var(--lc-space-4);background:var(--lc-surface);backdrop-filter:var(--lc-blur);border-block-end:var(--lc-border-width) solid var(--lc-border);z-index:var(--lc-z-sticky);display:flex;position:sticky;inset-block-start:0}.navbar-brand{font-weight:var(--lc-weight-bold);font-size:var(--lc-text-lg);color:var(--lc-text);text-decoration:none}.navbar-nav{align-items:center;gap:var(--lc-space-2);margin-block:0;margin-inline-start:auto;padding:0;list-style:none;display:flex}.navbar-nav li{margin:0}.navbar-nav a{color:var(--lc-text-muted);border-radius:var(--lc-radius-sm);padding:.5em .75em;text-decoration:none}.navbar-nav a:hover,.navbar-nav a[aria-current]{color:var(--lc-text);background:var(--lc-surface-2)}.navbar-toggle{display:none}@media (width<=768px){.navbar-toggle{margin-inline-start:auto;display:inline-flex}.navbar-nav{display:none}.navbar:has(.navbar-toggle:checked) .navbar-nav,.navbar.is-open .navbar-nav{padding:var(--lc-space-2);background:var(--lc-surface);border-block-end:var(--lc-border-width) solid var(--lc-border);backdrop-filter:var(--lc-blur);flex-direction:column;align-items:stretch;display:flex;position:absolute;inset-block-start:var(--lc-navbar-h);inset-inline:0}}.tabs{border-block-end:var(--lc-border-width) solid var(--lc-border);gap:var(--lc-space-1);display:flex}.tabs button,.tabs .tab{font:inherit;cursor:pointer;color:var(--lc-text-muted);padding:var(--lc-space-3) var(--lc-space-4);background:0 0;border:0;border-block-end:2px solid #0000;margin-block-end:-1px}.tabs button:hover{color:var(--lc-text)}.tabs button[aria-selected=true],.tabs .tab.is-active{color:var(--lc-accent);border-block-end-color:var(--lc-accent);font-weight:var(--lc-weight-medium)}.tab-panel{padding-block:var(--lc-space-4)}.tab-panel[hidden]{display:none}.accordion{border:var(--lc-border-width) solid var(--lc-border);border-radius:var(--lc-radius);overflow:hidden}.accordion details{border-block-end:var(--lc-border-width) solid var(--lc-border)}.accordion details:last-child{border-block-end:0}.accordion summary{cursor:pointer;padding:var(--lc-space-3) var(--lc-space-4);font-weight:var(--lc-weight-medium);background:var(--lc-surface);justify-content:space-between;align-items:center;list-style:none;display:flex}.accordion summary::-webkit-details-marker{display:none}.accordion summary:after{content:"+";color:var(--lc-text-muted);font-size:1.2em;line-height:1}.accordion details[open] summary:after{content:"−"}.accordion .accordion-body{padding:0 var(--lc-space-4) var(--lc-space-4);color:var(--lc-text-muted)}.dropdown{display:inline-block;position:relative}.dropdown-menu{z-index:var(--lc-z-dropdown);min-inline-size:12rem;padding:var(--lc-space-1);background:var(--lc-surface);backdrop-filter:var(--lc-blur);border:var(--lc-border-width) solid var(--lc-border);border-radius:var(--lc-radius);box-shadow:var(--lc-shadow-lg);opacity:0;visibility:hidden;transition:all var(--lc-transition);position:absolute;inset-block-start:calc(100% + 6px);inset-inline-start:0;transform:translateY(-4px)}.dropdown.is-open>.dropdown-menu,.dropdown:has(>[aria-expanded=true])>.dropdown-menu{opacity:1;visibility:visible;transform:none}.dropdown-item{text-align:start;border-radius:var(--lc-radius-sm);inline-size:100%;color:var(--lc-text);cursor:pointer;font:inherit;background:0 0;border:0;padding:.5em .75em;text-decoration:none;display:block}.dropdown-item:hover{background:var(--lc-surface-2)}.dropdown-divider{block-size:var(--lc-border-width);background:var(--lc-border);margin:var(--lc-space-1) 0}.navbar .dropdown-menu,.dropdown-menu.dropdown-end{inset-inline:auto 0}[data-tip]{position:relative}[data-tip]:after{content:attr(data-tip);font-size:var(--lc-text-xs);white-space:nowrap;color:var(--lc-bg);background:var(--lc-text);border-radius:var(--lc-radius-sm);opacity:0;pointer-events:none;transition:all var(--lc-transition);z-index:var(--lc-z-tooltip);padding:.35em .6em;position:absolute;inset-block-end:calc(100% + 6px);inset-inline-start:50%;transform:translate(-50%)translateY(4px)}[dir=rtl] [data-tip]:after{transform:translate(50%)translateY(4px)}[data-tip]:hover:after,[data-tip]:focus-visible:after{opacity:1;transform:translate(-50%)translateY(0)}[dir=rtl] [data-tip]:hover:after{transform:translate(50%)translateY(0)}dialog.modal{inline-size:100%;max-inline-size:min(92vw,520px);color:var(--lc-text);background:0 0;border:0;margin:auto;padding:0}dialog.modal::backdrop{backdrop-filter:blur(2px);background:#080a128c}.modal-card{background:var(--lc-surface);backdrop-filter:var(--lc-blur);border:var(--lc-border-width) solid var(--lc-border);border-radius:var(--lc-radius-lg);box-shadow:var(--lc-shadow-lg);overflow:hidden}.modal-header{padding:var(--lc-space-4) var(--lc-space-6);border-block-end:var(--lc-border-width) solid var(--lc-border);font-weight:var(--lc-weight-semibold);justify-content:space-between;align-items:center;gap:var(--lc-space-4);display:flex}.modal-body{padding:var(--lc-space-6)}.modal-footer{padding:var(--lc-space-4) var(--lc-space-6);border-block-start:var(--lc-border-width) solid var(--lc-border);gap:var(--lc-space-2);justify-content:flex-end;display:flex}.toast-region{z-index:var(--lc-z-toast);gap:var(--lc-space-2);flex-direction:column;display:flex;position:fixed;inset-block-end:var(--lc-space-6);inset-inline-end:var(--lc-space-6)}.toast{align-items:flex-start;gap:var(--lc-space-3);min-inline-size:16rem;max-inline-size:24rem;padding:var(--lc-space-3) var(--lc-space-4);background:var(--lc-surface);backdrop-filter:var(--lc-blur);border:var(--lc-border-width) solid var(--lc-border);border-radius:var(--lc-radius);box-shadow:var(--lc-shadow-lg);animation:lc-toast-in var(--lc-transition);display:flex}@keyframes lc-toast-in{0%{opacity:0;transform:translateY(8px)}}.steps{gap:var(--lc-space-2);counter-reset:step;margin:0;padding:0;list-style:none;display:flex}.steps li{gap:var(--lc-space-2);text-align:center;font-size:var(--lc-text-sm);color:var(--lc-text-muted);flex-direction:column;flex:1;align-items:center;display:flex;position:relative}.steps li:before{counter-increment:step;content:counter(step);border:var(--lc-border-width) solid var(--lc-border-strong);background:var(--lc-surface);border-radius:50%;justify-content:center;align-items:center;block-size:2em;inline-size:2em;display:flex}.steps li.is-active:before,.steps li.is-done:before{background:var(--lc-accent);color:var(--lc-accent-text);border-color:var(--lc-accent)}.steps li.is-active{color:var(--lc-text);font-weight:var(--lc-weight-medium)}.sidebar{gap:var(--lc-space-1);inline-size:240px;padding:var(--lc-space-3);background:var(--lc-surface);backdrop-filter:var(--lc-blur);border-inline-end:var(--lc-border-width) solid var(--lc-border);flex-direction:column;flex:none;display:flex}.sidebar-title{font-size:var(--lc-text-xs);text-transform:uppercase;letter-spacing:.08em;color:var(--lc-text-faint);padding:var(--lc-space-2) var(--lc-space-3);margin-block-start:var(--lc-space-2)}.sidebar-link{align-items:center;gap:var(--lc-space-2);border-radius:var(--lc-radius-sm);color:var(--lc-text-muted);font-weight:var(--lc-weight-medium);padding:.55em .75em;text-decoration:none;display:flex}.sidebar-link:hover{background:var(--lc-surface-2);color:var(--lc-text)}.sidebar-link.is-active,.sidebar-link[aria-current]{background:var(--lc-accent-soft);color:var(--lc-accent-soft-text)}.drawer-overlay{z-index:var(--lc-z-modal);backdrop-filter:blur(1px);opacity:0;visibility:hidden;transition:opacity var(--lc-transition), visibility var(--lc-transition);background:#080a1280;position:fixed;inset:0}.drawer{z-index:calc(var(--lc-z-modal) + 1);background:var(--lc-surface);inline-size:min(86vw,320px);max-inline-size:100%;backdrop-filter:var(--lc-blur);border-inline-end:var(--lc-border-width) solid var(--lc-border);box-shadow:var(--lc-shadow-lg);transition:transform var(--lc-transition);flex-direction:column;display:flex;position:fixed;inset-block:0;inset-inline-start:0;transform:translate(-100%)}.drawer-end{border-inline:0;border-inline-start:var(--lc-border-width) solid var(--lc-border);inset-inline:auto 0;transform:translate(100%)}[dir=rtl] .drawer{transform:translate(100%)}[dir=rtl] .drawer-end{transform:translate(-100%)}.drawer.is-open{transform:none}.drawer.is-open~.drawer-overlay,.drawer-overlay.is-open{opacity:1;visibility:visible}.drawer-header{padding:var(--lc-space-4);border-block-end:var(--lc-border-width) solid var(--lc-border);justify-content:space-between;align-items:center;gap:var(--lc-space-3);font-weight:var(--lc-weight-semibold);display:flex}.drawer-body{padding:var(--lc-space-4);flex:1;overflow-y:auto}.popover{display:inline-block;position:relative}.popover-panel{z-index:var(--lc-z-dropdown);inline-size:max-content;max-inline-size:18rem;padding:var(--lc-space-4);background:var(--lc-surface);backdrop-filter:var(--lc-blur);border:var(--lc-border-width) solid var(--lc-border);border-radius:var(--lc-radius);box-shadow:var(--lc-shadow-lg);opacity:0;visibility:hidden;transition:all var(--lc-transition);position:absolute;inset-block-start:calc(100% + 8px);inset-inline-start:0;transform:translateY(-4px)}.popover.is-open>.popover-panel,.popover:has(>[aria-expanded=true])>.popover-panel{opacity:1;visibility:visible;transform:none}.popover-title{font-weight:var(--lc-weight-semibold);margin-block-end:var(--lc-space-1)}.popover-panel:before{content:"";background:var(--lc-surface);border-inline-start:var(--lc-border-width) solid var(--lc-border);border-block-start:var(--lc-border-width) solid var(--lc-border);block-size:9px;inline-size:9px;position:absolute;inset-block-start:-5px;inset-inline-start:16px;transform:rotate(45deg)}.carousel{position:relative}.carousel-track{gap:var(--lc-space-4);scroll-snap-type:x mandatory;scroll-behavior:smooth;scrollbar-width:thin;overscroll-behavior-inline:contain;padding-block-end:var(--lc-space-2);display:flex;overflow-x:auto}.carousel-slide{scroll-snap-align:start;border-radius:var(--lc-radius-lg);flex:0 0 100%}@media (width>=768px){.carousel-slide.is-third{flex-basis:calc((100% - var(--lc-space-4) * 2) / 3)}}.carousel-track::-webkit-scrollbar{block-size:8px}.carousel-track::-webkit-scrollbar-thumb{background:var(--lc-border-strong);border-radius:var(--lc-radius-full)}.carousel-btn{z-index:2;border-radius:var(--lc-radius-full);cursor:pointer;block-size:2.4em;inline-size:2.4em;color:var(--lc-text);background:var(--lc-surface);border:var(--lc-border-width) solid var(--lc-border);box-shadow:var(--lc-shadow);justify-content:center;align-items:center;padding:0;display:inline-flex;position:absolute;inset-block-start:50%;transform:translateY(-50%)}.carousel-btn:hover{background:var(--lc-surface-2)}.carousel-prev{inset-inline-start:calc(var(--lc-space-2) * -1)}.carousel-next{inset-inline-end:calc(var(--lc-space-2) * -1)}[dir=rtl] .carousel-prev,[dir=rtl] .carousel-next{transform:translateY(-50%)scaleX(-1)}.carousel-dots{gap:var(--lc-space-2);justify-content:center;margin-block-start:var(--lc-space-3);display:flex}.carousel-dots>*{background:var(--lc-border-strong);cursor:pointer;block-size:8px;inline-size:8px;transition:background var(--lc-transition);border:0;border-radius:50%;padding:0}.carousel-dots>.is-active{background:var(--lc-accent);border-radius:var(--lc-radius-full);inline-size:20px}.timeline{margin:0;padding:0;list-style:none;position:relative}.timeline>li{margin:0;padding-block-end:var(--lc-space-6);padding-inline-start:var(--lc-space-8);position:relative}.timeline>li:before{content:"";background:var(--lc-border);inline-size:2px;position:absolute;inset-block:.4em 0;inset-inline-start:7px}.timeline>li:last-child:before{display:none}.timeline>li:after{content:"";background:var(--lc-surface);border:3px solid var(--lc-accent);border-radius:50%;block-size:16px;inline-size:16px;position:absolute;inset-block-start:.35em;inset-inline-start:0}.timeline .timeline-time{font-size:var(--lc-text-sm);color:var(--lc-text-muted)}.timeline .timeline-title{font-weight:var(--lc-weight-semibold);margin-block:.1em .25em}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.hidden{display:none}.flex{display:flex}.inline-flex{display:inline-flex}.grid{display:grid}.inline-grid{display:inline-grid}.flex-row{flex-direction:row}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.flex-1{flex:1}.flex-auto{flex:auto}.flex-none{flex:none}.items-start{align-items:flex-start}.items-center{align-items:center}.items-end{align-items:flex-end}.items-stretch{align-items:stretch}.items-baseline{align-items:baseline}.justify-start{justify-content:flex-start}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.justify-between{justify-content:space-between}.justify-around{justify-content:space-around}.justify-evenly{justify-content:space-evenly}.self-start{align-self:flex-start}.self-center{align-self:center}.self-end{align-self:flex-end}.grid-cols-1{grid-template-columns:repeat(1,1fr)}.grid-cols-2{grid-template-columns:repeat(2,1fr)}.grid-cols-3{grid-template-columns:repeat(3,1fr)}.grid-cols-4{grid-template-columns:repeat(4,1fr)}.grid-cols-5{grid-template-columns:repeat(5,1fr)}.grid-cols-6{grid-template-columns:repeat(6,1fr)}.grid-cols-12{grid-template-columns:repeat(12,1fr)}.col-span-2{grid-column:span 2}.col-span-3{grid-column:span 3}.col-span-4{grid-column:span 4}.col-span-6{grid-column:span 6}.col-span-full{grid-column:1/-1}.gap-0{gap:0}.gap-1{gap:var(--lc-space-1)}.gap-2{gap:var(--lc-space-2)}.gap-3{gap:var(--lc-space-3)}.gap-4{gap:var(--lc-space-4)}.gap-6{gap:var(--lc-space-6)}.gap-8{gap:var(--lc-space-8)}.p-0{padding:0}.p-1{padding:var(--lc-space-1)}.p-2{padding:var(--lc-space-2)}.p-3{padding:var(--lc-space-3)}.p-4{padding:var(--lc-space-4)}.p-6{padding:var(--lc-space-6)}.p-8{padding:var(--lc-space-8)}.px-2{padding-inline:var(--lc-space-2)}.px-3{padding-inline:var(--lc-space-3)}.px-4{padding-inline:var(--lc-space-4)}.px-6{padding-inline:var(--lc-space-6)}.py-1{padding-block:var(--lc-space-1)}.py-2{padding-block:var(--lc-space-2)}.py-3{padding-block:var(--lc-space-3)}.py-4{padding-block:var(--lc-space-4)}.py-6{padding-block:var(--lc-space-6)}.pt-4{padding-block-start:var(--lc-space-4)}.pb-4{padding-block-end:var(--lc-space-4)}.m-0{margin:0}.m-auto{margin:auto}.m-1{margin:var(--lc-space-1)}.m-2{margin:var(--lc-space-2)}.m-4{margin:var(--lc-space-4)}.mx-auto{margin-inline:auto}.my-2{margin-block:var(--lc-space-2)}.my-4{margin-block:var(--lc-space-4)}.my-6{margin-block:var(--lc-space-6)}.mt-2{margin-block-start:var(--lc-space-2)}.mt-4{margin-block-start:var(--lc-space-4)}.mt-6{margin-block-start:var(--lc-space-6)}.mb-0{margin-block-end:0}.mb-2{margin-block-end:var(--lc-space-2)}.mb-4{margin-block-end:var(--lc-space-4)}.mb-6{margin-block-end:var(--lc-space-6)}.ms-auto{margin-inline-start:auto}.me-auto{margin-inline-end:auto}.w-full{inline-size:100%}.w-auto{inline-size:auto}.w-screen{inline-size:100vw}.w-fit{inline-size:fit-content}.h-full{block-size:100%}.h-screen{block-size:100vh}.min-h-screen{min-block-size:100vh}.max-w-xs{max-inline-size:20rem}.max-w-sm{max-inline-size:24rem}.max-w-md{max-inline-size:28rem}.max-w-lg{max-inline-size:32rem}.max-w-xl{max-inline-size:36rem}.max-w-2xl{max-inline-size:42rem}.max-w-7xl{max-inline-size:80rem}.text-xs{font-size:var(--lc-text-xs)}.text-sm{font-size:var(--lc-text-sm)}.text-base{font-size:var(--lc-text-base)}.text-lg{font-size:var(--lc-text-lg)}.text-xl{font-size:var(--lc-text-xl)}.text-2xl{font-size:var(--lc-text-2xl)}.text-3xl{font-size:var(--lc-text-3xl)}.font-light{font-weight:300}.font-normal{font-weight:var(--lc-weight-normal)}.font-medium{font-weight:var(--lc-weight-medium)}.font-semibold{font-weight:var(--lc-weight-semibold)}.font-bold{font-weight:var(--lc-weight-bold)}.text-start{text-align:start}.text-center{text-align:center}.text-end{text-align:end}.text-justify{text-align:justify}.leading-tight{line-height:var(--lc-leading-tight)}.leading-normal{line-height:var(--lc-leading-normal)}.leading-relaxed{line-height:var(--lc-leading-relaxed)}.tracking-tight{letter-spacing:-.02em}.tracking-wide{letter-spacing:.04em}.uppercase{text-transform:uppercase}.capitalize{text-transform:capitalize}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.font-mono{font-family:var(--lc-font-mono)}.text-primary{color:var(--lc-accent)}.text-muted{color:var(--lc-text-muted)}.text-faint{color:var(--lc-text-faint)}.text-success{color:var(--lc-success-text)}.text-danger{color:var(--lc-danger-text)}.text-warning{color:var(--lc-warning-text)}.bg-bg{background:var(--lc-bg)}.bg-surface{background:var(--lc-surface)}.bg-surface-2{background:var(--lc-surface-2)}.bg-primary{background:var(--lc-accent);color:var(--lc-accent-text)}.bg-soft{background:var(--lc-accent-soft);color:var(--lc-accent-soft-text)}.border{border:var(--lc-border-width) solid var(--lc-border)}.border-strong{border-color:var(--lc-border-strong)}.border-0{border:0}.border-t{border-block-start:var(--lc-border-width) solid var(--lc-border)}.border-b{border-block-end:var(--lc-border-width) solid var(--lc-border)}.rounded-none{border-radius:0}.rounded-sm{border-radius:var(--lc-radius-sm)}.rounded{border-radius:var(--lc-radius)}.rounded-lg{border-radius:var(--lc-radius-lg)}.rounded-full{border-radius:var(--lc-radius-full)}.shadow-none{box-shadow:none}.shadow-sm{box-shadow:var(--lc-shadow-sm)}.shadow{box-shadow:var(--lc-shadow)}.shadow-lg{box-shadow:var(--lc-shadow-lg)}.backdrop-blur{backdrop-filter:blur(8px)}.opacity-50{opacity:.5}.opacity-75{opacity:.75}.relative{position:relative}.absolute{position:absolute}.fixed{position:fixed}.sticky{position:sticky}.inset-0{inset:0}.top-0{inset-block-start:0}.bottom-0{inset-block-end:0}.start-0{inset-inline-start:0}.end-0{inset-inline-end:0}.z-10{z-index:10}.z-20{z-index:20}.z-30{z-index:30}.z-50{z-index:50}.overflow-hidden{overflow:hidden}.overflow-auto{overflow:auto}.overflow-x-auto{overflow-x:auto}.cursor-pointer{cursor:pointer}.cursor-default{cursor:default}.select-none{user-select:none}.transition{transition:all var(--lc-transition)}.sr-only{clip:rect(0, 0, 0, 0);white-space:nowrap;border:0;block-size:1px;inline-size:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.aspect-square{aspect-ratio:1}.aspect-video{aspect-ratio:16/9}.text-info{color:var(--lc-info-text)}.bg-success{background:var(--lc-success);color:#fff}.bg-warning{background:var(--lc-warning);color:#fff}.bg-danger{background:var(--lc-danger);color:#fff}.bg-info{background:var(--lc-info);color:#fff}.bg-success-soft{background:var(--lc-success-soft);color:var(--lc-success-text)}.bg-warning-soft{background:var(--lc-warning-soft);color:var(--lc-warning-text)}.bg-danger-soft{background:var(--lc-danger-soft);color:var(--lc-danger-text)}.bg-info-soft{background:var(--lc-info-soft);color:var(--lc-info-text)}.border-success{border-color:var(--lc-success)}.border-warning{border-color:var(--lc-warning)}.border-danger{border-color:var(--lc-danger)}.border-info{border-color:var(--lc-info)}.border-primary{border-color:var(--lc-accent)}.gap-5{gap:var(--lc-space-5)}.gap-10{gap:var(--lc-space-10)}.gap-12{gap:var(--lc-space-12)}.gap-x-2{column-gap:var(--lc-space-2)}.gap-x-4{column-gap:var(--lc-space-4)}.gap-x-6{column-gap:var(--lc-space-6)}.gap-y-2{row-gap:var(--lc-space-2)}.gap-y-4{row-gap:var(--lc-space-4)}.gap-y-6{row-gap:var(--lc-space-6)}.col-span-1{grid-column:span 1}.col-span-5{grid-column:span 5}.col-span-7{grid-column:span 7}.col-span-8{grid-column:span 8}.col-span-9{grid-column:span 9}.col-span-10{grid-column:span 10}.col-span-11{grid-column:span 11}.col-span-12{grid-column:span 12}@media (width>=640px){.sm\:block{display:block}.sm\:inline-block{display:inline-block}.sm\:flex{display:flex}.sm\:inline-flex{display:inline-flex}.sm\:grid{display:grid}.sm\:inline-grid{display:inline-grid}.sm\:hidden{display:none}.sm\:flex-row{flex-direction:row}.sm\:flex-col{flex-direction:column}.sm\:flex-wrap{flex-wrap:wrap}.sm\:items-start{align-items:flex-start}.sm\:items-center{align-items:center}.sm\:items-end{align-items:flex-end}.sm\:justify-start{justify-content:flex-start}.sm\:justify-center{justify-content:center}.sm\:justify-end{justify-content:flex-end}.sm\:justify-between{justify-content:space-between}.sm\:grid-cols-1{grid-template-columns:repeat(1,1fr)}.sm\:grid-cols-2{grid-template-columns:repeat(2,1fr)}.sm\:grid-cols-3{grid-template-columns:repeat(3,1fr)}.sm\:grid-cols-4{grid-template-columns:repeat(4,1fr)}.sm\:grid-cols-5{grid-template-columns:repeat(5,1fr)}.sm\:grid-cols-6{grid-template-columns:repeat(6,1fr)}.sm\:grid-cols-12{grid-template-columns:repeat(12,1fr)}.sm\:col-span-1{grid-column:span 1}.sm\:col-span-2{grid-column:span 2}.sm\:col-span-3{grid-column:span 3}.sm\:col-span-4{grid-column:span 4}.sm\:col-span-5{grid-column:span 5}.sm\:col-span-6{grid-column:span 6}.sm\:col-span-full{grid-column:1/-1}.sm\:gap-0{gap:0}.sm\:gap-1{gap:var(--lc-space-1)}.sm\:gap-2{gap:var(--lc-space-2)}.sm\:gap-3{gap:var(--lc-space-3)}.sm\:gap-4{gap:var(--lc-space-4)}.sm\:gap-5{gap:var(--lc-space-5)}.sm\:gap-6{gap:var(--lc-space-6)}.sm\:gap-8{gap:var(--lc-space-8)}.sm\:text-start{text-align:start}.sm\:text-center{text-align:center}.sm\:text-end{text-align:end}}@media (width>=768px){.md\:block{display:block}.md\:inline-block{display:inline-block}.md\:flex{display:flex}.md\:inline-flex{display:inline-flex}.md\:grid{display:grid}.md\:inline-grid{display:inline-grid}.md\:hidden{display:none}.md\:flex-row{flex-direction:row}.md\:flex-col{flex-direction:column}.md\:flex-wrap{flex-wrap:wrap}.md\:items-start{align-items:flex-start}.md\:items-center{align-items:center}.md\:items-end{align-items:flex-end}.md\:justify-start{justify-content:flex-start}.md\:justify-center{justify-content:center}.md\:justify-end{justify-content:flex-end}.md\:justify-between{justify-content:space-between}.md\:grid-cols-1{grid-template-columns:repeat(1,1fr)}.md\:grid-cols-2{grid-template-columns:repeat(2,1fr)}.md\:grid-cols-3{grid-template-columns:repeat(3,1fr)}.md\:grid-cols-4{grid-template-columns:repeat(4,1fr)}.md\:grid-cols-5{grid-template-columns:repeat(5,1fr)}.md\:grid-cols-6{grid-template-columns:repeat(6,1fr)}.md\:grid-cols-12{grid-template-columns:repeat(12,1fr)}.md\:col-span-1{grid-column:span 1}.md\:col-span-2{grid-column:span 2}.md\:col-span-3{grid-column:span 3}.md\:col-span-4{grid-column:span 4}.md\:col-span-5{grid-column:span 5}.md\:col-span-6{grid-column:span 6}.md\:col-span-full{grid-column:1/-1}.md\:gap-0{gap:0}.md\:gap-1{gap:var(--lc-space-1)}.md\:gap-2{gap:var(--lc-space-2)}.md\:gap-3{gap:var(--lc-space-3)}.md\:gap-4{gap:var(--lc-space-4)}.md\:gap-5{gap:var(--lc-space-5)}.md\:gap-6{gap:var(--lc-space-6)}.md\:gap-8{gap:var(--lc-space-8)}.md\:text-start{text-align:start}.md\:text-center{text-align:center}.md\:text-end{text-align:end}}@media (width>=1024px){.lg\:block{display:block}.lg\:inline-block{display:inline-block}.lg\:flex{display:flex}.lg\:inline-flex{display:inline-flex}.lg\:grid{display:grid}.lg\:inline-grid{display:inline-grid}.lg\:hidden{display:none}.lg\:flex-row{flex-direction:row}.lg\:flex-col{flex-direction:column}.lg\:flex-wrap{flex-wrap:wrap}.lg\:items-start{align-items:flex-start}.lg\:items-center{align-items:center}.lg\:items-end{align-items:flex-end}.lg\:justify-start{justify-content:flex-start}.lg\:justify-center{justify-content:center}.lg\:justify-end{justify-content:flex-end}.lg\:justify-between{justify-content:space-between}.lg\:grid-cols-1{grid-template-columns:repeat(1,1fr)}.lg\:grid-cols-2{grid-template-columns:repeat(2,1fr)}.lg\:grid-cols-3{grid-template-columns:repeat(3,1fr)}.lg\:grid-cols-4{grid-template-columns:repeat(4,1fr)}.lg\:grid-cols-5{grid-template-columns:repeat(5,1fr)}.lg\:grid-cols-6{grid-template-columns:repeat(6,1fr)}.lg\:grid-cols-12{grid-template-columns:repeat(12,1fr)}.lg\:col-span-1{grid-column:span 1}.lg\:col-span-2{grid-column:span 2}.lg\:col-span-3{grid-column:span 3}.lg\:col-span-4{grid-column:span 4}.lg\:col-span-5{grid-column:span 5}.lg\:col-span-6{grid-column:span 6}.lg\:col-span-full{grid-column:1/-1}.lg\:gap-0{gap:0}.lg\:gap-1{gap:var(--lc-space-1)}.lg\:gap-2{gap:var(--lc-space-2)}.lg\:gap-3{gap:var(--lc-space-3)}.lg\:gap-4{gap:var(--lc-space-4)}.lg\:gap-5{gap:var(--lc-space-5)}.lg\:gap-6{gap:var(--lc-space-6)}.lg\:gap-8{gap:var(--lc-space-8)}.lg\:text-start{text-align:start}.lg\:text-center{text-align:center}.lg\:text-end{text-align:end}}@media (width>=1280px){.xl\:block{display:block}.xl\:inline-block{display:inline-block}.xl\:flex{display:flex}.xl\:inline-flex{display:inline-flex}.xl\:grid{display:grid}.xl\:inline-grid{display:inline-grid}.xl\:hidden{display:none}.xl\:flex-row{flex-direction:row}.xl\:flex-col{flex-direction:column}.xl\:flex-wrap{flex-wrap:wrap}.xl\:items-start{align-items:flex-start}.xl\:items-center{align-items:center}.xl\:items-end{align-items:flex-end}.xl\:justify-start{justify-content:flex-start}.xl\:justify-center{justify-content:center}.xl\:justify-end{justify-content:flex-end}.xl\:justify-between{justify-content:space-between}.xl\:grid-cols-1{grid-template-columns:repeat(1,1fr)}.xl\:grid-cols-2{grid-template-columns:repeat(2,1fr)}.xl\:grid-cols-3{grid-template-columns:repeat(3,1fr)}.xl\:grid-cols-4{grid-template-columns:repeat(4,1fr)}.xl\:grid-cols-5{grid-template-columns:repeat(5,1fr)}.xl\:grid-cols-6{grid-template-columns:repeat(6,1fr)}.xl\:grid-cols-12{grid-template-columns:repeat(12,1fr)}.xl\:col-span-1{grid-column:span 1}.xl\:col-span-2{grid-column:span 2}.xl\:col-span-3{grid-column:span 3}.xl\:col-span-4{grid-column:span 4}.xl\:col-span-5{grid-column:span 5}.xl\:col-span-6{grid-column:span 6}.xl\:col-span-full{grid-column:1/-1}.xl\:gap-0{gap:0}.xl\:gap-1{gap:var(--lc-space-1)}.xl\:gap-2{gap:var(--lc-space-2)}.xl\:gap-3{gap:var(--lc-space-3)}.xl\:gap-4{gap:var(--lc-space-4)}.xl\:gap-5{gap:var(--lc-space-5)}.xl\:gap-6{gap:var(--lc-space-6)}.xl\:gap-8{gap:var(--lc-space-8)}.xl\:text-start{text-align:start}.xl\:text-center{text-align:center}.xl\:text-end{text-align:end}}.print-only{display:none}@media print{:root,html[data-style],html[data-theme]{--lc-bg:#fff;--lc-surface:#fff;--lc-surface-2:#fff;--lc-text:#000;--lc-text-muted:#333;--lc-text-faint:#555;--lc-border:#bbb;--lc-border-strong:#888;--lc-accent:#111;--lc-accent-hover:#000;--lc-accent-active:#000;--lc-accent-text:#fff;--lc-accent-soft:#eee;--lc-accent-soft-text:#000;--lc-success:#137a3a;--lc-danger:#b42318;--lc-warning:#8a6100;--lc-info:#0b5cad;--lc-success-soft:#fff;--lc-danger-soft:#fff;--lc-warning-soft:#fff;--lc-info-soft:#fff;--lc-success-text:#0f5c2c;--lc-danger-text:#8a1c14;--lc-warning-text:#6b4b00;--lc-info-text:#0a4a86;--lc-shadow-sm:none;--lc-shadow:none;--lc-shadow-lg:none;--lc-shadow-hard:none;--lc-blur:none;--lc-bg-gradient:none;--lc-ring:transparent}html,body{color:#000!important;background:#fff!important}*,:before,:after{box-shadow:none!important;text-shadow:none!important}.navbar,.sidebar{position:static!important}.navbar-toggle,.drawer,.drawer-overlay,dialog.modal,.toast-region,.tooltip,.popover,.dropdown-menu,.carousel-nav,.carousel-dots,.spinner,.skeleton,.no-print{display:none!important}.print-only{display:revert!important}.card,.alert,.table th,.table td{border:1px solid #ccc!important}thead{display:table-header-group}a{text-decoration:underline}a:not(.btn,.badge)[href^=http]:after{content:" (" attr(href) ")";color:#555;word-break:break-all;font-size:.85em}h1,h2,h3,h4{break-after:avoid}p,li,blockquote{orphans:3;widows:3}img,pre,blockquote,table,tr,.card,.alert{break-inside:avoid}} \ No newline at end of file diff --git a/package/package.json b/package/package.json deleted file mode 100644 index 0f7a218..0000000 --- a/package/package.json +++ /dev/null @@ -1,76 +0,0 @@ -{ - "name": "lombokcss", - "version": "0.1.4", - "description": "Token-first component CSS framework. One markup, five design styles (Corporate Flat, Resonant Stark, Neo-Brutalism, Semantic Minimalist, Glassmorphism), dark mode + RTL. ~9.7KB gzipped.", - "license": "MIT", - "author": "codinglombok", - "homepage": "https://github.com/codinglombok/lombokcss#readme", - "repository": { - "type": "git", - "url": "git+https://github.com/codinglombok/lombokcss.git" - }, - "bugs": { - "url": "https://github.com/codinglombok/lombokcss/issues" - }, - "type": "module", - "style": "dist/lombok.min.css", - "main": "dist/lombok.js", - "unpkg": "dist/lombok.min.css", - "jsdelivr": "dist/lombok.min.css", - "sideEffects": true, - "exports": { - ".": "./dist/lombok.js", - "./css": "./dist/lombok.min.css", - "./css-full": "./dist/lombok.css", - "./js": "./dist/lombok.js", - "./src/*": "./src/*", - "./package.json": "./package.json" - }, - "files": [ - "dist", - "src", - "README.md", - "LICENSE" - ], - "engines": { - "node": ">=18" - }, - "scripts": { - "build:css": "node scripts/build-css.mjs", - "build:js": "node -e \"require('node:fs').copyFileSync('src/lombok.js','dist/lombok.js')\"", - "build:docs": "python3 build_docs.py && cp dist/lombok.min.css docs/assets/lombok.min.css && cp dist/lombok.js docs/assets/lombok.js", - "build": "npm run build:css && npm run build:js", - "size": "echo \"CSS $(gzip -c dist/lombok.min.css | wc -c) B gzip | JS $(gzip -c dist/lombok.js | wc -c) B gzip\"", - "size:check": "node scripts/size-check.mjs", - "prepublishOnly": "npm run build", - "format": "prettier --write \"src/**/*.{css,js}\" \"scripts/**/*.mjs\" \"tests/**/*.js\" \"*.{json,md}\" \"*.config.js\"", - "format:check": "prettier --check \"src/**/*.{css,js}\" \"scripts/**/*.mjs\" \"tests/**/*.js\" \"*.{json,md}\" \"*.config.js\"", - "test:visual": "playwright test tests/visual.spec.js", - "test:visual:update": "playwright test tests/visual.spec.js --update-snapshots", - "lint": "npm run format:check", - "test": "npm run size:check && node scripts/ssr-check.mjs", - "format:fix": "prettier --write \"src/**/*.{css,js}\" \"scripts/**/*.mjs\" \"tests/**/*.js\" \"*.{json,md}\" \"*.config.js\"", - "test:behavior": "playwright test tests/behavior.spec.js" - }, - "devDependencies": { - "@playwright/test": "1.56.0", - "lightningcss": "1.33.0", - "prettier": "3.9.6" - }, - "keywords": [ - "css", - "framework", - "components", - "ui", - "design-tokens", - "theming", - "dark-mode", - "rtl", - "glassmorphism", - "neo-brutalism", - "utility-classes", - "classless", - "lightweight", - "design-system" - ] -} diff --git a/package/src/components.css b/package/src/components.css deleted file mode 100644 index 4b828c5..0000000 --- a/package/src/components.css +++ /dev/null @@ -1,1397 +0,0 @@ -/* ========================================================================== - LombokCSS — components.css - Semantic component classes. All read tokens only -> auto-restyle per theme. - Logical properties (inline/block) everywhere for RTL safety. - Glass-aware surfaces apply backdrop-filter:var(--lc-blur) (inert when none). - ========================================================================== */ - -/* ---------- BUTTON ---------- */ -.btn { - --_bg: var(--lc-surface); - --_fg: var(--lc-text); - --_bd: var(--lc-border-strong); - display: inline-flex; - align-items: center; - justify-content: center; - gap: var(--lc-space-2); - font: inherit; - font-weight: var(--lc-weight-medium); - line-height: 1; - text-decoration: none; - white-space: nowrap; - cursor: pointer; - padding-block: 0.62em; - padding-inline: 1.05em; - color: var(--_fg); - background: var(--_bg); - border: var(--lc-border-width) solid var(--_bd); - border-radius: var(--lc-radius); - box-shadow: var(--lc-shadow-hard); - transition: - transform var(--lc-transition), - background-color var(--lc-transition), - border-color var(--lc-transition), - box-shadow var(--lc-transition), - color var(--lc-transition); - user-select: none; -} -.btn:hover { - background: var(--lc-surface-2); -} -.btn:active { - transform: translateY(1px); -} -.btn:disabled, -.btn[aria-disabled="true"] { - opacity: 0.55; - cursor: not-allowed; - pointer-events: none; -} - -.btn-primary { - --_bg: var(--lc-accent); - --_fg: var(--lc-accent-text); - --_bd: var(--lc-accent); -} -.btn-primary:hover { - background: var(--lc-accent-hover); - border-color: var(--lc-accent-hover); -} -.btn-secondary { - --_bg: var(--lc-surface-2); - --_fg: var(--lc-text); - --_bd: var(--lc-border-strong); -} -.btn-outline { - --_bg: transparent; - --_fg: var(--lc-accent); - --_bd: var(--lc-accent); -} -.btn-outline:hover { - background: var(--lc-accent-soft); -} -.btn-ghost { - --_bg: transparent; - --_fg: var(--lc-text); - --_bd: transparent; - box-shadow: none; -} -.btn-ghost:hover { - background: var(--lc-surface-2); -} -.btn-soft { - --_bg: var(--lc-accent-soft); - --_fg: var(--lc-accent-soft-text); - --_bd: transparent; - box-shadow: none; -} -.btn-link { - --_bg: transparent; - --_fg: var(--lc-accent); - --_bd: transparent; - box-shadow: none; - padding-inline: 0.25em; -} -.btn-link:hover { - text-decoration: underline; - background: transparent; -} -.btn-danger { - --_bg: var(--lc-danger); - --_fg: #fff; - --_bd: var(--lc-danger); -} - -.btn-sm { - padding-block: 0.4em; - padding-inline: 0.75em; - font-size: var(--lc-text-sm); -} -.btn-lg { - padding-block: 0.78em; - padding-inline: 1.4em; - font-size: var(--lc-text-lg); -} -.btn-block { - display: flex; - inline-size: 100%; -} -.btn-icon { - padding: 0.55em; - aspect-ratio: 1; -} -.btn-rounded { - border-radius: var(--lc-radius-full); -} - -.btn-group { - display: inline-flex; -} -.btn-group .btn { - border-radius: 0; - margin-inline-start: calc(var(--lc-border-width) * -1); -} -.btn-group .btn:first-child { - border-start-start-radius: var(--lc-radius); - border-end-start-radius: var(--lc-radius); - margin-inline-start: 0; -} -.btn-group .btn:last-child { - border-start-end-radius: var(--lc-radius); - border-end-end-radius: var(--lc-radius); -} - -/* ---------- CARD ---------- */ -.card { - background: var(--lc-surface); - -webkit-backdrop-filter: var(--lc-blur); - backdrop-filter: var(--lc-blur); - border: var(--lc-border-width) solid var(--lc-border); - border-radius: var(--lc-radius-lg); - box-shadow: var(--lc-shadow); - overflow: hidden; -} -.card-body { - padding: var(--lc-space-6); -} -.card-header { - padding: var(--lc-space-4) var(--lc-space-6); - border-block-end: var(--lc-border-width) solid var(--lc-border); - font-weight: var(--lc-weight-semibold); -} -.card-footer { - padding: var(--lc-space-4) var(--lc-space-6); - border-block-start: var(--lc-border-width) solid var(--lc-border); -} -.card-title { - font-size: var(--lc-text-lg); - font-weight: var(--lc-weight-semibold); - margin-block-end: var(--lc-space-1); -} -.card-text { - color: var(--lc-text-muted); - margin: 0; -} - -/* ---------- BADGE / PILL ---------- */ -.badge { - display: inline-flex; - align-items: center; - gap: 0.4em; - font-size: var(--lc-text-xs); - font-weight: var(--lc-weight-semibold); - line-height: 1; - padding: 0.4em 0.65em; - color: var(--lc-text); - background: var(--lc-surface-2); - border: var(--lc-border-width) solid var(--lc-border); - border-radius: var(--lc-radius-sm); -} -.badge-pill { - border-radius: var(--lc-radius-full); -} -.badge-primary { - background: var(--lc-accent-soft); - color: var(--lc-accent-soft-text); - border-color: transparent; -} -.badge-success { - background: var(--lc-success-soft); - color: var(--lc-success-text); - border-color: transparent; -} -.badge-warning { - background: var(--lc-warning-soft); - color: var(--lc-warning-text); - border-color: transparent; -} -.badge-danger { - background: var(--lc-danger-soft); - color: var(--lc-danger-text); - border-color: transparent; -} -.badge-info { - background: var(--lc-info-soft); - color: var(--lc-info-text); - border-color: transparent; -} -.badge-solid { - background: var(--lc-accent); - color: var(--lc-accent-text); - border-color: transparent; -} - -/* ---------- ALERT ---------- */ -.alert { - display: flex; - gap: var(--lc-space-3); - align-items: flex-start; - padding: var(--lc-space-4); - background: var(--lc-surface); - -webkit-backdrop-filter: var(--lc-blur); - backdrop-filter: var(--lc-blur); - border: var(--lc-border-width) solid var(--lc-border); - border-inline-start-width: 4px; - border-radius: var(--lc-radius); -} -.alert-title { - font-weight: var(--lc-weight-semibold); - margin-block-end: 0.15em; -} -.alert-success { - border-inline-start-color: var(--lc-success); - background: var(--lc-success-soft); -} -.alert-warning { - border-inline-start-color: var(--lc-warning); - background: var(--lc-warning-soft); -} -.alert-danger { - border-inline-start-color: var(--lc-danger); - background: var(--lc-danger-soft); -} -.alert-info { - border-inline-start-color: var(--lc-info); - background: var(--lc-info-soft); -} - -/* ---------- FORM ---------- */ -.field { - margin-block-end: var(--lc-space-4); -} -.label { - display: inline-block; - font-size: var(--lc-text-sm); - font-weight: var(--lc-weight-medium); - margin-block-end: var(--lc-space-2); -} -.help { - display: block; - font-size: var(--lc-text-sm); - color: var(--lc-text-muted); - margin-block-start: var(--lc-space-1); -} -.error-text { - display: none; - font-size: var(--lc-text-sm); - color: var(--lc-danger-text); - margin-block-start: var(--lc-space-1); -} - -.input, -.textarea, -.select, -input:where( - [type]:not([type="checkbox"], [type="radio"], [type="range"], [type="file"], [type="button"], [type="submit"]) -), -textarea, -select { - inline-size: 100%; - padding-block: 0.6em; - padding-inline: 0.8em; - color: var(--lc-text); - background: var(--lc-surface); - -webkit-backdrop-filter: var(--lc-blur); - backdrop-filter: var(--lc-blur); - border: var(--lc-border-width) solid var(--lc-border-strong); - border-radius: var(--lc-radius); - transition: - border-color var(--lc-transition), - box-shadow var(--lc-transition); - appearance: none; -} -.textarea, -textarea { - min-block-size: 6em; - resize: vertical; -} -.input::placeholder, -textarea::placeholder { - color: var(--lc-text-faint); -} - -.input:focus, -.textarea:focus, -.select:focus, -input:focus, -textarea:focus, -select:focus { - outline: none; - border-color: var(--lc-accent); - box-shadow: 0 0 0 3px var(--lc-ring); -} -.input:disabled, -textarea:disabled, -select:disabled { - background: var(--lc-surface-2); - opacity: 0.7; - cursor: not-allowed; -} - -/* native select caret (logical-aware) */ -.select, -select { - background-image: - linear-gradient(45deg, transparent 50%, var(--lc-text-muted) 50%), - linear-gradient(135deg, var(--lc-text-muted) 50%, transparent 50%); - background-position: - calc(100% - 18px) center, - calc(100% - 13px) center; - background-size: - 5px 5px, - 5px 5px; - background-repeat: no-repeat; - padding-inline-end: 2.2em; -} -[dir="rtl"] .select, -[dir="rtl"] select { - background-position: - 18px center, - 13px center; - padding-inline: 2.2em 0.8em; -} - -/* checkbox / radio use accent-color for native theming */ -input[type="checkbox"], -input[type="radio"] { - inline-size: 1.1em; - block-size: 1.1em; - accent-color: var(--lc-accent); - margin-inline-end: var(--lc-space-2); - vertical-align: -2px; - cursor: pointer; -} -.check { - display: flex; - align-items: center; - gap: var(--lc-space-2); - margin-block-end: var(--lc-space-2); -} -.check label { - cursor: pointer; -} - -/* switch / toggle */ -.switch { - position: relative; - display: inline-flex; - align-items: center; - cursor: pointer; - gap: var(--lc-space-2); -} -.switch input { - position: absolute; - opacity: 0; - inline-size: 0; - block-size: 0; -} -.switch .track { - inline-size: 40px; - block-size: 22px; - border-radius: var(--lc-radius-full); - background: var(--lc-border-strong); - transition: background var(--lc-transition); - position: relative; - flex: none; -} -.switch .track::after { - content: ""; - position: absolute; - inset-block-start: 2px; - inset-inline-start: 2px; - inline-size: 18px; - block-size: 18px; - border-radius: 50%; - background: #fff; - transition: inset-inline-start var(--lc-transition); -} -.switch input:checked + .track { - background: var(--lc-accent); -} -.switch input:checked + .track::after { - inset-inline-start: 20px; -} -.switch input:focus-visible + .track { - box-shadow: 0 0 0 3px var(--lc-ring); -} - -/* file upload */ -.file { - display: inline-flex; -} -input[type="file"] { - font-size: var(--lc-text-sm); -} -input[type="file"]::file-selector-button { - font: inherit; - cursor: pointer; - margin-inline-end: var(--lc-space-3); - padding: 0.5em 0.9em; - color: var(--lc-text); - background: var(--lc-surface-2); - border: var(--lc-border-width) solid var(--lc-border-strong); - border-radius: var(--lc-radius); -} - -/* VALIDATION — works with native :user-invalid and a .is-invalid hook */ -.input:user-invalid, -.input.is-invalid, -input:user-invalid, -textarea:user-invalid, -select:user-invalid, -.is-invalid { - border-color: var(--lc-danger); -} -.input:user-invalid:focus, -.is-invalid:focus { - box-shadow: 0 0 0 3px var(--lc-danger-soft); -} -.input:user-valid, -.is-valid, -input:user-valid { - border-color: var(--lc-success); -} - -/* show error text when field is invalid (modern :has) */ -.field:has(:user-invalid) .error-text, -.field.is-invalid .error-text { - display: block; -} -.field:has(:user-invalid) .help { - display: none; -} - -/* input sizes */ -.input-sm, -.select-sm { - padding-block: 0.4em; - padding-inline: 0.6em; - font-size: var(--lc-text-sm); -} -.input-lg, -.select-lg { - padding-block: 0.75em; - padding-inline: 1em; - font-size: var(--lc-text-lg); -} - -/* input group: join an input with leading/trailing addons or buttons */ -.input-group { - display: flex; - align-items: stretch; - inline-size: 100%; -} -.input-group > .input, -.input-group > .select, -.input-group > input, -.input-group > select { - inline-size: auto; - flex: 1 1 auto; - min-inline-size: 0; - border-radius: 0; -} -.input-group > :first-child { - border-start-start-radius: var(--lc-radius); - border-end-start-radius: var(--lc-radius); -} -.input-group > :last-child { - border-start-end-radius: var(--lc-radius); - border-end-end-radius: var(--lc-radius); -} -.input-group > * + * { - margin-inline-start: calc(var(--lc-border-width) * -1); -} -.input-group .input-addon { - display: inline-flex; - align-items: center; - white-space: nowrap; - padding-inline: 0.8em; - color: var(--lc-text-muted); - background: var(--lc-surface-2); - border: var(--lc-border-width) solid var(--lc-border-strong); -} -.input-group .btn { - border-radius: 0; -} -.input-group:focus-within > .input, -.input-group:focus-within > input { - border-color: var(--lc-accent); -} - -/* ---------- TABLE ---------- */ -.table { - inline-size: 100%; - border-collapse: collapse; - font-size: var(--lc-text-sm); -} -.table th, -.table td { - padding: var(--lc-space-3) var(--lc-space-4); - text-align: start; - border-block-end: var(--lc-border-width) solid var(--lc-border); -} -.table thead th { - font-weight: var(--lc-weight-semibold); - color: var(--lc-text-muted); - border-block-end: 2px solid var(--lc-border-strong); - white-space: nowrap; -} -.table-striped tbody tr:nth-child(even) { - background: var(--lc-surface-2); -} -.table-hover tbody tr:hover { - background: var(--lc-surface-2); -} -.table-bordered, -.table-bordered th, -.table-bordered td { - border: var(--lc-border-width) solid var(--lc-border); -} -/* sortable header affordance */ -.table th[aria-sort] { - cursor: pointer; - user-select: none; -} -.table th[aria-sort]::after { - content: "↕"; - opacity: 0.35; - margin-inline-start: 0.4em; - font-size: 0.85em; -} -.table th[aria-sort="ascending"]::after { - content: "↑"; - opacity: 1; -} -.table th[aria-sort="descending"]::after { - content: "↓"; - opacity: 1; -} -.table-wrap { - overflow-x: auto; - border-radius: var(--lc-radius); -} - -/* ---------- AVATAR ---------- */ -.avatar { - --_s: 40px; - display: inline-flex; - align-items: center; - justify-content: center; - inline-size: var(--_s); - block-size: var(--_s); - border-radius: var(--lc-radius-full); - background: var(--lc-accent-soft); - color: var(--lc-accent-soft-text); - font-weight: var(--lc-weight-semibold); - overflow: hidden; - flex: none; - border: var(--lc-border-width) solid var(--lc-border); -} -.avatar img { - inline-size: 100%; - block-size: 100%; - object-fit: cover; -} -.avatar-sm { - --_s: 28px; - font-size: var(--lc-text-xs); -} -.avatar-lg { - --_s: 56px; - font-size: var(--lc-text-lg); -} -.avatar-group { - display: inline-flex; -} -.avatar-group .avatar { - margin-inline-start: -10px; - box-shadow: 0 0 0 2px var(--lc-surface); -} -.avatar-group .avatar:first-child { - margin-inline-start: 0; -} - -/* ---------- PROGRESS ---------- */ -.progress { - inline-size: 100%; - block-size: 8px; - background: var(--lc-surface-2); - border-radius: var(--lc-radius-full); - overflow: hidden; -} -.progress > .bar { - block-size: 100%; - background: var(--lc-accent); - border-radius: inherit; - transition: inline-size var(--lc-transition); -} - -/* ---------- SPINNER ---------- */ -.spinner { - display: inline-block; - inline-size: 1.2em; - block-size: 1.2em; - vertical-align: -0.2em; - border: 2px solid var(--lc-border-strong); - border-block-start-color: var(--lc-accent); - border-radius: 50%; - animation: lc-spin 0.7s linear infinite; -} -@keyframes lc-spin { - to { - transform: rotate(360deg); - } -} - -/* ---------- SKELETON ---------- */ -.skeleton { - background: linear-gradient(90deg, var(--lc-surface-2) 25%, var(--lc-border) 37%, var(--lc-surface-2) 63%); - background-size: 400% 100%; - animation: lc-sk 1.4s ease infinite; - border-radius: var(--lc-radius-sm); - block-size: 1em; -} -@keyframes lc-sk { - 0% { - background-position: 100% 0; - } - 100% { - background-position: -100% 0; - } -} - -/* ---------- STAT ---------- */ -.stat { - padding: var(--lc-space-4); -} -.stat-label { - font-size: var(--lc-text-sm); - color: var(--lc-text-muted); -} -.stat-value { - font-size: var(--lc-text-3xl); - font-weight: var(--lc-weight-bold); - line-height: 1.1; -} - -/* ---------- LIST GROUP ---------- */ -.list-group { - border: var(--lc-border-width) solid var(--lc-border); - border-radius: var(--lc-radius); - overflow: hidden; -} -.list-group > * { - display: block; - padding: var(--lc-space-3) var(--lc-space-4); - border-block-end: var(--lc-border-width) solid var(--lc-border); - background: var(--lc-surface); -} -.list-group > *:last-child { - border-block-end: 0; -} -a.list-group-item:hover, -.list-group-item.is-active { - background: var(--lc-surface-2); -} - -/* ---------- BREADCRUMB ---------- */ -.breadcrumb { - display: flex; - flex-wrap: wrap; - gap: var(--lc-space-2); - list-style: none; - padding: 0; - margin: 0; - font-size: var(--lc-text-sm); -} -.breadcrumb li { - display: flex; - align-items: center; - gap: var(--lc-space-2); - margin: 0; -} -.breadcrumb li:not(:last-child)::after { - content: "/"; - color: var(--lc-text-faint); -} -[dir="rtl"] .breadcrumb li:not(:last-child)::after { - content: "\\"; -} -.breadcrumb a { - color: var(--lc-text-muted); -} -.breadcrumb [aria-current] { - color: var(--lc-text); - font-weight: var(--lc-weight-medium); -} - -/* ---------- PAGINATION ---------- */ -.pagination { - display: flex; - gap: var(--lc-space-1); - list-style: none; - padding: 0; - margin: 0; -} -.pagination li { - margin: 0; -} -.pagination a, -.pagination button { - display: inline-flex; - align-items: center; - justify-content: center; - min-inline-size: 2.2em; - block-size: 2.2em; - padding-inline: 0.6em; - border: var(--lc-border-width) solid var(--lc-border); - border-radius: var(--lc-radius-sm); - background: var(--lc-surface); - color: var(--lc-text); - cursor: pointer; - text-decoration: none; -} -.pagination a:hover { - background: var(--lc-surface-2); -} -.pagination .is-active a, -.pagination .is-active button { - background: var(--lc-accent); - color: var(--lc-accent-text); - border-color: var(--lc-accent); -} - -/* ---------- NAVBAR ---------- */ -.navbar { - display: flex; - align-items: center; - gap: var(--lc-space-4); - min-block-size: var(--lc-navbar-h); - padding-inline: var(--lc-space-4); - background: var(--lc-surface); - -webkit-backdrop-filter: var(--lc-blur); - backdrop-filter: var(--lc-blur); - border-block-end: var(--lc-border-width) solid var(--lc-border); - position: sticky; - inset-block-start: 0; - z-index: var(--lc-z-sticky); -} -.navbar-brand { - font-weight: var(--lc-weight-bold); - font-size: var(--lc-text-lg); - color: var(--lc-text); - text-decoration: none; -} -.navbar-nav { - display: flex; - align-items: center; - gap: var(--lc-space-2); - margin-inline-start: auto; - list-style: none; - padding: 0; - margin-block: 0; -} -.navbar-nav li { - margin: 0; -} -.navbar-nav a { - color: var(--lc-text-muted); - padding: 0.5em 0.75em; - border-radius: var(--lc-radius-sm); - text-decoration: none; -} -.navbar-nav a:hover, -.navbar-nav a[aria-current] { - color: var(--lc-text); - background: var(--lc-surface-2); -} -.navbar-toggle { - display: none; -} -@media (max-width: 768px) { - .navbar-toggle { - display: inline-flex; - margin-inline-start: auto; - } - .navbar-nav { - display: none; - } - .navbar:has(.navbar-toggle:checked) .navbar-nav, - .navbar.is-open .navbar-nav { - display: flex; - position: absolute; - inset-block-start: var(--lc-navbar-h); - inset-inline: 0; - flex-direction: column; - align-items: stretch; - padding: var(--lc-space-2); - background: var(--lc-surface); - border-block-end: var(--lc-border-width) solid var(--lc-border); - -webkit-backdrop-filter: var(--lc-blur); - backdrop-filter: var(--lc-blur); - } -} - -/* ---------- TABS ---------- */ -.tabs { - border-block-end: var(--lc-border-width) solid var(--lc-border); - display: flex; - gap: var(--lc-space-1); -} -.tabs button, -.tabs .tab { - font: inherit; - cursor: pointer; - background: none; - border: 0; - color: var(--lc-text-muted); - padding: var(--lc-space-3) var(--lc-space-4); - border-block-end: 2px solid transparent; - margin-block-end: -1px; -} -.tabs button:hover { - color: var(--lc-text); -} -.tabs button[aria-selected="true"], -.tabs .tab.is-active { - color: var(--lc-accent); - border-block-end-color: var(--lc-accent); - font-weight: var(--lc-weight-medium); -} -.tab-panel { - padding-block: var(--lc-space-4); -} -.tab-panel[hidden] { - display: none; -} - -/* ---------- ACCORDION (native details/summary) ---------- */ -.accordion { - border: var(--lc-border-width) solid var(--lc-border); - border-radius: var(--lc-radius); - overflow: hidden; -} -.accordion details { - border-block-end: var(--lc-border-width) solid var(--lc-border); -} -.accordion details:last-child { - border-block-end: 0; -} -.accordion summary { - cursor: pointer; - padding: var(--lc-space-3) var(--lc-space-4); - font-weight: var(--lc-weight-medium); - list-style: none; - display: flex; - align-items: center; - justify-content: space-between; - background: var(--lc-surface); -} -.accordion summary::-webkit-details-marker { - display: none; -} -.accordion summary::after { - content: "+"; - color: var(--lc-text-muted); - font-size: 1.2em; - line-height: 1; -} -.accordion details[open] summary::after { - content: "\2212"; -} -.accordion .accordion-body { - padding: 0 var(--lc-space-4) var(--lc-space-4); - color: var(--lc-text-muted); -} - -/* ---------- DROPDOWN / MENU ---------- */ -.dropdown { - position: relative; - display: inline-block; -} -.dropdown-menu { - position: absolute; - inset-block-start: calc(100% + 6px); - inset-inline-start: 0; - z-index: var(--lc-z-dropdown); - min-inline-size: 12rem; - padding: var(--lc-space-1); - background: var(--lc-surface); - -webkit-backdrop-filter: var(--lc-blur); - backdrop-filter: var(--lc-blur); - border: var(--lc-border-width) solid var(--lc-border); - border-radius: var(--lc-radius); - box-shadow: var(--lc-shadow-lg); - opacity: 0; - visibility: hidden; - transform: translateY(-4px); - transition: all var(--lc-transition); -} -.dropdown.is-open > .dropdown-menu, -.dropdown:has(> [aria-expanded="true"]) > .dropdown-menu { - opacity: 1; - visibility: visible; - transform: none; -} -.dropdown-item { - display: block; - inline-size: 100%; - text-align: start; - padding: 0.5em 0.75em; - border-radius: var(--lc-radius-sm); - color: var(--lc-text); - background: none; - border: 0; - cursor: pointer; - font: inherit; - text-decoration: none; -} -.dropdown-item:hover { - background: var(--lc-surface-2); -} -.dropdown-divider { - block-size: var(--lc-border-width); - background: var(--lc-border); - margin: var(--lc-space-1) 0; -} -/* navbar dropdowns sit near the inline-end, so open toward start to avoid overflow */ -.navbar .dropdown-menu, -.dropdown-menu.dropdown-end { - inset-inline: auto 0; -} - -/* ---------- TOOLTIP (CSS-only via data-tip) ---------- */ -[data-tip] { - position: relative; -} -[data-tip]::after { - content: attr(data-tip); - position: absolute; - inset-block-end: calc(100% + 6px); - inset-inline-start: 50%; - transform: translateX(-50%) translateY(4px); - padding: 0.35em 0.6em; - font-size: var(--lc-text-xs); - white-space: nowrap; - color: var(--lc-bg); - background: var(--lc-text); - border-radius: var(--lc-radius-sm); - opacity: 0; - pointer-events: none; - transition: all var(--lc-transition); - z-index: var(--lc-z-tooltip); -} -[dir="rtl"] [data-tip]::after { - transform: translateX(50%) translateY(4px); -} -[data-tip]:hover::after, -[data-tip]:focus-visible::after { - opacity: 1; - transform: translateX(-50%) translateY(0); -} -[dir="rtl"] [data-tip]:hover::after { - transform: translateX(50%) translateY(0); -} - -/* ---------- MODAL / DIALOG (native ) ---------- */ -dialog.modal { - padding: 0; - border: 0; - background: transparent; - max-inline-size: min(92vw, 520px); - inline-size: 100%; - color: var(--lc-text); - margin: auto; -} -dialog.modal::backdrop { - background: rgba(8, 10, 18, 0.55); - backdrop-filter: blur(2px); -} -.modal-card { - background: var(--lc-surface); - -webkit-backdrop-filter: var(--lc-blur); - backdrop-filter: var(--lc-blur); - border: var(--lc-border-width) solid var(--lc-border); - border-radius: var(--lc-radius-lg); - box-shadow: var(--lc-shadow-lg); - overflow: hidden; -} -.modal-header { - padding: var(--lc-space-4) var(--lc-space-6); - border-block-end: var(--lc-border-width) solid var(--lc-border); - font-weight: var(--lc-weight-semibold); - display: flex; - justify-content: space-between; - align-items: center; - gap: var(--lc-space-4); -} -.modal-body { - padding: var(--lc-space-6); -} -.modal-footer { - padding: var(--lc-space-4) var(--lc-space-6); - border-block-start: var(--lc-border-width) solid var(--lc-border); - display: flex; - gap: var(--lc-space-2); - justify-content: flex-end; -} - -/* ---------- TOAST ---------- */ -.toast-region { - position: fixed; - inset-block-end: var(--lc-space-6); - inset-inline-end: var(--lc-space-6); - z-index: var(--lc-z-toast); - display: flex; - flex-direction: column; - gap: var(--lc-space-2); -} -.toast { - display: flex; - align-items: flex-start; - gap: var(--lc-space-3); - min-inline-size: 16rem; - max-inline-size: 24rem; - padding: var(--lc-space-3) var(--lc-space-4); - background: var(--lc-surface); - -webkit-backdrop-filter: var(--lc-blur); - backdrop-filter: var(--lc-blur); - border: var(--lc-border-width) solid var(--lc-border); - border-radius: var(--lc-radius); - box-shadow: var(--lc-shadow-lg); - animation: lc-toast-in var(--lc-transition); -} -@keyframes lc-toast-in { - from { - opacity: 0; - transform: translateY(8px); - } -} - -/* ---------- STEPS / STEPPER ---------- */ -.steps { - display: flex; - gap: var(--lc-space-2); - list-style: none; - padding: 0; - margin: 0; - counter-reset: step; -} -.steps li { - flex: 1; - display: flex; - flex-direction: column; - gap: var(--lc-space-2); - align-items: center; - text-align: center; - font-size: var(--lc-text-sm); - color: var(--lc-text-muted); - position: relative; -} -.steps li::before { - counter-increment: step; - content: counter(step); - display: flex; - align-items: center; - justify-content: center; - inline-size: 2em; - block-size: 2em; - border-radius: 50%; - border: var(--lc-border-width) solid var(--lc-border-strong); - background: var(--lc-surface); -} -.steps li.is-active::before, -.steps li.is-done::before { - background: var(--lc-accent); - color: var(--lc-accent-text); - border-color: var(--lc-accent); -} -.steps li.is-active { - color: var(--lc-text); - font-weight: var(--lc-weight-medium); -} - -/* ---------- SIDEBAR ---------- */ -.sidebar { - display: flex; - flex-direction: column; - gap: var(--lc-space-1); - inline-size: 240px; - flex: none; - padding: var(--lc-space-3); - background: var(--lc-surface); - -webkit-backdrop-filter: var(--lc-blur); - backdrop-filter: var(--lc-blur); - border-inline-end: var(--lc-border-width) solid var(--lc-border); -} -.sidebar-title { - font-size: var(--lc-text-xs); - text-transform: uppercase; - letter-spacing: 0.08em; - color: var(--lc-text-faint); - padding: var(--lc-space-2) var(--lc-space-3); - margin-block-start: var(--lc-space-2); -} -.sidebar-link { - display: flex; - align-items: center; - gap: var(--lc-space-2); - padding: 0.55em 0.75em; - border-radius: var(--lc-radius-sm); - color: var(--lc-text-muted); - text-decoration: none; - font-weight: var(--lc-weight-medium); -} -.sidebar-link:hover { - background: var(--lc-surface-2); - color: var(--lc-text); -} -.sidebar-link.is-active, -.sidebar-link[aria-current] { - background: var(--lc-accent-soft); - color: var(--lc-accent-soft-text); -} - -/* ---------- DRAWER / OFFCANVAS ---------- */ -.drawer-overlay { - position: fixed; - inset: 0; - z-index: var(--lc-z-modal); - background: rgba(8, 10, 18, 0.5); - backdrop-filter: blur(1px); - opacity: 0; - visibility: hidden; - transition: - opacity var(--lc-transition), - visibility var(--lc-transition); -} -.drawer { - position: fixed; - inset-block: 0; - inset-inline-start: 0; - z-index: calc(var(--lc-z-modal) + 1); - inline-size: min(86vw, 320px); - max-inline-size: 100%; - display: flex; - flex-direction: column; - background: var(--lc-surface); - -webkit-backdrop-filter: var(--lc-blur); - backdrop-filter: var(--lc-blur); - border-inline-end: var(--lc-border-width) solid var(--lc-border); - box-shadow: var(--lc-shadow-lg); - transform: translateX(-100%); - transition: transform var(--lc-transition); -} -.drawer-end { - inset-inline: auto 0; - border-inline: 0; - border-inline-start: var(--lc-border-width) solid var(--lc-border); - transform: translateX(100%); -} -[dir="rtl"] .drawer { - transform: translateX(100%); -} -[dir="rtl"] .drawer-end { - transform: translateX(-100%); -} -.drawer.is-open { - transform: none; -} -.drawer.is-open ~ .drawer-overlay, -.drawer-overlay.is-open { - opacity: 1; - visibility: visible; -} -.drawer-header { - padding: var(--lc-space-4); - border-block-end: var(--lc-border-width) solid var(--lc-border); - display: flex; - justify-content: space-between; - align-items: center; - gap: var(--lc-space-3); - font-weight: var(--lc-weight-semibold); -} -.drawer-body { - padding: var(--lc-space-4); - overflow-y: auto; - flex: 1; -} - -/* ---------- POPOVER ---------- */ -.popover { - position: relative; - display: inline-block; -} -.popover-panel { - position: absolute; - inset-block-start: calc(100% + 8px); - inset-inline-start: 0; - z-index: var(--lc-z-dropdown); - inline-size: max-content; - max-inline-size: 18rem; - padding: var(--lc-space-4); - background: var(--lc-surface); - -webkit-backdrop-filter: var(--lc-blur); - backdrop-filter: var(--lc-blur); - border: var(--lc-border-width) solid var(--lc-border); - border-radius: var(--lc-radius); - box-shadow: var(--lc-shadow-lg); - opacity: 0; - visibility: hidden; - transform: translateY(-4px); - transition: all var(--lc-transition); -} -.popover.is-open > .popover-panel, -.popover:has(> [aria-expanded="true"]) > .popover-panel { - opacity: 1; - visibility: visible; - transform: none; -} -.popover-title { - font-weight: var(--lc-weight-semibold); - margin-block-end: var(--lc-space-1); -} -.popover-panel::before { - content: ""; - position: absolute; - inset-block-start: -5px; - inset-inline-start: 16px; - inline-size: 9px; - block-size: 9px; - background: var(--lc-surface); - border-inline-start: var(--lc-border-width) solid var(--lc-border); - border-block-start: var(--lc-border-width) solid var(--lc-border); - transform: rotate(45deg); -} - -/* ---------- CAROUSEL / SLIDER (CSS scroll-snap + optional JS controls) ---------- */ -.carousel { - position: relative; -} -.carousel-track { - display: flex; - gap: var(--lc-space-4); - overflow-x: auto; - scroll-snap-type: x mandatory; - scroll-behavior: smooth; - padding-block-end: var(--lc-space-2); - scrollbar-width: thin; - overscroll-behavior-inline: contain; -} -.carousel-slide { - flex: 0 0 100%; - scroll-snap-align: start; - border-radius: var(--lc-radius-lg); -} -@media (min-width: 768px) { - .carousel-slide.is-third { - flex-basis: calc((100% - var(--lc-space-4) * 2) / 3); - } -} -.carousel-track::-webkit-scrollbar { - block-size: 8px; -} -.carousel-track::-webkit-scrollbar-thumb { - background: var(--lc-border-strong); - border-radius: var(--lc-radius-full); -} -.carousel-btn { - position: absolute; - inset-block-start: 50%; - transform: translateY(-50%); - z-index: 2; - inline-size: 2.4em; - block-size: 2.4em; - padding: 0; - display: inline-flex; - align-items: center; - justify-content: center; - border-radius: var(--lc-radius-full); - cursor: pointer; - color: var(--lc-text); - background: var(--lc-surface); - border: var(--lc-border-width) solid var(--lc-border); - box-shadow: var(--lc-shadow); -} -.carousel-btn:hover { - background: var(--lc-surface-2); -} -.carousel-prev { - inset-inline-start: calc(var(--lc-space-2) * -1); -} -.carousel-next { - inset-inline-end: calc(var(--lc-space-2) * -1); -} -[dir="rtl"] .carousel-prev { - transform: translateY(-50%) scaleX(-1); -} -[dir="rtl"] .carousel-next { - transform: translateY(-50%) scaleX(-1); -} -.carousel-dots { - display: flex; - gap: var(--lc-space-2); - justify-content: center; - margin-block-start: var(--lc-space-3); -} -.carousel-dots > * { - inline-size: 8px; - block-size: 8px; - border-radius: 50%; - background: var(--lc-border-strong); - border: 0; - padding: 0; - cursor: pointer; - transition: background var(--lc-transition); -} -.carousel-dots > .is-active { - background: var(--lc-accent); - inline-size: 20px; - border-radius: var(--lc-radius-full); -} - -/* ---------- TIMELINE ---------- */ -.timeline { - list-style: none; - padding: 0; - margin: 0; - position: relative; -} -.timeline > li { - position: relative; - padding-inline-start: var(--lc-space-8); - padding-block-end: var(--lc-space-6); - margin: 0; -} -.timeline > li::before { - /* line */ - content: ""; - position: absolute; - inset-block: 0.4em 0; - inset-inline-start: 7px; - inline-size: 2px; - background: var(--lc-border); -} -.timeline > li:last-child::before { - display: none; -} -.timeline > li::after { - /* dot */ - content: ""; - position: absolute; - inset-block-start: 0.35em; - inset-inline-start: 0; - inline-size: 16px; - block-size: 16px; - border-radius: 50%; - background: var(--lc-surface); - border: 3px solid var(--lc-accent); -} -.timeline .timeline-time { - font-size: var(--lc-text-sm); - color: var(--lc-text-muted); -} -.timeline .timeline-title { - font-weight: var(--lc-weight-semibold); - margin-block: 0.1em 0.25em; -} diff --git a/package/src/core.css b/package/src/core.css deleted file mode 100644 index 326c78a..0000000 --- a/package/src/core.css +++ /dev/null @@ -1,230 +0,0 @@ -/* ========================================================================== - LombokCSS — core.css - Reset/reboot + base element styling. Base styling doubles as CLASSLESS mode: - plain semantic HTML is readable with zero classes. - ========================================================================== */ - -*, -*::before, -*::after { - box-sizing: border-box; -} -* { - margin: 0; -} - -html { - -webkit-text-size-adjust: 100%; - -moz-tab-size: 4; - tab-size: 4; - scroll-behavior: smooth; -} -@media (prefers-reduced-motion: reduce) { - html { - scroll-behavior: auto; - } - *, - *::before, - *::after { - animation-duration: 0.001ms !important; - transition-duration: 0.001ms !important; - } -} - -body { - margin: 0; - font-family: var(--lc-font-sans); - font-size: var(--lc-text-base); - line-height: var(--lc-leading-normal); - letter-spacing: var(--lc-tracking); - color: var(--lc-text); - background-color: var(--lc-bg); - -webkit-font-smoothing: antialiased; - text-rendering: optimizeLegibility; - transition: - background-color var(--lc-transition), - color var(--lc-transition); -} - -img, -picture, -video, -canvas, -svg { - display: block; - max-inline-size: 100%; - height: auto; -} -input, -button, -textarea, -select { - font: inherit; - color: inherit; -} -p, -h1, -h2, -h3, -h4, -h5, -h6 { - overflow-wrap: break-word; -} - -/* ---- Typography (classless) ---- */ -h1, -h2, -h3, -h4, -h5, -h6 { - font-family: var(--lc-font-display); - line-height: var(--lc-leading-tight); - font-weight: var(--lc-weight-semibold); - margin-block: 0 var(--lc-space-3); - text-wrap: balance; -} -h1 { - font-size: var(--lc-text-3xl); -} -h2 { - font-size: var(--lc-text-2xl); -} -h3 { - font-size: var(--lc-text-xl); -} -h4 { - font-size: var(--lc-text-lg); -} -h5 { - font-size: var(--lc-text-base); -} -h6 { - font-size: var(--lc-text-sm); - text-transform: uppercase; - letter-spacing: 0.06em; - color: var(--lc-text-muted); -} - -p { - margin-block: 0 var(--lc-space-4); -} -.lead { - font-size: var(--lc-text-lg); - color: var(--lc-text-muted); -} -small, -.caption { - font-size: var(--lc-text-sm); - color: var(--lc-text-muted); -} - -a { - color: var(--lc-accent); - text-decoration: none; - text-underline-offset: 3px; - transition: color var(--lc-transition); -} -a:hover { - color: var(--lc-accent-hover); - text-decoration: underline; -} - -strong, -b { - font-weight: var(--lc-weight-semibold); -} - -ul, -ol { - margin-block: 0 var(--lc-space-4); - padding-inline-start: 1.4em; -} -li { - margin-block-end: var(--lc-space-1); -} - -blockquote { - margin-block: 0 var(--lc-space-4); - padding-inline-start: var(--lc-space-4); - border-inline-start: 3px solid var(--lc-border-strong); - color: var(--lc-text-muted); -} - -hr, -.divider { - border: 0; - border-block-start: var(--lc-border-width) solid var(--lc-border); - margin-block: var(--lc-space-6); -} -.divider-vertical { - border: 0; - border-inline-start: var(--lc-border-width) solid var(--lc-border); - block-size: 1.2em; - margin-inline: var(--lc-space-3); - display: inline-block; -} - -code, -kbd, -samp, -pre { - font-family: var(--lc-font-mono); - font-size: 0.9em; -} -code { - background: var(--lc-surface-2); - padding: 0.15em 0.4em; - border-radius: var(--lc-radius-sm); - border: var(--lc-border-width) solid var(--lc-border); -} -pre { - background: var(--lc-surface-2); - border: var(--lc-border-width) solid var(--lc-border); - border-radius: var(--lc-radius); - padding: var(--lc-space-4); - overflow: auto; - margin-block: 0 var(--lc-space-4); -} -pre code { - background: none; - border: 0; - padding: 0; -} - -.kbd, -kbd { - display: inline-block; - font-family: var(--lc-font-mono); - font-size: var(--lc-text-xs); - line-height: 1; - padding: 0.35em 0.5em; - color: var(--lc-text); - background: var(--lc-surface); - border: var(--lc-border-width) solid var(--lc-border-strong); - border-block-end-width: 2px; - border-radius: var(--lc-radius-sm); -} - -::selection { - background: var(--lc-accent); - color: var(--lc-accent-text); -} - -:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible { - outline: 2px solid var(--lc-accent); - outline-offset: 2px; - border-radius: var(--lc-radius-sm); -} - -/* ---- Container & section helpers ---- */ -.container { - inline-size: 100%; - max-inline-size: var(--lc-container); - margin-inline: auto; - padding-inline: var(--lc-space-4); -} -.section { - padding-block: var(--lc-space-12); -} diff --git a/package/src/lombok.js b/package/src/lombok.js deleted file mode 100644 index 983ce31..0000000 --- a/package/src/lombok.js +++ /dev/null @@ -1,244 +0,0 @@ -/* LombokCSS — lombok.js (optional, ~1.5KB). Zero dependencies. - Enhances: dropdowns, tabs, modals, toasts, table sort, navbar toggle. - Everything degrades gracefully if JS is off (details/dialog are native). */ -(function () { - "use strict"; - - /* Bail out where there is no DOM. The package sets "type": "module" and - points main/exports["."] here, so SSR frameworks (Next, Nuxt, Astro, - SvelteKit) evaluate this file on the server. Without this guard the - import throws ReferenceError: document is not defined. */ - if (typeof document === "undefined") return; - - var d = document; - - /* Collapse a container and tell assistive tech its trigger is closed. */ - function collapse(el, toggleSelector) { - el.classList.remove("is-open"); - var b = el.querySelector(toggleSelector); - if (b) b.setAttribute("aria-expanded", "false"); - } - - /* Dropdowns: toggle [data-dropdown] -> nearest .dropdown gets .is-open */ - d.addEventListener("click", function (e) { - var t = e.target.closest("[data-dropdown-toggle]"); - var open = d.querySelector(".dropdown.is-open"); - if (open && (!t || !open.contains(t))) collapse(open, "[data-dropdown-toggle]"); - if (t) { - e.preventDefault(); - var dd = t.closest(".dropdown"); - if (dd) { - dd.classList.toggle("is-open"); - t.setAttribute("aria-expanded", dd.classList.contains("is-open")); - } - } - }); - d.addEventListener("keydown", function (e) { - if (e.key === "Escape") { - var o = d.querySelector(".dropdown.is-open"); - if (o) collapse(o, "[data-dropdown-toggle]"); - } - }); - - /* Tabs: [role=tablist] with buttons whose aria-controls -> panel id */ - d.querySelectorAll('[role="tablist"]').forEach(function (list) { - var tabs = list.querySelectorAll('[role="tab"]'); - tabs.forEach(function (tab) { - tab.addEventListener("click", function () { - tabs.forEach(function (x) { - x.setAttribute("aria-selected", "false"); - var p = d.getElementById(x.getAttribute("aria-controls")); - if (p) p.hidden = true; - }); - tab.setAttribute("aria-selected", "true"); - var panel = d.getElementById(tab.getAttribute("aria-controls")); - if (panel) panel.hidden = false; - }); - }); - }); - - /* Modal: [data-modal-open="id"] / [data-modal-close]; uses native */ - d.addEventListener("click", function (e) { - var op = e.target.closest("[data-modal-open]"); - if (op) { - var m = d.getElementById(op.getAttribute("data-modal-open")); - if (m && m.showModal) m.showModal(); - } - var cl = e.target.closest("[data-modal-close]"); - if (cl) { - var dlg = cl.closest("dialog"); - if (dlg) dlg.close(); - } - }); - /* click on backdrop closes */ - d.querySelectorAll("dialog.modal").forEach(function (dlg) { - dlg.addEventListener("click", function (e) { - if (e.target === dlg) dlg.close(); - }); - }); - - /* Navbar toggle (.navbar-toggle button toggles .is-open on .navbar) */ - d.addEventListener("click", function (e) { - var b = e.target.closest(".navbar-toggle"); - if (b) { - var nav = b.closest(".navbar"); - if (nav) nav.classList.toggle("is-open"); - } - }); - - /* Drawer / Offcanvas: [data-drawer-open="id"] / [data-drawer-close] */ - function closeDrawer(dr) { - dr.classList.remove("is-open"); - var ov = d.getElementById(dr.id + "-overlay") || dr.nextElementSibling; - if (ov && ov.classList.contains("drawer-overlay")) ov.classList.remove("is-open"); - } - d.addEventListener("click", function (e) { - var op = e.target.closest("[data-drawer-open]"); - if (op) { - var dr = d.getElementById(op.getAttribute("data-drawer-open")); - if (dr) { - dr.classList.add("is-open"); - var ov = d.getElementById(dr.id + "-overlay") || dr.nextElementSibling; - if (ov && ov.classList.contains("drawer-overlay")) ov.classList.add("is-open"); - } - } - var cl = e.target.closest("[data-drawer-close], .drawer-overlay"); - if (cl) { - var open = d.querySelector(".drawer.is-open"); - if (open) closeDrawer(open); - } - }); - - /* Popover: [data-popover-toggle] -> nearest .popover gets .is-open */ - d.addEventListener("click", function (e) { - var t = e.target.closest("[data-popover-toggle]"); - var open = d.querySelector(".popover.is-open"); - if (open && (!t || !open.contains(t))) collapse(open, "[data-popover-toggle]"); - if (t) { - e.preventDefault(); - var pop = t.closest(".popover"); - if (pop) { - pop.classList.toggle("is-open"); - t.setAttribute("aria-expanded", pop.classList.contains("is-open")); - } - } - }); - d.addEventListener("keydown", function (e) { - if (e.key === "Escape") { - var dr = d.querySelector(".drawer.is-open"); - if (dr) closeDrawer(dr); - var po = d.querySelector(".popover.is-open"); - if (po) collapse(po, "[data-popover-toggle]"); - } - }); - - /* Toast API: Lombok.toast("msg", {variant:"success", timeout:3000}) */ - window.Lombok = window.Lombok || {}; - window.Lombok.toast = function (msg, opts) { - opts = opts || {}; - var region = d.querySelector(".toast-region"); - if (!region) { - region = d.createElement("div"); - region.className = "toast-region"; - region.setAttribute("aria-live", "polite"); - d.body.appendChild(region); - } - var el = d.createElement("div"); - el.className = "toast" + (opts.variant ? " alert-" + opts.variant : ""); - el.setAttribute("role", "status"); - el.textContent = msg; - region.appendChild(el); - setTimeout(function () { - el.remove(); - }, opts.timeout || 3500); - return el; - }; - - /* Carousel: prev/next buttons + dots; scroll by one slide width */ - d.querySelectorAll(".carousel").forEach(function (c) { - var track = c.querySelector(".carousel-track"); - if (!track) return; - function step() { - var slide = track.querySelector(".carousel-slide"); - var gap = - parseFloat(getComputedStyle(track).columnGap || getComputedStyle(track).gap || 16) || 16; - return slide ? slide.getBoundingClientRect().width + gap : track.clientWidth; - } - function last() { - var n = track.querySelectorAll(".carousel-slide").length; - return n ? n - 1 : Math.round((track.scrollWidth - track.clientWidth) / step()); - } - var dir = d.documentElement.getAttribute("dir") === "rtl" ? -1 : 1; - /* Move to a tracked target index, never by a delta. scrollBy is relative to - wherever an in-flight smooth scroll currently is, so two quick clicks used - to advance from mid-animation and leave the track between slides. */ - var index = 0; - var settle; - function go(i) { - /* A re-sync armed by the previous animation must not land on top of the - target we are about to set; the events this scroll emits will arm a - fresh one. Without this, a click arriving between the end of one - animation and its 120ms re-sync moves from the stale index. */ - clearTimeout(settle); - index = Math.max(0, Math.min(i, last())); - track.scrollTo({ left: step() * index * dir, behavior: "smooth" }); - } - var prev = c.querySelector(".carousel-prev"), - next = c.querySelector(".carousel-next"); - if (prev) - prev.addEventListener("click", function () { - go(index - 1); - }); - if (next) - next.addEventListener("click", function () { - go(index + 1); - }); - var dots = c.querySelectorAll(".carousel-dots > *"); - dots.forEach(function (dot, i) { - dot.addEventListener("click", function () { - go(i); - }); - }); - track.addEventListener( - "scroll", - function () { - var idx = Math.round(Math.abs(track.scrollLeft) / step()); - dots.forEach(function (x, i) { - x.classList.toggle("is-active", i === idx); - }); - /* Re-sync the target after a drag or swipe, once the track stops. */ - clearTimeout(settle); - settle = setTimeout(function () { - index = Math.max(0, Math.min(idx, last())); - }, 120); - }, - { passive: true }, - ); - }); - - /* Table sort: click sorts its column (string/number aware) */ - d.querySelectorAll("table.table thead th[aria-sort]").forEach(function (th) { - th.addEventListener("click", function () { - var table = th.closest("table"), - tbody = table.tBodies[0]; - var idx = Array.prototype.indexOf.call(th.parentNode.children, th); - var asc = th.getAttribute("aria-sort") !== "ascending"; - th.parentNode.querySelectorAll("th[aria-sort]").forEach(function (o) { - o.setAttribute("aria-sort", "none"); - }); - th.setAttribute("aria-sort", asc ? "ascending" : "descending"); - var rows = Array.prototype.slice.call(tbody.rows); - rows.sort(function (a, b) { - var x = a.cells[idx].textContent.trim(), - y = b.cells[idx].textContent.trim(); - var nx = parseFloat(x), - ny = parseFloat(y); - var r = !isNaN(nx) && !isNaN(ny) ? nx - ny : x.localeCompare(y); - return asc ? r : -r; - }); - rows.forEach(function (r) { - tbody.appendChild(r); - }); - }); - }); -})(); diff --git a/package/src/print.css b/package/src/print.css deleted file mode 100644 index 3451283..0000000 --- a/package/src/print.css +++ /dev/null @@ -1,137 +0,0 @@ -/* ============================================================ - Print styles - Token-first: remap tokens to ink-friendly, high-contrast values - (overriding any data-style / data-theme), then tidy the chrome so - pages and PDFs are always legible. Utilities: .no-print, .print-only. - ============================================================ */ - -.print-only { - display: none; -} - -@media print { - /* Force a light, high-contrast palette regardless of the active style/theme. - html[data-style]/html[data-theme] (0,1,1) outrank the [data-style] blocks. */ - :root, - html[data-style], - html[data-theme] { - --lc-bg: #fff; - --lc-surface: #fff; - --lc-surface-2: #fff; - --lc-text: #000; - --lc-text-muted: #333; - --lc-text-faint: #555; - --lc-border: #bbb; - --lc-border-strong: #888; - --lc-accent: #111; - --lc-accent-hover: #000; - --lc-accent-active: #000; - --lc-accent-text: #fff; - --lc-accent-soft: #eee; - --lc-accent-soft-text: #000; - --lc-success: #137a3a; - --lc-danger: #b42318; - --lc-warning: #8a6100; - --lc-info: #0b5cad; - --lc-success-soft: #fff; - --lc-danger-soft: #fff; - --lc-warning-soft: #fff; - --lc-info-soft: #fff; - --lc-success-text: #0f5c2c; - --lc-danger-text: #8a1c14; - --lc-warning-text: #6b4b00; - --lc-info-text: #0a4a86; - --lc-shadow-sm: none; - --lc-shadow: none; - --lc-shadow-lg: none; - --lc-shadow-hard: none; - --lc-blur: none; - --lc-bg-gradient: none; - --lc-ring: transparent; - } - - html, - body { - background: #fff !important; - color: #000 !important; - } - *, - *::before, - *::after { - box-shadow: none !important; - text-shadow: none !important; - } - - /* Let content flow: no sticky/fixed chrome on paper */ - .navbar, - .sidebar { - position: static !important; - } - - /* Hide purely interactive or decorative chrome */ - .navbar-toggle, - .drawer, - .drawer-overlay, - dialog.modal, - .toast-region, - .tooltip, - .popover, - .dropdown-menu, - .carousel-nav, - .carousel-dots, - .spinner, - .skeleton, - .no-print { - display: none !important; - } - .print-only { - display: revert !important; - } - - /* Keep structure readable in ink */ - .card, - .alert { - border: 1px solid #ccc !important; - } - .table th, - .table td { - border: 1px solid #ccc !important; - } - thead { - display: table-header-group; - } - - /* Reveal link targets (skip buttons/badges) */ - a { - text-decoration: underline; - } - a:not(.btn, .badge)[href^="http"]::after { - content: " (" attr(href) ")"; - font-size: 0.85em; - color: #555; - word-break: break-all; - } - - /* Page-break hygiene */ - h1, - h2, - h3, - h4 { - break-after: avoid; - } - p, - li, - blockquote { - orphans: 3; - widows: 3; - } - img, - pre, - blockquote, - table, - tr, - .card, - .alert { - break-inside: avoid; - } -} diff --git a/package/src/themes.css b/package/src/themes.css deleted file mode 100644 index 3537da3..0000000 --- a/package/src/themes.css +++ /dev/null @@ -1,236 +0,0 @@ -/* ========================================================================== - LombokCSS — themes.css - Design-trend presets. Switch with data-style="..." on or . - Each preset ONLY re-maps tokens; component structure never changes. - Works alongside data-theme="dark|light". - ========================================================================== */ - -/* -------------------------------------------------------------------------- - 1) modern-corporate-flat (also the :root default) - Clean, flat, neutral + one brand color, medium radius, soft shadow. - Colors are inherited from :root / dark overlay, so we only confirm look. - -------------------------------------------------------------------------- */ -[data-style="modern-corporate-flat"] { - --lc-accent: #3b82f6; - --lc-accent-hover: #2f6fe0; - --lc-accent-active: #2861c9; - --lc-radius-sm: 6px; - --lc-radius: 10px; - --lc-radius-lg: 16px; - --lc-border-width: 1px; - --lc-shadow-sm: 0 1px 2px rgba(16, 24, 40, 0.06); - --lc-shadow: 0 4px 12px rgba(16, 24, 40, 0.08); - --lc-shadow-lg: 0 12px 32px rgba(16, 24, 40, 0.12); - --lc-shadow-hard: none; - --lc-blur: none; -} - -/* -------------------------------------------------------------------------- - 2) resonant-stark (Linear-style) — intrinsically dark, high contrast. - -------------------------------------------------------------------------- */ -[data-style="resonant-stark"] { - --lc-bg: #08090c; - --lc-surface: #101218; - --lc-surface-2: #171a22; - --lc-text: #f3f5f8; - --lc-text-muted: #a3acba; - --lc-text-faint: #6c7585; - --lc-border: #23262f; - --lc-border-strong: #333845; - --lc-accent: #7c6cff; - --lc-accent-hover: #8d7fff; - --lc-accent-active: #6b5af0; - --lc-accent-text: #ffffff; - --lc-accent-soft: #1b1830; - --lc-accent-soft-text: #bcb2ff; - --lc-ring: rgba(124, 108, 255, 0.5); - /* dark-appropriate status colors (soft backgrounds + readable text) */ - --lc-success-soft: #11271b; - --lc-success-text: #6ee7a0; - --lc-warning-soft: #2a1f0d; - --lc-warning-text: #fbbf24; - --lc-danger-soft: #2a1414; - --lc-danger-text: #fca5a5; - --lc-info-soft: #0c2530; - --lc-info-text: #67d3f7; - --lc-radius-sm: 5px; - --lc-radius: 7px; - --lc-radius-lg: 11px; - --lc-border-width: 1px; - --lc-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.5); - --lc-shadow: 0 2px 10px rgba(0, 0, 0, 0.55); - --lc-shadow-lg: 0 10px 36px rgba(0, 0, 0, 0.65); - --lc-shadow-hard: none; - --lc-blur: none; - --lc-tracking: -0.01em; - --lc-font-display: var(--lc-font-sans); - --lc-weight-semibold: 600; -} - -/* -------------------------------------------------------------------------- - 3) neo-brutalism — thick black borders, hard offset shadow, bold blocks. - -------------------------------------------------------------------------- */ -[data-style="neo-brutalism"] { - --lc-bg: #fdf6e3; - --lc-surface: #ffffff; - --lc-surface-2: #fff3c4; - --lc-text: #0a0a0a; - --lc-text-muted: #33312b; - --lc-text-faint: #6b6760; - --lc-border: #0a0a0a; - --lc-border-strong: #0a0a0a; - --lc-accent: #ff4f00; - --lc-accent-hover: #e84700; - --lc-accent-active: #cc3f00; - --lc-accent-text: #ffffff; - --lc-accent-soft: #ffe1cc; - --lc-accent-soft-text: #0a0a0a; - --lc-ring: rgba(10, 10, 10, 0.9); - --lc-success: #1f9e4d; - --lc-warning: #e0a400; - --lc-danger: #e3342f; - --lc-info: #2563eb; - --lc-success-soft: #d9f5e2; - --lc-warning-soft: #fff0c4; - --lc-danger-soft: #ffd9d7; - --lc-info-soft: #d7e3ff; - --lc-radius-sm: 0px; - --lc-radius: 0px; - --lc-radius-lg: 0px; - --lc-border-width: 2.5px; - --lc-shadow-sm: 3px 3px 0 #0a0a0a; - --lc-shadow: 5px 5px 0 #0a0a0a; - --lc-shadow-lg: 8px 8px 0 #0a0a0a; - --lc-shadow-hard: 5px 5px 0 #0a0a0a; - --lc-blur: none; - --lc-weight-medium: 700; - --lc-weight-semibold: 800; - --lc-weight-bold: 900; -} -[data-style="neo-brutalism"][data-theme="dark"] { - --lc-bg: #16140f; - --lc-surface: #1f1c14; - --lc-surface-2: #2a2517; - --lc-text: #fdf6e3; - --lc-text-muted: #cfc7ad; - --lc-text-faint: #8f8a72; - --lc-border: #fdf6e3; - --lc-border-strong: #fdf6e3; - --lc-shadow-sm: 3px 3px 0 #fdf6e3; - --lc-shadow: 5px 5px 0 #fdf6e3; - --lc-shadow-lg: 8px 8px 0 #fdf6e3; - --lc-shadow-hard: 5px 5px 0 #fdf6e3; - --lc-accent-soft: #3a2a1c; - --lc-accent-soft-text: #fdf6e3; - /* The light block above sets these; without dark values they win by source - order over the dark defaults in variables.css and leave pale panels under - light text. Dropped by 5f39ab5, restored here. */ - --lc-success-soft: #11271b; - --lc-success-text: #6ee7a0; - --lc-warning-soft: #2a1f0d; - --lc-warning-text: #fbbf24; - --lc-danger-soft: #2a1414; - --lc-danger-text: #fca5a5; - --lc-info-soft: #0c2530; - --lc-info-text: #67d3f7; -} - -/* -------------------------------------------------------------------------- - 4) semantic-minimalist — minimal, neutral, generous spacing, readable. - -------------------------------------------------------------------------- */ -[data-style="semantic-minimalist"] { - --lc-bg: #fbfbfa; - --lc-surface: #ffffff; - --lc-surface-2: #f4f4f2; - --lc-text: #23211e; - --lc-text-muted: #6a665f; - --lc-text-faint: #9a958c; - --lc-border: #e8e6e1; - --lc-border-strong: #d4d1c9; - --lc-accent: #1f6f5c; - --lc-accent-hover: #1a5e4e; - --lc-accent-active: #164f42; - --lc-accent-text: #ffffff; - --lc-accent-soft: #e4f0ec; - --lc-accent-soft-text: #155446; - --lc-ring: rgba(31, 111, 92, 0.4); - --lc-radius-sm: 4px; - --lc-radius: 6px; - --lc-radius-lg: 8px; - --lc-border-width: 1px; - --lc-shadow-sm: none; - --lc-shadow: 0 1px 3px rgba(0, 0, 0, 0.05); - --lc-shadow-lg: 0 6px 18px rgba(0, 0, 0, 0.07); - --lc-shadow-hard: none; - --lc-blur: none; - --lc-leading-normal: 1.7; - --lc-leading-relaxed: 1.85; - --lc-font-display: Georgia, "Times New Roman", serif; /* characterful display, restrained */ -} -[data-style="semantic-minimalist"][data-theme="dark"] { - --lc-bg: #16150f; - --lc-surface: #1d1c15; - --lc-surface-2: #26241b; - --lc-text: #ece9df; - --lc-text-muted: #a7a394; - --lc-text-faint: #777262; - --lc-border: #2c2a20; - --lc-border-strong: #3a3729; - --lc-accent-soft: #163029; -} - -/* -------------------------------------------------------------------------- - 5) glassmorphism — frosted glass; semi-transparent surfaces + backdrop blur. - Page sits on a gradient so the blur reads. Fallback below for no support. - -------------------------------------------------------------------------- */ -[data-style="glassmorphism"] { - --lc-bg: #0b1020; - --lc-bg-gradient: - radial-gradient(1200px 600px at 12% -10%, #6d28d9 0%, transparent 55%), - radial-gradient(900px 500px at 100% 0%, #0ea5e9 0%, transparent 50%), - radial-gradient(800px 600px at 50% 120%, #db2777 0%, transparent 55%); - --lc-surface: rgba(255, 255, 255, 0.1); - --lc-surface-2: rgba(255, 255, 255, 0.16); - --lc-text: #f4f6ff; - --lc-text-muted: #c4cbe6; - --lc-text-faint: #9aa2c4; - --lc-border: rgba(255, 255, 255, 0.22); - --lc-border-strong: rgba(255, 255, 255, 0.35); - --lc-accent: #a78bfa; - --lc-accent-hover: #b9a4fb; - --lc-accent-active: #9170f7; - --lc-accent-text: #13102a; - --lc-accent-soft: rgba(167, 139, 250, 0.22); - --lc-accent-soft-text: #e3dbff; - --lc-ring: rgba(167, 139, 250, 0.5); - --lc-success-soft: rgba(34, 197, 94, 0.2); - --lc-warning-soft: rgba(217, 119, 6, 0.22); - --lc-danger-soft: rgba(220, 38, 38, 0.22); - --lc-info-soft: rgba(14, 165, 233, 0.22); - --lc-radius-sm: 10px; - --lc-radius: 16px; - --lc-radius-lg: 22px; - --lc-border-width: 1px; - --lc-shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.25); - --lc-shadow: 0 8px 32px rgba(0, 0, 0, 0.32); - --lc-shadow-lg: 0 20px 60px rgba(0, 0, 0, 0.4); - --lc-shadow-hard: none; - --lc-blur: blur(14px) saturate(140%); - --lc-glass-tint: rgba(255, 255, 255, 0.1); - --lc-glass-border: rgba(255, 255, 255, 0.28); -} -[data-style="glassmorphism"] body { - background-image: var(--lc-bg-gradient); - background-attachment: fixed; -} - -/* Fallback: if backdrop-filter is unsupported, make glass surfaces opaque - so content stays legible (no see-through mud). */ -@supports not (backdrop-filter: blur(1px)) { - [data-style="glassmorphism"] { - --lc-surface: #1b2138; - --lc-surface-2: #232a44; - --lc-border: rgba(255, 255, 255, 0.18); - --lc-blur: none; - } -} diff --git a/package/src/utilities.css b/package/src/utilities.css deleted file mode 100644 index 9c68460..0000000 --- a/package/src/utilities.css +++ /dev/null @@ -1,1184 +0,0 @@ -/* ========================================================================== - LombokCSS — utilities.css - Atomic helpers. RTL-safe via logical properties. Responsive: sm/md/lg/xl. - ========================================================================== */ - -/* ---- Display ---- */ -.block { - display: block; -} -.inline-block { - display: inline-block; -} -.inline { - display: inline; -} -.hidden { - display: none; -} -.flex { - display: flex; -} -.inline-flex { - display: inline-flex; -} -.grid { - display: grid; -} -.inline-grid { - display: inline-grid; -} - -/* ---- Flexbox ---- */ -.flex-row { - flex-direction: row; -} -.flex-col { - flex-direction: column; -} -.flex-wrap { - flex-wrap: wrap; -} -.flex-1 { - flex: 1 1 0%; -} -.flex-auto { - flex: 1 1 auto; -} -.flex-none { - flex: none; -} -.items-start { - align-items: flex-start; -} -.items-center { - align-items: center; -} -.items-end { - align-items: flex-end; -} -.items-stretch { - align-items: stretch; -} -.items-baseline { - align-items: baseline; -} -.justify-start { - justify-content: flex-start; -} -.justify-center { - justify-content: center; -} -.justify-end { - justify-content: flex-end; -} -.justify-between { - justify-content: space-between; -} -.justify-around { - justify-content: space-around; -} -.justify-evenly { - justify-content: space-evenly; -} -.self-start { - align-self: flex-start; -} -.self-center { - align-self: center; -} -.self-end { - align-self: flex-end; -} - -/* ---- Grid ---- */ -.grid-cols-1 { - grid-template-columns: repeat(1, 1fr); -} -.grid-cols-2 { - grid-template-columns: repeat(2, 1fr); -} -.grid-cols-3 { - grid-template-columns: repeat(3, 1fr); -} -.grid-cols-4 { - grid-template-columns: repeat(4, 1fr); -} -.grid-cols-5 { - grid-template-columns: repeat(5, 1fr); -} -.grid-cols-6 { - grid-template-columns: repeat(6, 1fr); -} -.grid-cols-12 { - grid-template-columns: repeat(12, 1fr); -} -.col-span-2 { - grid-column: span 2; -} -.col-span-3 { - grid-column: span 3; -} -.col-span-4 { - grid-column: span 4; -} -.col-span-6 { - grid-column: span 6; -} -.col-span-full { - grid-column: 1 / -1; -} - -/* ---- Gap (uses spacing scale) ---- */ -.gap-0 { - gap: 0; -} -.gap-1 { - gap: var(--lc-space-1); -} -.gap-2 { - gap: var(--lc-space-2); -} -.gap-3 { - gap: var(--lc-space-3); -} -.gap-4 { - gap: var(--lc-space-4); -} -.gap-6 { - gap: var(--lc-space-6); -} -.gap-8 { - gap: var(--lc-space-8); -} - -/* ---- Spacing: padding (logical) ---- */ -.p-0 { - padding: 0; -} -.p-1 { - padding: var(--lc-space-1); -} -.p-2 { - padding: var(--lc-space-2); -} -.p-3 { - padding: var(--lc-space-3); -} -.p-4 { - padding: var(--lc-space-4); -} -.p-6 { - padding: var(--lc-space-6); -} -.p-8 { - padding: var(--lc-space-8); -} -.px-2 { - padding-inline: var(--lc-space-2); -} -.px-3 { - padding-inline: var(--lc-space-3); -} -.px-4 { - padding-inline: var(--lc-space-4); -} -.px-6 { - padding-inline: var(--lc-space-6); -} -.py-1 { - padding-block: var(--lc-space-1); -} -.py-2 { - padding-block: var(--lc-space-2); -} -.py-3 { - padding-block: var(--lc-space-3); -} -.py-4 { - padding-block: var(--lc-space-4); -} -.py-6 { - padding-block: var(--lc-space-6); -} -.pt-4 { - padding-block-start: var(--lc-space-4); -} -.pb-4 { - padding-block-end: var(--lc-space-4); -} - -/* ---- Spacing: margin (logical) ---- */ -.m-0 { - margin: 0; -} -.m-auto { - margin: auto; -} -.m-1 { - margin: var(--lc-space-1); -} -.m-2 { - margin: var(--lc-space-2); -} -.m-4 { - margin: var(--lc-space-4); -} -.mx-auto { - margin-inline: auto; -} -.my-2 { - margin-block: var(--lc-space-2); -} -.my-4 { - margin-block: var(--lc-space-4); -} -.my-6 { - margin-block: var(--lc-space-6); -} -.mt-2 { - margin-block-start: var(--lc-space-2); -} -.mt-4 { - margin-block-start: var(--lc-space-4); -} -.mt-6 { - margin-block-start: var(--lc-space-6); -} -.mb-0 { - margin-block-end: 0; -} -.mb-2 { - margin-block-end: var(--lc-space-2); -} -.mb-4 { - margin-block-end: var(--lc-space-4); -} -.mb-6 { - margin-block-end: var(--lc-space-6); -} -.ms-auto { - margin-inline-start: auto; -} -.me-auto { - margin-inline-end: auto; -} - -/* ---- Sizing ---- */ -.w-full { - inline-size: 100%; -} -.w-auto { - inline-size: auto; -} -.w-screen { - inline-size: 100vw; -} -.w-fit { - inline-size: fit-content; -} -.h-full { - block-size: 100%; -} -.h-screen { - block-size: 100vh; -} -.min-h-screen { - min-block-size: 100vh; -} -.max-w-xs { - max-inline-size: 20rem; -} -.max-w-sm { - max-inline-size: 24rem; -} -.max-w-md { - max-inline-size: 28rem; -} -.max-w-lg { - max-inline-size: 32rem; -} -.max-w-xl { - max-inline-size: 36rem; -} -.max-w-2xl { - max-inline-size: 42rem; -} -.max-w-7xl { - max-inline-size: 80rem; -} - -/* ---- Typography ---- */ -.text-xs { - font-size: var(--lc-text-xs); -} -.text-sm { - font-size: var(--lc-text-sm); -} -.text-base { - font-size: var(--lc-text-base); -} -.text-lg { - font-size: var(--lc-text-lg); -} -.text-xl { - font-size: var(--lc-text-xl); -} -.text-2xl { - font-size: var(--lc-text-2xl); -} -.text-3xl { - font-size: var(--lc-text-3xl); -} -.font-light { - font-weight: 300; -} -.font-normal { - font-weight: var(--lc-weight-normal); -} -.font-medium { - font-weight: var(--lc-weight-medium); -} -.font-semibold { - font-weight: var(--lc-weight-semibold); -} -.font-bold { - font-weight: var(--lc-weight-bold); -} -.text-start { - text-align: start; -} -.text-center { - text-align: center; -} -.text-end { - text-align: end; -} -.text-justify { - text-align: justify; -} -.leading-tight { - line-height: var(--lc-leading-tight); -} -.leading-normal { - line-height: var(--lc-leading-normal); -} -.leading-relaxed { - line-height: var(--lc-leading-relaxed); -} -.tracking-tight { - letter-spacing: -0.02em; -} -.tracking-wide { - letter-spacing: 0.04em; -} -.uppercase { - text-transform: uppercase; -} -.capitalize { - text-transform: capitalize; -} -.truncate { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} -.font-mono { - font-family: var(--lc-font-mono); -} - -/* ---- Colors ---- */ -.text-primary { - color: var(--lc-accent); -} -.text-muted { - color: var(--lc-text-muted); -} -.text-faint { - color: var(--lc-text-faint); -} -.text-success { - color: var(--lc-success-text); -} -.text-danger { - color: var(--lc-danger-text); -} -.text-warning { - color: var(--lc-warning-text); -} -.bg-bg { - background: var(--lc-bg); -} -.bg-surface { - background: var(--lc-surface); -} -.bg-surface-2 { - background: var(--lc-surface-2); -} -.bg-primary { - background: var(--lc-accent); - color: var(--lc-accent-text); -} -.bg-soft { - background: var(--lc-accent-soft); - color: var(--lc-accent-soft-text); -} -.border { - border: var(--lc-border-width) solid var(--lc-border); -} -.border-strong { - border-color: var(--lc-border-strong); -} -.border-0 { - border: 0; -} -.border-t { - border-block-start: var(--lc-border-width) solid var(--lc-border); -} -.border-b { - border-block-end: var(--lc-border-width) solid var(--lc-border); -} - -/* ---- Radius ---- */ -.rounded-none { - border-radius: 0; -} -.rounded-sm { - border-radius: var(--lc-radius-sm); -} -.rounded { - border-radius: var(--lc-radius); -} -.rounded-lg { - border-radius: var(--lc-radius-lg); -} -.rounded-full { - border-radius: var(--lc-radius-full); -} - -/* ---- Effects ---- */ -.shadow-none { - box-shadow: none; -} -.shadow-sm { - box-shadow: var(--lc-shadow-sm); -} -.shadow { - box-shadow: var(--lc-shadow); -} -.shadow-lg { - box-shadow: var(--lc-shadow-lg); -} -.backdrop-blur { - -webkit-backdrop-filter: blur(8px); - backdrop-filter: blur(8px); -} -.opacity-50 { - opacity: 0.5; -} -.opacity-75 { - opacity: 0.75; -} - -/* ---- Position ---- */ -.relative { - position: relative; -} -.absolute { - position: absolute; -} -.fixed { - position: fixed; -} -.sticky { - position: sticky; -} -.inset-0 { - inset: 0; -} -.top-0 { - inset-block-start: 0; -} -.bottom-0 { - inset-block-end: 0; -} -.start-0 { - inset-inline-start: 0; -} -.end-0 { - inset-inline-end: 0; -} -.z-10 { - z-index: 10; -} -.z-20 { - z-index: 20; -} -.z-30 { - z-index: 30; -} -.z-50 { - z-index: 50; -} - -/* ---- Misc ---- */ -.overflow-hidden { - overflow: hidden; -} -.overflow-auto { - overflow: auto; -} -.overflow-x-auto { - overflow-x: auto; -} -.cursor-pointer { - cursor: pointer; -} -.cursor-default { - cursor: default; -} -.select-none { - user-select: none; -} -.transition { - transition: all var(--lc-transition); -} -.sr-only { - position: absolute; - inline-size: 1px; - block-size: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - white-space: nowrap; - border: 0; -} -.aspect-square { - aspect-ratio: 1; -} -.aspect-video { - aspect-ratio: 16/9; -} - -/* ---- Status colors (solid / soft / text / border) ---- */ -.text-info { - color: var(--lc-info-text); -} -.bg-success { - background: var(--lc-success); - color: #fff; -} -.bg-warning { - background: var(--lc-warning); - color: #fff; -} -.bg-danger { - background: var(--lc-danger); - color: #fff; -} -.bg-info { - background: var(--lc-info); - color: #fff; -} -.bg-success-soft { - background: var(--lc-success-soft); - color: var(--lc-success-text); -} -.bg-warning-soft { - background: var(--lc-warning-soft); - color: var(--lc-warning-text); -} -.bg-danger-soft { - background: var(--lc-danger-soft); - color: var(--lc-danger-text); -} -.bg-info-soft { - background: var(--lc-info-soft); - color: var(--lc-info-text); -} -.border-success { - border-color: var(--lc-success); -} -.border-warning { - border-color: var(--lc-warning); -} -.border-danger { - border-color: var(--lc-danger); -} -.border-info { - border-color: var(--lc-info); -} -.border-primary { - border-color: var(--lc-accent); -} - -/* ---- Full gap scale + directional gaps ---- */ -.gap-5 { - gap: var(--lc-space-5); -} -.gap-10 { - gap: var(--lc-space-10); -} -.gap-12 { - gap: var(--lc-space-12); -} -.gap-x-2 { - column-gap: var(--lc-space-2); -} -.gap-x-4 { - column-gap: var(--lc-space-4); -} -.gap-x-6 { - column-gap: var(--lc-space-6); -} -.gap-y-2 { - row-gap: var(--lc-space-2); -} -.gap-y-4 { - row-gap: var(--lc-space-4); -} -.gap-y-6 { - row-gap: var(--lc-space-6); -} -/* ---- Full col-span scale ---- */ -.col-span-1 { - grid-column: span 1; -} -.col-span-5 { - grid-column: span 5; -} -.col-span-7 { - grid-column: span 7; -} -.col-span-8 { - grid-column: span 8; -} -.col-span-9 { - grid-column: span 9; -} -.col-span-10 { - grid-column: span 10; -} -.col-span-11 { - grid-column: span 11; -} -.col-span-12 { - grid-column: span 12; -} - -/* ========================================================================== - Responsive prefixes (mobile-first), full scale: sm 640 / md 768 / lg 1024 / xl 1280 - ========================================================================== */ -@media (min-width: 640px) { - .sm\:block { - display: block; - } - .sm\:inline-block { - display: inline-block; - } - .sm\:flex { - display: flex; - } - .sm\:inline-flex { - display: inline-flex; - } - .sm\:grid { - display: grid; - } - .sm\:inline-grid { - display: inline-grid; - } - .sm\:hidden { - display: none; - } - .sm\:flex-row { - flex-direction: row; - } - .sm\:flex-col { - flex-direction: column; - } - .sm\:flex-wrap { - flex-wrap: wrap; - } - .sm\:items-start { - align-items: flex-start; - } - .sm\:items-center { - align-items: center; - } - .sm\:items-end { - align-items: flex-end; - } - .sm\:justify-start { - justify-content: flex-start; - } - .sm\:justify-center { - justify-content: center; - } - .sm\:justify-end { - justify-content: flex-end; - } - .sm\:justify-between { - justify-content: space-between; - } - .sm\:grid-cols-1 { - grid-template-columns: repeat(1, 1fr); - } - .sm\:grid-cols-2 { - grid-template-columns: repeat(2, 1fr); - } - .sm\:grid-cols-3 { - grid-template-columns: repeat(3, 1fr); - } - .sm\:grid-cols-4 { - grid-template-columns: repeat(4, 1fr); - } - .sm\:grid-cols-5 { - grid-template-columns: repeat(5, 1fr); - } - .sm\:grid-cols-6 { - grid-template-columns: repeat(6, 1fr); - } - .sm\:grid-cols-12 { - grid-template-columns: repeat(12, 1fr); - } - .sm\:col-span-1 { - grid-column: span 1; - } - .sm\:col-span-2 { - grid-column: span 2; - } - .sm\:col-span-3 { - grid-column: span 3; - } - .sm\:col-span-4 { - grid-column: span 4; - } - .sm\:col-span-5 { - grid-column: span 5; - } - .sm\:col-span-6 { - grid-column: span 6; - } - .sm\:col-span-full { - grid-column: 1 / -1; - } - .sm\:gap-0 { - gap: 0; - } - .sm\:gap-1 { - gap: var(--lc-space-1); - } - .sm\:gap-2 { - gap: var(--lc-space-2); - } - .sm\:gap-3 { - gap: var(--lc-space-3); - } - .sm\:gap-4 { - gap: var(--lc-space-4); - } - .sm\:gap-5 { - gap: var(--lc-space-5); - } - .sm\:gap-6 { - gap: var(--lc-space-6); - } - .sm\:gap-8 { - gap: var(--lc-space-8); - } - .sm\:text-start { - text-align: start; - } - .sm\:text-center { - text-align: center; - } - .sm\:text-end { - text-align: end; - } -} -@media (min-width: 768px) { - .md\:block { - display: block; - } - .md\:inline-block { - display: inline-block; - } - .md\:flex { - display: flex; - } - .md\:inline-flex { - display: inline-flex; - } - .md\:grid { - display: grid; - } - .md\:inline-grid { - display: inline-grid; - } - .md\:hidden { - display: none; - } - .md\:flex-row { - flex-direction: row; - } - .md\:flex-col { - flex-direction: column; - } - .md\:flex-wrap { - flex-wrap: wrap; - } - .md\:items-start { - align-items: flex-start; - } - .md\:items-center { - align-items: center; - } - .md\:items-end { - align-items: flex-end; - } - .md\:justify-start { - justify-content: flex-start; - } - .md\:justify-center { - justify-content: center; - } - .md\:justify-end { - justify-content: flex-end; - } - .md\:justify-between { - justify-content: space-between; - } - .md\:grid-cols-1 { - grid-template-columns: repeat(1, 1fr); - } - .md\:grid-cols-2 { - grid-template-columns: repeat(2, 1fr); - } - .md\:grid-cols-3 { - grid-template-columns: repeat(3, 1fr); - } - .md\:grid-cols-4 { - grid-template-columns: repeat(4, 1fr); - } - .md\:grid-cols-5 { - grid-template-columns: repeat(5, 1fr); - } - .md\:grid-cols-6 { - grid-template-columns: repeat(6, 1fr); - } - .md\:grid-cols-12 { - grid-template-columns: repeat(12, 1fr); - } - .md\:col-span-1 { - grid-column: span 1; - } - .md\:col-span-2 { - grid-column: span 2; - } - .md\:col-span-3 { - grid-column: span 3; - } - .md\:col-span-4 { - grid-column: span 4; - } - .md\:col-span-5 { - grid-column: span 5; - } - .md\:col-span-6 { - grid-column: span 6; - } - .md\:col-span-full { - grid-column: 1 / -1; - } - .md\:gap-0 { - gap: 0; - } - .md\:gap-1 { - gap: var(--lc-space-1); - } - .md\:gap-2 { - gap: var(--lc-space-2); - } - .md\:gap-3 { - gap: var(--lc-space-3); - } - .md\:gap-4 { - gap: var(--lc-space-4); - } - .md\:gap-5 { - gap: var(--lc-space-5); - } - .md\:gap-6 { - gap: var(--lc-space-6); - } - .md\:gap-8 { - gap: var(--lc-space-8); - } - .md\:text-start { - text-align: start; - } - .md\:text-center { - text-align: center; - } - .md\:text-end { - text-align: end; - } -} -@media (min-width: 1024px) { - .lg\:block { - display: block; - } - .lg\:inline-block { - display: inline-block; - } - .lg\:flex { - display: flex; - } - .lg\:inline-flex { - display: inline-flex; - } - .lg\:grid { - display: grid; - } - .lg\:inline-grid { - display: inline-grid; - } - .lg\:hidden { - display: none; - } - .lg\:flex-row { - flex-direction: row; - } - .lg\:flex-col { - flex-direction: column; - } - .lg\:flex-wrap { - flex-wrap: wrap; - } - .lg\:items-start { - align-items: flex-start; - } - .lg\:items-center { - align-items: center; - } - .lg\:items-end { - align-items: flex-end; - } - .lg\:justify-start { - justify-content: flex-start; - } - .lg\:justify-center { - justify-content: center; - } - .lg\:justify-end { - justify-content: flex-end; - } - .lg\:justify-between { - justify-content: space-between; - } - .lg\:grid-cols-1 { - grid-template-columns: repeat(1, 1fr); - } - .lg\:grid-cols-2 { - grid-template-columns: repeat(2, 1fr); - } - .lg\:grid-cols-3 { - grid-template-columns: repeat(3, 1fr); - } - .lg\:grid-cols-4 { - grid-template-columns: repeat(4, 1fr); - } - .lg\:grid-cols-5 { - grid-template-columns: repeat(5, 1fr); - } - .lg\:grid-cols-6 { - grid-template-columns: repeat(6, 1fr); - } - .lg\:grid-cols-12 { - grid-template-columns: repeat(12, 1fr); - } - .lg\:col-span-1 { - grid-column: span 1; - } - .lg\:col-span-2 { - grid-column: span 2; - } - .lg\:col-span-3 { - grid-column: span 3; - } - .lg\:col-span-4 { - grid-column: span 4; - } - .lg\:col-span-5 { - grid-column: span 5; - } - .lg\:col-span-6 { - grid-column: span 6; - } - .lg\:col-span-full { - grid-column: 1 / -1; - } - .lg\:gap-0 { - gap: 0; - } - .lg\:gap-1 { - gap: var(--lc-space-1); - } - .lg\:gap-2 { - gap: var(--lc-space-2); - } - .lg\:gap-3 { - gap: var(--lc-space-3); - } - .lg\:gap-4 { - gap: var(--lc-space-4); - } - .lg\:gap-5 { - gap: var(--lc-space-5); - } - .lg\:gap-6 { - gap: var(--lc-space-6); - } - .lg\:gap-8 { - gap: var(--lc-space-8); - } - .lg\:text-start { - text-align: start; - } - .lg\:text-center { - text-align: center; - } - .lg\:text-end { - text-align: end; - } -} -@media (min-width: 1280px) { - .xl\:block { - display: block; - } - .xl\:inline-block { - display: inline-block; - } - .xl\:flex { - display: flex; - } - .xl\:inline-flex { - display: inline-flex; - } - .xl\:grid { - display: grid; - } - .xl\:inline-grid { - display: inline-grid; - } - .xl\:hidden { - display: none; - } - .xl\:flex-row { - flex-direction: row; - } - .xl\:flex-col { - flex-direction: column; - } - .xl\:flex-wrap { - flex-wrap: wrap; - } - .xl\:items-start { - align-items: flex-start; - } - .xl\:items-center { - align-items: center; - } - .xl\:items-end { - align-items: flex-end; - } - .xl\:justify-start { - justify-content: flex-start; - } - .xl\:justify-center { - justify-content: center; - } - .xl\:justify-end { - justify-content: flex-end; - } - .xl\:justify-between { - justify-content: space-between; - } - .xl\:grid-cols-1 { - grid-template-columns: repeat(1, 1fr); - } - .xl\:grid-cols-2 { - grid-template-columns: repeat(2, 1fr); - } - .xl\:grid-cols-3 { - grid-template-columns: repeat(3, 1fr); - } - .xl\:grid-cols-4 { - grid-template-columns: repeat(4, 1fr); - } - .xl\:grid-cols-5 { - grid-template-columns: repeat(5, 1fr); - } - .xl\:grid-cols-6 { - grid-template-columns: repeat(6, 1fr); - } - .xl\:grid-cols-12 { - grid-template-columns: repeat(12, 1fr); - } - .xl\:col-span-1 { - grid-column: span 1; - } - .xl\:col-span-2 { - grid-column: span 2; - } - .xl\:col-span-3 { - grid-column: span 3; - } - .xl\:col-span-4 { - grid-column: span 4; - } - .xl\:col-span-5 { - grid-column: span 5; - } - .xl\:col-span-6 { - grid-column: span 6; - } - .xl\:col-span-full { - grid-column: 1 / -1; - } - .xl\:gap-0 { - gap: 0; - } - .xl\:gap-1 { - gap: var(--lc-space-1); - } - .xl\:gap-2 { - gap: var(--lc-space-2); - } - .xl\:gap-3 { - gap: var(--lc-space-3); - } - .xl\:gap-4 { - gap: var(--lc-space-4); - } - .xl\:gap-5 { - gap: var(--lc-space-5); - } - .xl\:gap-6 { - gap: var(--lc-space-6); - } - .xl\:gap-8 { - gap: var(--lc-space-8); - } - .xl\:text-start { - text-align: start; - } - .xl\:text-center { - text-align: center; - } - .xl\:text-end { - text-align: end; - } -} diff --git a/package/src/variables.css b/package/src/variables.css deleted file mode 100644 index 91a3b51..0000000 --- a/package/src/variables.css +++ /dev/null @@ -1,169 +0,0 @@ -/* ========================================================================== - LombokCSS — variables.css - Token architecture. Every component reads SEMANTIC tokens only. - Themes (data-style) and dark mode (data-theme) just re-map these tokens. - -------------------------------------------------------------------------- - Naming: all tokens are namespaced `--lc-*` to avoid collisions. - ========================================================================== */ - -:root { - /* ---- Color primitives (raw palette) ---- */ - --lc-white: #ffffff; - --lc-black: #0a0a0a; - - /* ---- Semantic surface & text (LIGHT default = corporate-flat) ---- */ - --lc-bg: #f6f7f9; /* page background */ - --lc-surface: #ffffff; /* cards, modals, inputs */ - --lc-surface-2: #f1f3f5; /* subtle raised / hover */ - --lc-text: #1a1d21; /* primary text */ - --lc-text-muted: #5b6470; /* secondary text */ - --lc-text-faint: #8a93a0; /* placeholders, captions */ - --lc-border: #e2e6ea; /* hairline borders */ - --lc-border-strong: #c8cfd6; - - /* ---- Brand / accent ---- */ - --lc-accent: #3b82f6; - --lc-accent-hover: #2f6fe0; - --lc-accent-active: #2861c9; - --lc-accent-text: #ffffff; /* text on accent surface */ - --lc-accent-soft: #e8f0fe; /* soft accent background */ - --lc-accent-soft-text: #1f5fd1; - --lc-ring: rgba(59, 130, 246, 0.45); /* focus ring color */ - - /* ---- Status colors (bg / text / soft) ---- */ - --lc-success: #16a34a; - --lc-success-soft: #e7f6ec; - --lc-success-text: #0f7a37; - --lc-warning: #d97706; - --lc-warning-soft: #fdf0dd; - --lc-warning-text: #a85d05; - --lc-danger: #dc2626; - --lc-danger-soft: #fde8e8; - --lc-danger-text: #b21d1d; - --lc-info: #0ea5e9; - --lc-info-soft: #e3f5fd; - --lc-info-text: #0b7fb4; - - /* ---- Typography ---- */ - --lc-font-sans: system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; - --lc-font-mono: ui-monospace, "SF Mono", "JetBrains Mono", "Fira Code", Menlo, Consolas, monospace; - --lc-font-display: var(--lc-font-sans); - - --lc-text-xs: 0.75rem; - --lc-text-sm: 0.875rem; - --lc-text-base: 1rem; - --lc-text-lg: 1.125rem; - --lc-text-xl: 1.25rem; - --lc-text-2xl: 1.5rem; - --lc-text-3xl: 1.875rem; - --lc-text-4xl: 2.25rem; - - --lc-leading-tight: 1.2; - --lc-leading-normal: 1.55; - --lc-leading-relaxed: 1.75; - - --lc-weight-normal: 400; - --lc-weight-medium: 500; - --lc-weight-semibold: 600; - --lc-weight-bold: 700; - --lc-tracking: 0; /* letter-spacing for body */ - - /* ---- Spacing scale (used by utilities + components) ---- */ - --lc-space-0: 0; - --lc-space-1: 0.25rem; - --lc-space-2: 0.5rem; - --lc-space-3: 0.75rem; - --lc-space-4: 1rem; - --lc-space-5: 1.25rem; - --lc-space-6: 1.5rem; - --lc-space-8: 2rem; - --lc-space-10: 2.5rem; - --lc-space-12: 3rem; - - /* ---- Radius ---- */ - --lc-radius-sm: 6px; - --lc-radius: 10px; - --lc-radius-lg: 16px; - --lc-radius-full: 9999px; - - /* ---- Borders ---- */ - --lc-border-width: 1px; - - /* ---- Shadows ---- */ - --lc-shadow-sm: 0 1px 2px rgba(16, 24, 40, 0.06); - --lc-shadow: 0 4px 12px rgba(16, 24, 40, 0.08); - --lc-shadow-lg: 0 12px 32px rgba(16, 24, 40, 0.12); - /* hard-offset shadow only used by neo-brutalism, kept here for consistency */ - --lc-shadow-hard: none; - - /* ---- Glass tokens (inert unless a glass theme turns blur on) ---- */ - --lc-blur: none; /* backdrop-filter value */ - --lc-glass-tint: var(--lc-surface); - --lc-glass-border: var(--lc-border); - - /* ---- Motion ---- */ - --lc-transition: 160ms cubic-bezier(0.4, 0, 0.2, 1); - - /* ---- Layout ---- */ - --lc-container: 1120px; - --lc-navbar-h: 60px; - --lc-z-base: 1; - --lc-z-dropdown: 1000; - --lc-z-sticky: 1020; - --lc-z-modal: 1050; - --lc-z-toast: 1080; - --lc-z-tooltip: 1090; -} - -/* ========================================================================== - DARK MODE (color-token overlay) — applies to default + corporate + glass. - Themes that are intrinsically dark (resonant-stark) set their own values. - ========================================================================== */ -@media (prefers-color-scheme: dark) { - :root:not([data-theme="light"]) { - --lc-bg: #0f1115; - --lc-surface: #171a21; - --lc-surface-2: #1f242d; - --lc-text: #e7eaee; - --lc-text-muted: #9aa4b2; - --lc-text-faint: #6b7480; - --lc-border: #2a2f3a; - --lc-border-strong: #3a404d; - --lc-accent-soft: #16263f; - --lc-accent-soft-text: #8ab4ff; - --lc-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4); - --lc-shadow: 0 4px 12px rgba(0, 0, 0, 0.45); - --lc-shadow-lg: 0 12px 32px rgba(0, 0, 0, 0.55); - --lc-success-soft: #10241a; - --lc-warning-soft: #2a1f0d; - --lc-danger-soft: #2a1414; - --lc-info-soft: #0c2530; - --lc-success-text: #6ee7a0; - --lc-warning-text: #fbbf24; - --lc-danger-text: #fca5a5; - --lc-info-text: #67d3f7; - } -} -[data-theme="dark"] { - --lc-bg: #0f1115; - --lc-surface: #171a21; - --lc-surface-2: #1f242d; - --lc-text: #e7eaee; - --lc-text-muted: #9aa4b2; - --lc-text-faint: #6b7480; - --lc-border: #2a2f3a; - --lc-border-strong: #3a404d; - --lc-accent-soft: #16263f; - --lc-accent-soft-text: #8ab4ff; - --lc-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4); - --lc-shadow: 0 4px 12px rgba(0, 0, 0, 0.45); - --lc-shadow-lg: 0 12px 32px rgba(0, 0, 0, 0.55); - --lc-success-soft: #10241a; - --lc-warning-soft: #2a1f0d; - --lc-danger-soft: #2a1414; - --lc-info-soft: #0c2530; - --lc-success-text: #6ee7a0; - --lc-warning-text: #fbbf24; - --lc-danger-text: #fca5a5; - --lc-info-text: #67d3f7; -}