diff --git a/.github/profile/README.md b/.github/profile/README.md index b389e09..ce8ab6f 100644 --- a/.github/profile/README.md +++ b/.github/profile/README.md @@ -5,7 +5,7 @@ **GDIPS** is a GDPS (Geometry Dash Private Server) hosted on **GDPSFH**. The GDPS originally started on November 28th, 2024. *** ## Downloading -You can download the GDPS in [here](https://gdi.ps.fhgdps.com).
Platforms that are supported are: **Android** and **Windows** | **iOS** not added. +You can download the GDPS in [here](https://gdips.wasmer.app).
Platforms that are supported are: **Android** and **Windows** | **iOS** not added. *** ## Repositories [website](https://github.com/flessan/GDIPS) - The GDIPS website source code.
diff --git a/README.md b/README.md index 803498b..05f2c01 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

- GDIPS Logo + GDIPS Logo
GDIPS Website
@@ -43,7 +43,7 @@ ๐Ÿ  Buka Website ยท ๐Ÿ“ฅ Download Game ยท - ๐ŸŽฎ Dashboard Server + ๐ŸŽฎ Dashboard Server @@ -302,7 +302,7 @@ site/ | | Link | Deskripsi | |---|------|-----------| | ๐ŸŒ | [gdips.pages.dev](https://gdips.pages.dev) | Website ini (live) | -| ๐ŸŽฎ | [Dashboard](https://gdi.ps.fhgdps.com) | Game server dashboard | +| ๐ŸŽฎ | [Dashboard](https://gdips.wasmer.app) | Game server dashboard | | ๐Ÿ“ฅ | [Download](https://gdips.pages.dev/download) | Download game client | | ๐Ÿ’ป | [gmdips/GDIPS](https://github.com/gmdips/server) | Repo game server | | ๐Ÿข | [gmdips org](https://github.com/gmdips) | Organization GitHub | diff --git a/main/404.html b/main/404.html new file mode 100644 index 0000000..3b42280 --- /dev/null +++ b/main/404.html @@ -0,0 +1,89 @@ + + + + + + 404 ยท Halaman tidak ditemukan | GDIPS + + + + + + + + + + + + + + + + + + + + +
+
+ + + GDIPS + +
+ +
+
+
+ +
+
+ Error 404 +

404

+

Halaman yang kamu cari tidak ditemukan

+

+ Mungkin tautannya salah ketik, atau halamannya sudah dipindahkan. Coba salah satu + tautan di bawah ini supaya kamu tetap bisa main. +

+ + + + +
+
+ + + + + + diff --git a/main/_headers b/main/_headers index 6b885de..ea65fcb 100644 --- a/main/_headers +++ b/main/_headers @@ -3,3 +3,9 @@ X-Content-Type-Options: nosniff X-Frame-Options: DENY Referrer-Policy: strict-origin-when-cross-origin + +/assets/* + Cache-Control: public, max-age=604800 + +/sw.js + Cache-Control: no-cache diff --git a/main/_redirects b/main/_redirects index faf1c8c..7857ea4 100644 --- a/main/_redirects +++ b/main/_redirects @@ -1,4 +1,10 @@ / /pages 301 +/pages/id/rate /pages/id/rating-system/ 301 +/pages/id/rate.html /pages/id/rating-system/ 301 + +# Dashboard: site links use /dashboard/... and are forwarded to the live dashboard host +/dashboard https://gdips.wasmer.app/dashboard 302 +/dashboard/* https://gdips.wasmer.app/dashboard/:splat 302 # 404 fallback /* /404.html 404 diff --git a/main/assets/batik.css b/main/assets/batik.css deleted file mode 100644 index 32df393..0000000 --- a/main/assets/batik.css +++ /dev/null @@ -1,488 +0,0 @@ -:root { - /* Warna Indonesia */ - --primary: #c8102e; /* Merah Indonesia */ - --secondary: #f9f9f9; /* Putih Indonesia */ - --accent: #d4af37; /* Emas Indonesia */ - --dark: #1a1a1a; /* Background gelap */ - --light: #e8eaed; /* Teks terang */ - --card-bg: #2d2d2d; /* Background kartu */ - --text-secondary: #a0a0a0; /* Teks sekunder */ - --border-color: rgba(200, 16, 46, 0.3); /* Warna border */ -} - -* { - margin: 0; - padding: 0; - box-sizing: border-box; -} - -body { - font-family: 'Poppins', sans-serif; - background-color: var(--dark); - color: var(--light); - line-height: 1.6; - overflow-x: hidden; - position: relative; -} - -/* Indonesian pattern background */ -body::before { - content: ""; - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; - background-image: - linear-gradient(45deg, rgba(200, 16, 46, 0.05) 25%, transparent 25%), - linear-gradient(-45deg, rgba(200, 16, 46, 0.05) 25%, transparent 25%), - linear-gradient(45deg, transparent 75%, rgba(200, 16, 46, 0.05) 75%), - linear-gradient(-45deg, transparent 75%, rgba(200, 16, 46, 0.05) 75%); - background-size: 20px 20px; - background-position: 0 0, 0 10px, 10px -10px, -10px 0px; - z-index: -1; -} - -/* Header Styles */ -header { - background: linear-gradient(135deg, var(--primary), #8b0000); - padding: 15px 20px; - position: sticky; - top: 0; - z-index: 100; - box-shadow: 0 4px 15px rgba(0,0,0,0.2); -} - -nav { - display: flex; - justify-content: space-between; - align-items: center; - max-width: 1200px; - margin: 0 auto; -} - -.logo { - font-weight: 700; - font-size: 1.5rem; - color: var(--secondary); - text-shadow: 1px 1px 2px rgba(0,0,0,0.3); - display: flex; - align-items: center; - gap: 8px; -} - -.logo i { - font-size: 1.8rem; - color: var(--accent); -} - -.menu-toggle { - display: none; - background: none; - border: none; - color: var(--secondary); - font-size: 1.5rem; - cursor: pointer; -} - -.nav-links { - display: flex; - gap: 20px; - list-style: none; -} - -.nav-links a { - color: var(--secondary); - text-decoration: none; - font-weight: 500; - padding: 5px 10px; - border-radius: 20px; - transition: all 0.3s ease; - font-size: 0.9rem; -} - -.nav-links a:hover { - background-color: rgba(255,255,255,0.2); - transform: translateY(-2px); -} - -/* Hero Section */ -.hero { - text-align: center; - padding: 60px 20px; - background: linear-gradient(135deg, var(--primary), #8b0000); - position: relative; - overflow: hidden; -} - -.hero::before { - content: ""; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - background-image: - linear-gradient(45deg, rgba(255,255,255,0.05) 25%, transparent 25%), - linear-gradient(-45deg, rgba(255,255,255,0.05) 25%, transparent 25%), - linear-gradient(45deg, transparent 75%, rgba(255,255,255,0.05) 75%), - linear-gradient(-45deg, transparent 75%, rgba(255,255,255,0.05) 75%); - background-size: 20px 20px; - background-position: 0 0, 0 10px, 10px -10px, -10px 0px; - opacity: 0.1; - pointer-events: none; -} - -.icon-container { - display: flex; - justify-content: center; - align-items: center; - position: relative; - margin-bottom: 20px; -} - -.icon { - width: 100px; - height: 100px; - object-fit: contain; - border-radius: 50%; - border: 4px solid var(--secondary); - box-shadow: 0 8px 20px rgba(0,0,0,0.2); - transition: transform 0.3s ease; - z-index: 1; /* Pastikan ikon berada di atas elemen pseudo */ -} - -.icon:hover { - transform: scale(1.1) rotate(10deg); -} - -.icon-container::after { - content: ""; - position: absolute; - width: 100px; - height: 100px; - border-radius: 50%; - border: 2px dashed var(--accent); - animation: rotate 20s linear infinite; - z-index: 0; /* Pastikan elemen pseudo berada di bawah ikon */ -} - -@keyframes rotate { - from { transform: rotate(0deg); } - to { transform: rotate(360deg); } -} - -.hero h2 { - font-size: clamp(1.8rem, 5vw, 2.5rem); - margin-bottom: 15px; - color: var(--secondary); - text-shadow: 1px 1px 2px rgba(0,0,0,0.3); - position: relative; - display: inline-block; -} - -.hero h2::after { - content: ""; - position: absolute; - bottom: -5px; - left: 50%; - transform: translateX(-50%); - width: 50px; - height: 3px; - background-color: var(--accent); - border-radius: 3px; -} - -.hero p { - font-size: clamp(0.9rem, 2.5vw, 1.1rem); - max-width: 600px; - margin: 0 auto 30px; - color: var(--secondary); -} - -/* Credits Section */ -.credits-container { - padding: 40px 20px; - max-width: 1200px; - margin: 0 auto; -} - -.credit-card { - background-color: var(--card-bg); - border-radius: 15px; - padding: 25px; - margin-bottom: 30px; - display: flex; - flex-direction: column; - align-items: center; - text-align: center; - box-shadow: 0 10px 20px rgba(0,0,0,0.2); - transition: transform 0.3s ease, box-shadow 0.3s ease; - position: relative; - overflow: hidden; - border: 1px solid var(--border-color); -} - -.credit-card:hover { - transform: translateY(-10px); - box-shadow: 0 15px 30px rgba(0,0,0,0.4); -} - -.credit-card::before { - content: ""; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 5px; - background: linear-gradient(90deg, var(--primary), var(--accent)); -} - -.credit-img { - width: 100px; - height: 100px; - border-radius: 50%; - object-fit: cover; - border: 4px solid var(--secondary); - box-shadow: 0 5px 15px rgba(0,0,0,0.3); - margin-bottom: 20px; -} - -.credit-card h3 { - font-size: 1.5rem; - margin-bottom: 10px; - color: var(--secondary); -} - -.credit-card p { - font-size: 0.95rem; - margin-bottom: 20px; - color: var(--light); -} - -.role { - display: inline-block; - padding: 3px 10px; - background: linear-gradient(90deg, var(--primary), var(--accent)); - color: var(--secondary); - border-radius: 20px; - font-size: 0.8rem; - font-weight: 600; - margin-bottom: 15px; -} - -.view-btn { - background-color: var(--primary); - color: var(--secondary); - border: none; - padding: 10px 25px; - border-radius: 30px; - font-weight: 600; - cursor: pointer; - transition: all 0.3s ease; - display: flex; - align-items: center; - gap: 8px; - font-size: 0.9rem; - box-shadow: 0 4px 10px rgba(200, 16, 46, 0.3); -} - -.view-btn:hover { - background-color: #a00d26; - transform: translateY(-3px); - box-shadow: 0 7px 15px rgba(200, 16, 46, 0.4); -} - -/* Footer */ -footer { - background-color: var(--card-bg); - padding: 25px 20px; - text-align: center; - margin-top: 40px; - border-top: 1px solid var(--border-color); -} - -footer p { - font-size: 0.9rem; - color: var(--text-secondary); -} - -footer a { - color: var(--primary); - text-decoration: none; - font-weight: 600; - transition: color 0.3s ease; -} - -footer a:hover { - color: var(--accent); -} - -/* Floating Elements */ -.floating { - position: absolute; - animation: float 6s ease-in-out infinite; - opacity: 0.7; - z-index: 1; -} - -@keyframes float { - 0%, 100% { transform: translateY(0); } - 50% { transform: translateY(-20px); } -} - -.floating:nth-child(1) { - top: 10%; - left: 5%; - animation-delay: 0s; -} - -.floating:nth-child(2) { - top: 30%; - right: 8%; - animation-delay: 1s; -} - -.floating:nth-child(3) { - bottom: 20%; - left: 10%; - animation-delay: 2s; -} - -/* Special Effects */ -.sparkle { - position: absolute; - width: 5px; - height: 5px; - background-color: var(--accent); - border-radius: 50%; - opacity: 0; - animation: sparkle 2s ease-in-out infinite; -} - -@keyframes sparkle { - 0% { opacity: 0; transform: scale(0); } - 50% { opacity: 1; transform: scale(1); } - 100% { opacity: 0; transform: scale(0); } -} - -/* Cute Elements */ -.heart { - color: var(--primary); - font-size: 1.2rem; - margin: 0 5px; - animation: pulse 1.5s ease infinite; -} - -@keyframes pulse { - 0%, 100% { transform: scale(1); } - 50% { transform: scale(1.3); } -} - -/* Responsive Styles */ -@media (max-width: 768px) { - .menu-toggle { - display: block; - } - - .nav-links { - position: fixed; - top: 70px; - left: 0; - width: 100%; - background: linear-gradient(135deg, var(--primary), #8b0000); - flex-direction: column; - align-items: center; - padding: 20px 0; - gap: 15px; - clip-path: circle(0px at 90% -10%); - transition: all 0.5s ease-out; - pointer-events: none; - } - - .nav-links.active { - clip-path: circle(1000px at 90% -10%); - pointer-events: all; - } - - .hero h2 { - font-size: 1.8rem; - } - - .hero p { - font-size: 0.95rem; - } - - .credit-card { - padding: 20px; - } -} - -@media (min-width: 992px) { - .credits-container { - display: grid; - grid-template-columns: repeat(2, 1fr); - gap: 30px; - } - - .credit-card { - margin-bottom: 0; - } -} - -@media (max-width: 480px) { - .credits-container { - grid-template-columns: 1fr; - } - - .hero { - padding: 40px 15px; - } - - .icon { - width: 80px; - height: 80px; - } - - .icon-container::after { - width: 80px; - height: 80px; - } - - .credit-card { - padding: 15px; - } - - .credit-img { - width: 80px; - height: 80px; - } - - .view-btn { - padding: 8px 20px; - font-size: 0.85rem; - } -} - -/* Accessibility improvements */ -@media (prefers-reduced-motion: reduce) { - * { - animation-duration: 0.01ms !important; - animation-iteration-count: 1 !important; - transition-duration: 0.01ms !important; - } -} - -/* High contrast mode support */ -@media (prefers-contrast: high) { - :root { - --primary: #ff0000; - --secondary: #ffffff; - --accent: #ffff00; - --dark: #000000; - --light: #ffffff; - --card-bg: #222222; - --text-secondary: #cccccc; - --border-color: #ff0000; - } -} \ No newline at end of file diff --git a/main/assets/bg-pattern.png b/main/assets/bg-pattern.png deleted file mode 100644 index d245508..0000000 Binary files a/main/assets/bg-pattern.png and /dev/null differ diff --git a/main/assets/brand/apple-touch-icon.png b/main/assets/brand/apple-touch-icon.png new file mode 100644 index 0000000..bf03e2d Binary files /dev/null and b/main/assets/brand/apple-touch-icon.png differ diff --git a/main/assets/brand/favicon-32.png b/main/assets/brand/favicon-32.png new file mode 100644 index 0000000..5a4e16e Binary files /dev/null and b/main/assets/brand/favicon-32.png differ diff --git a/main/assets/brand/favicon.svg b/main/assets/brand/favicon.svg new file mode 100644 index 0000000..ef6cc32 --- /dev/null +++ b/main/assets/brand/favicon.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/main/assets/brand/gdips-mark-maskable.svg b/main/assets/brand/gdips-mark-maskable.svg new file mode 100644 index 0000000..e88c338 --- /dev/null +++ b/main/assets/brand/gdips-mark-maskable.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/main/assets/brand/gdips-mark.svg b/main/assets/brand/gdips-mark.svg new file mode 100644 index 0000000..ef6cc32 --- /dev/null +++ b/main/assets/brand/gdips-mark.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/main/assets/brand/icon-192.png b/main/assets/brand/icon-192.png new file mode 100644 index 0000000..a4ddc5d Binary files /dev/null and b/main/assets/brand/icon-192.png differ diff --git a/main/assets/brand/icon-512.png b/main/assets/brand/icon-512.png new file mode 100644 index 0000000..775e56a Binary files /dev/null and b/main/assets/brand/icon-512.png differ diff --git a/main/assets/brand/icon-maskable-512.png b/main/assets/brand/icon-maskable-512.png new file mode 100644 index 0000000..9069657 Binary files /dev/null and b/main/assets/brand/icon-maskable-512.png differ diff --git a/main/assets/m3/README.md b/main/assets/m3/README.md new file mode 100644 index 0000000..a158f7b --- /dev/null +++ b/main/assets/m3/README.md @@ -0,0 +1,121 @@ +# GDIPS ยท Material You 3 design system + +Everything the redesigned site renders comes from this folder. No build step, no +dependencies โ€” plain CSS and plain ES5-compatible JavaScript that runs straight +from Cloudflare Pages. + +## Load order + +Every page links the same five stylesheets, in this order, then its own page +stylesheet: + +```html + + + + + + + +``` + +`color.js` is intentionally **not** deferred: it resolves the theme and paints the +colour roles before first paint so there is no flash of the wrong theme. + +## Colour + +Colours are Material 3 *roles*, never raw hex values: `--m3-primary`, +`--m3-on-primary`, `--m3-primary-container`, `--m3-surface-container-high`, +`--m3-outline-variant`, `--m3-error-container`, โ€ฆ Use the role that describes the +meaning, and pair every `on-*` role with the surface it sits on. + +| Theme | Selector | Palette | +| --- | --- | --- | +| Light | `` or `` | `:root` block | +| Dark | `` | `:root[data-theme="dark"]` | +| System | no attribute, resolved by `color.js` | `@media (prefers-color-scheme: dark)` fallback | + +`` picks a named seed palette (`indigo`, `violet`, `crimson`, +`emerald`, `amber`, `azure`); the default is the GDIPS brand red. The seed picker +in the app bar (`
`) can also generate a palette from any +hex colour at runtime โ€” the result is stored in `localStorage['gdips:seed']`. + +### Regenerating the palettes + +```bash +python3 main/assets/m3/gen_palette.py # rewrites main/assets/m3/palettes.css +``` + +The generator and the runtime engine in `color.js` share the same algorithm +(CIELAB tone mapping with gamut-clamped chroma) and the same contrast rule: dark +container roles step down the tonal ramp until they reach 4.5:1 against their +`on-*` label. Never hand-edit `palettes.css`; change the generator and re-run it. + +## Typescale and spacing + +- `--m3-display-*`, `--m3-headline-*`, `--m3-title-*`, `--m3-body-*`, + `--m3-label-*` for size/weight/letter-spacing. +- `--m3-space-1 โ€ฆ --m3-space-16` for a 4 px-based spacing rhythm. +- `--m3-shape-xs|sm|md|lg|xl|full` for corner radii. +- `--m3-elevation-0 โ€ฆ --m3-elevation-5` for the M3 shadow levels (the dark theme + raises them automatically). + +## Components + +`components.css` provides `.m3-btn` (filled/tonal/outlined/text/elevated), +`.m3-icon-button`, `.m3-fab`, `.m3-chip` / `.m3-chip-set`, `.m3-card`, +`.m3-list` / `.m3-list-item`, `.m3-menu`, `.m3-dialog`, `.m3-sheet`, `.m3-scrim`, +`.m3-tabs`, `.m3-segmented`, `.m3-switch`, `.m3-slider`, `.m3-text-field`, +`.m3-table`, `.m3-expansion`, `.m3-snackbar`, `.m3-tooltip`, `.m3-meter`, +`.m3-empty`, plus loaders and skeletons. All of them define hover, focus-visible, +pressed, disabled, loading and error states. + +## Behaviour hooks + +`ui.js` binds declarative attributes, so pages stay markup-only: + +| Hook | Purpose | +| --- | --- | +| `[data-m3-drawer-toggle="#id"]`, `[data-m3-drawer-legacy]` | open/close a navigation drawer | +| `[data-m3-scrim-for="#id"]` | scrim that closes its drawer | +| `[data-m3-menu-trigger="#id"]` | menu button + `aria-expanded` sync | +| `[data-m3-dialog-open="#id"]` / `[data-m3-dialog-close]` | dialogs | +| `[data-m3-tabs]`, `[data-m3-segmented]`, `[data-m3-chip-toggle]` | selection groups | +| `[data-m3-copy]`, `[data-m3-range-output]`, `[data-m3-color-picker]` | copy buttons, slider output, seed picker | +| `.m3-theme-toggle` | light/dark switch | +| `.m3-reveal` | scroll-in animation (respects `prefers-reduced-motion`) | +| `m3ui:refresh` (event) | re-scan after injecting markup | + +`M3UI` also exposes `snackbar`, `openDialog`, `closeDialog`, `openDrawer`, +`setLoading`, `copy`, `lockScroll` and `unlockScroll`; `M3Color` exposes +`applySeed`, `resetSeed`, `setTheme`, `toggleTheme`, `theme`, `preference`, +`seed`, `presets`, `role`, `mountPicker` and emits `m3color:theme` / +`m3color:seed`. + +## Accessibility + +- Light and dark palettes are generated so every `on-*` / surface pair clears + WCAG AA (โ‰ฅ 4.5:1); alternate seeds are checked the same way. +- Focus states use `:focus-visible` with a visible ring; dialogs and drawers are + labelled and manage `aria-hidden`/`aria-expanded`; toasts and the list grid are + `aria-live` regions; icon-only controls carry `aria-label`s. +- `prefers-reduced-motion` collapses animation and transition durations. + +## Print + +`site.css` and the page stylesheets trim chrome (app bar, drawers, action rows, +pagination, toasts) and switch to plain black-on-white surfaces for printing. + +## Brand, people and vendored assets + +Every asset the site needs is served from this repository. Nothing is loaded from a third-party CDN except the AdSense script. + +| Folder | Contents | Notes | +| --- | --- | --- | +| `assets/brand/` | `gdips-mark.svg` (master mark), `favicon.svg`, `favicon-32.png`, `apple-touch-icon.png`, `icon-192.png`, `icon-512.png`, `icon-maskable-512.png` | Icons are rendered from the SVG masters. Re-render them after editing the SVG. | +| `assets/people/` | One SVG avatar per contributor (`.svg`) | Initials on a tonal background. To use real photos, drop an image at the same path with the same name. | +| `assets/vendor/fontawesome/` | Font Awesome Free 6.4.0 CSS and the solid, regular and brands WOFF2 files | CC BY 4.0 icons, SIL OFL fonts, MIT code. See `LICENSE.txt`. | +| `assets/vendor/papaparse/` | PapaParse 5.3.2 (MIT) | Used by the demon list and feedback apps to read published Google Sheets CSV. | +| `assets/vendor/fonts/` | Roboto Flex and JetBrains Mono, variable WOFF2 (Latin) | Declared in `tokens.css` as `Roboto Flex` and `JetBrains Mono`. SIL OFL. | + +`sw.js` (site root) precaches the app shell and serves same-origin requests network-first. Cross-origin data, such as the Google Sheets CSV, is never cached by the service worker. diff --git a/main/assets/m3/color.js b/main/assets/m3/color.js new file mode 100644 index 0000000..ce0fda6 --- /dev/null +++ b/main/assets/m3/color.js @@ -0,0 +1,440 @@ +/* ============================================================================ + GDIPS ยท Material You 3 โ€” Dynamic colour runtime + ---------------------------------------------------------------------------- + Generates a full Material 3 role set from any seed colour at runtime, so the + whole site can re-theme itself (Material You "dynamic colour") without a + build step. Tonal palettes use CIELAB tone mapping with sRGB gamut + clamping โ€” the same algorithm used to pre-generate assets/m3/palettes.css. + + Public API + M3Color.applySeed(hex) apply an arbitrary seed colour + M3Color.seed() current seed (#RRGGBB) + M3Color.setTheme('light'|'dark'|'system') + M3Color.theme() resolved theme + M3Color.presets [{ id, label, seed }] + M3Color.mountPicker(el) render an accessible seed-colour picker + ========================================================================== */ + +(function (global) { + 'use strict'; + + var STORAGE = { theme: 'gdips:theme', seed: 'gdips:seed' }; + var LEGACY_THEME_KEY = 'theme'; // older GDIPS scripts store the theme here + var TONES = [0, 4, 5, 6, 10, 12, 17, 20, 22, 24, 25, 30, 35, 40, 50, 60, 70, 80, 87, 90, 92, 94, 95, 96, 98, 99, 100]; + + var PRESETS = [ + { id: 'brand', label: 'GDIPS Merah', seed: '#C8102E' }, + { id: 'indigo', label: 'Indigo', seed: '#6366F1' }, + { id: 'violet', label: 'Violet', seed: '#8B5CF6' }, + { id: 'azure', label: 'Azure', seed: '#2563EB' }, + { id: 'emerald', label: 'Emerald', seed: '#0F9D58' }, + { id: 'amber', label: 'Amber', seed: '#F59E0B' } + ]; + + /* โ”€โ”€ Colour maths โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ + + function srgbToLin(c) { + c /= 255; + return c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4); + } + + function linToSrgb(c) { + c = Math.min(1, Math.max(0, c)); + var v = c <= 0.0031308 ? 12.92 * c : 1.055 * Math.pow(c, 1 / 2.4) - 0.055; + return Math.round(Math.min(255, Math.max(0, v * 255))); + } + + function hexToRgb(hex) { + hex = String(hex).trim().replace('#', ''); + if (hex.length === 3) hex = hex.split('').map(function (c) { return c + c; }).join(''); + var n = parseInt(hex, 16); + return [(n >> 16) & 255, (n >> 8) & 255, n & 255]; + } + + function rgbToHex(rgb) { + return '#' + rgb.map(function (c) { + var s = c.toString(16).toUpperCase(); + return s.length === 1 ? '0' + s : s; + }).join(''); + } + + var WHITE = [0.95047, 1.0, 1.08883]; + + function rgbToLab(rgb) { + var r = srgbToLin(rgb[0]), g = srgbToLin(rgb[1]), b = srgbToLin(rgb[2]); + var x = (r * 0.4124564 + g * 0.3575761 + b * 0.1804375) / WHITE[0]; + var y = (r * 0.2126729 + g * 0.7151522 + b * 0.0721750) / WHITE[1]; + var z = (r * 0.0193339 + g * 0.1191920 + b * 0.9503041) / WHITE[2]; + function f(t) { return t > 216 / 24389 ? Math.cbrt(t) : (841 / 108) * t + 4 / 29; } + var fx = f(x), fy = f(y), fz = f(z); + return [116 * fy - 16, 500 * (fx - fy), 200 * (fy - fz)]; + } + + function labToRgb(lab) { + var fy = (lab[0] + 16) / 116; + var fx = fy + lab[1] / 500; + var fz = fy - lab[2] / 200; + function fi(t) { var t3 = t * t * t; return t3 > 216 / 24389 ? t3 : (t - 4 / 29) * (108 / 841); } + var x = fi(fx) * WHITE[0], y = fi(fy) * WHITE[1], z = fi(fz) * WHITE[2]; + return [ + linToSrgb(x * 3.2404542 + y * -1.5371385 + z * -0.4985314), + linToSrgb(x * -0.9692660 + y * 1.8760108 + z * 0.0415560), + linToSrgb(x * 0.0556434 + y * -0.2040259 + z * 1.0572252) + ]; + } + + function inGamut(lab) { + var fy = (lab[0] + 16) / 116; + var fx = fy + lab[1] / 500; + var fz = fy - lab[2] / 200; + function fi(t) { var t3 = t * t * t; return t3 > 216 / 24389 ? t3 : (t - 4 / 29) * (108 / 841); } + var x = fi(fx), y = fi(fy), z = fi(fz); + return x >= -1e-4 && x <= 1.0001 && y >= -1e-4 && y <= 1.0001 && z >= -1e-4 && z <= 1.0001; + } + + /** Hex for target CIELAB lightness, chroma reduced until inside sRGB. */ + function toneToHex(L, a, b) { + if (L >= 100) return '#FFFFFF'; + if (L <= 0) return '#000000'; + var lab = [L, a, b]; + if (inGamut(lab)) return rgbToHex(labToRgb(lab)); + var lo = 0, hi = 1, best = L > 50 ? [255, 255, 255] : [0, 0, 0]; + for (var i = 0; i < 20; i++) { + var mid = (lo + hi) / 2; + lab = [L, a * mid, b * mid]; + if (inGamut(lab)) { best = labToRgb(lab); lo = mid; } else { hi = mid; } + } + return rgbToHex(best); + } + + function tonalPalette(seed, chromaScale, hueOverride) { + var lab = rgbToLab(hexToRgb(seed)); + var hue = Math.atan2(lab[2], lab[1]); + var chroma = Math.hypot(lab[1], lab[2]) * (chromaScale === undefined ? 1 : chromaScale); + if (hueOverride !== undefined) hue = hueOverride; + var out = {}; + for (var i = 0; i < TONES.length; i++) { + var t = TONES[i]; + out[t] = toneToHex(t, chroma * Math.cos(hue), chroma * Math.sin(hue)); + } + return out; + } + + var ROLE_MAP_LIGHT = { + primary: ['primary', 40], 'on-primary': ['primary', 100], + 'primary-container': ['primary', 90], 'on-primary-container': ['primary', 10], + 'primary-fixed': ['primary', 90], 'primary-fixed-dim': ['primary', 80], + 'on-primary-fixed': ['primary', 10], 'on-primary-fixed-variant': ['primary', 30], + secondary: ['secondary', 40], 'on-secondary': ['secondary', 100], + 'secondary-container': ['secondary', 90], 'on-secondary-container': ['secondary', 10], + tertiary: ['tertiary', 40], 'on-tertiary': ['tertiary', 100], + 'tertiary-container': ['tertiary', 90], 'on-tertiary-container': ['tertiary', 10], + error: ['error', 40], 'on-error': ['error', 100], + 'error-container': ['error', 90], 'on-error-container': ['error', 10], + background: ['neutral', 98], 'on-background': ['neutral', 10], + surface: ['neutral', 98], 'on-surface': ['neutral', 10], + 'surface-variant': ['neutral-variant', 90], 'on-surface-variant': ['neutral-variant', 30], + 'surface-dim': ['neutral', 87], 'surface-bright': ['neutral', 98], + 'surface-container-lowest': ['neutral', 100], 'surface-container-low': ['neutral', 96], + 'surface-container': ['neutral', 94], 'surface-container-high': ['neutral', 92], + 'surface-container-highest': ['neutral', 90], + outline: ['neutral-variant', 50], 'outline-variant': ['neutral-variant', 80], + 'inverse-surface': ['neutral', 20], 'inverse-on-surface': ['neutral', 95], + 'inverse-primary': ['primary', 80], + scrim: ['neutral', 0], shadow: ['neutral', 0], 'surface-tint': ['primary', 40] + }; + + var DARK_OVERRIDES = { + primary: ['primary', 80], 'on-primary': ['primary', 20], + 'primary-container': ['primary', 30], 'on-primary-container': ['primary', 90], + secondary: ['secondary', 80], 'on-secondary': ['secondary', 20], + 'secondary-container': ['secondary', 30], 'on-secondary-container': ['secondary', 90], + tertiary: ['tertiary', 80], 'on-tertiary': ['tertiary', 20], + 'tertiary-container': ['tertiary', 30], 'on-tertiary-container': ['tertiary', 90], + error: ['error', 80], 'on-error': ['error', 20], + 'error-container': ['error', 30], 'on-error-container': ['error', 90], + background: ['neutral', 6], 'on-background': ['neutral', 90], + surface: ['neutral', 6], 'on-surface': ['neutral', 90], + 'surface-variant': ['neutral-variant', 30], 'on-surface-variant': ['neutral-variant', 80], + 'surface-dim': ['neutral', 6], 'surface-bright': ['neutral', 24], + 'surface-container-lowest': ['neutral', 4], 'surface-container-low': ['neutral', 10], + 'surface-container': ['neutral', 12], 'surface-container-high': ['neutral', 17], + 'surface-container-highest': ['neutral', 22], + outline: ['neutral-variant', 60], 'outline-variant': ['neutral-variant', 30], + 'inverse-surface': ['neutral', 90], 'inverse-on-surface': ['neutral', 20], + 'inverse-primary': ['primary', 40], 'surface-tint': ['primary', 80] + }; + + function roleMap(dark) { + var map = {}; + for (var k in ROLE_MAP_LIGHT) map[k] = ROLE_MAP_LIGHT[k]; + if (dark) for (var d in DARK_OVERRIDES) map[d] = DARK_OVERRIDES[d]; + return map; + } + + /** Build every M3 colour role for a seed colour. */ + /* WCAG relative luminance / contrast, used to keep container pairs readable. */ + function relLum(hex) { + var rgb = hexToRgb(hex), chan = []; + for (var i = 0; i < 3; i++) { + var v = rgb[i] / 255; + chan.push(v <= 0.04045 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4)); + } + return 0.2126 * chan[0] + 0.7152 * chan[1] + 0.0722 * chan[2]; + } + + function contrast(a, b) { + var la = relLum(a), lb = relLum(b), hi = Math.max(la, lb), lo = Math.min(la, lb); + return (hi + 0.05) / (lo + 0.05); + } + + function buildScheme(seed, dark) { + var primary = tonalPalette(seed, 1); + var secondary = tonalPalette(seed, 0.34); + var seedLab = rgbToLab(hexToRgb(seed)); + var tertiary = tonalPalette(seed, 0.72, Math.atan2(seedLab[2], seedLab[1]) + Math.PI / 3); + var error = tonalPalette('#B3261E'); + var hue = Math.atan2(seedLab[2], seedLab[1]); + var neutral = tonalPalette(seed, 0); + var neutralVariant = tonalPalette(seed, 0); + TONES.forEach(function (t) { + neutral[t] = toneToHex(t, 3.2 * Math.cos(hue), 3.2 * Math.sin(hue)); + neutralVariant[t] = toneToHex(t, 9 * Math.cos(hue), 9 * Math.sin(hue)); + }); + var maps = { primary: primary, secondary: secondary, tertiary: tertiary, error: error, neutral: neutral, 'neutral-variant': neutralVariant }; + var map = roleMap(dark); + var out = {}; + Object.keys(map).forEach(function (role) { + var ref = map[role]; + var tone = ref[1]; + if (tone === 100) out['--m3-' + role] = '#FFFFFF'; + else if (tone === 0) out['--m3-' + role] = '#000000'; + else out['--m3-' + role] = maps[ref[0]][tone]; + }); + + /* Dark container roles default to tone 30; bright hues (crimson, amber) can + fall short of 4.5:1 against their tone-90 label, so step the container + down the tonal ramp until the pair stays readable. */ + if (dark) { + [['primary-container', 'on-primary-container'], + ['secondary-container', 'on-secondary-container'], + ['tertiary-container', 'on-tertiary-container'], + ['error-container', 'on-error-container']].forEach(function (pair) { + var ref = map[pair[0]]; + if (!ref) return; + var label = out['--m3-' + pair[1]]; + [ref[1], 25, 22, 20, 17, 12].some(function (tone) { + var value = tone === 100 ? '#FFFFFF' : (tone === 0 ? '#000000' : maps[ref[0]][tone]); + if (!value) return false; + if (contrast(value, label) >= 4.5) { out['--m3-' + pair[0]] = value; return true; } + return false; + }); + }); + } + + return out; + } + + /* โ”€โ”€ State โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ + + var media = global.matchMedia ? global.matchMedia('(prefers-color-scheme: dark)') : null; + var root = document.documentElement; + + function read(key) { + try { return global.localStorage.getItem(key); } catch (e) { return null; } + } + + function write(key, value) { + try { value === null ? global.localStorage.removeItem(key) : global.localStorage.setItem(key, value); } catch (e) { /* private mode */ } + } + + function isHex(value) { + return typeof value === 'string' && /^#?([0-9a-f]{3}|[0-9a-f]{6})$/i.test(value.trim()); + } + + /* The data-seed attribute doubles as a *named* palette selector + (e.g. data-seed="indigo" is delivered by palettes.css) and as an inline hex + seed. Only hex values are generated at runtime; named seeds stay in CSS. */ + var attrSeed = root.getAttribute('data-seed'); + var state = { + theme: read(STORAGE.theme) || read(LEGACY_THEME_KEY) || 'system', + seed: read(STORAGE.seed) || (isHex(attrSeed) ? attrSeed.toUpperCase() : null) + }; + + function resolvedTheme() { + if (state.theme === 'system') return media && media.matches ? 'dark' : 'light'; + return state.theme; + } + + function applyVars(vars) { + Object.keys(vars).forEach(function (k) { root.style.setProperty(k, vars[k]); }); + } + + function syncMetaTheme() { + var meta = document.querySelector('meta[name="theme-color"]'); + var color = getComputedStyle(document.body || root).getPropertyValue('--m3-surface').trim(); + if (!meta) { + meta = document.createElement('meta'); + meta.setAttribute('name', 'theme-color'); + document.head.appendChild(meta); + } + if (color) meta.setAttribute('content', color); + } + + var appliedVars = []; + + function clearVars() { + appliedVars.forEach(function (key) { root.style.removeProperty(key); }); + appliedVars = []; + } + + function paint() { + var theme = resolvedTheme(); + root.setAttribute('data-theme', theme); + if (state.seed) { + var vars = buildScheme(state.seed, theme === 'dark'); + clearVars(); + appliedVars = Object.keys(vars); + applyVars(vars); + } else { + clearVars(); // fall back to the palette declared in palettes.css + } + syncMetaTheme(); + } + + function announce(type, detail) { + root.dispatchEvent(new CustomEvent('m3color:' + type, { detail: detail })); + } + + var api = { + presets: PRESETS, + + seed: function () { return state.seed; }, + theme: function () { return resolvedTheme(); }, + preference: function () { return state.theme; }, + + /** Apply an arbitrary seed colour (#RGB / #RRGGBB). */ + applySeed: function (seed, options) { + var hex = String(seed || '').trim(); + if (!isHex(hex)) return false; + if (hex.charAt(0) !== '#') hex = '#' + hex; + state.seed = hex.toUpperCase(); + if (!options || options.persist !== false) write(STORAGE.seed, state.seed); + paint(); + announce('seed', { seed: state.seed }); + return true; + }, + + /** Drop the custom seed and return to the page's declared palette. */ + resetSeed: function () { + state.seed = isHex(attrSeed) ? attrSeed.toUpperCase() : null; + write(STORAGE.seed, null); + paint(); + announce('seed', { seed: state.seed }); + }, + + /** light ยท dark ยท system */ + setTheme: function (mode) { + state.theme = ['light', 'dark', 'system'].indexOf(mode) === -1 ? 'system' : mode; + write(STORAGE.theme, state.theme); + write(LEGACY_THEME_KEY, state.theme); + paint(); + announce('theme', { theme: resolvedTheme(), preference: state.theme }); + }, + + toggleTheme: function () { + api.setTheme(resolvedTheme() === 'dark' ? 'light' : 'dark'); + return resolvedTheme(); + }, + + /** Read a generated role, e.g. M3Color.role('primary') */ + role: function (name) { + return getComputedStyle(root).getPropertyValue('--m3-' + name).trim(); + }, + + /** Render an accessible dynamic-colour picker inside `el`. */ + mountPicker: function (el) { + if (!el) return; + el.innerHTML = ''; + el.classList.add('m3-color-picker'); + + var row = document.createElement('div'); + row.className = 'm3-chip-set'; + row.setAttribute('role', 'radiogroup'); + row.setAttribute('aria-label', 'Dynamic colour'); + + PRESETS.forEach(function (preset) { + var chip = document.createElement('button'); + chip.type = 'button'; + chip.className = 'm3-chip m3-chip--accent'; + chip.dataset.seed = preset.seed; + chip.dataset.id = preset.seed === '#C8102E' ? '' : preset.id; + chip.setAttribute('role', 'radio'); + chip.setAttribute('aria-label', preset.label); + chip.innerHTML = '' + preset.label + ''; + chip.addEventListener('click', function () { api.applySeed(preset.seed); mark(); }); + row.appendChild(chip); + }); + + var custom = document.createElement('label'); + custom.className = 'm3-chip m3-chip--sm'; + custom.style.cursor = 'pointer'; + custom.innerHTML = 'Custom' + + ''; + custom.querySelector('input').addEventListener('input', function (e) { + api.applySeed(e.target.value); + mark(); + }); + row.appendChild(custom); + + el.appendChild(row); + + function mark() { + var chips = row.querySelectorAll('.m3-chip[data-seed]'); + var named = root.getAttribute('data-seed') || ''; + Array.prototype.forEach.call(chips, function (chip) { + var active = state.seed + ? chip.dataset.seed.toLowerCase() === state.seed.toLowerCase() + : chip.dataset.id === named; + chip.setAttribute('aria-checked', String(active)); + chip.classList.toggle('is-selected', active); + }); + } + + mark(); + root.addEventListener('m3color:seed', mark); + return el; + } + }; + + /* Pages that manage their own toggle (the demon list) simply set + ; adopt those changes so both systems stay in sync. */ + if (global.MutationObserver) { + new MutationObserver(function () { + var value = root.getAttribute('data-theme'); + if (value !== 'light' && value !== 'dark') return; + if (value === resolvedTheme() && state.theme !== 'system') return; + state.theme = value; + write(STORAGE.theme, value); + write(LEGACY_THEME_KEY, value); + paint(); + }).observe(root, { attributes: true, attributeFilter: ['data-theme'] }); + } + + if (media) { + var onSystem = function () { if (state.theme === 'system') paint(); }; + media.addEventListener ? media.addEventListener('change', onSystem) : media.addListener(onSystem); + } + + root.addEventListener('m3color:theme', function () { syncMetaTheme(); }); + + paint(); + global.M3Color = api; + + // Upgrade every declarative picker on the page. + document.addEventListener('DOMContentLoaded', function () { + document.querySelectorAll('[data-m3-color-picker]').forEach(function (el) { api.mountPicker(el); }); + }); +})(window); diff --git a/main/assets/m3/components.css b/main/assets/m3/components.css new file mode 100644 index 0000000..7c40344 --- /dev/null +++ b/main/assets/m3/components.css @@ -0,0 +1,1749 @@ +/* ============================================================================ + GDIPS ยท Material You 3 โ€” Components + ---------------------------------------------------------------------------- + A hand-written, dependency-free Material 3 component layer. Everything is + driven by the tokens in tokens.css + palettes.css, so all components adapt to + the active dynamic colour scheme and theme automatically. + + Contents + 01 State layer 08 Checkbox / Radio / Switch + 02 Buttons 09 Slider + 03 Icon buttons / FAB 10 Lists + 04 Segmented buttons 11 Menus + 05 Cards 12 Dialogs & sheets + 06 Chips 13 Snackbar / tooltip / banner + 07 Text fields & selects 14 Tabs / nav bar / rail / drawer / app bar + 15 Tables, progress, badges, misc + ========================================================================== */ + +/* ============================================================================ + 01 ยท State layer + A reusable overlay that gives every interactive surface M3 hover / focus / + pressed states without hard-coding colours. + ========================================================================== */ + +.m3-state-layer { + position: relative; + isolation: isolate; + overflow: hidden; +} + +.m3-state-layer::after { + content: ''; + position: absolute; + inset: 0; + background: currentColor; + opacity: 0; + pointer-events: none; + border-radius: inherit; + transition: opacity var(--m3-duration-short) var(--m3-ease-standard); +} + +@media (hover: hover) { + .m3-state-layer:hover::after { opacity: var(--m3-state-hover); } +} + +.m3-state-layer:focus-visible::after { opacity: var(--m3-state-focus); } +.m3-state-layer:active::after { opacity: var(--m3-state-pressed); } +.m3-state-layer[aria-disabled='true']::after, +.m3-state-layer:disabled::after { opacity: 0; } + +/* Ripple -------------------------------------------------------------------- */ +.m3-ripple { + position: absolute; + border-radius: var(--m3-shape-full); + transform: scale(0); + background: currentColor; + opacity: 0.24; + pointer-events: none; + animation: m3-ripple-in 550ms var(--m3-ease-standard-decel) forwards; +} + +@keyframes m3-ripple-in { + to { transform: scale(1); opacity: 0; } +} + +/* ============================================================================ + 02 ยท Buttons + Variants: filled (default) ยท tonal ยท elevated ยท outlined ยท text + ========================================================================== */ + +.m3-button { + --m3-button-height: 40px; + --m3-button-pad: 24px; + --m3-button-gap: 8px; + position: relative; + display: inline-flex; + align-items: center; + justify-content: center; + gap: var(--m3-button-gap); + min-height: var(--m3-button-height); + padding: 0 var(--m3-button-pad); + border: 1px solid transparent; + border-radius: var(--m3-shape-full); + font-family: var(--m3-font-plain); + font-size: var(--m3-label-large-size); + line-height: var(--m3-label-large-line); + font-weight: var(--m3-label-large-weight); + letter-spacing: var(--m3-tracking-label); + text-decoration: none; + white-space: nowrap; + cursor: pointer; + user-select: none; + isolation: isolate; + overflow: hidden; + background: var(--m3-primary); + color: var(--m3-on-primary); + box-shadow: var(--m3-elevation-0); + transition: + background-color var(--m3-duration-short) var(--m3-ease-standard), + color var(--m3-duration-short) var(--m3-ease-standard), + box-shadow var(--m3-duration-short-2) var(--m3-ease-standard), + border-radius var(--m3-duration-short-2) var(--m3-ease-emphasized), + transform var(--m3-duration-short-2) var(--m3-ease-emphasized); +} + +.m3-button::after { + content: ''; + position: absolute; + inset: 0; + background: currentColor; + opacity: 0; + transition: opacity var(--m3-duration-short) var(--m3-ease-standard); +} + +@media (hover: hover) { + .m3-button:hover::after { opacity: var(--m3-state-hover); } +} + +.m3-button:focus-visible::after { opacity: var(--m3-state-focus); } +.m3-button:active::after { opacity: var(--m3-state-pressed); } +.m3-button:active { transform: scale(0.97); } + +.m3-button > * { position: relative; z-index: 1; } +.m3-button i, +.m3-button svg { font-size: 1.125em; } + +.m3-button--tonal { + background: var(--m3-secondary-container); + color: var(--m3-on-secondary-container); +} + +.m3-button--elevated { + background: var(--m3-surface-container-low); + color: var(--m3-primary); + box-shadow: var(--m3-elevation-1); +} + +@media (hover: hover) { + .m3-button--elevated:hover { box-shadow: var(--m3-elevation-2); } +} + +.m3-button--outlined { + background: transparent; + color: var(--m3-primary); + border-color: var(--m3-outline-variant); +} + +.m3-button--text { + background: transparent; + color: var(--m3-primary); + padding-inline: 12px; +} + +.m3-button--danger { + background: var(--m3-error); + color: var(--m3-on-error); +} + +.m3-button--danger-text { + background: transparent; + color: var(--m3-error); +} + +.m3-button--full { width: 100%; } +.m3-button--lg { --m3-button-height: 48px; --m3-button-pad: 28px; font-size: var(--m3-title-small-size); } +.m3-button--sm { --m3-button-height: 32px; --m3-button-pad: 16px; font-size: var(--m3-label-medium-size); } + +.m3-button:disabled, +.m3-button[aria-disabled='true'] { + background: color-mix(in srgb, var(--m3-on-surface) 12%, transparent); + color: color-mix(in srgb, var(--m3-on-surface) 38%, transparent); + box-shadow: none; + border-color: transparent; + transform: none; + pointer-events: none; +} + +.m3-button.is-loading { + color: transparent; + pointer-events: none; +} + +.m3-button.is-loading::before { + content: ''; + position: absolute; + inset-inline: 0; + margin-inline: auto; + width: 18px; + height: 18px; + border-radius: 50%; + border: 2px solid currentColor; + border-top-color: transparent; + color: var(--m3-on-primary); + animation: m3-spin 900ms linear infinite; +} + +.m3-button--tonal.is-loading::before, +.m3-button--outlined.is-loading::before, +.m3-button--text.is-loading::before, +.m3-button--elevated.is-loading::before { color: var(--m3-primary); } + +.m3-button--outlined.is-loading::before, +.m3-button--text.is-loading::before { color: var(--m3-primary); } + +.m3-button-group { display: inline-flex; gap: 8px; flex-wrap: wrap; } + +@keyframes m3-spin { + to { transform: rotate(360deg); } +} + +/* ============================================================================ + 03 ยท Icon buttons & FABs + ========================================================================== */ + +.m3-icon-button { + position: relative; + display: inline-flex; + align-items: center; + justify-content: center; + width: 40px; + height: 40px; + padding: 0; + border: 1px solid transparent; + border-radius: var(--m3-shape-full); + background: transparent; + color: var(--m3-on-surface-variant); + font-size: 1.15rem; + cursor: pointer; + isolation: isolate; + overflow: hidden; + text-decoration: none; + transition: + background-color var(--m3-duration-short) var(--m3-ease-standard), + color var(--m3-duration-short) var(--m3-ease-standard), + transform var(--m3-duration-short-2) var(--m3-ease-emphasized); +} + +.m3-icon-button::after { + content: ''; + position: absolute; + inset: 0; + background: currentColor; + opacity: 0; + transition: opacity var(--m3-duration-short) var(--m3-ease-standard); +} + +@media (hover: hover) { .m3-icon-button:hover::after { opacity: var(--m3-state-hover); } } +.m3-icon-button:focus-visible::after { opacity: var(--m3-state-focus); } +.m3-icon-button:active::after { opacity: var(--m3-state-pressed); } +.m3-icon-button:active { transform: scale(0.92); } +.m3-icon-button > * { position: relative; z-index: 1; } + +.m3-icon-button--filled { + background: var(--m3-primary); + color: var(--m3-on-primary); +} + +.m3-icon-button--tonal { + background: var(--m3-secondary-container); + color: var(--m3-on-secondary-container); +} + +.m3-icon-button--outlined { border-color: var(--m3-outline-variant); } +.m3-icon-button--selected { background: var(--m3-primary); color: var(--m3-on-primary); } +.m3-icon-button--lg { width: 48px; height: 48px; font-size: 1.35rem; } +.m3-icon-button--sm { width: 32px; height: 32px; font-size: 1rem; } + +.m3-icon-button:disabled { + color: color-mix(in srgb, var(--m3-on-surface) 38%, transparent); + pointer-events: none; +} + +/* FAB ----------------------------------------------------------------------- */ +.m3-fab { + position: relative; + display: inline-flex; + align-items: center; + justify-content: center; + gap: 12px; + height: 56px; + min-width: 56px; + padding-inline: 16px; + border: none; + border-radius: var(--m3-shape-lg); + background: var(--m3-primary-container); + color: var(--m3-on-primary-container); + font-size: 1.5rem; + box-shadow: var(--m3-elevation-3); + cursor: pointer; + isolation: isolate; + overflow: hidden; + transition: + box-shadow var(--m3-duration-short-2) var(--m3-ease-standard), + transform var(--m3-duration-short-2) var(--m3-ease-emphasized), + border-radius var(--m3-duration-short-2) var(--m3-ease-emphasized); +} + +.m3-fab::after { + content: ''; + position: absolute; + inset: 0; + background: currentColor; + opacity: 0; + transition: opacity var(--m3-duration-short) var(--m3-ease-standard); +} + +@media (hover: hover) { + .m3-fab:hover::after { opacity: var(--m3-state-hover); } + .m3-fab:hover { box-shadow: var(--m3-elevation-4); } +} + +.m3-fab:active { transform: scale(0.96); } +.m3-fab:active::after { opacity: var(--m3-state-pressed); } +.m3-fab > * { position: relative; z-index: 1; } +.m3-fab--extended { + width: auto; + padding-inline: 20px; + font-family: var(--m3-font-plain); + font-size: var(--m3-label-large-size); + font-weight: var(--m3-label-large-weight); + letter-spacing: var(--m3-tracking-label); +} +.m3-fab--sm { height: 40px; min-width: 40px; font-size: 1.15rem; border-radius: var(--m3-shape-md); } +.m3-fab--lg { height: 96px; min-width: 96px; font-size: 2.25rem; border-radius: var(--m3-shape-xl); } +.m3-fab--fixed { position: fixed; inset-block-end: 24px; inset-inline-end: 24px; z-index: var(--m3-z-appbar); } + +/* ============================================================================ + 04 ยท Segmented buttons + ========================================================================== */ + +.m3-segmented { + display: inline-flex; + align-items: stretch; + border: 1px solid var(--m3-outline); + border-radius: var(--m3-shape-full); + overflow: hidden; + background: transparent; + max-width: 100%; +} + +.m3-segmented__item { + position: relative; + display: inline-flex; + align-items: center; + justify-content: center; + gap: 8px; + flex: 1 1 auto; + min-height: 40px; + padding-inline: 16px; + border: none; + border-inline-start: 1px solid var(--m3-outline); + background: transparent; + color: var(--m3-on-surface); + font-size: var(--m3-label-large-size); + font-weight: var(--m3-label-large-weight); + letter-spacing: var(--m3-tracking-label); + white-space: nowrap; + cursor: pointer; + isolation: isolate; + overflow: hidden; + transition: background-color var(--m3-duration-short) var(--m3-ease-standard); +} + +.m3-segmented__item:first-child { border-inline-start: none; } + +.m3-segmented__item::after { + content: ''; + position: absolute; + inset: 0; + background: currentColor; + opacity: 0; + transition: opacity var(--m3-duration-short) var(--m3-ease-standard); +} + +@media (hover: hover) { .m3-segmented__item:hover::after { opacity: var(--m3-state-hover); } } +.m3-segmented__item:focus-visible::after { opacity: var(--m3-state-focus); } +.m3-segmented__item:active::after { opacity: var(--m3-state-pressed); } +.m3-segmented__item[aria-selected='true'], +.m3-segmented__item.is-selected { + background: var(--m3-secondary-container); + color: var(--m3-on-secondary-container); +} +.m3-segmented__item > * { position: relative; z-index: 1; } + +/* ============================================================================ + 05 ยท Cards + ========================================================================== */ + +.m3-card { + position: relative; + display: flex; + flex-direction: column; + border-radius: var(--m3-shape-md); + background: var(--m3-surface-container-low); + color: var(--m3-on-surface); + overflow: hidden; + transition: + box-shadow var(--m3-duration-short-2) var(--m3-ease-standard), + background-color var(--m3-duration-short) var(--m3-ease-standard), + transform var(--m3-duration-short-2) var(--m3-ease-emphasized); +} + +.m3-card--elevated { background: var(--m3-surface-container-low); box-shadow: var(--m3-elevation-1); } +.m3-card--filled { background: var(--m3-surface-container-highest); } +.m3-card--outlined { background: var(--m3-surface); border: 1px solid var(--m3-outline-variant); } + +@media (hover: hover) { + .m3-card--elevated:hover, + .m3-card--interactive:hover { box-shadow: var(--m3-elevation-2); } + .m3-card--interactive:hover { transform: translateY(-2px); } +} + +.m3-card--interactive { cursor: pointer; } +.m3-card--interactive:active { transform: translateY(0) scale(0.995); } + +.m3-card__media { + position: relative; + aspect-ratio: 16 / 9; + background: var(--m3-surface-container-highest); + overflow: hidden; +} + +.m3-card__media img, +.m3-card__media iframe { + width: 100%; + height: 100%; + object-fit: cover; +} + +.m3-card__content { + display: flex; + flex-direction: column; + gap: var(--m3-space-2); + padding: var(--m3-space-4); +} + +.m3-card__title { font-size: var(--m3-title-medium-size); font-weight: var(--m3-title-medium-weight); letter-spacing: var(--m3-tracking-title); } +.m3-card__subtitle { color: var(--m3-on-surface-variant); font-size: var(--m3-body-medium-size); } +.m3-card__text { color: var(--m3-on-surface-variant); font-size: var(--m3-body-medium-size); } +.m3-card__actions { + display: flex; + flex-wrap: wrap; + gap: var(--m3-space-2); + padding: var(--m3-space-4); + padding-top: 0; + margin-top: auto; +} +.m3-card__actions--end { justify-content: flex-end; } + +.m3-card--accent::before { + content: ''; + position: absolute; + inset-block-start: 0; + inset-inline: 0; + height: 4px; + background: linear-gradient(90deg, var(--m3-primary), var(--m3-tertiary)); +} + +/* ============================================================================ + 06 ยท Chips + ========================================================================== */ + +.m3-chip-set { display: flex; flex-wrap: wrap; gap: 8px; } + +.m3-chip { + position: relative; + display: inline-flex; + align-items: center; + gap: 8px; + height: 32px; + padding-inline: 12px; + border: 1px solid var(--m3-outline-variant); + border-radius: var(--m3-shape-sm); + background: transparent; + color: var(--m3-on-surface-variant); + font-size: var(--m3-label-large-size); + font-weight: var(--m3-label-large-weight); + letter-spacing: var(--m3-tracking-label); + cursor: pointer; + text-decoration: none; + isolation: isolate; + overflow: hidden; + transition: background-color var(--m3-duration-short) var(--m3-ease-standard); +} + +.m3-chip::after { + content: ''; + position: absolute; + inset: 0; + background: currentColor; + opacity: 0; + transition: opacity var(--m3-duration-short) var(--m3-ease-standard); +} + +@media (hover: hover) { .m3-chip:hover::after { opacity: var(--m3-state-hover); } } +.m3-chip:focus-visible::after { opacity: var(--m3-state-focus); } +.m3-chip:active::after { opacity: var(--m3-state-pressed); } +.m3-chip > * { position: relative; z-index: 1; } +.m3-chip--selected, +.m3-chip[aria-pressed='true'], +.m3-chip[aria-selected='true'] { + background: var(--m3-secondary-container); + color: var(--m3-on-secondary-container); + border-color: transparent; +} +.m3-chip--assist { border-color: var(--m3-outline); } +.m3-chip--sm { height: 26px; padding-inline: 10px; font-size: var(--m3-label-medium-size); } +.m3-chip--accent { + background: var(--m3-primary-container); + color: var(--m3-on-primary-container); + border-color: transparent; +} + +/* ============================================================================ + 07 ยท Text fields & selects + ========================================================================== */ + +.m3-field { + display: flex; + flex-direction: column; + gap: 4px; + min-width: 0; +} + +.m3-field__box { + position: relative; + display: flex; + align-items: center; + gap: 8px; + min-height: 56px; + padding-inline: 16px; + border-radius: var(--m3-shape-xs) var(--m3-shape-xs) 0 0; + background: var(--m3-surface-container-highest); + border-bottom: 1px solid var(--m3-on-surface-variant); + transition: + background-color var(--m3-duration-short) var(--m3-ease-standard), + border-color var(--m3-duration-short) var(--m3-ease-standard); +} + +.m3-field__box::after { + content: ''; + position: absolute; + inset-block-end: -1px; + inset-inline: 0; + height: 2px; + background: var(--m3-primary); + transform: scaleX(0); + transition: transform var(--m3-duration-short-2) var(--m3-ease-emphasized-decel); +} + +.m3-field__box:hover::after { transform: scaleX(1); opacity: 0.4; } +.m3-field__box:focus-within::after { transform: scaleX(1); opacity: 1; } + +.m3-field__input { + flex: 1 1 auto; + width: 100%; + min-width: 0; + padding: 20px 0 6px; + border: none; + background: transparent; + color: var(--m3-on-surface); + font-size: var(--m3-body-large-size); + outline: none; +} + +.m3-field__label { + position: absolute; + inset-inline-start: 16px; + inset-block-start: 50%; + translate: 0 -50%; + color: var(--m3-on-surface-variant); + font-size: var(--m3-body-large-size); + pointer-events: none; + transform-origin: left top; + transition: + transform var(--m3-duration-short-2) var(--m3-ease-emphasized-decel), + color var(--m3-duration-short) var(--m3-ease-standard); +} + +.m3-field__box:focus-within .m3-field__label, +.m3-field__input:not(:placeholder-shown) + .m3-field__label, +.m3-field__input:focus + .m3-field__label, +.m3-field--filled .m3-field__label, +.m3-field__box.has-value .m3-field__label, +.m3-field__select.has-value ~ .m3-field__label { + transform: translateY(-14px) scale(0.78); +} + +.m3-field__icon { color: var(--m3-on-surface-variant); font-size: 1.05rem; } +.m3-field__suffix { color: var(--m3-on-surface-variant); font-size: var(--m3-body-medium-size); white-space: nowrap; } +.m3-field__support { + padding-inline: 16px; + color: var(--m3-on-surface-variant); + font-size: var(--m3-body-small-size); + line-height: var(--m3-body-small-line); +} + +.m3-field__input::placeholder { color: transparent; } + +textarea.m3-field__input { + padding-top: 22px; + resize: vertical; + min-height: 96px; + line-height: 1.5; +} + +select.m3-field__input { + appearance: none; + padding-inline-end: 24px; + cursor: pointer; +} + +.m3-field__chevron { + position: absolute; + inset-inline-end: 16px; + color: var(--m3-on-surface-variant); + pointer-events: none; +} + +/* Outlined variant ---------------------------------------------------------- */ +.m3-field--outlined .m3-field__box { + border: 1px solid var(--m3-outline); + border-radius: var(--m3-shape-xs); + background: transparent; + padding-block: 0; +} + +.m3-field--outlined .m3-field__box::after { display: none; } +.m3-field--outlined .m3-field__box:hover { border-color: var(--m3-on-surface); } +.m3-field--outlined .m3-field__box:focus-within { + border-color: var(--m3-primary); + box-shadow: inset 0 0 0 1px var(--m3-primary); +} +.m3-field--outlined .m3-field__input { padding-block: 16px; } +.m3-field--outlined .m3-field__label { + inset-block-start: 0; + translate: 0 -50%; + padding-inline: 4px; + background: var(--m3-surface); + border-radius: 2px; + font-size: var(--m3-body-medium-size); +} + +/* Error state --------------------------------------------------------------- */ +.m3-field--error .m3-field__box { border-color: var(--m3-error); } +.m3-field--error .m3-field__box::after { background: var(--m3-error); opacity: 1; } +.m3-field--error .m3-field__support, +.m3-field--error .m3-field__label, +.m3-field--error .m3-field__icon { color: var(--m3-error); } + +.m3-field--disabled { opacity: 0.38; pointer-events: none; } + +/* Search bar (M3 "search bar" surface) -------------------------------------- */ +.m3-search-bar { + display: flex; + align-items: center; + gap: 12px; + width: 100%; + height: 56px; + padding-inline: 16px; + border: 1px solid transparent; + border-radius: var(--m3-shape-full); + background: var(--m3-surface-container-high); + color: var(--m3-on-surface-variant); + box-shadow: var(--m3-elevation-1); + transition: box-shadow var(--m3-duration-short-2) var(--m3-ease-standard), background-color var(--m3-duration-short) var(--m3-ease-standard); +} + +.m3-search-bar:focus-within { + background: var(--m3-surface-container-highest); + box-shadow: var(--m3-elevation-2); +} + +.m3-search-bar input { + flex: 1 1 auto; + min-width: 0; + border: none; + background: transparent; + outline: none; + color: var(--m3-on-surface); + font-size: var(--m3-body-large-size); +} + +.m3-search-bar input::placeholder { color: var(--m3-on-surface-variant); } + +/* ============================================================================ + 08 ยท Checkbox / Radio / Switch + ========================================================================== */ + +.m3-check { + display: inline-flex; + align-items: center; + gap: 12px; + min-height: 40px; + cursor: pointer; + font-size: var(--m3-body-medium-size); + color: var(--m3-on-surface); +} + +.m3-check input { + appearance: none; + flex: 0 0 auto; + width: 18px; + height: 18px; + margin: 0; + border: 2px solid var(--m3-on-surface-variant); + border-radius: 2px; + background: transparent; + cursor: pointer; + position: relative; + transition: background-color var(--m3-duration-short) var(--m3-ease-standard), border-color var(--m3-duration-short) var(--m3-ease-standard); +} + +.m3-check input::after { + content: ''; + position: absolute; + inset: -14px; + border-radius: 50%; + background: var(--m3-primary); + opacity: 0; + transition: opacity var(--m3-duration-short) var(--m3-ease-standard); + z-index: -1; +} + +@media (hover: hover) { .m3-check:hover input::after { opacity: var(--m3-state-hover); } } +.m3-check input:focus-visible { outline: 2px solid var(--m3-primary); outline-offset: 3px; } +.m3-check input:checked { + background: var(--m3-primary); + border-color: var(--m3-primary); +} +.m3-check input:checked::before { + content: ''; + position: absolute; + inset-inline-start: 4.5px; + inset-block-start: 1px; + width: 5px; + height: 9px; + border: solid var(--m3-on-primary); + border-width: 0 2px 2px 0; + transform: rotate(45deg); +} +.m3-check input:disabled { opacity: 0.38; pointer-events: none; } + +.m3-check--radio input { border-radius: 50%; } +.m3-check--radio input:checked { background: transparent; border-color: var(--m3-primary); } +.m3-check--radio input:checked::before { + inset: 3px; + width: auto; + height: auto; + border: none; + border-radius: 50%; + background: var(--m3-primary); + transform: none; +} + +.m3-switch { + display: inline-flex; + align-items: center; + gap: 12px; + cursor: pointer; + font-size: var(--m3-body-medium-size); +} + +.m3-switch input { + appearance: none; + position: relative; + flex: 0 0 auto; + width: 52px; + height: 32px; + margin: 0; + border: 2px solid var(--m3-outline); + border-radius: var(--m3-shape-full); + background: var(--m3-surface-container-highest); + cursor: pointer; + transition: background-color var(--m3-duration-short-2) var(--m3-ease-standard), border-color var(--m3-duration-short-2) var(--m3-ease-standard); +} + +.m3-switch input::before { + content: ''; + position: absolute; + inset-block-start: 50%; + inset-inline-start: 5px; + translate: 0 -50%; + width: 16px; + height: 16px; + border-radius: 50%; + background: var(--m3-outline); + transition: width var(--m3-duration-short-2) var(--m3-ease-emphasized), height var(--m3-duration-short-2) var(--m3-ease-emphasized), inset-inline-start var(--m3-duration-short-2) var(--m3-ease-emphasized), background-color var(--m3-duration-short-2) var(--m3-ease-standard); +} + +.m3-switch input:checked { + background: var(--m3-primary); + border-color: var(--m3-primary); +} + +.m3-switch input:checked::before { + inset-inline-start: 24px; + width: 24px; + height: 24px; + background: var(--m3-on-primary); +} + +@media (hover: hover) { + .m3-switch:hover input::before { width: 20px; height: 20px; } + .m3-switch:hover input:checked::before { inset-inline-start: 20px; width: 28px; height: 28px; } +} + +.m3-switch input:focus-visible { outline: 2px solid var(--m3-primary); outline-offset: 3px; } +.m3-switch input:disabled { opacity: 0.38; pointer-events: none; } + +/* ============================================================================ + 09 ยท Slider + ========================================================================== */ + +.m3-slider { + --m3-slider-fill: 50%; + appearance: none; + width: 100%; + height: 32px; + background: transparent; + cursor: pointer; +} + +.m3-slider::-webkit-slider-runnable-track { + height: 16px; + border-radius: var(--m3-shape-full); + background: + linear-gradient(var(--m3-primary), var(--m3-primary)) 0 / var(--m3-slider-fill) 100% no-repeat, + var(--m3-surface-container-highest); +} + +.m3-slider::-moz-range-track { + height: 16px; + border-radius: var(--m3-shape-full); + background: var(--m3-surface-container-highest); +} + +.m3-slider::-moz-range-progress { + height: 16px; + border-radius: var(--m3-shape-full); + background: var(--m3-primary); +} + +.m3-slider::-webkit-slider-thumb { + appearance: none; + width: 6px; + height: 24px; + margin-top: -4px; + border-radius: var(--m3-shape-full); + background: var(--m3-primary); + border: 2px solid var(--m3-primary); + box-shadow: 0 0 0 0 color-mix(in srgb, var(--m3-primary) 16%, transparent); + transition: box-shadow var(--m3-duration-short) var(--m3-ease-standard), height var(--m3-duration-short) var(--m3-ease-emphasized); +} + +.m3-slider::-moz-range-thumb { + width: 6px; + height: 24px; + border-radius: var(--m3-shape-full); + background: var(--m3-primary); + border: none; +} + +.m3-slider:hover::-webkit-slider-thumb { box-shadow: 0 0 0 6px color-mix(in srgb, var(--m3-primary) 12%, transparent); } +.m3-slider:active::-webkit-slider-thumb { height: 28px; margin-top: -6px; } +.m3-slider:focus-visible { outline: none; } +.m3-slider:focus-visible::-webkit-slider-thumb { box-shadow: 0 0 0 10px color-mix(in srgb, var(--m3-primary) 16%, transparent); } + +/* ============================================================================ + 10 ยท Lists + ========================================================================== */ + +.m3-list { + display: flex; + flex-direction: column; + padding: var(--m3-space-2) 0; + list-style: none; + margin: 0; +} + +.m3-list-item { + position: relative; + display: flex; + align-items: center; + gap: var(--m3-space-4); + min-height: 56px; + padding: var(--m3-space-2) var(--m3-space-4); + border-radius: var(--m3-shape-xs); + color: var(--m3-on-surface); + text-decoration: none; + isolation: isolate; + overflow: hidden; + transition: background-color var(--m3-duration-short) var(--m3-ease-standard); +} + +.m3-list-item::after { + content: ''; + position: absolute; + inset: 0; + background: currentColor; + opacity: 0; + transition: opacity var(--m3-duration-short) var(--m3-ease-standard); +} + +@media (hover: hover) { .m3-list-item:hover::after { opacity: var(--m3-state-hover); } } +.m3-list-item:focus-visible::after { opacity: var(--m3-state-focus); } +.m3-list-item:active::after { opacity: var(--m3-state-pressed); } +.m3-list-item > * { position: relative; z-index: 1; } +.m3-list-item:hover { text-decoration: none; } + +.m3-list-item__leading { + display: grid; + place-items: center; + flex: 0 0 auto; + width: 40px; + height: 40px; + border-radius: var(--m3-shape-full); + background: var(--m3-surface-container-highest); + color: var(--m3-on-surface-variant); + font-size: 1.05rem; +} + +.m3-list-item__text { display: flex; flex-direction: column; min-width: 0; } +.m3-list-item__headline { font-size: var(--m3-body-large-size); line-height: 1.35; } +.m3-list-item__supporting { color: var(--m3-on-surface-variant); font-size: var(--m3-body-medium-size); } +.m3-list-item__trailing { margin-inline-start: auto; color: var(--m3-on-surface-variant); font-size: var(--m3-label-medium-size); } + +.m3-divider { height: 1px; border: 0; background: var(--m3-outline-variant); margin: 0; } +.m3-divider--inset { margin-inline: var(--m3-space-4); } + +/* ============================================================================ + 11 ยท Menus + ========================================================================== */ + +.m3-menu-anchor { position: relative; display: inline-flex; } + +.m3-menu { + position: absolute; + z-index: var(--m3-z-menu); + min-width: 200px; + max-width: min(320px, calc(100vw - 32px)); + max-height: 60vh; + overflow-y: auto; + padding: var(--m3-space-2); + border-radius: var(--m3-shape-xs); + background: var(--m3-surface-container); + color: var(--m3-on-surface); + box-shadow: var(--m3-elevation-2); + opacity: 0; + transform: scale(0.9) translateY(-6px); + transform-origin: top left; + visibility: hidden; + transition: + opacity var(--m3-duration-short) var(--m3-ease-standard), + transform var(--m3-duration-short-2) var(--m3-ease-emphasized-decel), + visibility var(--m3-duration-short); +} + +.m3-menu--open, +.m3-menu.is-open { + opacity: 1; + transform: scale(1) translateY(0); + visibility: visible; +} + +.m3-menu--end { inset-inline-end: 0; transform-origin: top right; } +.m3-menu--bottom { top: 100%; margin-block-start: 4px; } + +.m3-menu-item { + display: flex; + align-items: center; + gap: 12px; + width: 100%; + min-height: 48px; + padding: var(--m3-space-2) var(--m3-space-3); + border: none; + border-radius: var(--m3-shape-xs); + background: transparent; + color: inherit; + font-size: var(--m3-body-large-size); + text-align: start; + text-decoration: none; + cursor: pointer; + transition: background-color var(--m3-duration-short) var(--m3-ease-standard); +} + +@media (hover: hover) { .m3-menu-item:hover { background: color-mix(in srgb, var(--m3-on-surface) 8%, transparent); text-decoration: none; } } +.m3-menu-item:focus-visible { background: color-mix(in srgb, var(--m3-on-surface) 10%, transparent); } +.m3-menu-item[aria-checked='true'], +.m3-menu-item.is-selected { background: var(--m3-secondary-container); color: var(--m3-on-secondary-container); } +.m3-menu-item i:first-child { width: 22px; text-align: center; color: var(--m3-on-surface-variant); } +.m3-menu-item[aria-checked='true'] i:first-child, +.m3-menu-item.is-selected i:first-child { color: inherit; } +.m3-menu-item__meta { margin-inline-start: auto; color: var(--m3-on-surface-variant); font-size: var(--m3-label-medium-size); } + +/* ============================================================================ + 12 ยท Dialogs, bottom sheets, scrims + ========================================================================== */ + +.m3-scrim { + position: fixed; + inset: 0; + z-index: var(--m3-z-drawer); + background: color-mix(in srgb, var(--m3-scrim) 42%, transparent); + opacity: 0; + visibility: hidden; + transition: opacity var(--m3-duration-medium) var(--m3-ease-standard), visibility var(--m3-duration-medium); +} + +.m3-scrim.is-open { opacity: 1; visibility: visible; } + +.m3-dialog { + position: fixed; + inset: 0; + z-index: var(--m3-z-dialog); + display: grid; + place-items: center; + padding: var(--m3-space-4); + background: color-mix(in srgb, var(--m3-scrim) 45%, transparent); + opacity: 0; + visibility: hidden; + transition: opacity var(--m3-duration-medium) var(--m3-ease-standard), visibility var(--m3-duration-medium); +} + +.m3-dialog.is-open, +.m3-dialog[open] { opacity: 1; visibility: visible; } + +.m3-dialog__surface { + width: min(560px, 100%); + max-height: min(88vh, 880px); + display: flex; + flex-direction: column; + border-radius: var(--m3-shape-xl); + background: var(--m3-surface-container-high); + color: var(--m3-on-surface); + box-shadow: var(--m3-elevation-3); + transform: scale(0.9); + opacity: 0; + transition: + transform var(--m3-duration-medium) var(--m3-ease-emphasized-decel), + opacity var(--m3-duration-medium) var(--m3-ease-standard); +} + +.m3-dialog.is-open .m3-dialog__surface { transform: scale(1); opacity: 1; } +.m3-dialog--wide .m3-dialog__surface { width: min(880px, 100%); } +.m3-dialog--full .m3-dialog__surface { width: min(1100px, 100%); height: min(88vh, 900px); } + +.m3-dialog__head { + display: flex; + align-items: center; + gap: var(--m3-space-4); + padding: var(--m3-space-6) var(--m3-space-6) var(--m3-space-4); +} + +.m3-dialog__head--centered { flex-direction: column; text-align: center; padding-inline: var(--m3-space-6); } + +.m3-dialog__icon { + display: grid; + place-items: center; + color: var(--m3-secondary); + font-size: 1.75rem; +} + +.m3-dialog__title { + font-size: var(--m3-headline-small-size); + line-height: var(--m3-headline-small-line); + font-weight: 500; + letter-spacing: var(--m3-tracking-headline); +} + +.m3-dialog__body { + flex: 1 1 auto; + overflow-y: auto; + padding: 0 var(--m3-space-6) var(--m3-space-4); + color: var(--m3-on-surface-variant); + font-size: var(--m3-body-medium-size); + line-height: var(--m3-body-medium-line); +} + +.m3-dialog__actions { + display: flex; + justify-content: flex-end; + gap: var(--m3-space-2); + padding: var(--m3-space-4) var(--m3-space-6) var(--m3-space-6); + flex-wrap: wrap; +} + +/* Bottom sheet -------------------------------------------------------------- */ +.m3-sheet { + position: fixed; + inset-inline: 0; + inset-block-end: 0; + z-index: var(--m3-z-dialog); + display: flex; + flex-direction: column; + max-height: 90dvh; + padding: var(--m3-space-3) var(--m3-space-4) calc(var(--m3-space-6) + env(safe-area-inset-bottom)); + border-radius: var(--m3-shape-xl) var(--m3-shape-xl) 0 0; + background: var(--m3-surface-container-low); + color: var(--m3-on-surface); + box-shadow: var(--m3-elevation-2); + transform: translateY(100%); + visibility: hidden; + transition: transform var(--m3-duration-medium) var(--m3-ease-emphasized-decel), visibility var(--m3-duration-medium); +} + +.m3-sheet.is-open { transform: translateY(0); visibility: visible; } + +.m3-sheet__handle { + width: 32px; + height: 4px; + margin: 0 auto var(--m3-space-4); + border-radius: var(--m3-shape-full); + background: var(--m3-outline-variant); +} + +/* ============================================================================ + 13 ยท Snackbar, tooltip, banner + ========================================================================== */ + +.m3-snackbar-region { + position: fixed; + z-index: var(--m3-z-snackbar); + inset-block-end: calc(var(--m3-space-5) + env(safe-area-inset-bottom)); + inset-inline: 0; + display: flex; + flex-direction: column; + align-items: center; + gap: var(--m3-space-2); + padding-inline: var(--m3-space-4); + pointer-events: none; +} + +.m3-snackbar { + display: flex; + align-items: center; + gap: var(--m3-space-3); + width: min(560px, 100%); + min-height: 48px; + padding: var(--m3-space-3) var(--m3-space-4); + border-radius: var(--m3-shape-xs); + background: var(--m3-inverse-surface); + color: var(--m3-inverse-on-surface); + font-size: var(--m3-body-medium-size); + box-shadow: var(--m3-elevation-3); + pointer-events: auto; + animation: m3-snackbar-in var(--m3-duration-medium) var(--m3-ease-emphasized-decel); +} + +.m3-snackbar.is-leaving { animation: m3-snackbar-out var(--m3-duration-short-2) var(--m3-ease-standard-accel) forwards; } +.m3-snackbar__action { + margin-inline-start: auto; + padding: 6px 10px; + border: none; + border-radius: var(--m3-shape-full); + background: transparent; + color: var(--m3-inverse-primary); + font-weight: var(--m3-label-large-weight); + font-size: var(--m3-label-large-size); + cursor: pointer; +} + +.m3-snackbar__action:hover { background: color-mix(in srgb, var(--m3-inverse-primary) 16%, transparent); } +.m3-snackbar--error { background: var(--m3-error-container); color: var(--m3-on-error-container); } + +@keyframes m3-snackbar-in { + from { opacity: 0; transform: translateY(16px) scale(0.96); } + to { opacity: 1; transform: translateY(0) scale(1); } +} + +@keyframes m3-snackbar-out { + to { opacity: 0; transform: translateY(12px) scale(0.96); } +} + +.m3-tooltip { + position: relative; +} + +.m3-tooltip::after { + content: attr(data-tooltip); + position: absolute; + inset-block-end: calc(100% + 6px); + inset-inline-start: 50%; + translate: -50% 0; + z-index: var(--m3-z-tooltip); + padding: 4px 8px; + border-radius: var(--m3-shape-xs); + background: var(--m3-inverse-surface); + color: var(--m3-inverse-on-surface); + font-size: var(--m3-body-small-size); + white-space: nowrap; + opacity: 0; + pointer-events: none; + transition: opacity var(--m3-duration-short) var(--m3-ease-standard); +} + +@media (hover: hover) { + .m3-tooltip:hover::after, + .m3-tooltip:focus-visible::after { opacity: 1; } +} + +.m3-banner { + display: flex; + align-items: center; + gap: var(--m3-space-4); + padding: var(--m3-space-3) var(--m3-space-4); + border-radius: var(--m3-shape-md); + background: var(--m3-surface-container-high); + color: var(--m3-on-surface); + font-size: var(--m3-body-medium-size); +} + +.m3-banner--info { background: var(--m3-secondary-container); color: var(--m3-on-secondary-container); } +.m3-banner--warn { background: var(--m3-tertiary-container); color: var(--m3-on-tertiary-container); } +.m3-banner--error { background: var(--m3-error-container); color: var(--m3-on-error-container); } + +/* ============================================================================ + 14 ยท Tabs, navigation bar / rail / drawer, app bar + ========================================================================== */ + +.m3-tabs { + position: relative; + display: flex; + align-items: stretch; + gap: var(--m3-space-2); + overflow-x: auto; + scrollbar-width: none; + border-block-end: 1px solid var(--m3-outline-variant); +} + +.m3-tabs::-webkit-scrollbar { display: none; } + +.m3-tab { + position: relative; + display: inline-flex; + align-items: center; + justify-content: center; + gap: 8px; + flex: 1 1 auto; + min-width: max-content; + min-height: 48px; + padding: 0 var(--m3-space-4); + border: none; + background: transparent; + color: var(--m3-on-surface-variant); + font-size: var(--m3-title-small-size); + font-weight: var(--m3-title-small-weight); + letter-spacing: var(--m3-tracking-title); + text-decoration: none; + cursor: pointer; + transition: color var(--m3-duration-short) var(--m3-ease-standard), background-color var(--m3-duration-short) var(--m3-ease-standard); +} + +.m3-tab:hover { color: var(--m3-on-surface); text-decoration: none; } +.m3-tab[aria-selected='true'], +.m3-tab.is-active { + color: var(--m3-primary); +} + +.m3-tab[aria-selected='true']::after, +.m3-tab.is-active::after { + content: ''; + position: absolute; + inset-block-end: 0; + inset-inline: var(--m3-space-4); + height: 3px; + border-radius: var(--m3-shape-full) var(--m3-shape-full) 0 0; + background: var(--m3-primary); +} + +.m3-tab-panel[hidden] { display: none; } +.m3-tab-panel { animation: m3-fade-in var(--m3-duration-medium) var(--m3-ease-standard-decel); } + +@keyframes m3-fade-in { + from { opacity: 0; transform: translateY(8px); } + to { opacity: 1; transform: translateY(0); } +} + +/* Navigation bar (mobile) --------------------------------------------------- */ +.m3-nav-bar { + position: fixed; + inset-block-end: 0; + inset-inline: 0; + z-index: var(--m3-z-appbar); + display: flex; + justify-content: space-around; + align-items: stretch; + height: calc(80px + env(safe-area-inset-bottom)); + padding-block-end: env(safe-area-inset-bottom); + background: var(--m3-surface-container); + box-shadow: var(--m3-elevation-2); +} + +.m3-nav-bar__item { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 4px; + flex: 1 1 0; + max-width: 120px; + padding: var(--m3-space-2) 0; + color: var(--m3-on-surface-variant); + font-size: var(--m3-label-medium-size); + font-weight: var(--m3-label-medium-weight); + text-decoration: none; + transition: color var(--m3-duration-short) var(--m3-ease-standard); +} + +.m3-nav-bar__item:hover { text-decoration: none; } + +.m3-nav-bar__icon { + display: grid; + place-items: center; + width: 64px; + height: 32px; + border-radius: var(--m3-shape-full); + font-size: 1.15rem; + transition: background-color var(--m3-duration-short-2) var(--m3-ease-emphasized), color var(--m3-duration-short) var(--m3-ease-standard); +} + +.m3-nav-bar__item[aria-current='page'] { color: var(--m3-on-secondary-container); } +.m3-nav-bar__item[aria-current='page'] .m3-nav-bar__icon { + background: var(--m3-secondary-container); + color: var(--m3-on-secondary-container); +} + +/* Navigation drawer --------------------------------------------------------- */ +.m3-drawer { + position: fixed; + inset-block: 0; + inset-inline-start: 0; + z-index: calc(var(--m3-z-drawer) + 1); + width: min(320px, 88vw); + display: flex; + flex-direction: column; + gap: var(--m3-space-2); + padding: var(--m3-space-3) var(--m3-space-3) calc(var(--m3-space-4) + env(safe-area-inset-bottom)); + background: var(--m3-surface-container-low); + color: var(--m3-on-surface); + box-shadow: var(--m3-elevation-1); + border-start-end-radius: var(--m3-shape-lg); + border-end-end-radius: var(--m3-shape-lg); + overflow-y: auto; + transform: translateX(-105%); + visibility: hidden; + transition: + transform var(--m3-duration-medium) var(--m3-ease-emphasized-decel), + visibility var(--m3-duration-medium); +} + +.m3-drawer.is-open, +.m3-drawer.active, +.m3-drawer[data-open='true'] { + transform: translateX(0); + visibility: visible; +} + +.m3-drawer__head { + display: flex; + align-items: center; + justify-content: space-between; + gap: var(--m3-space-3); + padding: var(--m3-space-2) var(--m3-space-2) var(--m3-space-4); +} + +.m3-drawer__brand { + display: flex; + align-items: center; + gap: var(--m3-space-3); + font-size: var(--m3-title-large-size); + font-weight: 600; + color: var(--m3-on-surface); +} + +.m3-drawer__brand img { + width: 40px; + height: 40px; + border-radius: var(--m3-shape-md); + object-fit: cover; +} + +.m3-drawer__label { + padding: var(--m3-space-4) var(--m3-space-4) var(--m3-space-2); + color: var(--m3-on-surface-variant); + font-size: var(--m3-label-large-size); + font-weight: var(--m3-label-large-weight); + letter-spacing: var(--m3-tracking-label); + text-transform: uppercase; +} + +.m3-drawer__item { + position: relative; + display: flex; + align-items: center; + gap: var(--m3-space-3); + min-height: 56px; + padding: var(--m3-space-2) var(--m3-space-4); + border-radius: var(--m3-shape-full); + color: var(--m3-on-surface-variant); + font-size: var(--m3-body-large-size); + font-weight: 500; + text-decoration: none; + isolation: isolate; + overflow: hidden; + transition: background-color var(--m3-duration-short-2) var(--m3-ease-standard), color var(--m3-duration-short) var(--m3-ease-standard); +} + +.m3-drawer__item::after { + content: ''; + position: absolute; + inset: 0; + background: currentColor; + opacity: 0; + transition: opacity var(--m3-duration-short) var(--m3-ease-standard); +} + +@media (hover: hover) { .m3-drawer__item:hover::after { opacity: var(--m3-state-hover); } } +.m3-drawer__item:focus-visible::after { opacity: var(--m3-state-focus); } +.m3-drawer__item:active::after { opacity: var(--m3-state-pressed); } +.m3-drawer__item > * { position: relative; z-index: 1; } +.m3-drawer__item:hover { text-decoration: none; color: var(--m3-on-surface); } + +.m3-drawer__item[aria-current='page'], +.m3-drawer__item.active, +.m3-drawer__item.is-active { + background: var(--m3-secondary-container); + color: var(--m3-on-secondary-container); + font-weight: 600; +} + +.m3-drawer__item i { width: 22px; text-align: center; } +.m3-drawer__footer { margin-top: auto; padding: var(--m3-space-4); color: var(--m3-on-surface-variant); font-size: var(--m3-body-small-size); } + +/* Top app bar --------------------------------------------------------------- */ +.m3-app-bar { + position: sticky; + inset-block-start: 0; + z-index: var(--m3-z-appbar); + background: var(--m3-surface); + color: var(--m3-on-surface); + transition: background-color var(--m3-duration-short-2) var(--m3-ease-standard), box-shadow var(--m3-duration-short-2) var(--m3-ease-standard); +} + +.m3-app-bar.is-scrolled { + background: var(--m3-surface-container); + box-shadow: var(--m3-elevation-2); +} + +.m3-app-bar__row { + display: flex; + align-items: center; + gap: var(--m3-space-2); + min-height: var(--m3-appbar-height); +} + +.m3-app-bar__row:not(.m3-container) { padding-inline: var(--m3-space-2); } +/* Header and page body share one measure so their edges line up. */ +.m3-app-bar__row.m3-container--wide { max-width: var(--m3-content-max); } + +.m3-app-bar__title { + display: flex; + align-items: center; + gap: var(--m3-space-2); + margin-inline-start: var(--m3-space-2); + font-family: var(--m3-font-brand); + font-size: var(--m3-title-large-size); + font-weight: 600; + letter-spacing: var(--m3-tracking-title); + color: inherit; + text-decoration: none; +} + +.m3-app-bar__title:hover { text-decoration: none; color: inherit; } +.m3-app-bar__title img { width: 36px; height: 36px; border-radius: var(--m3-shape-sm); object-fit: cover; } +.m3-app-bar__actions { display: flex; align-items: center; gap: 4px; margin-inline-start: auto; } + +.m3-app-bar--large { display: flex; flex-direction: column; } +.m3-app-bar--large .m3-app-bar__headline { + padding: var(--m3-space-2) var(--m3-space-6) var(--m3-space-6); + font-size: var(--m3-headline-medium-size); + line-height: var(--m3-headline-medium-line); +} + +/* ============================================================================ + 15 ยท Tables, progress, badges & misc + ========================================================================== */ + +.m3-table-wrap { + width: 100%; + overflow-x: auto; + border-radius: var(--m3-shape-md); + border: 1px solid var(--m3-outline-variant); + background: var(--m3-surface); + -webkit-overflow-scrolling: touch; +} + +.m3-table { + width: 100%; + border-collapse: collapse; + font-size: var(--m3-body-medium-size); +} + +.m3-table caption { + caption-side: top; + padding: var(--m3-space-4); + text-align: start; + color: var(--m3-on-surface-variant); + font-size: var(--m3-body-small-size); +} + +.m3-table th, +.m3-table td { + padding: var(--m3-space-3) var(--m3-space-4); + text-align: start; + border-block-end: 1px solid var(--m3-outline-variant); + vertical-align: middle; +} + +.m3-table thead th { + position: sticky; + inset-block-start: 0; + z-index: 1; + background: var(--m3-surface-container); + color: var(--m3-on-surface-variant); + font-size: var(--m3-label-large-size); + font-weight: var(--m3-label-large-weight); + letter-spacing: var(--m3-tracking-label); + white-space: nowrap; +} + +.m3-table tbody tr { transition: background-color var(--m3-duration-short) var(--m3-ease-standard); } +@media (hover: hover) { .m3-table tbody tr:hover { background: color-mix(in srgb, var(--m3-on-surface) 6%, transparent); } } +.m3-table tbody tr:last-child td { border-block-end: none; } +.m3-table__num { font-variant-numeric: tabular-nums; font-family: var(--m3-font-mono); } +.m3-table__actions { width: 1%; white-space: nowrap; text-align: end; } + +.m3-progress-linear { + position: relative; + height: 4px; + border-radius: var(--m3-shape-full); + background: var(--m3-surface-container-highest); + overflow: hidden; +} + +.m3-progress-linear__bar { + height: 100%; + border-radius: inherit; + background: var(--m3-primary); + transition: width var(--m3-duration-long) var(--m3-ease-emphasized-decel); +} + +.m3-progress-linear--indeterminate::after { + content: ''; + position: absolute; + inset-block: 0; + inset-inline-start: -40%; + width: 40%; + border-radius: inherit; + background: var(--m3-primary); + animation: m3-indeterminate 1.6s var(--m3-ease-standard) infinite; +} + +@keyframes m3-indeterminate { + 0% { inset-inline-start: -40%; } + 100% { inset-inline-start: 100%; } +} + +.m3-circular { + width: 32px; + height: 32px; + border-radius: 50%; + border: 3px solid var(--m3-surface-container-highest); + border-top-color: var(--m3-primary); + animation: m3-spin 900ms linear infinite; +} + +.m3-circular--sm { width: 18px; height: 18px; border-width: 2px; } + +.m3-badge { + display: inline-flex; + align-items: center; + gap: 6px; + padding: 4px 10px; + border-radius: var(--m3-shape-sm); + background: var(--m3-secondary-container); + color: var(--m3-on-secondary-container); + font-size: var(--m3-label-medium-size); + font-weight: var(--m3-label-medium-weight); + letter-spacing: var(--m3-tracking-label); +} + +.m3-badge--primary { background: var(--m3-primary-container); color: var(--m3-on-primary-container); } +.m3-badge--tertiary { background: var(--m3-tertiary-container); color: var(--m3-on-tertiary-container); } +.m3-badge--error { background: var(--m3-error-container); color: var(--m3-on-error-container); } +.m3-badge--outline { background: transparent; border: 1px solid var(--m3-outline-variant); color: var(--m3-on-surface-variant); } +.m3-badge--dot { + width: 8px; + height: 8px; + padding: 0; + border-radius: 50%; + background: var(--m3-error); +} + +.m3-avatar { + display: grid; + place-items: center; + width: 48px; + height: 48px; + border-radius: var(--m3-shape-full); + background: var(--m3-primary-container); + color: var(--m3-on-primary-container); + object-fit: cover; + font-weight: 600; + overflow: hidden; +} + +.m3-avatar--sm { width: 32px; height: 32px; font-size: var(--m3-body-small-size); } +.m3-avatar--lg { width: 88px; height: 88px; font-size: 2rem; } + +.m3-skeleton { + position: relative; + overflow: hidden; + border-radius: var(--m3-shape-sm); + background: var(--m3-surface-container-high); +} + +.m3-skeleton::after { + content: ''; + position: absolute; + inset: 0; + background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--m3-on-surface) 8%, transparent), transparent); + transform: translateX(-100%); + animation: m3-shimmer 1.4s var(--m3-ease-standard) infinite; +} + +@keyframes m3-shimmer { + to { transform: translateX(100%); } +} + +.m3-empty { + display: flex; + flex-direction: column; + align-items: center; + gap: var(--m3-space-3); + padding: var(--m3-space-12) var(--m3-space-4); + text-align: center; + color: var(--m3-on-surface-variant); +} + +.m3-empty i, +.m3-empty svg { font-size: 2.5rem; color: var(--m3-outline); } +.m3-empty h3 { color: var(--m3-on-surface); } + +.m3-expansion { + border-radius: var(--m3-shape-md); + background: var(--m3-surface-container-low); + overflow: hidden; +} + +.m3-expansion + .m3-expansion { margin-block-start: var(--m3-space-3); } + +.m3-expansion__summary { + display: flex; + align-items: center; + gap: var(--m3-space-3); + padding: var(--m3-space-4); + cursor: pointer; + list-style: none; + font-size: var(--m3-title-medium-size); + font-weight: var(--m3-title-medium-weight); + color: var(--m3-on-surface); +} + +.m3-expansion__summary::-webkit-details-marker { display: none; } +.m3-expansion__summary::after { + content: '\f107'; + font-family: 'Font Awesome 6 Free'; + font-weight: 900; + margin-inline-start: auto; + color: var(--m3-on-surface-variant); + transition: transform var(--m3-duration-medium) var(--m3-ease-emphasized); +} + +.m3-expansion[open] > .m3-expansion__summary::after { transform: rotate(180deg); } +.m3-expansion__content { padding: 0 var(--m3-space-4) var(--m3-space-4); color: var(--m3-on-surface-variant); } + +.m3-stepper { display: flex; align-items: center; gap: var(--m3-space-2); } +.m3-stepper__btn { + display: grid; + place-items: center; + width: 32px; + height: 32px; + border-radius: 50%; + border: 1px solid var(--m3-outline); + background: transparent; + color: var(--m3-on-surface-variant); + cursor: pointer; +} +.m3-stepper__value { min-width: 3ch; text-align: center; font-variant-numeric: tabular-nums; font-family: var(--m3-font-mono); } + +.m3-pagination { + display: flex; + align-items: center; + justify-content: center; + gap: 4px; + flex-wrap: wrap; +} + +.m3-page-btn { + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 40px; + height: 40px; + padding-inline: 12px; + border: none; + border-radius: var(--m3-shape-full); + background: transparent; + color: var(--m3-on-surface-variant); + font-size: var(--m3-label-large-size); + font-weight: var(--m3-label-large-weight); + cursor: pointer; + transition: background-color var(--m3-duration-short) var(--m3-ease-standard), color var(--m3-duration-short) var(--m3-ease-standard); +} + +@media (hover: hover) { .m3-page-btn:hover:not(:disabled) { background: color-mix(in srgb, var(--m3-on-surface) 8%, transparent); color: var(--m3-on-surface); } } +.m3-page-btn[aria-current='page'], +.m3-page-btn.is-active { background: var(--m3-primary); color: var(--m3-on-primary); } +.m3-page-btn:disabled { opacity: 0.38; cursor: not-allowed; } + +.m3-label-float { color: var(--m3-on-surface-variant); font-size: var(--m3-label-large-size); font-weight: var(--m3-label-large-weight); letter-spacing: var(--m3-tracking-label); } + +/* Motion utilities ---------------------------------------------------------- */ +.m3-animate-in { animation: m3-fade-in var(--m3-duration-medium) var(--m3-ease-emphasized-decel) both; } +.m3-press { transition: transform var(--m3-duration-short-2) var(--m3-ease-emphasized); } +.m3-press:active { transform: scale(0.96); } + +@media (prefers-reduced-motion: reduce) { + .m3-dialog__surface, + .m3-drawer, + .m3-sheet { transform: none !important; } +} + +/* โ”€โ”€ Dynamic colour picker (rendered by assets/m3/color.js) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ + +.m3-color-picker { display: flex; flex-direction: column; gap: var(--m3-space-2); } +.m3-color-picker .m3-chip { gap: 10px; } +.m3-color-picker input[type='color'] { border-radius: var(--m3-shape-full); } diff --git a/main/assets/m3/gen_palette.py b/main/assets/m3/gen_palette.py new file mode 100644 index 0000000..7810528 --- /dev/null +++ b/main/assets/m3/gen_palette.py @@ -0,0 +1,277 @@ +"""Generate Material You 3 tonal palettes from seed colors (offline, one-shot). +Mirrors the runtime generator in main/assets/m3/color.js (CIELAB-based tonal palettes).""" +import math + +def srgb_to_lin(c): + c = c / 255.0 + return c / 12.92 if c <= 0.04045 else ((c + 0.055) / 1.055) ** 2.4 + +def lin_to_srgb(c): + c = max(0.0, min(1.0, c)) + v = 12.92 * c if c <= 0.0031308 else 1.055 * (c ** (1 / 2.4)) - 0.055 + return round(max(0, min(255, v * 255))) + +def hex_to_rgb(h): + h = h.lstrip('#') + return tuple(int(h[i:i+2], 16) for i in (0, 2, 4)) + +def rgb_to_hex(rgb): + return '#%02X%02X%02X' % tuple(rgb) + +# sRGB (D65) -> XYZ -> Lab +def rgb_to_lab(rgb): + r, g, b = [srgb_to_lin(c) for c in rgb] + x = r * 0.4124564 + g * 0.3575761 + b * 0.1804375 + y = r * 0.2126729 + g * 0.7151522 + b * 0.0721750 + z = r * 0.0193339 + g * 0.1191920 + b * 0.9503041 + xn, yn, zn = 0.95047, 1.0, 1.08883 + def f(t): + return t ** (1/3) if t > 216/24389 else (841/108) * t + 4/29 + fx, fy, fz = f(x/xn), f(y/yn), f(z/zn) + return (116*fy - 16, 500*(fx-fy), 200*(fy-fz)) + +def lab_to_rgb(lab): + L, a, bb = lab + fy = (L + 16) / 116 + fx = fy + a / 500 + fz = fy - bb / 200 + def f_inv(t): + return t ** 3 if t ** 3 > 216/24389 else (t - 4/29) * (108/841) + x = f_inv(fx) * 0.95047 + y = f_inv(fy) * 1.0 + z = f_inv(fz) * 1.08883 + r = x * 3.2404542 + y * -1.5371385 + z * -0.4985314 + g = x * -0.9692660 + y * 1.8760108 + z * 0.0415560 + bl = x * 0.0556434 + y * -0.2040259 + z * 1.0572252 + return (lin_to_srgb(r), lin_to_srgb(g), lin_to_srgb(bl)) + +def in_gamut(rgb): + r, g, b = [srgb_to_lin(c) for c in rgb] + x = r * 0.4124564 + g * 0.3575761 + b * 0.1804375 + y = r * 0.2126729 + g * 0.7151522 + b * 0.0721750 + z = r * 0.0193339 + g * 0.1191920 + b * 0.9503041 + xn, yn, zn = 0.95047, 1.0, 1.08883 + x, y, z = x/xn, y/yn, z/zn + return (-1e-4 <= x <= 1.0001) and (-1e-4 <= y <= 1.0001) and (-1e-4 <= z <= 1.0001) + +def tone_to_hex(L, a, b): + """Return hex for target lightness L keeping (a,b) chroma, clamped into sRGB gamut.""" + aa, bb = a, b + rgb = lab_to_rgb((L, aa, bb)) + if in_gamut(rgb): + return rgb_to_hex(rgb) + # binary search chroma reduction + lo, hi = 0.0, 1.0 + best = (255, 255, 255) if L > 50 else (0, 0, 0) + for _ in range(24): + mid = (lo + hi) / 2 + rgb = lab_to_rgb((L, aa * mid, bb * mid)) + if in_gamut(rgb): + best = rgb + lo = mid + else: + hi = mid + return rgb_to_hex(best) + +TONES = [0, 4, 5, 6, 10, 12, 17, 20, 22, 24, 25, 30, 35, 40, 50, 60, 70, 80, 87, 90, 92, 94, 95, 96, 98, 99, 100] + +def palette(seed_hex, chroma_scale=1.0, forced_hue=None): + L, a, b = rgb_to_lab(hex_to_rgb(seed_hex)) + hue = math.atan2(b, a) + chroma = math.hypot(a, b) * chroma_scale + if forced_hue is not None: + hue = math.radians(forced_hue) + out = {} + for t in TONES: + out[t] = tone_to_hex(t, chroma * math.cos(hue), chroma * math.sin(hue)) + return out, math.degrees(hue), chroma + +LIGHT = dict( + primary=40, on_primary=100, primary_container=90, on_primary_container=10, + primary_fixed=90, primary_fixed_dim=80, on_primary_fixed=10, on_primary_fixed_variant=30, + secondary=40, on_secondary=100, secondary_container=90, on_secondary_container=10, + tertiary=40, on_tertiary=100, tertiary_container=90, on_tertiary_container=10, + error=40, on_error=100, error_container=90, on_error_container=10, + background=98, on_background=10, + surface=98, on_surface=10, surface_variant=90, on_surface_variant=30, + surface_dim=87, surface_bright=98, + surface_container_lowest=100, surface_container_low=96, surface_container=94, + surface_container_high=92, surface_container_highest=90, + outline=50, outline_variant=80, + inverse_surface=20, inverse_on_surface=95, inverse_primary=80, + scrim=0, shadow=0, surface_tint=40, +) +DARK = dict( + primary=80, on_primary=20, primary_container=30, on_primary_container=90, + primary_fixed=90, primary_fixed_dim=80, on_primary_fixed=10, on_primary_fixed_variant=30, + secondary=80, on_secondary=20, secondary_container=30, on_secondary_container=90, + tertiary=80, on_tertiary=20, tertiary_container=30, on_tertiary_container=90, + error=80, on_error=20, error_container=30, on_error_container=90, + background=6, on_background=90, + surface=6, on_surface=90, surface_variant=30, on_surface_variant=80, + surface_dim=6, surface_bright=24, + surface_container_lowest=4, surface_container_low=10, surface_container=12, + surface_container_high=17, surface_container_highest=22, + outline=60, outline_variant=30, + inverse_surface=90, inverse_on_surface=20, inverse_primary=40, + scrim=0, shadow=0, surface_tint=80, +) + +ERROR_SEED = '#B3261E' # M3 fixed error palette +NEUTRAL_CHROMA = 3.2 +NV_CHROMA = 9.0 + +def build(seed_hex, tertiary_hue_shift=60): + p, hue, chroma = palette(seed_hex) + # secondary = desaturated version of the seed hue + sec, _, _ = palette(seed_hex, chroma_scale=0.34) + ter, _, _ = palette(seed_hex, chroma_scale=0.72, forced_hue=hue + tertiary_hue_shift) + n_err, _, _ = palette(ERROR_SEED) + neu = {} + nv = {} + for t in TONES: + L, a, b = rgb_to_lab(hex_to_rgb(p[t])) + neu[t] = tone_to_hex(t, NEUTRAL_CHROMA * math.cos(math.radians(hue)), NEUTRAL_CHROMA * math.sin(math.radians(hue))) + nv[t] = tone_to_hex(t, NV_CHROMA * math.cos(math.radians(hue)), NV_CHROMA * math.sin(math.radians(hue))) + return dict(primary=p, secondary=sec, tertiary=ter, error=n_err, neutral=neu, neutral_variant=nv) + +# role -> (palette key, tone) -- explicit Material 3 role mapping +ROLE_MAP_LIGHT = { + 'primary': ('primary', 40), 'on_primary': ('primary', 100), + 'primary_container': ('primary', 90), 'on_primary_container': ('primary', 10), + 'primary_fixed': ('primary', 90), 'primary_fixed_dim': ('primary', 80), + 'on_primary_fixed': ('primary', 10), 'on_primary_fixed_variant': ('primary', 30), + 'secondary': ('secondary', 40), 'on_secondary': ('secondary', 100), + 'secondary_container': ('secondary', 90), 'on_secondary_container': ('secondary', 10), + 'tertiary': ('tertiary', 40), 'on_tertiary': ('tertiary', 100), + 'tertiary_container': ('tertiary', 90), 'on_tertiary_container': ('tertiary', 10), + 'error': ('error', 40), 'on_error': ('error', 100), + 'error_container': ('error', 90), 'on_error_container': ('error', 10), + 'background': ('neutral', 98), 'on_background': ('neutral', 10), + 'surface': ('neutral', 98), 'on_surface': ('neutral', 10), + 'surface_variant': ('neutral_variant', 90), 'on_surface_variant': ('neutral_variant', 30), + 'surface_dim': ('neutral', 87), 'surface_bright': ('neutral', 98), + 'surface_container_lowest': ('neutral', 100), 'surface_container_low': ('neutral', 96), + 'surface_container': ('neutral', 94), 'surface_container_high': ('neutral', 92), + 'surface_container_highest': ('neutral', 90), + 'outline': ('neutral_variant', 50), 'outline_variant': ('neutral_variant', 80), + 'inverse_surface': ('neutral', 20), 'inverse_on_surface': ('neutral', 95), + 'inverse_primary': ('primary', 80), + 'scrim': ('neutral', 0), 'shadow': ('neutral', 0), 'surface_tint': ('primary', 40), +} +ROLE_MAP_DARK = dict(ROLE_MAP_LIGHT) +ROLE_MAP_DARK.update({ + 'primary': ('primary', 80), 'on_primary': ('primary', 20), + 'primary_container': ('primary', 30), 'on_primary_container': ('primary', 90), + 'secondary': ('secondary', 80), 'on_secondary': ('secondary', 20), + 'secondary_container': ('secondary', 30), 'on_secondary_container': ('secondary', 90), + 'tertiary': ('tertiary', 80), 'on_tertiary': ('tertiary', 20), + 'tertiary_container': ('tertiary', 30), 'on_tertiary_container': ('tertiary', 90), + 'error': ('error', 80), 'on_error': ('error', 20), + 'error_container': ('error', 30), 'on_error_container': ('error', 90), + 'background': ('neutral', 6), 'on_background': ('neutral', 90), + 'surface': ('neutral', 6), 'on_surface': ('neutral', 90), + 'surface_variant': ('neutral_variant', 30), 'on_surface_variant': ('neutral_variant', 80), + 'surface_dim': ('neutral', 6), 'surface_bright': ('neutral', 24), + 'surface_container_lowest': ('neutral', 4), 'surface_container_low': ('neutral', 10), + 'surface_container': ('neutral', 12), 'surface_container_high': ('neutral', 17), + 'surface_container_highest': ('neutral', 22), + 'outline': ('neutral_variant', 60), 'outline_variant': ('neutral_variant', 30), + 'inverse_surface': ('neutral', 90), 'inverse_on_surface': ('neutral', 20), + 'inverse_primary': ('primary', 40), 'surface_tint': ('primary', 80), +}) + +def _rel_lum(hex_color): + r, g, b = hex_to_rgb(hex_color) + def chan(c): + c = c / 255.0 + return c / 12.92 if c <= 0.04045 else ((c + 0.055) / 1.055) ** 2.4 + r, g, b = chan(r), chan(g), chan(b) + return 0.2126 * r + 0.7152 * g + 0.0722 * b + +def contrast(hex_a, hex_b): + """WCAG contrast ratio between two hex colours.""" + la, lb = _rel_lum(hex_a), _rel_lum(hex_b) + hi, lo = max(la, lb), min(la, lb) + return (hi + 0.05) / (lo + 0.05) + +def readable_containers(scheme, maps): + """Dark container roles default to tone 30. Bright hues (crimson, amber) + can fall just short of 4.5:1 against their tone-90 label, so step the + container down the tonal ramp until the pair is accessible.""" + scheme = dict(scheme) + pairs = (('primary_container', 'on_primary_container'), + ('secondary_container', 'on_secondary_container'), + ('tertiary_container', 'on_tertiary_container'), + ('error_container', 'on_error_container')) + for role, on_role in pairs: + key, tone = scheme[role] + on_key, on_tone = scheme[on_role] + label = _tone(maps, on_key, on_tone) + for candidate in (tone, 25, 22, 20, 17, 12): + if candidate not in maps[key]: + continue + if contrast(_tone(maps, key, candidate), label) >= 4.5: + scheme[role] = (key, candidate) + break + return scheme + +def _tone(maps, key, tone): + if tone == 100: + return '#FFFFFF' + if tone == 0: + return '#000000' + return maps[key][tone] + +def roles(scheme, maps): + return {role: _tone(maps, *ref) for role, ref in scheme.items()} + +def css_block(selector, scheme, maps, indent=' '): + r = roles(scheme, maps) + lines = [f'{selector} {{'] + for k in scheme.keys(): + lines.append(f'{indent}--m3-{k.replace("_", "-")}: {r[k]};') + lines.append('}') + return '\n'.join(lines) + +SEEDS = { + '': '#C8102E', # GDIPS red (default / brand) + 'indigo': '#6366F1', + 'violet': '#8B5CF6', + 'crimson': '#DC2626', + 'emerald': '#0F9D58', + 'amber': '#F59E0B', + 'azure': '#2563EB', +} + +blocks = [] +# default seed: light + dark (+ system dark fallback for no-JS) +maps_default = build(SEEDS['']) +blocks.append('/* โ”€โ”€ Default dynamic palette: GDIPS red โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */') +blocks.append(css_block(':root', ROLE_MAP_LIGHT, maps_default)) +blocks.append(css_block(':root[data-theme="dark"]', readable_containers(ROLE_MAP_DARK, maps_default), maps_default)) +blocks.append('@media (prefers-color-scheme: dark) {\n ' + + css_block(':root:not([data-theme="light"])', readable_containers(ROLE_MAP_DARK, maps_default), maps_default).replace('\n', '\n ') + '\n}') + +for name, seed in SEEDS.items(): + if not name: + continue + m = build(seed) + blocks.append(f'/* โ”€โ”€ Seed: {name} ({seed}) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */') + blocks.append(css_block(f':root[data-seed="{name}"]', ROLE_MAP_LIGHT, m)) + blocks.append(css_block(f':root[data-seed="{name}"][data-theme="dark"]', readable_containers(ROLE_MAP_DARK, m), m)) + blocks.append('@media (prefers-color-scheme: dark) {\n ' + + css_block(f':root[data-seed="{name}"]:not([data-theme="light"])', readable_containers(ROLE_MAP_DARK, m), m).replace('\n', '\n ') + '\n}') + +header = '''/* ============================================================================ + GDIPS ยท Material You 3 โ€” Dynamic color palettes + ---------------------------------------------------------------------------- + Material 3 tonal palettes generated from seed colours (CIELAB tone mapping, + gamut-clamped). The default seed is the GDIPS brand red; alternate seeds are + selected with and the runtime generator in + assets/m3/color.js can produce a palette from *any* user-chosen seed. + ========================================================================== */ +''' +open('main/assets/m3/palettes.css', 'w').write(header + '\n' + '\n\n'.join(blocks) + '\n') +print('wrote palettes.css', len(header + '\n'.join(blocks))) +print('sample light primary:', roles(ROLE_MAP_LIGHT, maps_default)['primary'], roles(ROLE_MAP_LIGHT, maps_default)['on_primary']) diff --git a/main/assets/m3/pages.css b/main/assets/m3/pages.css new file mode 100644 index 0000000..ffad140 --- /dev/null +++ b/main/assets/m3/pages.css @@ -0,0 +1,464 @@ +/* ============================================================================ + GDIPS ยท Material You 3 โ€” Page level styles + ---------------------------------------------------------------------------- + Layouts that are specific to individual GDIPS pages (entry bootloader, + download, rating standards, tools, feedback, 404, redirect). Everything here + is built from the shared tokens/components. + ========================================================================== */ + +/* ============================================================================ + Entry / bootloader page + ========================================================================== */ + +.gd-boot-page { + overflow: hidden; + height: 100dvh; + overscroll-behavior: none; +} + +.gd-boot { + position: relative; + display: grid; + place-items: center; + min-height: 100dvh; + padding-block: var(--m3-space-6); + background: var(--m3-surface); + isolation: isolate; +} + +.gd-boot__glow { + position: absolute; + inset: 0; + overflow: hidden; + pointer-events: none; + z-index: -1; +} + +.gd-boot__orb { + position: absolute; + display: block; + border-radius: 50%; + filter: blur(60px); + opacity: 0.55; + animation: gd-drift 18s var(--m3-ease-standard) infinite alternate; +} + +.gd-boot__orb--primary { + width: clamp(240px, 45vw, 520px); + aspect-ratio: 1; + inset-block-start: -12%; + inset-inline-start: -8%; + background: var(--m3-primary-container); +} + +.gd-boot__orb--tertiary { + width: clamp(200px, 38vw, 440px); + aspect-ratio: 1; + inset-block-end: -14%; + inset-inline-end: -6%; + background: var(--m3-tertiary-container); + animation-delay: -6s; +} + +.gd-boot__grid { + position: absolute; + inset: 0; + background-image: + linear-gradient(color-mix(in srgb, var(--m3-outline-variant) 45%, transparent) 1px, transparent 1px), + linear-gradient(90deg, color-mix(in srgb, var(--m3-outline-variant) 45%, transparent) 1px, transparent 1px); + background-size: 56px 56px; + mask-image: radial-gradient(circle at 50% 45%, #000 0%, transparent 78%); + -webkit-mask-image: radial-gradient(circle at 50% 45%, #000 0%, transparent 78%); + opacity: 0.6; +} + +@keyframes gd-drift { + from { transform: translate3d(0, 0, 0) scale(1); } + to { transform: translate3d(4%, 6%, 0) scale(1.12); } +} + +.gd-boot__inner { + display: flex; + flex-direction: column; + gap: var(--m3-space-5); + width: 100%; + max-width: 640px; +} + +.gd-boot__brand { + margin: 0; + font-size: clamp(1.5rem, 4vw, 2rem); +} + +.gd-boot__brand-sub { + display: block; + font-size: var(--m3-label-medium-size); + font-weight: 600; + letter-spacing: var(--m3-tracking-label); + text-transform: uppercase; + color: var(--m3-on-surface-variant); +} + +.gd-boot__card { + padding: clamp(20px, 4vw, 32px); + background: color-mix(in srgb, var(--m3-surface-container-low) 88%, transparent); + backdrop-filter: blur(14px); + border-radius: var(--m3-shape-xl); +} + +.gd-boot__card-head { + display: flex; + flex-direction: column; + gap: var(--m3-space-2); + margin-block-end: var(--m3-space-5); +} + +.gd-boot__menu { + display: flex; + flex-direction: column; + gap: var(--m3-space-2); + transition: opacity var(--m3-duration-medium) var(--m3-ease-standard), transform var(--m3-duration-medium) var(--m3-ease-emphasized); +} + +.gd-boot__menu.is-hidden { + opacity: 0; + transform: scale(0.98); + pointer-events: none; +} + +.gd-boot__item { + position: relative; + display: flex; + align-items: center; + gap: var(--m3-space-3); + padding: var(--m3-space-3) var(--m3-space-4); + border: 1px solid transparent; + border-radius: var(--m3-shape-lg); + color: var(--m3-on-surface); + text-decoration: none; + isolation: isolate; + overflow: hidden; + transition: + background-color var(--m3-duration-short-2) var(--m3-ease-standard), + border-color var(--m3-duration-short-2) var(--m3-ease-standard), + transform var(--m3-duration-short-2) var(--m3-ease-emphasized); +} + +.gd-boot__item:hover { + background: var(--m3-surface-container-high); + text-decoration: none; + transform: translateX(4px); +} + +.gd-boot__item.is-active { + background: var(--m3-secondary-container); + color: var(--m3-on-secondary-container); + border-color: color-mix(in srgb, var(--m3-primary) 45%, transparent); +} + +.gd-boot__indicator { + display: grid; + place-items: center; + width: 24px; + color: var(--m3-primary); + opacity: 0; + transform: translateX(-6px); + transition: opacity var(--m3-duration-short-2) var(--m3-ease-standard), transform var(--m3-duration-short-2) var(--m3-ease-emphasized); +} + +.gd-boot__item.is-active .gd-boot__indicator { opacity: 1; transform: none; } + +.gd-boot__item-icon { + display: grid; + place-items: center; + width: 44px; + height: 44px; + flex: 0 0 auto; + border-radius: var(--m3-shape-full); + background: var(--m3-surface-container-highest); + color: var(--m3-on-surface-variant); + font-size: 1.1rem; +} + +.gd-boot__item.is-active .gd-boot__item-icon { + background: var(--m3-primary); + color: var(--m3-on-primary); +} + +.gd-boot__item-text { display: flex; flex-direction: column; min-width: 0; } +.gd-boot__item-title { font-size: var(--m3-title-medium-size); font-weight: 600; } +.gd-boot__item-sub { color: inherit; opacity: 0.75; font-size: var(--m3-body-small-size); } + +.gd-boot__item-key { + margin-inline-start: auto; + display: grid; + place-items: center; + width: 28px; + height: 28px; + border-radius: var(--m3-shape-sm); + background: color-mix(in srgb, currentColor 10%, transparent); + font-size: var(--m3-label-medium-size); +} + +.gd-boot__foot { + display: flex; + align-items: center; + gap: var(--m3-space-4); + flex-wrap: wrap; + margin-block-start: var(--m3-space-5); + padding-block-start: var(--m3-space-4); + border-block-start: 1px solid var(--m3-outline-variant); +} + +.gd-boot__theme { margin-inline-start: auto; } + +.gd-boot__output { + position: fixed; + inset: 0; + display: grid; + place-items: center; + background: var(--m3-surface); + opacity: 0; + pointer-events: none; + transition: opacity var(--m3-duration-medium) var(--m3-ease-standard); + z-index: 5; +} + +.gd-boot__output.is-visible { opacity: 1; } + +.gd-boot__output-card { + display: flex; + flex-direction: column; + gap: var(--m3-space-4); + width: min(420px, 86vw); + padding: var(--m3-space-6); + border-radius: var(--m3-shape-xl); + background: var(--m3-surface-container); + box-shadow: var(--m3-elevation-2); +} + +.gd-boot__output-text { + font-size: clamp(0.95rem, 2.4vw, 1.15rem); + color: var(--m3-primary); + min-height: 1.6em; +} + +.gd-boot__output-text::after { + content: ''; + display: inline-block; + width: 9px; + height: 1.15em; + margin-inline-start: 6px; + vertical-align: -0.15em; + background: currentColor; + animation: gd-blink 1s step-end infinite; +} + +.gd-boot__output-text.is-loading::after { animation: gd-dots 1.4s steps(4, end) infinite content; } +.gd-boot__output-text.is-loading::before { content: ''; } + +@keyframes gd-blink { + 0%, 100% { opacity: 1; } + 50% { opacity: 0; } +} + +/* ============================================================================ + Shared content page pieces + ========================================================================== */ + +.gd-page-head { + display: flex; + flex-direction: column; + gap: var(--m3-space-3); + padding-block: clamp(24px, 5vw, 48px) var(--m3-space-6); +} + +.gd-page-head__title { font-size: clamp(1.75rem, 4.2vw, 2.75rem); font-weight: 600; } +.gd-page-head__lead { color: var(--m3-on-surface-variant); max-width: 68ch; } + +.gd-card-icon { + display: grid; + place-items: center; + width: 48px; + height: 48px; + border-radius: var(--m3-shape-md); + background: var(--m3-primary-container); + color: var(--m3-on-primary-container); + font-size: 1.2rem; +} + +.gd-meta { + display: flex; + flex-wrap: wrap; + gap: var(--m3-space-4); + color: var(--m3-on-surface-variant); + font-size: var(--m3-body-small-size); +} + +.gd-meta span { display: inline-flex; align-items: center; gap: 6px; } + +/* Download cards ------------------------------------------------------------ */ + +.gd-download { + display: flex; + flex-direction: column; + gap: var(--m3-space-3); + padding: var(--m3-space-5); + height: 100%; +} + +.gd-download__head { display: flex; align-items: center; gap: var(--m3-space-3); } +.gd-download__title { font-size: var(--m3-title-large-size); font-weight: 600; } +.gd-download__size { color: var(--m3-on-surface-variant); font-size: var(--m3-body-small-size); } +.gd-download__actions { display: flex; gap: var(--m3-space-2); margin-block-start: auto; padding-block-start: var(--m3-space-3); flex-wrap: wrap; } + +/* Rating standards ---------------------------------------------------------- */ + +.gd-rating-card { padding: var(--m3-space-5); display: flex; flex-direction: column; gap: var(--m3-space-4); height: 100%; } +.gd-rating-card__tier { display: flex; align-items: center; justify-content: space-between; gap: var(--m3-space-3); } +.gd-rating-card__name { font-size: var(--m3-title-large-size); font-weight: 600; } +.gd-rating-card__meters { display: flex; flex-direction: column; gap: var(--m3-space-3); } + +/* Tools grid ---------------------------------------------------------------- */ + +.gd-tool { + display: flex; + flex-direction: column; + gap: var(--m3-space-3); + padding: var(--m3-space-5); + height: 100%; +} + +.gd-tool__head { display: flex; align-items: center; gap: var(--m3-space-3); } +.gd-tool__title { font-size: var(--m3-title-medium-size); font-weight: 600; } +.gd-tool__actions { margin-block-start: auto; padding-block-start: var(--m3-space-2); } + +/* Error page ---------------------------------------------------------------- */ + +.gd-error { + display: grid; + place-items: center; + min-height: 100dvh; + padding: var(--m3-space-6); + text-align: center; + background: + radial-gradient(circle at 50% 0%, color-mix(in srgb, var(--m3-error-container) 55%, transparent), transparent 60%), + var(--m3-surface); +} + +.gd-error__inner { max-width: 620px; display: flex; flex-direction: column; align-items: center; gap: var(--m3-space-4); } +.gd-error__code { + font-family: var(--m3-font-display); + font-size: clamp(4rem, 18vw, 9rem); + line-height: 1; + color: var(--m3-error); + animation: gd-bob 3s var(--m3-ease-standard) infinite; +} +.gd-error__actions { display: flex; flex-wrap: wrap; gap: var(--m3-space-3); justify-content: center; margin-block-start: var(--m3-space-2); } + +@keyframes gd-bob { + 0%, 100% { transform: translateY(0); } + 50% { transform: translateY(-10px); } +} + +/* Redirect / interstitial page --------------------------------------------- */ + +.gd-redirect { + display: grid; + place-items: center; + min-height: 100dvh; + padding: var(--m3-space-6); + text-align: center; + background: var(--m3-surface); +} + +.gd-redirect__card { + display: flex; + flex-direction: column; + align-items: center; + gap: var(--m3-space-4); + width: min(460px, 100%); + padding: clamp(24px, 5vw, 40px); + border-radius: var(--m3-shape-xl); + background: var(--m3-surface-container-low); + box-shadow: var(--m3-elevation-2); +} + +.gd-redirect__logo { + width: 96px; + height: 96px; + border-radius: var(--m3-shape-lg); + object-fit: cover; + animation: gd-bob 2.6s var(--m3-ease-standard) infinite; +} + +.gd-redirect__count { + font-family: var(--m3-font-mono); + font-size: 2.5rem; + font-weight: 600; + color: var(--m3-primary); + font-variant-numeric: tabular-nums; +} + +.gd-redirect__ring { + --m3-meter-value: 0%; + width: 100%; +} + +/* ============================================================================ + Feedback pages + ========================================================================== */ + +.gd-feedback-grid { + display: grid; + gap: var(--m3-space-5); + align-items: start; +} + +@media (min-width: 1024px) { + .gd-feedback-grid { grid-template-columns: minmax(0, 1fr) 340px; } +} + +.gd-feedback-table td:nth-child(1) { white-space: nowrap; color: var(--m3-on-surface-variant); font-size: var(--m3-body-small-size); } +.gd-feedback-table .gd-feedback-text { max-width: 46ch; } +.gd-feedback-actions { display: flex; gap: var(--m3-space-2); flex-wrap: wrap; } + +.gd-faq-list { display: flex; flex-direction: column; gap: var(--m3-space-3); } + +.gd-tabs-wrap { + position: sticky; + inset-block-start: var(--m3-appbar-height); + z-index: 2; + background: var(--m3-surface); + padding-block: var(--m3-space-2); +} + +.gd-legal section + section { margin-block-start: var(--m3-space-8); } + +/* Contact page -------------------------------------------------------------- */ + +.gd-contact-list { display: grid; gap: var(--m3-space-4); } +@media (min-width: 720px) { .gd-contact-list { grid-template-columns: repeat(2, minmax(0, 1fr)); } } + +.gd-contact-card { + display: flex; + gap: var(--m3-space-4); + padding: var(--m3-space-5); + border-radius: var(--m3-shape-lg); + background: var(--m3-surface-container-low); + border: 1px solid var(--m3-outline-variant); + transition: transform var(--m3-duration-short-2) var(--m3-ease-emphasized), box-shadow var(--m3-duration-short-2) var(--m3-ease-standard); +} + +@media (hover: hover) { + .gd-contact-card:hover { transform: translateY(-3px); box-shadow: var(--m3-elevation-2); } +} + +.gd-forms-grid { display: grid; gap: var(--m3-space-4); } +@media (min-width: 720px) { .gd-forms-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } } + +/* Pulse used when a prediction result updates (kept from the original design) */ +@keyframes pulse { + 0%, 100% { transform: scale(1); } + 50% { transform: scale(1.04); } +} diff --git a/main/assets/m3/palettes.css b/main/assets/m3/palettes.css new file mode 100644 index 0000000..00862c6 --- /dev/null +++ b/main/assets/m3/palettes.css @@ -0,0 +1,960 @@ +/* ============================================================================ + GDIPS ยท Material You 3 โ€” Dynamic color palettes + ---------------------------------------------------------------------------- + Material 3 tonal palettes generated from seed colours (CIELAB tone mapping, + gamut-clamped). The default seed is the GDIPS brand red; alternate seeds are + selected with and the runtime generator in + assets/m3/color.js can produce a palette from *any* user-chosen seed. + ========================================================================== */ + +/* โ”€โ”€ Default dynamic palette: GDIPS red โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ + +:root { + --m3-primary: #C00029; + --m3-on-primary: #FFFFFF; + --m3-primary-container: #FFA9A2; + --m3-on-primary-container: #640000; + --m3-primary-fixed: #FFA9A2; + --m3-primary-fixed-dim: #FF8C88; + --m3-on-primary-fixed: #640000; + --m3-on-primary-fixed-variant: #A00014; + --m3-secondary: #864F4C; + --m3-on-secondary: #FFFFFF; + --m3-secondary-container: #FFD3CC; + --m3-on-secondary-container: #390B08; + --m3-tertiary: #745C00; + --m3-on-tertiary: #FFFFFF; + --m3-tertiary-container: #FFDE79; + --m3-on-tertiary-container: #321800; + --m3-error: #B4271F; + --m3-on-error: #FFFFFF; + --m3-error-container: #FFB598; + --m3-on-error-container: #5B0000; + --m3-background: #FFF7F6; + --m3-on-background: #201A1A; + --m3-surface: #FFF7F6; + --m3-on-surface: #201A1A; + --m3-surface-variant: #F5DDDB; + --m3-on-surface-variant: #554240; + --m3-surface-dim: #E1D8D7; + --m3-surface-bright: #FFF7F6; + --m3-surface-container-lowest: #FFFFFF; + --m3-surface-container-low: #FAF2F1; + --m3-surface-container: #F5ECEB; + --m3-surface-container-high: #EFE6E5; + --m3-surface-container-highest: #E9E0E0; + --m3-outline: #877270; + --m3-outline-variant: #D9C1BF; + --m3-inverse-surface: #352F2E; + --m3-inverse-on-surface: #F8EFEE; + --m3-inverse-primary: #FF8C88; + --m3-scrim: #000000; + --m3-shadow: #000000; + --m3-surface-tint: #C00029; +} + +:root[data-theme="dark"] { + --m3-primary: #FF8C88; + --m3-on-primary: #810000; + --m3-primary-container: #A00014; + --m3-on-primary-container: #FFA9A2; + --m3-primary-fixed: #FFA9A2; + --m3-primary-fixed-dim: #FF8C88; + --m3-on-primary-fixed: #640000; + --m3-on-primary-fixed-variant: #A00014; + --m3-secondary: #F7B7B1; + --m3-on-secondary: #522120; + --m3-secondary-container: #6B3835; + --m3-on-secondary-container: #FFD3CC; + --m3-tertiary: #E7C35F; + --m3-on-tertiary: #432E00; + --m3-tertiary-container: #5A4400; + --m3-on-tertiary-container: #FFDE79; + --m3-error: #FF987E; + --m3-on-error: #770000; + --m3-error-container: #950008; + --m3-on-error-container: #FFB598; + --m3-background: #181211; + --m3-on-background: #E9E0E0; + --m3-surface: #181211; + --m3-on-surface: #E9E0E0; + --m3-surface-variant: #554240; + --m3-on-surface-variant: #D9C1BF; + --m3-surface-dim: #181211; + --m3-surface-bright: #3E3837; + --m3-surface-container-lowest: #140C0B; + --m3-surface-container-low: #201A1A; + --m3-surface-container: #241E1D; + --m3-surface-container-high: #2F2828; + --m3-surface-container-highest: #3A3332; + --m3-outline: #A28C89; + --m3-outline-variant: #554240; + --m3-inverse-surface: #E9E0E0; + --m3-inverse-on-surface: #352F2E; + --m3-inverse-primary: #C00029; + --m3-scrim: #000000; + --m3-shadow: #000000; + --m3-surface-tint: #FF8C88; +} + +@media (prefers-color-scheme: dark) { + :root:not([data-theme="light"]) { + --m3-primary: #FF8C88; + --m3-on-primary: #810000; + --m3-primary-container: #A00014; + --m3-on-primary-container: #FFA9A2; + --m3-primary-fixed: #FFA9A2; + --m3-primary-fixed-dim: #FF8C88; + --m3-on-primary-fixed: #640000; + --m3-on-primary-fixed-variant: #A00014; + --m3-secondary: #F7B7B1; + --m3-on-secondary: #522120; + --m3-secondary-container: #6B3835; + --m3-on-secondary-container: #FFD3CC; + --m3-tertiary: #E7C35F; + --m3-on-tertiary: #432E00; + --m3-tertiary-container: #5A4400; + --m3-on-tertiary-container: #FFDE79; + --m3-error: #FF987E; + --m3-on-error: #770000; + --m3-error-container: #950008; + --m3-on-error-container: #FFB598; + --m3-background: #181211; + --m3-on-background: #E9E0E0; + --m3-surface: #181211; + --m3-on-surface: #E9E0E0; + --m3-surface-variant: #554240; + --m3-on-surface-variant: #D9C1BF; + --m3-surface-dim: #181211; + --m3-surface-bright: #3E3837; + --m3-surface-container-lowest: #140C0B; + --m3-surface-container-low: #201A1A; + --m3-surface-container: #241E1D; + --m3-surface-container-high: #2F2828; + --m3-surface-container-highest: #3A3332; + --m3-outline: #A28C89; + --m3-outline-variant: #554240; + --m3-inverse-surface: #E9E0E0; + --m3-inverse-on-surface: #352F2E; + --m3-inverse-primary: #C00029; + --m3-scrim: #000000; + --m3-shadow: #000000; + --m3-surface-tint: #FF8C88; + } +} + +/* โ”€โ”€ Seed: indigo (#6366F1) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ + +:root[data-seed="indigo"] { + --m3-primary: #414ED4; + --m3-on-primary: #FFFFFF; + --m3-primary-container: #DDCFFF; + --m3-on-primary-container: #000E81; + --m3-primary-fixed: #DDCFFF; + --m3-primary-fixed-dim: #BFB4FF; + --m3-on-primary-fixed: #000E81; + --m3-on-primary-fixed-variant: #0D37B8; + --m3-secondary: #5F5985; + --m3-on-secondary: #FFFFFF; + --m3-secondary-container: #E5DCFF; + --m3-on-secondary-container: #18173C; + --m3-tertiary: #AE2562; + --m3-on-tertiary: #FFFFFF; + --m3-tertiary-container: #FFB5E7; + --m3-on-tertiary-container: #58001F; + --m3-error: #B4271F; + --m3-on-error: #FFFFFF; + --m3-error-container: #FFB598; + --m3-on-error-container: #5B0000; + --m3-background: #FAF8FF; + --m3-on-background: #1C1B1F; + --m3-surface: #FAF8FF; + --m3-on-surface: #1C1B1F; + --m3-surface-variant: #E4E0F1; + --m3-on-surface-variant: #484553; + --m3-surface-dim: #DAD9DF; + --m3-surface-bright: #FAF8FF; + --m3-surface-container-lowest: #FFFFFF; + --m3-surface-container-low: #F4F3F9; + --m3-surface-container: #EEEDF3; + --m3-surface-container-high: #E9E7ED; + --m3-surface-container-highest: #E3E2E8; + --m3-outline: #787584; + --m3-outline-variant: #C8C4D5; + --m3-inverse-surface: #313034; + --m3-inverse-on-surface: #F1F0F6; + --m3-inverse-primary: #BFB4FF; + --m3-scrim: #000000; + --m3-shadow: #000000; + --m3-surface-tint: #414ED4; +} + +:root[data-seed="indigo"][data-theme="dark"] { + --m3-primary: #BFB4FF; + --m3-on-primary: #00219C; + --m3-primary-container: #0D37B8; + --m3-on-primary-container: #DDCFFF; + --m3-primary-fixed: #DDCFFF; + --m3-primary-fixed-dim: #BFB4FF; + --m3-on-primary-fixed: #000E81; + --m3-on-primary-fixed-variant: #0D37B8; + --m3-secondary: #C9C0F3; + --m3-on-secondary: #2F2B53; + --m3-secondary-container: #47416C; + --m3-on-secondary-container: #E5DCFF; + --m3-tertiary: #FF98CB; + --m3-on-tertiary: #740034; + --m3-tertiary-container: #91004B; + --m3-on-tertiary-container: #FFB5E7; + --m3-error: #FF987E; + --m3-on-error: #770000; + --m3-error-container: #950008; + --m3-on-error-container: #FFB598; + --m3-background: #141317; + --m3-on-background: #E3E2E8; + --m3-surface: #141317; + --m3-on-surface: #E3E2E8; + --m3-surface-variant: #484553; + --m3-on-surface-variant: #C8C4D5; + --m3-surface-dim: #141317; + --m3-surface-bright: #39383D; + --m3-surface-container-lowest: #0F0D13; + --m3-surface-container-low: #1C1B1F; + --m3-surface-container: #201F23; + --m3-surface-container-high: #2A292E; + --m3-surface-container-highest: #353439; + --m3-outline: #928F9E; + --m3-outline-variant: #484553; + --m3-inverse-surface: #E3E2E8; + --m3-inverse-on-surface: #313034; + --m3-inverse-primary: #414ED4; + --m3-scrim: #000000; + --m3-shadow: #000000; + --m3-surface-tint: #BFB4FF; +} + +@media (prefers-color-scheme: dark) { + :root[data-seed="indigo"]:not([data-theme="light"]) { + --m3-primary: #BFB4FF; + --m3-on-primary: #00219C; + --m3-primary-container: #0D37B8; + --m3-on-primary-container: #DDCFFF; + --m3-primary-fixed: #DDCFFF; + --m3-primary-fixed-dim: #BFB4FF; + --m3-on-primary-fixed: #000E81; + --m3-on-primary-fixed-variant: #0D37B8; + --m3-secondary: #C9C0F3; + --m3-on-secondary: #2F2B53; + --m3-secondary-container: #47416C; + --m3-on-secondary-container: #E5DCFF; + --m3-tertiary: #FF98CB; + --m3-on-tertiary: #740034; + --m3-tertiary-container: #91004B; + --m3-on-tertiary-container: #FFB5E7; + --m3-error: #FF987E; + --m3-on-error: #770000; + --m3-error-container: #950008; + --m3-on-error-container: #FFB598; + --m3-background: #141317; + --m3-on-background: #E3E2E8; + --m3-surface: #141317; + --m3-on-surface: #E3E2E8; + --m3-surface-variant: #484553; + --m3-on-surface-variant: #C8C4D5; + --m3-surface-dim: #141317; + --m3-surface-bright: #39383D; + --m3-surface-container-lowest: #0F0D13; + --m3-surface-container-low: #1C1B1F; + --m3-surface-container: #201F23; + --m3-surface-container-high: #2A292E; + --m3-surface-container-highest: #353439; + --m3-outline: #928F9E; + --m3-outline-variant: #484553; + --m3-inverse-surface: #E3E2E8; + --m3-inverse-on-surface: #313034; + --m3-inverse-primary: #414ED4; + --m3-scrim: #000000; + --m3-shadow: #000000; + --m3-surface-tint: #BFB4FF; + } +} + +/* โ”€โ”€ Seed: violet (#8B5CF6) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ + +:root[data-seed="violet"] { + --m3-primary: #683FD4; + --m3-on-primary: #FFFFFF; + --m3-primary-container: #FEC3FF; + --m3-on-primary-container: #000082; + --m3-primary-fixed: #FEC3FF; + --m3-primary-fixed-dim: #E0A7FF; + --m3-on-primary-fixed: #000082; + --m3-on-primary-fixed-variant: #4925B8; + --m3-secondary: #685686; + --m3-on-secondary: #FFFFFF; + --m3-secondary-container: #F0D9FF; + --m3-on-secondary-container: #21133C; + --m3-tertiary: #B71455; + --m3-on-tertiary: #FFFFFF; + --m3-tertiary-container: #FFAED6; + --m3-on-tertiary-container: #5E0014; + --m3-error: #B4271F; + --m3-on-error: #FFFFFF; + --m3-error-container: #FFB598; + --m3-on-error-container: #5B0000; + --m3-background: #FBF8FE; + --m3-on-background: #1D1B1F; + --m3-surface: #FBF8FE; + --m3-on-surface: #1D1B1F; + --m3-surface-variant: #E7E0F0; + --m3-on-surface-variant: #4A4452; + --m3-surface-dim: #DBD9DF; + --m3-surface-bright: #FBF8FE; + --m3-surface-container-lowest: #FFFFFF; + --m3-surface-container-low: #F5F2F8; + --m3-surface-container: #EFEDF3; + --m3-surface-container-high: #EAE7ED; + --m3-surface-container-highest: #E4E1E7; + --m3-outline: #7B7483; + --m3-outline-variant: #CBC4D4; + --m3-inverse-surface: #313034; + --m3-inverse-on-surface: #F2F0F6; + --m3-inverse-primary: #E0A7FF; + --m3-scrim: #000000; + --m3-shadow: #000000; + --m3-surface-tint: #683FD4; +} + +:root[data-seed="violet"][data-theme="dark"] { + --m3-primary: #E0A7FF; + --m3-on-primary: #25099C; + --m3-primary-container: #4925B8; + --m3-on-primary-container: #FEC3FF; + --m3-primary-fixed: #FEC3FF; + --m3-primary-fixed-dim: #E0A7FF; + --m3-on-primary-fixed: #000082; + --m3-on-primary-fixed-variant: #4925B8; + --m3-secondary: #D3BDF3; + --m3-on-secondary: #372854; + --m3-secondary-container: #4F3E6C; + --m3-on-secondary-container: #F0D9FF; + --m3-tertiary: #FF92BB; + --m3-on-tertiary: #7B0028; + --m3-tertiary-container: #99003E; + --m3-on-tertiary-container: #FFAED6; + --m3-error: #FF987E; + --m3-on-error: #770000; + --m3-error-container: #950008; + --m3-on-error-container: #FFB598; + --m3-background: #151217; + --m3-on-background: #E4E1E7; + --m3-surface: #151217; + --m3-on-surface: #E4E1E7; + --m3-surface-variant: #4A4452; + --m3-on-surface-variant: #CBC4D4; + --m3-surface-dim: #151217; + --m3-surface-bright: #3A383D; + --m3-surface-container-lowest: #100D13; + --m3-surface-container-low: #1D1B1F; + --m3-surface-container: #211F23; + --m3-surface-container-high: #2B292E; + --m3-surface-container-highest: #363438; + --m3-outline: #948E9D; + --m3-outline-variant: #4A4452; + --m3-inverse-surface: #E4E1E7; + --m3-inverse-on-surface: #313034; + --m3-inverse-primary: #683FD4; + --m3-scrim: #000000; + --m3-shadow: #000000; + --m3-surface-tint: #E0A7FF; +} + +@media (prefers-color-scheme: dark) { + :root[data-seed="violet"]:not([data-theme="light"]) { + --m3-primary: #E0A7FF; + --m3-on-primary: #25099C; + --m3-primary-container: #4925B8; + --m3-on-primary-container: #FEC3FF; + --m3-primary-fixed: #FEC3FF; + --m3-primary-fixed-dim: #E0A7FF; + --m3-on-primary-fixed: #000082; + --m3-on-primary-fixed-variant: #4925B8; + --m3-secondary: #D3BDF3; + --m3-on-secondary: #372854; + --m3-secondary-container: #4F3E6C; + --m3-on-secondary-container: #F0D9FF; + --m3-tertiary: #FF92BB; + --m3-on-tertiary: #7B0028; + --m3-tertiary-container: #99003E; + --m3-on-tertiary-container: #FFAED6; + --m3-error: #FF987E; + --m3-on-error: #770000; + --m3-error-container: #950008; + --m3-on-error-container: #FFB598; + --m3-background: #151217; + --m3-on-background: #E4E1E7; + --m3-surface: #151217; + --m3-on-surface: #E4E1E7; + --m3-surface-variant: #4A4452; + --m3-on-surface-variant: #CBC4D4; + --m3-surface-dim: #151217; + --m3-surface-bright: #3A383D; + --m3-surface-container-lowest: #100D13; + --m3-surface-container-low: #1D1B1F; + --m3-surface-container: #211F23; + --m3-surface-container-high: #2B292E; + --m3-surface-container-highest: #363438; + --m3-outline: #948E9D; + --m3-outline-variant: #4A4452; + --m3-inverse-surface: #E4E1E7; + --m3-inverse-on-surface: #313034; + --m3-inverse-primary: #683FD4; + --m3-scrim: #000000; + --m3-shadow: #000000; + --m3-surface-tint: #E0A7FF; + } +} + +/* โ”€โ”€ Seed: crimson (#DC2626) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ + +:root[data-seed="crimson"] { + --m3-primary: #C20014; + --m3-on-primary: #FFFFFF; + --m3-primary-container: #FFA78D; + --m3-on-primary-container: #670000; + --m3-primary-fixed: #FFA78D; + --m3-primary-fixed-dim: #FF8A73; + --m3-on-primary-fixed: #670000; + --m3-on-primary-fixed-variant: #A20000; + --m3-secondary: #884F45; + --m3-on-secondary: #FFFFFF; + --m3-secondary-container: #FFD2C5; + --m3-on-secondary-container: #3A0A00; + --m3-tertiary: #6B5F00; + --m3-on-tertiary: #FFFFFF; + --m3-tertiary-container: #FBE26F; + --m3-on-tertiary-container: #2E1B00; + --m3-error: #B4271F; + --m3-on-error: #FFFFFF; + --m3-error-container: #FFB598; + --m3-on-error-container: #5B0000; + --m3-background: #FFF7F6; + --m3-on-background: #201A19; + --m3-surface: #FFF7F6; + --m3-on-surface: #201A19; + --m3-surface-variant: #F5DDD9; + --m3-on-surface-variant: #55423F; + --m3-surface-dim: #E1D8D6; + --m3-surface-bright: #FFF7F6; + --m3-surface-container-lowest: #FFFFFF; + --m3-surface-container-low: #FAF2F0; + --m3-surface-container: #F5ECEA; + --m3-surface-container-high: #EFE6E5; + --m3-surface-container-highest: #E9E1DF; + --m3-outline: #87726E; + --m3-outline-variant: #D8C1BD; + --m3-inverse-surface: #352F2E; + --m3-inverse-on-surface: #F7EFED; + --m3-inverse-primary: #FF8A73; + --m3-scrim: #000000; + --m3-shadow: #000000; + --m3-surface-tint: #C20014; +} + +:root[data-seed="crimson"][data-theme="dark"] { + --m3-primary: #FF8A73; + --m3-on-primary: #830000; + --m3-primary-container: #930000; + --m3-on-primary-container: #FFA78D; + --m3-primary-fixed: #FFA78D; + --m3-primary-fixed-dim: #FF8A73; + --m3-on-primary-fixed: #670000; + --m3-on-primary-fixed-variant: #A20000; + --m3-secondary: #FAB6AA; + --m3-on-secondary: #53211A; + --m3-secondary-container: #6D372F; + --m3-on-secondary-container: #FFD2C5; + --m3-tertiary: #DEC654; + --m3-on-tertiary: #3C3100; + --m3-tertiary-container: #524700; + --m3-on-tertiary-container: #FBE26F; + --m3-error: #FF987E; + --m3-on-error: #770000; + --m3-error-container: #950008; + --m3-on-error-container: #FFB598; + --m3-background: #181210; + --m3-on-background: #E9E1DF; + --m3-surface: #181210; + --m3-on-surface: #E9E1DF; + --m3-surface-variant: #55423F; + --m3-on-surface-variant: #D8C1BD; + --m3-surface-dim: #181210; + --m3-surface-bright: #3E3836; + --m3-surface-container-lowest: #140C0A; + --m3-surface-container-low: #201A19; + --m3-surface-container: #241E1D; + --m3-surface-container-high: #2F2927; + --m3-surface-container-highest: #3A3332; + --m3-outline: #A18C88; + --m3-outline-variant: #55423F; + --m3-inverse-surface: #E9E1DF; + --m3-inverse-on-surface: #352F2E; + --m3-inverse-primary: #C20014; + --m3-scrim: #000000; + --m3-shadow: #000000; + --m3-surface-tint: #FF8A73; +} + +@media (prefers-color-scheme: dark) { + :root[data-seed="crimson"]:not([data-theme="light"]) { + --m3-primary: #FF8A73; + --m3-on-primary: #830000; + --m3-primary-container: #930000; + --m3-on-primary-container: #FFA78D; + --m3-primary-fixed: #FFA78D; + --m3-primary-fixed-dim: #FF8A73; + --m3-on-primary-fixed: #670000; + --m3-on-primary-fixed-variant: #A20000; + --m3-secondary: #FAB6AA; + --m3-on-secondary: #53211A; + --m3-secondary-container: #6D372F; + --m3-on-secondary-container: #FFD2C5; + --m3-tertiary: #DEC654; + --m3-on-tertiary: #3C3100; + --m3-tertiary-container: #524700; + --m3-on-tertiary-container: #FBE26F; + --m3-error: #FF987E; + --m3-on-error: #770000; + --m3-error-container: #950008; + --m3-on-error-container: #FFB598; + --m3-background: #181210; + --m3-on-background: #E9E1DF; + --m3-surface: #181210; + --m3-on-surface: #E9E1DF; + --m3-surface-variant: #55423F; + --m3-on-surface-variant: #D8C1BD; + --m3-surface-dim: #181210; + --m3-surface-bright: #3E3836; + --m3-surface-container-lowest: #140C0A; + --m3-surface-container-low: #201A19; + --m3-surface-container: #241E1D; + --m3-surface-container-high: #2F2927; + --m3-surface-container-highest: #3A3332; + --m3-outline: #A18C88; + --m3-outline-variant: #55423F; + --m3-inverse-surface: #E9E1DF; + --m3-inverse-on-surface: #352F2E; + --m3-inverse-primary: #C20014; + --m3-scrim: #000000; + --m3-shadow: #000000; + --m3-surface-tint: #FF8A73; + } +} + +/* โ”€โ”€ Seed: emerald (#0F9D58) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ + +:root[data-seed="emerald"] { + --m3-primary: #007030; + --m3-on-primary: #FFFFFF; + --m3-primary-container: #82FAAD; + --m3-on-primary-container: #002900; + --m3-primary-fixed: #82FAAD; + --m3-primary-fixed-dim: #64DD93; + --m3-on-primary-fixed: #002900; + --m3-on-primary-fixed-variant: #005619; + --m3-secondary: #45664F; + --m3-on-secondary: #FFFFFF; + --m3-secondary-container: #C6EBD1; + --m3-on-secondary-container: #01210D; + --m3-tertiary: #006E81; + --m3-on-tertiary: #FFFFFF; + --m3-tertiary-container: #59F6FF; + --m3-on-tertiary-container: #002839; + --m3-error: #B4271F; + --m3-on-error: #FFFFFF; + --m3-error-container: #FFB598; + --m3-on-error-container: #5B0000; + --m3-background: #F5FBF6; + --m3-on-background: #181D19; + --m3-surface: #F5FBF6; + --m3-on-surface: #181D19; + --m3-surface-variant: #D6E7DA; + --m3-on-surface-variant: #3C4A40; + --m3-surface-dim: #D5DBD7; + --m3-surface-bright: #F5FBF6; + --m3-surface-container-lowest: #FFFFFF; + --m3-surface-container-low: #EFF5F0; + --m3-surface-container: #E9EFEB; + --m3-surface-container-high: #E4EAE5; + --m3-surface-container-highest: #DEE4DF; + --m3-outline: #6C7B70; + --m3-outline-variant: #BACBBE; + --m3-inverse-surface: #2D312E; + --m3-inverse-on-surface: #ECF2EE; + --m3-inverse-primary: #64DD93; + --m3-scrim: #000000; + --m3-shadow: #000000; + --m3-surface-tint: #007030; +} + +:root[data-seed="emerald"][data-theme="dark"] { + --m3-primary: #64DD93; + --m3-on-primary: #003E01; + --m3-primary-container: #005619; + --m3-on-primary-container: #82FAAD; + --m3-primary-fixed: #82FAAD; + --m3-primary-fixed-dim: #64DD93; + --m3-on-primary-fixed: #002900; + --m3-on-primary-fixed-variant: #005619; + --m3-secondary: #ABCFB5; + --m3-on-secondary: #173723; + --m3-secondary-container: #2E4D38; + --m3-on-secondary-container: #C6EBD1; + --m3-tertiary: #2ADAEE; + --m3-on-tertiary: #003D50; + --m3-tertiary-container: #005568; + --m3-on-tertiary-container: #59F6FF; + --m3-error: #FF987E; + --m3-on-error: #770000; + --m3-error-container: #950008; + --m3-on-error-container: #FFB598; + --m3-background: #0F1511; + --m3-on-background: #DEE4DF; + --m3-surface: #0F1511; + --m3-on-surface: #DEE4DF; + --m3-surface-variant: #3C4A40; + --m3-on-surface-variant: #BACBBE; + --m3-surface-dim: #0F1511; + --m3-surface-bright: #363A37; + --m3-surface-container-lowest: #09100B; + --m3-surface-container-low: #181D19; + --m3-surface-container: #1C211D; + --m3-surface-container-high: #262B28; + --m3-surface-container-highest: #313632; + --m3-outline: #859589; + --m3-outline-variant: #3C4A40; + --m3-inverse-surface: #DEE4DF; + --m3-inverse-on-surface: #2D312E; + --m3-inverse-primary: #007030; + --m3-scrim: #000000; + --m3-shadow: #000000; + --m3-surface-tint: #64DD93; +} + +@media (prefers-color-scheme: dark) { + :root[data-seed="emerald"]:not([data-theme="light"]) { + --m3-primary: #64DD93; + --m3-on-primary: #003E01; + --m3-primary-container: #005619; + --m3-on-primary-container: #82FAAD; + --m3-primary-fixed: #82FAAD; + --m3-primary-fixed-dim: #64DD93; + --m3-on-primary-fixed: #002900; + --m3-on-primary-fixed-variant: #005619; + --m3-secondary: #ABCFB5; + --m3-on-secondary: #173723; + --m3-secondary-container: #2E4D38; + --m3-on-secondary-container: #C6EBD1; + --m3-tertiary: #2ADAEE; + --m3-on-tertiary: #003D50; + --m3-tertiary-container: #005568; + --m3-on-tertiary-container: #59F6FF; + --m3-error: #FF987E; + --m3-on-error: #770000; + --m3-error-container: #950008; + --m3-on-error-container: #FFB598; + --m3-background: #0F1511; + --m3-on-background: #DEE4DF; + --m3-surface: #0F1511; + --m3-on-surface: #DEE4DF; + --m3-surface-variant: #3C4A40; + --m3-on-surface-variant: #BACBBE; + --m3-surface-dim: #0F1511; + --m3-surface-bright: #363A37; + --m3-surface-container-lowest: #09100B; + --m3-surface-container-low: #181D19; + --m3-surface-container: #1C211D; + --m3-surface-container-high: #262B28; + --m3-surface-container-highest: #313632; + --m3-outline: #859589; + --m3-outline-variant: #3C4A40; + --m3-inverse-surface: #DEE4DF; + --m3-inverse-on-surface: #2D312E; + --m3-inverse-primary: #007030; + --m3-scrim: #000000; + --m3-shadow: #000000; + --m3-surface-tint: #64DD93; + } +} + +/* โ”€โ”€ Seed: amber (#F59E0B) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ + +:root[data-seed="amber"] { + --m3-primary: #924D00; + --m3-on-primary: #FFFFFF; + --m3-primary-container: #FFCF4B; + --m3-on-primary-container: #480400; + --m3-primary-fixed: #FFCF4B; + --m3-primary-fixed-dim: #FFB32C; + --m3-on-primary-fixed: #480400; + --m3-on-primary-fixed-variant: #763500; + --m3-secondary: #775935; + --m3-on-secondary: #FFFFFF; + --m3-secondary-container: #FFDCB2; + --m3-on-secondary-container: #2F1600; + --m3-tertiary: #296C0E; + --m3-on-tertiary: #FFFFFF; + --m3-tertiary-container: #B1F490; + --m3-on-tertiary-container: #002600; + --m3-error: #B4271F; + --m3-on-error: #FFFFFF; + --m3-error-container: #FFB598; + --m3-on-error-container: #5B0000; + --m3-background: #FEF8F3; + --m3-on-background: #1E1B17; + --m3-surface: #FEF8F3; + --m3-on-surface: #1E1B17; + --m3-surface-variant: #EFE0D2; + --m3-on-surface-variant: #504539; + --m3-surface-dim: #DED9D4; + --m3-surface-bright: #FEF8F3; + --m3-surface-container-lowest: #FFFFFF; + --m3-surface-container-low: #F8F3EE; + --m3-surface-container: #F2EDE8; + --m3-surface-container-high: #EDE7E2; + --m3-surface-container-highest: #E7E2DD; + --m3-outline: #817569; + --m3-outline-variant: #D2C4B7; + --m3-inverse-surface: #34302C; + --m3-inverse-on-surface: #F5F0EB; + --m3-inverse-primary: #FFB32C; + --m3-scrim: #000000; + --m3-shadow: #000000; + --m3-surface-tint: #924D00; +} + +:root[data-seed="amber"][data-theme="dark"] { + --m3-primary: #FFB32C; + --m3-on-primary: #5D1E00; + --m3-primary-container: #763500; + --m3-on-primary-container: #FFCF4B; + --m3-primary-fixed: #FFCF4B; + --m3-primary-fixed-dim: #FFB32C; + --m3-on-primary-fixed: #480400; + --m3-on-primary-fixed-variant: #763500; + --m3-secondary: #E6C097; + --m3-on-secondary: #442B08; + --m3-secondary-container: #5D411E; + --m3-on-secondary-container: #FFDCB2; + --m3-tertiary: #96D876; + --m3-on-tertiary: #003B00; + --m3-tertiary-container: #045300; + --m3-on-tertiary-container: #B1F490; + --m3-error: #FF987E; + --m3-on-error: #770000; + --m3-error-container: #950008; + --m3-on-error-container: #FFB598; + --m3-background: #17130E; + --m3-on-background: #E7E2DD; + --m3-surface: #17130E; + --m3-on-surface: #E7E2DD; + --m3-surface-variant: #504539; + --m3-on-surface-variant: #D2C4B7; + --m3-surface-dim: #17130E; + --m3-surface-bright: #3D3835; + --m3-surface-container-lowest: #120D07; + --m3-surface-container-low: #1E1B17; + --m3-surface-container: #231F1B; + --m3-surface-container-high: #2D2926; + --m3-surface-container-highest: #383430; + --m3-outline: #9C8E82; + --m3-outline-variant: #504539; + --m3-inverse-surface: #E7E2DD; + --m3-inverse-on-surface: #34302C; + --m3-inverse-primary: #924D00; + --m3-scrim: #000000; + --m3-shadow: #000000; + --m3-surface-tint: #FFB32C; +} + +@media (prefers-color-scheme: dark) { + :root[data-seed="amber"]:not([data-theme="light"]) { + --m3-primary: #FFB32C; + --m3-on-primary: #5D1E00; + --m3-primary-container: #763500; + --m3-on-primary-container: #FFCF4B; + --m3-primary-fixed: #FFCF4B; + --m3-primary-fixed-dim: #FFB32C; + --m3-on-primary-fixed: #480400; + --m3-on-primary-fixed-variant: #763500; + --m3-secondary: #E6C097; + --m3-on-secondary: #442B08; + --m3-secondary-container: #5D411E; + --m3-on-secondary-container: #FFDCB2; + --m3-tertiary: #96D876; + --m3-on-tertiary: #003B00; + --m3-tertiary-container: #045300; + --m3-on-tertiary-container: #B1F490; + --m3-error: #FF987E; + --m3-on-error: #770000; + --m3-error-container: #950008; + --m3-on-error-container: #FFB598; + --m3-background: #17130E; + --m3-on-background: #E7E2DD; + --m3-surface: #17130E; + --m3-on-surface: #E7E2DD; + --m3-surface-variant: #504539; + --m3-on-surface-variant: #D2C4B7; + --m3-surface-dim: #17130E; + --m3-surface-bright: #3D3835; + --m3-surface-container-lowest: #120D07; + --m3-surface-container-low: #1E1B17; + --m3-surface-container: #231F1B; + --m3-surface-container-high: #2D2926; + --m3-surface-container-highest: #383430; + --m3-outline: #9C8E82; + --m3-outline-variant: #504539; + --m3-inverse-surface: #E7E2DD; + --m3-inverse-on-surface: #34302C; + --m3-inverse-primary: #924D00; + --m3-scrim: #000000; + --m3-shadow: #000000; + --m3-surface-tint: #FFB32C; + } +} + +/* โ”€โ”€ Seed: azure (#2563EB) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ + +:root[data-seed="azure"] { + --m3-primary: #0055D9; + --m3-on-primary: #FFFFFF; + --m3-primary-container: #C2D6FF; + --m3-on-primary-container: #001886; + --m3-primary-fixed: #C2D6FF; + --m3-primary-fixed-dim: #A3BAFF; + --m3-on-primary-fixed: #001886; + --m3-on-primary-fixed-variant: #003EBD; + --m3-secondary: #595B87; + --m3-on-secondary: #FFFFFF; + --m3-secondary-container: #DEDEFF; + --m3-on-secondary-container: #0F193E; + --m3-tertiary: #AB286C; + --m3-on-tertiary: #FFFFFF; + --m3-tertiary-container: #FFB6F2; + --m3-on-tertiary-container: #560027; + --m3-error: #B4271F; + --m3-on-error: #FFFFFF; + --m3-error-container: #FFB598; + --m3-on-error-container: #5B0000; + --m3-background: #F9F9FF; + --m3-on-background: #1B1B1F; + --m3-surface: #F9F9FF; + --m3-on-surface: #1B1B1F; + --m3-surface-variant: #E2E1F2; + --m3-on-surface-variant: #464553; + --m3-surface-dim: #DAD9DF; + --m3-surface-bright: #F9F9FF; + --m3-surface-container-lowest: #FFFFFF; + --m3-surface-container-low: #F3F3F9; + --m3-surface-container: #EEEDF3; + --m3-surface-container-high: #E8E7EE; + --m3-surface-container-highest: #E2E2E8; + --m3-outline: #767685; + --m3-outline-variant: #C6C5D6; + --m3-inverse-surface: #303035; + --m3-inverse-on-surface: #F0F0F6; + --m3-inverse-primary: #A3BAFF; + --m3-scrim: #000000; + --m3-shadow: #000000; + --m3-surface-tint: #0055D9; +} + +:root[data-seed="azure"][data-theme="dark"] { + --m3-primary: #A3BAFF; + --m3-on-primary: #002AA1; + --m3-primary-container: #003EBD; + --m3-on-primary-container: #C2D6FF; + --m3-primary-fixed: #C2D6FF; + --m3-primary-fixed-dim: #A3BAFF; + --m3-on-primary-fixed: #001886; + --m3-on-primary-fixed-variant: #003EBD; + --m3-secondary: #C2C2F5; + --m3-on-secondary: #282D55; + --m3-secondary-container: #40436E; + --m3-on-secondary-container: #DEDEFF; + --m3-tertiary: #FF9AD6; + --m3-on-tertiary: #72003D; + --m3-tertiary-container: #8E0054; + --m3-on-tertiary-container: #FFB6F2; + --m3-error: #FF987E; + --m3-on-error: #770000; + --m3-error-container: #950008; + --m3-on-error-container: #FFB598; + --m3-background: #131317; + --m3-on-background: #E2E2E8; + --m3-surface: #131317; + --m3-on-surface: #E2E2E8; + --m3-surface-variant: #464553; + --m3-on-surface-variant: #C6C5D6; + --m3-surface-dim: #131317; + --m3-surface-bright: #39393D; + --m3-surface-container-lowest: #0E0E13; + --m3-surface-container-low: #1B1B1F; + --m3-surface-container: #1F1F24; + --m3-surface-container-high: #2A292E; + --m3-surface-container-highest: #343439; + --m3-outline: #908F9F; + --m3-outline-variant: #464553; + --m3-inverse-surface: #E2E2E8; + --m3-inverse-on-surface: #303035; + --m3-inverse-primary: #0055D9; + --m3-scrim: #000000; + --m3-shadow: #000000; + --m3-surface-tint: #A3BAFF; +} + +@media (prefers-color-scheme: dark) { + :root[data-seed="azure"]:not([data-theme="light"]) { + --m3-primary: #A3BAFF; + --m3-on-primary: #002AA1; + --m3-primary-container: #003EBD; + --m3-on-primary-container: #C2D6FF; + --m3-primary-fixed: #C2D6FF; + --m3-primary-fixed-dim: #A3BAFF; + --m3-on-primary-fixed: #001886; + --m3-on-primary-fixed-variant: #003EBD; + --m3-secondary: #C2C2F5; + --m3-on-secondary: #282D55; + --m3-secondary-container: #40436E; + --m3-on-secondary-container: #DEDEFF; + --m3-tertiary: #FF9AD6; + --m3-on-tertiary: #72003D; + --m3-tertiary-container: #8E0054; + --m3-on-tertiary-container: #FFB6F2; + --m3-error: #FF987E; + --m3-on-error: #770000; + --m3-error-container: #950008; + --m3-on-error-container: #FFB598; + --m3-background: #131317; + --m3-on-background: #E2E2E8; + --m3-surface: #131317; + --m3-on-surface: #E2E2E8; + --m3-surface-variant: #464553; + --m3-on-surface-variant: #C6C5D6; + --m3-surface-dim: #131317; + --m3-surface-bright: #39393D; + --m3-surface-container-lowest: #0E0E13; + --m3-surface-container-low: #1B1B1F; + --m3-surface-container: #1F1F24; + --m3-surface-container-high: #2A292E; + --m3-surface-container-highest: #343439; + --m3-outline: #908F9F; + --m3-outline-variant: #464553; + --m3-inverse-surface: #E2E2E8; + --m3-inverse-on-surface: #303035; + --m3-inverse-primary: #0055D9; + --m3-scrim: #000000; + --m3-shadow: #000000; + --m3-surface-tint: #A3BAFF; + } +} diff --git a/main/assets/m3/site.css b/main/assets/m3/site.css new file mode 100644 index 0000000..1001aa4 --- /dev/null +++ b/main/assets/m3/site.css @@ -0,0 +1,449 @@ +/* ============================================================================ + GDIPS ยท Material You 3 โ€” Site shell + ---------------------------------------------------------------------------- + Layout + shared page furniture (app bar, drawer, hero, footer, section + headers, team/credit cards, download cards, rating tables) built on top of + tokens.css and components.css. + ========================================================================== */ + +/* โ”€โ”€ Page shell โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ + +.m3-page { + display: flex; + flex-direction: column; + min-height: 100dvh; + background: var(--m3-surface); +} + +.m3-main { flex: 1 1 auto; } + +.m3-main--offset { + padding-block-end: calc(88px + env(safe-area-inset-bottom)); +} + +@media (min-width: 900px) { + .m3-main--offset { padding-block-end: 0; } +} + +/* โ”€โ”€ App bar shortcuts โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ + +.m3-app-bar__brand-mark { + display: grid; + place-items: center; + width: 40px; + height: 40px; + border-radius: var(--m3-shape-md); + background: var(--m3-primary-container); + color: var(--m3-on-primary-container); + font-size: 1.15rem; +} + +.m3-app-bar__brand-mark img { + width: 100%; + height: 100%; + border-radius: inherit; + object-fit: cover; +} + +.m3-theme-toggle .m3-theme-toggle__dark { display: none; } +:root[data-theme='dark'] .m3-theme-toggle .m3-theme-toggle__dark { display: inline-block; } +:root[data-theme='dark'] .m3-theme-toggle .m3-theme-toggle__light { display: none; } + +@media (prefers-color-scheme: dark) { + :root:not([data-theme='light']) .m3-theme-toggle .m3-theme-toggle__dark { display: inline-block; } + :root:not([data-theme='light']) .m3-theme-toggle .m3-theme-toggle__light { display: none; } +} + +/* โ”€โ”€ Hero โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ + +.m3-hero { + position: relative; + overflow: hidden; + padding-block: clamp(32px, 7vw, 72px); + background: + radial-gradient(circle at 12% 18%, color-mix(in srgb, var(--m3-primary-container) 70%, transparent) 0%, transparent 45%), + radial-gradient(circle at 88% 8%, color-mix(in srgb, var(--m3-tertiary-container) 45%, transparent) 0%, transparent 42%), + var(--m3-surface); + isolation: isolate; +} + +.m3-hero__grid { + display: grid; + gap: clamp(24px, 5vw, 48px); + align-items: center; +} + +@media (min-width: 900px) { + .m3-hero__grid { grid-template-columns: 1.1fr 0.9fr; } +} + +.m3-hero__eyebrow { + display: inline-flex; + align-items: center; + gap: 8px; + padding: 6px 14px; + border-radius: var(--m3-shape-full); + background: var(--m3-secondary-container); + color: var(--m3-on-secondary-container); + font-size: var(--m3-label-large-size); + font-weight: var(--m3-label-large-weight); + letter-spacing: var(--m3-tracking-label); +} + +.m3-hero__title { + margin-block: var(--m3-space-4) var(--m3-space-3); + font-size: clamp(2rem, 5.2vw, 3.5rem); + line-height: 1.08; + letter-spacing: var(--m3-tracking-display); + font-weight: 600; +} + +.m3-hero__title em { + font-style: normal; + background: linear-gradient(100deg, var(--m3-primary), var(--m3-tertiary)); + -webkit-background-clip: text; + background-clip: text; + color: transparent; +} + +.m3-hero__lead { + max-width: 60ch; + color: var(--m3-on-surface-variant); + font-size: clamp(1rem, 1.4vw, 1.125rem); + line-height: 1.6; +} + +.m3-hero__actions { margin-block-start: var(--m3-space-6); } + +.m3-hero__visual { + position: relative; + display: grid; + place-items: center; + min-height: 240px; +} + +.m3-hero__orb { + position: relative; + display: grid; + place-items: center; + width: clamp(180px, 40vw, 300px); + aspect-ratio: 1; + border-radius: var(--m3-shape-full); + background: linear-gradient(145deg, var(--m3-primary-container), var(--m3-tertiary-container)); + box-shadow: var(--m3-elevation-3); + animation: m3-float 7s var(--m3-ease-standard) infinite; +} + +.m3-hero__orb img { + width: 62%; + height: 62%; + border-radius: var(--m3-shape-full); + object-fit: cover; + border: 6px solid color-mix(in srgb, var(--m3-surface) 65%, transparent); +} + +.m3-hero__badge { + position: absolute; + display: flex; + align-items: center; + gap: 8px; + padding: 10px 16px; + border-radius: var(--m3-shape-full); + background: var(--m3-surface-container-high); + color: var(--m3-on-surface); + box-shadow: var(--m3-elevation-2); + font-size: var(--m3-label-large-size); + font-weight: var(--m3-label-large-weight); + white-space: nowrap; + z-index: 1; +} + +.m3-hero__badge--tl { inset-block-start: 4%; inset-inline-start: 0; } +.m3-hero__badge--br { inset-block-end: 6%; inset-inline-end: 0; } + +@keyframes m3-float { + 0%, 100% { transform: translateY(0); } + 50% { transform: translateY(-14px); } +} + +/* โ”€โ”€ Section header โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ + +.m3-section-head { + display: flex; + flex-wrap: wrap; + align-items: flex-end; + justify-content: space-between; + gap: var(--m3-space-4); + margin-block-end: var(--m3-space-6); +} + +.m3-section-head__title { font-size: clamp(1.5rem, 3vw, 2rem); font-weight: 600; } +.m3-section-head__sub { color: var(--m3-on-surface-variant); margin-block-start: 6px; max-width: 65ch; } +.m3-section-head--centered { flex-direction: column; align-items: center; text-align: center; } + +/* โ”€โ”€ Feature / stat tiles โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ + +.m3-tile { + display: flex; + flex-direction: column; + gap: var(--m3-space-3); + padding: var(--m3-space-5); + border-radius: var(--m3-shape-lg); + background: var(--m3-surface-container-low); + border: 1px solid var(--m3-outline-variant); + transition: transform var(--m3-duration-medium) var(--m3-ease-emphasized), box-shadow var(--m3-duration-medium) var(--m3-ease-standard), border-color var(--m3-duration-short) var(--m3-ease-standard); +} + +@media (hover: hover) { + .m3-tile:hover { + transform: translateY(-4px); + box-shadow: var(--m3-elevation-2); + border-color: transparent; + } +} + +.m3-tile__icon { + display: grid; + place-items: center; + width: 48px; + height: 48px; + border-radius: var(--m3-shape-md); + background: var(--m3-primary-container); + color: var(--m3-on-primary-container); + font-size: 1.25rem; +} + +.m3-tile__icon--secondary { background: var(--m3-secondary-container); color: var(--m3-on-secondary-container); } +.m3-tile__icon--tertiary { background: var(--m3-tertiary-container); color: var(--m3-on-tertiary-container); } +.m3-tile__title { font-size: var(--m3-title-medium-size); font-weight: var(--m3-title-medium-weight); } +.m3-tile__text { color: var(--m3-on-surface-variant); font-size: var(--m3-body-medium-size); } + +.m3-stat { + display: flex; + flex-direction: column; + gap: 2px; + padding: var(--m3-space-4); + border-radius: var(--m3-shape-md); + background: var(--m3-surface-container); +} + +.m3-stat__value { + font-size: clamp(1.5rem, 3vw, 2rem); + font-weight: 600; + line-height: 1.15; + font-variant-numeric: tabular-nums; +} + +.m3-stat__label { color: var(--m3-on-surface-variant); font-size: var(--m3-label-large-size); font-weight: var(--m3-label-large-weight); letter-spacing: var(--m3-tracking-label); } + +/* โ”€โ”€ Person / credit cards (team, contributors) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ + +.m3-person { + display: flex; + flex-direction: column; + align-items: center; + gap: var(--m3-space-3); + padding: var(--m3-space-6) var(--m3-space-5); + border-radius: var(--m3-shape-xl); + background: var(--m3-surface-container-low); + border: 1px solid var(--m3-outline-variant); + text-align: center; + height: 100%; + transition: transform var(--m3-duration-medium) var(--m3-ease-emphasized), box-shadow var(--m3-duration-medium) var(--m3-ease-standard); +} + +@media (hover: hover) { + .m3-person:hover { transform: translateY(-4px); box-shadow: var(--m3-elevation-2); } +} + +.m3-person__avatar { + width: 96px; + height: 96px; + border-radius: var(--m3-shape-full); + object-fit: cover; + border: 4px solid var(--m3-surface-container-high); + background: var(--m3-surface-container-high); +} + +.m3-person__role { + padding: 4px 12px; + border-radius: var(--m3-shape-full); + background: var(--m3-primary-container); + color: var(--m3-on-primary-container); + font-size: var(--m3-label-medium-size); + font-weight: var(--m3-label-medium-weight); + letter-spacing: var(--m3-tracking-label); +} + +.m3-person__name { font-size: var(--m3-title-large-size); font-weight: 600; } +.m3-person__bio { color: var(--m3-on-surface-variant); font-size: var(--m3-body-medium-size); } +.m3-person__actions { margin-block-start: auto; padding-block-start: var(--m3-space-2); } + +/* โ”€โ”€ Footer โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ + +.m3-footer { + margin-block-start: clamp(32px, 6vw, 64px); + padding-block: var(--m3-space-8) calc(var(--m3-space-8) + env(safe-area-inset-bottom)); + background: var(--m3-surface-container); + color: var(--m3-on-surface-variant); + font-size: var(--m3-body-medium-size); +} + +.m3-footer__grid { + display: grid; + gap: var(--m3-space-8); +} + +@media (min-width: 720px) { + .m3-footer__grid { grid-template-columns: 1.4fr 1fr 1fr; } +} + +.m3-footer__brand { display: flex; align-items: center; gap: var(--m3-space-3); color: var(--m3-on-surface); font-size: var(--m3-title-medium-size); font-weight: 600; } +.m3-footer__brand img { width: 40px; height: 40px; border-radius: var(--m3-shape-sm); } +.m3-footer__heading { color: var(--m3-on-surface); font-size: var(--m3-label-large-size); font-weight: var(--m3-label-large-weight); letter-spacing: var(--m3-tracking-label); text-transform: uppercase; margin-block-end: var(--m3-space-3); } +.m3-footer__links { display: flex; flex-direction: column; gap: var(--m3-space-2); } +.m3-footer__links a { color: var(--m3-on-surface-variant); text-decoration: none; width: fit-content; } +.m3-footer__links a:hover { color: var(--m3-primary); text-decoration: underline; } +.m3-footer__bottom { + margin-block-start: var(--m3-space-8); + padding-block-start: var(--m3-space-4); + border-block-start: 1px solid var(--m3-outline-variant); + display: flex; + flex-wrap: wrap; + gap: var(--m3-space-3); + justify-content: space-between; + align-items: center; + font-size: var(--m3-body-small-size); +} + +/* โ”€โ”€ Rich text / legal pages โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ + +.m3-prose { + max-width: 74ch; + color: var(--m3-on-surface-variant); + font-size: var(--m3-body-large-size); + line-height: 1.7; +} + +.m3-prose > * + * { margin-block-start: var(--m3-space-4); } +.m3-prose h2 { color: var(--m3-on-surface); margin-block-start: var(--m3-space-8); } +.m3-prose h3 { color: var(--m3-on-surface); margin-block-start: var(--m3-space-6); } +.m3-prose strong { color: var(--m3-on-surface); } +.m3-prose ul, +.m3-prose ol { padding-inline-start: 1.5em; display: flex; flex-direction: column; gap: 8px; } +.m3-prose a { text-decoration: underline; text-underline-offset: 2px; } + +/* โ”€โ”€ Progress / rating meters (rating-system page) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ + +.m3-meter { display: flex; flex-direction: column; gap: 6px; } +.m3-meter__head { display: flex; justify-content: space-between; font-size: var(--m3-label-large-size); font-weight: var(--m3-label-large-weight); color: var(--m3-on-surface-variant); } +.m3-meter__track { height: 8px; border-radius: var(--m3-shape-full); background: var(--m3-surface-container-highest); overflow: hidden; } +.m3-meter__fill { height: 100%; border-radius: inherit; background: linear-gradient(90deg, var(--m3-primary), var(--m3-tertiary)); width: var(--m3-meter-value, 0%); transition: width var(--m3-duration-long) var(--m3-ease-emphasized-decel); } + +.m3-rating-chip { + display: inline-flex; + align-items: center; + gap: 8px; + padding: 6px 14px; + border-radius: var(--m3-shape-full); + background: var(--m3-surface-container-highest); + color: var(--m3-on-surface); + font-size: var(--m3-label-large-size); + font-weight: var(--m3-label-large-weight); +} + +.m3-rating-chip i { color: var(--m3-tertiary); } + +/* Difficulty accents reused by the demon list cards */ +:root { + --m3-diff-easy: #2e7d32; + --m3-diff-medium: #ef6c00; + --m3-diff-hard: #c62828; + --m3-diff-insane: #6a1b9a; + --m3-diff-extreme: #1565c0; + --m3-diff-impossible: #37474f; +} + +:root[data-theme='dark'] { + --m3-diff-easy: #81c995; + --m3-diff-medium: #ffb74d; + --m3-diff-hard: #f28b82; + --m3-diff-insane: #d7aefb; + --m3-diff-extreme: #8ab4f8; + --m3-diff-impossible: #cfd8dc; +} + +/* โ”€โ”€ Utility: two-column split used by several pages โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ + +.m3-split { + display: grid; + gap: clamp(20px, 4vw, 40px); + align-items: start; +} + +@media (min-width: 1024px) { + .m3-split { grid-template-columns: minmax(0, 1fr) minmax(280px, 360px); } + .m3-split--reverse { grid-template-columns: minmax(280px, 360px) minmax(0, 1fr); } +} + +.m3-aside { + display: flex; + flex-direction: column; + gap: var(--m3-space-4); + position: sticky; + inset-block-start: calc(var(--m3-appbar-height) + 16px); +} + +.m3-panel { + padding: var(--m3-space-5); + border-radius: var(--m3-shape-lg); + background: var(--m3-surface-container-low); + border: 1px solid var(--m3-outline-variant); +} + +.m3-panel--filled { background: var(--m3-surface-container-high); border-color: transparent; } + +/* โ”€โ”€ Print โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ + +@media print { + .m3-app-bar, + .m3-drawer, + .m3-nav-bar, + .m3-footer, + .m3-scrim, + .m3-fab { display: none !important; } + + body { background: #fff; color: #000; } +} + +/* โ”€โ”€ Scroll reveal โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ + +.m3-reveal { + opacity: 0; + transform: translateY(18px); + transition: + opacity var(--m3-duration-long) var(--m3-ease-emphasized-decel), + transform var(--m3-duration-long) var(--m3-ease-emphasized-decel); + will-change: opacity, transform; +} + +.m3-reveal.is-visible { opacity: 1; transform: none; } + +@media (prefers-reduced-motion: reduce) { + .m3-reveal { opacity: 1; transform: none; } +} + +/* โ”€โ”€ Small shared helpers used across the redesigned pages โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ + +.m3-meta { + color: var(--m3-on-surface-variant); + font-size: var(--m3-body-small-size); +} + +.m3-drawer__meta { + color: var(--m3-on-surface-variant); + font-size: 0.75rem; + line-height: 1; +} + +.gd-year { font-variant-numeric: tabular-nums; } diff --git a/main/assets/m3/tokens.css b/main/assets/m3/tokens.css new file mode 100644 index 0000000..4e9da65 --- /dev/null +++ b/main/assets/m3/tokens.css @@ -0,0 +1,503 @@ +/* ============================================================================ + GDIPS ยท Material You 3 โ€” Design tokens + ---------------------------------------------------------------------------- + Non-colour tokens (type scale, shape, elevation, motion, spacing) shared by + every page. Colour roles live in palettes.css and are generated from a seed + colour, so themes are fully dynamic. + ========================================================================== */ + +/* Self-hosted UI faces (no third-party font requests). Variable weight axes. */ +@font-face { + font-family: 'Roboto Flex'; + src: url('../vendor/fonts/roboto-flex-latin-wght-normal.woff2') format('woff2'); + font-style: normal; + font-weight: 100 1000; + font-display: swap; +} +@font-face { + font-family: 'JetBrains Mono'; + src: url('../vendor/fonts/jetbrains-mono-latin-wght-normal.woff2') format('woff2'); + font-style: normal; + font-weight: 100 800; + font-display: swap; +} + +/* Local display face used for GDIPS "game style" headlines (404, bootloader) */ +@font-face { + font-family: 'Pusab'; + src: url('../Pusab.ttf') format('truetype'); + font-display: swap; + font-weight: 400; +} + +:root { + /* โ”€โ”€ Typography โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + Material 3 expressive scale. Roboto Flex is the variable M3 face; the + Grotesk stack keeps the "GDIPS" personality in display sizes. */ + --m3-font-brand: 'Roboto Flex', 'Google Sans', 'Roboto', 'Segoe UI', system-ui, sans-serif; + --m3-font-plain: 'Roboto Flex', 'Roboto', 'Segoe UI', system-ui, -apple-system, sans-serif; + --m3-font-mono: 'JetBrains Mono', ui-monospace, 'SFMono-Regular', 'Cascadia Code', Consolas, monospace; + --m3-font-display: 'Pusab', 'Roboto Flex', 'Roboto', system-ui, sans-serif; + + --m3-display-large-size: 3.5625rem; /* 57 */ + --m3-display-medium-size: 2.8125rem; /* 45 */ + --m3-display-small-size: 2.25rem; /* 36 */ + --m3-headline-large-size: 2rem; /* 32 */ + --m3-headline-medium-size: 1.75rem; /* 28 */ + --m3-headline-small-size: 1.5rem; /* 24 */ + --m3-title-large-size: 1.375rem; /* 22 */ + --m3-title-medium-size: 1rem; /* 16 */ + --m3-title-small-size: 0.875rem; /* 14 */ + --m3-body-large-size: 1rem; /* 16 */ + --m3-body-medium-size: 0.875rem; /* 14 */ + --m3-body-small-size: 0.75rem; /* 12 */ + --m3-label-large-size: 0.875rem; /* 14 */ + --m3-label-medium-size: 0.75rem; /* 12 */ + --m3-label-small-size: 0.6875rem; /* 11 */ + + --m3-display-large-line: 4rem; + --m3-display-medium-line: 3.25rem; + --m3-display-small-line: 2.75rem; + --m3-headline-large-line: 2.5rem; + --m3-headline-medium-line: 2.25rem; + --m3-headline-small-line: 2rem; + --m3-title-large-line: 1.75rem; + --m3-title-medium-line: 1.5rem; + --m3-title-small-line: 1.25rem; + --m3-body-large-line: 1.5rem; + --m3-body-medium-line: 1.25rem; + --m3-body-small-line: 1rem; + --m3-label-large-line: 1.25rem; + --m3-label-medium-line: 1rem; + --m3-label-small-line: 1rem; + + --m3-display-large-weight: 500; + --m3-display-small-weight: 500; + --m3-headline-weight: 500; + --m3-title-large-weight: 500; + --m3-title-medium-weight: 600; + --m3-title-small-weight: 600; + --m3-body-weight: 400; + --m3-label-large-weight: 600; + --m3-label-medium-weight: 600; + + --m3-tracking-display: -0.02em; + --m3-tracking-headline: -0.012em; + --m3-tracking-title: 0.006em; + --m3-tracking-body: 0.015em; + --m3-tracking-label: 0.035em; + + /* โ”€โ”€ Shape (corner radii) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ + --m3-shape-none: 0; + --m3-shape-xs: 4px; + --m3-shape-sm: 8px; + --m3-shape-md: 12px; + --m3-shape-lg: 16px; + --m3-shape-xl: 28px; + --m3-shape-2xl: 32px; + --m3-shape-full: 999px; + + /* โ”€โ”€ Elevation (M3 key + ambient shadows) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ + --m3-elevation-0: none; + --m3-elevation-1: 0 1px 2px 0 rgb(0 0 0 / 0.30), 0 1px 3px 1px rgb(0 0 0 / 0.15); + --m3-elevation-2: 0 1px 2px 0 rgb(0 0 0 / 0.30), 0 2px 6px 2px rgb(0 0 0 / 0.15); + --m3-elevation-3: 0 1px 3px 0 rgb(0 0 0 / 0.30), 0 4px 8px 3px rgb(0 0 0 / 0.15); + --m3-elevation-4: 0 2px 3px 0 rgb(0 0 0 / 0.30), 0 6px 10px 4px rgb(0 0 0 / 0.15); + --m3-elevation-5: 0 4px 4px 0 rgb(0 0 0 / 0.30), 0 8px 12px 6px rgb(0 0 0 / 0.15); + + /* โ”€โ”€ Spacing (4dp grid) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ + --m3-space-1: 4px; + --m3-space-2: 8px; + --m3-space-3: 12px; + --m3-space-4: 16px; + --m3-space-5: 20px; + --m3-space-6: 24px; + --m3-space-7: 28px; + --m3-space-8: 32px; + --m3-space-10: 40px; + --m3-space-12: 48px; + --m3-space-16: 64px; + --m3-space-20: 80px; + + --m3-page-gutter: clamp(16px, 4vw, 32px); + --m3-content-max: 1200px; + --m3-content-wide: 1440px; + --m3-appbar-height: 64px; + + /* โ”€โ”€ Motion โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ + --m3-ease-standard: cubic-bezier(0.2, 0, 0, 1); + --m3-ease-standard-decel: cubic-bezier(0.05, 0.7, 0.1, 1); + --m3-ease-standard-accel: cubic-bezier(0.3, 0, 0.8, 0.15); + --m3-ease-emphasized: cubic-bezier(0.2, 0, 0, 1); + --m3-ease-emphasized-decel: cubic-bezier(0.05, 0.7, 0.1, 1); + --m3-ease-emphasized-accel: cubic-bezier(0.3, 0, 0.8, 0.15); + --m3-ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1); + --m3-duration-short: 150ms; + --m3-duration-short-2: 200ms; + --m3-duration-medium: 300ms; + --m3-duration-long: 500ms; + --m3-duration-extra-long: 700ms; + + /* โ”€โ”€ State layers (M3 interaction opacities) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ + --m3-state-hover: 0.08; + --m3-state-focus: 0.10; + --m3-state-pressed: 0.10; + --m3-state-drag: 0.16; + --m3-state-disabled-content: 0.38; + --m3-state-disabled-container: 0.12; + + /* โ”€โ”€ Misc โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ + --m3-focus-ring: 3px; + --m3-z-drawer: 1000; + --m3-z-appbar: 900; + --m3-z-dialog: 1200; + --m3-z-menu: 1100; + --m3-z-snackbar: 1300; + --m3-z-tooltip: 1400; + + color-scheme: light; +} + +:root[data-theme='dark'] { + color-scheme: dark; + --m3-elevation-1: 0 1px 3px 1px rgb(0 0 0 / 0.55), 0 1px 2px 0 rgb(0 0 0 / 0.7); + --m3-elevation-2: 0 2px 6px 2px rgb(0 0 0 / 0.55), 0 1px 2px 0 rgb(0 0 0 / 0.7); + --m3-elevation-3: 0 4px 8px 3px rgb(0 0 0 / 0.55), 0 1px 3px 0 rgb(0 0 0 / 0.7); + --m3-elevation-4: 0 6px 10px 4px rgb(0 0 0 / 0.55), 0 2px 3px 0 rgb(0 0 0 / 0.7); + --m3-elevation-5: 0 8px 12px 6px rgb(0 0 0 / 0.55), 0 4px 4px 0 rgb(0 0 0 / 0.7); +} + +/* ============================================================================ + Base / reset + ========================================================================== */ + +*, +*::before, +*::after { + box-sizing: border-box; +} + +html { + -webkit-text-size-adjust: 100%; + text-size-adjust: 100%; + scroll-behavior: smooth; + scroll-padding-top: calc(var(--m3-appbar-height) + 16px); +} + +body { + margin: 0; + min-height: 100dvh; + font-family: var(--m3-font-plain); + font-size: var(--m3-body-large-size); + line-height: var(--m3-body-large-line); + letter-spacing: var(--m3-tracking-body); + font-weight: var(--m3-body-weight); + color: var(--m3-on-surface); + background-color: var(--m3-surface); + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-rendering: optimizeLegibility; + font-variant-ligatures: common-ligatures; +} + +h1, +h2, +h3, +h4, +h5, +h6, +p, +figure, +blockquote, +dl, +dd { + margin: 0; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + font-family: var(--m3-font-brand); + font-weight: var(--m3-headline-weight); + letter-spacing: var(--m3-tracking-headline); + line-height: 1.25; + text-wrap: balance; +} + +h1 { font-size: var(--m3-headline-large-size); } +h2 { font-size: var(--m3-headline-medium-size); } +h3 { font-size: var(--m3-title-large-size); font-weight: var(--m3-title-large-weight); } +h4 { font-size: var(--m3-title-medium-size); font-weight: var(--m3-title-medium-weight); } +h5 { font-size: var(--m3-title-small-size); } + +p { text-wrap: pretty; } + +ul, +ol { + margin: 0; + padding-inline-start: 1.35em; +} + +img, +svg, +video, +canvas, +iframe { + max-width: 100%; + display: block; +} + +img { height: auto; } + +a { + color: var(--m3-primary); + text-decoration: none; + border-radius: var(--m3-shape-xs); + transition: color var(--m3-duration-short) var(--m3-ease-standard); +} + +a:hover { color: var(--m3-primary); text-decoration: underline; } +a:visited { color: var(--m3-tertiary); } + +button, +input, +select, +textarea { + font: inherit; + letter-spacing: inherit; + color: inherit; +} + +button { cursor: pointer; } +button:disabled { cursor: not-allowed; } + +hr { + border: 0; + border-top: 1px solid var(--m3-outline-variant); + margin-block: var(--m3-space-5); +} + +code, +kbd, +samp, +pre { + font-family: var(--m3-font-mono); + font-size: 0.9em; +} + +kbd { + display: inline-block; + padding: 0.1em 0.45em; + border-radius: var(--m3-shape-xs); + background: var(--m3-surface-container-high); + border: 1px solid var(--m3-outline-variant); + border-bottom-width: 2px; + color: var(--m3-on-surface-variant); + font-size: var(--m3-label-medium-size); + line-height: 1.5; +} + +strong, +b { font-weight: 650; } + +small { font-size: var(--m3-body-small-size); } + +/* โ”€โ”€ Focus โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ +:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible, +.m3-focus-ring:focus-visible { + outline: var(--m3-focus-ring) solid var(--m3-secondary); + outline-offset: 2px; +} + +:focus:not(:focus-visible) { outline: none; } + +/* โ”€โ”€ Selection & scrollbars โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ +::selection { + background: var(--m3-primary); + color: var(--m3-on-primary); +} + +* { + scrollbar-color: var(--m3-outline) transparent; + scrollbar-width: thin; +} + +::-webkit-scrollbar { width: 10px; height: 10px; } +::-webkit-scrollbar-track { background: transparent; } +::-webkit-scrollbar-thumb { + background: var(--m3-outline-variant); + border-radius: var(--m3-shape-full); + border: 3px solid transparent; + background-clip: content-box; +} +::-webkit-scrollbar-thumb:hover { background-clip: content-box; background-color: var(--m3-outline); } + +/* ============================================================================ + Typography utilities + ========================================================================== */ + +.m3-display-large, +.m3-display-medium, +.m3-display-small, +.m3-headline-large, +.m3-headline-medium, +.m3-headline-small, +.m3-title-large, +.m3-title-medium, +.m3-title-small, +.m3-body-large, +.m3-body-medium, +.m3-body-small, +.m3-label-large, +.m3-label-medium, +.m3-label-small { + font-family: var(--m3-font-brand); + margin: 0; +} + +.m3-display-large { font-size: var(--m3-display-large-size); line-height: var(--m3-display-large-line); font-weight: var(--m3-display-large-weight); letter-spacing: var(--m3-tracking-display); } +.m3-display-medium { font-size: var(--m3-display-medium-size); line-height: var(--m3-display-medium-line); font-weight: var(--m3-display-large-weight); letter-spacing: var(--m3-tracking-display); } +.m3-display-small { font-size: var(--m3-display-small-size); line-height: var(--m3-display-small-line); font-weight: var(--m3-display-small-weight); letter-spacing: var(--m3-tracking-display); } +.m3-headline-large { font-size: var(--m3-headline-large-size); line-height: var(--m3-headline-large-line); letter-spacing: var(--m3-tracking-headline); } +.m3-headline-medium { font-size: var(--m3-headline-medium-size); line-height: var(--m3-headline-medium-line); letter-spacing: var(--m3-tracking-headline); } +.m3-headline-small { font-size: var(--m3-headline-small-size); line-height: var(--m3-headline-small-line); letter-spacing: var(--m3-tracking-headline); } +.m3-title-large { font-size: var(--m3-title-large-size); line-height: var(--m3-title-large-line); font-weight: var(--m3-title-large-weight); letter-spacing: var(--m3-tracking-title); } +.m3-title-medium { font-size: var(--m3-title-medium-size); line-height: var(--m3-title-medium-line); font-weight: var(--m3-title-medium-weight); letter-spacing: var(--m3-tracking-title); } +.m3-title-small { font-size: var(--m3-title-small-size); line-height: var(--m3-title-small-line); font-weight: var(--m3-title-small-weight); letter-spacing: var(--m3-tracking-title); } + +.m3-body-large { font-family: var(--m3-font-plain); font-size: var(--m3-body-large-size); line-height: var(--m3-body-large-line); letter-spacing: var(--m3-tracking-body); } +.m3-body-medium { font-family: var(--m3-font-plain); font-size: var(--m3-body-medium-size); line-height: var(--m3-body-medium-line); letter-spacing: var(--m3-tracking-body); } +.m3-body-small { font-family: var(--m3-font-plain); font-size: var(--m3-body-small-size); line-height: var(--m3-body-small-line); letter-spacing: var(--m3-tracking-body); } +.m3-label-large { font-family: var(--m3-font-plain); font-size: var(--m3-label-large-size); line-height: var(--m3-label-large-line); font-weight: var(--m3-label-large-weight); letter-spacing: var(--m3-tracking-label); } +.m3-label-medium { font-family: var(--m3-font-plain); font-size: var(--m3-label-medium-size); line-height: var(--m3-label-medium-line); font-weight: var(--m3-label-medium-weight); letter-spacing: var(--m3-tracking-label); } +.m3-label-small { font-family: var(--m3-font-plain); font-size: var(--m3-label-small-size); line-height: var(--m3-label-small-line); font-weight: var(--m3-label-medium-weight); letter-spacing: var(--m3-tracking-label); } + +.m3-mono { font-family: var(--m3-font-mono); font-variant-numeric: tabular-nums; } +.m3-display-font { font-family: var(--m3-font-display); letter-spacing: 0.01em; } +.m3-text-primary { color: var(--m3-primary); } +.m3-text-muted { color: var(--m3-on-surface-variant); } +.m3-text-error { color: var(--m3-error); } +.m3-truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } +.m3-clamp-2 { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; } +.m3-clamp-3 { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; } + +/* ============================================================================ + Layout helpers + ========================================================================== */ + +.m3-container { + width: 100%; + max-width: var(--m3-content-max); + margin-inline: auto; + padding-inline: var(--m3-page-gutter); +} + +.m3-container--wide { max-width: var(--m3-content-wide); } + +.m3-section { padding-block: clamp(24px, 6vw, 56px); } + +.m3-stack { display: flex; flex-direction: column; gap: var(--m3-space-4); } +.m3-row { display: flex; flex-wrap: wrap; gap: var(--m3-space-3); align-items: center; } +.m3-spacer { flex: 1 1 auto; } + +.m3-grid { display: grid; gap: var(--m3-space-5); } +.m3-grid--auto { grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr)); } +.m3-grid--2 { grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr)); } +.m3-grid--3 { grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr)); } + +.m3-shape-none { border-radius: 0; } +.m3-shape-xs { border-radius: var(--m3-shape-xs); } +.m3-shape-sm { border-radius: var(--m3-shape-sm); } +.m3-shape-md { border-radius: var(--m3-shape-md); } +.m3-shape-lg { border-radius: var(--m3-shape-lg); } +.m3-shape-xl { border-radius: var(--m3-shape-xl); } +.m3-shape-full { border-radius: var(--m3-shape-full); } + +.m3-elevation-0 { box-shadow: var(--m3-elevation-0); } +.m3-elevation-1 { box-shadow: var(--m3-elevation-1); } +.m3-elevation-2 { box-shadow: var(--m3-elevation-2); } +.m3-elevation-3 { box-shadow: var(--m3-elevation-3); } +.m3-elevation-4 { box-shadow: var(--m3-elevation-4); } +.m3-elevation-5 { box-shadow: var(--m3-elevation-5); } + +.m3-hidden { display: none !important; } +.m3-visually-hidden, +.sr-only { + position: absolute !important; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0 0 0 0); + clip-path: inset(50%); + white-space: nowrap; + border: 0; +} + +.m3-skip-link { + position: absolute; + inset-inline-start: var(--m3-space-4); + top: -80px; + z-index: calc(var(--m3-z-snackbar) + 1); + padding: 12px 20px; + border-radius: var(--m3-shape-full); + background: var(--m3-primary); + color: var(--m3-on-primary); + font-weight: 650; + box-shadow: var(--m3-elevation-3); + transition: top var(--m3-duration-short-2) var(--m3-ease-emphasized-decel); +} + +.m3-skip-link:focus { top: var(--m3-space-4); text-decoration: none; } + +/* ============================================================================ + Motion + ========================================================================== */ + +@media (prefers-reduced-motion: reduce) { + html { scroll-behavior: auto; } + + *, + *::before, + *::after { + animation-duration: 0.001ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.001ms !important; + scroll-behavior: auto !important; + } +} + +@media (prefers-contrast: more) { + :root { + --m3-outline-variant: var(--m3-outline); + } + + .m3-card, + .m3-button, + .m3-text-field, + .m3-navigation-drawer { + border-color: currentColor; + } +} + +/* โ”€โ”€ Responsive visibility helpers โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ + +@media (max-width: 599px) { + .m3-hide-sm { display: none !important; } +} + +@media (min-width: 600px) and (max-width: 899px) { + .m3-hide-md { display: none !important; } +} + +@media (max-width: 899px) { + .m3-hide-below-md { display: none !important; } +} + +@media (min-width: 900px) { + .m3-show-below-md { display: none !important; } +} diff --git a/main/assets/m3/ui.js b/main/assets/m3/ui.js new file mode 100644 index 0000000..1d2fbda --- /dev/null +++ b/main/assets/m3/ui.js @@ -0,0 +1,583 @@ +/* ============================================================================ + GDIPS ยท Material You 3 โ€” Interaction layer + ---------------------------------------------------------------------------- + Progressive enhancement for the M3 components: ripples, app-bar elevation, + navigation drawers + scrims, menus, dialogs (with focus trap), tabs, + segmented buttons, text-field state, sliders, snackbars, copy-to-clipboard + and scroll reveals. Every behaviour is declarative โ€” pages only add data + attributes, no per-page scripting required. + + Public API + M3UI.snackbar(message, opts) transient message with optional action + M3UI.openDialog(elOrId) / close() dialog helpers + M3UI.openDrawer(elOrId, open) drawer helpers + M3UI.setLoading(el, bool) button loading state + M3UI.copy(text) clipboard helper + ========================================================================== */ + +(function (global) { + 'use strict'; + + var REDUCED = global.matchMedia && global.matchMedia('(prefers-reduced-motion: reduce)').matches; + var FOCUSABLE = 'a[href],button:not([disabled]),input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex="-1"])'; + + function $(sel, scope) { return (scope || document).querySelector(sel); } + function $$(sel, scope) { return Array.prototype.slice.call((scope || document).querySelectorAll(sel)); } + function byId(id) { return typeof id === 'string' ? document.getElementById(id.replace(/^#/, '')) : id; } + + /* โ”€โ”€ Scroll lock โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ + + var lockCount = 0; + function lockScroll() { + if (lockCount++ === 0) { + var gap = global.innerWidth - document.documentElement.clientWidth; + document.body.style.overflow = 'hidden'; + if (gap > 0) document.body.style.paddingInlineEnd = gap + 'px'; + } + } + function unlockScroll() { + if (lockCount > 0 && --lockCount === 0) { + document.body.style.overflow = ''; + document.body.style.paddingInlineEnd = ''; + } + } + + /* โ”€โ”€ Ripple โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ + + var RIPPLE_SELECTOR = [ + '.m3-button', '.m3-icon-button', '.m3-fab', '.m3-chip', '.m3-tab', + '.m3-list-item', '.m3-menu-item', '.m3-page-btn', '.m3-nav-bar__item', + '.m3-drawer__item', '.m3-segmented__item', '.m3-card--interactive', + '.sidebar-link', '.card-action-btn', '.view-btn', '.action-btn', '.filter-option' + ].join(','); + + function attachRipple(el) { + if (REDUCED || el.dataset.m3Ripple === 'off') return; + el.addEventListener('pointerdown', function (event) { + var rect = el.getBoundingClientRect(); + var size = Math.max(rect.width, rect.height) * 2; + var ripple = document.createElement('span'); + ripple.className = 'm3-ripple'; + ripple.style.width = ripple.style.height = size + 'px'; + ripple.style.left = (event.clientX - rect.left - size / 2) + 'px'; + ripple.style.top = (event.clientY - rect.top - size / 2) + 'px'; + if (getComputedStyle(el).position === 'static') el.style.position = 'relative'; + el.appendChild(ripple); + setTimeout(function () { ripple.remove(); }, 600); + }); + } + + /* โ”€โ”€ App bar elevation on scroll โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ + + function setupAppBars(scope) { + $$('.m3-app-bar', scope).forEach(function (bar) { + if (bar.dataset.m3Bound) return; + bar.dataset.m3Bound = '1'; + var sentinel = document.createElement('div'); + sentinel.setAttribute('aria-hidden', 'true'); + sentinel.style.cssText = 'position:absolute;top:0;left:0;height:1px;width:1px;'; + bar.parentNode.insertBefore(sentinel, bar); + if ('IntersectionObserver' in global) { + new IntersectionObserver(function (entries) { + bar.classList.toggle('is-scrolled', !entries[0].isIntersecting); + }, { threshold: 0 }).observe(sentinel); + } + }); + } + + /* โ”€โ”€ Drawers โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ + + function setDrawer(drawer, open) { + if (!drawer) return; + var wasOpen = drawer.classList.contains('is-open') || drawer.classList.contains('active'); + drawer.classList.toggle('is-open', open); + drawer.classList.toggle('active', open); + drawer.setAttribute('aria-hidden', open ? 'false' : 'true'); + var scrim = $('.m3-scrim[data-m3-scrim-for="#' + drawer.id + '"]') || $('.m3-scrim.is-paired'); + if (scrim) scrim.classList.toggle('is-open', open); + if (open && !wasOpen) { + lockScroll(); + var focusable = $(FOCUSABLE, drawer); + if (focusable) setTimeout(function () { focusable.focus(); }, 220); + } else if (!open && wasOpen) { + unlockScroll(); + } + if (!open) { + var toggle = $('[data-m3-drawer-toggle="#' + drawer.id + '"]'); + if (toggle) toggle.focus(); + } + } + + function setupDrawers(scope) { + $$('[data-m3-drawer-toggle]', scope).forEach(function (toggle) { + if (toggle.dataset.m3Bound) return; + toggle.dataset.m3Bound = '1'; + toggle.addEventListener('click', function (event) { + event.preventDefault(); + var drawer = byId(toggle.getAttribute('data-m3-drawer-toggle')); + if (!drawer) return; + setDrawer(drawer, !(drawer.classList.contains('is-open') || drawer.classList.contains('active'))); + }); + }); + + $$('[data-m3-drawer-close]', scope).forEach(function (btn) { + if (btn.dataset.m3Bound) return; + btn.dataset.m3Bound = '1'; + btn.addEventListener('click', function () { setDrawer(btn.closest('.m3-drawer, .sidebar'), false); }); + }); + + // Bridge for drawers whose open/close state is owned by legacy scripts + // (the demon list toggles `.active` itself โ€” we only mirror it). + $$('[data-m3-scrim-for]', scope).forEach(function (scrim) { + var drawer = byId(scrim.getAttribute('data-m3-scrim-for')); + if (!drawer || scrim.dataset.m3Bound) return; + scrim.dataset.m3Bound = '1'; + var sync = function () { + var open = drawer.classList.contains('is-open') || drawer.classList.contains('active'); + scrim.classList.toggle('is-open', open); + if (open) { lockScroll(); } else { unlockScroll(); } + }; + new MutationObserver(sync).observe(drawer, { attributes: true, attributeFilter: ['class'] }); + scrim.addEventListener('click', function () { + drawer.classList.remove('is-open', 'active'); + if (typeof global.DemonListApp !== 'undefined') { /* legacy app keeps its own state */ } + setDrawer(drawer, false); + }); + sync(); + }); + } + + /* โ”€โ”€ Menus โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ + + function closeMenus(except) { + $$('.m3-menu.is-open').forEach(function (menu) { + if (menu === except) return; + menu.classList.remove('is-open'); + var trigger = $('[data-m3-menu-trigger="#' + menu.id + '"]'); + if (trigger) trigger.setAttribute('aria-expanded', 'false'); + }); + } + + function setupMenus(scope) { + $$('[data-m3-menu-trigger]', scope).forEach(function (trigger) { + if (trigger.dataset.m3Bound) return; + trigger.dataset.m3Bound = '1'; + trigger.setAttribute('aria-haspopup', 'true'); + trigger.setAttribute('aria-expanded', 'false'); + trigger.addEventListener('click', function (event) { + event.preventDefault(); + event.stopPropagation(); + var menu = byId(trigger.getAttribute('data-m3-menu-trigger')); + if (!menu) return; + var willOpen = !menu.classList.contains('is-open'); + closeMenus(menu); + menu.classList.toggle('is-open', willOpen); + trigger.setAttribute('aria-expanded', String(willOpen)); + }); + }); + + $$('.m3-menu', scope).forEach(function (menu) { + if (menu.dataset.m3Bound) return; + menu.dataset.m3Bound = '1'; + menu.addEventListener('click', function (event) { + if (event.target.closest('[data-m3-menu-keep]')) return; + if (event.target.closest('.m3-menu-item')) closeMenus(); + }); + }); + } + + /* โ”€โ”€ Dialogs โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ + + var openDialogs = []; + + function openDialog(target) { + var dialog = byId(target); + if (!dialog) return; + dialog.classList.add('is-open'); + dialog.setAttribute('aria-hidden', 'false'); + openDialogs.push(dialog); + lockScroll(); + var focusable = $(FOCUSABLE, dialog); + if (focusable) setTimeout(function () { focusable.focus(); }, 180); + dialog.dispatchEvent(new CustomEvent('m3dialog:open', { bubbles: true })); + } + + function closeDialog(target) { + var dialog = target ? byId(target) : openDialogs[openDialogs.length - 1]; + if (!dialog) return; + dialog.classList.remove('is-open'); + dialog.setAttribute('aria-hidden', 'true'); + openDialogs = openDialogs.filter(function (d) { return d !== dialog; }); + unlockScroll(); + var trigger = $('[data-m3-dialog-open="#' + dialog.id + '"]'); + if (trigger) trigger.focus(); + dialog.dispatchEvent(new CustomEvent('m3dialog:close', { bubbles: true })); + } + + function trapFocus(dialog, event) { + var items = $$(FOCUSABLE, dialog).filter(function (el) { return el.offsetParent !== null || el === document.activeElement; }); + if (!items.length) return; + var first = items[0]; + var last = items[items.length - 1]; + if (event.shiftKey && document.activeElement === first) { event.preventDefault(); last.focus(); } + else if (!event.shiftKey && document.activeElement === last) { event.preventDefault(); first.focus(); } + } + + function setupDialogs(scope) { + $$('[data-m3-dialog-open]', scope).forEach(function (trigger) { + if (trigger.dataset.m3Bound) return; + trigger.dataset.m3Bound = '1'; + trigger.addEventListener('click', function (event) { + event.preventDefault(); + openDialog(trigger.getAttribute('data-m3-dialog-open')); + }); + }); + + $$('.m3-dialog', scope).forEach(function (dialog) { + if (dialog.dataset.m3Bound) return; + dialog.dataset.m3Bound = '1'; + dialog.setAttribute('role', 'dialog'); + dialog.setAttribute('aria-modal', 'true'); + dialog.setAttribute('aria-hidden', 'true'); + dialog.addEventListener('click', function (event) { + if (event.target === dialog) closeDialog(dialog); + }); + }); + + document.addEventListener('click', function (event) { + var closer = event.target.closest('[data-m3-dialog-close]'); + if (closer) { + event.preventDefault(); + closeDialog(closer.closest('.m3-dialog')); + } + }); + + document.addEventListener('keydown', function (event) { + if (event.key === 'Escape') { + if (openDialogs.length) { closeDialog(); return; } + if ($('.m3-menu.is-open')) { closeMenus(); return; } + var drawer = $('.m3-scrim.is-open'); + if (drawer) { + var target = byId(drawer.getAttribute('data-m3-scrim-for')); + if (target) setDrawer(target, false); + } + } + if (event.key === 'Tab' && openDialogs.length) trapFocus(openDialogs[openDialogs.length - 1], event); + }); + + document.addEventListener('click', function (event) { + if (!event.target.closest('.m3-menu') && !event.target.closest('[data-m3-menu-trigger]')) closeMenus(); + }); + } + + /* โ”€โ”€ Snackbar โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ + + function region() { + var el = $('.m3-snackbar-region'); + if (!el) { + el = document.createElement('div'); + el.className = 'm3-snackbar-region'; + el.setAttribute('role', 'status'); + el.setAttribute('aria-live', 'polite'); + document.body.appendChild(el); + } + return el; + } + + function snackbar(message, options) { + var opts = options || {}; + var bar = document.createElement('div'); + bar.className = 'm3-snackbar' + (opts.variant === 'error' ? ' m3-snackbar--error' : ''); + var icon = opts.variant === 'error' ? 'fa-circle-exclamation' : (opts.icon || null); + bar.innerHTML = (icon ? '' : '') + + '' + message + ''; + if (opts.actionLabel) { + var action = document.createElement('button'); + action.type = 'button'; + action.className = 'm3-snackbar__action'; + action.textContent = opts.actionLabel; + action.addEventListener('click', function () { + if (typeof opts.onAction === 'function') opts.onAction(); + dismiss(); + }); + bar.appendChild(action); + } + region().appendChild(bar); + var timer = setTimeout(dismiss, opts.duration || 4000); + function dismiss() { + clearTimeout(timer); + bar.classList.add('is-leaving'); + setTimeout(function () { bar.remove(); }, 200); + } + return dismiss; + } + + /* โ”€โ”€ Tabs โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ + + function activateTab(tab) { + var group = tab.closest('[data-m3-tabs]'); + if (!group) return; + var tabs = $$('[role="tab"]', group); + tabs.forEach(function (t) { + var selected = t === tab; + t.setAttribute('aria-selected', String(selected)); + t.classList.toggle('is-active', selected); + t.tabIndex = selected ? 0 : -1; + var panelId = t.getAttribute('aria-controls') || (t.getAttribute('href') || '').replace(/^.*#/, ''); + var panel = panelId ? byId(panelId) : null; + if (panel) { + panel.hidden = !selected; + panel.classList.toggle('is-active', selected); + } + }); + } + + function setupTabs(scope) { + $$('[data-m3-tabs]', scope).forEach(function (group) { + if (group.dataset.m3Bound) return; + group.dataset.m3Bound = '1'; + group.setAttribute('role', 'tablist'); + var tabs = $$('[role="tab"]', group); + tabs.forEach(function (tab, index) { + if (!tab.hasAttribute('aria-controls')) { + var href = (tab.getAttribute('href') || '').replace(/^.*#/, ''); + if (href) tab.setAttribute('aria-controls', href); + } + tab.addEventListener('click', function (event) { + event.preventDefault(); + activateTab(tab); + if (global.history && tab.getAttribute('href') && tab.getAttribute('href').charAt(0) === '#') { + global.history.replaceState(null, '', tab.getAttribute('href')); + } + }); + tab.addEventListener('keydown', function (event) { + var step = event.key === 'ArrowRight' ? 1 : event.key === 'ArrowLeft' ? -1 : 0; + if (!step) return; + event.preventDefault(); + var next = tabs[(index + step + tabs.length) % tabs.length]; + next.focus(); + activateTab(next); + }); + }); + var initial = tabs.filter(function (t) { return t.getAttribute('aria-selected') === 'true' || t.classList.contains('is-active'); })[0] || tabs[0]; + if (initial) activateTab(initial); + }); + } + + /* โ”€โ”€ Segmented buttons & chips โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ + + function setupSegmented(scope) { + $$('[data-m3-segmented]', scope).forEach(function (group) { + if (group.dataset.m3Bound) return; + group.dataset.m3Bound = '1'; + group.setAttribute('role', 'tablist'); + var items = $$('.m3-segmented__item', group); + items.forEach(function (item) { + item.setAttribute('role', 'tab'); + item.setAttribute('aria-selected', String(item.classList.contains('is-selected'))); + item.addEventListener('click', function () { + items.forEach(function (other) { + other.classList.toggle('is-selected', other === item); + other.setAttribute('aria-selected', String(other === item)); + }); + group.dispatchEvent(new CustomEvent('m3segment:change', { detail: { value: item.dataset.value, item: item }, bubbles: true })); + }); + }); + }); + + $$('[data-m3-chip-toggle]', scope).forEach(function (chip) { + if (chip.dataset.m3Bound) return; + chip.dataset.m3Bound = '1'; + chip.addEventListener('click', function () { + var pressed = chip.getAttribute('aria-pressed') === 'true'; + chip.setAttribute('aria-pressed', String(!pressed)); + chip.classList.toggle('m3-chip--selected', !pressed); + }); + }); + } + + /* โ”€โ”€ Fields, sliders, switches โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ + + function setupFields(scope) { + $$('.m3-field__box', scope).forEach(function (box) { + var field = box.closest('.m3-field'); + var input = $('.m3-field__input', box); + if (!input || box.dataset.m3Bound) return; + box.dataset.m3Bound = '1'; + var sync = function () { + box.classList.toggle('has-value', !!input.value); + if (field) field.classList.toggle('m3-field--filled', !!input.value); + }; + input.addEventListener('input', sync); + input.addEventListener('change', sync); + input.addEventListener('blur', function () { + if (field && field.dataset.m3Validate === 'required' && !input.value) { + field.classList.add('m3-field--error'); + } + }); + sync(); + }); + + var syncRange = function (input) { + var min = parseFloat(input.min || 0); + var max = parseFloat(input.max || 100); + var value = parseFloat(input.value); + var pct = ((value - min) / (max - min)) * 100; + input.style.setProperty('--m3-slider-fill', pct + '%'); + }; + + $$('.m3-slider', scope).forEach(function (input) { + if (input.dataset.m3Bound) return; + input.dataset.m3Bound = '1'; + input.addEventListener('input', function () { syncRange(input); }); + syncRange(input); + }); + + $$('[data-m3-range-output]', scope).forEach(function (input) { + var output = byId(input.getAttribute('data-m3-range-output')); + if (!output) return; + var update = function () { output.textContent = input.value; }; + input.addEventListener('input', update); + update(); + }); + } + + /* โ”€โ”€ Theme toggles & copy buttons โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ + + function setupThemeToggles(scope) { + $$('.m3-theme-toggle', scope).forEach(function (btn) { + if (btn.dataset.m3Bound) return; + btn.dataset.m3Bound = '1'; + btn.addEventListener('click', function (event) { + event.preventDefault(); + if (global.M3Color) { + var theme = global.M3Color.toggleTheme(); + btn.setAttribute('aria-label', theme === 'dark' ? 'Switch to light theme' : 'Switch to dark theme'); + } + }); + }); + } + + function copy(text) { + if (navigator.clipboard && global.isSecureContext) return navigator.clipboard.writeText(text); + return new Promise(function (resolve, reject) { + try { + var area = document.createElement('textarea'); + area.value = text; + area.setAttribute('readonly', ''); + area.style.cssText = 'position:absolute;left:-9999px;'; + document.body.appendChild(area); + area.select(); + document.execCommand('copy'); + area.remove(); + resolve(); + } catch (error) { reject(error); } + }); + } + + function setupCopy(scope) { + $$('[data-m3-copy]', scope).forEach(function (btn) { + if (btn.dataset.m3Bound) return; + btn.dataset.m3Bound = '1'; + btn.addEventListener('click', function (event) { + event.preventDefault(); + var source = btn.getAttribute('data-m3-copy'); + var field = source ? $(source) : null; + var value = field ? (field.value || field.textContent) : source; + copy(value.trim()).then(function () { + snackbar(btn.getAttribute('data-m3-copy-message') || 'Copied to clipboard'); + }).catch(function () { + snackbar('Could not copy โ€” copy manually: ' + value, { variant: 'error' }); + }); + }); + }); + } + + /* โ”€โ”€ Reveal on scroll โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ + + function setupReveals(scope) { + var items = $$('.m3-reveal', scope); + if (!items.length) return; + if (REDUCED || !('IntersectionObserver' in global)) { + items.forEach(function (el) { el.classList.add('is-visible'); }); + return; + } + var observer = new IntersectionObserver(function (entries) { + entries.forEach(function (entry) { + if (!entry.isIntersecting) return; + var delay = parseInt(entry.target.getAttribute('data-m3-reveal-delay') || '0', 10); + setTimeout(function () { entry.target.classList.add('is-visible'); }, delay); + observer.unobserve(entry.target); + }); + }, { threshold: 0.12, rootMargin: '0px 0px -40px 0px' }); + items.forEach(function (el) { observer.observe(el); }); + } + + /* โ”€โ”€ Loading state โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ + + function setLoading(el, loading, label) { + if (!el) return; + var target = el.classList.contains('m3-button') ? el : el.closest('.m3-button') || el; + target.classList.toggle('is-loading', !!loading); + target.setAttribute('aria-busy', String(!!loading)); + if (loading) { + target.dataset.m3Label = target.dataset.m3Label || target.textContent.trim(); + if (!target.querySelector('.sr-only')) { + var sr = document.createElement('span'); + sr.className = 'sr-only'; + sr.textContent = label || 'Loading'; + target.appendChild(sr); + } + } else { + var sr = target.querySelector('.sr-only.sr-only--auto'); + if (sr) sr.remove(); + } + target.disabled = !!loading; + } + + /* โ”€โ”€ Boot โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ + + function init(scope) { + scope = scope || document; + $$(RIPPLE_SELECTOR, scope).forEach(attachRipple); + setupAppBars(scope); + setupDrawers(scope); + setupMenus(scope); + setupDialogs(scope); + setupTabs(scope); + setupSegmented(scope); + setupFields(scope); + setupThemeToggles(scope); + setupCopy(scope); + setupReveals(scope); + } + + global.M3UI = { + init: init, + snackbar: snackbar, + openDialog: openDialog, + closeDialog: closeDialog, + openDrawer: function (target, open) { setDrawer(byId(target), open); }, + setLoading: setLoading, + copy: copy, + lockScroll: lockScroll, + unlockScroll: unlockScroll + }; + + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', function () { init(); }); + } else { + init(); + } + + // Re-scan when pages inject markup dynamically (e.g. the demon list grids). + global.addEventListener('m3ui:refresh', function () { init(); }); + + // Legacy bridge: elements that toggle drawers via plain classes. + document.addEventListener('click', function (event) { + var toggle = event.target.closest('[data-m3-drawer-legacy]'); + if (!toggle) return; + var drawer = byId(toggle.getAttribute('data-m3-drawer-legacy')); + if (drawer) setTimeout(function () { setDrawer(drawer, drawer.classList.contains('active') || drawer.classList.contains('is-open')); }, 0); + }); +})(window); diff --git a/main/assets/people/alonebg.svg b/main/assets/people/alonebg.svg new file mode 100644 index 0000000..f535e96 --- /dev/null +++ b/main/assets/people/alonebg.svg @@ -0,0 +1,4 @@ + diff --git a/main/assets/people/blazen.svg b/main/assets/people/blazen.svg new file mode 100644 index 0000000..9631bdb --- /dev/null +++ b/main/assets/people/blazen.svg @@ -0,0 +1,4 @@ + diff --git a/main/assets/people/danzgame.svg b/main/assets/people/danzgame.svg new file mode 100644 index 0000000..c3decb2 --- /dev/null +++ b/main/assets/people/danzgame.svg @@ -0,0 +1,4 @@ + diff --git a/main/assets/people/denyzr.svg b/main/assets/people/denyzr.svg new file mode 100644 index 0000000..1761b7a --- /dev/null +++ b/main/assets/people/denyzr.svg @@ -0,0 +1,4 @@ + diff --git a/main/assets/people/fless.svg b/main/assets/people/fless.svg new file mode 100644 index 0000000..c5e54d5 --- /dev/null +++ b/main/assets/people/fless.svg @@ -0,0 +1,4 @@ + diff --git a/main/assets/people/giffarirmx.svg b/main/assets/people/giffarirmx.svg new file mode 100644 index 0000000..13c6081 --- /dev/null +++ b/main/assets/people/giffarirmx.svg @@ -0,0 +1,4 @@ + diff --git a/main/assets/people/mathieuar.svg b/main/assets/people/mathieuar.svg new file mode 100644 index 0000000..0062e57 --- /dev/null +++ b/main/assets/people/mathieuar.svg @@ -0,0 +1,4 @@ + diff --git a/main/assets/people/megasaint.svg b/main/assets/people/megasaint.svg new file mode 100644 index 0000000..329a2bd --- /dev/null +++ b/main/assets/people/megasaint.svg @@ -0,0 +1,4 @@ + diff --git a/main/assets/people/migmatos.svg b/main/assets/people/migmatos.svg new file mode 100644 index 0000000..16540e6 --- /dev/null +++ b/main/assets/people/migmatos.svg @@ -0,0 +1,4 @@ + diff --git a/main/assets/people/robtop.svg b/main/assets/people/robtop.svg new file mode 100644 index 0000000..24ed725 --- /dev/null +++ b/main/assets/people/robtop.svg @@ -0,0 +1,4 @@ + diff --git a/main/assets/people/zeroxygd.svg b/main/assets/people/zeroxygd.svg new file mode 100644 index 0000000..8aa0927 --- /dev/null +++ b/main/assets/people/zeroxygd.svg @@ -0,0 +1,4 @@ + diff --git a/main/assets/vendor/fontawesome/LICENSE.txt b/main/assets/vendor/fontawesome/LICENSE.txt new file mode 100644 index 0000000..39e18e3 --- /dev/null +++ b/main/assets/vendor/fontawesome/LICENSE.txt @@ -0,0 +1,165 @@ +Fonticons, Inc. (https://fontawesome.com) + +-------------------------------------------------------------------------------- + +Font Awesome Free License + +Font Awesome Free is free, open source, and GPL friendly. You can use it for +commercial projects, open source projects, or really almost whatever you want. +Full Font Awesome Free license: https://fontawesome.com/license/free. + +-------------------------------------------------------------------------------- + +# Icons: CC BY 4.0 License (https://creativecommons.org/licenses/by/4.0/) + +The Font Awesome Free download is licensed under a Creative Commons +Attribution 4.0 International License and applies to all icons packaged +as SVG and JS file types. + +-------------------------------------------------------------------------------- + +# Fonts: SIL OFL 1.1 License + +In the Font Awesome Free download, the SIL OFL license applies to all icons +packaged as web and desktop font files. + +Copyright (c) 2023 Fonticons, Inc. (https://fontawesome.com) +with Reserved Font Name: "Font Awesome". + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + +SIL OPEN FONT LICENSE +Version 1.1 - 26 February 2007 + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting โ€” in part or in whole โ€” any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. + +-------------------------------------------------------------------------------- + +# Code: MIT License (https://opensource.org/licenses/MIT) + +In the Font Awesome Free download, the MIT license applies to all non-font and +non-icon files. + +Copyright 2023 Fonticons, Inc. + +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. + +-------------------------------------------------------------------------------- + +# Attribution + +Attribution is required by MIT, SIL OFL, and CC BY licenses. Downloaded Font +Awesome Free files already contain embedded comments with sufficient +attribution, so you shouldn't need to do anything additional when using these +files normally. + +We've kept attribution comments terse, so we ask that you do not actively work +to remove them from files, especially code. They're a great way for folks to +learn about Font Awesome. + +-------------------------------------------------------------------------------- + +# Brand Icons + +All brand icons are trademarks of their respective owners. The use of these +trademarks does not indicate endorsement of the trademark holder by Font +Awesome, nor vice versa. **Please do not use brand logos for any purpose except +to represent the company, product, or service to which they refer.** diff --git a/main/assets/vendor/fontawesome/css/all.min.css b/main/assets/vendor/fontawesome/css/all.min.css new file mode 100644 index 0000000..a18b779 --- /dev/null +++ b/main/assets/vendor/fontawesome/css/all.min.css @@ -0,0 +1,9 @@ +/*! + * Font Awesome Free 6.4.0 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + * Copyright 2023 Fonticons, Inc. + */ +.fa{font-family:var(--fa-style-family,"Font Awesome 6 Free");font-weight:var(--fa-style,900)}.fa,.fa-brands,.fa-classic,.fa-regular,.fa-sharp,.fa-solid,.fab,.far,.fas{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:var(--fa-display,inline-block);font-style:normal;font-variant:normal;line-height:1;text-rendering:auto}.fa-classic,.fa-regular,.fa-solid,.far,.fas{font-family:"Font Awesome 6 Free"}.fa-brands,.fab{font-family:"Font Awesome 6 Brands"}.fa-1x{font-size:1em}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-6x{font-size:6em}.fa-7x{font-size:7em}.fa-8x{font-size:8em}.fa-9x{font-size:9em}.fa-10x{font-size:10em}.fa-2xs{font-size:.625em;line-height:.1em;vertical-align:.225em}.fa-xs{font-size:.75em;line-height:.08333em;vertical-align:.125em}.fa-sm{font-size:.875em;line-height:.07143em;vertical-align:.05357em}.fa-lg{font-size:1.25em;line-height:.05em;vertical-align:-.075em}.fa-xl{font-size:1.5em;line-height:.04167em;vertical-align:-.125em}.fa-2xl{font-size:2em;line-height:.03125em;vertical-align:-.1875em}.fa-fw{text-align:center;width:1.25em}.fa-ul{list-style-type:none;margin-left:var(--fa-li-margin,2.5em);padding-left:0}.fa-ul>li{position:relative}.fa-li{left:calc(var(--fa-li-width, 2em)*-1);position:absolute;text-align:center;width:var(--fa-li-width,2em);line-height:inherit}.fa-border{border-radius:var(--fa-border-radius,.1em);border:var(--fa-border-width,.08em) var(--fa-border-style,solid) var(--fa-border-color,#eee);padding:var(--fa-border-padding,.2em .25em .15em)}.fa-pull-left{float:left;margin-right:var(--fa-pull-margin,.3em)}.fa-pull-right{float:right;margin-left:var(--fa-pull-margin,.3em)}.fa-beat{-webkit-animation-name:fa-beat;animation-name:fa-beat;-webkit-animation-delay:var(--fa-animation-delay,0s);animation-delay:var(--fa-animation-delay,0s);-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal);-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,ease-in-out);animation-timing-function:var(--fa-animation-timing,ease-in-out)}.fa-bounce{-webkit-animation-name:fa-bounce;animation-name:fa-bounce;-webkit-animation-delay:var(--fa-animation-delay,0s);animation-delay:var(--fa-animation-delay,0s);-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal);-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,cubic-bezier(.28,.84,.42,1));animation-timing-function:var(--fa-animation-timing,cubic-bezier(.28,.84,.42,1))}.fa-fade{-webkit-animation-name:fa-fade;animation-name:fa-fade;-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,cubic-bezier(.4,0,.6,1));animation-timing-function:var(--fa-animation-timing,cubic-bezier(.4,0,.6,1))}.fa-beat-fade,.fa-fade{-webkit-animation-delay:var(--fa-animation-delay,0s);animation-delay:var(--fa-animation-delay,0s);-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal);-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s)}.fa-beat-fade{-webkit-animation-name:fa-beat-fade;animation-name:fa-beat-fade;-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,cubic-bezier(.4,0,.6,1));animation-timing-function:var(--fa-animation-timing,cubic-bezier(.4,0,.6,1))}.fa-flip{-webkit-animation-name:fa-flip;animation-name:fa-flip;-webkit-animation-delay:var(--fa-animation-delay,0s);animation-delay:var(--fa-animation-delay,0s);-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal);-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,ease-in-out);animation-timing-function:var(--fa-animation-timing,ease-in-out)}.fa-shake{-webkit-animation-name:fa-shake;animation-name:fa-shake;-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,linear);animation-timing-function:var(--fa-animation-timing,linear)}.fa-shake,.fa-spin{-webkit-animation-delay:var(--fa-animation-delay,0s);animation-delay:var(--fa-animation-delay,0s);-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal)}.fa-spin{-webkit-animation-name:fa-spin;animation-name:fa-spin;-webkit-animation-duration:var(--fa-animation-duration,2s);animation-duration:var(--fa-animation-duration,2s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,linear);animation-timing-function:var(--fa-animation-timing,linear)}.fa-spin-reverse{--fa-animation-direction:reverse}.fa-pulse,.fa-spin-pulse{-webkit-animation-name:fa-spin;animation-name:fa-spin;-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal);-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,steps(8));animation-timing-function:var(--fa-animation-timing,steps(8))}@media (prefers-reduced-motion:reduce){.fa-beat,.fa-beat-fade,.fa-bounce,.fa-fade,.fa-flip,.fa-pulse,.fa-shake,.fa-spin,.fa-spin-pulse{-webkit-animation-delay:-1ms;animation-delay:-1ms;-webkit-animation-duration:1ms;animation-duration:1ms;-webkit-animation-iteration-count:1;animation-iteration-count:1;-webkit-transition-delay:0s;transition-delay:0s;-webkit-transition-duration:0s;transition-duration:0s}}@-webkit-keyframes fa-beat{0%,90%{-webkit-transform:scale(1);transform:scale(1)}45%{-webkit-transform:scale(var(--fa-beat-scale,1.25));transform:scale(var(--fa-beat-scale,1.25))}}@keyframes fa-beat{0%,90%{-webkit-transform:scale(1);transform:scale(1)}45%{-webkit-transform:scale(var(--fa-beat-scale,1.25));transform:scale(var(--fa-beat-scale,1.25))}}@-webkit-keyframes fa-bounce{0%{-webkit-transform:scale(1) translateY(0);transform:scale(1) translateY(0)}10%{-webkit-transform:scale(var(--fa-bounce-start-scale-x,1.1),var(--fa-bounce-start-scale-y,.9)) translateY(0);transform:scale(var(--fa-bounce-start-scale-x,1.1),var(--fa-bounce-start-scale-y,.9)) translateY(0)}30%{-webkit-transform:scale(var(--fa-bounce-jump-scale-x,.9),var(--fa-bounce-jump-scale-y,1.1)) translateY(var(--fa-bounce-height,-.5em));transform:scale(var(--fa-bounce-jump-scale-x,.9),var(--fa-bounce-jump-scale-y,1.1)) translateY(var(--fa-bounce-height,-.5em))}50%{-webkit-transform:scale(var(--fa-bounce-land-scale-x,1.05),var(--fa-bounce-land-scale-y,.95)) translateY(0);transform:scale(var(--fa-bounce-land-scale-x,1.05),var(--fa-bounce-land-scale-y,.95)) translateY(0)}57%{-webkit-transform:scale(1) translateY(var(--fa-bounce-rebound,-.125em));transform:scale(1) translateY(var(--fa-bounce-rebound,-.125em))}64%{-webkit-transform:scale(1) translateY(0);transform:scale(1) translateY(0)}to{-webkit-transform:scale(1) translateY(0);transform:scale(1) translateY(0)}}@keyframes fa-bounce{0%{-webkit-transform:scale(1) translateY(0);transform:scale(1) translateY(0)}10%{-webkit-transform:scale(var(--fa-bounce-start-scale-x,1.1),var(--fa-bounce-start-scale-y,.9)) translateY(0);transform:scale(var(--fa-bounce-start-scale-x,1.1),var(--fa-bounce-start-scale-y,.9)) translateY(0)}30%{-webkit-transform:scale(var(--fa-bounce-jump-scale-x,.9),var(--fa-bounce-jump-scale-y,1.1)) translateY(var(--fa-bounce-height,-.5em));transform:scale(var(--fa-bounce-jump-scale-x,.9),var(--fa-bounce-jump-scale-y,1.1)) translateY(var(--fa-bounce-height,-.5em))}50%{-webkit-transform:scale(var(--fa-bounce-land-scale-x,1.05),var(--fa-bounce-land-scale-y,.95)) translateY(0);transform:scale(var(--fa-bounce-land-scale-x,1.05),var(--fa-bounce-land-scale-y,.95)) translateY(0)}57%{-webkit-transform:scale(1) translateY(var(--fa-bounce-rebound,-.125em));transform:scale(1) translateY(var(--fa-bounce-rebound,-.125em))}64%{-webkit-transform:scale(1) translateY(0);transform:scale(1) translateY(0)}to{-webkit-transform:scale(1) translateY(0);transform:scale(1) translateY(0)}}@-webkit-keyframes fa-fade{50%{opacity:var(--fa-fade-opacity,.4)}}@keyframes fa-fade{50%{opacity:var(--fa-fade-opacity,.4)}}@-webkit-keyframes fa-beat-fade{0%,to{opacity:var(--fa-beat-fade-opacity,.4);-webkit-transform:scale(1);transform:scale(1)}50%{opacity:1;-webkit-transform:scale(var(--fa-beat-fade-scale,1.125));transform:scale(var(--fa-beat-fade-scale,1.125))}}@keyframes fa-beat-fade{0%,to{opacity:var(--fa-beat-fade-opacity,.4);-webkit-transform:scale(1);transform:scale(1)}50%{opacity:1;-webkit-transform:scale(var(--fa-beat-fade-scale,1.125));transform:scale(var(--fa-beat-fade-scale,1.125))}}@-webkit-keyframes fa-flip{50%{-webkit-transform:rotate3d(var(--fa-flip-x,0),var(--fa-flip-y,1),var(--fa-flip-z,0),var(--fa-flip-angle,-180deg));transform:rotate3d(var(--fa-flip-x,0),var(--fa-flip-y,1),var(--fa-flip-z,0),var(--fa-flip-angle,-180deg))}}@keyframes fa-flip{50%{-webkit-transform:rotate3d(var(--fa-flip-x,0),var(--fa-flip-y,1),var(--fa-flip-z,0),var(--fa-flip-angle,-180deg));transform:rotate3d(var(--fa-flip-x,0),var(--fa-flip-y,1),var(--fa-flip-z,0),var(--fa-flip-angle,-180deg))}}@-webkit-keyframes fa-shake{0%{-webkit-transform:rotate(-15deg);transform:rotate(-15deg)}4%{-webkit-transform:rotate(15deg);transform:rotate(15deg)}8%,24%{-webkit-transform:rotate(-18deg);transform:rotate(-18deg)}12%,28%{-webkit-transform:rotate(18deg);transform:rotate(18deg)}16%{-webkit-transform:rotate(-22deg);transform:rotate(-22deg)}20%{-webkit-transform:rotate(22deg);transform:rotate(22deg)}32%{-webkit-transform:rotate(-12deg);transform:rotate(-12deg)}36%{-webkit-transform:rotate(12deg);transform:rotate(12deg)}40%,to{-webkit-transform:rotate(0deg);transform:rotate(0deg)}}@keyframes fa-shake{0%{-webkit-transform:rotate(-15deg);transform:rotate(-15deg)}4%{-webkit-transform:rotate(15deg);transform:rotate(15deg)}8%,24%{-webkit-transform:rotate(-18deg);transform:rotate(-18deg)}12%,28%{-webkit-transform:rotate(18deg);transform:rotate(18deg)}16%{-webkit-transform:rotate(-22deg);transform:rotate(-22deg)}20%{-webkit-transform:rotate(22deg);transform:rotate(22deg)}32%{-webkit-transform:rotate(-12deg);transform:rotate(-12deg)}36%{-webkit-transform:rotate(12deg);transform:rotate(12deg)}40%,to{-webkit-transform:rotate(0deg);transform:rotate(0deg)}}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}.fa-rotate-90{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-webkit-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-webkit-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-webkit-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-webkit-transform:scaleY(-1);transform:scaleY(-1)}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical{-webkit-transform:scale(-1);transform:scale(-1)}.fa-rotate-by{-webkit-transform:rotate(var(--fa-rotate-angle,none));transform:rotate(var(--fa-rotate-angle,none))}.fa-stack{display:inline-block;height:2em;line-height:2em;position:relative;vertical-align:middle;width:2.5em}.fa-stack-1x,.fa-stack-2x{left:0;position:absolute;text-align:center;width:100%;z-index:var(--fa-stack-z-index,auto)}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:var(--fa-inverse,#fff)} + +.fa-0:before{content:"\30"}.fa-1:before{content:"\31"}.fa-2:before{content:"\32"}.fa-3:before{content:"\33"}.fa-4:before{content:"\34"}.fa-5:before{content:"\35"}.fa-6:before{content:"\36"}.fa-7:before{content:"\37"}.fa-8:before{content:"\38"}.fa-9:before{content:"\39"}.fa-fill-drip:before{content:"\f576"}.fa-arrows-to-circle:before{content:"\e4bd"}.fa-chevron-circle-right:before,.fa-circle-chevron-right:before{content:"\f138"}.fa-at:before{content:"\40"}.fa-trash-alt:before,.fa-trash-can:before{content:"\f2ed"}.fa-text-height:before{content:"\f034"}.fa-user-times:before,.fa-user-xmark:before{content:"\f235"}.fa-stethoscope:before{content:"\f0f1"}.fa-comment-alt:before,.fa-message:before{content:"\f27a"}.fa-info:before{content:"\f129"}.fa-compress-alt:before,.fa-down-left-and-up-right-to-center:before{content:"\f422"}.fa-explosion:before{content:"\e4e9"}.fa-file-alt:before,.fa-file-lines:before,.fa-file-text:before{content:"\f15c"}.fa-wave-square:before{content:"\f83e"}.fa-ring:before{content:"\f70b"}.fa-building-un:before{content:"\e4d9"}.fa-dice-three:before{content:"\f527"}.fa-calendar-alt:before,.fa-calendar-days:before{content:"\f073"}.fa-anchor-circle-check:before{content:"\e4aa"}.fa-building-circle-arrow-right:before{content:"\e4d1"}.fa-volleyball-ball:before,.fa-volleyball:before{content:"\f45f"}.fa-arrows-up-to-line:before{content:"\e4c2"}.fa-sort-desc:before,.fa-sort-down:before{content:"\f0dd"}.fa-circle-minus:before,.fa-minus-circle:before{content:"\f056"}.fa-door-open:before{content:"\f52b"}.fa-right-from-bracket:before,.fa-sign-out-alt:before{content:"\f2f5"}.fa-atom:before{content:"\f5d2"}.fa-soap:before{content:"\e06e"}.fa-heart-music-camera-bolt:before,.fa-icons:before{content:"\f86d"}.fa-microphone-alt-slash:before,.fa-microphone-lines-slash:before{content:"\f539"}.fa-bridge-circle-check:before{content:"\e4c9"}.fa-pump-medical:before{content:"\e06a"}.fa-fingerprint:before{content:"\f577"}.fa-hand-point-right:before{content:"\f0a4"}.fa-magnifying-glass-location:before,.fa-search-location:before{content:"\f689"}.fa-forward-step:before,.fa-step-forward:before{content:"\f051"}.fa-face-smile-beam:before,.fa-smile-beam:before{content:"\f5b8"}.fa-flag-checkered:before{content:"\f11e"}.fa-football-ball:before,.fa-football:before{content:"\f44e"}.fa-school-circle-exclamation:before{content:"\e56c"}.fa-crop:before{content:"\f125"}.fa-angle-double-down:before,.fa-angles-down:before{content:"\f103"}.fa-users-rectangle:before{content:"\e594"}.fa-people-roof:before{content:"\e537"}.fa-people-line:before{content:"\e534"}.fa-beer-mug-empty:before,.fa-beer:before{content:"\f0fc"}.fa-diagram-predecessor:before{content:"\e477"}.fa-arrow-up-long:before,.fa-long-arrow-up:before{content:"\f176"}.fa-burn:before,.fa-fire-flame-simple:before{content:"\f46a"}.fa-male:before,.fa-person:before{content:"\f183"}.fa-laptop:before{content:"\f109"}.fa-file-csv:before{content:"\f6dd"}.fa-menorah:before{content:"\f676"}.fa-truck-plane:before{content:"\e58f"}.fa-record-vinyl:before{content:"\f8d9"}.fa-face-grin-stars:before,.fa-grin-stars:before{content:"\f587"}.fa-bong:before{content:"\f55c"}.fa-pastafarianism:before,.fa-spaghetti-monster-flying:before{content:"\f67b"}.fa-arrow-down-up-across-line:before{content:"\e4af"}.fa-spoon:before,.fa-utensil-spoon:before{content:"\f2e5"}.fa-jar-wheat:before{content:"\e517"}.fa-envelopes-bulk:before,.fa-mail-bulk:before{content:"\f674"}.fa-file-circle-exclamation:before{content:"\e4eb"}.fa-circle-h:before,.fa-hospital-symbol:before{content:"\f47e"}.fa-pager:before{content:"\f815"}.fa-address-book:before,.fa-contact-book:before{content:"\f2b9"}.fa-strikethrough:before{content:"\f0cc"}.fa-k:before{content:"\4b"}.fa-landmark-flag:before{content:"\e51c"}.fa-pencil-alt:before,.fa-pencil:before{content:"\f303"}.fa-backward:before{content:"\f04a"}.fa-caret-right:before{content:"\f0da"}.fa-comments:before{content:"\f086"}.fa-file-clipboard:before,.fa-paste:before{content:"\f0ea"}.fa-code-pull-request:before{content:"\e13c"}.fa-clipboard-list:before{content:"\f46d"}.fa-truck-loading:before,.fa-truck-ramp-box:before{content:"\f4de"}.fa-user-check:before{content:"\f4fc"}.fa-vial-virus:before{content:"\e597"}.fa-sheet-plastic:before{content:"\e571"}.fa-blog:before{content:"\f781"}.fa-user-ninja:before{content:"\f504"}.fa-person-arrow-up-from-line:before{content:"\e539"}.fa-scroll-torah:before,.fa-torah:before{content:"\f6a0"}.fa-broom-ball:before,.fa-quidditch-broom-ball:before,.fa-quidditch:before{content:"\f458"}.fa-toggle-off:before{content:"\f204"}.fa-archive:before,.fa-box-archive:before{content:"\f187"}.fa-person-drowning:before{content:"\e545"}.fa-arrow-down-9-1:before,.fa-sort-numeric-desc:before,.fa-sort-numeric-down-alt:before{content:"\f886"}.fa-face-grin-tongue-squint:before,.fa-grin-tongue-squint:before{content:"\f58a"}.fa-spray-can:before{content:"\f5bd"}.fa-truck-monster:before{content:"\f63b"}.fa-w:before{content:"\57"}.fa-earth-africa:before,.fa-globe-africa:before{content:"\f57c"}.fa-rainbow:before{content:"\f75b"}.fa-circle-notch:before{content:"\f1ce"}.fa-tablet-alt:before,.fa-tablet-screen-button:before{content:"\f3fa"}.fa-paw:before{content:"\f1b0"}.fa-cloud:before{content:"\f0c2"}.fa-trowel-bricks:before{content:"\e58a"}.fa-face-flushed:before,.fa-flushed:before{content:"\f579"}.fa-hospital-user:before{content:"\f80d"}.fa-tent-arrow-left-right:before{content:"\e57f"}.fa-gavel:before,.fa-legal:before{content:"\f0e3"}.fa-binoculars:before{content:"\f1e5"}.fa-microphone-slash:before{content:"\f131"}.fa-box-tissue:before{content:"\e05b"}.fa-motorcycle:before{content:"\f21c"}.fa-bell-concierge:before,.fa-concierge-bell:before{content:"\f562"}.fa-pen-ruler:before,.fa-pencil-ruler:before{content:"\f5ae"}.fa-people-arrows-left-right:before,.fa-people-arrows:before{content:"\e068"}.fa-mars-and-venus-burst:before{content:"\e523"}.fa-caret-square-right:before,.fa-square-caret-right:before{content:"\f152"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-sun-plant-wilt:before{content:"\e57a"}.fa-toilets-portable:before{content:"\e584"}.fa-hockey-puck:before{content:"\f453"}.fa-table:before{content:"\f0ce"}.fa-magnifying-glass-arrow-right:before{content:"\e521"}.fa-digital-tachograph:before,.fa-tachograph-digital:before{content:"\f566"}.fa-users-slash:before{content:"\e073"}.fa-clover:before{content:"\e139"}.fa-mail-reply:before,.fa-reply:before{content:"\f3e5"}.fa-star-and-crescent:before{content:"\f699"}.fa-house-fire:before{content:"\e50c"}.fa-minus-square:before,.fa-square-minus:before{content:"\f146"}.fa-helicopter:before{content:"\f533"}.fa-compass:before{content:"\f14e"}.fa-caret-square-down:before,.fa-square-caret-down:before{content:"\f150"}.fa-file-circle-question:before{content:"\e4ef"}.fa-laptop-code:before{content:"\f5fc"}.fa-swatchbook:before{content:"\f5c3"}.fa-prescription-bottle:before{content:"\f485"}.fa-bars:before,.fa-navicon:before{content:"\f0c9"}.fa-people-group:before{content:"\e533"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-heart-broken:before,.fa-heart-crack:before{content:"\f7a9"}.fa-external-link-square-alt:before,.fa-square-up-right:before{content:"\f360"}.fa-face-kiss-beam:before,.fa-kiss-beam:before{content:"\f597"}.fa-film:before{content:"\f008"}.fa-ruler-horizontal:before{content:"\f547"}.fa-people-robbery:before{content:"\e536"}.fa-lightbulb:before{content:"\f0eb"}.fa-caret-left:before{content:"\f0d9"}.fa-circle-exclamation:before,.fa-exclamation-circle:before{content:"\f06a"}.fa-school-circle-xmark:before{content:"\e56d"}.fa-arrow-right-from-bracket:before,.fa-sign-out:before{content:"\f08b"}.fa-chevron-circle-down:before,.fa-circle-chevron-down:before{content:"\f13a"}.fa-unlock-alt:before,.fa-unlock-keyhole:before{content:"\f13e"}.fa-cloud-showers-heavy:before{content:"\f740"}.fa-headphones-alt:before,.fa-headphones-simple:before{content:"\f58f"}.fa-sitemap:before{content:"\f0e8"}.fa-circle-dollar-to-slot:before,.fa-donate:before{content:"\f4b9"}.fa-memory:before{content:"\f538"}.fa-road-spikes:before{content:"\e568"}.fa-fire-burner:before{content:"\e4f1"}.fa-flag:before{content:"\f024"}.fa-hanukiah:before{content:"\f6e6"}.fa-feather:before{content:"\f52d"}.fa-volume-down:before,.fa-volume-low:before{content:"\f027"}.fa-comment-slash:before{content:"\f4b3"}.fa-cloud-sun-rain:before{content:"\f743"}.fa-compress:before{content:"\f066"}.fa-wheat-alt:before,.fa-wheat-awn:before{content:"\e2cd"}.fa-ankh:before{content:"\f644"}.fa-hands-holding-child:before{content:"\e4fa"}.fa-asterisk:before{content:"\2a"}.fa-check-square:before,.fa-square-check:before{content:"\f14a"}.fa-peseta-sign:before{content:"\e221"}.fa-header:before,.fa-heading:before{content:"\f1dc"}.fa-ghost:before{content:"\f6e2"}.fa-list-squares:before,.fa-list:before{content:"\f03a"}.fa-phone-square-alt:before,.fa-square-phone-flip:before{content:"\f87b"}.fa-cart-plus:before{content:"\f217"}.fa-gamepad:before{content:"\f11b"}.fa-circle-dot:before,.fa-dot-circle:before{content:"\f192"}.fa-dizzy:before,.fa-face-dizzy:before{content:"\f567"}.fa-egg:before{content:"\f7fb"}.fa-house-medical-circle-xmark:before{content:"\e513"}.fa-campground:before{content:"\f6bb"}.fa-folder-plus:before{content:"\f65e"}.fa-futbol-ball:before,.fa-futbol:before,.fa-soccer-ball:before{content:"\f1e3"}.fa-paint-brush:before,.fa-paintbrush:before{content:"\f1fc"}.fa-lock:before{content:"\f023"}.fa-gas-pump:before{content:"\f52f"}.fa-hot-tub-person:before,.fa-hot-tub:before{content:"\f593"}.fa-map-location:before,.fa-map-marked:before{content:"\f59f"}.fa-house-flood-water:before{content:"\e50e"}.fa-tree:before{content:"\f1bb"}.fa-bridge-lock:before{content:"\e4cc"}.fa-sack-dollar:before{content:"\f81d"}.fa-edit:before,.fa-pen-to-square:before{content:"\f044"}.fa-car-side:before{content:"\f5e4"}.fa-share-alt:before,.fa-share-nodes:before{content:"\f1e0"}.fa-heart-circle-minus:before{content:"\e4ff"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-microscope:before{content:"\f610"}.fa-sink:before{content:"\e06d"}.fa-bag-shopping:before,.fa-shopping-bag:before{content:"\f290"}.fa-arrow-down-z-a:before,.fa-sort-alpha-desc:before,.fa-sort-alpha-down-alt:before{content:"\f881"}.fa-mitten:before{content:"\f7b5"}.fa-person-rays:before{content:"\e54d"}.fa-users:before{content:"\f0c0"}.fa-eye-slash:before{content:"\f070"}.fa-flask-vial:before{content:"\e4f3"}.fa-hand-paper:before,.fa-hand:before{content:"\f256"}.fa-om:before{content:"\f679"}.fa-worm:before{content:"\e599"}.fa-house-circle-xmark:before{content:"\e50b"}.fa-plug:before{content:"\f1e6"}.fa-chevron-up:before{content:"\f077"}.fa-hand-spock:before{content:"\f259"}.fa-stopwatch:before{content:"\f2f2"}.fa-face-kiss:before,.fa-kiss:before{content:"\f596"}.fa-bridge-circle-xmark:before{content:"\e4cb"}.fa-face-grin-tongue:before,.fa-grin-tongue:before{content:"\f589"}.fa-chess-bishop:before{content:"\f43a"}.fa-face-grin-wink:before,.fa-grin-wink:before{content:"\f58c"}.fa-deaf:before,.fa-deafness:before,.fa-ear-deaf:before,.fa-hard-of-hearing:before{content:"\f2a4"}.fa-road-circle-check:before{content:"\e564"}.fa-dice-five:before{content:"\f523"}.fa-rss-square:before,.fa-square-rss:before{content:"\f143"}.fa-land-mine-on:before{content:"\e51b"}.fa-i-cursor:before{content:"\f246"}.fa-stamp:before{content:"\f5bf"}.fa-stairs:before{content:"\e289"}.fa-i:before{content:"\49"}.fa-hryvnia-sign:before,.fa-hryvnia:before{content:"\f6f2"}.fa-pills:before{content:"\f484"}.fa-face-grin-wide:before,.fa-grin-alt:before{content:"\f581"}.fa-tooth:before{content:"\f5c9"}.fa-v:before{content:"\56"}.fa-bangladeshi-taka-sign:before{content:"\e2e6"}.fa-bicycle:before{content:"\f206"}.fa-rod-asclepius:before,.fa-rod-snake:before,.fa-staff-aesculapius:before,.fa-staff-snake:before{content:"\e579"}.fa-head-side-cough-slash:before{content:"\e062"}.fa-ambulance:before,.fa-truck-medical:before{content:"\f0f9"}.fa-wheat-awn-circle-exclamation:before{content:"\e598"}.fa-snowman:before{content:"\f7d0"}.fa-mortar-pestle:before{content:"\f5a7"}.fa-road-barrier:before{content:"\e562"}.fa-school:before{content:"\f549"}.fa-igloo:before{content:"\f7ae"}.fa-joint:before{content:"\f595"}.fa-angle-right:before{content:"\f105"}.fa-horse:before{content:"\f6f0"}.fa-q:before{content:"\51"}.fa-g:before{content:"\47"}.fa-notes-medical:before{content:"\f481"}.fa-temperature-2:before,.fa-temperature-half:before,.fa-thermometer-2:before,.fa-thermometer-half:before{content:"\f2c9"}.fa-dong-sign:before{content:"\e169"}.fa-capsules:before{content:"\f46b"}.fa-poo-bolt:before,.fa-poo-storm:before{content:"\f75a"}.fa-face-frown-open:before,.fa-frown-open:before{content:"\f57a"}.fa-hand-point-up:before{content:"\f0a6"}.fa-money-bill:before{content:"\f0d6"}.fa-bookmark:before{content:"\f02e"}.fa-align-justify:before{content:"\f039"}.fa-umbrella-beach:before{content:"\f5ca"}.fa-helmet-un:before{content:"\e503"}.fa-bullseye:before{content:"\f140"}.fa-bacon:before{content:"\f7e5"}.fa-hand-point-down:before{content:"\f0a7"}.fa-arrow-up-from-bracket:before{content:"\e09a"}.fa-folder-blank:before,.fa-folder:before{content:"\f07b"}.fa-file-medical-alt:before,.fa-file-waveform:before{content:"\f478"}.fa-radiation:before{content:"\f7b9"}.fa-chart-simple:before{content:"\e473"}.fa-mars-stroke:before{content:"\f229"}.fa-vial:before{content:"\f492"}.fa-dashboard:before,.fa-gauge-med:before,.fa-gauge:before,.fa-tachometer-alt-average:before{content:"\f624"}.fa-magic-wand-sparkles:before,.fa-wand-magic-sparkles:before{content:"\e2ca"}.fa-e:before{content:"\45"}.fa-pen-alt:before,.fa-pen-clip:before{content:"\f305"}.fa-bridge-circle-exclamation:before{content:"\e4ca"}.fa-user:before{content:"\f007"}.fa-school-circle-check:before{content:"\e56b"}.fa-dumpster:before{content:"\f793"}.fa-shuttle-van:before,.fa-van-shuttle:before{content:"\f5b6"}.fa-building-user:before{content:"\e4da"}.fa-caret-square-left:before,.fa-square-caret-left:before{content:"\f191"}.fa-highlighter:before{content:"\f591"}.fa-key:before{content:"\f084"}.fa-bullhorn:before{content:"\f0a1"}.fa-globe:before{content:"\f0ac"}.fa-synagogue:before{content:"\f69b"}.fa-person-half-dress:before{content:"\e548"}.fa-road-bridge:before{content:"\e563"}.fa-location-arrow:before{content:"\f124"}.fa-c:before{content:"\43"}.fa-tablet-button:before{content:"\f10a"}.fa-building-lock:before{content:"\e4d6"}.fa-pizza-slice:before{content:"\f818"}.fa-money-bill-wave:before{content:"\f53a"}.fa-area-chart:before,.fa-chart-area:before{content:"\f1fe"}.fa-house-flag:before{content:"\e50d"}.fa-person-circle-minus:before{content:"\e540"}.fa-ban:before,.fa-cancel:before{content:"\f05e"}.fa-camera-rotate:before{content:"\e0d8"}.fa-air-freshener:before,.fa-spray-can-sparkles:before{content:"\f5d0"}.fa-star:before{content:"\f005"}.fa-repeat:before{content:"\f363"}.fa-cross:before{content:"\f654"}.fa-box:before{content:"\f466"}.fa-venus-mars:before{content:"\f228"}.fa-arrow-pointer:before,.fa-mouse-pointer:before{content:"\f245"}.fa-expand-arrows-alt:before,.fa-maximize:before{content:"\f31e"}.fa-charging-station:before{content:"\f5e7"}.fa-shapes:before,.fa-triangle-circle-square:before{content:"\f61f"}.fa-random:before,.fa-shuffle:before{content:"\f074"}.fa-person-running:before,.fa-running:before{content:"\f70c"}.fa-mobile-retro:before{content:"\e527"}.fa-grip-lines-vertical:before{content:"\f7a5"}.fa-spider:before{content:"\f717"}.fa-hands-bound:before{content:"\e4f9"}.fa-file-invoice-dollar:before{content:"\f571"}.fa-plane-circle-exclamation:before{content:"\e556"}.fa-x-ray:before{content:"\f497"}.fa-spell-check:before{content:"\f891"}.fa-slash:before{content:"\f715"}.fa-computer-mouse:before,.fa-mouse:before{content:"\f8cc"}.fa-arrow-right-to-bracket:before,.fa-sign-in:before{content:"\f090"}.fa-shop-slash:before,.fa-store-alt-slash:before{content:"\e070"}.fa-server:before{content:"\f233"}.fa-virus-covid-slash:before{content:"\e4a9"}.fa-shop-lock:before{content:"\e4a5"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-blender-phone:before{content:"\f6b6"}.fa-building-wheat:before{content:"\e4db"}.fa-person-breastfeeding:before{content:"\e53a"}.fa-right-to-bracket:before,.fa-sign-in-alt:before{content:"\f2f6"}.fa-venus:before{content:"\f221"}.fa-passport:before{content:"\f5ab"}.fa-heart-pulse:before,.fa-heartbeat:before{content:"\f21e"}.fa-people-carry-box:before,.fa-people-carry:before{content:"\f4ce"}.fa-temperature-high:before{content:"\f769"}.fa-microchip:before{content:"\f2db"}.fa-crown:before{content:"\f521"}.fa-weight-hanging:before{content:"\f5cd"}.fa-xmarks-lines:before{content:"\e59a"}.fa-file-prescription:before{content:"\f572"}.fa-weight-scale:before,.fa-weight:before{content:"\f496"}.fa-user-friends:before,.fa-user-group:before{content:"\f500"}.fa-arrow-up-a-z:before,.fa-sort-alpha-up:before{content:"\f15e"}.fa-chess-knight:before{content:"\f441"}.fa-face-laugh-squint:before,.fa-laugh-squint:before{content:"\f59b"}.fa-wheelchair:before{content:"\f193"}.fa-arrow-circle-up:before,.fa-circle-arrow-up:before{content:"\f0aa"}.fa-toggle-on:before{content:"\f205"}.fa-person-walking:before,.fa-walking:before{content:"\f554"}.fa-l:before{content:"\4c"}.fa-fire:before{content:"\f06d"}.fa-bed-pulse:before,.fa-procedures:before{content:"\f487"}.fa-shuttle-space:before,.fa-space-shuttle:before{content:"\f197"}.fa-face-laugh:before,.fa-laugh:before{content:"\f599"}.fa-folder-open:before{content:"\f07c"}.fa-heart-circle-plus:before{content:"\e500"}.fa-code-fork:before{content:"\e13b"}.fa-city:before{content:"\f64f"}.fa-microphone-alt:before,.fa-microphone-lines:before{content:"\f3c9"}.fa-pepper-hot:before{content:"\f816"}.fa-unlock:before{content:"\f09c"}.fa-colon-sign:before{content:"\e140"}.fa-headset:before{content:"\f590"}.fa-store-slash:before{content:"\e071"}.fa-road-circle-xmark:before{content:"\e566"}.fa-user-minus:before{content:"\f503"}.fa-mars-stroke-up:before,.fa-mars-stroke-v:before{content:"\f22a"}.fa-champagne-glasses:before,.fa-glass-cheers:before{content:"\f79f"}.fa-clipboard:before{content:"\f328"}.fa-house-circle-exclamation:before{content:"\e50a"}.fa-file-arrow-up:before,.fa-file-upload:before{content:"\f574"}.fa-wifi-3:before,.fa-wifi-strong:before,.fa-wifi:before{content:"\f1eb"}.fa-bath:before,.fa-bathtub:before{content:"\f2cd"}.fa-underline:before{content:"\f0cd"}.fa-user-edit:before,.fa-user-pen:before{content:"\f4ff"}.fa-signature:before{content:"\f5b7"}.fa-stroopwafel:before{content:"\f551"}.fa-bold:before{content:"\f032"}.fa-anchor-lock:before{content:"\e4ad"}.fa-building-ngo:before{content:"\e4d7"}.fa-manat-sign:before{content:"\e1d5"}.fa-not-equal:before{content:"\f53e"}.fa-border-style:before,.fa-border-top-left:before{content:"\f853"}.fa-map-location-dot:before,.fa-map-marked-alt:before{content:"\f5a0"}.fa-jedi:before{content:"\f669"}.fa-poll:before,.fa-square-poll-vertical:before{content:"\f681"}.fa-mug-hot:before{content:"\f7b6"}.fa-battery-car:before,.fa-car-battery:before{content:"\f5df"}.fa-gift:before{content:"\f06b"}.fa-dice-two:before{content:"\f528"}.fa-chess-queen:before{content:"\f445"}.fa-glasses:before{content:"\f530"}.fa-chess-board:before{content:"\f43c"}.fa-building-circle-check:before{content:"\e4d2"}.fa-person-chalkboard:before{content:"\e53d"}.fa-mars-stroke-h:before,.fa-mars-stroke-right:before{content:"\f22b"}.fa-hand-back-fist:before,.fa-hand-rock:before{content:"\f255"}.fa-caret-square-up:before,.fa-square-caret-up:before{content:"\f151"}.fa-cloud-showers-water:before{content:"\e4e4"}.fa-bar-chart:before,.fa-chart-bar:before{content:"\f080"}.fa-hands-bubbles:before,.fa-hands-wash:before{content:"\e05e"}.fa-less-than-equal:before{content:"\f537"}.fa-train:before{content:"\f238"}.fa-eye-low-vision:before,.fa-low-vision:before{content:"\f2a8"}.fa-crow:before{content:"\f520"}.fa-sailboat:before{content:"\e445"}.fa-window-restore:before{content:"\f2d2"}.fa-plus-square:before,.fa-square-plus:before{content:"\f0fe"}.fa-torii-gate:before{content:"\f6a1"}.fa-frog:before{content:"\f52e"}.fa-bucket:before{content:"\e4cf"}.fa-image:before{content:"\f03e"}.fa-microphone:before{content:"\f130"}.fa-cow:before{content:"\f6c8"}.fa-caret-up:before{content:"\f0d8"}.fa-screwdriver:before{content:"\f54a"}.fa-folder-closed:before{content:"\e185"}.fa-house-tsunami:before{content:"\e515"}.fa-square-nfi:before{content:"\e576"}.fa-arrow-up-from-ground-water:before{content:"\e4b5"}.fa-glass-martini-alt:before,.fa-martini-glass:before{content:"\f57b"}.fa-rotate-back:before,.fa-rotate-backward:before,.fa-rotate-left:before,.fa-undo-alt:before{content:"\f2ea"}.fa-columns:before,.fa-table-columns:before{content:"\f0db"}.fa-lemon:before{content:"\f094"}.fa-head-side-mask:before{content:"\e063"}.fa-handshake:before{content:"\f2b5"}.fa-gem:before{content:"\f3a5"}.fa-dolly-box:before,.fa-dolly:before{content:"\f472"}.fa-smoking:before{content:"\f48d"}.fa-compress-arrows-alt:before,.fa-minimize:before{content:"\f78c"}.fa-monument:before{content:"\f5a6"}.fa-snowplow:before{content:"\f7d2"}.fa-angle-double-right:before,.fa-angles-right:before{content:"\f101"}.fa-cannabis:before{content:"\f55f"}.fa-circle-play:before,.fa-play-circle:before{content:"\f144"}.fa-tablets:before{content:"\f490"}.fa-ethernet:before{content:"\f796"}.fa-eur:before,.fa-euro-sign:before,.fa-euro:before{content:"\f153"}.fa-chair:before{content:"\f6c0"}.fa-check-circle:before,.fa-circle-check:before{content:"\f058"}.fa-circle-stop:before,.fa-stop-circle:before{content:"\f28d"}.fa-compass-drafting:before,.fa-drafting-compass:before{content:"\f568"}.fa-plate-wheat:before{content:"\e55a"}.fa-icicles:before{content:"\f7ad"}.fa-person-shelter:before{content:"\e54f"}.fa-neuter:before{content:"\f22c"}.fa-id-badge:before{content:"\f2c1"}.fa-marker:before{content:"\f5a1"}.fa-face-laugh-beam:before,.fa-laugh-beam:before{content:"\f59a"}.fa-helicopter-symbol:before{content:"\e502"}.fa-universal-access:before{content:"\f29a"}.fa-chevron-circle-up:before,.fa-circle-chevron-up:before{content:"\f139"}.fa-lari-sign:before{content:"\e1c8"}.fa-volcano:before{content:"\f770"}.fa-person-walking-dashed-line-arrow-right:before{content:"\e553"}.fa-gbp:before,.fa-pound-sign:before,.fa-sterling-sign:before{content:"\f154"}.fa-viruses:before{content:"\e076"}.fa-square-person-confined:before{content:"\e577"}.fa-user-tie:before{content:"\f508"}.fa-arrow-down-long:before,.fa-long-arrow-down:before{content:"\f175"}.fa-tent-arrow-down-to-line:before{content:"\e57e"}.fa-certificate:before{content:"\f0a3"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-suitcase:before{content:"\f0f2"}.fa-person-skating:before,.fa-skating:before{content:"\f7c5"}.fa-filter-circle-dollar:before,.fa-funnel-dollar:before{content:"\f662"}.fa-camera-retro:before{content:"\f083"}.fa-arrow-circle-down:before,.fa-circle-arrow-down:before{content:"\f0ab"}.fa-arrow-right-to-file:before,.fa-file-import:before{content:"\f56f"}.fa-external-link-square:before,.fa-square-arrow-up-right:before{content:"\f14c"}.fa-box-open:before{content:"\f49e"}.fa-scroll:before{content:"\f70e"}.fa-spa:before{content:"\f5bb"}.fa-location-pin-lock:before{content:"\e51f"}.fa-pause:before{content:"\f04c"}.fa-hill-avalanche:before{content:"\e507"}.fa-temperature-0:before,.fa-temperature-empty:before,.fa-thermometer-0:before,.fa-thermometer-empty:before{content:"\f2cb"}.fa-bomb:before{content:"\f1e2"}.fa-registered:before{content:"\f25d"}.fa-address-card:before,.fa-contact-card:before,.fa-vcard:before{content:"\f2bb"}.fa-balance-scale-right:before,.fa-scale-unbalanced-flip:before{content:"\f516"}.fa-subscript:before{content:"\f12c"}.fa-diamond-turn-right:before,.fa-directions:before{content:"\f5eb"}.fa-burst:before{content:"\e4dc"}.fa-house-laptop:before,.fa-laptop-house:before{content:"\e066"}.fa-face-tired:before,.fa-tired:before{content:"\f5c8"}.fa-money-bills:before{content:"\e1f3"}.fa-smog:before{content:"\f75f"}.fa-crutch:before{content:"\f7f7"}.fa-cloud-arrow-up:before,.fa-cloud-upload-alt:before,.fa-cloud-upload:before{content:"\f0ee"}.fa-palette:before{content:"\f53f"}.fa-arrows-turn-right:before{content:"\e4c0"}.fa-vest:before{content:"\e085"}.fa-ferry:before{content:"\e4ea"}.fa-arrows-down-to-people:before{content:"\e4b9"}.fa-seedling:before,.fa-sprout:before{content:"\f4d8"}.fa-arrows-alt-h:before,.fa-left-right:before{content:"\f337"}.fa-boxes-packing:before{content:"\e4c7"}.fa-arrow-circle-left:before,.fa-circle-arrow-left:before{content:"\f0a8"}.fa-group-arrows-rotate:before{content:"\e4f6"}.fa-bowl-food:before{content:"\e4c6"}.fa-candy-cane:before{content:"\f786"}.fa-arrow-down-wide-short:before,.fa-sort-amount-asc:before,.fa-sort-amount-down:before{content:"\f160"}.fa-cloud-bolt:before,.fa-thunderstorm:before{content:"\f76c"}.fa-remove-format:before,.fa-text-slash:before{content:"\f87d"}.fa-face-smile-wink:before,.fa-smile-wink:before{content:"\f4da"}.fa-file-word:before{content:"\f1c2"}.fa-file-powerpoint:before{content:"\f1c4"}.fa-arrows-h:before,.fa-arrows-left-right:before{content:"\f07e"}.fa-house-lock:before{content:"\e510"}.fa-cloud-arrow-down:before,.fa-cloud-download-alt:before,.fa-cloud-download:before{content:"\f0ed"}.fa-children:before{content:"\e4e1"}.fa-blackboard:before,.fa-chalkboard:before{content:"\f51b"}.fa-user-alt-slash:before,.fa-user-large-slash:before{content:"\f4fa"}.fa-envelope-open:before{content:"\f2b6"}.fa-handshake-alt-slash:before,.fa-handshake-simple-slash:before{content:"\e05f"}.fa-mattress-pillow:before{content:"\e525"}.fa-guarani-sign:before{content:"\e19a"}.fa-arrows-rotate:before,.fa-refresh:before,.fa-sync:before{content:"\f021"}.fa-fire-extinguisher:before{content:"\f134"}.fa-cruzeiro-sign:before{content:"\e152"}.fa-greater-than-equal:before{content:"\f532"}.fa-shield-alt:before,.fa-shield-halved:before{content:"\f3ed"}.fa-atlas:before,.fa-book-atlas:before{content:"\f558"}.fa-virus:before{content:"\e074"}.fa-envelope-circle-check:before{content:"\e4e8"}.fa-layer-group:before{content:"\f5fd"}.fa-arrows-to-dot:before{content:"\e4be"}.fa-archway:before{content:"\f557"}.fa-heart-circle-check:before{content:"\e4fd"}.fa-house-chimney-crack:before,.fa-house-damage:before{content:"\f6f1"}.fa-file-archive:before,.fa-file-zipper:before{content:"\f1c6"}.fa-square:before{content:"\f0c8"}.fa-glass-martini:before,.fa-martini-glass-empty:before{content:"\f000"}.fa-couch:before{content:"\f4b8"}.fa-cedi-sign:before{content:"\e0df"}.fa-italic:before{content:"\f033"}.fa-church:before{content:"\f51d"}.fa-comments-dollar:before{content:"\f653"}.fa-democrat:before{content:"\f747"}.fa-z:before{content:"\5a"}.fa-person-skiing:before,.fa-skiing:before{content:"\f7c9"}.fa-road-lock:before{content:"\e567"}.fa-a:before{content:"\41"}.fa-temperature-arrow-down:before,.fa-temperature-down:before{content:"\e03f"}.fa-feather-alt:before,.fa-feather-pointed:before{content:"\f56b"}.fa-p:before{content:"\50"}.fa-snowflake:before{content:"\f2dc"}.fa-newspaper:before{content:"\f1ea"}.fa-ad:before,.fa-rectangle-ad:before{content:"\f641"}.fa-arrow-circle-right:before,.fa-circle-arrow-right:before{content:"\f0a9"}.fa-filter-circle-xmark:before{content:"\e17b"}.fa-locust:before{content:"\e520"}.fa-sort:before,.fa-unsorted:before{content:"\f0dc"}.fa-list-1-2:before,.fa-list-numeric:before,.fa-list-ol:before{content:"\f0cb"}.fa-person-dress-burst:before{content:"\e544"}.fa-money-check-alt:before,.fa-money-check-dollar:before{content:"\f53d"}.fa-vector-square:before{content:"\f5cb"}.fa-bread-slice:before{content:"\f7ec"}.fa-language:before{content:"\f1ab"}.fa-face-kiss-wink-heart:before,.fa-kiss-wink-heart:before{content:"\f598"}.fa-filter:before{content:"\f0b0"}.fa-question:before{content:"\3f"}.fa-file-signature:before{content:"\f573"}.fa-arrows-alt:before,.fa-up-down-left-right:before{content:"\f0b2"}.fa-house-chimney-user:before{content:"\e065"}.fa-hand-holding-heart:before{content:"\f4be"}.fa-puzzle-piece:before{content:"\f12e"}.fa-money-check:before{content:"\f53c"}.fa-star-half-alt:before,.fa-star-half-stroke:before{content:"\f5c0"}.fa-code:before{content:"\f121"}.fa-glass-whiskey:before,.fa-whiskey-glass:before{content:"\f7a0"}.fa-building-circle-exclamation:before{content:"\e4d3"}.fa-magnifying-glass-chart:before{content:"\e522"}.fa-arrow-up-right-from-square:before,.fa-external-link:before{content:"\f08e"}.fa-cubes-stacked:before{content:"\e4e6"}.fa-krw:before,.fa-won-sign:before,.fa-won:before{content:"\f159"}.fa-virus-covid:before{content:"\e4a8"}.fa-austral-sign:before{content:"\e0a9"}.fa-f:before{content:"\46"}.fa-leaf:before{content:"\f06c"}.fa-road:before{content:"\f018"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-person-circle-plus:before{content:"\e541"}.fa-chart-pie:before,.fa-pie-chart:before{content:"\f200"}.fa-bolt-lightning:before{content:"\e0b7"}.fa-sack-xmark:before{content:"\e56a"}.fa-file-excel:before{content:"\f1c3"}.fa-file-contract:before{content:"\f56c"}.fa-fish-fins:before{content:"\e4f2"}.fa-building-flag:before{content:"\e4d5"}.fa-face-grin-beam:before,.fa-grin-beam:before{content:"\f582"}.fa-object-ungroup:before{content:"\f248"}.fa-poop:before{content:"\f619"}.fa-location-pin:before,.fa-map-marker:before{content:"\f041"}.fa-kaaba:before{content:"\f66b"}.fa-toilet-paper:before{content:"\f71e"}.fa-hard-hat:before,.fa-hat-hard:before,.fa-helmet-safety:before{content:"\f807"}.fa-eject:before{content:"\f052"}.fa-arrow-alt-circle-right:before,.fa-circle-right:before{content:"\f35a"}.fa-plane-circle-check:before{content:"\e555"}.fa-face-rolling-eyes:before,.fa-meh-rolling-eyes:before{content:"\f5a5"}.fa-object-group:before{content:"\f247"}.fa-chart-line:before,.fa-line-chart:before{content:"\f201"}.fa-mask-ventilator:before{content:"\e524"}.fa-arrow-right:before{content:"\f061"}.fa-map-signs:before,.fa-signs-post:before{content:"\f277"}.fa-cash-register:before{content:"\f788"}.fa-person-circle-question:before{content:"\e542"}.fa-h:before{content:"\48"}.fa-tarp:before{content:"\e57b"}.fa-screwdriver-wrench:before,.fa-tools:before{content:"\f7d9"}.fa-arrows-to-eye:before{content:"\e4bf"}.fa-plug-circle-bolt:before{content:"\e55b"}.fa-heart:before{content:"\f004"}.fa-mars-and-venus:before{content:"\f224"}.fa-home-user:before,.fa-house-user:before{content:"\e1b0"}.fa-dumpster-fire:before{content:"\f794"}.fa-house-crack:before{content:"\e3b1"}.fa-cocktail:before,.fa-martini-glass-citrus:before{content:"\f561"}.fa-face-surprise:before,.fa-surprise:before{content:"\f5c2"}.fa-bottle-water:before{content:"\e4c5"}.fa-circle-pause:before,.fa-pause-circle:before{content:"\f28b"}.fa-toilet-paper-slash:before{content:"\e072"}.fa-apple-alt:before,.fa-apple-whole:before{content:"\f5d1"}.fa-kitchen-set:before{content:"\e51a"}.fa-r:before{content:"\52"}.fa-temperature-1:before,.fa-temperature-quarter:before,.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:"\f2ca"}.fa-cube:before{content:"\f1b2"}.fa-bitcoin-sign:before{content:"\e0b4"}.fa-shield-dog:before{content:"\e573"}.fa-solar-panel:before{content:"\f5ba"}.fa-lock-open:before{content:"\f3c1"}.fa-elevator:before{content:"\e16d"}.fa-money-bill-transfer:before{content:"\e528"}.fa-money-bill-trend-up:before{content:"\e529"}.fa-house-flood-water-circle-arrow-right:before{content:"\e50f"}.fa-poll-h:before,.fa-square-poll-horizontal:before{content:"\f682"}.fa-circle:before{content:"\f111"}.fa-backward-fast:before,.fa-fast-backward:before{content:"\f049"}.fa-recycle:before{content:"\f1b8"}.fa-user-astronaut:before{content:"\f4fb"}.fa-plane-slash:before{content:"\e069"}.fa-trademark:before{content:"\f25c"}.fa-basketball-ball:before,.fa-basketball:before{content:"\f434"}.fa-satellite-dish:before{content:"\f7c0"}.fa-arrow-alt-circle-up:before,.fa-circle-up:before{content:"\f35b"}.fa-mobile-alt:before,.fa-mobile-screen-button:before{content:"\f3cd"}.fa-volume-high:before,.fa-volume-up:before{content:"\f028"}.fa-users-rays:before{content:"\e593"}.fa-wallet:before{content:"\f555"}.fa-clipboard-check:before{content:"\f46c"}.fa-file-audio:before{content:"\f1c7"}.fa-burger:before,.fa-hamburger:before{content:"\f805"}.fa-wrench:before{content:"\f0ad"}.fa-bugs:before{content:"\e4d0"}.fa-rupee-sign:before,.fa-rupee:before{content:"\f156"}.fa-file-image:before{content:"\f1c5"}.fa-circle-question:before,.fa-question-circle:before{content:"\f059"}.fa-plane-departure:before{content:"\f5b0"}.fa-handshake-slash:before{content:"\e060"}.fa-book-bookmark:before{content:"\e0bb"}.fa-code-branch:before{content:"\f126"}.fa-hat-cowboy:before{content:"\f8c0"}.fa-bridge:before{content:"\e4c8"}.fa-phone-alt:before,.fa-phone-flip:before{content:"\f879"}.fa-truck-front:before{content:"\e2b7"}.fa-cat:before{content:"\f6be"}.fa-anchor-circle-exclamation:before{content:"\e4ab"}.fa-truck-field:before{content:"\e58d"}.fa-route:before{content:"\f4d7"}.fa-clipboard-question:before{content:"\e4e3"}.fa-panorama:before{content:"\e209"}.fa-comment-medical:before{content:"\f7f5"}.fa-teeth-open:before{content:"\f62f"}.fa-file-circle-minus:before{content:"\e4ed"}.fa-tags:before{content:"\f02c"}.fa-wine-glass:before{content:"\f4e3"}.fa-fast-forward:before,.fa-forward-fast:before{content:"\f050"}.fa-face-meh-blank:before,.fa-meh-blank:before{content:"\f5a4"}.fa-parking:before,.fa-square-parking:before{content:"\f540"}.fa-house-signal:before{content:"\e012"}.fa-bars-progress:before,.fa-tasks-alt:before{content:"\f828"}.fa-faucet-drip:before{content:"\e006"}.fa-cart-flatbed:before,.fa-dolly-flatbed:before{content:"\f474"}.fa-ban-smoking:before,.fa-smoking-ban:before{content:"\f54d"}.fa-terminal:before{content:"\f120"}.fa-mobile-button:before{content:"\f10b"}.fa-house-medical-flag:before{content:"\e514"}.fa-basket-shopping:before,.fa-shopping-basket:before{content:"\f291"}.fa-tape:before{content:"\f4db"}.fa-bus-alt:before,.fa-bus-simple:before{content:"\f55e"}.fa-eye:before{content:"\f06e"}.fa-face-sad-cry:before,.fa-sad-cry:before{content:"\f5b3"}.fa-audio-description:before{content:"\f29e"}.fa-person-military-to-person:before{content:"\e54c"}.fa-file-shield:before{content:"\e4f0"}.fa-user-slash:before{content:"\f506"}.fa-pen:before{content:"\f304"}.fa-tower-observation:before{content:"\e586"}.fa-file-code:before{content:"\f1c9"}.fa-signal-5:before,.fa-signal-perfect:before,.fa-signal:before{content:"\f012"}.fa-bus:before{content:"\f207"}.fa-heart-circle-xmark:before{content:"\e501"}.fa-home-lg:before,.fa-house-chimney:before{content:"\e3af"}.fa-window-maximize:before{content:"\f2d0"}.fa-face-frown:before,.fa-frown:before{content:"\f119"}.fa-prescription:before{content:"\f5b1"}.fa-shop:before,.fa-store-alt:before{content:"\f54f"}.fa-floppy-disk:before,.fa-save:before{content:"\f0c7"}.fa-vihara:before{content:"\f6a7"}.fa-balance-scale-left:before,.fa-scale-unbalanced:before{content:"\f515"}.fa-sort-asc:before,.fa-sort-up:before{content:"\f0de"}.fa-comment-dots:before,.fa-commenting:before{content:"\f4ad"}.fa-plant-wilt:before{content:"\e5aa"}.fa-diamond:before{content:"\f219"}.fa-face-grin-squint:before,.fa-grin-squint:before{content:"\f585"}.fa-hand-holding-dollar:before,.fa-hand-holding-usd:before{content:"\f4c0"}.fa-bacterium:before{content:"\e05a"}.fa-hand-pointer:before{content:"\f25a"}.fa-drum-steelpan:before{content:"\f56a"}.fa-hand-scissors:before{content:"\f257"}.fa-hands-praying:before,.fa-praying-hands:before{content:"\f684"}.fa-arrow-right-rotate:before,.fa-arrow-rotate-forward:before,.fa-arrow-rotate-right:before,.fa-redo:before{content:"\f01e"}.fa-biohazard:before{content:"\f780"}.fa-location-crosshairs:before,.fa-location:before{content:"\f601"}.fa-mars-double:before{content:"\f227"}.fa-child-dress:before{content:"\e59c"}.fa-users-between-lines:before{content:"\e591"}.fa-lungs-virus:before{content:"\e067"}.fa-face-grin-tears:before,.fa-grin-tears:before{content:"\f588"}.fa-phone:before{content:"\f095"}.fa-calendar-times:before,.fa-calendar-xmark:before{content:"\f273"}.fa-child-reaching:before{content:"\e59d"}.fa-head-side-virus:before{content:"\e064"}.fa-user-cog:before,.fa-user-gear:before{content:"\f4fe"}.fa-arrow-up-1-9:before,.fa-sort-numeric-up:before{content:"\f163"}.fa-door-closed:before{content:"\f52a"}.fa-shield-virus:before{content:"\e06c"}.fa-dice-six:before{content:"\f526"}.fa-mosquito-net:before{content:"\e52c"}.fa-bridge-water:before{content:"\e4ce"}.fa-person-booth:before{content:"\f756"}.fa-text-width:before{content:"\f035"}.fa-hat-wizard:before{content:"\f6e8"}.fa-pen-fancy:before{content:"\f5ac"}.fa-digging:before,.fa-person-digging:before{content:"\f85e"}.fa-trash:before{content:"\f1f8"}.fa-gauge-simple-med:before,.fa-gauge-simple:before,.fa-tachometer-average:before{content:"\f629"}.fa-book-medical:before{content:"\f7e6"}.fa-poo:before{content:"\f2fe"}.fa-quote-right-alt:before,.fa-quote-right:before{content:"\f10e"}.fa-shirt:before,.fa-t-shirt:before,.fa-tshirt:before{content:"\f553"}.fa-cubes:before{content:"\f1b3"}.fa-divide:before{content:"\f529"}.fa-tenge-sign:before,.fa-tenge:before{content:"\f7d7"}.fa-headphones:before{content:"\f025"}.fa-hands-holding:before{content:"\f4c2"}.fa-hands-clapping:before{content:"\e1a8"}.fa-republican:before{content:"\f75e"}.fa-arrow-left:before{content:"\f060"}.fa-person-circle-xmark:before{content:"\e543"}.fa-ruler:before{content:"\f545"}.fa-align-left:before{content:"\f036"}.fa-dice-d6:before{content:"\f6d1"}.fa-restroom:before{content:"\f7bd"}.fa-j:before{content:"\4a"}.fa-users-viewfinder:before{content:"\e595"}.fa-file-video:before{content:"\f1c8"}.fa-external-link-alt:before,.fa-up-right-from-square:before{content:"\f35d"}.fa-table-cells:before,.fa-th:before{content:"\f00a"}.fa-file-pdf:before{content:"\f1c1"}.fa-bible:before,.fa-book-bible:before{content:"\f647"}.fa-o:before{content:"\4f"}.fa-medkit:before,.fa-suitcase-medical:before{content:"\f0fa"}.fa-user-secret:before{content:"\f21b"}.fa-otter:before{content:"\f700"}.fa-female:before,.fa-person-dress:before{content:"\f182"}.fa-comment-dollar:before{content:"\f651"}.fa-briefcase-clock:before,.fa-business-time:before{content:"\f64a"}.fa-table-cells-large:before,.fa-th-large:before{content:"\f009"}.fa-book-tanakh:before,.fa-tanakh:before{content:"\f827"}.fa-phone-volume:before,.fa-volume-control-phone:before{content:"\f2a0"}.fa-hat-cowboy-side:before{content:"\f8c1"}.fa-clipboard-user:before{content:"\f7f3"}.fa-child:before{content:"\f1ae"}.fa-lira-sign:before{content:"\f195"}.fa-satellite:before{content:"\f7bf"}.fa-plane-lock:before{content:"\e558"}.fa-tag:before{content:"\f02b"}.fa-comment:before{content:"\f075"}.fa-birthday-cake:before,.fa-cake-candles:before,.fa-cake:before{content:"\f1fd"}.fa-envelope:before{content:"\f0e0"}.fa-angle-double-up:before,.fa-angles-up:before{content:"\f102"}.fa-paperclip:before{content:"\f0c6"}.fa-arrow-right-to-city:before{content:"\e4b3"}.fa-ribbon:before{content:"\f4d6"}.fa-lungs:before{content:"\f604"}.fa-arrow-up-9-1:before,.fa-sort-numeric-up-alt:before{content:"\f887"}.fa-litecoin-sign:before{content:"\e1d3"}.fa-border-none:before{content:"\f850"}.fa-circle-nodes:before{content:"\e4e2"}.fa-parachute-box:before{content:"\f4cd"}.fa-indent:before{content:"\f03c"}.fa-truck-field-un:before{content:"\e58e"}.fa-hourglass-empty:before,.fa-hourglass:before{content:"\f254"}.fa-mountain:before{content:"\f6fc"}.fa-user-doctor:before,.fa-user-md:before{content:"\f0f0"}.fa-circle-info:before,.fa-info-circle:before{content:"\f05a"}.fa-cloud-meatball:before{content:"\f73b"}.fa-camera-alt:before,.fa-camera:before{content:"\f030"}.fa-square-virus:before{content:"\e578"}.fa-meteor:before{content:"\f753"}.fa-car-on:before{content:"\e4dd"}.fa-sleigh:before{content:"\f7cc"}.fa-arrow-down-1-9:before,.fa-sort-numeric-asc:before,.fa-sort-numeric-down:before{content:"\f162"}.fa-hand-holding-droplet:before,.fa-hand-holding-water:before{content:"\f4c1"}.fa-water:before{content:"\f773"}.fa-calendar-check:before{content:"\f274"}.fa-braille:before{content:"\f2a1"}.fa-prescription-bottle-alt:before,.fa-prescription-bottle-medical:before{content:"\f486"}.fa-landmark:before{content:"\f66f"}.fa-truck:before{content:"\f0d1"}.fa-crosshairs:before{content:"\f05b"}.fa-person-cane:before{content:"\e53c"}.fa-tent:before{content:"\e57d"}.fa-vest-patches:before{content:"\e086"}.fa-check-double:before{content:"\f560"}.fa-arrow-down-a-z:before,.fa-sort-alpha-asc:before,.fa-sort-alpha-down:before{content:"\f15d"}.fa-money-bill-wheat:before{content:"\e52a"}.fa-cookie:before{content:"\f563"}.fa-arrow-left-rotate:before,.fa-arrow-rotate-back:before,.fa-arrow-rotate-backward:before,.fa-arrow-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-hard-drive:before,.fa-hdd:before{content:"\f0a0"}.fa-face-grin-squint-tears:before,.fa-grin-squint-tears:before{content:"\f586"}.fa-dumbbell:before{content:"\f44b"}.fa-list-alt:before,.fa-rectangle-list:before{content:"\f022"}.fa-tarp-droplet:before{content:"\e57c"}.fa-house-medical-circle-check:before{content:"\e511"}.fa-person-skiing-nordic:before,.fa-skiing-nordic:before{content:"\f7ca"}.fa-calendar-plus:before{content:"\f271"}.fa-plane-arrival:before{content:"\f5af"}.fa-arrow-alt-circle-left:before,.fa-circle-left:before{content:"\f359"}.fa-subway:before,.fa-train-subway:before{content:"\f239"}.fa-chart-gantt:before{content:"\e0e4"}.fa-indian-rupee-sign:before,.fa-indian-rupee:before,.fa-inr:before{content:"\e1bc"}.fa-crop-alt:before,.fa-crop-simple:before{content:"\f565"}.fa-money-bill-1:before,.fa-money-bill-alt:before{content:"\f3d1"}.fa-left-long:before,.fa-long-arrow-alt-left:before{content:"\f30a"}.fa-dna:before{content:"\f471"}.fa-virus-slash:before{content:"\e075"}.fa-minus:before,.fa-subtract:before{content:"\f068"}.fa-chess:before{content:"\f439"}.fa-arrow-left-long:before,.fa-long-arrow-left:before{content:"\f177"}.fa-plug-circle-check:before{content:"\e55c"}.fa-street-view:before{content:"\f21d"}.fa-franc-sign:before{content:"\e18f"}.fa-volume-off:before{content:"\f026"}.fa-american-sign-language-interpreting:before,.fa-asl-interpreting:before,.fa-hands-american-sign-language-interpreting:before,.fa-hands-asl-interpreting:before{content:"\f2a3"}.fa-cog:before,.fa-gear:before{content:"\f013"}.fa-droplet-slash:before,.fa-tint-slash:before{content:"\f5c7"}.fa-mosque:before{content:"\f678"}.fa-mosquito:before{content:"\e52b"}.fa-star-of-david:before{content:"\f69a"}.fa-person-military-rifle:before{content:"\e54b"}.fa-cart-shopping:before,.fa-shopping-cart:before{content:"\f07a"}.fa-vials:before{content:"\f493"}.fa-plug-circle-plus:before{content:"\e55f"}.fa-place-of-worship:before{content:"\f67f"}.fa-grip-vertical:before{content:"\f58e"}.fa-arrow-turn-up:before,.fa-level-up:before{content:"\f148"}.fa-u:before{content:"\55"}.fa-square-root-alt:before,.fa-square-root-variable:before{content:"\f698"}.fa-clock-four:before,.fa-clock:before{content:"\f017"}.fa-backward-step:before,.fa-step-backward:before{content:"\f048"}.fa-pallet:before{content:"\f482"}.fa-faucet:before{content:"\e005"}.fa-baseball-bat-ball:before{content:"\f432"}.fa-s:before{content:"\53"}.fa-timeline:before{content:"\e29c"}.fa-keyboard:before{content:"\f11c"}.fa-caret-down:before{content:"\f0d7"}.fa-clinic-medical:before,.fa-house-chimney-medical:before{content:"\f7f2"}.fa-temperature-3:before,.fa-temperature-three-quarters:before,.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-mobile-android-alt:before,.fa-mobile-screen:before{content:"\f3cf"}.fa-plane-up:before{content:"\e22d"}.fa-piggy-bank:before{content:"\f4d3"}.fa-battery-3:before,.fa-battery-half:before{content:"\f242"}.fa-mountain-city:before{content:"\e52e"}.fa-coins:before{content:"\f51e"}.fa-khanda:before{content:"\f66d"}.fa-sliders-h:before,.fa-sliders:before{content:"\f1de"}.fa-folder-tree:before{content:"\f802"}.fa-network-wired:before{content:"\f6ff"}.fa-map-pin:before{content:"\f276"}.fa-hamsa:before{content:"\f665"}.fa-cent-sign:before{content:"\e3f5"}.fa-flask:before{content:"\f0c3"}.fa-person-pregnant:before{content:"\e31e"}.fa-wand-sparkles:before{content:"\f72b"}.fa-ellipsis-v:before,.fa-ellipsis-vertical:before{content:"\f142"}.fa-ticket:before{content:"\f145"}.fa-power-off:before{content:"\f011"}.fa-long-arrow-alt-right:before,.fa-right-long:before{content:"\f30b"}.fa-flag-usa:before{content:"\f74d"}.fa-laptop-file:before{content:"\e51d"}.fa-teletype:before,.fa-tty:before{content:"\f1e4"}.fa-diagram-next:before{content:"\e476"}.fa-person-rifle:before{content:"\e54e"}.fa-house-medical-circle-exclamation:before{content:"\e512"}.fa-closed-captioning:before{content:"\f20a"}.fa-hiking:before,.fa-person-hiking:before{content:"\f6ec"}.fa-venus-double:before{content:"\f226"}.fa-images:before{content:"\f302"}.fa-calculator:before{content:"\f1ec"}.fa-people-pulling:before{content:"\e535"}.fa-n:before{content:"\4e"}.fa-cable-car:before,.fa-tram:before{content:"\f7da"}.fa-cloud-rain:before{content:"\f73d"}.fa-building-circle-xmark:before{content:"\e4d4"}.fa-ship:before{content:"\f21a"}.fa-arrows-down-to-line:before{content:"\e4b8"}.fa-download:before{content:"\f019"}.fa-face-grin:before,.fa-grin:before{content:"\f580"}.fa-backspace:before,.fa-delete-left:before{content:"\f55a"}.fa-eye-dropper-empty:before,.fa-eye-dropper:before,.fa-eyedropper:before{content:"\f1fb"}.fa-file-circle-check:before{content:"\e5a0"}.fa-forward:before{content:"\f04e"}.fa-mobile-android:before,.fa-mobile-phone:before,.fa-mobile:before{content:"\f3ce"}.fa-face-meh:before,.fa-meh:before{content:"\f11a"}.fa-align-center:before{content:"\f037"}.fa-book-dead:before,.fa-book-skull:before{content:"\f6b7"}.fa-drivers-license:before,.fa-id-card:before{content:"\f2c2"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-heart-circle-exclamation:before{content:"\e4fe"}.fa-home-alt:before,.fa-home-lg-alt:before,.fa-home:before,.fa-house:before{content:"\f015"}.fa-calendar-week:before{content:"\f784"}.fa-laptop-medical:before{content:"\f812"}.fa-b:before{content:"\42"}.fa-file-medical:before{content:"\f477"}.fa-dice-one:before{content:"\f525"}.fa-kiwi-bird:before{content:"\f535"}.fa-arrow-right-arrow-left:before,.fa-exchange:before{content:"\f0ec"}.fa-redo-alt:before,.fa-rotate-forward:before,.fa-rotate-right:before{content:"\f2f9"}.fa-cutlery:before,.fa-utensils:before{content:"\f2e7"}.fa-arrow-up-wide-short:before,.fa-sort-amount-up:before{content:"\f161"}.fa-mill-sign:before{content:"\e1ed"}.fa-bowl-rice:before{content:"\e2eb"}.fa-skull:before{content:"\f54c"}.fa-broadcast-tower:before,.fa-tower-broadcast:before{content:"\f519"}.fa-truck-pickup:before{content:"\f63c"}.fa-long-arrow-alt-up:before,.fa-up-long:before{content:"\f30c"}.fa-stop:before{content:"\f04d"}.fa-code-merge:before{content:"\f387"}.fa-upload:before{content:"\f093"}.fa-hurricane:before{content:"\f751"}.fa-mound:before{content:"\e52d"}.fa-toilet-portable:before{content:"\e583"}.fa-compact-disc:before{content:"\f51f"}.fa-file-arrow-down:before,.fa-file-download:before{content:"\f56d"}.fa-caravan:before{content:"\f8ff"}.fa-shield-cat:before{content:"\e572"}.fa-bolt:before,.fa-zap:before{content:"\f0e7"}.fa-glass-water:before{content:"\e4f4"}.fa-oil-well:before{content:"\e532"}.fa-vault:before{content:"\e2c5"}.fa-mars:before{content:"\f222"}.fa-toilet:before{content:"\f7d8"}.fa-plane-circle-xmark:before{content:"\e557"}.fa-cny:before,.fa-jpy:before,.fa-rmb:before,.fa-yen-sign:before,.fa-yen:before{content:"\f157"}.fa-rouble:before,.fa-rub:before,.fa-ruble-sign:before,.fa-ruble:before{content:"\f158"}.fa-sun:before{content:"\f185"}.fa-guitar:before{content:"\f7a6"}.fa-face-laugh-wink:before,.fa-laugh-wink:before{content:"\f59c"}.fa-horse-head:before{content:"\f7ab"}.fa-bore-hole:before{content:"\e4c3"}.fa-industry:before{content:"\f275"}.fa-arrow-alt-circle-down:before,.fa-circle-down:before{content:"\f358"}.fa-arrows-turn-to-dots:before{content:"\e4c1"}.fa-florin-sign:before{content:"\e184"}.fa-arrow-down-short-wide:before,.fa-sort-amount-desc:before,.fa-sort-amount-down-alt:before{content:"\f884"}.fa-less-than:before{content:"\3c"}.fa-angle-down:before{content:"\f107"}.fa-car-tunnel:before{content:"\e4de"}.fa-head-side-cough:before{content:"\e061"}.fa-grip-lines:before{content:"\f7a4"}.fa-thumbs-down:before{content:"\f165"}.fa-user-lock:before{content:"\f502"}.fa-arrow-right-long:before,.fa-long-arrow-right:before{content:"\f178"}.fa-anchor-circle-xmark:before{content:"\e4ac"}.fa-ellipsis-h:before,.fa-ellipsis:before{content:"\f141"}.fa-chess-pawn:before{content:"\f443"}.fa-first-aid:before,.fa-kit-medical:before{content:"\f479"}.fa-person-through-window:before{content:"\e5a9"}.fa-toolbox:before{content:"\f552"}.fa-hands-holding-circle:before{content:"\e4fb"}.fa-bug:before{content:"\f188"}.fa-credit-card-alt:before,.fa-credit-card:before{content:"\f09d"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-hand-holding-hand:before{content:"\e4f7"}.fa-book-open-reader:before,.fa-book-reader:before{content:"\f5da"}.fa-mountain-sun:before{content:"\e52f"}.fa-arrows-left-right-to-line:before{content:"\e4ba"}.fa-dice-d20:before{content:"\f6cf"}.fa-truck-droplet:before{content:"\e58c"}.fa-file-circle-xmark:before{content:"\e5a1"}.fa-temperature-arrow-up:before,.fa-temperature-up:before{content:"\e040"}.fa-medal:before{content:"\f5a2"}.fa-bed:before{content:"\f236"}.fa-h-square:before,.fa-square-h:before{content:"\f0fd"}.fa-podcast:before{content:"\f2ce"}.fa-temperature-4:before,.fa-temperature-full:before,.fa-thermometer-4:before,.fa-thermometer-full:before{content:"\f2c7"}.fa-bell:before{content:"\f0f3"}.fa-superscript:before{content:"\f12b"}.fa-plug-circle-xmark:before{content:"\e560"}.fa-star-of-life:before{content:"\f621"}.fa-phone-slash:before{content:"\f3dd"}.fa-paint-roller:before{content:"\f5aa"}.fa-hands-helping:before,.fa-handshake-angle:before{content:"\f4c4"}.fa-location-dot:before,.fa-map-marker-alt:before{content:"\f3c5"}.fa-file:before{content:"\f15b"}.fa-greater-than:before{content:"\3e"}.fa-person-swimming:before,.fa-swimmer:before{content:"\f5c4"}.fa-arrow-down:before{content:"\f063"}.fa-droplet:before,.fa-tint:before{content:"\f043"}.fa-eraser:before{content:"\f12d"}.fa-earth-america:before,.fa-earth-americas:before,.fa-earth:before,.fa-globe-americas:before{content:"\f57d"}.fa-person-burst:before{content:"\e53b"}.fa-dove:before{content:"\f4ba"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-socks:before{content:"\f696"}.fa-inbox:before{content:"\f01c"}.fa-section:before{content:"\e447"}.fa-gauge-high:before,.fa-tachometer-alt-fast:before,.fa-tachometer-alt:before{content:"\f625"}.fa-envelope-open-text:before{content:"\f658"}.fa-hospital-alt:before,.fa-hospital-wide:before,.fa-hospital:before{content:"\f0f8"}.fa-wine-bottle:before{content:"\f72f"}.fa-chess-rook:before{content:"\f447"}.fa-bars-staggered:before,.fa-reorder:before,.fa-stream:before{content:"\f550"}.fa-dharmachakra:before{content:"\f655"}.fa-hotdog:before{content:"\f80f"}.fa-blind:before,.fa-person-walking-with-cane:before{content:"\f29d"}.fa-drum:before{content:"\f569"}.fa-ice-cream:before{content:"\f810"}.fa-heart-circle-bolt:before{content:"\e4fc"}.fa-fax:before{content:"\f1ac"}.fa-paragraph:before{content:"\f1dd"}.fa-check-to-slot:before,.fa-vote-yea:before{content:"\f772"}.fa-star-half:before{content:"\f089"}.fa-boxes-alt:before,.fa-boxes-stacked:before,.fa-boxes:before{content:"\f468"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-assistive-listening-systems:before,.fa-ear-listen:before{content:"\f2a2"}.fa-tree-city:before{content:"\e587"}.fa-play:before{content:"\f04b"}.fa-font:before{content:"\f031"}.fa-rupiah-sign:before{content:"\e23d"}.fa-magnifying-glass:before,.fa-search:before{content:"\f002"}.fa-ping-pong-paddle-ball:before,.fa-table-tennis-paddle-ball:before,.fa-table-tennis:before{content:"\f45d"}.fa-diagnoses:before,.fa-person-dots-from-line:before{content:"\f470"}.fa-trash-can-arrow-up:before,.fa-trash-restore-alt:before{content:"\f82a"}.fa-naira-sign:before{content:"\e1f6"}.fa-cart-arrow-down:before{content:"\f218"}.fa-walkie-talkie:before{content:"\f8ef"}.fa-file-edit:before,.fa-file-pen:before{content:"\f31c"}.fa-receipt:before{content:"\f543"}.fa-pen-square:before,.fa-pencil-square:before,.fa-square-pen:before{content:"\f14b"}.fa-suitcase-rolling:before{content:"\f5c1"}.fa-person-circle-exclamation:before{content:"\e53f"}.fa-chevron-down:before{content:"\f078"}.fa-battery-5:before,.fa-battery-full:before,.fa-battery:before{content:"\f240"}.fa-skull-crossbones:before{content:"\f714"}.fa-code-compare:before{content:"\e13a"}.fa-list-dots:before,.fa-list-ul:before{content:"\f0ca"}.fa-school-lock:before{content:"\e56f"}.fa-tower-cell:before{content:"\e585"}.fa-down-long:before,.fa-long-arrow-alt-down:before{content:"\f309"}.fa-ranking-star:before{content:"\e561"}.fa-chess-king:before{content:"\f43f"}.fa-person-harassing:before{content:"\e549"}.fa-brazilian-real-sign:before{content:"\e46c"}.fa-landmark-alt:before,.fa-landmark-dome:before{content:"\f752"}.fa-arrow-up:before{content:"\f062"}.fa-television:before,.fa-tv-alt:before,.fa-tv:before{content:"\f26c"}.fa-shrimp:before{content:"\e448"}.fa-list-check:before,.fa-tasks:before{content:"\f0ae"}.fa-jug-detergent:before{content:"\e519"}.fa-circle-user:before,.fa-user-circle:before{content:"\f2bd"}.fa-user-shield:before{content:"\f505"}.fa-wind:before{content:"\f72e"}.fa-car-burst:before,.fa-car-crash:before{content:"\f5e1"}.fa-y:before{content:"\59"}.fa-person-snowboarding:before,.fa-snowboarding:before{content:"\f7ce"}.fa-shipping-fast:before,.fa-truck-fast:before{content:"\f48b"}.fa-fish:before{content:"\f578"}.fa-user-graduate:before{content:"\f501"}.fa-adjust:before,.fa-circle-half-stroke:before{content:"\f042"}.fa-clapperboard:before{content:"\e131"}.fa-circle-radiation:before,.fa-radiation-alt:before{content:"\f7ba"}.fa-baseball-ball:before,.fa-baseball:before{content:"\f433"}.fa-jet-fighter-up:before{content:"\e518"}.fa-diagram-project:before,.fa-project-diagram:before{content:"\f542"}.fa-copy:before{content:"\f0c5"}.fa-volume-mute:before,.fa-volume-times:before,.fa-volume-xmark:before{content:"\f6a9"}.fa-hand-sparkles:before{content:"\e05d"}.fa-grip-horizontal:before,.fa-grip:before{content:"\f58d"}.fa-share-from-square:before,.fa-share-square:before{content:"\f14d"}.fa-child-combatant:before,.fa-child-rifle:before{content:"\e4e0"}.fa-gun:before{content:"\e19b"}.fa-phone-square:before,.fa-square-phone:before{content:"\f098"}.fa-add:before,.fa-plus:before{content:"\2b"}.fa-expand:before{content:"\f065"}.fa-computer:before{content:"\e4e5"}.fa-close:before,.fa-multiply:before,.fa-remove:before,.fa-times:before,.fa-xmark:before{content:"\f00d"}.fa-arrows-up-down-left-right:before,.fa-arrows:before{content:"\f047"}.fa-chalkboard-teacher:before,.fa-chalkboard-user:before{content:"\f51c"}.fa-peso-sign:before{content:"\e222"}.fa-building-shield:before{content:"\e4d8"}.fa-baby:before{content:"\f77c"}.fa-users-line:before{content:"\e592"}.fa-quote-left-alt:before,.fa-quote-left:before{content:"\f10d"}.fa-tractor:before{content:"\f722"}.fa-trash-arrow-up:before,.fa-trash-restore:before{content:"\f829"}.fa-arrow-down-up-lock:before{content:"\e4b0"}.fa-lines-leaning:before{content:"\e51e"}.fa-ruler-combined:before{content:"\f546"}.fa-copyright:before{content:"\f1f9"}.fa-equals:before{content:"\3d"}.fa-blender:before{content:"\f517"}.fa-teeth:before{content:"\f62e"}.fa-ils:before,.fa-shekel-sign:before,.fa-shekel:before,.fa-sheqel-sign:before,.fa-sheqel:before{content:"\f20b"}.fa-map:before{content:"\f279"}.fa-rocket:before{content:"\f135"}.fa-photo-film:before,.fa-photo-video:before{content:"\f87c"}.fa-folder-minus:before{content:"\f65d"}.fa-store:before{content:"\f54e"}.fa-arrow-trend-up:before{content:"\e098"}.fa-plug-circle-minus:before{content:"\e55e"}.fa-sign-hanging:before,.fa-sign:before{content:"\f4d9"}.fa-bezier-curve:before{content:"\f55b"}.fa-bell-slash:before{content:"\f1f6"}.fa-tablet-android:before,.fa-tablet:before{content:"\f3fb"}.fa-school-flag:before{content:"\e56e"}.fa-fill:before{content:"\f575"}.fa-angle-up:before{content:"\f106"}.fa-drumstick-bite:before{content:"\f6d7"}.fa-holly-berry:before{content:"\f7aa"}.fa-chevron-left:before{content:"\f053"}.fa-bacteria:before{content:"\e059"}.fa-hand-lizard:before{content:"\f258"}.fa-notdef:before{content:"\e1fe"}.fa-disease:before{content:"\f7fa"}.fa-briefcase-medical:before{content:"\f469"}.fa-genderless:before{content:"\f22d"}.fa-chevron-right:before{content:"\f054"}.fa-retweet:before{content:"\f079"}.fa-car-alt:before,.fa-car-rear:before{content:"\f5de"}.fa-pump-soap:before{content:"\e06b"}.fa-video-slash:before{content:"\f4e2"}.fa-battery-2:before,.fa-battery-quarter:before{content:"\f243"}.fa-radio:before{content:"\f8d7"}.fa-baby-carriage:before,.fa-carriage-baby:before{content:"\f77d"}.fa-traffic-light:before{content:"\f637"}.fa-thermometer:before{content:"\f491"}.fa-vr-cardboard:before{content:"\f729"}.fa-hand-middle-finger:before{content:"\f806"}.fa-percent:before,.fa-percentage:before{content:"\25"}.fa-truck-moving:before{content:"\f4df"}.fa-glass-water-droplet:before{content:"\e4f5"}.fa-display:before{content:"\e163"}.fa-face-smile:before,.fa-smile:before{content:"\f118"}.fa-thumb-tack:before,.fa-thumbtack:before{content:"\f08d"}.fa-trophy:before{content:"\f091"}.fa-person-praying:before,.fa-pray:before{content:"\f683"}.fa-hammer:before{content:"\f6e3"}.fa-hand-peace:before{content:"\f25b"}.fa-rotate:before,.fa-sync-alt:before{content:"\f2f1"}.fa-spinner:before{content:"\f110"}.fa-robot:before{content:"\f544"}.fa-peace:before{content:"\f67c"}.fa-cogs:before,.fa-gears:before{content:"\f085"}.fa-warehouse:before{content:"\f494"}.fa-arrow-up-right-dots:before{content:"\e4b7"}.fa-splotch:before{content:"\f5bc"}.fa-face-grin-hearts:before,.fa-grin-hearts:before{content:"\f584"}.fa-dice-four:before{content:"\f524"}.fa-sim-card:before{content:"\f7c4"}.fa-transgender-alt:before,.fa-transgender:before{content:"\f225"}.fa-mercury:before{content:"\f223"}.fa-arrow-turn-down:before,.fa-level-down:before{content:"\f149"}.fa-person-falling-burst:before{content:"\e547"}.fa-award:before{content:"\f559"}.fa-ticket-alt:before,.fa-ticket-simple:before{content:"\f3ff"}.fa-building:before{content:"\f1ad"}.fa-angle-double-left:before,.fa-angles-left:before{content:"\f100"}.fa-qrcode:before{content:"\f029"}.fa-clock-rotate-left:before,.fa-history:before{content:"\f1da"}.fa-face-grin-beam-sweat:before,.fa-grin-beam-sweat:before{content:"\f583"}.fa-arrow-right-from-file:before,.fa-file-export:before{content:"\f56e"}.fa-shield-blank:before,.fa-shield:before{content:"\f132"}.fa-arrow-up-short-wide:before,.fa-sort-amount-up-alt:before{content:"\f885"}.fa-house-medical:before{content:"\e3b2"}.fa-golf-ball-tee:before,.fa-golf-ball:before{content:"\f450"}.fa-chevron-circle-left:before,.fa-circle-chevron-left:before{content:"\f137"}.fa-house-chimney-window:before{content:"\e00d"}.fa-pen-nib:before{content:"\f5ad"}.fa-tent-arrow-turn-left:before{content:"\e580"}.fa-tents:before{content:"\e582"}.fa-magic:before,.fa-wand-magic:before{content:"\f0d0"}.fa-dog:before{content:"\f6d3"}.fa-carrot:before{content:"\f787"}.fa-moon:before{content:"\f186"}.fa-wine-glass-alt:before,.fa-wine-glass-empty:before{content:"\f5ce"}.fa-cheese:before{content:"\f7ef"}.fa-yin-yang:before{content:"\f6ad"}.fa-music:before{content:"\f001"}.fa-code-commit:before{content:"\f386"}.fa-temperature-low:before{content:"\f76b"}.fa-biking:before,.fa-person-biking:before{content:"\f84a"}.fa-broom:before{content:"\f51a"}.fa-shield-heart:before{content:"\e574"}.fa-gopuram:before{content:"\f664"}.fa-earth-oceania:before,.fa-globe-oceania:before{content:"\e47b"}.fa-square-xmark:before,.fa-times-square:before,.fa-xmark-square:before{content:"\f2d3"}.fa-hashtag:before{content:"\23"}.fa-expand-alt:before,.fa-up-right-and-down-left-from-center:before{content:"\f424"}.fa-oil-can:before{content:"\f613"}.fa-t:before{content:"\54"}.fa-hippo:before{content:"\f6ed"}.fa-chart-column:before{content:"\e0e3"}.fa-infinity:before{content:"\f534"}.fa-vial-circle-check:before{content:"\e596"}.fa-person-arrow-down-to-line:before{content:"\e538"}.fa-voicemail:before{content:"\f897"}.fa-fan:before{content:"\f863"}.fa-person-walking-luggage:before{content:"\e554"}.fa-arrows-alt-v:before,.fa-up-down:before{content:"\f338"}.fa-cloud-moon-rain:before{content:"\f73c"}.fa-calendar:before{content:"\f133"}.fa-trailer:before{content:"\e041"}.fa-bahai:before,.fa-haykal:before{content:"\f666"}.fa-sd-card:before{content:"\f7c2"}.fa-dragon:before{content:"\f6d5"}.fa-shoe-prints:before{content:"\f54b"}.fa-circle-plus:before,.fa-plus-circle:before{content:"\f055"}.fa-face-grin-tongue-wink:before,.fa-grin-tongue-wink:before{content:"\f58b"}.fa-hand-holding:before{content:"\f4bd"}.fa-plug-circle-exclamation:before{content:"\e55d"}.fa-chain-broken:before,.fa-chain-slash:before,.fa-link-slash:before,.fa-unlink:before{content:"\f127"}.fa-clone:before{content:"\f24d"}.fa-person-walking-arrow-loop-left:before{content:"\e551"}.fa-arrow-up-z-a:before,.fa-sort-alpha-up-alt:before{content:"\f882"}.fa-fire-alt:before,.fa-fire-flame-curved:before{content:"\f7e4"}.fa-tornado:before{content:"\f76f"}.fa-file-circle-plus:before{content:"\e494"}.fa-book-quran:before,.fa-quran:before{content:"\f687"}.fa-anchor:before{content:"\f13d"}.fa-border-all:before{content:"\f84c"}.fa-angry:before,.fa-face-angry:before{content:"\f556"}.fa-cookie-bite:before{content:"\f564"}.fa-arrow-trend-down:before{content:"\e097"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-draw-polygon:before{content:"\f5ee"}.fa-balance-scale:before,.fa-scale-balanced:before{content:"\f24e"}.fa-gauge-simple-high:before,.fa-tachometer-fast:before,.fa-tachometer:before{content:"\f62a"}.fa-shower:before{content:"\f2cc"}.fa-desktop-alt:before,.fa-desktop:before{content:"\f390"}.fa-m:before{content:"\4d"}.fa-table-list:before,.fa-th-list:before{content:"\f00b"}.fa-comment-sms:before,.fa-sms:before{content:"\f7cd"}.fa-book:before{content:"\f02d"}.fa-user-plus:before{content:"\f234"}.fa-check:before{content:"\f00c"}.fa-battery-4:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-house-circle-check:before{content:"\e509"}.fa-angle-left:before{content:"\f104"}.fa-diagram-successor:before{content:"\e47a"}.fa-truck-arrow-right:before{content:"\e58b"}.fa-arrows-split-up-and-left:before{content:"\e4bc"}.fa-fist-raised:before,.fa-hand-fist:before{content:"\f6de"}.fa-cloud-moon:before{content:"\f6c3"}.fa-briefcase:before{content:"\f0b1"}.fa-person-falling:before{content:"\e546"}.fa-image-portrait:before,.fa-portrait:before{content:"\f3e0"}.fa-user-tag:before{content:"\f507"}.fa-rug:before{content:"\e569"}.fa-earth-europe:before,.fa-globe-europe:before{content:"\f7a2"}.fa-cart-flatbed-suitcase:before,.fa-luggage-cart:before{content:"\f59d"}.fa-rectangle-times:before,.fa-rectangle-xmark:before,.fa-times-rectangle:before,.fa-window-close:before{content:"\f410"}.fa-baht-sign:before{content:"\e0ac"}.fa-book-open:before{content:"\f518"}.fa-book-journal-whills:before,.fa-journal-whills:before{content:"\f66a"}.fa-handcuffs:before{content:"\e4f8"}.fa-exclamation-triangle:before,.fa-triangle-exclamation:before,.fa-warning:before{content:"\f071"}.fa-database:before{content:"\f1c0"}.fa-arrow-turn-right:before,.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-bottle-droplet:before{content:"\e4c4"}.fa-mask-face:before{content:"\e1d7"}.fa-hill-rockslide:before{content:"\e508"}.fa-exchange-alt:before,.fa-right-left:before{content:"\f362"}.fa-paper-plane:before{content:"\f1d8"}.fa-road-circle-exclamation:before{content:"\e565"}.fa-dungeon:before{content:"\f6d9"}.fa-align-right:before{content:"\f038"}.fa-money-bill-1-wave:before,.fa-money-bill-wave-alt:before{content:"\f53b"}.fa-life-ring:before{content:"\f1cd"}.fa-hands:before,.fa-sign-language:before,.fa-signing:before{content:"\f2a7"}.fa-calendar-day:before{content:"\f783"}.fa-ladder-water:before,.fa-swimming-pool:before,.fa-water-ladder:before{content:"\f5c5"}.fa-arrows-up-down:before,.fa-arrows-v:before{content:"\f07d"}.fa-face-grimace:before,.fa-grimace:before{content:"\f57f"}.fa-wheelchair-alt:before,.fa-wheelchair-move:before{content:"\e2ce"}.fa-level-down-alt:before,.fa-turn-down:before{content:"\f3be"}.fa-person-walking-arrow-right:before{content:"\e552"}.fa-envelope-square:before,.fa-square-envelope:before{content:"\f199"}.fa-dice:before{content:"\f522"}.fa-bowling-ball:before{content:"\f436"}.fa-brain:before{content:"\f5dc"}.fa-band-aid:before,.fa-bandage:before{content:"\f462"}.fa-calendar-minus:before{content:"\f272"}.fa-circle-xmark:before,.fa-times-circle:before,.fa-xmark-circle:before{content:"\f057"}.fa-gifts:before{content:"\f79c"}.fa-hotel:before{content:"\f594"}.fa-earth-asia:before,.fa-globe-asia:before{content:"\f57e"}.fa-id-card-alt:before,.fa-id-card-clip:before{content:"\f47f"}.fa-magnifying-glass-plus:before,.fa-search-plus:before{content:"\f00e"}.fa-thumbs-up:before{content:"\f164"}.fa-user-clock:before{content:"\f4fd"}.fa-allergies:before,.fa-hand-dots:before{content:"\f461"}.fa-file-invoice:before{content:"\f570"}.fa-window-minimize:before{content:"\f2d1"}.fa-coffee:before,.fa-mug-saucer:before{content:"\f0f4"}.fa-brush:before{content:"\f55d"}.fa-mask:before{content:"\f6fa"}.fa-magnifying-glass-minus:before,.fa-search-minus:before{content:"\f010"}.fa-ruler-vertical:before{content:"\f548"}.fa-user-alt:before,.fa-user-large:before{content:"\f406"}.fa-train-tram:before{content:"\e5b4"}.fa-user-nurse:before{content:"\f82f"}.fa-syringe:before{content:"\f48e"}.fa-cloud-sun:before{content:"\f6c4"}.fa-stopwatch-20:before{content:"\e06f"}.fa-square-full:before{content:"\f45c"}.fa-magnet:before{content:"\f076"}.fa-jar:before{content:"\e516"}.fa-note-sticky:before,.fa-sticky-note:before{content:"\f249"}.fa-bug-slash:before{content:"\e490"}.fa-arrow-up-from-water-pump:before{content:"\e4b6"}.fa-bone:before{content:"\f5d7"}.fa-user-injured:before{content:"\f728"}.fa-face-sad-tear:before,.fa-sad-tear:before{content:"\f5b4"}.fa-plane:before{content:"\f072"}.fa-tent-arrows-down:before{content:"\e581"}.fa-exclamation:before{content:"\21"}.fa-arrows-spin:before{content:"\e4bb"}.fa-print:before{content:"\f02f"}.fa-try:before,.fa-turkish-lira-sign:before,.fa-turkish-lira:before{content:"\e2bb"}.fa-dollar-sign:before,.fa-dollar:before,.fa-usd:before{content:"\24"}.fa-x:before{content:"\58"}.fa-magnifying-glass-dollar:before,.fa-search-dollar:before{content:"\f688"}.fa-users-cog:before,.fa-users-gear:before{content:"\f509"}.fa-person-military-pointing:before{content:"\e54a"}.fa-bank:before,.fa-building-columns:before,.fa-institution:before,.fa-museum:before,.fa-university:before{content:"\f19c"}.fa-umbrella:before{content:"\f0e9"}.fa-trowel:before{content:"\e589"}.fa-d:before{content:"\44"}.fa-stapler:before{content:"\e5af"}.fa-masks-theater:before,.fa-theater-masks:before{content:"\f630"}.fa-kip-sign:before{content:"\e1c4"}.fa-hand-point-left:before{content:"\f0a5"}.fa-handshake-alt:before,.fa-handshake-simple:before{content:"\f4c6"}.fa-fighter-jet:before,.fa-jet-fighter:before{content:"\f0fb"}.fa-share-alt-square:before,.fa-square-share-nodes:before{content:"\f1e1"}.fa-barcode:before{content:"\f02a"}.fa-plus-minus:before{content:"\e43c"}.fa-video-camera:before,.fa-video:before{content:"\f03d"}.fa-graduation-cap:before,.fa-mortar-board:before{content:"\f19d"}.fa-hand-holding-medical:before{content:"\e05c"}.fa-person-circle-check:before{content:"\e53e"}.fa-level-up-alt:before,.fa-turn-up:before{content:"\f3bf"} +.fa-sr-only,.fa-sr-only-focusable:not(:focus),.sr-only,.sr-only-focusable:not(:focus){position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}:host,:root{--fa-style-family-brands:"Font Awesome 6 Brands";--fa-font-brands:normal 400 1em/1 "Font Awesome 6 Brands"}@font-face{font-family:"Font Awesome 6 Brands";font-style:normal;font-weight:400;font-display:block;src:url(../webfonts/fa-brands-400.woff2) format("woff2")}.fa-brands,.fab{font-weight:400}.fa-monero:before{content:"\f3d0"}.fa-hooli:before{content:"\f427"}.fa-yelp:before{content:"\f1e9"}.fa-cc-visa:before{content:"\f1f0"}.fa-lastfm:before{content:"\f202"}.fa-shopware:before{content:"\f5b5"}.fa-creative-commons-nc:before{content:"\f4e8"}.fa-aws:before{content:"\f375"}.fa-redhat:before{content:"\f7bc"}.fa-yoast:before{content:"\f2b1"}.fa-cloudflare:before{content:"\e07d"}.fa-ups:before{content:"\f7e0"}.fa-wpexplorer:before{content:"\f2de"}.fa-dyalog:before{content:"\f399"}.fa-bity:before{content:"\f37a"}.fa-stackpath:before{content:"\f842"}.fa-buysellads:before{content:"\f20d"}.fa-first-order:before{content:"\f2b0"}.fa-modx:before{content:"\f285"}.fa-guilded:before{content:"\e07e"}.fa-vnv:before{content:"\f40b"}.fa-js-square:before,.fa-square-js:before{content:"\f3b9"}.fa-microsoft:before{content:"\f3ca"}.fa-qq:before{content:"\f1d6"}.fa-orcid:before{content:"\f8d2"}.fa-java:before{content:"\f4e4"}.fa-invision:before{content:"\f7b0"}.fa-creative-commons-pd-alt:before{content:"\f4ed"}.fa-centercode:before{content:"\f380"}.fa-glide-g:before{content:"\f2a6"}.fa-drupal:before{content:"\f1a9"}.fa-hire-a-helper:before{content:"\f3b0"}.fa-creative-commons-by:before{content:"\f4e7"}.fa-unity:before{content:"\e049"}.fa-whmcs:before{content:"\f40d"}.fa-rocketchat:before{content:"\f3e8"}.fa-vk:before{content:"\f189"}.fa-untappd:before{content:"\f405"}.fa-mailchimp:before{content:"\f59e"}.fa-css3-alt:before{content:"\f38b"}.fa-reddit-square:before,.fa-square-reddit:before{content:"\f1a2"}.fa-vimeo-v:before{content:"\f27d"}.fa-contao:before{content:"\f26d"}.fa-square-font-awesome:before{content:"\e5ad"}.fa-deskpro:before{content:"\f38f"}.fa-sistrix:before{content:"\f3ee"}.fa-instagram-square:before,.fa-square-instagram:before{content:"\e055"}.fa-battle-net:before{content:"\f835"}.fa-the-red-yeti:before{content:"\f69d"}.fa-hacker-news-square:before,.fa-square-hacker-news:before{content:"\f3af"}.fa-edge:before{content:"\f282"}.fa-napster:before{content:"\f3d2"}.fa-snapchat-square:before,.fa-square-snapchat:before{content:"\f2ad"}.fa-google-plus-g:before{content:"\f0d5"}.fa-artstation:before{content:"\f77a"}.fa-markdown:before{content:"\f60f"}.fa-sourcetree:before{content:"\f7d3"}.fa-google-plus:before{content:"\f2b3"}.fa-diaspora:before{content:"\f791"}.fa-foursquare:before{content:"\f180"}.fa-stack-overflow:before{content:"\f16c"}.fa-github-alt:before{content:"\f113"}.fa-phoenix-squadron:before{content:"\f511"}.fa-pagelines:before{content:"\f18c"}.fa-algolia:before{content:"\f36c"}.fa-red-river:before{content:"\f3e3"}.fa-creative-commons-sa:before{content:"\f4ef"}.fa-safari:before{content:"\f267"}.fa-google:before{content:"\f1a0"}.fa-font-awesome-alt:before,.fa-square-font-awesome-stroke:before{content:"\f35c"}.fa-atlassian:before{content:"\f77b"}.fa-linkedin-in:before{content:"\f0e1"}.fa-digital-ocean:before{content:"\f391"}.fa-nimblr:before{content:"\f5a8"}.fa-chromecast:before{content:"\f838"}.fa-evernote:before{content:"\f839"}.fa-hacker-news:before{content:"\f1d4"}.fa-creative-commons-sampling:before{content:"\f4f0"}.fa-adversal:before{content:"\f36a"}.fa-creative-commons:before{content:"\f25e"}.fa-watchman-monitoring:before{content:"\e087"}.fa-fonticons:before{content:"\f280"}.fa-weixin:before{content:"\f1d7"}.fa-shirtsinbulk:before{content:"\f214"}.fa-codepen:before{content:"\f1cb"}.fa-git-alt:before{content:"\f841"}.fa-lyft:before{content:"\f3c3"}.fa-rev:before{content:"\f5b2"}.fa-windows:before{content:"\f17a"}.fa-wizards-of-the-coast:before{content:"\f730"}.fa-square-viadeo:before,.fa-viadeo-square:before{content:"\f2aa"}.fa-meetup:before{content:"\f2e0"}.fa-centos:before{content:"\f789"}.fa-adn:before{content:"\f170"}.fa-cloudsmith:before{content:"\f384"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-dribbble-square:before,.fa-square-dribbble:before{content:"\f397"}.fa-codiepie:before{content:"\f284"}.fa-node:before{content:"\f419"}.fa-mix:before{content:"\f3cb"}.fa-steam:before{content:"\f1b6"}.fa-cc-apple-pay:before{content:"\f416"}.fa-scribd:before{content:"\f28a"}.fa-openid:before{content:"\f19b"}.fa-instalod:before{content:"\e081"}.fa-expeditedssl:before{content:"\f23e"}.fa-sellcast:before{content:"\f2da"}.fa-square-twitter:before,.fa-twitter-square:before{content:"\f081"}.fa-r-project:before{content:"\f4f7"}.fa-delicious:before{content:"\f1a5"}.fa-freebsd:before{content:"\f3a4"}.fa-vuejs:before{content:"\f41f"}.fa-accusoft:before{content:"\f369"}.fa-ioxhost:before{content:"\f208"}.fa-fonticons-fi:before{content:"\f3a2"}.fa-app-store:before{content:"\f36f"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-itunes-note:before{content:"\f3b5"}.fa-golang:before{content:"\e40f"}.fa-kickstarter:before{content:"\f3bb"}.fa-grav:before{content:"\f2d6"}.fa-weibo:before{content:"\f18a"}.fa-uncharted:before{content:"\e084"}.fa-firstdraft:before{content:"\f3a1"}.fa-square-youtube:before,.fa-youtube-square:before{content:"\f431"}.fa-wikipedia-w:before{content:"\f266"}.fa-rendact:before,.fa-wpressr:before{content:"\f3e4"}.fa-angellist:before{content:"\f209"}.fa-galactic-republic:before{content:"\f50c"}.fa-nfc-directional:before{content:"\e530"}.fa-skype:before{content:"\f17e"}.fa-joget:before{content:"\f3b7"}.fa-fedora:before{content:"\f798"}.fa-stripe-s:before{content:"\f42a"}.fa-meta:before{content:"\e49b"}.fa-laravel:before{content:"\f3bd"}.fa-hotjar:before{content:"\f3b1"}.fa-bluetooth-b:before{content:"\f294"}.fa-sticker-mule:before{content:"\f3f7"}.fa-creative-commons-zero:before{content:"\f4f3"}.fa-hips:before{content:"\f452"}.fa-behance:before{content:"\f1b4"}.fa-reddit:before{content:"\f1a1"}.fa-discord:before{content:"\f392"}.fa-chrome:before{content:"\f268"}.fa-app-store-ios:before{content:"\f370"}.fa-cc-discover:before{content:"\f1f2"}.fa-wpbeginner:before{content:"\f297"}.fa-confluence:before{content:"\f78d"}.fa-mdb:before{content:"\f8ca"}.fa-dochub:before{content:"\f394"}.fa-accessible-icon:before{content:"\f368"}.fa-ebay:before{content:"\f4f4"}.fa-amazon:before{content:"\f270"}.fa-unsplash:before{content:"\e07c"}.fa-yarn:before{content:"\f7e3"}.fa-square-steam:before,.fa-steam-square:before{content:"\f1b7"}.fa-500px:before{content:"\f26e"}.fa-square-vimeo:before,.fa-vimeo-square:before{content:"\f194"}.fa-asymmetrik:before{content:"\f372"}.fa-font-awesome-flag:before,.fa-font-awesome-logo-full:before,.fa-font-awesome:before{content:"\f2b4"}.fa-gratipay:before{content:"\f184"}.fa-apple:before{content:"\f179"}.fa-hive:before{content:"\e07f"}.fa-gitkraken:before{content:"\f3a6"}.fa-keybase:before{content:"\f4f5"}.fa-apple-pay:before{content:"\f415"}.fa-padlet:before{content:"\e4a0"}.fa-amazon-pay:before{content:"\f42c"}.fa-github-square:before,.fa-square-github:before{content:"\f092"}.fa-stumbleupon:before{content:"\f1a4"}.fa-fedex:before{content:"\f797"}.fa-phoenix-framework:before{content:"\f3dc"}.fa-shopify:before{content:"\e057"}.fa-neos:before{content:"\f612"}.fa-hackerrank:before{content:"\f5f7"}.fa-researchgate:before{content:"\f4f8"}.fa-swift:before{content:"\f8e1"}.fa-angular:before{content:"\f420"}.fa-speakap:before{content:"\f3f3"}.fa-angrycreative:before{content:"\f36e"}.fa-y-combinator:before{content:"\f23b"}.fa-empire:before{content:"\f1d1"}.fa-envira:before{content:"\f299"}.fa-gitlab-square:before,.fa-square-gitlab:before{content:"\e5ae"}.fa-studiovinari:before{content:"\f3f8"}.fa-pied-piper:before{content:"\f2ae"}.fa-wordpress:before{content:"\f19a"}.fa-product-hunt:before{content:"\f288"}.fa-firefox:before{content:"\f269"}.fa-linode:before{content:"\f2b8"}.fa-goodreads:before{content:"\f3a8"}.fa-odnoklassniki-square:before,.fa-square-odnoklassniki:before{content:"\f264"}.fa-jsfiddle:before{content:"\f1cc"}.fa-sith:before{content:"\f512"}.fa-themeisle:before{content:"\f2b2"}.fa-page4:before{content:"\f3d7"}.fa-hashnode:before{content:"\e499"}.fa-react:before{content:"\f41b"}.fa-cc-paypal:before{content:"\f1f4"}.fa-squarespace:before{content:"\f5be"}.fa-cc-stripe:before{content:"\f1f5"}.fa-creative-commons-share:before{content:"\f4f2"}.fa-bitcoin:before{content:"\f379"}.fa-keycdn:before{content:"\f3ba"}.fa-opera:before{content:"\f26a"}.fa-itch-io:before{content:"\f83a"}.fa-umbraco:before{content:"\f8e8"}.fa-galactic-senate:before{content:"\f50d"}.fa-ubuntu:before{content:"\f7df"}.fa-draft2digital:before{content:"\f396"}.fa-stripe:before{content:"\f429"}.fa-houzz:before{content:"\f27c"}.fa-gg:before{content:"\f260"}.fa-dhl:before{content:"\f790"}.fa-pinterest-square:before,.fa-square-pinterest:before{content:"\f0d3"}.fa-xing:before{content:"\f168"}.fa-blackberry:before{content:"\f37b"}.fa-creative-commons-pd:before{content:"\f4ec"}.fa-playstation:before{content:"\f3df"}.fa-quinscape:before{content:"\f459"}.fa-less:before{content:"\f41d"}.fa-blogger-b:before{content:"\f37d"}.fa-opencart:before{content:"\f23d"}.fa-vine:before{content:"\f1ca"}.fa-paypal:before{content:"\f1ed"}.fa-gitlab:before{content:"\f296"}.fa-typo3:before{content:"\f42b"}.fa-reddit-alien:before{content:"\f281"}.fa-yahoo:before{content:"\f19e"}.fa-dailymotion:before{content:"\e052"}.fa-affiliatetheme:before{content:"\f36b"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-bootstrap:before{content:"\f836"}.fa-odnoklassniki:before{content:"\f263"}.fa-nfc-symbol:before{content:"\e531"}.fa-ethereum:before{content:"\f42e"}.fa-speaker-deck:before{content:"\f83c"}.fa-creative-commons-nc-eu:before{content:"\f4e9"}.fa-patreon:before{content:"\f3d9"}.fa-avianex:before{content:"\f374"}.fa-ello:before{content:"\f5f1"}.fa-gofore:before{content:"\f3a7"}.fa-bimobject:before{content:"\f378"}.fa-facebook-f:before{content:"\f39e"}.fa-google-plus-square:before,.fa-square-google-plus:before{content:"\f0d4"}.fa-mandalorian:before{content:"\f50f"}.fa-first-order-alt:before{content:"\f50a"}.fa-osi:before{content:"\f41a"}.fa-google-wallet:before{content:"\f1ee"}.fa-d-and-d-beyond:before{content:"\f6ca"}.fa-periscope:before{content:"\f3da"}.fa-fulcrum:before{content:"\f50b"}.fa-cloudscale:before{content:"\f383"}.fa-forumbee:before{content:"\f211"}.fa-mizuni:before{content:"\f3cc"}.fa-schlix:before{content:"\f3ea"}.fa-square-xing:before,.fa-xing-square:before{content:"\f169"}.fa-bandcamp:before{content:"\f2d5"}.fa-wpforms:before{content:"\f298"}.fa-cloudversify:before{content:"\f385"}.fa-usps:before{content:"\f7e1"}.fa-megaport:before{content:"\f5a3"}.fa-magento:before{content:"\f3c4"}.fa-spotify:before{content:"\f1bc"}.fa-optin-monster:before{content:"\f23c"}.fa-fly:before{content:"\f417"}.fa-aviato:before{content:"\f421"}.fa-itunes:before{content:"\f3b4"}.fa-cuttlefish:before{content:"\f38c"}.fa-blogger:before{content:"\f37c"}.fa-flickr:before{content:"\f16e"}.fa-viber:before{content:"\f409"}.fa-soundcloud:before{content:"\f1be"}.fa-digg:before{content:"\f1a6"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-symfony:before{content:"\f83d"}.fa-maxcdn:before{content:"\f136"}.fa-etsy:before{content:"\f2d7"}.fa-facebook-messenger:before{content:"\f39f"}.fa-audible:before{content:"\f373"}.fa-think-peaks:before{content:"\f731"}.fa-bilibili:before{content:"\e3d9"}.fa-erlang:before{content:"\f39d"}.fa-cotton-bureau:before{content:"\f89e"}.fa-dashcube:before{content:"\f210"}.fa-42-group:before,.fa-innosoft:before{content:"\e080"}.fa-stack-exchange:before{content:"\f18d"}.fa-elementor:before{content:"\f430"}.fa-pied-piper-square:before,.fa-square-pied-piper:before{content:"\e01e"}.fa-creative-commons-nd:before{content:"\f4eb"}.fa-palfed:before{content:"\f3d8"}.fa-superpowers:before{content:"\f2dd"}.fa-resolving:before{content:"\f3e7"}.fa-xbox:before{content:"\f412"}.fa-searchengin:before{content:"\f3eb"}.fa-tiktok:before{content:"\e07b"}.fa-facebook-square:before,.fa-square-facebook:before{content:"\f082"}.fa-renren:before{content:"\f18b"}.fa-linux:before{content:"\f17c"}.fa-glide:before{content:"\f2a5"}.fa-linkedin:before{content:"\f08c"}.fa-hubspot:before{content:"\f3b2"}.fa-deploydog:before{content:"\f38e"}.fa-twitch:before{content:"\f1e8"}.fa-ravelry:before{content:"\f2d9"}.fa-mixer:before{content:"\e056"}.fa-lastfm-square:before,.fa-square-lastfm:before{content:"\f203"}.fa-vimeo:before{content:"\f40a"}.fa-mendeley:before{content:"\f7b3"}.fa-uniregistry:before{content:"\f404"}.fa-figma:before{content:"\f799"}.fa-creative-commons-remix:before{content:"\f4ee"}.fa-cc-amazon-pay:before{content:"\f42d"}.fa-dropbox:before{content:"\f16b"}.fa-instagram:before{content:"\f16d"}.fa-cmplid:before{content:"\e360"}.fa-facebook:before{content:"\f09a"}.fa-gripfire:before{content:"\f3ac"}.fa-jedi-order:before{content:"\f50e"}.fa-uikit:before{content:"\f403"}.fa-fort-awesome-alt:before{content:"\f3a3"}.fa-phabricator:before{content:"\f3db"}.fa-ussunnah:before{content:"\f407"}.fa-earlybirds:before{content:"\f39a"}.fa-trade-federation:before{content:"\f513"}.fa-autoprefixer:before{content:"\f41c"}.fa-whatsapp:before{content:"\f232"}.fa-slideshare:before{content:"\f1e7"}.fa-google-play:before{content:"\f3ab"}.fa-viadeo:before{content:"\f2a9"}.fa-line:before{content:"\f3c0"}.fa-google-drive:before{content:"\f3aa"}.fa-servicestack:before{content:"\f3ec"}.fa-simplybuilt:before{content:"\f215"}.fa-bitbucket:before{content:"\f171"}.fa-imdb:before{content:"\f2d8"}.fa-deezer:before{content:"\e077"}.fa-raspberry-pi:before{content:"\f7bb"}.fa-jira:before{content:"\f7b1"}.fa-docker:before{content:"\f395"}.fa-screenpal:before{content:"\e570"}.fa-bluetooth:before{content:"\f293"}.fa-gitter:before{content:"\f426"}.fa-d-and-d:before{content:"\f38d"}.fa-microblog:before{content:"\e01a"}.fa-cc-diners-club:before{content:"\f24c"}.fa-gg-circle:before{content:"\f261"}.fa-pied-piper-hat:before{content:"\f4e5"}.fa-kickstarter-k:before{content:"\f3bc"}.fa-yandex:before{content:"\f413"}.fa-readme:before{content:"\f4d5"}.fa-html5:before{content:"\f13b"}.fa-sellsy:before{content:"\f213"}.fa-sass:before{content:"\f41e"}.fa-wirsindhandwerk:before,.fa-wsh:before{content:"\e2d0"}.fa-buromobelexperte:before{content:"\f37f"}.fa-salesforce:before{content:"\f83b"}.fa-octopus-deploy:before{content:"\e082"}.fa-medapps:before{content:"\f3c6"}.fa-ns8:before{content:"\f3d5"}.fa-pinterest-p:before{content:"\f231"}.fa-apper:before{content:"\f371"}.fa-fort-awesome:before{content:"\f286"}.fa-waze:before{content:"\f83f"}.fa-cc-jcb:before{content:"\f24b"}.fa-snapchat-ghost:before,.fa-snapchat:before{content:"\f2ab"}.fa-fantasy-flight-games:before{content:"\f6dc"}.fa-rust:before{content:"\e07a"}.fa-wix:before{content:"\f5cf"}.fa-behance-square:before,.fa-square-behance:before{content:"\f1b5"}.fa-supple:before{content:"\f3f9"}.fa-rebel:before{content:"\f1d0"}.fa-css3:before{content:"\f13c"}.fa-staylinked:before{content:"\f3f5"}.fa-kaggle:before{content:"\f5fa"}.fa-space-awesome:before{content:"\e5ac"}.fa-deviantart:before{content:"\f1bd"}.fa-cpanel:before{content:"\f388"}.fa-goodreads-g:before{content:"\f3a9"}.fa-git-square:before,.fa-square-git:before{content:"\f1d2"}.fa-square-tumblr:before,.fa-tumblr-square:before{content:"\f174"}.fa-trello:before{content:"\f181"}.fa-creative-commons-nc-jp:before{content:"\f4ea"}.fa-get-pocket:before{content:"\f265"}.fa-perbyte:before{content:"\e083"}.fa-grunt:before{content:"\f3ad"}.fa-weebly:before{content:"\f5cc"}.fa-connectdevelop:before{content:"\f20e"}.fa-leanpub:before{content:"\f212"}.fa-black-tie:before{content:"\f27e"}.fa-themeco:before{content:"\f5c6"}.fa-python:before{content:"\f3e2"}.fa-android:before{content:"\f17b"}.fa-bots:before{content:"\e340"}.fa-free-code-camp:before{content:"\f2c5"}.fa-hornbill:before{content:"\f592"}.fa-js:before{content:"\f3b8"}.fa-ideal:before{content:"\e013"}.fa-git:before{content:"\f1d3"}.fa-dev:before{content:"\f6cc"}.fa-sketch:before{content:"\f7c6"}.fa-yandex-international:before{content:"\f414"}.fa-cc-amex:before{content:"\f1f3"}.fa-uber:before{content:"\f402"}.fa-github:before{content:"\f09b"}.fa-php:before{content:"\f457"}.fa-alipay:before{content:"\f642"}.fa-youtube:before{content:"\f167"}.fa-skyatlas:before{content:"\f216"}.fa-firefox-browser:before{content:"\e007"}.fa-replyd:before{content:"\f3e6"}.fa-suse:before{content:"\f7d6"}.fa-jenkins:before{content:"\f3b6"}.fa-twitter:before{content:"\f099"}.fa-rockrms:before{content:"\f3e9"}.fa-pinterest:before{content:"\f0d2"}.fa-buffer:before{content:"\f837"}.fa-npm:before{content:"\f3d4"}.fa-yammer:before{content:"\f840"}.fa-btc:before{content:"\f15a"}.fa-dribbble:before{content:"\f17d"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-internet-explorer:before{content:"\f26b"}.fa-stubber:before{content:"\e5c7"}.fa-telegram-plane:before,.fa-telegram:before{content:"\f2c6"}.fa-old-republic:before{content:"\f510"}.fa-odysee:before{content:"\e5c6"}.fa-square-whatsapp:before,.fa-whatsapp-square:before{content:"\f40c"}.fa-node-js:before{content:"\f3d3"}.fa-edge-legacy:before{content:"\e078"}.fa-slack-hash:before,.fa-slack:before{content:"\f198"}.fa-medrt:before{content:"\f3c8"}.fa-usb:before{content:"\f287"}.fa-tumblr:before{content:"\f173"}.fa-vaadin:before{content:"\f408"}.fa-quora:before{content:"\f2c4"}.fa-reacteurope:before{content:"\f75d"}.fa-medium-m:before,.fa-medium:before{content:"\f23a"}.fa-amilia:before{content:"\f36d"}.fa-mixcloud:before{content:"\f289"}.fa-flipboard:before{content:"\f44d"}.fa-viacoin:before{content:"\f237"}.fa-critical-role:before{content:"\f6c9"}.fa-sitrox:before{content:"\e44a"}.fa-discourse:before{content:"\f393"}.fa-joomla:before{content:"\f1aa"}.fa-mastodon:before{content:"\f4f6"}.fa-airbnb:before{content:"\f834"}.fa-wolf-pack-battalion:before{content:"\f514"}.fa-buy-n-large:before{content:"\f8a6"}.fa-gulp:before{content:"\f3ae"}.fa-creative-commons-sampling-plus:before{content:"\f4f1"}.fa-strava:before{content:"\f428"}.fa-ember:before{content:"\f423"}.fa-canadian-maple-leaf:before{content:"\f785"}.fa-teamspeak:before{content:"\f4f9"}.fa-pushed:before{content:"\f3e1"}.fa-wordpress-simple:before{content:"\f411"}.fa-nutritionix:before{content:"\f3d6"}.fa-wodu:before{content:"\e088"}.fa-google-pay:before{content:"\e079"}.fa-intercom:before{content:"\f7af"}.fa-zhihu:before{content:"\f63f"}.fa-korvue:before{content:"\f42f"}.fa-pix:before{content:"\e43a"}.fa-steam-symbol:before{content:"\f3f6"}:host,:root{--fa-font-regular:normal 400 1em/1 "Font Awesome 6 Free"}@font-face{font-family:"Font Awesome 6 Free";font-style:normal;font-weight:400;font-display:block;src:url(../webfonts/fa-regular-400.woff2) format("woff2")}.fa-regular,.far{font-weight:400}:host,:root{--fa-style-family-classic:"Font Awesome 6 Free";--fa-font-solid:normal 900 1em/1 "Font Awesome 6 Free"}@font-face{font-family:"Font Awesome 6 Free";font-style:normal;font-weight:900;font-display:block;src:url(../webfonts/fa-solid-900.woff2) format("woff2")}.fa-solid,.fas{font-weight:900}@font-face{font-family:"Font Awesome 5 Brands";font-display:block;font-weight:400;src:url(../webfonts/fa-brands-400.woff2) format("woff2")}@font-face{font-family:"Font Awesome 5 Free";font-display:block;font-weight:900;src:url(../webfonts/fa-solid-900.woff2) format("woff2")}@font-face{font-family:"Font Awesome 5 Free";font-display:block;font-weight:400;src:url(../webfonts/fa-regular-400.woff2) format("woff2")}@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-solid-900.woff2) format("woff2")}@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-brands-400.woff2) format("woff2")}@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-regular-400.woff2) format("woff2");unicode-range:u+f003,u+f006,u+f014,u+f016-f017,u+f01a-f01b,u+f01d,u+f022,u+f03e,u+f044,u+f046,u+f05c-f05d,u+f06e,u+f070,u+f087-f088,u+f08a,u+f094,u+f096-f097,u+f09d,u+f0a0,u+f0a2,u+f0a4-f0a7,u+f0c5,u+f0c7,u+f0e5-f0e6,u+f0eb,u+f0f6-f0f8,u+f10c,u+f114-f115,u+f118-f11a,u+f11c-f11d,u+f133,u+f147,u+f14e,u+f150-f152,u+f185-f186,u+f18e,u+f190-f192,u+f196,u+f1c1-f1c9,u+f1d9,u+f1db,u+f1e3,u+f1ea,u+f1f7,u+f1f9,u+f20a,u+f247-f248,u+f24a,u+f24d,u+f255-f25b,u+f25d,u+f271-f274,u+f278,u+f27b,u+f28c,u+f28e,u+f29c,u+f2b5,u+f2b7,u+f2ba,u+f2bc,u+f2be,u+f2c0-f2c1,u+f2c3,u+f2d0,u+f2d2,u+f2d4,u+f2dc}@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-v4compatibility.woff2) format("woff2");unicode-range:u+f041,u+f047,u+f065-f066,u+f07d-f07e,u+f080,u+f08b,u+f08e,u+f090,u+f09a,u+f0ac,u+f0ae,u+f0b2,u+f0d0,u+f0d6,u+f0e4,u+f0ec,u+f10a-f10b,u+f123,u+f13e,u+f148-f149,u+f14c,u+f156,u+f15e,u+f160-f161,u+f163,u+f175-f178,u+f195,u+f1f8,u+f219,u+f27a} \ No newline at end of file diff --git a/main/assets/vendor/fontawesome/webfonts/fa-brands-400.woff2 b/main/assets/vendor/fontawesome/webfonts/fa-brands-400.woff2 new file mode 100644 index 0000000..71e3185 Binary files /dev/null and b/main/assets/vendor/fontawesome/webfonts/fa-brands-400.woff2 differ diff --git a/main/assets/vendor/fontawesome/webfonts/fa-regular-400.woff2 b/main/assets/vendor/fontawesome/webfonts/fa-regular-400.woff2 new file mode 100644 index 0000000..7f02168 Binary files /dev/null and b/main/assets/vendor/fontawesome/webfonts/fa-regular-400.woff2 differ diff --git a/main/assets/vendor/fontawesome/webfonts/fa-solid-900.woff2 b/main/assets/vendor/fontawesome/webfonts/fa-solid-900.woff2 new file mode 100644 index 0000000..5c16cd3 Binary files /dev/null and b/main/assets/vendor/fontawesome/webfonts/fa-solid-900.woff2 differ diff --git a/main/assets/vendor/fontawesome/webfonts/fa-v4compatibility.woff2 b/main/assets/vendor/fontawesome/webfonts/fa-v4compatibility.woff2 new file mode 100644 index 0000000..9027e38 Binary files /dev/null and b/main/assets/vendor/fontawesome/webfonts/fa-v4compatibility.woff2 differ diff --git a/main/assets/vendor/fonts/LICENSE-jetbrains-mono.txt b/main/assets/vendor/fonts/LICENSE-jetbrains-mono.txt new file mode 100644 index 0000000..8f7ed67 --- /dev/null +++ b/main/assets/vendor/fonts/LICENSE-jetbrains-mono.txt @@ -0,0 +1,93 @@ +Copyright 2020 The JetBrains Mono Project Authors (https://github.com/JetBrains/JetBrainsMono) JetBrainsMono-Italic[wght].ttf: Copyright 2020 The JetBrains Mono Project Authors (https://github.com/JetBrains/JetBrainsMono) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/main/assets/vendor/fonts/LICENSE-roboto-flex.txt b/main/assets/vendor/fonts/LICENSE-roboto-flex.txt new file mode 100644 index 0000000..2750ff6 --- /dev/null +++ b/main/assets/vendor/fonts/LICENSE-roboto-flex.txt @@ -0,0 +1,93 @@ +Copyright 2017 The Roboto Flex Project Authors (https://github.com/googlefonts/roboto-flex) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/main/assets/vendor/fonts/jetbrains-mono-latin-wght-normal.woff2 b/main/assets/vendor/fonts/jetbrains-mono-latin-wght-normal.woff2 new file mode 100644 index 0000000..cd5102a Binary files /dev/null and b/main/assets/vendor/fonts/jetbrains-mono-latin-wght-normal.woff2 differ diff --git a/main/assets/vendor/fonts/roboto-flex-latin-wght-normal.woff2 b/main/assets/vendor/fonts/roboto-flex-latin-wght-normal.woff2 new file mode 100644 index 0000000..88bbf49 Binary files /dev/null and b/main/assets/vendor/fonts/roboto-flex-latin-wght-normal.woff2 differ diff --git a/main/assets/vendor/papaparse/LICENSE b/main/assets/vendor/papaparse/LICENSE new file mode 100644 index 0000000..12f5b35 --- /dev/null +++ b/main/assets/vendor/papaparse/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2015 Matthew Holt + +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/main/assets/vendor/papaparse/papaparse.min.js b/main/assets/vendor/papaparse/papaparse.min.js new file mode 100644 index 0000000..edfdb37 --- /dev/null +++ b/main/assets/vendor/papaparse/papaparse.min.js @@ -0,0 +1,7 @@ +/* @license +Papa Parse +v5.3.2 +https://github.com/mholt/PapaParse +License: MIT +*/ +!function(e,t){"function"==typeof define&&define.amd?define([],t):"object"==typeof module&&"undefined"!=typeof exports?module.exports=t():e.Papa=t()}(this,function s(){"use strict";var f="undefined"!=typeof self?self:"undefined"!=typeof window?window:void 0!==f?f:{};var n=!f.document&&!!f.postMessage,o=n&&/blob:/i.test((f.location||{}).protocol),a={},h=0,b={parse:function(e,t){var i=(t=t||{}).dynamicTyping||!1;M(i)&&(t.dynamicTypingFunction=i,i={});if(t.dynamicTyping=i,t.transform=!!M(t.transform)&&t.transform,t.worker&&b.WORKERS_SUPPORTED){var r=function(){if(!b.WORKERS_SUPPORTED)return!1;var e=(i=f.URL||f.webkitURL||null,r=s.toString(),b.BLOB_URL||(b.BLOB_URL=i.createObjectURL(new Blob(["(",r,")();"],{type:"text/javascript"})))),t=new f.Worker(e);var i,r;return t.onmessage=_,t.id=h++,a[t.id]=t}();return r.userStep=t.step,r.userChunk=t.chunk,r.userComplete=t.complete,r.userError=t.error,t.step=M(t.step),t.chunk=M(t.chunk),t.complete=M(t.complete),t.error=M(t.error),delete t.worker,void r.postMessage({input:e,config:t,workerId:r.id})}var n=null;b.NODE_STREAM_INPUT,"string"==typeof e?n=t.download?new l(t):new p(t):!0===e.readable&&M(e.read)&&M(e.on)?n=new g(t):(f.File&&e instanceof File||e instanceof Object)&&(n=new c(t));return n.stream(e)},unparse:function(e,t){var n=!1,_=!0,m=",",y="\r\n",s='"',a=s+s,i=!1,r=null,o=!1;!function(){if("object"!=typeof t)return;"string"!=typeof t.delimiter||b.BAD_DELIMITERS.filter(function(e){return-1!==t.delimiter.indexOf(e)}).length||(m=t.delimiter);("boolean"==typeof t.quotes||"function"==typeof t.quotes||Array.isArray(t.quotes))&&(n=t.quotes);"boolean"!=typeof t.skipEmptyLines&&"string"!=typeof t.skipEmptyLines||(i=t.skipEmptyLines);"string"==typeof t.newline&&(y=t.newline);"string"==typeof t.quoteChar&&(s=t.quoteChar);"boolean"==typeof t.header&&(_=t.header);if(Array.isArray(t.columns)){if(0===t.columns.length)throw new Error("Option columns is empty");r=t.columns}void 0!==t.escapeChar&&(a=t.escapeChar+s);("boolean"==typeof t.escapeFormulae||t.escapeFormulae instanceof RegExp)&&(o=t.escapeFormulae instanceof RegExp?t.escapeFormulae:/^[=+\-@\t\r].*$/)}();var h=new RegExp(j(s),"g");"string"==typeof e&&(e=JSON.parse(e));if(Array.isArray(e)){if(!e.length||Array.isArray(e[0]))return u(null,e,i);if("object"==typeof e[0])return u(r||Object.keys(e[0]),e,i)}else if("object"==typeof e)return"string"==typeof e.data&&(e.data=JSON.parse(e.data)),Array.isArray(e.data)&&(e.fields||(e.fields=e.meta&&e.meta.fields||r),e.fields||(e.fields=Array.isArray(e.data[0])?e.fields:"object"==typeof e.data[0]?Object.keys(e.data[0]):[]),Array.isArray(e.data[0])||"object"==typeof e.data[0]||(e.data=[e.data])),u(e.fields||[],e.data||[],i);throw new Error("Unable to serialize unrecognized input");function u(e,t,i){var r="";"string"==typeof e&&(e=JSON.parse(e)),"string"==typeof t&&(t=JSON.parse(t));var n=Array.isArray(e)&&0=this._config.preview;if(o)f.postMessage({results:n,workerId:b.WORKER_ID,finished:a});else if(M(this._config.chunk)&&!t){if(this._config.chunk(n,this._handle),this._handle.paused()||this._handle.aborted())return void(this._halted=!0);n=void 0,this._completeResults=void 0}return this._config.step||this._config.chunk||(this._completeResults.data=this._completeResults.data.concat(n.data),this._completeResults.errors=this._completeResults.errors.concat(n.errors),this._completeResults.meta=n.meta),this._completed||!a||!M(this._config.complete)||n&&n.meta.aborted||(this._config.complete(this._completeResults,this._input),this._completed=!0),a||n&&n.meta.paused||this._nextChunk(),n}this._halted=!0},this._sendError=function(e){M(this._config.error)?this._config.error(e):o&&this._config.error&&f.postMessage({workerId:b.WORKER_ID,error:e,finished:!1})}}function l(e){var r;(e=e||{}).chunkSize||(e.chunkSize=b.RemoteChunkSize),u.call(this,e),this._nextChunk=n?function(){this._readChunk(),this._chunkLoaded()}:function(){this._readChunk()},this.stream=function(e){this._input=e,this._nextChunk()},this._readChunk=function(){if(this._finished)this._chunkLoaded();else{if(r=new XMLHttpRequest,this._config.withCredentials&&(r.withCredentials=this._config.withCredentials),n||(r.onload=v(this._chunkLoaded,this),r.onerror=v(this._chunkError,this)),r.open(this._config.downloadRequestBody?"POST":"GET",this._input,!n),this._config.downloadRequestHeaders){var e=this._config.downloadRequestHeaders;for(var t in e)r.setRequestHeader(t,e[t])}if(this._config.chunkSize){var i=this._start+this._config.chunkSize-1;r.setRequestHeader("Range","bytes="+this._start+"-"+i)}try{r.send(this._config.downloadRequestBody)}catch(e){this._chunkError(e.message)}n&&0===r.status&&this._chunkError()}},this._chunkLoaded=function(){4===r.readyState&&(r.status<200||400<=r.status?this._chunkError():(this._start+=this._config.chunkSize?this._config.chunkSize:r.responseText.length,this._finished=!this._config.chunkSize||this._start>=function(e){var t=e.getResponseHeader("Content-Range");if(null===t)return-1;return parseInt(t.substring(t.lastIndexOf("/")+1))}(r),this.parseChunk(r.responseText)))},this._chunkError=function(e){var t=r.statusText||e;this._sendError(new Error(t))}}function c(e){var r,n;(e=e||{}).chunkSize||(e.chunkSize=b.LocalChunkSize),u.call(this,e);var s="undefined"!=typeof FileReader;this.stream=function(e){this._input=e,n=e.slice||e.webkitSlice||e.mozSlice,s?((r=new FileReader).onload=v(this._chunkLoaded,this),r.onerror=v(this._chunkError,this)):r=new FileReaderSync,this._nextChunk()},this._nextChunk=function(){this._finished||this._config.preview&&!(this._rowCount=this._input.size,this.parseChunk(e.target.result)},this._chunkError=function(){this._sendError(r.error)}}function p(e){var i;u.call(this,e=e||{}),this.stream=function(e){return i=e,this._nextChunk()},this._nextChunk=function(){if(!this._finished){var e,t=this._config.chunkSize;return t?(e=i.substring(0,t),i=i.substring(t)):(e=i,i=""),this._finished=!i,this.parseChunk(e)}}}function g(e){u.call(this,e=e||{});var t=[],i=!0,r=!1;this.pause=function(){u.prototype.pause.apply(this,arguments),this._input.pause()},this.resume=function(){u.prototype.resume.apply(this,arguments),this._input.resume()},this.stream=function(e){this._input=e,this._input.on("data",this._streamData),this._input.on("end",this._streamEnd),this._input.on("error",this._streamError)},this._checkIsFinished=function(){r&&1===t.length&&(this._finished=!0)},this._nextChunk=function(){this._checkIsFinished(),t.length?this.parseChunk(t.shift()):i=!0},this._streamData=v(function(e){try{t.push("string"==typeof e?e:e.toString(this._config.encoding)),i&&(i=!1,this._checkIsFinished(),this.parseChunk(t.shift()))}catch(e){this._streamError(e)}},this),this._streamError=v(function(e){this._streamCleanUp(),this._sendError(e)},this),this._streamEnd=v(function(){this._streamCleanUp(),r=!0,this._streamData("")},this),this._streamCleanUp=v(function(){this._input.removeListener("data",this._streamData),this._input.removeListener("end",this._streamEnd),this._input.removeListener("error",this._streamError)},this)}function i(m){var a,o,h,r=Math.pow(2,53),n=-r,s=/^\s*-?(\d+\.?|\.\d+|\d+\.\d+)([eE][-+]?\d+)?\s*$/,u=/^(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))$/,t=this,i=0,f=0,d=!1,e=!1,l=[],c={data:[],errors:[],meta:{}};if(M(m.step)){var p=m.step;m.step=function(e){if(c=e,_())g();else{if(g(),0===c.data.length)return;i+=e.data.length,m.preview&&i>m.preview?o.abort():(c.data=c.data[0],p(c,t))}}}function y(e){return"greedy"===m.skipEmptyLines?""===e.join("").trim():1===e.length&&0===e[0].length}function g(){return c&&h&&(k("Delimiter","UndetectableDelimiter","Unable to auto-detect delimiting character; defaulted to '"+b.DefaultDelimiter+"'"),h=!1),m.skipEmptyLines&&(c.data=c.data.filter(function(e){return!y(e)})),_()&&function(){if(!c)return;function e(e,t){M(m.transformHeader)&&(e=m.transformHeader(e,t)),l.push(e)}if(Array.isArray(c.data[0])){for(var t=0;_()&&t=l.length?"__parsed_extra":l[i]),m.transform&&(s=m.transform(s,n)),s=v(n,s),"__parsed_extra"===n?(r[n]=r[n]||[],r[n].push(s)):r[n]=s}return m.header&&(i>l.length?k("FieldMismatch","TooManyFields","Too many fields: expected "+l.length+" fields but parsed "+i,f+t):i=r.length/2?"\r\n":"\r"}(e,r)),h=!1,m.delimiter)M(m.delimiter)&&(m.delimiter=m.delimiter(e),c.meta.delimiter=m.delimiter);else{var n=function(e,t,i,r,n){var s,a,o,h;n=n||[",","\t","|",";",b.RECORD_SEP,b.UNIT_SEP];for(var u=0;u=D)return C(!0)}else for(m=F,F++;;){if(-1===(m=r.indexOf(S,m+1)))return i||u.push({type:"Quotes",code:"MissingQuotes",message:"Quoted field unterminated",row:h.length,index:F}),E();if(m===n-1)return E(r.substring(F,m).replace(_,S));if(S!==L||r[m+1]!==L){if(S===L||0===m||r[m-1]!==L){-1!==p&&p=D)return C(!0);break}u.push({type:"Quotes",code:"InvalidQuotes",message:"Trailing quote on quoted field is malformed",row:h.length,index:F}),m++}}else m++}return E();function k(e){h.push(e),d=F}function b(e){var t=0;if(-1!==e){var i=r.substring(m+1,e);i&&""===i.trim()&&(t=i.length)}return t}function E(e){return i||(void 0===e&&(e=r.substring(F)),f.push(e),F=n,k(f),o&&R()),C()}function w(e){F=e,k(f),f=[],g=r.indexOf(x,F)}function C(e){return{data:h,errors:u,meta:{delimiter:O,linebreak:x,aborted:z,truncated:!!e,cursor:d+(t||0)}}}function R(){T(C()),h=[],u=[]}},this.abort=function(){z=!0},this.getCharIndex=function(){return F}}function _(e){var t=e.data,i=a[t.workerId],r=!1;if(t.error)i.userError(t.error,t.file);else if(t.results&&t.results.data){var n={abort:function(){r=!0,m(t.workerId,{data:[],errors:[],meta:{aborted:!0}})},pause:y,resume:y};if(M(i.userStep)){for(var s=0;s - + Leaderboard - GDIPS Demonlist - - - - + + + + + + + + + + + + + - -
-
-
+
-
-

Top Players Leaderboard

+
+
+

Top Players Leaderboard

+

Ranked by weighted points across every verified GDIPS completion

+
-
- - +
-
-
- - - - - - - - - - - - - - -
#PlayerPointsDemonsCPLast Record
Loading...
+
+ +
+ + + + + + + + + + + + + + + +
GDIPS demon list leaderboard
#PlayerPointsDemonsCPLast Record
Loadingโ€ฆ
-
-

ยฉ 2025 GDIPS Demon List | All Rights Reserved

-

Not affiliated with Geometry Dash or RobTop Games

+ + + diff --git a/main/demonlist/impossiblelist.html b/main/demonlist/impossiblelist.html index 53fd749..93ff4e8 100644 --- a/main/demonlist/impossiblelist.html +++ b/main/demonlist/impossiblelist.html @@ -1,3521 +1,497 @@ - + - GDIPS Imposssible List + GDIPS Impossible List - - - - + + + + + + + + + + + + - -
-
-
- -
- - -
-
-
-
+ + +
-
-
-
0
-
Total Impossible
-
-
-
0
-
Extreme Impossible
-
-
-
-
-
Last Updated
-
+
+ + +
+
+ +
+

Dynamic colour

+
+
+
+
+
+
+
+ + + +
+
+
+
+
0
+
Total Impossible
+
+
+
0
+
Extreme Impossible
+
+
+
-
+
Last Updated
+
+
-
-
- - -
-
- -
-
- -
-
All Difficulties
-
Easy
-
Medium
-
Hard
-
Insane
-
Extreme
-
Impossible
-
-
- -
- -
-
Rank
-
Name
-
Difficulty
-
Creator
-
Rating
-
-
-
- -
-
- - -
- -
- - - - - -
-
+
+ -
-

Advanced Filters

-
- - -
0
-
-
- - -
5
-
-
- - -
-
- - -
-
- -
-
- - -
-
- - -
-
- - -
+
+
+ + +
+ +
+ + +
-
Loading impossible levels...
-
- -
+
+
+ + +
- -
+ +
+

Advanced Filters

+
+ + +
0
-
- -
-
+ + +