diff --git a/.prettierignore b/.prettierignore index 6d08e4c..020918d 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,3 +1,4 @@ node_modules/ yarn.lock dist/ +.claude/ diff --git a/README.md b/README.md index e5a74b5..f327059 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ src/ index.html index.js components/ — UI components (account list, send form, etc.) - styles/ — CSS + styles/ — CSS (Tailwind) content/ — content script injected into web pages index.js — injects the provider into page context inpage.js — the window.ethereum provider object @@ -69,6 +69,85 @@ manifest/ firefox.json — Manifest V2/V3 for Firefox ``` +### UI Design Philosophy + +The UI follows a "Universal Paperclips" aesthetic — a deliberately spartan, +almost brutalist approach: + +- **Monochrome**: Black text on white background. No brand colors, no gradients, + no color-coding. Color may be introduced later for specific semantic purposes + (e.g. error states) but the baseline is monochrome. +- **Text-first**: Every piece of information is presented as text. Balances are + numbers. Addresses are hex strings. Status is a sentence. No progress spinners + with animations — a text status line is sufficient. +- **Monospace font**: All text is rendered in the system monospace font. + Ethereum addresses, transaction hashes, and balances are inherently + fixed-width data. Rather than mixing proportional and monospace fonts, we use + monospace everywhere for visual consistency and alignment. +- **Icon fonts only**: Where icons are needed (copy, send, settings, etc.) we + use an icon font (no SVGs, no PNGs, no image assets). This keeps the extension + size tiny and the build simple. +- **No images**: Zero image assets in the entire extension. No logos, no + illustrations, no token icons. Token identity is conveyed by symbol text (ETH, + USDC, etc.). +- **Tailwind CSS**: Utility-first CSS via Tailwind. No custom CSS classes for + styling. Tailwind is configured with a minimal monochrome palette. This keeps + the styling co-located with the markup and eliminates CSS file management. +- **Vanilla JS**: No framework (React, Vue, Svelte, etc.). The popup UI is small + enough that vanilla JS with simple view switching is sufficient. A framework + would add bundle size, build complexity, and attack surface for no benefit at + this scale. +- **360x600 popup**: Standard browser extension popup dimensions. The UI is + designed for this fixed viewport — no responsive breakpoints needed. + +### UI Views + +The popup has the following views, switched via simple show/hide: + +1. **Lock screen**: Password input + unlock button. Shown when the wallet is + locked or on first open after browser restart. +2. **Setup / Onboarding**: Shown on first use. Create a new wallet (generates + BIP-39 mnemonic, user confirms backup, sets password) or import an existing + seed phrase. +3. **Main / Account view**: The default view after unlock. Shows the current + account address (truncated, click to copy), ETH balance, list of added ERC-20 + tokens with balances, and action buttons (Send, Receive, Settings). +4. **Send**: Form with To address, amount, token selector (ETH or any added + ERC-20), and a Send button. Shows gas estimate before confirming. +5. **Receive**: Displays the current account address in full (copyable). That's + it. +6. **Settings**: Configure RPC endpoint URL, manage wallets (add/remove seed + phrases), derive additional accounts, view/export seed phrase (requires + password re-entry), manage added ERC-20 tokens. +7. **Approval popups**: When a connected site requests a transaction signature + or message signature, an approval view shows the details and Approve/Reject + buttons. + +### External Services + +AutistMask is not a fully self-contained offline tool. It necessarily +communicates with external services to function as a wallet: + +- **Ethereum JSON-RPC endpoint**: The extension needs an Ethereum node to query + balances (`eth_getBalance`), read ERC-20 token contracts (`eth_call`), + estimate gas (`eth_estimateGas`), fetch nonces (`eth_getTransactionCount`), + broadcast transactions (`eth_sendRawTransaction`), and check transaction + receipts. The default endpoint is a public RPC (configurable by the user to + any endpoint they prefer, including a local node). This is the only external + service the extension talks to. + +What the extension does NOT do: + +- No analytics or telemetry services +- No token list APIs (user adds tokens manually by contract address) +- No price feed APIs (balances are shown in token units, not fiat) +- No phishing/blocklist APIs +- No Infura/Alchemy dependency (any JSON-RPC endpoint works) +- No backend servers operated by the developer + +The user's RPC endpoint is the single point of external communication. Users who +want maximum privacy can point it at their own Ethereum node. + ### Key Decisions - **No framework**: The popup UI is vanilla JS and HTML. The extension is small @@ -85,9 +164,6 @@ manifest/ - **Minimal RPC**: The extension communicates with Ethereum nodes via JSON-RPC. The default endpoint is configurable. No Infura dependency — users can point it at any Ethereum JSON-RPC endpoint. -- **No external services**: No analytics, no tracking, no telemetry, no ads, no - phishing lists, no token price feeds. The extension only talks to the - configured Ethereum RPC endpoint. ### Supported Functionality @@ -109,24 +185,29 @@ manifest/ ### Non-Goals - Token swaps (use a DEX in the browser) -- Portfolio/price tracking +- Portfolio/price tracking (balances shown in token units only, no fiat) - NFT display or management - Multi-chain support (Ethereum mainnet only, for now) - Analytics, telemetry, or tracking of any kind - Advertisements or promotions - Phishing detection (use your brain) - Hardware wallet support (maybe later) +- Token list auto-discovery (user adds tokens manually) +- Fiat on/off ramps +- Browser notifications +- Transaction history (use Etherscan) ## TODO -- [ ] Set up build system (webpack/esbuild) for Chrome and Firefox targets +- [x] Project scaffolding (Makefile, Dockerfile, CI, manifests) +- [ ] Set up Tailwind CSS build pipeline +- [ ] Build popup UI views (lock, setup, main, send, receive, settings) - [ ] Implement BIP-39 mnemonic generation and validation - [ ] Implement BIP-32/BIP-44 HD key derivation for Ethereum - [ ] Implement encrypted storage for seed phrases -- [ ] Build popup UI: lock screen, account list, send/receive views - [ ] Implement background wallet manager - [ ] Implement EIP-1193 provider and content script injection -- [ ] Implement ETH send/receive +- [ ] Implement ETH balance lookup and send - [ ] Implement ERC-20 token management (add by contract, view balance, send) - [ ] Implement site connection approval flow - [ ] Implement transaction signing approval flow diff --git a/build.js b/build.js index 2faf418..ca4b719 100644 --- a/build.js +++ b/build.js @@ -1,21 +1,26 @@ const fs = require("fs"); const path = require("path"); +const { execSync } = require("child_process"); const DIST_CHROME = path.join(__dirname, "dist", "chrome"); const DIST_FIREFOX = path.join(__dirname, "dist", "firefox"); +const SRC = path.join(__dirname, "src"); function ensureDir(dir) { fs.mkdirSync(dir, { recursive: true }); } -function copyDir(src, dest) { +function copyDir(src, dest, opts = {}) { ensureDir(dest); const entries = fs.readdirSync(src, { withFileTypes: true }); for (const entry of entries) { const srcPath = path.join(src, entry.name); const destPath = path.join(dest, entry.name); + if (opts.skip && opts.skip.includes(entry.name)) { + continue; + } if (entry.isDirectory()) { - copyDir(srcPath, destPath); + copyDir(srcPath, destPath, opts); } else { fs.copyFileSync(srcPath, destPath); } @@ -25,12 +30,40 @@ function copyDir(src, dest) { function build() { console.log("Building AutistMask extension..."); - ensureDir(DIST_CHROME); - ensureDir(DIST_FIREFOX); + // compile tailwind CSS + console.log("Compiling Tailwind CSS..."); + const tailwindInput = path.join(SRC, "popup", "styles", "main.css"); + const tailwindOutput = path.join(__dirname, "dist", "styles.css"); + ensureDir(path.join(__dirname, "dist")); + execSync( + `npx @tailwindcss/cli -i ${tailwindInput} -o ${tailwindOutput} --minify`, + { stdio: "inherit" }, + ); - copyDir(path.join(__dirname, "src"), path.join(DIST_CHROME, "src")); - copyDir(path.join(__dirname, "src"), path.join(DIST_FIREFOX, "src")); + // copy source files (skip the styles dir, we compiled it) + for (const distDir of [DIST_CHROME, DIST_FIREFOX]) { + ensureDir(distDir); + copyDir(path.join(SRC, "popup"), path.join(distDir, "src", "popup"), { + skip: ["styles"], + }); + copyDir( + path.join(SRC, "background"), + path.join(distDir, "src", "background"), + ); + copyDir( + path.join(SRC, "content"), + path.join(distDir, "src", "content"), + ); + copyDir(path.join(SRC, "shared"), path.join(distDir, "src", "shared")); + // place compiled CSS next to popup HTML + fs.copyFileSync( + tailwindOutput, + path.join(distDir, "src", "popup", "styles.css"), + ); + } + + // copy manifests fs.copyFileSync( path.join(__dirname, "manifest", "chrome.json"), path.join(DIST_CHROME, "manifest.json"), diff --git a/package.json b/package.json index 4aa6910..ba677ea 100644 --- a/package.json +++ b/package.json @@ -13,8 +13,10 @@ "fmt-check": "prettier --check ." }, "devDependencies": { + "@tailwindcss/cli": "^4.2.1", "jest": "^30.2.0", - "prettier": "^3.8.1" + "prettier": "^3.8.1", + "tailwindcss": "^4.2.1" }, "dependencies": {} } diff --git a/src/popup/index.html b/src/popup/index.html index b968a9a..2e85bdf 100644 --- a/src/popup/index.html +++ b/src/popup/index.html @@ -4,10 +4,471 @@ AutistMask - + - -
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ diff --git a/src/popup/index.js b/src/popup/index.js index ce398f2..50dfb00 100644 --- a/src/popup/index.js +++ b/src/popup/index.js @@ -1,2 +1,372 @@ -// AutistMask popup UI -// TODO: lock screen, account list, send/receive views +// AutistMask popup UI — view management and event wiring +// All wallet logic will live in background/; this file is purely UI. + +const views = [ + "lock", + "setup", + "create", + "import", + "main", + "send", + "receive", + "add-token", + "settings", + "approve", +]; + +function showView(name) { + for (const v of views) { + const el = document.getElementById(`view-${v}`); + if (el) { + el.classList.toggle("hidden", v !== name); + } + } +} + +// -- mock state (will be replaced by background messaging) -- +const state = { + locked: true, + hasWallet: false, + password: null, + accounts: [], + selectedAccount: 0, + tokens: [], + rpcUrl: "https://eth.llamarpc.com", + mnemonic: null, +}; + +// -- helpers -- +function $(id) { + return document.getElementById(id); +} + +function showError(id, msg) { + const el = $(id); + el.textContent = msg; + el.classList.remove("hidden"); +} + +function hideError(id) { + $(id).classList.add("hidden"); +} + +function truncateAddress(addr) { + if (!addr) return ""; + return addr.slice(0, 6) + "..." + addr.slice(-4); +} + +function updateAccountSelector() { + const sel = $("account-selector"); + sel.innerHTML = ""; + state.accounts.forEach((acct, i) => { + const opt = document.createElement("option"); + opt.value = i; + opt.textContent = `Account ${i}: ${truncateAddress(acct.address)}`; + sel.appendChild(opt); + }); + sel.value = state.selectedAccount; + $("current-address").textContent = + state.accounts[state.selectedAccount]?.address || ""; + $("eth-balance").textContent = + state.accounts[state.selectedAccount]?.balance || "0.0000"; +} + +function updateTokenList() { + const list = $("token-list"); + if (state.tokens.length === 0) { + list.innerHTML = + '
no tokens added
'; + return; + } + list.innerHTML = state.tokens + .map( + (t) => + `
` + + `${t.symbol}` + + `${t.balance || "0.0000"}` + + `
`, + ) + .join(""); +} + +function updateSendTokenSelect() { + const sel = $("send-token"); + sel.innerHTML = ''; + state.tokens.forEach((t) => { + const opt = document.createElement("option"); + opt.value = t.address; + opt.textContent = t.symbol; + sel.appendChild(opt); + }); +} + +// -- init -- +function init() { + // For now, always show setup (no wallet exists yet). + // Once background messaging is wired, this will check actual state. + if (!state.hasWallet) { + showView("setup"); + } else if (state.locked) { + showView("lock"); + } else { + showView("main"); + } + + // -- Lock screen -- + $("btn-unlock").addEventListener("click", () => { + const pw = $("unlock-password").value; + if (!pw) { + showError("unlock-error", "enter a password"); + return; + } + hideError("unlock-error"); + // TODO: send unlock message to background + state.locked = false; + updateAccountSelector(); + updateTokenList(); + showView("main"); + }); + + // -- Setup -- + $("btn-setup-create").addEventListener("click", () => { + // TODO: request mnemonic generation from background + $("create-mnemonic").textContent = + "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"; + showView("create"); + }); + + $("btn-setup-import").addEventListener("click", () => { + showView("import"); + }); + + // -- Create wallet -- + $("btn-create-confirm").addEventListener("click", () => { + const pw = $("create-password").value; + const pw2 = $("create-password-confirm").value; + if (!pw) { + showError("create-error", "enter a password"); + return; + } + if (pw !== pw2) { + showError("create-error", "passwords do not match"); + return; + } + hideError("create-error"); + // TODO: send create wallet message to background + state.hasWallet = true; + state.locked = false; + state.password = pw; + state.mnemonic = $("create-mnemonic").textContent; + state.accounts = [ + { + address: "0x0000000000000000000000000000000000000001", + balance: "0.0000", + }, + ]; + state.selectedAccount = 0; + updateAccountSelector(); + updateTokenList(); + showView("main"); + }); + + $("btn-create-back").addEventListener("click", () => { + showView("setup"); + }); + + // -- Import wallet -- + $("btn-import-confirm").addEventListener("click", () => { + const mnemonic = $("import-mnemonic").value.trim(); + const pw = $("import-password").value; + const pw2 = $("import-password-confirm").value; + if (!mnemonic) { + showError("import-error", "enter a seed phrase"); + return; + } + if (!pw) { + showError("import-error", "enter a password"); + return; + } + if (pw !== pw2) { + showError("import-error", "passwords do not match"); + return; + } + hideError("import-error"); + // TODO: validate mnemonic and send to background + state.hasWallet = true; + state.locked = false; + state.password = pw; + state.mnemonic = mnemonic; + state.accounts = [ + { + address: "0x0000000000000000000000000000000000000001", + balance: "0.0000", + }, + ]; + state.selectedAccount = 0; + updateAccountSelector(); + updateTokenList(); + showView("main"); + }); + + $("btn-import-back").addEventListener("click", () => { + showView("setup"); + }); + + // -- Main view -- + $("btn-lock").addEventListener("click", () => { + state.locked = true; + $("unlock-password").value = ""; + showView("lock"); + }); + + $("btn-settings").addEventListener("click", () => { + $("settings-rpc").value = state.rpcUrl; + showView("settings"); + }); + + $("account-selector").addEventListener("change", (e) => { + state.selectedAccount = parseInt(e.target.value, 10); + $("current-address").textContent = + state.accounts[state.selectedAccount]?.address || ""; + $("eth-balance").textContent = + state.accounts[state.selectedAccount]?.balance || "0.0000"; + }); + + $("btn-copy-address").addEventListener("click", () => { + const addr = state.accounts[state.selectedAccount]?.address; + if (addr) { + navigator.clipboard.writeText(addr); + } + }); + + $("btn-send").addEventListener("click", () => { + updateSendTokenSelect(); + $("send-to").value = ""; + $("send-amount").value = ""; + $("send-gas-estimate").classList.add("hidden"); + $("send-status").classList.add("hidden"); + showView("send"); + }); + + $("btn-receive").addEventListener("click", () => { + $("receive-address").textContent = + state.accounts[state.selectedAccount]?.address || ""; + showView("receive"); + }); + + $("btn-add-token").addEventListener("click", () => { + $("add-token-address").value = ""; + $("add-token-info").classList.add("hidden"); + hideError("add-token-error"); + showView("add-token"); + }); + + // -- Send -- + $("btn-send-confirm").addEventListener("click", () => { + const to = $("send-to").value.trim(); + const amount = $("send-amount").value.trim(); + if (!to) { + showError("send-status", "enter a recipient address"); + $("send-status").classList.remove("hidden"); + return; + } + if (!amount || isNaN(parseFloat(amount))) { + showError("send-status", "enter a valid amount"); + $("send-status").classList.remove("hidden"); + return; + } + // TODO: construct and send transaction via background + const el = $("send-status"); + el.textContent = "transaction sent (stub)"; + el.classList.remove("hidden"); + }); + + $("btn-send-back").addEventListener("click", () => { + showView("main"); + }); + + // -- Receive -- + $("btn-receive-copy").addEventListener("click", () => { + const addr = $("receive-address").textContent; + if (addr) { + navigator.clipboard.writeText(addr); + } + }); + + $("btn-receive-back").addEventListener("click", () => { + showView("main"); + }); + + // -- Add Token -- + $("btn-add-token-confirm").addEventListener("click", () => { + const addr = $("add-token-address").value.trim(); + if (!addr || !addr.startsWith("0x")) { + showError("add-token-error", "enter a valid contract address"); + return; + } + hideError("add-token-error"); + // TODO: look up token name/symbol/decimals from contract via background + state.tokens.push({ + address: addr, + symbol: "TKN", + decimals: 18, + balance: "0.0000", + }); + updateTokenList(); + showView("main"); + }); + + $("btn-add-token-back").addEventListener("click", () => { + showView("main"); + }); + + // -- Settings -- + $("btn-save-rpc").addEventListener("click", () => { + state.rpcUrl = $("settings-rpc").value.trim(); + // TODO: persist via background + }); + + $("btn-derive-account").addEventListener("click", () => { + const idx = state.accounts.length; + // TODO: derive from seed via background + state.accounts.push({ + address: `0x${idx.toString(16).padStart(40, "0")}`, + balance: "0.0000", + }); + updateAccountSelector(); + }); + + $("btn-show-seed").addEventListener("click", () => { + const display = $("settings-seed-display"); + if (display.classList.contains("hidden")) { + // TODO: require password re-entry, get from background + display.textContent = state.mnemonic || "(no seed loaded)"; + display.classList.remove("hidden"); + } else { + display.classList.add("hidden"); + } + }); + + $("btn-import-additional").addEventListener("click", () => { + showView("import"); + }); + + $("btn-settings-back").addEventListener("click", () => { + updateAccountSelector(); + updateTokenList(); + showView("main"); + }); + + // -- Approval -- + $("btn-approve").addEventListener("click", () => { + // TODO: send approval to background + showView("main"); + }); + + $("btn-reject").addEventListener("click", () => { + // TODO: send rejection to background + showView("main"); + }); +} + +document.addEventListener("DOMContentLoaded", init); diff --git a/src/popup/styles/main.css b/src/popup/styles/main.css index 2c679b7..46746d9 100644 --- a/src/popup/styles/main.css +++ b/src/popup/styles/main.css @@ -1,18 +1,18 @@ -* { - margin: 0; - padding: 0; - box-sizing: border-box; +@import "tailwindcss"; + +@theme { + --font-mono: + ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, + "Liberation Mono", monospace; + --color-bg: #ffffff; + --color-fg: #000000; + --color-muted: #666666; + --color-border: #000000; + --color-border-light: #cccccc; + --color-hover: #eeeeee; } body { width: 360px; min-height: 600px; - font-family: - -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; - background: #1a1a2e; - color: #e0e0e0; -} - -#app { - padding: 16px; } diff --git a/yarn.lock b/yarn.lock index 51dc728..99e8bf5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -270,7 +270,7 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@emnapi/core@^1.4.3": +"@emnapi/core@^1.4.3", "@emnapi/core@^1.7.1", "@emnapi/core@^1.8.1": version "1.8.1" resolved "https://registry.yarnpkg.com/@emnapi/core/-/core-1.8.1.tgz#fd9efe721a616288345ffee17a1f26ac5dd01349" integrity sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg== @@ -278,14 +278,14 @@ "@emnapi/wasi-threads" "1.1.0" tslib "^2.4.0" -"@emnapi/runtime@^1.4.3": +"@emnapi/runtime@^1.4.3", "@emnapi/runtime@^1.7.1", "@emnapi/runtime@^1.8.1": version "1.8.1" resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.8.1.tgz#550fa7e3c0d49c5fb175a116e8cd70614f9a22a5" integrity sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg== dependencies: tslib "^2.4.0" -"@emnapi/wasi-threads@1.1.0": +"@emnapi/wasi-threads@1.1.0", "@emnapi/wasi-threads@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz#60b2102fddc9ccb78607e4a3cf8403ea69be41bf" integrity sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ== @@ -561,7 +561,7 @@ resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== -"@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0": +"@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0", "@jridgewell/sourcemap-codec@^1.5.5": version "1.5.5" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz#6912b00d2c631c0d15ce1a7ab57cd657f2a8f8ba" integrity sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og== @@ -583,6 +583,104 @@ "@emnapi/runtime" "^1.4.3" "@tybys/wasm-util" "^0.10.0" +"@napi-rs/wasm-runtime@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.1.tgz#c3705ab549d176b8dc5172723d6156c3dc426af2" + integrity sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A== + dependencies: + "@emnapi/core" "^1.7.1" + "@emnapi/runtime" "^1.7.1" + "@tybys/wasm-util" "^0.10.1" + +"@parcel/watcher-android-arm64@2.5.6": + version "2.5.6" + resolved "https://registry.yarnpkg.com/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.6.tgz#5f32e0dba356f4ac9a11068d2a5c134ca3ba6564" + integrity sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A== + +"@parcel/watcher-darwin-arm64@2.5.6": + version "2.5.6" + resolved "https://registry.yarnpkg.com/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.6.tgz#88d3e720b59b1eceffce98dac46d7c40e8be5e8e" + integrity sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA== + +"@parcel/watcher-darwin-x64@2.5.6": + version "2.5.6" + resolved "https://registry.yarnpkg.com/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.6.tgz#bf05d76a78bc15974f15ec3671848698b0838063" + integrity sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg== + +"@parcel/watcher-freebsd-x64@2.5.6": + version "2.5.6" + resolved "https://registry.yarnpkg.com/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.6.tgz#8bc26e9848e7303ac82922a5ae1b1ef1bdb48a53" + integrity sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng== + +"@parcel/watcher-linux-arm-glibc@2.5.6": + version "2.5.6" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.6.tgz#1328fee1deb0c2d7865079ef53a2ba4cc2f8b40a" + integrity sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ== + +"@parcel/watcher-linux-arm-musl@2.5.6": + version "2.5.6" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.6.tgz#bad0f45cb3e2157746db8b9d22db6a125711f152" + integrity sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg== + +"@parcel/watcher-linux-arm64-glibc@2.5.6": + version "2.5.6" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.6.tgz#b75913fbd501d9523c5f35d420957bf7d0204809" + integrity sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA== + +"@parcel/watcher-linux-arm64-musl@2.5.6": + version "2.5.6" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.6.tgz#da5621a6a576070c8c0de60dea8b46dc9c3827d4" + integrity sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA== + +"@parcel/watcher-linux-x64-glibc@2.5.6": + version "2.5.6" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.6.tgz#ce437accdc4b30f93a090b4a221fd95cd9b89639" + integrity sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ== + +"@parcel/watcher-linux-x64-musl@2.5.6": + version "2.5.6" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.6.tgz#02400c54b4a67efcc7e2327b249711920ac969e2" + integrity sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg== + +"@parcel/watcher-win32-arm64@2.5.6": + version "2.5.6" + resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.6.tgz#caae3d3c7583ca0a7171e6bd142c34d20ea1691e" + integrity sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q== + +"@parcel/watcher-win32-ia32@2.5.6": + version "2.5.6" + resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.6.tgz#9ac922550896dfe47bfc5ae3be4f1bcaf8155d6d" + integrity sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g== + +"@parcel/watcher-win32-x64@2.5.6": + version "2.5.6" + resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.6.tgz#73fdafba2e21c448f0e456bbe13178d8fe11739d" + integrity sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw== + +"@parcel/watcher@^2.5.1": + version "2.5.6" + resolved "https://registry.yarnpkg.com/@parcel/watcher/-/watcher-2.5.6.tgz#3f932828c894f06d0ad9cfefade1756ecc6ef1f1" + integrity sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ== + dependencies: + detect-libc "^2.0.3" + is-glob "^4.0.3" + node-addon-api "^7.0.0" + picomatch "^4.0.3" + optionalDependencies: + "@parcel/watcher-android-arm64" "2.5.6" + "@parcel/watcher-darwin-arm64" "2.5.6" + "@parcel/watcher-darwin-x64" "2.5.6" + "@parcel/watcher-freebsd-x64" "2.5.6" + "@parcel/watcher-linux-arm-glibc" "2.5.6" + "@parcel/watcher-linux-arm-musl" "2.5.6" + "@parcel/watcher-linux-arm64-glibc" "2.5.6" + "@parcel/watcher-linux-arm64-musl" "2.5.6" + "@parcel/watcher-linux-x64-glibc" "2.5.6" + "@parcel/watcher-linux-x64-musl" "2.5.6" + "@parcel/watcher-win32-arm64" "2.5.6" + "@parcel/watcher-win32-ia32" "2.5.6" + "@parcel/watcher-win32-x64" "2.5.6" + "@pkgjs/parseargs@^0.11.0": version "0.11.0" resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" @@ -612,7 +710,118 @@ dependencies: "@sinonjs/commons" "^3.0.1" -"@tybys/wasm-util@^0.10.0": +"@tailwindcss/cli@^4.2.1": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@tailwindcss/cli/-/cli-4.2.1.tgz#a61addb3c4935e3a3f6169cd3e5fb941a6404632" + integrity sha512-b7MGn51IA80oSG+7fuAgzfQ+7pZBgjzbqwmiv6NO7/+a1sev32cGqnwhscT7h0EcAvMa9r7gjRylqOH8Xhc4DA== + dependencies: + "@parcel/watcher" "^2.5.1" + "@tailwindcss/node" "4.2.1" + "@tailwindcss/oxide" "4.2.1" + enhanced-resolve "^5.19.0" + mri "^1.2.0" + picocolors "^1.1.1" + tailwindcss "4.2.1" + +"@tailwindcss/node@4.2.1": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@tailwindcss/node/-/node-4.2.1.tgz#e963ac242a885353a4660e7e3e9c695cde7d3fc9" + integrity sha512-jlx6sLk4EOwO6hHe1oCGm1Q4AN/s0rSrTTPBGPM0/RQ6Uylwq17FuU8IeJJKEjtc6K6O07zsvP+gDO6MMWo7pg== + dependencies: + "@jridgewell/remapping" "^2.3.5" + enhanced-resolve "^5.19.0" + jiti "^2.6.1" + lightningcss "1.31.1" + magic-string "^0.30.21" + source-map-js "^1.2.1" + tailwindcss "4.2.1" + +"@tailwindcss/oxide-android-arm64@4.2.1": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.2.1.tgz#a7c24919b607e7f884e6ab97799d12c7fb5b47bd" + integrity sha512-eZ7G1Zm5EC8OOKaesIKuw77jw++QJ2lL9N+dDpdQiAB/c/B2wDh0QPFHbkBVrXnwNugvrbJFk1gK2SsVjwWReg== + +"@tailwindcss/oxide-darwin-arm64@4.2.1": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.2.1.tgz#6f6e91ff0e1b5476cc0dad0da1ea8474f4563212" + integrity sha512-q/LHkOstoJ7pI1J0q6djesLzRvQSIfEto148ppAd+BVQK0JYjQIFSK3JgYZJa+Yzi0DDa52ZsQx2rqytBnf8Hw== + +"@tailwindcss/oxide-darwin-x64@4.2.1": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.2.1.tgz#1e59ef0665f6cb9e658bf0ebcb3cb50f21b2c175" + integrity sha512-/f/ozlaXGY6QLbpvd/kFTro2l18f7dHKpB+ieXz+Cijl4Mt9AI2rTrpq7V+t04nK+j9XBQHnSMdeQRhbGyt6fw== + +"@tailwindcss/oxide-freebsd-x64@4.2.1": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.2.1.tgz#6b0c75e9dac7f1a241cb9a5eaa89f0d9664835b6" + integrity sha512-5e/AkgYJT/cpbkys/OU2Ei2jdETCLlifwm7ogMC7/hksI2fC3iiq6OcXwjibcIjPung0kRtR3TxEITkqgn0TcA== + +"@tailwindcss/oxide-linux-arm-gnueabihf@4.2.1": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.2.1.tgz#717044d8fe746b1f0760485946c0c9a900174f7b" + integrity sha512-Uny1EcVTTmerCKt/1ZuKTkb0x8ZaiuYucg2/kImO5A5Y/kBz41/+j0gxUZl+hTF3xkWpDmHX+TaWhOtba2Fyuw== + +"@tailwindcss/oxide-linux-arm64-gnu@4.2.1": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.2.1.tgz#f544b0faf166d80791347911b2dd4372a893129d" + integrity sha512-CTrwomI+c7n6aSSQlsPL0roRiNMDQ/YzMD9EjcR+H4f0I1SQ8QqIuPnsVp7QgMkC1Qi8rtkekLkOFjo7OlEFRQ== + +"@tailwindcss/oxide-linux-arm64-musl@4.2.1": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.2.1.tgz#9fbaf8dc00b858a2b955526abb15d88f5678d1ef" + integrity sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ== + +"@tailwindcss/oxide-linux-x64-gnu@4.2.1": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.2.1.tgz#6ab4e6b8d308d037a1155b8443df5941dbfa6aa1" + integrity sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g== + +"@tailwindcss/oxide-linux-x64-musl@4.2.1": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.2.1.tgz#52c55593394dff85f1fa88172f69f8fdcde182b6" + integrity sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g== + +"@tailwindcss/oxide-wasm32-wasi@4.2.1": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.2.1.tgz#7401e35f881d3654b6180badd1243d75a2702ea5" + integrity sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q== + dependencies: + "@emnapi/core" "^1.8.1" + "@emnapi/runtime" "^1.8.1" + "@emnapi/wasi-threads" "^1.1.0" + "@napi-rs/wasm-runtime" "^1.1.1" + "@tybys/wasm-util" "^0.10.1" + tslib "^2.8.1" + +"@tailwindcss/oxide-win32-arm64-msvc@4.2.1": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.2.1.tgz#63a502e7b696dcd976aa356b94ce0f4f8f832c44" + integrity sha512-YlUEHRHBGnCMh4Nj4GnqQyBtsshUPdiNroZj8VPkvTZSoHsilRCwXcVKnG9kyi0ZFAS/3u+qKHBdDc81SADTRA== + +"@tailwindcss/oxide-win32-x64-msvc@4.2.1": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.2.1.tgz#8cc59b28ebc4dc866c0c14d7057f07f0ed04c4a8" + integrity sha512-rbO34G5sMWWyrN/idLeVxAZgAKWrn5LiR3/I90Q9MkA67s6T1oB0xtTe+0heoBvHSpbU9Mk7i6uwJnpo4u21XQ== + +"@tailwindcss/oxide@4.2.1": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide/-/oxide-4.2.1.tgz#43ae4217268a7e8b4736f1c056d0ef6f393c79d3" + integrity sha512-yv9jeEFWnjKCI6/T3Oq50yQEOqmpmpfzG1hcZsAOaXFQPfzWprWrlHSdGPEF3WQTi8zu8ohC9Mh9J470nT5pUw== + optionalDependencies: + "@tailwindcss/oxide-android-arm64" "4.2.1" + "@tailwindcss/oxide-darwin-arm64" "4.2.1" + "@tailwindcss/oxide-darwin-x64" "4.2.1" + "@tailwindcss/oxide-freebsd-x64" "4.2.1" + "@tailwindcss/oxide-linux-arm-gnueabihf" "4.2.1" + "@tailwindcss/oxide-linux-arm64-gnu" "4.2.1" + "@tailwindcss/oxide-linux-arm64-musl" "4.2.1" + "@tailwindcss/oxide-linux-x64-gnu" "4.2.1" + "@tailwindcss/oxide-linux-x64-musl" "4.2.1" + "@tailwindcss/oxide-wasm32-wasi" "4.2.1" + "@tailwindcss/oxide-win32-arm64-msvc" "4.2.1" + "@tailwindcss/oxide-win32-x64-msvc" "4.2.1" + +"@tybys/wasm-util@^0.10.0", "@tybys/wasm-util@^0.10.1": version "0.10.1" resolved "https://registry.yarnpkg.com/@tybys/wasm-util/-/wasm-util-0.10.1.tgz#ecddd3205cf1e2d5274649ff0eedd2991ed7f414" integrity sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg== @@ -1076,6 +1285,11 @@ deepmerge@^4.3.1: resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== +detect-libc@^2.0.3: + version "2.1.2" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.1.2.tgz#689c5dcdc1900ef5583a4cb9f6d7b473742074ad" + integrity sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ== + detect-newline@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" @@ -1106,6 +1320,14 @@ emoji-regex@^9.2.2: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== +enhanced-resolve@^5.19.0: + version "5.19.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.19.0.tgz#6687446a15e969eaa63c2fa2694510e17ae6d97c" + integrity sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.3.0" + error-ex@^1.3.1: version "1.3.4" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.4.tgz#b3a8d8bb6f92eecc1629e3e27d3c8607a8a32414" @@ -1249,7 +1471,7 @@ glob@^7.1.4: once "^1.3.0" path-is-absolute "^1.0.0" -graceful-fs@^4.2.11: +graceful-fs@^4.2.11, graceful-fs@^4.2.4: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== @@ -1300,6 +1522,11 @@ is-arrayish@^0.2.1: resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + is-fullwidth-code-point@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" @@ -1310,6 +1537,13 @@ is-generator-fn@^2.1.0: resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== +is-glob@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + is-number@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" @@ -1732,6 +1966,11 @@ jest@^30.2.0: import-local "^3.2.0" jest-cli "30.2.0" +jiti@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/jiti/-/jiti-2.6.1.tgz#178ef2fc9a1a594248c20627cd820187a4d78d92" + integrity sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ== + js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -1765,6 +2004,80 @@ leven@^3.1.0: resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== +lightningcss-android-arm64@1.31.1: + version "1.31.1" + resolved "https://registry.yarnpkg.com/lightningcss-android-arm64/-/lightningcss-android-arm64-1.31.1.tgz#609ff48332adff452a8157a7c2842fd692a8eac4" + integrity sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg== + +lightningcss-darwin-arm64@1.31.1: + version "1.31.1" + resolved "https://registry.yarnpkg.com/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.31.1.tgz#a13da040a7929582bab3ace9a67bdc146e99fc2d" + integrity sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg== + +lightningcss-darwin-x64@1.31.1: + version "1.31.1" + resolved "https://registry.yarnpkg.com/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.31.1.tgz#f7482c311273571ec0c2bd8277c1f5f6e90e03a4" + integrity sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA== + +lightningcss-freebsd-x64@1.31.1: + version "1.31.1" + resolved "https://registry.yarnpkg.com/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.31.1.tgz#91df1bb290f1cb7bb2af832d7d0d8809225e0124" + integrity sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A== + +lightningcss-linux-arm-gnueabihf@1.31.1: + version "1.31.1" + resolved "https://registry.yarnpkg.com/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.31.1.tgz#c3cad5ae8b70045f21600dc95295ab6166acf57e" + integrity sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g== + +lightningcss-linux-arm64-gnu@1.31.1: + version "1.31.1" + resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.31.1.tgz#a5c4f6a5ac77447093f61b209c0bd7fef1f0a3e3" + integrity sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg== + +lightningcss-linux-arm64-musl@1.31.1: + version "1.31.1" + resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.31.1.tgz#af26ab8f829b727ada0a200938a6c8796ff36900" + integrity sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg== + +lightningcss-linux-x64-gnu@1.31.1: + version "1.31.1" + resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.31.1.tgz#a891d44e84b71c0d88959feb9a7522bbf61450ee" + integrity sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA== + +lightningcss-linux-x64-musl@1.31.1: + version "1.31.1" + resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.31.1.tgz#8c8b21def851f4d477fa897b80cb3db2b650bc6e" + integrity sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA== + +lightningcss-win32-arm64-msvc@1.31.1: + version "1.31.1" + resolved "https://registry.yarnpkg.com/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.31.1.tgz#79000fb8c57e94a91b8fc643e74d5a54407d7080" + integrity sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w== + +lightningcss-win32-x64-msvc@1.31.1: + version "1.31.1" + resolved "https://registry.yarnpkg.com/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.31.1.tgz#7f025274c81c7d659829731e09c8b6f442209837" + integrity sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw== + +lightningcss@1.31.1: + version "1.31.1" + resolved "https://registry.yarnpkg.com/lightningcss/-/lightningcss-1.31.1.tgz#1a19dd327b547a7eda1d5c296ebe1e72df5a184b" + integrity sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ== + dependencies: + detect-libc "^2.0.3" + optionalDependencies: + lightningcss-android-arm64 "1.31.1" + lightningcss-darwin-arm64 "1.31.1" + lightningcss-darwin-x64 "1.31.1" + lightningcss-freebsd-x64 "1.31.1" + lightningcss-linux-arm-gnueabihf "1.31.1" + lightningcss-linux-arm64-gnu "1.31.1" + lightningcss-linux-arm64-musl "1.31.1" + lightningcss-linux-x64-gnu "1.31.1" + lightningcss-linux-x64-musl "1.31.1" + lightningcss-win32-arm64-msvc "1.31.1" + lightningcss-win32-x64-msvc "1.31.1" + lines-and-columns@^1.1.6: version "1.2.4" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" @@ -1789,6 +2102,13 @@ lru-cache@^5.1.1: dependencies: yallist "^3.0.2" +magic-string@^0.30.21: + version "0.30.21" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.21.tgz#56763ec09a0fa8091df27879fd94d19078c00d91" + integrity sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.5" + make-dir@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" @@ -1840,6 +2160,11 @@ minimatch@^9.0.4: resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.3.tgz#79389b4eb1bb2d003a9bba87d492f2bd37bdc65b" integrity sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A== +mri@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b" + integrity sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA== + ms@^2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" @@ -1855,6 +2180,11 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== +node-addon-api@^7.0.0: + version "7.1.1" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-7.1.1.tgz#1aba6693b0f255258a049d621329329322aad558" + integrity sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ== + node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" @@ -1965,7 +2295,7 @@ picomatch@^2.0.4, picomatch@^2.3.1: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== -picomatch@^4.0.2: +picomatch@^4.0.2, picomatch@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.3.tgz#796c76136d1eead715db1e7bad785dedd695a042" integrity sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q== @@ -2060,6 +2390,11 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== +source-map-js@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" + integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== + source-map-support@0.5.13: version "0.5.13" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" @@ -2177,6 +2512,16 @@ synckit@^0.11.8: dependencies: "@pkgr/core" "^0.2.9" +tailwindcss@4.2.1, tailwindcss@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-4.2.1.tgz#018c4720b58baf98a6bf56b0a12aa797c6cfef1d" + integrity sha512-/tBrSQ36vCleJkAOsy9kbNTgaxvGbyOamC30PRePTQe/o1MFwEKHQk4Cn7BNGaPtjp+PuUrByJehM1hgxfq4sw== + +tapable@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.3.0.tgz#7e3ea6d5ca31ba8e078b560f0d83ce9a14aa8be6" + integrity sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg== + test-exclude@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" @@ -2198,7 +2543,7 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" -tslib@^2.4.0: +tslib@^2.4.0, tslib@^2.8.1: version "2.8.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==