diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..8b09c8d --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,40 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + quality: + name: Quality checks + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + + - run: npm ci + + - name: TypeScript + run: npm run typecheck + + - name: Lint + run: npm run lint + + - name: Tests + run: npm run test -- --run + + - name: Build + run: npm run build + + - name: Upload extension + uses: actions/upload-artifact@v4 + with: + name: pixellens-extension + path: dist/ diff --git a/.gitignore b/.gitignore index 3c3629e..740f357 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ node_modules +PRD_02_PixelLens.mddist/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..6b84c72 --- /dev/null +++ b/README.md @@ -0,0 +1,141 @@ +# 🔍 PixelLens + +> *Inspect any website. Copy any design system.* + +Extension Chrome pour designers et dĂ©veloppeurs qui inspecte n'importe quel site web en un clic : extraction des couleurs, typographies, spacings, et gĂ©nĂ©ration automatique d'un mini design system exportable. + +## ✹ Features + +### 🎯 Mode Inspection +- Hover highlight avec box model visuel (padding vert, margin orange, content bleu) +- Clic sur un Ă©lĂ©ment → panel avec toutes les infos CSS +- Copie en un clic de n'importe quelle valeur + +### 📊 Mode Scan +- Analyse la page entiĂšre automatiquement +- Extraction : couleurs, typographies, spacings, shadows, border-radius +- Clustering intelligent des couleurs (deltaE) +- Classification auto : Primary, Secondary, Neutrals, Background, Text + +### 🎹 Design System Generator +- GĂ©nĂ©ration automatique d'un design system structurĂ© +- Tokens Ă©ditables (renommer, supprimer) +- Export multi-format : + - **CSS Variables** — `:root { --color-primary: ... }` + - **Tailwind Config** — `theme.extend` prĂȘt Ă  coller + - **JSON Tokens** — Compatible Style Dictionary / Figma + - **PNG Palette** — Image partageable + +### đŸ› ïž Outils +- 📏 Mesure de distances entre Ă©lĂ©ments +- 📐 Grid overlay configurable (4/8/12/16px) +- 🎯 Floating toolbar draggable + +## đŸ—ïž Tech Stack + +| Technologie | Usage | +|---|---| +| React 19 | UI Side Panel + Popup | +| TypeScript (strict) | Type safety partout | +| Tailwind CSS v4 | Styling avec design tokens | +| Vite + CRXJS | Build + HMR Chrome Extension | +| Zustand v5 | State management | +| Chroma.js | Color manipulation + clustering | +| Phosphor Icons | Iconographie | +| Chrome Extension MV3 | Manifest V3 + Side Panel API | + +## 📩 Installation + +### PrĂ©requis +- Node.js 20+ +- npm 9+ +- Chrome 114+ (pour la Side Panel API) + +### DĂ©veloppement +```bash +# Cloner le repo +git clone https://github.com/vgtray/pixellens.git +cd pixellens + +# Installer les dĂ©pendances +npm install + +# Lancer en mode dev (avec HMR) +npm run dev +``` + +### Charger l'extension dans Chrome +1. Ouvrir `chrome://extensions/` +2. Activer **Mode dĂ©veloppeur** (toggle en haut Ă  droite) +3. Cliquer **"Charger l'extension non empaquetĂ©e"** +4. SĂ©lectionner le dossier `dist/` du projet +5. L'icĂŽne 🔍 PixelLens apparaĂźt dans la toolbar Chrome +6. **Important** : aprĂšs chaque modification en dev, cliquer le bouton 🔄 sur la carte de l'extension dans `chrome://extensions/` + +### Utilisation rapide +| Action | Comment | +|---|---| +| Toggle inspection | `Ctrl+Shift+L` (ou `Cmd+Shift+L` sur Mac) | +| Inspecter un Ă©lĂ©ment | Mode Inspect activĂ© → clic sur l'Ă©lĂ©ment | +| Scanner une page | Clic "Scan" dans la floating toolbar | +| Voir le Side Panel | Se ouvre auto quand on inspecte | + +## đŸ›ïž Architecture + +``` +src/ +├── types/ # Types partagĂ©s (DesignSystem, Inspection, Messages) +├── lib/ # Utilitaires (colors, CSS parser, tokens, DOM, export, messaging, storage) +├── background/ # Service worker (routing messages, commands, badge) +├── popup/ # Popup compact (quick actions) +├── content/ # Content scripts injectĂ©s dans les pages +│ ├── inspector/ # ElementHighlighter, ElementSelector, DistanceMeasurer, GridOverlay +│ ├── scanner/ # PageScanner, ColorExtractor, TypographyExtractor, SpacingExtractor +│ └── ui/ # FloatingToolbar, InspectorTooltip, ContentApp (Shadow DOM) +└── sidepanel/ # Side Panel React app + ├── views/ # InspectorView, ScanView, DesignSystemView, ExportView, HistoryView + └── components/ # ColorSwatch, ColorPalette, TypeSpecimen, SpacingScale, BoxModelViz... +``` + +``` +Content Script ←→ Background Service Worker ←→ Side Panel + (DOM) (routing, storage) (React UI) +``` + +## 📋 Scripts + +| Script | Description | +|---|---| +| `npm run dev` | Dev avec Hot Module Replacement | +| `npm run build` | Build production dans `dist/` | +| `npm run typecheck` | VĂ©rification TypeScript | +| `npm run lint` | ESLint sur `src/` | +| `npm run test` | Tests unitaires (Vitest) | +| `npm run test:coverage` | Tests avec couverture | + +## 🚀 Build Production + +```bash +npm run build +``` + +Le dossier `dist/` contient l'extension prĂȘte. Pour le Chrome Web Store : +```bash +cd dist && zip -r ../pixellens.zip . +``` + +## đŸ§Ș Tests + +```bash +npm run test # Run une fois +npm run test -- --watch # Watch mode +npm run test:coverage # Avec rapport de couverture +``` + +## 📄 License + +MIT + +## đŸ‘€ Author + +**Adam Hnaien** — [@vgtray](https://github.com/vgtray) diff --git a/dist/assets/ClockCounterClockwise.es-CQVwCTyJ.js b/dist/assets/ClockCounterClockwise.es-CQVwCTyJ.js new file mode 100644 index 0000000..3288daa --- /dev/null +++ b/dist/assets/ClockCounterClockwise.es-CQVwCTyJ.js @@ -0,0 +1 @@ +import{r as e,p as s}from"./Scan.es-D0n8eUjn.js";(function(){const r=document.createElement("link").relList;if(r&&r.supports&&r.supports("modulepreload"))return;for(const t of document.querySelectorAll('link[rel="modulepreload"]'))o(t);new MutationObserver(t=>{for(const a of t)if(a.type==="childList")for(const l of a.addedNodes)l.tagName==="LINK"&&l.rel==="modulepreload"&&o(l)}).observe(document,{childList:!0,subtree:!0});function i(t){const a={};return t.integrity&&(a.integrity=t.integrity),t.referrerPolicy&&(a.referrerPolicy=t.referrerPolicy),t.crossOrigin==="use-credentials"?a.credentials="include":t.crossOrigin==="anonymous"?a.credentials="omit":a.credentials="same-origin",a}function o(t){if(t.ep)return;t.ep=!0;const a=i(t);fetch(t.href,a)}})();const m=new Map([["bold",e.createElement(e.Fragment,null,e.createElement("path",{d:"M140,80v41.21l34.17,20.5a12,12,0,1,1-12.34,20.58l-40-24A12,12,0,0,1,116,128V80a12,12,0,0,1,24,0ZM128,28A99.38,99.38,0,0,0,57.24,57.34c-4.69,4.74-9,9.37-13.24,14V64a12,12,0,0,0-24,0v40a12,12,0,0,0,12,12H72a12,12,0,0,0,0-24H57.77C63,86,68.37,80.22,74.26,74.26a76,76,0,1,1,1.58,109,12,12,0,0,0-16.48,17.46A100,100,0,1,0,128,28Z"}))],["duotone",e.createElement(e.Fragment,null,e.createElement("path",{d:"M216,128a88,88,0,1,1-88-88A88,88,0,0,1,216,128Z",opacity:"0.2"}),e.createElement("path",{d:"M136,80v43.47l36.12,21.67a8,8,0,0,1-8.24,13.72l-40-24A8,8,0,0,1,120,128V80a8,8,0,0,1,16,0Zm-8-48A95.44,95.44,0,0,0,60.08,60.15C52.81,67.51,46.35,74.59,40,82V64a8,8,0,0,0-16,0v40a8,8,0,0,0,8,8H72a8,8,0,0,0,0-16H49c7.15-8.42,14.27-16.35,22.39-24.57a80,80,0,1,1,1.66,114.75,8,8,0,1,0-11,11.64A96,96,0,1,0,128,32Z"}))],["fill",e.createElement(e.Fragment,null,e.createElement("path",{d:"M224,128A96,96,0,0,1,62.11,197.82a8,8,0,1,1,11-11.64A80,80,0,1,0,71.43,71.43C67.9,75,64.58,78.51,61.35,82L77.66,98.34A8,8,0,0,1,72,112H32a8,8,0,0,1-8-8V64a8,8,0,0,1,13.66-5.66L50,70.7c3.22-3.49,6.54-7,10.06-10.55A96,96,0,0,1,224,128ZM128,72a8,8,0,0,0-8,8v48a8,8,0,0,0,3.88,6.86l40,24a8,8,0,1,0,8.24-13.72L136,123.47V80A8,8,0,0,0,128,72Z"}))],["light",e.createElement(e.Fragment,null,e.createElement("path",{d:"M134,80v44.6l37.09,22.25a6,6,0,0,1-6.18,10.3l-40-24A6,6,0,0,1,122,128V80a6,6,0,0,1,12,0Zm-6-46A93.4,93.4,0,0,0,61.51,61.56c-8.58,8.68-16,17-23.51,25.8V64a6,6,0,0,0-12,0v40a6,6,0,0,0,6,6H72a6,6,0,0,0,0-12H44.73C52.86,88.29,60.79,79.35,70,70a82,82,0,1,1,1.7,117.62,6,6,0,1,0-8.24,8.72A94,94,0,1,0,128,34Z"}))],["regular",e.createElement(e.Fragment,null,e.createElement("path",{d:"M136,80v43.47l36.12,21.67a8,8,0,0,1-8.24,13.72l-40-24A8,8,0,0,1,120,128V80a8,8,0,0,1,16,0Zm-8-48A95.44,95.44,0,0,0,60.08,60.15C52.81,67.51,46.35,74.59,40,82V64a8,8,0,0,0-16,0v40a8,8,0,0,0,8,8H72a8,8,0,0,0,0-16H49c7.15-8.42,14.27-16.35,22.39-24.57a80,80,0,1,1,1.66,114.75,8,8,0,1,0-11,11.64A96,96,0,1,0,128,32Z"}))],["thin",e.createElement(e.Fragment,null,e.createElement("path",{d:"M132,80v45.74l38.06,22.83a4,4,0,0,1-4.12,6.86l-40-24A4,4,0,0,1,124,128V80a4,4,0,0,1,8,0Zm-4-44A91.42,91.42,0,0,0,62.93,63C53.05,73,44.66,82.47,36,92.86V64a4,4,0,0,0-8,0v40a4,4,0,0,0,4,4H72a4,4,0,0,0,0-8H40.47C49.61,89,58.3,79,68.6,68.6a84,84,0,1,1,1.75,120.49,4,4,0,1,0-5.5,5.82A92,92,0,1,0,128,36Z"}))]]),c=e.forwardRef((n,r)=>e.createElement(s,{ref:r,...n,weights:m}));c.displayName="ClockCounterClockwiseIcon";const d=c;export{d as a}; diff --git a/dist/assets/ContentApp-DS3Bful2.js b/dist/assets/ContentApp-DS3Bful2.js new file mode 100644 index 0000000..ec08e9f --- /dev/null +++ b/dist/assets/ContentApp-DS3Bful2.js @@ -0,0 +1 @@ +import{r as e,p as A,j as o,f as y,s as w,c as S}from"./Scan.es-D0n8eUjn.js";import{s as C}from"./Eyedropper.es-Cn4UL7iP.js";import{s as m}from"./colors-Czz5EmDP.js";import{M as p}from"./messages-CGxgbOds.js";const F=new Map([["bold",e.createElement(e.Fragment,null,e.createElement("path",{d:"M200,36H56A20,20,0,0,0,36,56V200a20,20,0,0,0,20,20H200a20,20,0,0,0,20-20V56A20,20,0,0,0,200,36Zm-4,80H140V60h56ZM116,60v56H60V60ZM60,140h56v56H60Zm80,56V140h56v56Z"}))],["duotone",e.createElement(e.Fragment,null,e.createElement("path",{d:"M208,56V200a8,8,0,0,1-8,8H56a8,8,0,0,1-8-8V56a8,8,0,0,1,8-8H200A8,8,0,0,1,208,56Z",opacity:"0.2"}),e.createElement("path",{d:"M200,40H56A16,16,0,0,0,40,56V200a16,16,0,0,0,16,16H200a16,16,0,0,0,16-16V56A16,16,0,0,0,200,40Zm0,80H136V56h64ZM120,56v64H56V56ZM56,136h64v64H56Zm144,64H136V136h64v64Z"}))],["fill",e.createElement(e.Fragment,null,e.createElement("path",{d:"M216,56v60a4,4,0,0,1-4,4H136V44a4,4,0,0,1,4-4h60A16,16,0,0,1,216,56ZM116,40H56A16,16,0,0,0,40,56v60a4,4,0,0,0,4,4h76V44A4,4,0,0,0,116,40Zm96,96H136v76a4,4,0,0,0,4,4h60a16,16,0,0,0,16-16V140A4,4,0,0,0,212,136ZM40,140v60a16,16,0,0,0,16,16h60a4,4,0,0,0,4-4V136H44A4,4,0,0,0,40,140Z"}))],["light",e.createElement(e.Fragment,null,e.createElement("path",{d:"M200,42H56A14,14,0,0,0,42,56V200a14,14,0,0,0,14,14H200a14,14,0,0,0,14-14V56A14,14,0,0,0,200,42Zm2,14v66H134V54h66A2,2,0,0,1,202,56ZM56,54h66v68H54V56A2,2,0,0,1,56,54ZM54,200V134h68v68H56A2,2,0,0,1,54,200Zm146,2H134V134h68v66A2,2,0,0,1,200,202Z"}))],["regular",e.createElement(e.Fragment,null,e.createElement("path",{d:"M200,40H56A16,16,0,0,0,40,56V200a16,16,0,0,0,16,16H200a16,16,0,0,0,16-16V56A16,16,0,0,0,200,40Zm0,80H136V56h64ZM120,56v64H56V56ZM56,136h64v64H56Zm144,64H136V136h64v64Z"}))],["thin",e.createElement(e.Fragment,null,e.createElement("path",{d:"M200,44H56A12,12,0,0,0,44,56V200a12,12,0,0,0,12,12H200a12,12,0,0,0,12-12V56A12,12,0,0,0,200,44Zm4,12v68H132V52h68A4,4,0,0,1,204,56ZM56,52h68v72H52V56A4,4,0,0,1,56,52ZM52,200V132h72v72H56A4,4,0,0,1,52,200Zm148,4H132V132h72v68A4,4,0,0,1,200,204Z"}))]]),k=new Map([["bold",e.createElement(e.Fragment,null,e.createElement("path",{d:"M238.15,70.54,185.46,17.86a20,20,0,0,0-28.29,0L17.85,157.17a20,20,0,0,0,0,28.29l52.69,52.68a20,20,0,0,0,28.29,0L238.15,98.83A20,20,0,0,0,238.15,70.54ZM84.68,218.34l-47-47L64,145l23.52,23.52a12,12,0,0,0,17-17L81,128l15-15,23.51,23.52a12,12,0,0,0,17-17L113,96l15-15,23.52,23.52a12,12,0,0,0,17-17L145,64l26.35-26.34,47,47Z"}))],["duotone",e.createElement(e.Fragment,null,e.createElement("path",{d:"M229.66,90.34,90.34,229.66a8,8,0,0,1-11.31,0L26.34,177a8,8,0,0,1,0-11.31L165.66,26.34a8,8,0,0,1,11.31,0L229.66,79A8,8,0,0,1,229.66,90.34Z",opacity:"0.2"}),e.createElement("path",{d:"M235.32,73.37,182.63,20.69a16,16,0,0,0-22.63,0L20.68,160a16,16,0,0,0,0,22.63l52.69,52.68a16,16,0,0,0,22.63,0L235.32,96A16,16,0,0,0,235.32,73.37ZM84.68,224,32,171.31l32-32,26.34,26.35a8,8,0,0,0,11.32-11.32L75.31,128,96,107.31l26.34,26.35a8,8,0,0,0,11.32-11.32L107.31,96,128,75.31l26.34,26.35a8,8,0,0,0,11.32-11.32L139.31,64l32-32L224,84.69Z"}))],["fill",e.createElement(e.Fragment,null,e.createElement("path",{d:"M235.32,96,96,235.31a16,16,0,0,1-22.63,0L20.68,182.63a16,16,0,0,1,0-22.63l29.17-29.17a4,4,0,0,1,5.66,0l34.83,34.83a8,8,0,0,0,11.71-.43,8.18,8.18,0,0,0-.6-11.09L66.82,119.51a4,4,0,0,1,0-5.65l15-15a4,4,0,0,1,5.66,0l34.83,34.83a8,8,0,0,0,11.71-.43,8.18,8.18,0,0,0-.6-11.09L98.83,87.51a4,4,0,0,1,0-5.65l15-15a4,4,0,0,1,5.65,0l34.83,34.83a8,8,0,0,0,11.72-.43,8.18,8.18,0,0,0-.61-11.09L130.83,55.51a4,4,0,0,1,0-5.65L160,20.69a16,16,0,0,1,22.63,0l52.69,52.68A16,16,0,0,1,235.32,96Z"}))],["light",e.createElement(e.Fragment,null,e.createElement("path",{d:"M233.91,74.79,181.22,22.1a14,14,0,0,0-19.8,0L22.09,161.41a14,14,0,0,0,0,19.8L74.78,233.9a14,14,0,0,0,19.8,0L233.91,94.59A14,14,0,0,0,233.91,74.79ZM225.42,86.1,86.1,225.41h0a2,2,0,0,1-2.83,0L30.58,172.73a2,2,0,0,1,0-2.83L64,136.48l27.76,27.76a6,6,0,1,0,8.48-8.48L72.48,128,96,104.48l27.76,27.76a6,6,0,0,0,8.48-8.48L104.48,96,128,72.49l27.76,27.75a6,6,0,0,0,8.48-8.48L136.49,64,169.9,30.59a2,2,0,0,1,2.83,0l52.69,52.68A2,2,0,0,1,225.42,86.1Z"}))],["regular",e.createElement(e.Fragment,null,e.createElement("path",{d:"M235.32,73.37,182.63,20.69a16,16,0,0,0-22.63,0L20.68,160a16,16,0,0,0,0,22.63l52.69,52.68a16,16,0,0,0,22.63,0L235.32,96A16,16,0,0,0,235.32,73.37ZM84.68,224,32,171.31l32-32,26.34,26.35a8,8,0,0,0,11.32-11.32L75.31,128,96,107.31l26.34,26.35a8,8,0,0,0,11.32-11.32L107.31,96,128,75.31l26.34,26.35a8,8,0,0,0,11.32-11.32L139.31,64l32-32L224,84.69Z"}))],["thin",e.createElement(e.Fragment,null,e.createElement("path",{d:"M232.49,76.2,179.8,23.51a12,12,0,0,0-17,0L23.51,162.83a12,12,0,0,0,0,17L76.2,232.49a12,12,0,0,0,17,0L232.49,93.17A12,12,0,0,0,232.49,76.2Zm-5.66,11.31L87.51,226.83a4,4,0,0,1-5.65,0L29.17,174.14a4,4,0,0,1,0-5.65L64,133.66l29.17,29.17a4,4,0,1,0,5.66-5.66L69.65,128,96,101.66l29.17,29.17a4,4,0,0,0,5.66-5.66L101.65,96,128,69.66l29.17,29.17a4,4,0,1,0,5.66-5.66L133.66,64l34.83-34.83a4,4,0,0,1,5.65,0l52.69,52.69A4,4,0,0,1,226.83,87.51Z"}))]]),H=e.forwardRef((t,a)=>e.createElement(A,{ref:a,...t,weights:F}));H.displayName="GridFourIcon";const T=H,V=e.forwardRef((t,a)=>e.createElement(A,{ref:a,...t,weights:k}));V.displayName="RulerIcon";const G=V,b="pixellens_toolbar_pos";function N({mode:t,gridVisible:a,onModeChange:c,onGridToggle:d,onScan:g}){const h=e.useRef(null),[v,L]=e.useState(!1),[f,r]=e.useState(!1),[l,i]=e.useState(null),u=e.useRef({x:0,y:0});e.useEffect(()=>{try{const n=localStorage.getItem(b);n&&i(JSON.parse(n))}catch{}requestAnimationFrame(()=>L(!0))},[]),e.useEffect(()=>{if(l)try{localStorage.setItem(b,JSON.stringify(l))}catch{}},[l]);const E=e.useCallback(n=>{if(!h.current)return;const s=h.current.getBoundingClientRect();u.current={x:n.clientX-s.left,y:n.clientY-s.top},r(!0)},[]);e.useEffect(()=>{if(!f)return;const n=Z=>{i({x:Z.clientX-u.current.x,y:Z.clientY-u.current.y})},s=()=>r(!1);return window.addEventListener("mousemove",n),window.addEventListener("mouseup",s),()=>{window.removeEventListener("mousemove",n),window.removeEventListener("mouseup",s)}},[f]);const M=l?{left:l.x,top:l.y,transform:"none"}:{},x=[{icon:o.jsx(y,{size:18,weight:t==="inspect"?"fill":"regular"}),label:"Inspect",active:t==="inspect",onClick:()=>c("inspect")},{icon:o.jsx(G,{size:18,weight:t==="measure"?"fill":"regular"}),label:"Measure",active:t==="measure",onClick:()=>c("measure")},{icon:o.jsx(T,{size:18,weight:a?"fill":"regular"}),label:"Grid",active:a,onClick:d},{icon:o.jsx(C,{size:18,weight:"regular"}),label:"Picker",active:!1,onClick:()=>{}},{icon:o.jsx(w,{size:18,weight:"regular"}),label:"Scan",active:!1,onClick:g}];return o.jsx("div",{ref:h,onMouseDown:E,style:{position:"fixed",bottom:l?"auto":"24px",left:l?"auto":"50%",transform:l?"none":"translateX(-50%)",display:"flex",alignItems:"center",gap:"4px",padding:"6px 8px",background:"rgba(12, 12, 14, 0.90)",backdropFilter:"blur(12px)",border:"1px solid #222225",borderRadius:"14px",boxShadow:"0 8px 32px rgba(0,0,0,0.5)",cursor:f?"grabbing":"grab",userSelect:"none",pointerEvents:"auto",opacity:v?1:0,transition:v?"opacity 300ms ease-out, transform 300ms ease-out":"none",...M},children:x.map(n=>o.jsx("button",{title:n.label,onClick:s=>{s.stopPropagation(),n.onClick()},style:{display:"flex",alignItems:"center",justifyContent:"center",width:"36px",height:"36px",borderRadius:"10px",border:"none",cursor:"pointer",background:n.active?"#6366F1":"transparent",color:n.active?"#fff":"#7E7E85",transition:"background 150ms ease, color 150ms ease"},onMouseEnter:s=>{n.active||(s.currentTarget.style.background="rgba(255,255,255,0.06)",s.currentTarget.style.color="#EDEDEF")},onMouseLeave:s=>{n.active||(s.currentTarget.style.background="transparent",s.currentTarget.style.color="#7E7E85")},children:n.icon},n.label))})}function j({data:t}){const a=t.className?`${t.tagName}.${t.className.split(/\s+/)[0]}`:t.tagName,c=a.length>35?a.slice(0,35)+"...":a;return o.jsxs("div",{style:{position:"fixed",left:t.x+12,top:t.y+12,background:"rgba(12, 12, 14, 0.95)",color:"#EDEDEF",fontFamily:"'JetBrains Mono', monospace",fontSize:"11px",lineHeight:"16px",padding:"4px 8px",borderRadius:"6px",boxShadow:"0 4px 12px rgba(0,0,0,0.4)",pointerEvents:"none",zIndex:2147483647,whiteSpace:"nowrap",opacity:1,transition:"opacity 100ms ease-out"},children:[o.jsx("span",{style:{color:"#818CF8"},children:c}),o.jsxs("span",{style:{color:"#7E7E85",marginLeft:"8px"},children:[t.width," x ",t.height]})]})}function R(){const[t,a]=e.useState("off"),[c,d]=e.useState(null),[g,h]=e.useState(!1);e.useEffect(()=>{const r=l=>{const i=l.detail;a(i.mode)};return document.addEventListener("pixellens:mode-change",r),()=>document.removeEventListener("pixellens:mode-change",r)},[]),e.useEffect(()=>{if(t!=="inspect"){d(null);return}const r=l=>{var x;const i=l.target;if(!i||I(i)){d(null);return}const u=i.getBoundingClientRect(),E=((x=i.className)==null?void 0:x.toString())||"",M=E.length>30?E.slice(0,30)+"...":E;d({tagName:i.tagName.toLowerCase(),className:M,width:Math.round(u.width),height:Math.round(u.height),x:l.clientX,y:l.clientY})};return document.addEventListener("mousemove",r,{passive:!0}),()=>document.removeEventListener("mousemove",r)},[t]);const v=e.useCallback(r=>{if(r===t){a("off"),m(p.TOGGLE_INSPECT,{active:!1});return}a(r),r==="inspect"?m(p.TOGGLE_INSPECT,{active:!0}):r==="measure"&&(m(p.TOGGLE_INSPECT,{active:!1}),m(p.TOGGLE_MEASURE,{active:!0}))},[t]),L=e.useCallback(()=>{const r=!g;h(r),m(p.TOGGLE_GRID,{visible:r})},[g]),f=e.useCallback(()=>{m(p.SCAN_PAGE,void 0)},[]);return o.jsxs(o.Fragment,{children:[o.jsx(N,{mode:t,gridVisible:g,onModeChange:v,onGridToggle:L,onScan:f}),c&&o.jsx(j,{data:c})]})}function I(t){let a=t;for(;a;){if(a.id==="pixellens-host")return!0;a=a.parentNode}return!1}function D(t){S.createRoot(t).render(o.jsx(R,{}))}export{D as mountContentApp}; diff --git a/dist/assets/Eyedropper.es-Cn4UL7iP.js b/dist/assets/Eyedropper.es-Cn4UL7iP.js new file mode 100644 index 0000000..092c029 --- /dev/null +++ b/dist/assets/Eyedropper.es-Cn4UL7iP.js @@ -0,0 +1 @@ +import{r as a,p as n}from"./Scan.es-D0n8eUjn.js";const r=new Map([["bold",a.createElement(a.Fragment,null,a.createElement("path",{d:"M228,67.24a39.77,39.77,0,0,0-12.51-28.52C199.91,24,174.71,24.5,159.29,39.93L142.48,56.84a28,28,0,0,0-35.64,3.29l-9,9a20,20,0,0,0-.73,27.49L48.9,144.84A43.76,43.76,0,0,0,37,185.28l-7.5,17.19a17.66,17.66,0,0,0,3.71,19.65,19.9,19.9,0,0,0,22.15,4.19l16.31-7.13a43.88,43.88,0,0,0,39.45-12.09l48.24-48.26a20,20,0,0,0,27.47-.73l9-9a28.06,28.06,0,0,0,3.26-35.72l17.23-17.33A39.69,39.69,0,0,0,228,67.24ZM94.15,190.11a20,20,0,0,1-20,5,11.93,11.93,0,0,0-8.32.47L57,199.38,60.69,191a12,12,0,0,0,.37-8.64,19.92,19.92,0,0,1,4.81-20.55l48.2-48.22,28.28,28.3Zm105.14-111-25.37,25.52a12,12,0,0,0,0,16.95l4.88,4.89a4,4,0,0,1,0,5.66l-6.14,6.15-55-55.05,6.14-6.14a4,4,0,0,1,5.65,0L134.35,82a12,12,0,0,0,8.49,3.51h0A12,12,0,0,0,151.34,82l24.94-25.08c6.3-6.3,16.48-6.63,22.71-.74a16,16,0,0,1,.3,23Z"}))],["duotone",a.createElement(a.Fragment,null,a.createElement("path",{d:"M207.8,87.6l-25.37,25.53,4.89,4.88a16,16,0,0,1,0,22.64l-9,9a8,8,0,0,1-11.32,0l-60.68-60.7a8,8,0,0,1,0-11.32l9-9a16,16,0,0,1,22.63,0l4.88,4.89,25-25.11c10.79-10.79,28.37-11.45,39.45-1A28,28,0,0,1,207.8,87.6Z",opacity:"0.2"}),a.createElement("path",{d:"M224,67.3a35.79,35.79,0,0,0-11.26-25.66c-14-13.28-36.72-12.78-50.62,1.13L142.8,62.2a24,24,0,0,0-33.14.77l-9,9a16,16,0,0,0,0,22.64l2,2.06-51,51a39.75,39.75,0,0,0-10.53,38l-8,18.41A13.68,13.68,0,0,0,36,219.3a15.92,15.92,0,0,0,17.71,3.35L71.23,215a39.89,39.89,0,0,0,37.06-10.75l51-51,2.06,2.06a16,16,0,0,0,22.62,0l9-9a24,24,0,0,0,.74-33.18l19.75-19.87A35.75,35.75,0,0,0,224,67.3ZM97,193a24,24,0,0,1-24,6,8,8,0,0,0-5.55.31l-18.1,7.91L57,189.41a8,8,0,0,0,.25-5.75A23.88,23.88,0,0,1,63,159l51-51,33.94,34ZM202.13,82l-25.37,25.52a8,8,0,0,0,0,11.3l4.89,4.89a8,8,0,0,1,0,11.32l-9,9L112,83.26l9-9a8,8,0,0,1,11.31,0l4.89,4.89a8,8,0,0,0,5.65,2.34h0a8,8,0,0,0,5.66-2.36l24.94-25.09c7.81-7.82,20.5-8.18,28.29-.81a20,20,0,0,1,.39,28.7Z"}))],["fill",a.createElement(a.Fragment,null,a.createElement("path",{d:"M224,67.3a35.79,35.79,0,0,0-11.26-25.66c-14-13.28-36.72-12.78-50.62,1.13L138.8,66.2a24,24,0,0,0-33.14.77l-5,5a16,16,0,0,0,0,22.64l2,2.06-51,51a39.75,39.75,0,0,0-10.53,38l-8,18.41A13.68,13.68,0,0,0,36,219.3a15.92,15.92,0,0,0,17.71,3.35L71.23,215a39.89,39.89,0,0,0,37.06-10.75l51-51,2.06,2.06a16,16,0,0,0,22.62,0l5-5a24,24,0,0,0,.74-33.18l23.75-23.87A35.75,35.75,0,0,0,224,67.3ZM97,193a24,24,0,0,1-24,6,8,8,0,0,0-5.55.31l-18.1,7.91L57,189.41a8,8,0,0,0,.25-5.75A23.88,23.88,0,0,1,63,159l51-51,33.94,34Z"}))],["light",a.createElement(a.Fragment,null,a.createElement("path",{d:"M222,67.34a33.81,33.81,0,0,0-10.64-24.25C198.12,30.56,176.68,31,163.54,44.18L142.82,65l-.63-.63a22,22,0,0,0-31.11,0l-9,9a14,14,0,0,0,0,19.81l3.47,3.47L53.14,149.1a37.79,37.79,0,0,0-9.84,36.73l-8.31,19a11.68,11.68,0,0,0,2.46,13A13.91,13.91,0,0,0,47.32,222,14.15,14.15,0,0,0,53,220.82L71,212.92a37.92,37.92,0,0,0,35.84-10.07l52.44-52.46,3.47,3.48a14,14,0,0,0,19.8,0l9-9a22,22,0,0,0,0-31.12l-.66-.66L212,91.85A33.76,33.76,0,0,0,222,67.34Zm-123.61,127a26,26,0,0,1-26,6.47,6,6,0,0,0-4.16.24l-20,8.75a2,2,0,0,1-2.09-.31l9.12-20.9a5.94,5.94,0,0,0,.19-4.31,25.88,25.88,0,0,1,6.26-26.72l52.44-52.45,36.76,36.78Zm105.16-111L178.17,108.9a6,6,0,0,0,0,8.47l4.88,4.89a10,10,0,0,1,0,14.15l-9,9a2,2,0,0,1-2.82,0l-60.69-60.7a2,2,0,0,1,0-2.83l9-9a10,10,0,0,1,14.14,0l4.89,4.89a6,6,0,0,0,4.24,1.75h0a6,6,0,0,0,4.25-1.77L172,52.66c8.58-8.58,22.52-9,31.08-.85a22,22,0,0,1,.44,31.57Z"}))],["regular",a.createElement(a.Fragment,null,a.createElement("path",{d:"M224,67.3a35.79,35.79,0,0,0-11.26-25.66c-14-13.28-36.72-12.78-50.62,1.13L142.8,62.2a24,24,0,0,0-33.14.77l-9,9a16,16,0,0,0,0,22.64l2,2.06-51,51a39.75,39.75,0,0,0-10.53,38l-8,18.41A13.68,13.68,0,0,0,36,219.3a15.92,15.92,0,0,0,17.71,3.35L71.23,215a39.89,39.89,0,0,0,37.06-10.75l51-51,2.06,2.06a16,16,0,0,0,22.62,0l9-9a24,24,0,0,0,.74-33.18l19.75-19.87A35.75,35.75,0,0,0,224,67.3ZM97,193a24,24,0,0,1-24,6,8,8,0,0,0-5.55.31l-18.1,7.91L57,189.41a8,8,0,0,0,.25-5.75A23.88,23.88,0,0,1,63,159l51-51,33.94,34ZM202.13,82l-25.37,25.52a8,8,0,0,0,0,11.3l4.89,4.89a8,8,0,0,1,0,11.32l-9,9L112,83.26l9-9a8,8,0,0,1,11.31,0l4.89,4.89a8,8,0,0,0,11.33,0l24.94-25.09c7.81-7.82,20.5-8.18,28.29-.81a20,20,0,0,1,.39,28.7Z"}))],["thin",a.createElement(a.Fragment,null,a.createElement("path",{d:"M220,67.37a31.82,31.82,0,0,0-10-22.82c-12.46-11.8-32.66-11.33-45,1.05L142.82,67.86l-2-2a20,20,0,0,0-28.28,0l-9,9a12,12,0,0,0,0,17l4.89,4.89L54.55,150.52A35.81,35.81,0,0,0,45.42,186l-8.6,19.7a9.7,9.7,0,0,0,2,10.79A12,12,0,0,0,52.15,219l18.72-8.18a35.9,35.9,0,0,0,34.59-9.37l53.86-53.87,4.88,4.89a12,12,0,0,0,17,0l9-9a20,20,0,0,0,0-28.3l-2.06-2.06,22.55-22.69A31.75,31.75,0,0,0,220,67.37ZM99.81,195.78a28,28,0,0,1-28,7,4,4,0,0,0-2.78.15l-20,8.75a4,4,0,0,1-4.43-.84,1.73,1.73,0,0,1-.36-1.93l9.19-21.06a4,4,0,0,0,.12-2.88,27.87,27.87,0,0,1,6.74-28.77l53.85-53.87,39.6,39.61Zm79.78-85.47a4,4,0,0,0,0,5.65l4.89,4.89a12,12,0,0,1,0,17l-9,9a4,4,0,0,1-5.66,0L109.18,86.1a4,4,0,0,1,0-5.66l9-9a12,12,0,0,1,17,0L140,76.36a4,4,0,0,0,2.83,1.17h0a4,4,0,0,0,2.83-1.18l25-25.1c9.33-9.34,24.52-9.73,33.87-.89A24,24,0,0,1,205,84.79Z"}))]]),l=a.forwardRef((e,t)=>a.createElement(n,{ref:t,...e,weights:r}));l.displayName="EyedropperIcon";const m=l;export{m as s}; diff --git a/dist/assets/Scan.es-D0n8eUjn.js b/dist/assets/Scan.es-D0n8eUjn.js new file mode 100644 index 0000000..9c24971 --- /dev/null +++ b/dist/assets/Scan.es-D0n8eUjn.js @@ -0,0 +1,49 @@ +function My(O){return O&&O.__esModule&&Object.prototype.hasOwnProperty.call(O,"default")?O.default:O}var ei={exports:{}},be={};/** + * @license React + * react-jsx-runtime.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var sy;function $2(){if(sy)return be;sy=1;var O=Symbol.for("react.transitional.element"),ml=Symbol.for("react.fragment");function k(o,fl,dl){var Tl=null;if(dl!==void 0&&(Tl=""+dl),fl.key!==void 0&&(Tl=""+fl.key),"key"in fl){dl={};for(var rl in fl)rl!=="key"&&(dl[rl]=fl[rl])}else dl=fl;return fl=dl.ref,{$$typeof:O,type:o,key:Tl,ref:fl!==void 0?fl:null,props:dl}}return be.Fragment=ml,be.jsx=k,be.jsxs=k,be}var hy;function F2(){return hy||(hy=1,ei.exports=$2()),ei.exports}var id=F2(),ni={exports:{}},B={};/** + * @license React + * react.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var oy;function k2(){if(oy)return B;oy=1;var O=Symbol.for("react.transitional.element"),ml=Symbol.for("react.portal"),k=Symbol.for("react.fragment"),o=Symbol.for("react.strict_mode"),fl=Symbol.for("react.profiler"),dl=Symbol.for("react.consumer"),Tl=Symbol.for("react.context"),rl=Symbol.for("react.forward_ref"),H=Symbol.for("react.suspense"),T=Symbol.for("react.memo"),J=Symbol.for("react.lazy"),N=Symbol.for("react.activity"),cl=Symbol.iterator;function Bl(y){return y===null||typeof y!="object"?null:(y=cl&&y[cl]||y["@@iterator"],typeof y=="function"?y:null)}var Rl={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},Yl=Object.assign,Ut={};function $l(y,A,_){this.props=y,this.context=A,this.refs=Ut,this.updater=_||Rl}$l.prototype.isReactComponent={},$l.prototype.setState=function(y,A){if(typeof y!="object"&&typeof y!="function"&&y!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,y,A,"setState")},$l.prototype.forceUpdate=function(y){this.updater.enqueueForceUpdate(this,y,"forceUpdate")};function Wt(){}Wt.prototype=$l.prototype;function ql(y,A,_){this.props=y,this.context=A,this.refs=Ut,this.updater=_||Rl}var ft=ql.prototype=new Wt;ft.constructor=ql,Yl(ft,$l.prototype),ft.isPureReactComponent=!0;var At=Array.isArray;function Xl(){}var L={H:null,A:null,T:null,S:null},Ql=Object.prototype.hasOwnProperty;function Tt(y,A,_){var D=_.ref;return{$$typeof:O,type:y,key:A,ref:D!==void 0?D:null,props:_}}function Qa(y,A){return Tt(y.type,A,y.props)}function Mt(y){return typeof y=="object"&&y!==null&&y.$$typeof===O}function jl(y){var A={"=":"=0",":":"=2"};return"$"+y.replace(/[=:]/g,function(_){return A[_]})}var Ea=/\/+/g;function Ht(y,A){return typeof y=="object"&&y!==null&&y.key!=null?jl(""+y.key):A.toString(36)}function gt(y){switch(y.status){case"fulfilled":return y.value;case"rejected":throw y.reason;default:switch(typeof y.status=="string"?y.then(Xl,Xl):(y.status="pending",y.then(function(A){y.status==="pending"&&(y.status="fulfilled",y.value=A)},function(A){y.status==="pending"&&(y.status="rejected",y.reason=A)})),y.status){case"fulfilled":return y.value;case"rejected":throw y.reason}}throw y}function b(y,A,_,D,Y){var X=typeof y;(X==="undefined"||X==="boolean")&&(y=null);var F=!1;if(y===null)F=!0;else switch(X){case"bigint":case"string":case"number":F=!0;break;case"object":switch(y.$$typeof){case O:case ml:F=!0;break;case J:return F=y._init,b(F(y._payload),A,_,D,Y)}}if(F)return Y=Y(y),F=D===""?"."+Ht(y,0):D,At(Y)?(_="",F!=null&&(_=F.replace(Ea,"$&/")+"/"),b(Y,A,_,"",function(Ou){return Ou})):Y!=null&&(Mt(Y)&&(Y=Qa(Y,_+(Y.key==null||y&&y.key===Y.key?"":(""+Y.key).replace(Ea,"$&/")+"/")+F)),A.push(Y)),1;F=0;var Zl=D===""?".":D+":";if(At(y))for(var ol=0;ol>>1,el=b[ll];if(0>>1;llfl(_,q))Dfl(Y,_)?(b[ll]=Y,b[D]=q,ll=D):(b[ll]=_,b[A]=q,ll=A);else if(Dfl(Y,q))b[ll]=Y,b[D]=q,ll=D;else break l}}return M}function fl(b,M){var q=b.sortIndex-M.sortIndex;return q!==0?q:b.id-M.id}if(O.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var dl=performance;O.unstable_now=function(){return dl.now()}}else{var Tl=Date,rl=Tl.now();O.unstable_now=function(){return Tl.now()-rl}}var H=[],T=[],J=1,N=null,cl=3,Bl=!1,Rl=!1,Yl=!1,Ut=!1,$l=typeof setTimeout=="function"?setTimeout:null,Wt=typeof clearTimeout=="function"?clearTimeout:null,ql=typeof setImmediate<"u"?setImmediate:null;function ft(b){for(var M=k(T);M!==null;){if(M.callback===null)o(T);else if(M.startTime<=b)o(T),M.sortIndex=M.expirationTime,ml(H,M);else break;M=k(T)}}function At(b){if(Yl=!1,ft(b),!Rl)if(k(H)!==null)Rl=!0,Xl||(Xl=!0,jl());else{var M=k(T);M!==null&>(At,M.startTime-b)}}var Xl=!1,L=-1,Ql=5,Tt=-1;function Qa(){return Ut?!0:!(O.unstable_now()-Ttb&&Qa());){var ll=N.callback;if(typeof ll=="function"){N.callback=null,cl=N.priorityLevel;var el=ll(N.expirationTime<=b);if(b=O.unstable_now(),typeof el=="function"){N.callback=el,ft(b),M=!0;break t}N===k(H)&&o(H),ft(b)}else o(H);N=k(H)}if(N!==null)M=!0;else{var y=k(T);y!==null&>(At,y.startTime-b),M=!1}}break l}finally{N=null,cl=q,Bl=!1}M=void 0}}finally{M?jl():Xl=!1}}}var jl;if(typeof ql=="function")jl=function(){ql(Mt)};else if(typeof MessageChannel<"u"){var Ea=new MessageChannel,Ht=Ea.port2;Ea.port1.onmessage=Mt,jl=function(){Ht.postMessage(null)}}else jl=function(){$l(Mt,0)};function gt(b,M){L=$l(function(){b(O.unstable_now())},M)}O.unstable_IdlePriority=5,O.unstable_ImmediatePriority=1,O.unstable_LowPriority=4,O.unstable_NormalPriority=3,O.unstable_Profiling=null,O.unstable_UserBlockingPriority=2,O.unstable_cancelCallback=function(b){b.callback=null},O.unstable_forceFrameRate=function(b){0>b||125ll?(b.sortIndex=q,ml(T,b),k(H)===null&&b===k(T)&&(Yl?(Wt(L),L=-1):Yl=!0,gt(At,q-ll))):(b.sortIndex=el,ml(H,b),Rl||Bl||(Rl=!0,Xl||(Xl=!0,jl()))),b},O.unstable_shouldYield=Qa,O.unstable_wrapCallback=function(b){var M=cl;return function(){var q=cl;cl=M;try{return b.apply(this,arguments)}finally{cl=q}}}})(ii)),ii}var by;function P2(){return by||(by=1,ci.exports=I2()),ci.exports}var vi={exports:{}},Cl={};/** + * @license React + * react-dom.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var zy;function ld(){if(zy)return Cl;zy=1;var O=yi();function ml(H){var T="https://react.dev/errors/"+H;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(O)}catch(ml){console.error(ml)}}return O(),vi.exports=ld(),vi.exports}/** + * @license React + * react-dom-client.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var Ay;function ad(){if(Ay)return ze;Ay=1;var O=P2(),ml=yi(),k=td();function o(l){var t="https://react.dev/errors/"+l;if(1el||(l.current=ll[el],ll[el]=null,el--)}function _(l,t){el++,ll[el]=l.current,l.current=t}var D=y(null),Y=y(null),X=y(null),F=y(null);function Zl(l,t){switch(_(X,t),_(Y,l),_(D,null),t.nodeType){case 9:case 11:l=(l=t.documentElement)&&(l=l.namespaceURI)?Yv(l):0;break;default:if(l=t.tagName,t=t.namespaceURI)t=Yv(t),l=Zv(t,l);else switch(l){case"svg":l=1;break;case"math":l=2;break;default:l=0}}A(D),_(D,l)}function ol(){A(D),A(Y),A(X)}function Ou(l){l.memoizedState!==null&&_(F,l);var t=D.current,a=Zv(t,l.type);t!==a&&(_(Y,l),_(D,a))}function Ee(l){Y.current===l&&(A(D),A(Y)),F.current===l&&(A(F),he._currentValue=q)}var Xn,di;function Aa(l){if(Xn===void 0)try{throw Error()}catch(a){var t=a.stack.trim().match(/\n( *(at )?)/);Xn=t&&t[1]||"",di=-1)":-1e||i[u]!==s[e]){var g=` +`+i[u].replace(" at new "," at ");return l.displayName&&g.includes("")&&(g=g.replace("",l.displayName)),g}while(1<=u&&0<=e);break}}}finally{Qn=!1,Error.prepareStackTrace=a}return(a=l?l.displayName||l.name:"")?Aa(a):""}function ry(l,t){switch(l.tag){case 26:case 27:case 5:return Aa(l.type);case 16:return Aa("Lazy");case 13:return l.child!==t&&t!==null?Aa("Suspense Fallback"):Aa("Suspense");case 19:return Aa("SuspenseList");case 0:case 15:return jn(l.type,!1);case 11:return jn(l.type.render,!1);case 1:return jn(l.type,!0);case 31:return Aa("Activity");default:return""}}function si(l){try{var t="",a=null;do t+=ry(l,a),a=l,l=l.return;while(l);return t}catch(u){return` +Error generating stack: `+u.message+` +`+u.stack}}var Vn=Object.prototype.hasOwnProperty,xn=O.unstable_scheduleCallback,Ln=O.unstable_cancelCallback,Dy=O.unstable_shouldYield,Uy=O.unstable_requestPaint,Fl=O.unstable_now,Hy=O.unstable_getCurrentPriorityLevel,hi=O.unstable_ImmediatePriority,oi=O.unstable_UserBlockingPriority,Ae=O.unstable_NormalPriority,py=O.unstable_LowPriority,Si=O.unstable_IdlePriority,Ny=O.log,Ry=O.unstable_setDisableYieldValue,ru=null,kl=null;function $t(l){if(typeof Ny=="function"&&Ry(l),kl&&typeof kl.setStrictMode=="function")try{kl.setStrictMode(ru,l)}catch{}}var Il=Math.clz32?Math.clz32:By,qy=Math.log,Cy=Math.LN2;function By(l){return l>>>=0,l===0?32:31-(qy(l)/Cy|0)|0}var Te=256,Me=262144,_e=4194304;function Ta(l){var t=l&42;if(t!==0)return t;switch(l&-l){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return l&261888;case 262144:case 524288:case 1048576:case 2097152:return l&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return l&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return l}}function Oe(l,t,a){var u=l.pendingLanes;if(u===0)return 0;var e=0,n=l.suspendedLanes,f=l.pingedLanes;l=l.warmLanes;var c=u&134217727;return c!==0?(u=c&~n,u!==0?e=Ta(u):(f&=c,f!==0?e=Ta(f):a||(a=c&~l,a!==0&&(e=Ta(a))))):(c=u&~n,c!==0?e=Ta(c):f!==0?e=Ta(f):a||(a=u&~l,a!==0&&(e=Ta(a)))),e===0?0:t!==0&&t!==e&&(t&n)===0&&(n=e&-e,a=t&-t,n>=a||n===32&&(a&4194048)!==0)?t:e}function Du(l,t){return(l.pendingLanes&~(l.suspendedLanes&~l.pingedLanes)&t)===0}function Yy(l,t){switch(l){case 1:case 2:case 4:case 8:case 64:return t+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function gi(){var l=_e;return _e<<=1,(_e&62914560)===0&&(_e=4194304),l}function Kn(l){for(var t=[],a=0;31>a;a++)t.push(l);return t}function Uu(l,t){l.pendingLanes|=t,t!==268435456&&(l.suspendedLanes=0,l.pingedLanes=0,l.warmLanes=0)}function Zy(l,t,a,u,e,n){var f=l.pendingLanes;l.pendingLanes=a,l.suspendedLanes=0,l.pingedLanes=0,l.warmLanes=0,l.expiredLanes&=a,l.entangledLanes&=a,l.errorRecoveryDisabledLanes&=a,l.shellSuspendCounter=0;var c=l.entanglements,i=l.expirationTimes,s=l.hiddenUpdates;for(a=f&~a;0"u")return null;try{return l.activeElement||l.body}catch{return l.body}}var xy=/[\n"\\]/g;function it(l){return l.replace(xy,function(t){return"\\"+t.charCodeAt(0).toString(16)+" "})}function kn(l,t,a,u,e,n,f,c){l.name="",f!=null&&typeof f!="function"&&typeof f!="symbol"&&typeof f!="boolean"?l.type=f:l.removeAttribute("type"),t!=null?f==="number"?(t===0&&l.value===""||l.value!=t)&&(l.value=""+ct(t)):l.value!==""+ct(t)&&(l.value=""+ct(t)):f!=="submit"&&f!=="reset"||l.removeAttribute("value"),t!=null?In(l,f,ct(t)):a!=null?In(l,f,ct(a)):u!=null&&l.removeAttribute("value"),e==null&&n!=null&&(l.defaultChecked=!!n),e!=null&&(l.checked=e&&typeof e!="function"&&typeof e!="symbol"),c!=null&&typeof c!="function"&&typeof c!="symbol"&&typeof c!="boolean"?l.name=""+ct(c):l.removeAttribute("name")}function pi(l,t,a,u,e,n,f,c){if(n!=null&&typeof n!="function"&&typeof n!="symbol"&&typeof n!="boolean"&&(l.type=n),t!=null||a!=null){if(!(n!=="submit"&&n!=="reset"||t!=null)){Fn(l);return}a=a!=null?""+ct(a):"",t=t!=null?""+ct(t):a,c||t===l.value||(l.value=t),l.defaultValue=t}u=u??e,u=typeof u!="function"&&typeof u!="symbol"&&!!u,l.checked=c?l.checked:!!u,l.defaultChecked=!!u,f!=null&&typeof f!="function"&&typeof f!="symbol"&&typeof f!="boolean"&&(l.name=f),Fn(l)}function In(l,t,a){t==="number"&&Ue(l.ownerDocument)===l||l.defaultValue===""+a||(l.defaultValue=""+a)}function Ja(l,t,a,u){if(l=l.options,t){t={};for(var e=0;e"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),uf=!1;if(Rt)try{var Ru={};Object.defineProperty(Ru,"passive",{get:function(){uf=!0}}),window.addEventListener("test",Ru,Ru),window.removeEventListener("test",Ru,Ru)}catch{uf=!1}var kt=null,ef=null,pe=null;function Zi(){if(pe)return pe;var l,t=ef,a=t.length,u,e="value"in kt?kt.value:kt.textContent,n=e.length;for(l=0;l=Bu),xi=" ",Li=!1;function Ki(l,t){switch(l){case"keyup":return gm.indexOf(t.keyCode)!==-1;case"keydown":return t.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Ji(l){return l=l.detail,typeof l=="object"&&"data"in l?l.data:null}var Fa=!1;function zm(l,t){switch(l){case"compositionend":return Ji(t);case"keypress":return t.which!==32?null:(Li=!0,xi);case"textInput":return l=t.data,l===xi&&Li?null:l;default:return null}}function Em(l,t){if(Fa)return l==="compositionend"||!yf&&Ki(l,t)?(l=Zi(),pe=ef=kt=null,Fa=!1,l):null;switch(l){case"paste":return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:a,offset:t-l};l=u}l:{for(;a;){if(a.nextSibling){a=a.nextSibling;break l}a=a.parentNode}a=void 0}a=l0(a)}}function a0(l,t){return l&&t?l===t?!0:l&&l.nodeType===3?!1:t&&t.nodeType===3?a0(l,t.parentNode):"contains"in l?l.contains(t):l.compareDocumentPosition?!!(l.compareDocumentPosition(t)&16):!1:!1}function u0(l){l=l!=null&&l.ownerDocument!=null&&l.ownerDocument.defaultView!=null?l.ownerDocument.defaultView:window;for(var t=Ue(l.document);t instanceof l.HTMLIFrameElement;){try{var a=typeof t.contentWindow.location.href=="string"}catch{a=!1}if(a)l=t.contentWindow;else break;t=Ue(l.document)}return t}function sf(l){var t=l&&l.nodeName&&l.nodeName.toLowerCase();return t&&(t==="input"&&(l.type==="text"||l.type==="search"||l.type==="tel"||l.type==="url"||l.type==="password")||t==="textarea"||l.contentEditable==="true")}var Um=Rt&&"documentMode"in document&&11>=document.documentMode,ka=null,hf=null,Xu=null,of=!1;function e0(l,t,a){var u=a.window===a?a.document:a.nodeType===9?a:a.ownerDocument;of||ka==null||ka!==Ue(u)||(u=ka,"selectionStart"in u&&sf(u)?u={start:u.selectionStart,end:u.selectionEnd}:(u=(u.ownerDocument&&u.ownerDocument.defaultView||window).getSelection(),u={anchorNode:u.anchorNode,anchorOffset:u.anchorOffset,focusNode:u.focusNode,focusOffset:u.focusOffset}),Xu&&Gu(Xu,u)||(Xu=u,u=_n(hf,"onSelect"),0>=f,e-=f,_t=1<<32-Il(t)+e|a<G?(x=U,U=null):x=U.sibling;var W=h(m,U,d[G],z);if(W===null){U===null&&(U=x);break}l&&U&&W.alternate===null&&t(m,U),v=n(W,v,G),w===null?p=W:w.sibling=W,w=W,U=x}if(G===d.length)return a(m,U),K&&Ct(m,G),p;if(U===null){for(;GG?(x=U,U=null):x=U.sibling;var za=h(m,U,W.value,z);if(za===null){U===null&&(U=x);break}l&&U&&za.alternate===null&&t(m,U),v=n(za,v,G),w===null?p=za:w.sibling=za,w=za,U=x}if(W.done)return a(m,U),K&&Ct(m,G),p;if(U===null){for(;!W.done;G++,W=d.next())W=E(m,W.value,z),W!==null&&(v=n(W,v,G),w===null?p=W:w.sibling=W,w=W);return K&&Ct(m,G),p}for(U=u(U);!W.done;G++,W=d.next())W=S(U,m,G,W.value,z),W!==null&&(l&&W.alternate!==null&&U.delete(W.key===null?G:W.key),v=n(W,v,G),w===null?p=W:w.sibling=W,w=W);return l&&U.forEach(function(W2){return t(m,W2)}),K&&Ct(m,G),p}function ul(m,v,d,z){if(typeof d=="object"&&d!==null&&d.type===Yl&&d.key===null&&(d=d.props.children),typeof d=="object"&&d!==null){switch(d.$$typeof){case Bl:l:{for(var p=d.key;v!==null;){if(v.key===p){if(p=d.type,p===Yl){if(v.tag===7){a(m,v.sibling),z=e(v,d.props.children),z.return=m,m=z;break l}}else if(v.elementType===p||typeof p=="object"&&p!==null&&p.$$typeof===Ql&&qa(p)===v.type){a(m,v.sibling),z=e(v,d.props),Ku(z,d),z.return=m,m=z;break l}a(m,v);break}else t(m,v);v=v.sibling}d.type===Yl?(z=Ua(d.props.children,m.mode,z,d.key),z.return=m,m=z):(z=Qe(d.type,d.key,d.props,null,m.mode,z),Ku(z,d),z.return=m,m=z)}return f(m);case Rl:l:{for(p=d.key;v!==null;){if(v.key===p)if(v.tag===4&&v.stateNode.containerInfo===d.containerInfo&&v.stateNode.implementation===d.implementation){a(m,v.sibling),z=e(v,d.children||[]),z.return=m,m=z;break l}else{a(m,v);break}else t(m,v);v=v.sibling}z=Tf(d,m.mode,z),z.return=m,m=z}return f(m);case Ql:return d=qa(d),ul(m,v,d,z)}if(gt(d))return r(m,v,d,z);if(jl(d)){if(p=jl(d),typeof p!="function")throw Error(o(150));return d=p.call(d),R(m,v,d,z)}if(typeof d.then=="function")return ul(m,v,we(d),z);if(d.$$typeof===ql)return ul(m,v,xe(m,d),z);We(m,d)}return typeof d=="string"&&d!==""||typeof d=="number"||typeof d=="bigint"?(d=""+d,v!==null&&v.tag===6?(a(m,v.sibling),z=e(v,d),z.return=m,m=z):(a(m,v),z=Af(d,m.mode,z),z.return=m,m=z),f(m)):a(m,v)}return function(m,v,d,z){try{Lu=0;var p=ul(m,v,d,z);return iu=null,p}catch(U){if(U===cu||U===Ke)throw U;var w=lt(29,U,null,m.mode);return w.lanes=z,w.return=m,w}finally{}}}var Ba=D0(!0),U0=D0(!1),aa=!1;function Cf(l){l.updateQueue={baseState:l.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function Bf(l,t){l=l.updateQueue,t.updateQueue===l&&(t.updateQueue={baseState:l.baseState,firstBaseUpdate:l.firstBaseUpdate,lastBaseUpdate:l.lastBaseUpdate,shared:l.shared,callbacks:null})}function ua(l){return{lane:l,tag:0,payload:null,callback:null,next:null}}function ea(l,t,a){var u=l.updateQueue;if(u===null)return null;if(u=u.shared,($&2)!==0){var e=u.pending;return e===null?t.next=t:(t.next=e.next,e.next=t),u.pending=t,t=Xe(l),m0(l,null,a),t}return Ge(l,u,t,a),Xe(l)}function Ju(l,t,a){if(t=t.updateQueue,t!==null&&(t=t.shared,(a&4194048)!==0)){var u=t.lanes;u&=l.pendingLanes,a|=u,t.lanes=a,zi(l,a)}}function Yf(l,t){var a=l.updateQueue,u=l.alternate;if(u!==null&&(u=u.updateQueue,a===u)){var e=null,n=null;if(a=a.firstBaseUpdate,a!==null){do{var f={lane:a.lane,tag:a.tag,payload:a.payload,callback:null,next:null};n===null?e=n=f:n=n.next=f,a=a.next}while(a!==null);n===null?e=n=t:n=n.next=t}else e=n=t;a={baseState:u.baseState,firstBaseUpdate:e,lastBaseUpdate:n,shared:u.shared,callbacks:u.callbacks},l.updateQueue=a;return}l=a.lastBaseUpdate,l===null?a.firstBaseUpdate=t:l.next=t,a.lastBaseUpdate=t}var Zf=!1;function wu(){if(Zf){var l=fu;if(l!==null)throw l}}function Wu(l,t,a,u){Zf=!1;var e=l.updateQueue;aa=!1;var n=e.firstBaseUpdate,f=e.lastBaseUpdate,c=e.shared.pending;if(c!==null){e.shared.pending=null;var i=c,s=i.next;i.next=null,f===null?n=s:f.next=s,f=i;var g=l.alternate;g!==null&&(g=g.updateQueue,c=g.lastBaseUpdate,c!==f&&(c===null?g.firstBaseUpdate=s:c.next=s,g.lastBaseUpdate=i))}if(n!==null){var E=e.baseState;f=0,g=s=i=null,c=n;do{var h=c.lane&-536870913,S=h!==c.lane;if(S?(V&h)===h:(u&h)===h){h!==0&&h===nu&&(Zf=!0),g!==null&&(g=g.next={lane:0,tag:c.tag,payload:c.payload,callback:null,next:null});l:{var r=l,R=c;h=t;var ul=a;switch(R.tag){case 1:if(r=R.payload,typeof r=="function"){E=r.call(ul,E,h);break l}E=r;break l;case 3:r.flags=r.flags&-65537|128;case 0:if(r=R.payload,h=typeof r=="function"?r.call(ul,E,h):r,h==null)break l;E=N({},E,h);break l;case 2:aa=!0}}h=c.callback,h!==null&&(l.flags|=64,S&&(l.flags|=8192),S=e.callbacks,S===null?e.callbacks=[h]:S.push(h))}else S={lane:h,tag:c.tag,payload:c.payload,callback:c.callback,next:null},g===null?(s=g=S,i=E):g=g.next=S,f|=h;if(c=c.next,c===null){if(c=e.shared.pending,c===null)break;S=c,c=S.next,S.next=null,e.lastBaseUpdate=S,e.shared.pending=null}}while(!0);g===null&&(i=E),e.baseState=i,e.firstBaseUpdate=s,e.lastBaseUpdate=g,n===null&&(e.shared.lanes=0),va|=f,l.lanes=f,l.memoizedState=E}}function H0(l,t){if(typeof l!="function")throw Error(o(191,l));l.call(t)}function p0(l,t){var a=l.callbacks;if(a!==null)for(l.callbacks=null,l=0;ln?n:8;var f=b.T,c={};b.T=c,ac(l,!1,t,a);try{var i=e(),s=b.S;if(s!==null&&s(c,i),i!==null&&typeof i=="object"&&typeof i.then=="function"){var g=Zm(i,u);ku(l,t,g,nt(l))}else ku(l,t,u,nt(l))}catch(E){ku(l,t,{then:function(){},status:"rejected",reason:E},nt())}finally{M.p=n,f!==null&&c.types!==null&&(f.types=c.types),b.T=f}}function xm(){}function lc(l,t,a,u){if(l.tag!==5)throw Error(o(476));var e=i1(l).queue;c1(l,e,t,q,a===null?xm:function(){return v1(l),a(u)})}function i1(l){var t=l.memoizedState;if(t!==null)return t;t={memoizedState:q,baseState:q,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Gt,lastRenderedState:q},next:null};var a={};return t.next={memoizedState:a,baseState:a,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Gt,lastRenderedState:a},next:null},l.memoizedState=t,l=l.alternate,l!==null&&(l.memoizedState=t),t}function v1(l){var t=i1(l);t.next===null&&(t=l.alternate.memoizedState),ku(l,t.next.queue,{},nt())}function tc(){return Hl(he)}function y1(){return gl().memoizedState}function m1(){return gl().memoizedState}function Lm(l){for(var t=l.return;t!==null;){switch(t.tag){case 24:case 3:var a=nt();l=ua(a);var u=ea(t,l,a);u!==null&&(Wl(u,t,a),Ju(u,t,a)),t={cache:pf()},l.payload=t;return}t=t.return}}function Km(l,t,a){var u=nt();a={lane:u,revertLane:0,gesture:null,action:a,hasEagerState:!1,eagerState:null,next:null},en(l)?s1(t,a):(a=zf(l,t,a,u),a!==null&&(Wl(a,l,u),h1(a,t,u)))}function d1(l,t,a){var u=nt();ku(l,t,a,u)}function ku(l,t,a,u){var e={lane:u,revertLane:0,gesture:null,action:a,hasEagerState:!1,eagerState:null,next:null};if(en(l))s1(t,e);else{var n=l.alternate;if(l.lanes===0&&(n===null||n.lanes===0)&&(n=t.lastRenderedReducer,n!==null))try{var f=t.lastRenderedState,c=n(f,a);if(e.hasEagerState=!0,e.eagerState=c,Pl(c,f))return Ge(l,t,e,0),nl===null&&Ze(),!1}catch{}finally{}if(a=zf(l,t,e,u),a!==null)return Wl(a,l,u),h1(a,t,u),!0}return!1}function ac(l,t,a,u){if(u={lane:2,revertLane:Cc(),gesture:null,action:u,hasEagerState:!1,eagerState:null,next:null},en(l)){if(t)throw Error(o(479))}else t=zf(l,a,u,2),t!==null&&Wl(t,l,2)}function en(l){var t=l.alternate;return l===Z||t!==null&&t===Z}function s1(l,t){yu=ke=!0;var a=l.pending;a===null?t.next=t:(t.next=a.next,a.next=t),l.pending=t}function h1(l,t,a){if((a&4194048)!==0){var u=t.lanes;u&=l.pendingLanes,a|=u,t.lanes=a,zi(l,a)}}var Iu={readContext:Hl,use:ln,useCallback:sl,useContext:sl,useEffect:sl,useImperativeHandle:sl,useLayoutEffect:sl,useInsertionEffect:sl,useMemo:sl,useReducer:sl,useRef:sl,useState:sl,useDebugValue:sl,useDeferredValue:sl,useTransition:sl,useSyncExternalStore:sl,useId:sl,useHostTransitionStatus:sl,useFormState:sl,useActionState:sl,useOptimistic:sl,useMemoCache:sl,useCacheRefresh:sl};Iu.useEffectEvent=sl;var o1={readContext:Hl,use:ln,useCallback:function(l,t){return Gl().memoizedState=[l,t===void 0?null:t],l},useContext:Hl,useEffect:I0,useImperativeHandle:function(l,t,a){a=a!=null?a.concat([l]):null,an(4194308,4,a1.bind(null,t,l),a)},useLayoutEffect:function(l,t){return an(4194308,4,l,t)},useInsertionEffect:function(l,t){an(4,2,l,t)},useMemo:function(l,t){var a=Gl();t=t===void 0?null:t;var u=l();if(Ya){$t(!0);try{l()}finally{$t(!1)}}return a.memoizedState=[u,t],u},useReducer:function(l,t,a){var u=Gl();if(a!==void 0){var e=a(t);if(Ya){$t(!0);try{a(t)}finally{$t(!1)}}}else e=t;return u.memoizedState=u.baseState=e,l={pending:null,lanes:0,dispatch:null,lastRenderedReducer:l,lastRenderedState:e},u.queue=l,l=l.dispatch=Km.bind(null,Z,l),[u.memoizedState,l]},useRef:function(l){var t=Gl();return l={current:l},t.memoizedState=l},useState:function(l){l=$f(l);var t=l.queue,a=d1.bind(null,Z,t);return t.dispatch=a,[l.memoizedState,a]},useDebugValue:If,useDeferredValue:function(l,t){var a=Gl();return Pf(a,l,t)},useTransition:function(){var l=$f(!1);return l=c1.bind(null,Z,l.queue,!0,!1),Gl().memoizedState=l,[!1,l]},useSyncExternalStore:function(l,t,a){var u=Z,e=Gl();if(K){if(a===void 0)throw Error(o(407));a=a()}else{if(a=t(),nl===null)throw Error(o(349));(V&127)!==0||Y0(u,t,a)}e.memoizedState=a;var n={value:a,getSnapshot:t};return e.queue=n,I0(G0.bind(null,u,n,l),[l]),u.flags|=2048,du(9,{destroy:void 0},Z0.bind(null,u,n,a,t),null),a},useId:function(){var l=Gl(),t=nl.identifierPrefix;if(K){var a=Ot,u=_t;a=(u&~(1<<32-Il(u)-1)).toString(32)+a,t="_"+t+"R_"+a,a=Ie++,0<\/script>",n=n.removeChild(n.firstChild);break;case"select":n=typeof u.is=="string"?f.createElement("select",{is:u.is}):f.createElement("select"),u.multiple?n.multiple=!0:u.size&&(n.size=u.size);break;default:n=typeof u.is=="string"?f.createElement(e,{is:u.is}):f.createElement(e)}}n[Dl]=t,n[Vl]=u;l:for(f=t.child;f!==null;){if(f.tag===5||f.tag===6)n.appendChild(f.stateNode);else if(f.tag!==4&&f.tag!==27&&f.child!==null){f.child.return=f,f=f.child;continue}if(f===t)break l;for(;f.sibling===null;){if(f.return===null||f.return===t)break l;f=f.return}f.sibling.return=f.return,f=f.sibling}t.stateNode=n;l:switch(Nl(n,e,u),e){case"button":case"input":case"select":case"textarea":u=!!u.autoFocus;break l;case"img":u=!0;break l;default:u=!1}u&&Qt(t)}}return vl(t),Sc(t,t.type,l===null?null:l.memoizedProps,t.pendingProps,a),null;case 6:if(l&&t.stateNode!=null)l.memoizedProps!==u&&Qt(t);else{if(typeof u!="string"&&t.stateNode===null)throw Error(o(166));if(l=X.current,uu(t)){if(l=t.stateNode,a=t.memoizedProps,u=null,e=Ul,e!==null)switch(e.tag){case 27:case 5:u=e.memoizedProps}l[Dl]=t,l=!!(l.nodeValue===a||u!==null&&u.suppressHydrationWarning===!0||Cv(l.nodeValue,a)),l||la(t,!0)}else l=On(l).createTextNode(u),l[Dl]=t,t.stateNode=l}return vl(t),null;case 31:if(a=t.memoizedState,l===null||l.memoizedState!==null){if(u=uu(t),a!==null){if(l===null){if(!u)throw Error(o(318));if(l=t.memoizedState,l=l!==null?l.dehydrated:null,!l)throw Error(o(557));l[Dl]=t}else Ha(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;vl(t),l=!1}else a=rf(),l!==null&&l.memoizedState!==null&&(l.memoizedState.hydrationErrors=a),l=!0;if(!l)return t.flags&256?(at(t),t):(at(t),null);if((t.flags&128)!==0)throw Error(o(558))}return vl(t),null;case 13:if(u=t.memoizedState,l===null||l.memoizedState!==null&&l.memoizedState.dehydrated!==null){if(e=uu(t),u!==null&&u.dehydrated!==null){if(l===null){if(!e)throw Error(o(318));if(e=t.memoizedState,e=e!==null?e.dehydrated:null,!e)throw Error(o(317));e[Dl]=t}else Ha(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;vl(t),e=!1}else e=rf(),l!==null&&l.memoizedState!==null&&(l.memoizedState.hydrationErrors=e),e=!0;if(!e)return t.flags&256?(at(t),t):(at(t),null)}return at(t),(t.flags&128)!==0?(t.lanes=a,t):(a=u!==null,l=l!==null&&l.memoizedState!==null,a&&(u=t.child,e=null,u.alternate!==null&&u.alternate.memoizedState!==null&&u.alternate.memoizedState.cachePool!==null&&(e=u.alternate.memoizedState.cachePool.pool),n=null,u.memoizedState!==null&&u.memoizedState.cachePool!==null&&(n=u.memoizedState.cachePool.pool),n!==e&&(u.flags|=2048)),a!==l&&a&&(t.child.flags|=8192),yn(t,t.updateQueue),vl(t),null);case 4:return ol(),l===null&&Gc(t.stateNode.containerInfo),vl(t),null;case 10:return Yt(t.type),vl(t),null;case 19:if(A(Sl),u=t.memoizedState,u===null)return vl(t),null;if(e=(t.flags&128)!==0,n=u.rendering,n===null)if(e)le(u,!1);else{if(hl!==0||l!==null&&(l.flags&128)!==0)for(l=t.child;l!==null;){if(n=Fe(l),n!==null){for(t.flags|=128,le(u,!1),l=n.updateQueue,t.updateQueue=l,yn(t,l),t.subtreeFlags=0,l=a,a=t.child;a!==null;)d0(a,l),a=a.sibling;return _(Sl,Sl.current&1|2),K&&Ct(t,u.treeForkCount),t.child}l=l.sibling}u.tail!==null&&Fl()>on&&(t.flags|=128,e=!0,le(u,!1),t.lanes=4194304)}else{if(!e)if(l=Fe(n),l!==null){if(t.flags|=128,e=!0,l=l.updateQueue,t.updateQueue=l,yn(t,l),le(u,!0),u.tail===null&&u.tailMode==="hidden"&&!n.alternate&&!K)return vl(t),null}else 2*Fl()-u.renderingStartTime>on&&a!==536870912&&(t.flags|=128,e=!0,le(u,!1),t.lanes=4194304);u.isBackwards?(n.sibling=t.child,t.child=n):(l=u.last,l!==null?l.sibling=n:t.child=n,u.last=n)}return u.tail!==null?(l=u.tail,u.rendering=l,u.tail=l.sibling,u.renderingStartTime=Fl(),l.sibling=null,a=Sl.current,_(Sl,e?a&1|2:a&1),K&&Ct(t,u.treeForkCount),l):(vl(t),null);case 22:case 23:return at(t),Xf(),u=t.memoizedState!==null,l!==null?l.memoizedState!==null!==u&&(t.flags|=8192):u&&(t.flags|=8192),u?(a&536870912)!==0&&(t.flags&128)===0&&(vl(t),t.subtreeFlags&6&&(t.flags|=8192)):vl(t),a=t.updateQueue,a!==null&&yn(t,a.retryQueue),a=null,l!==null&&l.memoizedState!==null&&l.memoizedState.cachePool!==null&&(a=l.memoizedState.cachePool.pool),u=null,t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(u=t.memoizedState.cachePool.pool),u!==a&&(t.flags|=2048),l!==null&&A(Ra),null;case 24:return a=null,l!==null&&(a=l.memoizedState.cache),t.memoizedState.cache!==a&&(t.flags|=2048),Yt(bl),vl(t),null;case 25:return null;case 30:return null}throw Error(o(156,t.tag))}function Fm(l,t){switch(_f(t),t.tag){case 1:return l=t.flags,l&65536?(t.flags=l&-65537|128,t):null;case 3:return Yt(bl),ol(),l=t.flags,(l&65536)!==0&&(l&128)===0?(t.flags=l&-65537|128,t):null;case 26:case 27:case 5:return Ee(t),null;case 31:if(t.memoizedState!==null){if(at(t),t.alternate===null)throw Error(o(340));Ha()}return l=t.flags,l&65536?(t.flags=l&-65537|128,t):null;case 13:if(at(t),l=t.memoizedState,l!==null&&l.dehydrated!==null){if(t.alternate===null)throw Error(o(340));Ha()}return l=t.flags,l&65536?(t.flags=l&-65537|128,t):null;case 19:return A(Sl),null;case 4:return ol(),null;case 10:return Yt(t.type),null;case 22:case 23:return at(t),Xf(),l!==null&&A(Ra),l=t.flags,l&65536?(t.flags=l&-65537|128,t):null;case 24:return Yt(bl),null;case 25:return null;default:return null}}function X1(l,t){switch(_f(t),t.tag){case 3:Yt(bl),ol();break;case 26:case 27:case 5:Ee(t);break;case 4:ol();break;case 31:t.memoizedState!==null&&at(t);break;case 13:at(t);break;case 19:A(Sl);break;case 10:Yt(t.type);break;case 22:case 23:at(t),Xf(),l!==null&&A(Ra);break;case 24:Yt(bl)}}function te(l,t){try{var a=t.updateQueue,u=a!==null?a.lastEffect:null;if(u!==null){var e=u.next;a=e;do{if((a.tag&l)===l){u=void 0;var n=a.create,f=a.inst;u=n(),f.destroy=u}a=a.next}while(a!==e)}}catch(c){P(t,t.return,c)}}function ca(l,t,a){try{var u=t.updateQueue,e=u!==null?u.lastEffect:null;if(e!==null){var n=e.next;u=n;do{if((u.tag&l)===l){var f=u.inst,c=f.destroy;if(c!==void 0){f.destroy=void 0,e=t;var i=a,s=c;try{s()}catch(g){P(e,i,g)}}}u=u.next}while(u!==n)}}catch(g){P(t,t.return,g)}}function Q1(l){var t=l.updateQueue;if(t!==null){var a=l.stateNode;try{p0(t,a)}catch(u){P(l,l.return,u)}}}function j1(l,t,a){a.props=Za(l.type,l.memoizedProps),a.state=l.memoizedState;try{a.componentWillUnmount()}catch(u){P(l,t,u)}}function ae(l,t){try{var a=l.ref;if(a!==null){switch(l.tag){case 26:case 27:case 5:var u=l.stateNode;break;case 30:u=l.stateNode;break;default:u=l.stateNode}typeof a=="function"?l.refCleanup=a(u):a.current=u}}catch(e){P(l,t,e)}}function rt(l,t){var a=l.ref,u=l.refCleanup;if(a!==null)if(typeof u=="function")try{u()}catch(e){P(l,t,e)}finally{l.refCleanup=null,l=l.alternate,l!=null&&(l.refCleanup=null)}else if(typeof a=="function")try{a(null)}catch(e){P(l,t,e)}else a.current=null}function V1(l){var t=l.type,a=l.memoizedProps,u=l.stateNode;try{l:switch(t){case"button":case"input":case"select":case"textarea":a.autoFocus&&u.focus();break l;case"img":a.src?u.src=a.src:a.srcSet&&(u.srcset=a.srcSet)}}catch(e){P(l,l.return,e)}}function gc(l,t,a){try{var u=l.stateNode;b2(u,l.type,a,t),u[Vl]=t}catch(e){P(l,l.return,e)}}function x1(l){return l.tag===5||l.tag===3||l.tag===26||l.tag===27&&ha(l.type)||l.tag===4}function bc(l){l:for(;;){for(;l.sibling===null;){if(l.return===null||x1(l.return))return null;l=l.return}for(l.sibling.return=l.return,l=l.sibling;l.tag!==5&&l.tag!==6&&l.tag!==18;){if(l.tag===27&&ha(l.type)||l.flags&2||l.child===null||l.tag===4)continue l;l.child.return=l,l=l.child}if(!(l.flags&2))return l.stateNode}}function zc(l,t,a){var u=l.tag;if(u===5||u===6)l=l.stateNode,t?(a.nodeType===9?a.body:a.nodeName==="HTML"?a.ownerDocument.body:a).insertBefore(l,t):(t=a.nodeType===9?a.body:a.nodeName==="HTML"?a.ownerDocument.body:a,t.appendChild(l),a=a._reactRootContainer,a!=null||t.onclick!==null||(t.onclick=Nt));else if(u!==4&&(u===27&&ha(l.type)&&(a=l.stateNode,t=null),l=l.child,l!==null))for(zc(l,t,a),l=l.sibling;l!==null;)zc(l,t,a),l=l.sibling}function mn(l,t,a){var u=l.tag;if(u===5||u===6)l=l.stateNode,t?a.insertBefore(l,t):a.appendChild(l);else if(u!==4&&(u===27&&ha(l.type)&&(a=l.stateNode),l=l.child,l!==null))for(mn(l,t,a),l=l.sibling;l!==null;)mn(l,t,a),l=l.sibling}function L1(l){var t=l.stateNode,a=l.memoizedProps;try{for(var u=l.type,e=t.attributes;e.length;)t.removeAttributeNode(e[0]);Nl(t,u,a),t[Dl]=l,t[Vl]=a}catch(n){P(l,l.return,n)}}var jt=!1,Al=!1,Ec=!1,K1=typeof WeakSet=="function"?WeakSet:Set,Ol=null;function km(l,t){if(l=l.containerInfo,jc=Rn,l=u0(l),sf(l)){if("selectionStart"in l)var a={start:l.selectionStart,end:l.selectionEnd};else l:{a=(a=l.ownerDocument)&&a.defaultView||window;var u=a.getSelection&&a.getSelection();if(u&&u.rangeCount!==0){a=u.anchorNode;var e=u.anchorOffset,n=u.focusNode;u=u.focusOffset;try{a.nodeType,n.nodeType}catch{a=null;break l}var f=0,c=-1,i=-1,s=0,g=0,E=l,h=null;t:for(;;){for(var S;E!==a||e!==0&&E.nodeType!==3||(c=f+e),E!==n||u!==0&&E.nodeType!==3||(i=f+u),E.nodeType===3&&(f+=E.nodeValue.length),(S=E.firstChild)!==null;)h=E,E=S;for(;;){if(E===l)break t;if(h===a&&++s===e&&(c=f),h===n&&++g===u&&(i=f),(S=E.nextSibling)!==null)break;E=h,h=E.parentNode}E=S}a=c===-1||i===-1?null:{start:c,end:i}}else a=null}a=a||{start:0,end:0}}else a=null;for(Vc={focusedElem:l,selectionRange:a},Rn=!1,Ol=t;Ol!==null;)if(t=Ol,l=t.child,(t.subtreeFlags&1028)!==0&&l!==null)l.return=t,Ol=l;else for(;Ol!==null;){switch(t=Ol,n=t.alternate,l=t.flags,t.tag){case 0:if((l&4)!==0&&(l=t.updateQueue,l=l!==null?l.events:null,l!==null))for(a=0;a title"))),Nl(n,u,a),n[Dl]=l,_l(n),u=n;break l;case"link":var f=kv("link","href",e).get(u+(a.href||""));if(f){for(var c=0;cul&&(f=ul,ul=R,R=f);var m=t0(c,R),v=t0(c,ul);if(m&&v&&(S.rangeCount!==1||S.anchorNode!==m.node||S.anchorOffset!==m.offset||S.focusNode!==v.node||S.focusOffset!==v.offset)){var d=E.createRange();d.setStart(m.node,m.offset),S.removeAllRanges(),R>ul?(S.addRange(d),S.extend(v.node,v.offset)):(d.setEnd(v.node,v.offset),S.addRange(d))}}}}for(E=[],S=c;S=S.parentNode;)S.nodeType===1&&E.push({element:S,left:S.scrollLeft,top:S.scrollTop});for(typeof c.focus=="function"&&c.focus(),c=0;ca?32:a,b.T=null,a=Dc,Dc=null;var n=ma,f=Jt;if(Ml=0,gu=ma=null,Jt=0,($&6)!==0)throw Error(o(331));var c=$;if($|=4,av(n.current),P1(n,n.current,f,a),$=c,ie(0,!1),kl&&typeof kl.onPostCommitFiberRoot=="function")try{kl.onPostCommitFiberRoot(ru,n)}catch{}return!0}finally{M.p=e,b.T=u,Ev(l,t)}}function Tv(l,t,a){t=yt(a,t),t=fc(l.stateNode,t,2),l=ea(l,t,2),l!==null&&(Uu(l,2),Dt(l))}function P(l,t,a){if(l.tag===3)Tv(l,l,a);else for(;t!==null;){if(t.tag===3){Tv(t,l,a);break}else if(t.tag===1){var u=t.stateNode;if(typeof t.type.getDerivedStateFromError=="function"||typeof u.componentDidCatch=="function"&&(ya===null||!ya.has(u))){l=yt(a,l),a=M1(2),u=ea(t,a,2),u!==null&&(_1(a,u,t,l),Uu(u,2),Dt(u));break}}t=t.return}}function Nc(l,t,a){var u=l.pingCache;if(u===null){u=l.pingCache=new l2;var e=new Set;u.set(t,e)}else e=u.get(t),e===void 0&&(e=new Set,u.set(t,e));e.has(a)||(Mc=!0,e.add(a),l=n2.bind(null,l,t,a),t.then(l,l))}function n2(l,t,a){var u=l.pingCache;u!==null&&u.delete(t),l.pingedLanes|=l.suspendedLanes&a,l.warmLanes&=~a,nl===l&&(V&a)===a&&(hl===4||hl===3&&(V&62914560)===V&&300>Fl()-hn?($&2)===0&&bu(l,0):_c|=a,Su===V&&(Su=0)),Dt(l)}function Mv(l,t){t===0&&(t=gi()),l=Da(l,t),l!==null&&(Uu(l,t),Dt(l))}function f2(l){var t=l.memoizedState,a=0;t!==null&&(a=t.retryLane),Mv(l,a)}function c2(l,t){var a=0;switch(l.tag){case 31:case 13:var u=l.stateNode,e=l.memoizedState;e!==null&&(a=e.retryLane);break;case 19:u=l.stateNode;break;case 22:u=l.stateNode._retryCache;break;default:throw Error(o(314))}u!==null&&u.delete(t),Mv(l,a)}function i2(l,t){return xn(l,t)}var An=null,Eu=null,Rc=!1,Tn=!1,qc=!1,sa=0;function Dt(l){l!==Eu&&l.next===null&&(Eu===null?An=Eu=l:Eu=Eu.next=l),Tn=!0,Rc||(Rc=!0,y2())}function ie(l,t){if(!qc&&Tn){qc=!0;do for(var a=!1,u=An;u!==null;){if(l!==0){var e=u.pendingLanes;if(e===0)var n=0;else{var f=u.suspendedLanes,c=u.pingedLanes;n=(1<<31-Il(42|l)+1)-1,n&=e&~(f&~c),n=n&201326741?n&201326741|1:n?n|2:0}n!==0&&(a=!0,Dv(u,n))}else n=V,n=Oe(u,u===nl?n:0,u.cancelPendingCommit!==null||u.timeoutHandle!==-1),(n&3)===0||Du(u,n)||(a=!0,Dv(u,n));u=u.next}while(a);qc=!1}}function v2(){_v()}function _v(){Tn=Rc=!1;var l=0;sa!==0&&E2()&&(l=sa);for(var t=Fl(),a=null,u=An;u!==null;){var e=u.next,n=Ov(u,t);n===0?(u.next=null,a===null?An=e:a.next=e,e===null&&(Eu=a)):(a=u,(l!==0||(n&3)!==0)&&(Tn=!0)),u=e}Ml!==0&&Ml!==5||ie(l),sa!==0&&(sa=0)}function Ov(l,t){for(var a=l.suspendedLanes,u=l.pingedLanes,e=l.expirationTimes,n=l.pendingLanes&-62914561;0c)break;var g=i.transferSize,E=i.initiatorType;g&&Bv(E)&&(i=i.responseEnd,f+=g*(i"u"?null:document;function wv(l,t,a){var u=Au;if(u&&typeof t=="string"&&t){var e=it(t);e='link[rel="'+l+'"][href="'+e+'"]',typeof a=="string"&&(e+='[crossorigin="'+a+'"]'),Jv.has(e)||(Jv.add(e),l={rel:l,crossOrigin:a,href:t},u.querySelector(e)===null&&(t=u.createElement("link"),Nl(t,"link",l),_l(t),u.head.appendChild(t)))}}function H2(l){wt.D(l),wv("dns-prefetch",l,null)}function p2(l,t){wt.C(l,t),wv("preconnect",l,t)}function N2(l,t,a){wt.L(l,t,a);var u=Au;if(u&&l&&t){var e='link[rel="preload"][as="'+it(t)+'"]';t==="image"&&a&&a.imageSrcSet?(e+='[imagesrcset="'+it(a.imageSrcSet)+'"]',typeof a.imageSizes=="string"&&(e+='[imagesizes="'+it(a.imageSizes)+'"]')):e+='[href="'+it(l)+'"]';var n=e;switch(t){case"style":n=Tu(l);break;case"script":n=Mu(l)}St.has(n)||(l=N({rel:"preload",href:t==="image"&&a&&a.imageSrcSet?void 0:l,as:t},a),St.set(n,l),u.querySelector(e)!==null||t==="style"&&u.querySelector(de(n))||t==="script"&&u.querySelector(se(n))||(t=u.createElement("link"),Nl(t,"link",l),_l(t),u.head.appendChild(t)))}}function R2(l,t){wt.m(l,t);var a=Au;if(a&&l){var u=t&&typeof t.as=="string"?t.as:"script",e='link[rel="modulepreload"][as="'+it(u)+'"][href="'+it(l)+'"]',n=e;switch(u){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":n=Mu(l)}if(!St.has(n)&&(l=N({rel:"modulepreload",href:l},t),St.set(n,l),a.querySelector(e)===null)){switch(u){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(a.querySelector(se(n)))return}u=a.createElement("link"),Nl(u,"link",l),_l(u),a.head.appendChild(u)}}}function q2(l,t,a){wt.S(l,t,a);var u=Au;if(u&&l){var e=La(u).hoistableStyles,n=Tu(l);t=t||"default";var f=e.get(n);if(!f){var c={loading:0,preload:null};if(f=u.querySelector(de(n)))c.loading=5;else{l=N({rel:"stylesheet",href:l,"data-precedence":t},a),(a=St.get(n))&&$c(l,a);var i=f=u.createElement("link");_l(i),Nl(i,"link",l),i._p=new Promise(function(s,g){i.onload=s,i.onerror=g}),i.addEventListener("load",function(){c.loading|=1}),i.addEventListener("error",function(){c.loading|=2}),c.loading|=4,Dn(f,t,u)}f={type:"stylesheet",instance:f,count:1,state:c},e.set(n,f)}}}function C2(l,t){wt.X(l,t);var a=Au;if(a&&l){var u=La(a).hoistableScripts,e=Mu(l),n=u.get(e);n||(n=a.querySelector(se(e)),n||(l=N({src:l,async:!0},t),(t=St.get(e))&&Fc(l,t),n=a.createElement("script"),_l(n),Nl(n,"link",l),a.head.appendChild(n)),n={type:"script",instance:n,count:1,state:null},u.set(e,n))}}function B2(l,t){wt.M(l,t);var a=Au;if(a&&l){var u=La(a).hoistableScripts,e=Mu(l),n=u.get(e);n||(n=a.querySelector(se(e)),n||(l=N({src:l,async:!0,type:"module"},t),(t=St.get(e))&&Fc(l,t),n=a.createElement("script"),_l(n),Nl(n,"link",l),a.head.appendChild(n)),n={type:"script",instance:n,count:1,state:null},u.set(e,n))}}function Wv(l,t,a,u){var e=(e=X.current)?rn(e):null;if(!e)throw Error(o(446));switch(l){case"meta":case"title":return null;case"style":return typeof a.precedence=="string"&&typeof a.href=="string"?(t=Tu(a.href),a=La(e).hoistableStyles,u=a.get(t),u||(u={type:"style",instance:null,count:0,state:null},a.set(t,u)),u):{type:"void",instance:null,count:0,state:null};case"link":if(a.rel==="stylesheet"&&typeof a.href=="string"&&typeof a.precedence=="string"){l=Tu(a.href);var n=La(e).hoistableStyles,f=n.get(l);if(f||(e=e.ownerDocument||e,f={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},n.set(l,f),(n=e.querySelector(de(l)))&&!n._p&&(f.instance=n,f.state.loading=5),St.has(l)||(a={rel:"preload",as:"style",href:a.href,crossOrigin:a.crossOrigin,integrity:a.integrity,media:a.media,hrefLang:a.hrefLang,referrerPolicy:a.referrerPolicy},St.set(l,a),n||Y2(e,l,a,f.state))),t&&u===null)throw Error(o(528,""));return f}if(t&&u!==null)throw Error(o(529,""));return null;case"script":return t=a.async,a=a.src,typeof a=="string"&&t&&typeof t!="function"&&typeof t!="symbol"?(t=Mu(a),a=La(e).hoistableScripts,u=a.get(t),u||(u={type:"script",instance:null,count:0,state:null},a.set(t,u)),u):{type:"void",instance:null,count:0,state:null};default:throw Error(o(444,l))}}function Tu(l){return'href="'+it(l)+'"'}function de(l){return'link[rel="stylesheet"]['+l+"]"}function $v(l){return N({},l,{"data-precedence":l.precedence,precedence:null})}function Y2(l,t,a,u){l.querySelector('link[rel="preload"][as="style"]['+t+"]")?u.loading=1:(t=l.createElement("link"),u.preload=t,t.addEventListener("load",function(){return u.loading|=1}),t.addEventListener("error",function(){return u.loading|=2}),Nl(t,"link",a),_l(t),l.head.appendChild(t))}function Mu(l){return'[src="'+it(l)+'"]'}function se(l){return"script[async]"+l}function Fv(l,t,a){if(t.count++,t.instance===null)switch(t.type){case"style":var u=l.querySelector('style[data-href~="'+it(a.href)+'"]');if(u)return t.instance=u,_l(u),u;var e=N({},a,{"data-href":a.href,"data-precedence":a.precedence,href:null,precedence:null});return u=(l.ownerDocument||l).createElement("style"),_l(u),Nl(u,"style",e),Dn(u,a.precedence,l),t.instance=u;case"stylesheet":e=Tu(a.href);var n=l.querySelector(de(e));if(n)return t.state.loading|=4,t.instance=n,_l(n),n;u=$v(a),(e=St.get(e))&&$c(u,e),n=(l.ownerDocument||l).createElement("link"),_l(n);var f=n;return f._p=new Promise(function(c,i){f.onload=c,f.onerror=i}),Nl(n,"link",u),t.state.loading|=4,Dn(n,a.precedence,l),t.instance=n;case"script":return n=Mu(a.src),(e=l.querySelector(se(n)))?(t.instance=e,_l(e),e):(u=a,(e=St.get(n))&&(u=N({},a),Fc(u,e)),l=l.ownerDocument||l,e=l.createElement("script"),_l(e),Nl(e,"link",u),l.head.appendChild(e),t.instance=e);case"void":return null;default:throw Error(o(443,t.type))}else t.type==="stylesheet"&&(t.state.loading&4)===0&&(u=t.instance,t.state.loading|=4,Dn(u,a.precedence,l));return t.instance}function Dn(l,t,a){for(var u=a.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),e=u.length?u[u.length-1]:null,n=e,f=0;f title"):null)}function Z2(l,t,a){if(a===1||t.itemProp!=null)return!1;switch(l){case"meta":case"title":return!0;case"style":if(typeof t.precedence!="string"||typeof t.href!="string"||t.href==="")break;return!0;case"link":if(typeof t.rel!="string"||typeof t.href!="string"||t.href===""||t.onLoad||t.onError)break;switch(t.rel){case"stylesheet":return l=t.disabled,typeof t.precedence=="string"&&l==null;default:return!0}case"script":if(t.async&&typeof t.async!="function"&&typeof t.async!="symbol"&&!t.onLoad&&!t.onError&&t.src&&typeof t.src=="string")return!0}return!1}function Pv(l){return!(l.type==="stylesheet"&&(l.state.loading&3)===0)}function G2(l,t,a,u){if(a.type==="stylesheet"&&(typeof u.media!="string"||matchMedia(u.media).matches!==!1)&&(a.state.loading&4)===0){if(a.instance===null){var e=Tu(u.href),n=t.querySelector(de(e));if(n){t=n._p,t!==null&&typeof t=="object"&&typeof t.then=="function"&&(l.count++,l=Hn.bind(l),t.then(l,l)),a.state.loading|=4,a.instance=n,_l(n);return}n=t.ownerDocument||t,u=$v(u),(e=St.get(e))&&$c(u,e),n=n.createElement("link"),_l(n);var f=n;f._p=new Promise(function(c,i){f.onload=c,f.onerror=i}),Nl(n,"link",u),a.instance=n}l.stylesheets===null&&(l.stylesheets=new Map),l.stylesheets.set(a,t),(t=a.state.preload)&&(a.state.loading&3)===0&&(l.count++,a=Hn.bind(l),t.addEventListener("load",a),t.addEventListener("error",a))}}var kc=0;function X2(l,t){return l.stylesheets&&l.count===0&&Nn(l,l.stylesheets),0kc?50:800)+t);return l.unsuspend=a,function(){l.unsuspend=null,clearTimeout(u),clearTimeout(e)}}:null}function Hn(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)Nn(this,this.stylesheets);else if(this.unsuspend){var l=this.unsuspend;this.unsuspend=null,l()}}}var pn=null;function Nn(l,t){l.stylesheets=null,l.unsuspend!==null&&(l.count++,pn=new Map,t.forEach(Q2,l),pn=null,Hn.call(l))}function Q2(l,t){if(!(t.state.loading&4)){var a=pn.get(l);if(a)var u=a.get(null);else{a=new Map,pn.set(l,a);for(var e=l.querySelectorAll("link[data-precedence],style[data-precedence]"),n=0;n"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(O)}catch(ml){console.error(ml)}}return O(),fi.exports=ad(),fi.exports}var ed=ud();const yd=My(ed),nd=new Map([["bold",C.createElement(C.Fragment,null,C.createElement("path",{d:"M232.49,215.51,185,168a92.12,92.12,0,1,0-17,17l47.53,47.54a12,12,0,0,0,17-17ZM44,112a68,68,0,1,1,68,68A68.07,68.07,0,0,1,44,112Z"}))],["duotone",C.createElement(C.Fragment,null,C.createElement("path",{d:"M192,112a80,80,0,1,1-80-80A80,80,0,0,1,192,112Z",opacity:"0.2"}),C.createElement("path",{d:"M229.66,218.34,179.6,168.28a88.21,88.21,0,1,0-11.32,11.31l50.06,50.07a8,8,0,0,0,11.32-11.32ZM40,112a72,72,0,1,1,72,72A72.08,72.08,0,0,1,40,112Z"}))],["fill",C.createElement(C.Fragment,null,C.createElement("path",{d:"M168,112a56,56,0,1,1-56-56A56,56,0,0,1,168,112Zm61.66,117.66a8,8,0,0,1-11.32,0l-50.06-50.07a88,88,0,1,1,11.32-11.31l50.06,50.06A8,8,0,0,1,229.66,229.66ZM112,184a72,72,0,1,0-72-72A72.08,72.08,0,0,0,112,184Z"}))],["light",C.createElement(C.Fragment,null,C.createElement("path",{d:"M228.24,219.76l-51.38-51.38a86.15,86.15,0,1,0-8.48,8.48l51.38,51.38a6,6,0,0,0,8.48-8.48ZM38,112a74,74,0,1,1,74,74A74.09,74.09,0,0,1,38,112Z"}))],["regular",C.createElement(C.Fragment,null,C.createElement("path",{d:"M229.66,218.34l-50.07-50.06a88.11,88.11,0,1,0-11.31,11.31l50.06,50.07a8,8,0,0,0,11.32-11.32ZM40,112a72,72,0,1,1,72,72A72.08,72.08,0,0,1,40,112Z"}))],["thin",C.createElement(C.Fragment,null,C.createElement("path",{d:"M226.83,221.17l-52.7-52.7a84.1,84.1,0,1,0-5.66,5.66l52.7,52.7a4,4,0,0,0,5.66-5.66ZM36,112a76,76,0,1,1,76,76A76.08,76.08,0,0,1,36,112Z"}))]]),fd=new Map([["bold",C.createElement(C.Fragment,null,C.createElement("path",{d:"M228,40V80a12,12,0,0,1-24,0V52H176a12,12,0,0,1,0-24h40A12,12,0,0,1,228,40ZM80,204H52V176a12,12,0,0,0-24,0v40a12,12,0,0,0,12,12H80a12,12,0,0,0,0-24Zm136-40a12,12,0,0,0-12,12v28H176a12,12,0,0,0,0,24h40a12,12,0,0,0,12-12V176A12,12,0,0,0,216,164ZM40,92A12,12,0,0,0,52,80V52H80a12,12,0,0,0,0-24H40A12,12,0,0,0,28,40V80A12,12,0,0,0,40,92ZM84,72h88a12,12,0,0,1,12,12v88a12,12,0,0,1-12,12H84a12,12,0,0,1-12-12V84A12,12,0,0,1,84,72Zm12,88h64V96H96Z"}))],["duotone",C.createElement(C.Fragment,null,C.createElement("path",{d:"M176,80v96H80V80Z",opacity:"0.2"}),C.createElement("path",{d:"M224,40V80a8,8,0,0,1-16,0V48H176a8,8,0,0,1,0-16h40A8,8,0,0,1,224,40ZM80,208H48V176a8,8,0,0,0-16,0v40a8,8,0,0,0,8,8H80a8,8,0,0,0,0-16Zm136-40a8,8,0,0,0-8,8v32H176a8,8,0,0,0,0,16h40a8,8,0,0,0,8-8V176A8,8,0,0,0,216,168ZM40,88a8,8,0,0,0,8-8V48H80a8,8,0,0,0,0-16H40a8,8,0,0,0-8,8V80A8,8,0,0,0,40,88ZM80,72h96a8,8,0,0,1,8,8v96a8,8,0,0,1-8,8H80a8,8,0,0,1-8-8V80A8,8,0,0,1,80,72Zm8,96h80V88H88Z"}))],["fill",C.createElement(C.Fragment,null,C.createElement("path",{d:"M224,40V80a8,8,0,0,1-16,0V48H176a8,8,0,0,1,0-16h40A8,8,0,0,1,224,40ZM80,208H48V176a8,8,0,0,0-16,0v40a8,8,0,0,0,8,8H80a8,8,0,0,0,0-16Zm136-40a8,8,0,0,0-8,8v32H176a8,8,0,0,0,0,16h40a8,8,0,0,0,8-8V176A8,8,0,0,0,216,168ZM40,88a8,8,0,0,0,8-8V48H80a8,8,0,0,0,0-16H40a8,8,0,0,0-8,8V80A8,8,0,0,0,40,88Zm32-8v96a8,8,0,0,0,8,8h96a8,8,0,0,0,8-8V80a8,8,0,0,0-8-8H80A8,8,0,0,0,72,80Z"}))],["light",C.createElement(C.Fragment,null,C.createElement("path",{d:"M222,40V80a6,6,0,0,1-12,0V46H176a6,6,0,0,1,0-12h40A6,6,0,0,1,222,40ZM80,210H46V176a6,6,0,0,0-12,0v40a6,6,0,0,0,6,6H80a6,6,0,0,0,0-12Zm136-40a6,6,0,0,0-6,6v34H176a6,6,0,0,0,0,12h40a6,6,0,0,0,6-6V176A6,6,0,0,0,216,170ZM40,86a6,6,0,0,0,6-6V46H80a6,6,0,0,0,0-12H40a6,6,0,0,0-6,6V80A6,6,0,0,0,40,86ZM80,74h96a6,6,0,0,1,6,6v96a6,6,0,0,1-6,6H80a6,6,0,0,1-6-6V80A6,6,0,0,1,80,74Zm6,96h84V86H86Z"}))],["regular",C.createElement(C.Fragment,null,C.createElement("path",{d:"M224,40V80a8,8,0,0,1-16,0V48H176a8,8,0,0,1,0-16h40A8,8,0,0,1,224,40ZM80,208H48V176a8,8,0,0,0-16,0v40a8,8,0,0,0,8,8H80a8,8,0,0,0,0-16Zm136-40a8,8,0,0,0-8,8v32H176a8,8,0,0,0,0,16h40a8,8,0,0,0,8-8V176A8,8,0,0,0,216,168ZM40,88a8,8,0,0,0,8-8V48H80a8,8,0,0,0,0-16H40a8,8,0,0,0-8,8V80A8,8,0,0,0,40,88ZM80,72h96a8,8,0,0,1,8,8v96a8,8,0,0,1-8,8H80a8,8,0,0,1-8-8V80A8,8,0,0,1,80,72Zm8,96h80V88H88Z"}))],["thin",C.createElement(C.Fragment,null,C.createElement("path",{d:"M220,40V80a4,4,0,0,1-8,0V44H176a4,4,0,0,1,0-8h40A4,4,0,0,1,220,40ZM80,212H44V176a4,4,0,0,0-8,0v40a4,4,0,0,0,4,4H80a4,4,0,0,0,0-8Zm136-40a4,4,0,0,0-4,4v36H176a4,4,0,0,0,0,8h40a4,4,0,0,0,4-4V176A4,4,0,0,0,216,172ZM40,84a4,4,0,0,0,4-4V44H80a4,4,0,0,0,0-8H40a4,4,0,0,0-4,4V80A4,4,0,0,0,40,84Zm40-8h96a4,4,0,0,1,4,4v96a4,4,0,0,1-4,4H80a4,4,0,0,1-4-4V80A4,4,0,0,1,80,76Zm4,96h88V84H84Z"}))]]),cd=C.createContext({color:"currentColor",size:"1em",weight:"regular",mirrored:!1}),mi=C.forwardRef((O,ml)=>{const{alt:k,color:o,size:fl,weight:dl,mirrored:Tl,children:rl,weights:H,...T}=O,{color:J="currentColor",size:N,weight:cl="regular",mirrored:Bl=!1,...Rl}=C.useContext(cd);return C.createElement("svg",{ref:ml,xmlns:"http://www.w3.org/2000/svg",width:fl??N,height:fl??N,fill:o??J,viewBox:"0 0 256 256",transform:Tl||Bl?"scale(-1, 1)":void 0,...Rl,...T},!!k&&C.createElement("title",null,k),rl,H.get(dl??cl))});mi.displayName="IconBase";const _y=C.forwardRef((O,ml)=>C.createElement(mi,{ref:ml,...O,weights:nd}));_y.displayName="MagnifyingGlassIcon";const md=_y,Oy=C.forwardRef((O,ml)=>C.createElement(mi,{ref:ml,...O,weights:fd}));Oy.displayName="ScanIcon";const dd=Oy;export{vd as R,yd as a,ed as c,md as f,id as j,mi as p,C as r,dd as s}; diff --git a/dist/assets/colors-Czz5EmDP.js b/dist/assets/colors-Czz5EmDP.js new file mode 100644 index 0000000..571966f --- /dev/null +++ b/dist/assets/colors-Czz5EmDP.js @@ -0,0 +1,13 @@ +function Ir(t,e){return chrome.runtime.sendMessage({type:t,payload:e})}function Tr(t,e){chrome.runtime.onMessage.addListener((n,r,o)=>{if(n.type===t)return e(n.payload,r,o)})}const{min:ze,max:Ge}=Math,J=(t,e=0,n=1)=>ze(Ge(e,t),n),Yt=t=>{t._clipped=!1,t._unclipped=t.slice(0);for(let e=0;e<=3;e++)e<3?((t[e]<0||t[e]>255)&&(t._clipped=!0),t[e]=J(t[e],0,255)):e===3&&(t[e]=J(t[e],0,1));return t},re={};for(let t of["Boolean","Number","String","Function","Array","Date","RegExp","Undefined","Null"])re[`[object ${t}]`]=t.toLowerCase();function A(t){return re[Object.prototype.toString.call(t)]||"object"}const x=(t,e=null)=>t.length>=3?Array.prototype.slice.call(t):A(t[0])=="object"&&e?e.split("").filter(n=>t[0][n]!==void 0).map(n=>t[0][n]):t[0].slice(0),ot=t=>{if(t.length<2)return null;const e=t.length-1;return A(t[e])=="string"?t[e].toLowerCase():null},{PI:wt,min:oe,max:ce}=Math,S=t=>Math.round(t*100)/100,vt=t=>Math.round(t*100)/100,K=wt*2,Mt=wt/3,qe=wt/180,Be=180/wt;function se(t){return[...t.slice(0,3).reverse(),...t.slice(3)]}const _={format:{},autodetect:[]};class u{constructor(...e){const n=this;if(A(e[0])==="object"&&e[0].constructor&&e[0].constructor===this.constructor)return e[0];let r=ot(e),o=!1;if(!r){o=!0,_.sorted||(_.autodetect=_.autodetect.sort((c,s)=>s.p-c.p),_.sorted=!0);for(let c of _.autodetect)if(r=c.test(...e),r)break}if(_.format[r]){const c=_.format[r].apply(null,o?e:e.slice(0,-1));n._rgb=Yt(c)}else throw new Error("unknown format: "+e);n._rgb.length===3&&n._rgb.push(1)}toString(){return A(this.hex)=="function"?this.hex():`[${this._rgb.join(",")}]`}}const Se="3.2.0",$=(...t)=>new u(...t);$.version=Se;const nt={aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgreen:"#006400",darkgrey:"#a9a9a9",darkkhaki:"#bdb76b",darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",darkseagreen:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkslategrey:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",deepskyblue:"#00bfff",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",fuchsia:"#ff00ff",gainsboro:"#dcdcdc",ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",green:"#008000",greenyellow:"#adff2f",grey:"#808080",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred:"#cd5c5c",indigo:"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",laserlemon:"#ffff54",lavender:"#e6e6fa",lavenderblush:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",lightcyan:"#e0ffff",lightgoldenrod:"#fafad2",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3",lightgreen:"#90ee90",lightgrey:"#d3d3d3",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime:"#00ff00",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff",maroon:"#800000",maroon2:"#7f0000",maroon3:"#b03060",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3",mediumpurple:"#9370db",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#db7093",papayawhip:"#ffefd5",peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",purple2:"#7f007f",purple3:"#a020f0",rebeccapurple:"#663399",red:"#ff0000",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",slategrey:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32"},Xe=/^#?([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/,Ze=/^#?([A-Fa-f0-9]{8}|[A-Fa-f0-9]{4})$/,fe=t=>{if(t.match(Xe)){(t.length===4||t.length===7)&&(t=t.substr(1)),t.length===3&&(t=t.split(""),t=t[0]+t[0]+t[1]+t[1]+t[2]+t[2]);const e=parseInt(t,16),n=e>>16,r=e>>8&255,o=e&255;return[n,r,o,1]}if(t.match(Ze)){(t.length===5||t.length===9)&&(t=t.substr(1)),t.length===4&&(t=t.split(""),t=t[0]+t[0]+t[1]+t[1]+t[2]+t[2]+t[3]+t[3]);const e=parseInt(t,16),n=e>>24&255,r=e>>16&255,o=e>>8&255,c=Math.round((e&255)/255*100)/100;return[n,r,o,c]}throw new Error(`unknown hex color: ${t}`)},{round:bt}=Math,ae=(...t)=>{let[e,n,r,o]=x(t,"rgba"),c=ot(t)||"auto";o===void 0&&(o=1),c==="auto"&&(c=o<1?"rgba":"rgb"),e=bt(e),n=bt(n),r=bt(r);let f="000000"+(e<<16|n<<8|r).toString(16);f=f.substr(f.length-6);let a="0"+bt(o*255).toString(16);switch(a=a.substr(a.length-2),c.toLowerCase()){case"rgba":return`#${f}${a}`;case"argb":return`#${a}${f}`;default:return`#${f}`}};u.prototype.name=function(){const t=ae(this._rgb,"rgb");for(let e of Object.keys(nt))if(nt[e]===t)return e.toLowerCase();return t};_.format.named=t=>{if(t=t.toLowerCase(),nt[t])return fe(nt[t]);throw new Error("unknown color name: "+t)};_.autodetect.push({p:5,test:(t,...e)=>{if(!e.length&&A(t)==="string"&&nt[t.toLowerCase()])return"named"}});u.prototype.alpha=function(t,e=!1){return t!==void 0&&A(t)==="number"?e?(this._rgb[3]=t,this):new u([this._rgb[0],this._rgb[1],this._rgb[2],t],"rgb"):this._rgb[3]};u.prototype.clipped=function(){return this._rgb._clipped||!1};const T={Kn:18,labWhitePoint:"d65",Xn:.95047,Yn:1,Zn:1.08883,kE:216/24389,kKE:8,kK:24389/27,RefWhiteRGB:{X:.95047,Y:1,Z:1.08883},MtxRGB2XYZ:{m00:.4124564390896922,m01:.21267285140562253,m02:.0193338955823293,m10:.357576077643909,m11:.715152155287818,m12:.11919202588130297,m20:.18043748326639894,m21:.07217499330655958,m22:.9503040785363679},MtxXYZ2RGB:{m00:3.2404541621141045,m01:-.9692660305051868,m02:.055643430959114726,m10:-1.5371385127977166,m11:1.8760108454466942,m12:-.2040259135167538,m20:-.498531409556016,m21:.041556017530349834,m22:1.0572251882231791},As:.9414285350000001,Bs:1.040417467,Cs:1.089532651,MtxAdaptMa:{m00:.8951,m01:-.7502,m02:.0389,m10:.2664,m11:1.7135,m12:-.0685,m20:-.1614,m21:.0367,m22:1.0296},MtxAdaptMaI:{m00:.9869929054667123,m01:.43230526972339456,m02:-.008528664575177328,m10:-.14705425642099013,m11:.5183602715367776,m12:.04004282165408487,m20:.15996265166373125,m21:.0492912282128556,m22:.9684866957875502}},Ie=new Map([["a",[1.0985,.35585]],["b",[1.0985,.35585]],["c",[.98074,1.18232]],["d50",[.96422,.82521]],["d55",[.95682,.92149]],["d65",[.95047,1.08883]],["e",[1,1,1]],["f2",[.99186,.67393]],["f7",[.95041,1.08747]],["f11",[1.00962,.6435]],["icc",[.96422,.82521]]]);function W(t){const e=Ie.get(String(t).toLowerCase());if(!e)throw new Error("unknown Lab illuminant "+t);T.labWhitePoint=t,T.Xn=e[0],T.Zn=e[1]}function lt(){return T.labWhitePoint}const zt=(...t)=>{t=x(t,"lab");const[e,n,r]=t,[o,c,s]=Te(e,n,r),[f,a,l]=le(o,c,s);return[f,a,l,t.length>3?t[3]:1]},Te=(t,e,n)=>{const{kE:r,kK:o,kKE:c,Xn:s,Yn:f,Zn:a}=T,l=(t+16)/116,h=.002*e+l,d=l-.005*n,b=h*h*h,g=d*d*d,M=b>r?b:(116*h-16)/o,N=t>c?Math.pow((t+16)/116,3):t/o,m=g>r?g:(116*d-16)/o,y=M*s,Y=N*f,C=m*a;return[y,Y,C]},$t=t=>{const e=Math.sign(t);return t=Math.abs(t),(t<=.0031308?t*12.92:1.055*Math.pow(t,1/2.4)-.055)*e},le=(t,e,n)=>{const{MtxAdaptMa:r,MtxAdaptMaI:o,MtxXYZ2RGB:c,RefWhiteRGB:s,Xn:f,Yn:a,Zn:l}=T,h=f*r.m00+a*r.m10+l*r.m20,d=f*r.m01+a*r.m11+l*r.m21,b=f*r.m02+a*r.m12+l*r.m22,g=s.X*r.m00+s.Y*r.m10+s.Z*r.m20,M=s.X*r.m01+s.Y*r.m11+s.Z*r.m21,N=s.X*r.m02+s.Y*r.m12+s.Z*r.m22,m=(t*r.m00+e*r.m10+n*r.m20)*(g/h),y=(t*r.m01+e*r.m11+n*r.m21)*(M/d),Y=(t*r.m02+e*r.m12+n*r.m22)*(N/b),C=m*o.m00+y*o.m10+Y*o.m20,P=m*o.m01+y*o.m11+Y*o.m21,O=m*o.m02+y*o.m12+Y*o.m22,B=$t(C*c.m00+P*c.m10+O*c.m20),L=$t(C*c.m01+P*c.m11+O*c.m21),i=$t(C*c.m02+P*c.m12+O*c.m22);return[B*255,L*255,i*255]},Gt=(...t)=>{const[e,n,r,...o]=x(t,"rgb"),[c,s,f]=ie(e,n,r),[a,l,h]=He(c,s,f);return[a,l,h,...o.length>0&&o[0]<1?[o[0]]:[]]};function He(t,e,n){const{Xn:r,Yn:o,Zn:c,kE:s,kK:f}=T,a=t/r,l=e/o,h=n/c,d=a>s?Math.pow(a,1/3):(f*a+16)/116,b=l>s?Math.pow(l,1/3):(f*l+16)/116,g=h>s?Math.pow(h,1/3):(f*h+16)/116;return[116*b-16,500*(d-b),200*(b-g)]}function xt(t){const e=Math.sign(t);return t=Math.abs(t),(t<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4))*e}const ie=(t,e,n)=>{t=xt(t/255),e=xt(e/255),n=xt(n/255);const{MtxRGB2XYZ:r,MtxAdaptMa:o,MtxAdaptMaI:c,Xn:s,Yn:f,Zn:a,As:l,Bs:h,Cs:d}=T;let b=t*r.m00+e*r.m10+n*r.m20,g=t*r.m01+e*r.m11+n*r.m21,M=t*r.m02+e*r.m12+n*r.m22;const N=s*o.m00+f*o.m10+a*o.m20,m=s*o.m01+f*o.m11+a*o.m21,y=s*o.m02+f*o.m12+a*o.m22;let Y=b*o.m00+g*o.m10+M*o.m20,C=b*o.m01+g*o.m11+M*o.m21,P=b*o.m02+g*o.m12+M*o.m22;return Y*=N/l,C*=m/h,P*=y/d,b=Y*c.m00+C*c.m10+P*c.m20,g=Y*c.m01+C*c.m11+P*c.m21,M=Y*c.m02+C*c.m12+P*c.m22,[b,g,M]};u.prototype.lab=function(){return Gt(this._rgb)};const Ke=(...t)=>new u(...t,"lab");Object.assign($,{lab:Ke,getLabWhitePoint:lt,setLabWhitePoint:W});_.format.lab=zt;_.autodetect.push({p:2,test:(...t)=>{if(t=x(t,"lab"),A(t)==="array"&&t.length===3)return"lab"}});u.prototype.darken=function(t=1){const e=this,n=e.lab();return n[0]-=T.Kn*t,new u(n,"lab").alpha(e.alpha(),!0)};u.prototype.brighten=function(t=1){return this.darken(-t)};u.prototype.darker=u.prototype.darken;u.prototype.brighter=u.prototype.brighten;u.prototype.get=function(t){const[e,n]=t.split("."),r=this[e]();if(n){const o=e.indexOf(n)-(e.substr(0,2)==="ok"?2:0);if(o>-1)return r[o];throw new Error(`unknown channel ${n} in mode ${e}`)}else return r};const{pow:We}=Math,De=1e-7,Fe=20;u.prototype.luminance=function(t,e="rgb"){if(t!==void 0&&A(t)==="number"){if(t===0)return new u([0,0,0,this._rgb[3]],"rgb");if(t===1)return new u([255,255,255,this._rgb[3]],"rgb");let n=this.luminance(),r=Fe;const o=(s,f)=>{const a=s.interpolate(f,.5,e),l=a.luminance();return Math.abs(t-l)t?o(s,a):o(a,f)},c=(n>t?o(new u([0,0,0]),this):o(this,new u([255,255,255]))).rgb();return new u([...c,this._rgb[3]])}return Ue(...this._rgb.slice(0,3))};const Ue=(t,e,n)=>(t=Et(t),e=Et(e),n=Et(n),.2126*t+.7152*e+.0722*n),Et=t=>(t/=255,t<=.03928?t/12.92:We((t+.055)/1.055,2.4)),z={},rt=(t,e,n=.5,...r)=>{let o=r[0]||"lrgb";if(!z[o]&&!r.length&&(o=Object.keys(z)[0]),!z[o])throw new Error(`interpolation mode ${o} is not defined`);return A(t)!=="object"&&(t=new u(t)),A(e)!=="object"&&(e=new u(e)),z[o](t,e,n).alpha(t.alpha()+n*(e.alpha()-t.alpha()))};u.prototype.mix=u.prototype.interpolate=function(t,e=.5,...n){return rt(this,t,e,...n)};u.prototype.premultiply=function(t=!1){const e=this._rgb,n=e[3];return t?(this._rgb=[e[0]*n,e[1]*n,e[2]*n,n],this):new u([e[0]*n,e[1]*n,e[2]*n,n],"rgb")};const{sin:Ve,cos:Je}=Math,ue=(...t)=>{let[e,n,r]=x(t,"lch");return isNaN(r)&&(r=0),r=r*qe,[e,Je(r)*n,Ve(r)*n]},qt=(...t)=>{t=x(t,"lch");const[e,n,r]=t,[o,c,s]=ue(e,n,r),[f,a,l]=zt(o,c,s);return[f,a,l,t.length>3?t[3]:1]},Qe=(...t)=>{const e=se(x(t,"hcl"));return qt(...e)},{sqrt:tn,atan2:en,round:nn}=Math,be=(...t)=>{const[e,n,r]=x(t,"lab"),o=tn(n*n+r*r);let c=(en(r,n)*Be+360)%360;return nn(o*1e4)===0&&(c=Number.NaN),[e,o,c]},Bt=(...t)=>{const[e,n,r,...o]=x(t,"rgb"),[c,s,f]=Gt(e,n,r),[a,l,h]=be(c,s,f);return[a,l,h,...o.length>0&&o[0]<1?[o[0]]:[]]};u.prototype.lch=function(){return Bt(this._rgb)};u.prototype.hcl=function(){return se(Bt(this._rgb))};const rn=(...t)=>new u(...t,"lch"),on=(...t)=>new u(...t,"hcl");Object.assign($,{lch:rn,hcl:on});_.format.lch=qt;_.format.hcl=Qe;["lch","hcl"].forEach(t=>_.autodetect.push({p:2,test:(...e)=>{if(e=x(e,t),A(e)==="array"&&e.length===3)return t}}));u.prototype.saturate=function(t=1){const e=this,n=e.lch();return n[1]+=T.Kn*t,n[1]<0&&(n[1]=0),new u(n,"lch").alpha(e.alpha(),!0)};u.prototype.desaturate=function(t=1){return this.saturate(-t)};u.prototype.set=function(t,e,n=!1){const[r,o]=t.split("."),c=this[r]();if(o){const s=r.indexOf(o)-(r.substr(0,2)==="ok"?2:0);if(s>-1){if(A(e)=="string")switch(e.charAt(0)){case"+":c[s]+=+e;break;case"-":c[s]+=+e;break;case"*":c[s]*=+e.substr(1);break;case"/":c[s]/=+e.substr(1);break;default:c[s]=+e}else if(A(e)==="number")c[s]=e;else throw new Error("unsupported value for Color.set");const f=new u(c,r);return n?(this._rgb=f._rgb,this):f}throw new Error(`unknown channel ${o} in mode ${r}`)}else return c};u.prototype.tint=function(t=.5,...e){return rt(this,"white",t,...e)};u.prototype.shade=function(t=.5,...e){return rt(this,"black",t,...e)};const cn=(t,e,n)=>{const r=t._rgb,o=e._rgb;return new u(r[0]+n*(o[0]-r[0]),r[1]+n*(o[1]-r[1]),r[2]+n*(o[2]-r[2]),"rgb")};z.rgb=cn;const{sqrt:At,pow:Q}=Math,sn=(t,e,n)=>{const[r,o,c]=t._rgb,[s,f,a]=e._rgb;return new u(At(Q(r,2)*(1-n)+Q(s,2)*n),At(Q(o,2)*(1-n)+Q(f,2)*n),At(Q(c,2)*(1-n)+Q(a,2)*n),"rgb")};z.lrgb=sn;const fn=(t,e,n)=>{const r=t.lab(),o=e.lab();return new u(r[0]+n*(o[0]-r[0]),r[1]+n*(o[1]-r[1]),r[2]+n*(o[2]-r[2]),"lab")};z.lab=fn;const ct=(t,e,n,r)=>{let o,c;r==="hsl"?(o=t.hsl(),c=e.hsl()):r==="hsv"?(o=t.hsv(),c=e.hsv()):r==="hcg"?(o=t.hcg(),c=e.hcg()):r==="hsi"?(o=t.hsi(),c=e.hsi()):r==="lch"||r==="hcl"?(r="hcl",o=t.hcl(),c=e.hcl()):r==="oklch"&&(o=t.oklch().reverse(),c=e.oklch().reverse());let s,f,a,l,h,d;(r.substr(0,1)==="h"||r==="oklch")&&([s,a,h]=o,[f,l,d]=c);let b,g,M,N;return!isNaN(s)&&!isNaN(f)?(f>s&&f-s>180?N=f-(s+360):f180?N=f+360-s:N=f-s,g=s+n*N):isNaN(s)?isNaN(f)?g=Number.NaN:(g=f,(h==1||h==0)&&r!="hsv"&&(b=l)):(g=s,(d==1||d==0)&&r!="hsv"&&(b=a)),b===void 0&&(b=a+n*(l-a)),M=h+n*(d-h),r==="oklch"?new u([M,b,g],r):new u([g,b,M],r)},he=(t,e,n)=>ct(t,e,n,"lch");z.lch=he;z.hcl=he;const an=t=>{if(A(t)=="number"&&t>=0&&t<=16777215){const e=t>>16,n=t>>8&255,r=t&255;return[e,n,r,1]}throw new Error("unknown num color: "+t)},ln=(...t)=>{const[e,n,r]=x(t,"rgb");return(e<<16)+(n<<8)+r};u.prototype.num=function(){return ln(this._rgb)};const un=(...t)=>new u(...t,"num");Object.assign($,{num:un});_.format.num=an;_.autodetect.push({p:5,test:(...t)=>{if(t.length===1&&A(t[0])==="number"&&t[0]>=0&&t[0]<=16777215)return"num"}});const bn=(t,e,n)=>{const r=t.num(),o=e.num();return new u(r+n*(o-r),"num")};z.num=bn;const{floor:hn}=Math,dn=(...t)=>{t=x(t,"hcg");let[e,n,r]=t,o,c,s;r=r*255;const f=n*255;if(n===0)o=c=s=r;else{e===360&&(e=0),e>360&&(e-=360),e<0&&(e+=360),e/=60;const a=hn(e),l=e-a,h=r*(1-n),d=h+f*(1-l),b=h+f*l,g=h+f;switch(a){case 0:[o,c,s]=[g,b,h];break;case 1:[o,c,s]=[d,g,h];break;case 2:[o,c,s]=[h,g,b];break;case 3:[o,c,s]=[h,d,g];break;case 4:[o,c,s]=[b,h,g];break;case 5:[o,c,s]=[g,h,d];break}}return[o,c,s,t.length>3?t[3]:1]},pn=(...t)=>{const[e,n,r]=x(t,"rgb"),o=oe(e,n,r),c=ce(e,n,r),s=c-o,f=s*100/255,a=o/(255-s)*100;let l;return s===0?l=Number.NaN:(e===c&&(l=(n-r)/s),n===c&&(l=2+(r-e)/s),r===c&&(l=4+(e-n)/s),l*=60,l<0&&(l+=360)),[l,f,a]};u.prototype.hcg=function(){return pn(this._rgb)};const gn=(...t)=>new u(...t,"hcg");$.hcg=gn;_.format.hcg=dn;_.autodetect.push({p:1,test:(...t)=>{if(t=x(t,"hcg"),A(t)==="array"&&t.length===3)return"hcg"}});const mn=(t,e,n)=>ct(t,e,n,"hcg");z.hcg=mn;const{cos:tt}=Math,yn=(...t)=>{t=x(t,"hsi");let[e,n,r]=t,o,c,s;return isNaN(e)&&(e=0),isNaN(n)&&(n=0),e>360&&(e-=360),e<0&&(e+=360),e/=360,e<1/3?(s=(1-n)/3,o=(1+n*tt(K*e)/tt(Mt-K*e))/3,c=1-(s+o)):e<2/3?(e-=1/3,o=(1-n)/3,c=(1+n*tt(K*e)/tt(Mt-K*e))/3,s=1-(o+c)):(e-=2/3,c=(1-n)/3,s=(1+n*tt(K*e)/tt(Mt-K*e))/3,o=1-(c+s)),o=J(r*o*3),c=J(r*c*3),s=J(r*s*3),[o*255,c*255,s*255,t.length>3?t[3]:1]},{min:wn,sqrt:kn,acos:_n}=Math,Mn=(...t)=>{let[e,n,r]=x(t,"rgb");e/=255,n/=255,r/=255;let o;const c=wn(e,n,r),s=(e+n+r)/3,f=s>0?1-c/s:0;return f===0?o=NaN:(o=(e-n+(e-r))/2,o/=kn((e-n)*(e-n)+(e-r)*(n-r)),o=_n(o),r>n&&(o=K-o),o/=K),[o*360,f,s]};u.prototype.hsi=function(){return Mn(this._rgb)};const $n=(...t)=>new u(...t,"hsi");$.hsi=$n;_.format.hsi=yn;_.autodetect.push({p:2,test:(...t)=>{if(t=x(t,"hsi"),A(t)==="array"&&t.length===3)return"hsi"}});const xn=(t,e,n)=>ct(t,e,n,"hsi");z.hsi=xn;const Pt=(...t)=>{t=x(t,"hsl");const[e,n,r]=t;let o,c,s;if(n===0)o=c=s=r*255;else{const f=[0,0,0],a=[0,0,0],l=r<.5?r*(1+n):r+n-r*n,h=2*r-l,d=e/360;f[0]=d+1/3,f[1]=d,f[2]=d-1/3;for(let b=0;b<3;b++)f[b]<0&&(f[b]+=1),f[b]>1&&(f[b]-=1),6*f[b]<1?a[b]=h+(l-h)*6*f[b]:2*f[b]<1?a[b]=l:3*f[b]<2?a[b]=h+(l-h)*(2/3-f[b])*6:a[b]=h;[o,c,s]=[a[0]*255,a[1]*255,a[2]*255]}return t.length>3?[o,c,s,t[3]]:[o,c,s,1]},de=(...t)=>{t=x(t,"rgba");let[e,n,r]=t;e/=255,n/=255,r/=255;const o=oe(e,n,r),c=ce(e,n,r),s=(c+o)/2;let f,a;return c===o?(f=0,a=Number.NaN):f=s<.5?(c-o)/(c+o):(c-o)/(2-c-o),e==c?a=(n-r)/(c-o):n==c?a=2+(r-e)/(c-o):r==c&&(a=4+(e-n)/(c-o)),a*=60,a<0&&(a+=360),t.length>3&&t[3]!==void 0?[a,f,s,t[3]]:[a,f,s]};u.prototype.hsl=function(){return de(this._rgb)};const En=(...t)=>new u(...t,"hsl");$.hsl=En;_.format.hsl=Pt;_.autodetect.push({p:2,test:(...t)=>{if(t=x(t,"hsl"),A(t)==="array"&&t.length===3)return"hsl"}});const An=(t,e,n)=>ct(t,e,n,"hsl");z.hsl=An;const{floor:Ln}=Math,Nn=(...t)=>{t=x(t,"hsv");let[e,n,r]=t,o,c,s;if(r*=255,n===0)o=c=s=r;else{e===360&&(e=0),e>360&&(e-=360),e<0&&(e+=360),e/=60;const f=Ln(e),a=e-f,l=r*(1-n),h=r*(1-n*a),d=r*(1-n*(1-a));switch(f){case 0:[o,c,s]=[r,d,l];break;case 1:[o,c,s]=[h,r,l];break;case 2:[o,c,s]=[l,r,d];break;case 3:[o,c,s]=[l,h,r];break;case 4:[o,c,s]=[d,l,r];break;case 5:[o,c,s]=[r,l,h];break}}return[o,c,s,t.length>3?t[3]:1]},{min:Rn,max:Cn}=Math,jn=(...t)=>{t=x(t,"rgb");let[e,n,r]=t;const o=Rn(e,n,r),c=Cn(e,n,r),s=c-o;let f,a,l;return l=c/255,c===0?(f=Number.NaN,a=0):(a=s/c,e===c&&(f=(n-r)/s),n===c&&(f=2+(r-e)/s),r===c&&(f=4+(e-n)/s),f*=60,f<0&&(f+=360)),[f,a,l]};u.prototype.hsv=function(){return jn(this._rgb)};const vn=(...t)=>new u(...t,"hsv");$.hsv=vn;_.format.hsv=Nn;_.autodetect.push({p:2,test:(...t)=>{if(t=x(t,"hsv"),A(t)==="array"&&t.length===3)return"hsv"}});const Pn=(t,e,n)=>ct(t,e,n,"hsv");z.hsv=Pn;function gt(t,e){let n=t.length;Array.isArray(t[0])||(t=[t]),Array.isArray(e[0])||(e=e.map(s=>[s]));let r=e[0].length,o=e[0].map((s,f)=>e.map(a=>a[f])),c=t.map(s=>o.map(f=>Array.isArray(s)?s.reduce((a,l,h)=>a+l*(f[h]||0),0):f.reduce((a,l)=>a+l*s,0)));return n===1&&(c=c[0]),r===1?c.map(s=>s[0]):c}const St=(...t)=>{t=x(t,"lab");const[e,n,r,...o]=t,[c,s,f]=On([e,n,r]),[a,l,h]=le(c,s,f);return[a,l,h,...o.length>0&&o[0]<1?[o[0]]:[]]};function On(t){var e=[[1.2268798758459243,-.5578149944602171,.2813910456659647],[-.0405757452148008,1.112286803280317,-.0717110580655164],[-.0763729366746601,-.4214933324022432,1.5869240198367816]],n=[[1,.3963377773761749,.2158037573099136],[1,-.1055613458156586,-.0638541728258133],[1,-.0894841775298119,-1.2914855480194092]],r=gt(n,t);return gt(e,r.map(o=>o**3))}const Xt=(...t)=>{const[e,n,r,...o]=x(t,"rgb"),c=ie(e,n,r);return[...Yn(c),...o.length>0&&o[0]<1?[o[0]]:[]]};function Yn(t){const e=[[.819022437996703,.3619062600528904,-.1288737815209879],[.0329836539323885,.9292868615863434,.0361446663506424],[.0481771893596242,.2642395317527308,.6335478284694309]],n=[[.210454268309314,.7936177747023054,-.0040720430116193],[1.9779985324311684,-2.42859224204858,.450593709617411],[.0259040424655478,.7827717124575296,-.8086757549230774]],r=gt(e,t);return gt(n,r.map(o=>Math.cbrt(o)))}u.prototype.oklab=function(){return Xt(this._rgb)};const zn=(...t)=>new u(...t,"oklab");Object.assign($,{oklab:zn});_.format.oklab=St;_.autodetect.push({p:2,test:(...t)=>{if(t=x(t,"oklab"),A(t)==="array"&&t.length===3)return"oklab"}});const Gn=(t,e,n)=>{const r=t.oklab(),o=e.oklab();return new u(r[0]+n*(o[0]-r[0]),r[1]+n*(o[1]-r[1]),r[2]+n*(o[2]-r[2]),"oklab")};z.oklab=Gn;const qn=(t,e,n)=>ct(t,e,n,"oklch");z.oklch=qn;const{pow:Lt,sqrt:Nt,PI:Rt,cos:Tt,sin:Ht,atan2:Bn}=Math,Sn=(t,e="lrgb",n=null)=>{const r=t.length;n||(n=Array.from(new Array(r)).map(()=>1));const o=r/n.reduce(function(d,b){return d+b});if(n.forEach((d,b)=>{n[b]*=o}),t=t.map(d=>new u(d)),e==="lrgb")return Xn(t,n);const c=t.shift(),s=c.get(e),f=[];let a=0,l=0;for(let d=0;d{const g=d.get(e);h+=d.alpha()*n[b+1];for(let M=0;M=360;)b-=360;s[d]=b}else s[d]=s[d]/f[d];return h/=r,new u(s,e).alpha(h>.99999?1:h,!0)},Xn=(t,e)=>{const n=t.length,r=[0,0,0,0];for(let o=0;o.9999999&&(r[3]=1),new u(Yt(r))},{pow:Zn}=Math;function mt(t){let e="rgb",n=$("#ccc"),r=0,o=[0,1],c=[0,1],s=[],f=[0,0],a=!1,l=[],h=!1,d=0,b=1,g=!1,M={},N=!0,m=1;const y=function(i){if(i=i||["#fff","#000"],i&&A(i)==="string"&&$.brewer&&$.brewer[i.toLowerCase()]&&(i=$.brewer[i.toLowerCase()]),A(i)==="array"){i.length===1&&(i=[i[0],i[0]]),i=i.slice(0);for(let p=0;p=a[E];)E++;return E-1}return 0};let C=i=>i,P=i=>i;const O=function(i,p){let E,w;if(p==null&&(p=!1),isNaN(i)||i===null)return n;p?w=i:a&&a.length>2?w=Y(i)/(a.length-2):b!==d?w=(i-d)/(b-d):w=1,w=P(w),p||(w=C(w)),m!==1&&(w=Zn(w,m)),w=f[0]+w*(1-f[0]-f[1]),w=J(w,0,1);const R=Math.floor(w*1e4);if(N&&M[R])E=M[R];else{if(A(l)==="array")for(let k=0;k=G&&k===s.length-1){E=l[k];break}if(w>G&&wM={};y(t);const L=function(i){const p=$(O(i));return h&&p[h]?p[h]():p};return L.classes=function(i){if(i!=null){if(A(i)==="array")a=i,o=[i[0],i[i.length-1]];else{const p=$.analyze(o);i===0?a=[p.min,p.max]:a=$.limits(p,"e",i)}return L}return a},L.domain=function(i){if(!arguments.length)return c;c=i.slice(0),d=i[0],b=i[i.length-1],s=[];const p=l.length;if(i.length===p&&d!==b)for(let E of Array.from(i))s.push((E-d)/(b-d));else{for(let E=0;E2){const E=i.map((R,k)=>k/(i.length-1)),w=i.map(R=>(R-d)/(b-d));w.every((R,k)=>E[k]===R)||(P=R=>{if(R<=0||R>=1)return R;let k=0;for(;R>=w[k+1];)k++;const G=(R-w[k])/(w[k+1]-w[k]);return E[k]+G*(E[k+1]-E[k])})}}return o=[d,b],L},L.mode=function(i){return arguments.length?(e=i,B(),L):e},L.range=function(i,p){return y(i),L},L.out=function(i){return h=i,L},L.spread=function(i){return arguments.length?(r=i,L):r},L.correctLightness=function(i){return i==null&&(i=!0),g=i,B(),g?C=function(p){const E=O(0,!0).lab()[0],w=O(1,!0).lab()[0],R=E>w;let k=O(p,!0).lab()[0];const G=E+(w-E)*p;let F=k-G,it=0,at=1,ut=20;for(;Math.abs(F)>.01&&ut-- >0;)(function(){return R&&(F*=-1),F<0?(it=p,p+=(at-p)*.5):(at=p,p+=(it-p)*.5),k=O(p,!0).lab()[0],F=k-G})();return p}:C=p=>p,L},L.padding=function(i){return i!=null?(A(i)==="number"&&(i=[i,i]),f=i,L):f},L.colors=function(i,p){arguments.length<2&&(p="hex");let E=[];if(arguments.length===0)E=l.slice(0);else if(i===1)E=[L(.5)];else if(i>1){const w=o[0],R=o[1]-w;E=In(0,i).map(k=>L(w+k/(i-1)*R))}else{t=[];let w=[];if(a&&a.length>2)for(let R=1,k=a.length,G=1<=k;G?Rk;G?R++:R--)w.push((a[R-1]+a[R])*.5);else w=o;E=w.map(R=>L(R))}return $[p]&&(E=E.map(w=>w[p]())),E},L.cache=function(i){return i!=null?(N=i,L):N},L.gamma=function(i){return i!=null?(m=i,L):m},L.nodata=function(i){return i!=null?(n=$(i),L):n},L}function In(t,e,n){let r=[],o=tc;o?s++:s--)r.push(s);return r}const Tn=function(t){let e=[1,1];for(let n=1;nnew u(c)),t.length===2)[n,r]=t.map(c=>c.lab()),e=function(c){const s=[0,1,2].map(f=>n[f]+c*(r[f]-n[f]));return new u(s,"lab")};else if(t.length===3)[n,r,o]=t.map(c=>c.lab()),e=function(c){const s=[0,1,2].map(f=>(1-c)*(1-c)*n[f]+2*(1-c)*c*r[f]+c*c*o[f]);return new u(s,"lab")};else if(t.length===4){let c;[n,r,o,c]=t.map(s=>s.lab()),e=function(s){const f=[0,1,2].map(a=>(1-s)*(1-s)*(1-s)*n[a]+3*(1-s)*(1-s)*s*r[a]+3*(1-s)*s*s*o[a]+s*s*s*c[a]);return new u(f,"lab")}}else if(t.length>=5){let c,s,f;c=t.map(a=>a.lab()),f=t.length-1,s=Tn(f),e=function(a){const l=1-a,h=[0,1,2].map(d=>c.reduce((b,g,M)=>b+s[M]*l**(f-M)*a**M*g[d],0));return new u(h,"lab")}}else throw new RangeError("No point in running bezier with only one color.");return e},Kn=t=>{const e=Hn(t);return e.scale=()=>mt(e),e},{round:pe}=Math;u.prototype.rgb=function(t=!0){return t===!1?this._rgb.slice(0,3):this._rgb.slice(0,3).map(pe)};u.prototype.rgba=function(t=!0){return this._rgb.slice(0,4).map((e,n)=>n<3?t===!1?e:pe(e):e)};const Wn=(...t)=>new u(...t,"rgb");Object.assign($,{rgb:Wn});_.format.rgb=(...t)=>{const e=x(t,"rgba");return e[3]===void 0&&(e[3]=1),e};_.autodetect.push({p:3,test:(...t)=>{if(t=x(t,"rgba"),A(t)==="array"&&(t.length===3||t.length===4&&A(t[3])=="number"&&t[3]>=0&&t[3]<=1))return"rgb"}});const I=(t,e,n)=>{if(!I[n])throw new Error("unknown blend mode "+n);return I[n](t,e)},U=t=>(e,n)=>{const r=$(n).rgb(),o=$(e).rgb();return $.rgb(t(r,o))},V=t=>(e,n)=>{const r=[];return r[0]=t(e[0],n[0]),r[1]=t(e[1],n[1]),r[2]=t(e[2],n[2]),r},Dn=t=>t,Fn=(t,e)=>t*e/255,Un=(t,e)=>t>e?e:t,Vn=(t,e)=>t>e?t:e,Jn=(t,e)=>255*(1-(1-t/255)*(1-e/255)),Qn=(t,e)=>e<128?2*t*e/255:255*(1-2*(1-t/255)*(1-e/255)),tr=(t,e)=>255*(1-(1-e/255)/(t/255)),er=(t,e)=>t===255?255:(t=255*(e/255)/(1-t/255),t>255?255:t);I.normal=U(V(Dn));I.multiply=U(V(Fn));I.screen=U(V(Jn));I.overlay=U(V(Qn));I.darken=U(V(Un));I.lighten=U(V(Vn));I.dodge=U(V(er));I.burn=U(V(tr));const{pow:nr,sin:rr,cos:or}=Math;function cr(t=300,e=-1.5,n=1,r=1,o=[0,1]){let c=0,s;A(o)==="array"?s=o[1]-o[0]:(s=0,o=[o,o]);const f=function(a){const l=K*((t+120)/360+e*a),h=nr(o[0]+s*a,r),b=(c!==0?n[0]+a*c:n)*h*(1-h)/2,g=or(l),M=rr(l),N=h+b*(-.14861*g+1.78277*M),m=h+b*(-.29227*g-.90649*M),y=h+b*(1.97294*g);return $(Yt([N*255,m*255,y*255,1]))};return f.start=function(a){return a==null?t:(t=a,f)},f.rotations=function(a){return a==null?e:(e=a,f)},f.gamma=function(a){return a==null?r:(r=a,f)},f.hue=function(a){return a==null?n:(n=a,A(n)==="array"?(c=n[1]-n[0],c===0&&(n=n[1])):c=0,f)},f.lightness=function(a){return a==null?o:(A(a)==="array"?(o=a,s=a[1]-a[0]):(o=[a,a],s=0),f)},f.scale=()=>$.scale(f),f.hue(n),f}const sr="0123456789abcdef",{floor:fr,random:ar}=Math,lr=(t=ar)=>{let e="#";for(let n=0;n<6;n++)e+=sr.charAt(fr(t()*16));return new u(e,"hex")},{log:Kt,pow:ir,floor:ur,abs:br}=Math;function ge(t,e=null){const n={min:Number.MAX_VALUE,max:Number.MAX_VALUE*-1,sum:0,values:[],count:0};return A(t)==="object"&&(t=Object.values(t)),t.forEach(r=>{e&&A(r)==="object"&&(r=r[e]),r!=null&&!isNaN(r)&&(n.values.push(r),n.sum+=r,rn.max&&(n.max=r),n.count+=1)}),n.domain=[n.min,n.max],n.limits=(r,o)=>me(n,r,o),n}function me(t,e="equal",n=7){A(t)=="array"&&(t=ge(t));const{min:r,max:o}=t,c=t.values.sort((f,a)=>f-a);if(n===1)return[r,o];const s=[];if(e.substr(0,1)==="c"&&(s.push(r),s.push(o)),e.substr(0,1)==="e"){s.push(r);for(let f=1;f 0");const f=Math.LOG10E*Kt(r),a=Math.LOG10E*Kt(o);s.push(r);for(let l=1;l200&&(d=!1)}const M={};for(let m=0;mm-y),s.push(N[0]);for(let m=1;m{t=new u(t),e=new u(e);const n=t.luminance(),r=e.luminance();return n>r?(n+.05)/(r+.05):(r+.05)/(n+.05)};/** + * @license + * + * The APCA contrast prediction algorithm is based of the formulas published + * in the APCA-1.0.98G specification by Myndex. The specification is available at: + * https://raw.githubusercontent.com/Myndex/apca-w3/master/images/APCAw3_0.1.17_APCA0.0.98G.svg + * + * Note that the APCA implementation is still beta, so please update to + * future versions of chroma.js when they become available. + * + * You can read more about the APCA Readability Criterion at + * https://readtech.org/ARC/ + */const Wt=.027,dr=5e-4,pr=.1,Dt=1.14,ht=.022,Ft=1.414,gr=(t,e)=>{t=new u(t),e=new u(e),t.alpha()<1&&(t=rt(e,t,t.alpha(),"rgb"));const n=Ut(...t.rgb()),r=Ut(...e.rgb()),o=n>=ht?n:n+Math.pow(ht-n,Ft),c=r>=ht?r:r+Math.pow(ht-r,Ft),s=Math.pow(c,.56)-Math.pow(o,.57),f=Math.pow(c,.65)-Math.pow(o,.62),a=Math.abs(c-o)0?a-Wt:a+Wt)*100};function Ut(t,e,n){return .2126729*Math.pow(t/255,2.4)+.7151522*Math.pow(e/255,2.4)+.072175*Math.pow(n/255,2.4)}const{sqrt:H,pow:j,min:mr,max:yr,atan2:Vt,abs:Jt,cos:dt,sin:Qt,exp:wr,PI:te}=Math;function kr(t,e,n=1,r=1,o=1){var c=function(_t){return 360*_t/(2*te)},s=function(_t){return 2*te*_t/360};t=new u(t),e=new u(e);const[f,a,l]=Array.from(t.lab()),[h,d,b]=Array.from(e.lab()),g=(f+h)/2,M=H(j(a,2)+j(l,2)),N=H(j(d,2)+j(b,2)),m=(M+N)/2,y=.5*(1-H(j(m,7)/(j(m,7)+j(25,7)))),Y=a*(1+y),C=d*(1+y),P=H(j(Y,2)+j(l,2)),O=H(j(C,2)+j(b,2)),B=(P+O)/2,L=c(Vt(l,Y)),i=c(Vt(b,C)),p=L>=0?L:L+360,E=i>=0?i:i+360,w=Jt(p-E)>180?(p+E+360)/2:(p+E)/2,R=1-.17*dt(s(w-30))+.24*dt(s(2*w))+.32*dt(s(3*w+6))-.2*dt(s(4*w-63));let k=E-p;k=Jt(k)<=180?k:E<=p?k+360:k-360,k=2*H(P*O)*Qt(s(k)/2);const G=h-f,F=O-P,it=1+.015*j(g-50,2)/H(20+j(g-50,2)),at=1+.045*B,ut=1+.015*B*R,Pe=30*wr(-j((w-275)/25,2)),Oe=-(2*H(j(B,7)/(j(B,7)+j(25,7))))*Qt(2*s(Pe)),Ye=H(j(G/(n*it),2)+j(F/(r*at),2)+j(k/(o*ut),2)+Oe*(F/(r*at))*(k/(o*ut)));return yr(0,mr(100,Ye))}function _r(t,e,n="lab"){t=new u(t),e=new u(e);const r=t.get(n),o=e.get(n);let c=0;for(let s in r){const f=(r[s]||0)-(o[s]||0);c+=f*f}return Math.sqrt(c)}const Mr=(...t)=>{try{return new u(...t),!0}catch{return!1}},$r={cool(){return mt([$.hsl(180,1,.9),$.hsl(250,.7,.4)])},hot(){return mt(["#000","#f00","#ff0","#fff"]).mode("rgb")}},Ot={OrRd:["#fff7ec","#fee8c8","#fdd49e","#fdbb84","#fc8d59","#ef6548","#d7301f","#b30000","#7f0000"],PuBu:["#fff7fb","#ece7f2","#d0d1e6","#a6bddb","#74a9cf","#3690c0","#0570b0","#045a8d","#023858"],BuPu:["#f7fcfd","#e0ecf4","#bfd3e6","#9ebcda","#8c96c6","#8c6bb1","#88419d","#810f7c","#4d004b"],Oranges:["#fff5eb","#fee6ce","#fdd0a2","#fdae6b","#fd8d3c","#f16913","#d94801","#a63603","#7f2704"],BuGn:["#f7fcfd","#e5f5f9","#ccece6","#99d8c9","#66c2a4","#41ae76","#238b45","#006d2c","#00441b"],YlOrBr:["#ffffe5","#fff7bc","#fee391","#fec44f","#fe9929","#ec7014","#cc4c02","#993404","#662506"],YlGn:["#ffffe5","#f7fcb9","#d9f0a3","#addd8e","#78c679","#41ab5d","#238443","#006837","#004529"],Reds:["#fff5f0","#fee0d2","#fcbba1","#fc9272","#fb6a4a","#ef3b2c","#cb181d","#a50f15","#67000d"],RdPu:["#fff7f3","#fde0dd","#fcc5c0","#fa9fb5","#f768a1","#dd3497","#ae017e","#7a0177","#49006a"],Greens:["#f7fcf5","#e5f5e0","#c7e9c0","#a1d99b","#74c476","#41ab5d","#238b45","#006d2c","#00441b"],YlGnBu:["#ffffd9","#edf8b1","#c7e9b4","#7fcdbb","#41b6c4","#1d91c0","#225ea8","#253494","#081d58"],Purples:["#fcfbfd","#efedf5","#dadaeb","#bcbddc","#9e9ac8","#807dba","#6a51a3","#54278f","#3f007d"],GnBu:["#f7fcf0","#e0f3db","#ccebc5","#a8ddb5","#7bccc4","#4eb3d3","#2b8cbe","#0868ac","#084081"],Greys:["#ffffff","#f0f0f0","#d9d9d9","#bdbdbd","#969696","#737373","#525252","#252525","#000000"],YlOrRd:["#ffffcc","#ffeda0","#fed976","#feb24c","#fd8d3c","#fc4e2a","#e31a1c","#bd0026","#800026"],PuRd:["#f7f4f9","#e7e1ef","#d4b9da","#c994c7","#df65b0","#e7298a","#ce1256","#980043","#67001f"],Blues:["#f7fbff","#deebf7","#c6dbef","#9ecae1","#6baed6","#4292c6","#2171b5","#08519c","#08306b"],PuBuGn:["#fff7fb","#ece2f0","#d0d1e6","#a6bddb","#67a9cf","#3690c0","#02818a","#016c59","#014636"],Viridis:["#440154","#482777","#3f4a8a","#31678e","#26838f","#1f9d8a","#6cce5a","#b6de2b","#fee825"],Spectral:["#9e0142","#d53e4f","#f46d43","#fdae61","#fee08b","#ffffbf","#e6f598","#abdda4","#66c2a5","#3288bd","#5e4fa2"],RdYlGn:["#a50026","#d73027","#f46d43","#fdae61","#fee08b","#ffffbf","#d9ef8b","#a6d96a","#66bd63","#1a9850","#006837"],RdBu:["#67001f","#b2182b","#d6604d","#f4a582","#fddbc7","#f7f7f7","#d1e5f0","#92c5de","#4393c3","#2166ac","#053061"],PiYG:["#8e0152","#c51b7d","#de77ae","#f1b6da","#fde0ef","#f7f7f7","#e6f5d0","#b8e186","#7fbc41","#4d9221","#276419"],PRGn:["#40004b","#762a83","#9970ab","#c2a5cf","#e7d4e8","#f7f7f7","#d9f0d3","#a6dba0","#5aae61","#1b7837","#00441b"],RdYlBu:["#a50026","#d73027","#f46d43","#fdae61","#fee090","#ffffbf","#e0f3f8","#abd9e9","#74add1","#4575b4","#313695"],BrBG:["#543005","#8c510a","#bf812d","#dfc27d","#f6e8c3","#f5f5f5","#c7eae5","#80cdc1","#35978f","#01665e","#003c30"],RdGy:["#67001f","#b2182b","#d6604d","#f4a582","#fddbc7","#ffffff","#e0e0e0","#bababa","#878787","#4d4d4d","#1a1a1a"],PuOr:["#7f3b08","#b35806","#e08214","#fdb863","#fee0b6","#f7f7f7","#d8daeb","#b2abd2","#8073ac","#542788","#2d004b"],Set2:["#66c2a5","#fc8d62","#8da0cb","#e78ac3","#a6d854","#ffd92f","#e5c494","#b3b3b3"],Accent:["#7fc97f","#beaed4","#fdc086","#ffff99","#386cb0","#f0027f","#bf5b17","#666666"],Set1:["#e41a1c","#377eb8","#4daf4a","#984ea3","#ff7f00","#ffff33","#a65628","#f781bf","#999999"],Set3:["#8dd3c7","#ffffb3","#bebada","#fb8072","#80b1d3","#fdb462","#b3de69","#fccde5","#d9d9d9","#bc80bd","#ccebc5","#ffed6f"],Dark2:["#1b9e77","#d95f02","#7570b3","#e7298a","#66a61e","#e6ab02","#a6761d","#666666"],Paired:["#a6cee3","#1f78b4","#b2df8a","#33a02c","#fb9a99","#e31a1c","#fdbf6f","#ff7f00","#cab2d6","#6a3d9a","#ffff99","#b15928"],Pastel2:["#b3e2cd","#fdcdac","#cbd5e8","#f4cae4","#e6f5c9","#fff2ae","#f1e2cc","#cccccc"],Pastel1:["#fbb4ae","#b3cde3","#ccebc5","#decbe4","#fed9a6","#ffffcc","#e5d8bd","#fddaec","#f2f2f2"]},ye=Object.keys(Ot),ee=new Map(ye.map(t=>[t.toLowerCase(),t])),xr=typeof Proxy=="function"?new Proxy(Ot,{get(t,e){const n=e.toLowerCase();if(ee.has(n))return t[ee.get(n)]},getOwnPropertyNames(){return Object.getOwnPropertyNames(ye)}}):Ot,Er=(...t)=>{t=x(t,"cmyk");const[e,n,r,o]=t,c=t.length>4?t[4]:1;return o===1?[0,0,0,c]:[e>=1?0:255*(1-e)*(1-o),n>=1?0:255*(1-n)*(1-o),r>=1?0:255*(1-r)*(1-o),c]},{max:ne}=Math,Ar=(...t)=>{let[e,n,r]=x(t,"rgb");e=e/255,n=n/255,r=r/255;const o=1-ne(e,ne(n,r)),c=o<1?1/(1-o):0,s=(1-e-o)*c,f=(1-n-o)*c,a=(1-r-o)*c;return[s,f,a,o]};u.prototype.cmyk=function(){return Ar(this._rgb)};const Lr=(...t)=>new u(...t,"cmyk");Object.assign($,{cmyk:Lr});_.format.cmyk=Er;_.autodetect.push({p:2,test:(...t)=>{if(t=x(t,"cmyk"),A(t)==="array"&&t.length===4)return"cmyk"}});const Nr=(...t)=>{const e=x(t,"hsla");let n=ot(t)||"lsa";return e[0]=S(e[0]||0)+"deg",e[1]=S(e[1]*100)+"%",e[2]=S(e[2]*100)+"%",n==="hsla"||e.length>3&&e[3]<1?(e[3]="/ "+(e.length>3?e[3]:1),n="hsla"):e.length=3,`${n.substr(0,3)}(${e.join(" ")})`},Rr=(...t)=>{const e=x(t,"lab");let n=ot(t)||"lab";return e[0]=S(e[0])+"%",e[1]=S(e[1]),e[2]=S(e[2]),n==="laba"||e.length>3&&e[3]<1?e[3]="/ "+(e.length>3?e[3]:1):e.length=3,`lab(${e.join(" ")})`},Cr=(...t)=>{const e=x(t,"lch");let n=ot(t)||"lab";return e[0]=S(e[0])+"%",e[1]=S(e[1]),e[2]=isNaN(e[2])?"none":S(e[2])+"deg",n==="lcha"||e.length>3&&e[3]<1?e[3]="/ "+(e.length>3?e[3]:1):e.length=3,`lch(${e.join(" ")})`},jr=(...t)=>{const e=x(t,"lab");return e[0]=S(e[0]*100)+"%",e[1]=vt(e[1]),e[2]=vt(e[2]),e.length>3&&e[3]<1?e[3]="/ "+(e.length>3?e[3]:1):e.length=3,`oklab(${e.join(" ")})`},we=(...t)=>{const[e,n,r,...o]=x(t,"rgb"),[c,s,f]=Xt(e,n,r),[a,l,h]=be(c,s,f);return[a,l,h,...o.length>0&&o[0]<1?[o[0]]:[]]},vr=(...t)=>{const e=x(t,"lch");return e[0]=S(e[0]*100)+"%",e[1]=vt(e[1]),e[2]=isNaN(e[2])?"none":S(e[2])+"deg",e.length>3&&e[3]<1?e[3]="/ "+(e.length>3?e[3]:1):e.length=3,`oklch(${e.join(" ")})`},{round:Ct}=Math,Pr=(...t)=>{const e=x(t,"rgba");let n=ot(t)||"rgb";if(n.substr(0,3)==="hsl")return Nr(de(e),n);if(n.substr(0,3)==="lab"){const r=lt();W("d50");const o=Rr(Gt(e),n);return W(r),o}if(n.substr(0,3)==="lch"){const r=lt();W("d50");const o=Cr(Bt(e),n);return W(r),o}return n.substr(0,5)==="oklab"?jr(Xt(e)):n.substr(0,5)==="oklch"?vr(we(e)):(e[0]=Ct(e[0]),e[1]=Ct(e[1]),e[2]=Ct(e[2]),(n==="rgba"||e.length>3&&e[3]<1)&&(e[3]="/ "+(e.length>3?e[3]:1),n="rgba"),`${n.substr(0,3)}(${e.slice(0,n==="rgb"?3:4).join(" ")})`)},ke=(...t)=>{t=x(t,"lch");const[e,n,r,...o]=t,[c,s,f]=ue(e,n,r),[a,l,h]=St(c,s,f);return[a,l,h,...o.length>0&&o[0]<1?[o[0]]:[]]},D=/((?:-?\d+)|(?:-?\d+(?:\.\d+)?)%|none)/.source,Z=/((?:-?(?:\d+(?:\.\d*)?|\.\d+)%?)|none)/.source,yt=/((?:-?(?:\d+(?:\.\d*)?|\.\d+)%)|none)/.source,X=/\s*/.source,st=/\s+/.source,Zt=/\s*,\s*/.source,kt=/((?:-?(?:\d+(?:\.\d*)?|\.\d+)(?:deg)?)|none)/.source,ft=/\s*(?:\/\s*((?:[01]|[01]?\.\d+)|\d+(?:\.\d+)?%))?/.source,_e=new RegExp("^rgba?\\("+X+[D,D,D].join(st)+ft+"\\)$"),Me=new RegExp("^rgb\\("+X+[D,D,D].join(Zt)+X+"\\)$"),$e=new RegExp("^rgba\\("+X+[D,D,D,Z].join(Zt)+X+"\\)$"),xe=new RegExp("^hsla?\\("+X+[kt,yt,yt].join(st)+ft+"\\)$"),Ee=new RegExp("^hsl?\\("+X+[kt,yt,yt].join(Zt)+X+"\\)$"),Ae=/^hsla\(\s*(-?\d+(?:\.\d+)?),\s*(-?\d+(?:\.\d+)?)%\s*,\s*(-?\d+(?:\.\d+)?)%\s*,\s*([01]|[01]?\.\d+)\)$/,Le=new RegExp("^lab\\("+X+[Z,Z,Z].join(st)+ft+"\\)$"),Ne=new RegExp("^lch\\("+X+[Z,Z,kt].join(st)+ft+"\\)$"),Re=new RegExp("^oklab\\("+X+[Z,Z,Z].join(st)+ft+"\\)$"),Ce=new RegExp("^oklch\\("+X+[Z,Z,kt].join(st)+ft+"\\)$"),{round:je}=Math,et=t=>t.map((e,n)=>n<=2?J(je(e),0,255):e),v=(t,e=0,n=100,r=!1)=>(typeof t=="string"&&t.endsWith("%")&&(t=parseFloat(t.substring(0,t.length-1))/100,r?t=e+(t+1)*.5*(n-e):t=e+t*(n-e)),+t),q=(t,e)=>t==="none"?e:t,It=t=>{if(t=t.toLowerCase().trim(),t==="transparent")return[0,0,0,0];let e;if(_.format.named)try{return _.format.named(t)}catch{}if((e=t.match(_e))||(e=t.match(Me))){let n=e.slice(1,4);for(let o=0;o<3;o++)n[o]=+v(q(n[o],0),0,255);n=et(n);const r=e[4]!==void 0?+v(e[4],0,1):1;return n[3]=r,n}if(e=t.match($e)){const n=e.slice(1,5);for(let r=0;r<4;r++)n[r]=+v(n[r],0,255);return n}if((e=t.match(xe))||(e=t.match(Ee))){const n=e.slice(1,4);n[0]=+q(n[0].replace("deg",""),0),n[1]=+v(q(n[1],0),0,100)*.01,n[2]=+v(q(n[2],0),0,100)*.01;const r=et(Pt(n)),o=e[4]!==void 0?+v(e[4],0,1):1;return r[3]=o,r}if(e=t.match(Ae)){const n=e.slice(1,4);n[1]*=.01,n[2]*=.01;const r=Pt(n);for(let o=0;o<3;o++)r[o]=je(r[o]);return r[3]=+e[4],r}if(e=t.match(Le)){const n=e.slice(1,4);n[0]=v(q(n[0],0),0,100),n[1]=v(q(n[1],0),-125,125,!0),n[2]=v(q(n[2],0),-125,125,!0);const r=lt();W("d50");const o=et(zt(n));W(r);const c=e[4]!==void 0?+v(e[4],0,1):1;return o[3]=c,o}if(e=t.match(Ne)){const n=e.slice(1,4);n[0]=v(n[0],0,100),n[1]=v(q(n[1],0),0,150,!1),n[2]=+q(n[2].replace("deg",""),0);const r=lt();W("d50");const o=et(qt(n));W(r);const c=e[4]!==void 0?+v(e[4],0,1):1;return o[3]=c,o}if(e=t.match(Re)){const n=e.slice(1,4);n[0]=v(q(n[0],0),0,1),n[1]=v(q(n[1],0),-.4,.4,!0),n[2]=v(q(n[2],0),-.4,.4,!0);const r=et(St(n)),o=e[4]!==void 0?+v(e[4],0,1):1;return r[3]=o,r}if(e=t.match(Ce)){const n=e.slice(1,4);n[0]=v(q(n[0],0),0,1),n[1]=v(q(n[1],0),0,.4,!1),n[2]=+q(n[2].replace("deg",""),0);const r=et(ke(n)),o=e[4]!==void 0?+v(e[4],0,1):1;return r[3]=o,r}};It.test=t=>_e.test(t)||xe.test(t)||Le.test(t)||Ne.test(t)||Re.test(t)||Ce.test(t)||Me.test(t)||$e.test(t)||Ee.test(t)||Ae.test(t)||t==="transparent";u.prototype.css=function(t){return Pr(this._rgb,t)};const Or=(...t)=>new u(...t,"css");$.css=Or;_.format.css=It;_.autodetect.push({p:5,test:(t,...e)=>{if(!e.length&&A(t)==="string"&&It.test(t))return"css"}});_.format.gl=(...t)=>{const e=x(t,"rgba");return e[0]*=255,e[1]*=255,e[2]*=255,e};const Yr=(...t)=>new u(...t,"gl");$.gl=Yr;u.prototype.gl=function(){const t=this._rgb;return[t[0]/255,t[1]/255,t[2]/255,t[3]]};u.prototype.hex=function(t){return ae(this._rgb,t)};const zr=(...t)=>new u(...t,"hex");$.hex=zr;_.format.hex=fe;_.autodetect.push({p:4,test:(t,...e)=>{if(!e.length&&A(t)==="string"&&[3,4,5,6,7,8,9].indexOf(t.length)>=0)return"hex"}});const{log:pt}=Math,ve=t=>{const e=t/100;let n,r,o;return e<66?(n=255,r=e<6?0:-155.25485562709179-.44596950469579133*(r=e-2)+104.49216199393888*pt(r),o=e<20?0:-254.76935184120902+.8274096064007395*(o=e-10)+115.67994401066147*pt(o)):(n=351.97690566805693+.114206453784165*(n=e-55)-40.25366309332127*pt(n),r=325.4494125711974+.07943456536662342*(r=e-50)-28.0852963507957*pt(r),o=255),[n,r,o,1]},{round:Gr}=Math,qr=(...t)=>{const e=x(t,"rgb"),n=e[0],r=e[2];let o=1e3,c=4e4;const s=.4;let f;for(;c-o>s;){f=(c+o)*.5;const a=ve(f);a[2]/a[0]>=r/n?c=f:o=f}return Gr(f)};u.prototype.temp=u.prototype.kelvin=u.prototype.temperature=function(){return qr(this._rgb)};const jt=(...t)=>new u(...t,"temp");Object.assign($,{temp:jt,kelvin:jt,temperature:jt});_.format.temp=_.format.kelvin=_.format.temperature=ve;u.prototype.oklch=function(){return we(this._rgb)};const Br=(...t)=>new u(...t,"oklch");Object.assign($,{oklch:Br});_.format.oklch=ke;_.autodetect.push({p:2,test:(...t)=>{if(t=x(t,"oklch"),A(t)==="array"&&t.length===3)return"oklch"}});Object.assign($,{analyze:ge,average:Sn,bezier:Kn,blend:I,brewer:xr,Color:u,colors:nt,contrast:hr,contrastAPCA:gr,cubehelix:cr,deltaE:kr,distance:_r,input:_,interpolate:rt,limits:me,mix:rt,random:lr,scale:mt,scales:$r,valid:Mr});function Hr(t){try{return $(t).hex()}catch{return t}}function Kr(t){try{const[e,n,r]=$(t).rgb();return{r:e,g:n,b:r}}catch{return{r:0,g:0,b:0}}}function Wr(t){try{const[e,n,r]=$(t).hsl();return{h:Math.round(isNaN(e)?0:e),s:Math.round(n*100),l:Math.round(r*100)}}catch{return{h:0,s:0,l:0}}}function Sr(t,e){try{return $.deltaE(t,e)}catch{return 1/0}}function Xr(t){try{const[,e]=$(t).hsl();return e<.1}catch{return!1}}function Dr(t){try{return $(t).alpha()===0}catch{return t==="transparent"||t==="rgba(0, 0, 0, 0)"}}function Fr(t,e=5){if(t.length===0)return[];const n=[...t].sort((o,c)=>c.frequency-o.frequency),r=[];for(const o of n){const c=r.find(s=>Sr(s.hex,o.hex)c.frequency-o.frequency)}function Ur(t){const e=[...t].sort((o,c)=>c.frequency-o.frequency),n=[],r=[];for(const o of e)Xr(o.hex)?n.push(o):r.push(o);for(const o of n){const c=$(o.hex).luminance();c>.85?o.category="background":c<.15?o.category="text":o.category="neutral"}return r.forEach((o,c)=>{c===0?o.category="primary":c===1?o.category="secondary":o.category="accent"}),[...r,...n]}export{Wr as a,Kr as b,Fr as c,Ur as d,Dr as i,Tr as o,Ir as s,Hr as t}; diff --git a/dist/assets/index-BNvlt7m8.css b/dist/assets/index-BNvlt7m8.css new file mode 100644 index 0000000..6a430ec --- /dev/null +++ b/dist/assets/index-BNvlt7m8.css @@ -0,0 +1 @@ +/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-x-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-ease:initial;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1}}}@layer theme{:root,:host{--font-sans:"Inter", ui-sans-serif, system-ui, sans-serif;--font-mono:"JetBrains Mono", ui-monospace, monospace;--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-orange-400:oklch(75% .183 55.934);--color-orange-500:oklch(70.5% .213 47.604);--color-amber-400:oklch(82.8% .189 84.429);--color-green-400:oklch(79.2% .209 151.711);--color-green-500:oklch(72.3% .219 149.579);--color-blue-400:oklch(70.7% .165 254.624);--color-blue-500:oklch(62.3% .214 259.815);--color-white:#fff;--spacing:.25rem;--font-weight-medium:500;--font-weight-semibold:600;--tracking-tight:-.025em;--tracking-wider:.05em;--leading-relaxed:1.625;--radius-sm:.25rem;--radius-md:.375rem;--radius-lg:.5rem;--radius-2xl:1rem;--drop-shadow-md:0 3px 3px #0000001f;--ease-out:cubic-bezier(0, 0, .2, 1);--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-panel-bg:#0c0c0e;--color-panel-surface:#161618;--color-panel-border:#222225;--color-panel-text:#ededef;--color-panel-text-dim:#7e7e85;--color-panel-accent:#6366f1;--color-panel-accent-hover:#818cf8;--color-success:#22c55e}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.pointer-events-none{pointer-events:none}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.top-0{top:calc(var(--spacing) * 0)}.top-0\.5{top:calc(var(--spacing) * .5)}.top-1\/2{top:50%}.top-2{top:calc(var(--spacing) * 2)}.top-full{top:100%}.right-0{right:calc(var(--spacing) * 0)}.right-0\.5{right:calc(var(--spacing) * .5)}.right-2{right:calc(var(--spacing) * 2)}.bottom-0{bottom:calc(var(--spacing) * 0)}.bottom-0\.5{bottom:calc(var(--spacing) * .5)}.bottom-full{bottom:100%}.left-0\.5{left:calc(var(--spacing) * .5)}.left-1{left:calc(var(--spacing) * 1)}.left-1\/2{left:50%}.z-10{z-index:10}.z-20{z-index:20}.col-span-2{grid-column:span 2/span 2}.container{width:100%}@media(min-width:40rem){.container{max-width:40rem}}@media(min-width:48rem){.container{max-width:48rem}}@media(min-width:64rem){.container{max-width:64rem}}@media(min-width:80rem){.container{max-width:80rem}}@media(min-width:96rem){.container{max-width:96rem}}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:calc(var(--spacing) * 1)}.mt-1\.5{margin-top:calc(var(--spacing) * 1.5)}.mt-2\.5{margin-top:calc(var(--spacing) * 2.5)}.mr-3{margin-right:calc(var(--spacing) * 3)}.mb-1{margin-bottom:calc(var(--spacing) * 1)}.mb-1\.5{margin-bottom:calc(var(--spacing) * 1.5)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.ml-auto{margin-left:auto}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-flex{display:inline-flex}.h-1\.5{height:calc(var(--spacing) * 1.5)}.h-2{height:calc(var(--spacing) * 2)}.h-3{height:calc(var(--spacing) * 3)}.h-5{height:calc(var(--spacing) * 5)}.h-6{height:calc(var(--spacing) * 6)}.h-16{height:calc(var(--spacing) * 16)}.h-\[2px\]{height:2px}.h-full{height:100%}.h-screen{height:100vh}.max-h-\[300px\]{max-height:300px}.w-1\.5{width:calc(var(--spacing) * 1.5)}.w-5{width:calc(var(--spacing) * 5)}.w-6{width:calc(var(--spacing) * 6)}.w-8{width:calc(var(--spacing) * 8)}.w-10{width:calc(var(--spacing) * 10)}.w-16{width:calc(var(--spacing) * 16)}.w-24{width:calc(var(--spacing) * 24)}.w-44{width:calc(var(--spacing) * 44)}.w-full{width:100%}.max-w-\[100px\]{max-width:100px}.max-w-\[180px\]{max-width:180px}.max-w-\[220px\]{max-width:220px}.min-w-0{min-width:calc(var(--spacing) * 0)}.min-w-\[200px\]{min-width:200px}.flex-1{flex:1}.shrink-0{flex-shrink:0}.-translate-x-1\/2{--tw-translate-x: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-y-1\/2{--tw-translate-y: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y)}.-rotate-90{rotate:-90deg}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.resize{resize:both}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-0{gap:calc(var(--spacing) * 0)}.gap-1{gap:calc(var(--spacing) * 1)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-2\.5{gap:calc(var(--spacing) * 2.5)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-5{gap:calc(var(--spacing) * 5)}:where(.-space-x-1\.5>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing) * -1.5) * var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing) * -1.5) * calc(1 - var(--tw-space-x-reverse)))}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-hidden{overflow:hidden}.overflow-x-hidden{overflow-x:hidden}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-sm{border-radius:var(--radius-sm)}.border{border-style:var(--tw-border-style);border-width:1px}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-blue-500\/40{border-color:#3080ff66}@supports (color:color-mix(in lab,red,red)){.border-blue-500\/40{border-color:color-mix(in oklab,var(--color-blue-500) 40%,transparent)}}.border-green-500\/40{border-color:#00c75866}@supports (color:color-mix(in lab,red,red)){.border-green-500\/40{border-color:color-mix(in oklab,var(--color-green-500) 40%,transparent)}}.border-orange-500\/40{border-color:#fe6e0066}@supports (color:color-mix(in lab,red,red)){.border-orange-500\/40{border-color:color-mix(in oklab,var(--color-orange-500) 40%,transparent)}}.border-panel-accent{border-color:var(--color-panel-accent)}.border-panel-accent\/30{border-color:#6366f14d}@supports (color:color-mix(in lab,red,red)){.border-panel-accent\/30{border-color:color-mix(in oklab,var(--color-panel-accent) 30%,transparent)}}.border-panel-border{border-color:var(--color-panel-border)}.border-panel-surface{border-color:var(--color-panel-surface)}.bg-blue-500\/5{background-color:#3080ff0d}@supports (color:color-mix(in lab,red,red)){.bg-blue-500\/5{background-color:color-mix(in oklab,var(--color-blue-500) 5%,transparent)}}.bg-green-500\/5{background-color:#00c7580d}@supports (color:color-mix(in lab,red,red)){.bg-green-500\/5{background-color:color-mix(in oklab,var(--color-green-500) 5%,transparent)}}.bg-orange-500\/5{background-color:#fe6e000d}@supports (color:color-mix(in lab,red,red)){.bg-orange-500\/5{background-color:color-mix(in oklab,var(--color-orange-500) 5%,transparent)}}.bg-panel-accent{background-color:var(--color-panel-accent)}.bg-panel-accent\/10{background-color:#6366f11a}@supports (color:color-mix(in lab,red,red)){.bg-panel-accent\/10{background-color:color-mix(in oklab,var(--color-panel-accent) 10%,transparent)}}.bg-panel-accent\/40{background-color:#6366f166}@supports (color:color-mix(in lab,red,red)){.bg-panel-accent\/40{background-color:color-mix(in oklab,var(--color-panel-accent) 40%,transparent)}}.bg-panel-bg{background-color:var(--color-panel-bg)}.bg-panel-bg\/80{background-color:#0c0c0ecc}@supports (color:color-mix(in lab,red,red)){.bg-panel-bg\/80{background-color:color-mix(in oklab,var(--color-panel-bg) 80%,transparent)}}.bg-panel-surface{background-color:var(--color-panel-surface)}.bg-panel-surface\/50{background-color:#16161880}@supports (color:color-mix(in lab,red,red)){.bg-panel-surface\/50{background-color:color-mix(in oklab,var(--color-panel-surface) 50%,transparent)}}.bg-success{background-color:var(--color-success)}.bg-success\/20{background-color:#22c55e33}@supports (color:color-mix(in lab,red,red)){.bg-success\/20{background-color:color-mix(in oklab,var(--color-success) 20%,transparent)}}.bg-success\/90{background-color:#22c55ee6}@supports (color:color-mix(in lab,red,red)){.bg-success\/90{background-color:color-mix(in oklab,var(--color-success) 90%,transparent)}}.p-0\.5{padding:calc(var(--spacing) * .5)}.p-1\.5{padding:calc(var(--spacing) * 1.5)}.p-2\.5{padding:calc(var(--spacing) * 2.5)}.p-3{padding:calc(var(--spacing) * 3)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.pt-1{padding-top:calc(var(--spacing) * 1)}.pt-3{padding-top:calc(var(--spacing) * 3)}.pr-10{padding-right:calc(var(--spacing) * 10)}.pb-0{padding-bottom:calc(var(--spacing) * 0)}.pb-2{padding-bottom:calc(var(--spacing) * 2)}.pb-3{padding-bottom:calc(var(--spacing) * 3)}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.font-mono{font-family:var(--font-mono)}.text-\[8px\]{font-size:8px}.text-\[9px\]{font-size:9px}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[12px\]{font-size:12px}.text-\[13px\]{font-size:13px}.text-\[14px\]{font-size:14px}.text-\[16px\]{font-size:16px}.leading-\[1\.6\]{--tw-leading:1.6;line-height:1.6}.leading-none{--tw-leading:1;line-height:1}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.break-all{word-break:break-all}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.text-amber-400{color:var(--color-amber-400)}.text-blue-400\/70{color:#54a2ffb3}@supports (color:color-mix(in lab,red,red)){.text-blue-400\/70{color:color-mix(in oklab,var(--color-blue-400) 70%,transparent)}}.text-green-400\/70{color:#05df72b3}@supports (color:color-mix(in lab,red,red)){.text-green-400\/70{color:color-mix(in oklab,var(--color-green-400) 70%,transparent)}}.text-orange-400\/70{color:#ff8b1ab3}@supports (color:color-mix(in lab,red,red)){.text-orange-400\/70{color:color-mix(in oklab,var(--color-orange-400) 70%,transparent)}}.text-panel-accent{color:var(--color-panel-accent)}.text-panel-text{color:var(--color-panel-text)}.text-panel-text-dim{color:var(--color-panel-text-dim)}.text-success{color:var(--color-success)}.text-white{color:var(--color-white)}.uppercase{text-transform:uppercase}.opacity-0{opacity:0}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a), 0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.drop-shadow-md{--tw-drop-shadow-size:drop-shadow(0 3px 3px var(--tw-drop-shadow-color,#0000001f));--tw-drop-shadow:drop-shadow(var(--drop-shadow-md));filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.backdrop-filter{-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[grid-template-rows\]{transition-property:grid-template-rows;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[width\]{transition-property:width;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-150{--tw-duration:.15s;transition-duration:.15s}.duration-200{--tw-duration:.2s;transition-duration:.2s}.duration-300{--tw-duration:.3s;transition-duration:.3s}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.select-none{-webkit-user-select:none;user-select:none}@media(hover:hover){.group-hover\:scale-105:is(:where(.group):hover *){--tw-scale-x:105%;--tw-scale-y:105%;--tw-scale-z:105%;scale:var(--tw-scale-x) var(--tw-scale-y)}.group-hover\:opacity-100:is(:where(.group):hover *){opacity:1}.hover\:scale-\[1\.15\]:hover{scale:1.15}.hover\:border-panel-accent\/40:hover{border-color:#6366f166}@supports (color:color-mix(in lab,red,red)){.hover\:border-panel-accent\/40:hover{border-color:color-mix(in oklab,var(--color-panel-accent) 40%,transparent)}}.hover\:border-panel-accent\/50:hover{border-color:#6366f180}@supports (color:color-mix(in lab,red,red)){.hover\:border-panel-accent\/50:hover{border-color:color-mix(in oklab,var(--color-panel-accent) 50%,transparent)}}.hover\:border-red-500\/50:hover{border-color:#fb2c3680}@supports (color:color-mix(in lab,red,red)){.hover\:border-red-500\/50:hover{border-color:color-mix(in oklab,var(--color-red-500) 50%,transparent)}}.hover\:bg-panel-accent-hover:hover{background-color:var(--color-panel-accent-hover)}.hover\:bg-panel-accent\/10:hover{background-color:#6366f11a}@supports (color:color-mix(in lab,red,red)){.hover\:bg-panel-accent\/10:hover{background-color:color-mix(in oklab,var(--color-panel-accent) 10%,transparent)}}.hover\:bg-panel-bg:hover{background-color:var(--color-panel-bg)}.hover\:bg-panel-surface:hover{background-color:var(--color-panel-surface)}.hover\:text-panel-accent:hover{color:var(--color-panel-accent)}.hover\:text-panel-accent-hover:hover{color:var(--color-panel-accent-hover)}.hover\:text-panel-text:hover{color:var(--color-panel-text)}.hover\:text-red-400:hover{color:var(--color-red-400)}}.focus\:border-panel-accent:focus{border-color:var(--color-panel-accent)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.focus-visible\:ring-2:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-visible\:ring-panel-accent:focus-visible{--tw-ring-color:var(--color-panel-accent)}.focus-visible\:ring-offset-1:focus-visible{--tw-ring-offset-width:1px;--tw-ring-offset-shadow:var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)}.focus-visible\:ring-offset-2:focus-visible{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)}.focus-visible\:ring-offset-panel-bg:focus-visible{--tw-ring-offset-color:var(--color-panel-bg)}}body{background-color:var(--color-panel-bg);color:var(--color-panel-text);font-family:var(--font-sans);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;margin:0;padding:0;font-size:13px;line-height:1.5;overflow:hidden}#root{flex-direction:column;height:100vh;display:flex}::-webkit-scrollbar{width:6px}::-webkit-scrollbar-track{background:0 0}::-webkit-scrollbar-thumb{background:var(--color-panel-border);border-radius:3px}::-webkit-scrollbar-thumb:hover{background:var(--color-panel-text-dim)}@keyframes toast-slide-up{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}@keyframes toast-fade-out{0%{opacity:1}to{opacity:0}}@keyframes shimmer{0%{background-position:-200% 0}to{background-position:200% 0}}@keyframes confetti-pop{0%{opacity:1;transform:translate(0)scale(1)}to{transform:translate(var(--confetti-x),var(--confetti-y)) scale(0);opacity:0}}.toast-enter{animation:.2s ease-out toast-slide-up}.toast-exit{animation:.2s ease-in forwards toast-fade-out}.shimmer-bar{background:linear-gradient(90deg,var(--color-panel-accent) 0%,var(--color-panel-accent-hover) 50%,var(--color-panel-accent) 100%);background-size:200% 100%;animation:1.5s ease-in-out infinite shimmer}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-space-x-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1} diff --git a/dist/assets/index-DlyFT5zE.css b/dist/assets/index-DlyFT5zE.css new file mode 100644 index 0000000..c7810ff --- /dev/null +++ b/dist/assets/index-DlyFT5zE.css @@ -0,0 +1 @@ +@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-x-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-ease:initial;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1}}}@layer theme{:root,:host{--font-sans:"Inter", ui-sans-serif, system-ui, sans-serif;--font-mono:"JetBrains Mono", ui-monospace, monospace;--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-orange-400:oklch(75% .183 55.934);--color-orange-500:oklch(70.5% .213 47.604);--color-amber-400:oklch(82.8% .189 84.429);--color-green-400:oklch(79.2% .209 151.711);--color-green-500:oklch(72.3% .219 149.579);--color-blue-400:oklch(70.7% .165 254.624);--color-blue-500:oklch(62.3% .214 259.815);--color-white:#fff;--spacing:.25rem;--font-weight-medium:500;--font-weight-semibold:600;--tracking-tight:-.025em;--tracking-wider:.05em;--leading-relaxed:1.625;--radius-sm:.25rem;--radius-md:.375rem;--radius-lg:.5rem;--radius-2xl:1rem;--drop-shadow-md:0 3px 3px #0000001f;--ease-out:cubic-bezier(0, 0, .2, 1);--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-panel-bg:#0c0c0e;--color-panel-surface:#161618;--color-panel-border:#222225;--color-panel-text:#ededef;--color-panel-text-dim:#7e7e85;--color-panel-accent:#6366f1;--color-panel-accent-hover:#818cf8;--color-success:#22c55e}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.pointer-events-none{pointer-events:none}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.top-0{top:calc(var(--spacing) * 0)}.top-0\.5{top:calc(var(--spacing) * .5)}.top-1\/2{top:50%}.top-2{top:calc(var(--spacing) * 2)}.top-full{top:100%}.right-0{right:calc(var(--spacing) * 0)}.right-0\.5{right:calc(var(--spacing) * .5)}.right-2{right:calc(var(--spacing) * 2)}.bottom-0{bottom:calc(var(--spacing) * 0)}.bottom-0\.5{bottom:calc(var(--spacing) * .5)}.bottom-full{bottom:100%}.left-0\.5{left:calc(var(--spacing) * .5)}.left-1{left:calc(var(--spacing) * 1)}.left-1\/2{left:50%}.z-10{z-index:10}.z-20{z-index:20}.col-span-2{grid-column:span 2/span 2}.container{width:100%}@media(min-width:40rem){.container{max-width:40rem}}@media(min-width:48rem){.container{max-width:48rem}}@media(min-width:64rem){.container{max-width:64rem}}@media(min-width:80rem){.container{max-width:80rem}}@media(min-width:96rem){.container{max-width:96rem}}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:calc(var(--spacing) * 1)}.mt-1\.5{margin-top:calc(var(--spacing) * 1.5)}.mt-2\.5{margin-top:calc(var(--spacing) * 2.5)}.mr-3{margin-right:calc(var(--spacing) * 3)}.mb-1{margin-bottom:calc(var(--spacing) * 1)}.mb-1\.5{margin-bottom:calc(var(--spacing) * 1.5)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.ml-auto{margin-left:auto}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-flex{display:inline-flex}.h-1\.5{height:calc(var(--spacing) * 1.5)}.h-2{height:calc(var(--spacing) * 2)}.h-3{height:calc(var(--spacing) * 3)}.h-5{height:calc(var(--spacing) * 5)}.h-6{height:calc(var(--spacing) * 6)}.h-16{height:calc(var(--spacing) * 16)}.h-\[2px\]{height:2px}.h-full{height:100%}.h-screen{height:100vh}.max-h-\[300px\]{max-height:300px}.w-1\.5{width:calc(var(--spacing) * 1.5)}.w-5{width:calc(var(--spacing) * 5)}.w-6{width:calc(var(--spacing) * 6)}.w-8{width:calc(var(--spacing) * 8)}.w-10{width:calc(var(--spacing) * 10)}.w-16{width:calc(var(--spacing) * 16)}.w-24{width:calc(var(--spacing) * 24)}.w-44{width:calc(var(--spacing) * 44)}.w-full{width:100%}.max-w-\[100px\]{max-width:100px}.max-w-\[180px\]{max-width:180px}.max-w-\[220px\]{max-width:220px}.min-w-0{min-width:calc(var(--spacing) * 0)}.min-w-\[200px\]{min-width:200px}.flex-1{flex:1}.shrink-0{flex-shrink:0}.-translate-x-1\/2{--tw-translate-x: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-y-1\/2{--tw-translate-y: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y)}.-rotate-90{rotate:-90deg}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.resize{resize:both}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-0{gap:calc(var(--spacing) * 0)}.gap-1{gap:calc(var(--spacing) * 1)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-2\.5{gap:calc(var(--spacing) * 2.5)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-5{gap:calc(var(--spacing) * 5)}:where(.-space-x-1\.5>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing) * -1.5) * var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing) * -1.5) * calc(1 - var(--tw-space-x-reverse)))}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-hidden{overflow:hidden}.overflow-x-hidden{overflow-x:hidden}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-sm{border-radius:var(--radius-sm)}.border{border-style:var(--tw-border-style);border-width:1px}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-blue-500\/40{border-color:#3080ff66}@supports (color:color-mix(in lab,red,red)){.border-blue-500\/40{border-color:color-mix(in oklab,var(--color-blue-500) 40%,transparent)}}.border-green-500\/40{border-color:#00c75866}@supports (color:color-mix(in lab,red,red)){.border-green-500\/40{border-color:color-mix(in oklab,var(--color-green-500) 40%,transparent)}}.border-orange-500\/40{border-color:#fe6e0066}@supports (color:color-mix(in lab,red,red)){.border-orange-500\/40{border-color:color-mix(in oklab,var(--color-orange-500) 40%,transparent)}}.border-panel-accent{border-color:var(--color-panel-accent)}.border-panel-accent\/30{border-color:#6366f14d}@supports (color:color-mix(in lab,red,red)){.border-panel-accent\/30{border-color:color-mix(in oklab,var(--color-panel-accent) 30%,transparent)}}.border-panel-border{border-color:var(--color-panel-border)}.border-panel-surface{border-color:var(--color-panel-surface)}.bg-blue-500\/5{background-color:#3080ff0d}@supports (color:color-mix(in lab,red,red)){.bg-blue-500\/5{background-color:color-mix(in oklab,var(--color-blue-500) 5%,transparent)}}.bg-green-500\/5{background-color:#00c7580d}@supports (color:color-mix(in lab,red,red)){.bg-green-500\/5{background-color:color-mix(in oklab,var(--color-green-500) 5%,transparent)}}.bg-orange-500\/5{background-color:#fe6e000d}@supports (color:color-mix(in lab,red,red)){.bg-orange-500\/5{background-color:color-mix(in oklab,var(--color-orange-500) 5%,transparent)}}.bg-panel-accent{background-color:var(--color-panel-accent)}.bg-panel-accent\/10{background-color:#6366f11a}@supports (color:color-mix(in lab,red,red)){.bg-panel-accent\/10{background-color:color-mix(in oklab,var(--color-panel-accent) 10%,transparent)}}.bg-panel-accent\/40{background-color:#6366f166}@supports (color:color-mix(in lab,red,red)){.bg-panel-accent\/40{background-color:color-mix(in oklab,var(--color-panel-accent) 40%,transparent)}}.bg-panel-bg{background-color:var(--color-panel-bg)}.bg-panel-bg\/80{background-color:#0c0c0ecc}@supports (color:color-mix(in lab,red,red)){.bg-panel-bg\/80{background-color:color-mix(in oklab,var(--color-panel-bg) 80%,transparent)}}.bg-panel-surface{background-color:var(--color-panel-surface)}.bg-panel-surface\/50{background-color:#16161880}@supports (color:color-mix(in lab,red,red)){.bg-panel-surface\/50{background-color:color-mix(in oklab,var(--color-panel-surface) 50%,transparent)}}.bg-success{background-color:var(--color-success)}.bg-success\/20{background-color:#22c55e33}@supports (color:color-mix(in lab,red,red)){.bg-success\/20{background-color:color-mix(in oklab,var(--color-success) 20%,transparent)}}.bg-success\/90{background-color:#22c55ee6}@supports (color:color-mix(in lab,red,red)){.bg-success\/90{background-color:color-mix(in oklab,var(--color-success) 90%,transparent)}}.p-0\.5{padding:calc(var(--spacing) * .5)}.p-1\.5{padding:calc(var(--spacing) * 1.5)}.p-2\.5{padding:calc(var(--spacing) * 2.5)}.p-3{padding:calc(var(--spacing) * 3)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.pt-1{padding-top:calc(var(--spacing) * 1)}.pt-3{padding-top:calc(var(--spacing) * 3)}.pr-10{padding-right:calc(var(--spacing) * 10)}.pb-0{padding-bottom:calc(var(--spacing) * 0)}.pb-2{padding-bottom:calc(var(--spacing) * 2)}.pb-3{padding-bottom:calc(var(--spacing) * 3)}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.font-mono{font-family:var(--font-mono)}.text-\[8px\]{font-size:8px}.text-\[9px\]{font-size:9px}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[12px\]{font-size:12px}.text-\[13px\]{font-size:13px}.text-\[14px\]{font-size:14px}.text-\[16px\]{font-size:16px}.leading-\[1\.6\]{--tw-leading:1.6;line-height:1.6}.leading-none{--tw-leading:1;line-height:1}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.break-all{word-break:break-all}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.text-amber-400{color:var(--color-amber-400)}.text-blue-400\/70{color:#54a2ffb3}@supports (color:color-mix(in lab,red,red)){.text-blue-400\/70{color:color-mix(in oklab,var(--color-blue-400) 70%,transparent)}}.text-green-400\/70{color:#05df72b3}@supports (color:color-mix(in lab,red,red)){.text-green-400\/70{color:color-mix(in oklab,var(--color-green-400) 70%,transparent)}}.text-orange-400\/70{color:#ff8b1ab3}@supports (color:color-mix(in lab,red,red)){.text-orange-400\/70{color:color-mix(in oklab,var(--color-orange-400) 70%,transparent)}}.text-panel-accent{color:var(--color-panel-accent)}.text-panel-text{color:var(--color-panel-text)}.text-panel-text-dim{color:var(--color-panel-text-dim)}.text-success{color:var(--color-success)}.text-white{color:var(--color-white)}.uppercase{text-transform:uppercase}.opacity-0{opacity:0}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a), 0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.drop-shadow-md{--tw-drop-shadow-size:drop-shadow(0 3px 3px var(--tw-drop-shadow-color,#0000001f));--tw-drop-shadow:drop-shadow(var(--drop-shadow-md));filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.backdrop-filter{-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[grid-template-rows\]{transition-property:grid-template-rows;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[width\]{transition-property:width;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-150{--tw-duration:.15s;transition-duration:.15s}.duration-200{--tw-duration:.2s;transition-duration:.2s}.duration-300{--tw-duration:.3s;transition-duration:.3s}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.select-none{-webkit-user-select:none;user-select:none}@media(hover:hover){.group-hover\:scale-105:is(:where(.group):hover *){--tw-scale-x:105%;--tw-scale-y:105%;--tw-scale-z:105%;scale:var(--tw-scale-x) var(--tw-scale-y)}.group-hover\:opacity-100:is(:where(.group):hover *){opacity:1}.hover\:scale-\[1\.15\]:hover{scale:1.15}.hover\:border-panel-accent\/40:hover{border-color:#6366f166}@supports (color:color-mix(in lab,red,red)){.hover\:border-panel-accent\/40:hover{border-color:color-mix(in oklab,var(--color-panel-accent) 40%,transparent)}}.hover\:border-panel-accent\/50:hover{border-color:#6366f180}@supports (color:color-mix(in lab,red,red)){.hover\:border-panel-accent\/50:hover{border-color:color-mix(in oklab,var(--color-panel-accent) 50%,transparent)}}.hover\:border-red-500\/50:hover{border-color:#fb2c3680}@supports (color:color-mix(in lab,red,red)){.hover\:border-red-500\/50:hover{border-color:color-mix(in oklab,var(--color-red-500) 50%,transparent)}}.hover\:bg-panel-accent-hover:hover{background-color:var(--color-panel-accent-hover)}.hover\:bg-panel-accent\/10:hover{background-color:#6366f11a}@supports (color:color-mix(in lab,red,red)){.hover\:bg-panel-accent\/10:hover{background-color:color-mix(in oklab,var(--color-panel-accent) 10%,transparent)}}.hover\:bg-panel-bg:hover{background-color:var(--color-panel-bg)}.hover\:bg-panel-surface:hover{background-color:var(--color-panel-surface)}.hover\:text-panel-accent:hover{color:var(--color-panel-accent)}.hover\:text-panel-accent-hover:hover{color:var(--color-panel-accent-hover)}.hover\:text-panel-text:hover{color:var(--color-panel-text)}.hover\:text-red-400:hover{color:var(--color-red-400)}}.focus\:border-panel-accent:focus{border-color:var(--color-panel-accent)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.focus-visible\:ring-2:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-visible\:ring-panel-accent:focus-visible{--tw-ring-color:var(--color-panel-accent)}.focus-visible\:ring-offset-1:focus-visible{--tw-ring-offset-width:1px;--tw-ring-offset-shadow:var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)}.focus-visible\:ring-offset-2:focus-visible{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)}.focus-visible\:ring-offset-panel-bg:focus-visible{--tw-ring-offset-color:var(--color-panel-bg)}}body{background:var(--color-panel-bg);width:320px;min-height:400px;color:var(--color-panel-text);font-family:var(--font-sans);-webkit-font-smoothing:antialiased;margin:0;font-size:13px}.popup{flex-direction:column;gap:16px;min-height:400px;padding:16px;display:flex}.popup-header{justify-content:space-between;align-items:center;display:flex}.popup-logo{align-items:center;gap:8px;display:flex}.popup-title{letter-spacing:-.01em;font-size:15px;font-weight:600}.popup-url{color:var(--color-panel-text-dim);font-size:11px;font-family:var(--font-mono);text-overflow:ellipsis;white-space:nowrap;max-width:140px;overflow:hidden}.popup-status{background:var(--color-panel-surface);border:1px solid var(--color-panel-border);color:var(--color-panel-text-dim);border-radius:8px;align-items:center;gap:8px;padding:10px 12px;font-size:12px;display:flex}.popup-status-dot{background:var(--color-panel-text-dim);border-radius:50%;width:8px;height:8px;transition:background-color .2s}.popup-status-dot.active{background:var(--color-success);box-shadow:0 0 8px #22c55e66}.popup-actions{flex-direction:column;gap:8px;display:flex}.popup-btn{background:var(--color-panel-surface);border:1px solid var(--color-panel-border);width:100%;color:var(--color-panel-text);font-size:13px;font-family:var(--font-sans);cursor:pointer;border-radius:8px;align-items:center;gap:10px;padding:11px 14px;transition:background-color .15s,border-color .15s;display:flex}.popup-btn:hover{background:var(--color-panel-border);border-color:var(--color-panel-text-dim)}.popup-btn:focus-visible{box-shadow:0 0 0 2px var(--color-panel-accent);outline:none}.popup-btn-primary{background:var(--color-panel-accent);border-color:var(--color-panel-accent);font-weight:500}.popup-btn-primary:hover{background:var(--color-panel-accent-hover);border-color:var(--color-panel-accent-hover)}.popup-shortcuts{background:var(--color-panel-surface);border:1px solid var(--color-panel-border);border-radius:8px;flex-direction:column;gap:8px;padding:12px;display:flex}.popup-shortcuts-title{color:var(--color-panel-text-dim);text-transform:uppercase;letter-spacing:.05em;align-items:center;gap:6px;font-size:11px;font-weight:500;display:flex}.popup-shortcut-row{color:var(--color-panel-text-dim);justify-content:space-between;align-items:center;font-size:12px;display:flex}.popup-shortcut-row kbd{background:var(--color-panel-bg);border:1px solid var(--color-panel-border);font-family:var(--font-mono);color:var(--color-panel-text);border-radius:4px;padding:2px 6px;font-size:10px}.popup-footer{border-top:1px solid var(--color-panel-border);justify-content:space-between;align-items:center;margin-top:auto;padding-top:12px;display:flex}.popup-footer-btn{width:28px;height:28px;color:var(--color-panel-text-dim);cursor:pointer;background:0 0;border:1px solid #0000;border-radius:6px;justify-content:center;align-items:center;transition:color .15s,border-color .15s;display:flex}.popup-footer-btn:hover{color:var(--color-panel-text);border-color:var(--color-panel-border)}.popup-footer-btn:focus-visible{box-shadow:0 0 0 2px var(--color-panel-accent);outline:none}.popup-version{font-size:10px;font-family:var(--font-mono);color:var(--color-panel-text-dim)}/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-x-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-ease:initial;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1}}}@layer theme{:root,:host{--font-sans:"Inter", ui-sans-serif, system-ui, sans-serif;--font-mono:"JetBrains Mono", ui-monospace, monospace;--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-orange-400:oklch(75% .183 55.934);--color-orange-500:oklch(70.5% .213 47.604);--color-amber-400:oklch(82.8% .189 84.429);--color-green-400:oklch(79.2% .209 151.711);--color-green-500:oklch(72.3% .219 149.579);--color-blue-400:oklch(70.7% .165 254.624);--color-blue-500:oklch(62.3% .214 259.815);--color-white:#fff;--spacing:.25rem;--font-weight-medium:500;--font-weight-semibold:600;--tracking-tight:-.025em;--tracking-wider:.05em;--leading-relaxed:1.625;--radius-sm:.25rem;--radius-md:.375rem;--radius-lg:.5rem;--radius-2xl:1rem;--drop-shadow-md:0 3px 3px #0000001f;--ease-out:cubic-bezier(0, 0, .2, 1);--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-panel-bg:#0c0c0e;--color-panel-surface:#161618;--color-panel-border:#222225;--color-panel-text:#ededef;--color-panel-text-dim:#7e7e85;--color-panel-accent:#6366f1;--color-panel-accent-hover:#818cf8;--color-success:#22c55e}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.pointer-events-none{pointer-events:none}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.top-0{top:calc(var(--spacing) * 0)}.top-0\.5{top:calc(var(--spacing) * .5)}.top-1\/2{top:50%}.top-2{top:calc(var(--spacing) * 2)}.top-full{top:100%}.right-0{right:calc(var(--spacing) * 0)}.right-0\.5{right:calc(var(--spacing) * .5)}.right-2{right:calc(var(--spacing) * 2)}.bottom-0{bottom:calc(var(--spacing) * 0)}.bottom-0\.5{bottom:calc(var(--spacing) * .5)}.bottom-full{bottom:100%}.left-0\.5{left:calc(var(--spacing) * .5)}.left-1{left:calc(var(--spacing) * 1)}.left-1\/2{left:50%}.z-10{z-index:10}.z-20{z-index:20}.col-span-2{grid-column:span 2/span 2}.container{width:100%}@media(min-width:40rem){.container{max-width:40rem}}@media(min-width:48rem){.container{max-width:48rem}}@media(min-width:64rem){.container{max-width:64rem}}@media(min-width:80rem){.container{max-width:80rem}}@media(min-width:96rem){.container{max-width:96rem}}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:calc(var(--spacing) * 1)}.mt-1\.5{margin-top:calc(var(--spacing) * 1.5)}.mt-2\.5{margin-top:calc(var(--spacing) * 2.5)}.mr-3{margin-right:calc(var(--spacing) * 3)}.mb-1{margin-bottom:calc(var(--spacing) * 1)}.mb-1\.5{margin-bottom:calc(var(--spacing) * 1.5)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.ml-auto{margin-left:auto}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-flex{display:inline-flex}.h-1\.5{height:calc(var(--spacing) * 1.5)}.h-2{height:calc(var(--spacing) * 2)}.h-3{height:calc(var(--spacing) * 3)}.h-5{height:calc(var(--spacing) * 5)}.h-6{height:calc(var(--spacing) * 6)}.h-16{height:calc(var(--spacing) * 16)}.h-\[2px\]{height:2px}.h-full{height:100%}.h-screen{height:100vh}.max-h-\[300px\]{max-height:300px}.w-1\.5{width:calc(var(--spacing) * 1.5)}.w-5{width:calc(var(--spacing) * 5)}.w-6{width:calc(var(--spacing) * 6)}.w-8{width:calc(var(--spacing) * 8)}.w-10{width:calc(var(--spacing) * 10)}.w-16{width:calc(var(--spacing) * 16)}.w-24{width:calc(var(--spacing) * 24)}.w-44{width:calc(var(--spacing) * 44)}.w-full{width:100%}.max-w-\[100px\]{max-width:100px}.max-w-\[180px\]{max-width:180px}.max-w-\[220px\]{max-width:220px}.min-w-0{min-width:calc(var(--spacing) * 0)}.min-w-\[200px\]{min-width:200px}.flex-1{flex:1}.shrink-0{flex-shrink:0}.-translate-x-1\/2{--tw-translate-x: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-y-1\/2{--tw-translate-y: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y)}.-rotate-90{rotate:-90deg}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.resize{resize:both}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-0{gap:calc(var(--spacing) * 0)}.gap-1{gap:calc(var(--spacing) * 1)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-2\.5{gap:calc(var(--spacing) * 2.5)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-5{gap:calc(var(--spacing) * 5)}:where(.-space-x-1\.5>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing) * -1.5) * var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing) * -1.5) * calc(1 - var(--tw-space-x-reverse)))}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-hidden{overflow:hidden}.overflow-x-hidden{overflow-x:hidden}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-sm{border-radius:var(--radius-sm)}.border{border-style:var(--tw-border-style);border-width:1px}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-blue-500\/40{border-color:#3080ff66}@supports (color:color-mix(in lab,red,red)){.border-blue-500\/40{border-color:color-mix(in oklab,var(--color-blue-500) 40%,transparent)}}.border-green-500\/40{border-color:#00c75866}@supports (color:color-mix(in lab,red,red)){.border-green-500\/40{border-color:color-mix(in oklab,var(--color-green-500) 40%,transparent)}}.border-orange-500\/40{border-color:#fe6e0066}@supports (color:color-mix(in lab,red,red)){.border-orange-500\/40{border-color:color-mix(in oklab,var(--color-orange-500) 40%,transparent)}}.border-panel-accent{border-color:var(--color-panel-accent)}.border-panel-accent\/30{border-color:#6366f14d}@supports (color:color-mix(in lab,red,red)){.border-panel-accent\/30{border-color:color-mix(in oklab,var(--color-panel-accent) 30%,transparent)}}.border-panel-border{border-color:var(--color-panel-border)}.border-panel-surface{border-color:var(--color-panel-surface)}.bg-blue-500\/5{background-color:#3080ff0d}@supports (color:color-mix(in lab,red,red)){.bg-blue-500\/5{background-color:color-mix(in oklab,var(--color-blue-500) 5%,transparent)}}.bg-green-500\/5{background-color:#00c7580d}@supports (color:color-mix(in lab,red,red)){.bg-green-500\/5{background-color:color-mix(in oklab,var(--color-green-500) 5%,transparent)}}.bg-orange-500\/5{background-color:#fe6e000d}@supports (color:color-mix(in lab,red,red)){.bg-orange-500\/5{background-color:color-mix(in oklab,var(--color-orange-500) 5%,transparent)}}.bg-panel-accent{background-color:var(--color-panel-accent)}.bg-panel-accent\/10{background-color:#6366f11a}@supports (color:color-mix(in lab,red,red)){.bg-panel-accent\/10{background-color:color-mix(in oklab,var(--color-panel-accent) 10%,transparent)}}.bg-panel-accent\/40{background-color:#6366f166}@supports (color:color-mix(in lab,red,red)){.bg-panel-accent\/40{background-color:color-mix(in oklab,var(--color-panel-accent) 40%,transparent)}}.bg-panel-bg{background-color:var(--color-panel-bg)}.bg-panel-bg\/80{background-color:#0c0c0ecc}@supports (color:color-mix(in lab,red,red)){.bg-panel-bg\/80{background-color:color-mix(in oklab,var(--color-panel-bg) 80%,transparent)}}.bg-panel-surface{background-color:var(--color-panel-surface)}.bg-panel-surface\/50{background-color:#16161880}@supports (color:color-mix(in lab,red,red)){.bg-panel-surface\/50{background-color:color-mix(in oklab,var(--color-panel-surface) 50%,transparent)}}.bg-success{background-color:var(--color-success)}.bg-success\/20{background-color:#22c55e33}@supports (color:color-mix(in lab,red,red)){.bg-success\/20{background-color:color-mix(in oklab,var(--color-success) 20%,transparent)}}.bg-success\/90{background-color:#22c55ee6}@supports (color:color-mix(in lab,red,red)){.bg-success\/90{background-color:color-mix(in oklab,var(--color-success) 90%,transparent)}}.p-0\.5{padding:calc(var(--spacing) * .5)}.p-1\.5{padding:calc(var(--spacing) * 1.5)}.p-2\.5{padding:calc(var(--spacing) * 2.5)}.p-3{padding:calc(var(--spacing) * 3)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.pt-1{padding-top:calc(var(--spacing) * 1)}.pt-3{padding-top:calc(var(--spacing) * 3)}.pr-10{padding-right:calc(var(--spacing) * 10)}.pb-0{padding-bottom:calc(var(--spacing) * 0)}.pb-2{padding-bottom:calc(var(--spacing) * 2)}.pb-3{padding-bottom:calc(var(--spacing) * 3)}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.font-mono{font-family:var(--font-mono)}.text-\[8px\]{font-size:8px}.text-\[9px\]{font-size:9px}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[12px\]{font-size:12px}.text-\[13px\]{font-size:13px}.text-\[14px\]{font-size:14px}.text-\[16px\]{font-size:16px}.leading-\[1\.6\]{--tw-leading:1.6;line-height:1.6}.leading-none{--tw-leading:1;line-height:1}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.break-all{word-break:break-all}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.text-amber-400{color:var(--color-amber-400)}.text-blue-400\/70{color:#54a2ffb3}@supports (color:color-mix(in lab,red,red)){.text-blue-400\/70{color:color-mix(in oklab,var(--color-blue-400) 70%,transparent)}}.text-green-400\/70{color:#05df72b3}@supports (color:color-mix(in lab,red,red)){.text-green-400\/70{color:color-mix(in oklab,var(--color-green-400) 70%,transparent)}}.text-orange-400\/70{color:#ff8b1ab3}@supports (color:color-mix(in lab,red,red)){.text-orange-400\/70{color:color-mix(in oklab,var(--color-orange-400) 70%,transparent)}}.text-panel-accent{color:var(--color-panel-accent)}.text-panel-text{color:var(--color-panel-text)}.text-panel-text-dim{color:var(--color-panel-text-dim)}.text-success{color:var(--color-success)}.text-white{color:var(--color-white)}.uppercase{text-transform:uppercase}.opacity-0{opacity:0}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a), 0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.drop-shadow-md{--tw-drop-shadow-size:drop-shadow(0 3px 3px var(--tw-drop-shadow-color,#0000001f));--tw-drop-shadow:drop-shadow(var(--drop-shadow-md));filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.backdrop-filter{-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[grid-template-rows\]{transition-property:grid-template-rows;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[width\]{transition-property:width;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-150{--tw-duration:.15s;transition-duration:.15s}.duration-200{--tw-duration:.2s;transition-duration:.2s}.duration-300{--tw-duration:.3s;transition-duration:.3s}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.select-none{-webkit-user-select:none;user-select:none}@media(hover:hover){.group-hover\:scale-105:is(:where(.group):hover *){--tw-scale-x:105%;--tw-scale-y:105%;--tw-scale-z:105%;scale:var(--tw-scale-x) var(--tw-scale-y)}.group-hover\:opacity-100:is(:where(.group):hover *){opacity:1}.hover\:scale-\[1\.15\]:hover{scale:1.15}.hover\:border-panel-accent\/40:hover{border-color:#6366f166}@supports (color:color-mix(in lab,red,red)){.hover\:border-panel-accent\/40:hover{border-color:color-mix(in oklab,var(--color-panel-accent) 40%,transparent)}}.hover\:border-panel-accent\/50:hover{border-color:#6366f180}@supports (color:color-mix(in lab,red,red)){.hover\:border-panel-accent\/50:hover{border-color:color-mix(in oklab,var(--color-panel-accent) 50%,transparent)}}.hover\:border-red-500\/50:hover{border-color:#fb2c3680}@supports (color:color-mix(in lab,red,red)){.hover\:border-red-500\/50:hover{border-color:color-mix(in oklab,var(--color-red-500) 50%,transparent)}}.hover\:bg-panel-accent-hover:hover{background-color:var(--color-panel-accent-hover)}.hover\:bg-panel-accent\/10:hover{background-color:#6366f11a}@supports (color:color-mix(in lab,red,red)){.hover\:bg-panel-accent\/10:hover{background-color:color-mix(in oklab,var(--color-panel-accent) 10%,transparent)}}.hover\:bg-panel-bg:hover{background-color:var(--color-panel-bg)}.hover\:bg-panel-surface:hover{background-color:var(--color-panel-surface)}.hover\:text-panel-accent:hover{color:var(--color-panel-accent)}.hover\:text-panel-accent-hover:hover{color:var(--color-panel-accent-hover)}.hover\:text-panel-text:hover{color:var(--color-panel-text)}.hover\:text-red-400:hover{color:var(--color-red-400)}}.focus\:border-panel-accent:focus{border-color:var(--color-panel-accent)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.focus-visible\:ring-2:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-visible\:ring-panel-accent:focus-visible{--tw-ring-color:var(--color-panel-accent)}.focus-visible\:ring-offset-1:focus-visible{--tw-ring-offset-width:1px;--tw-ring-offset-shadow:var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)}.focus-visible\:ring-offset-2:focus-visible{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)}.focus-visible\:ring-offset-panel-bg:focus-visible{--tw-ring-offset-color:var(--color-panel-bg)}}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-space-x-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1} diff --git a/dist/assets/index.html-ClNSdlzV.js b/dist/assets/index.html-ClNSdlzV.js new file mode 100644 index 0000000..67d351a --- /dev/null +++ b/dist/assets/index.html-ClNSdlzV.js @@ -0,0 +1 @@ +import{a as u}from"./ClockCounterClockwise.es-CQVwCTyJ.js";import{r as a,p as o,j as e,f as Z,s as H,c as L,R as x}from"./Scan.es-D0n8eUjn.js";import{M as s}from"./messages-CGxgbOds.js";const E=new Map([["bold",a.createElement(a.Fragment,null,a.createElement("path",{d:"M128,76a52,52,0,1,0,52,52A52.06,52.06,0,0,0,128,76Zm0,80a28,28,0,1,1,28-28A28,28,0,0,1,128,156Zm113.86-49.57A12,12,0,0,0,236,98.34L208.21,82.49l-.11-31.31a12,12,0,0,0-4.25-9.12,116,116,0,0,0-38-21.41,12,12,0,0,0-9.68.89L128,37.27,99.83,21.53a12,12,0,0,0-9.7-.9,116.06,116.06,0,0,0-38,21.47,12,12,0,0,0-4.24,9.1l-.14,31.34L20,98.35a12,12,0,0,0-5.85,8.11,110.7,110.7,0,0,0,0,43.11A12,12,0,0,0,20,157.66l27.82,15.85.11,31.31a12,12,0,0,0,4.25,9.12,116,116,0,0,0,38,21.41,12,12,0,0,0,9.68-.89L128,218.73l28.14,15.74a12,12,0,0,0,9.7.9,116.06,116.06,0,0,0,38-21.47,12,12,0,0,0,4.24-9.1l.14-31.34,27.81-15.81a12,12,0,0,0,5.85-8.11A110.7,110.7,0,0,0,241.86,106.43Zm-22.63,33.18-26.88,15.28a11.94,11.94,0,0,0-4.55,4.59c-.54,1-1.11,1.93-1.7,2.88a12,12,0,0,0-1.83,6.31L184.13,199a91.83,91.83,0,0,1-21.07,11.87l-27.15-15.19a12,12,0,0,0-5.86-1.53h-.29c-1.14,0-2.3,0-3.44,0a12.08,12.08,0,0,0-6.14,1.51L93,210.82A92.27,92.27,0,0,1,71.88,199l-.11-30.24a12,12,0,0,0-1.83-6.32c-.58-.94-1.16-1.91-1.7-2.88A11.92,11.92,0,0,0,63.7,155L36.8,139.63a86.53,86.53,0,0,1,0-23.24l26.88-15.28a12,12,0,0,0,4.55-4.58c.54-1,1.11-1.94,1.7-2.89a12,12,0,0,0,1.83-6.31L71.87,57A91.83,91.83,0,0,1,92.94,45.17l27.15,15.19a11.92,11.92,0,0,0,6.15,1.52c1.14,0,2.3,0,3.44,0a12.08,12.08,0,0,0,6.14-1.51L163,45.18A92.27,92.27,0,0,1,184.12,57l.11,30.24a12,12,0,0,0,1.83,6.32c.58.94,1.16,1.91,1.7,2.88A11.92,11.92,0,0,0,192.3,101l26.9,15.33A86.53,86.53,0,0,1,219.23,139.61Z"}))],["duotone",a.createElement(a.Fragment,null,a.createElement("path",{d:"M230.1,108.76,198.25,90.62c-.64-1.16-1.31-2.29-2-3.41l-.12-36A104.61,104.61,0,0,0,162,32L130,49.89c-1.34,0-2.69,0-4,0L94,32A104.58,104.58,0,0,0,59.89,51.25l-.16,36c-.7,1.12-1.37,2.26-2,3.41l-31.84,18.1a99.15,99.15,0,0,0,0,38.46l31.85,18.14c.64,1.16,1.31,2.29,2,3.41l.12,36A104.61,104.61,0,0,0,94,224l32-17.87c1.34,0,2.69,0,4,0L162,224a104.58,104.58,0,0,0,34.08-19.25l.16-36c.7-1.12,1.37-2.26,2-3.41l31.84-18.1A99.15,99.15,0,0,0,230.1,108.76ZM128,168a40,40,0,1,1,40-40A40,40,0,0,1,128,168Z",opacity:"0.2"}),a.createElement("path",{d:"M128,80a48,48,0,1,0,48,48A48.05,48.05,0,0,0,128,80Zm0,80a32,32,0,1,1,32-32A32,32,0,0,1,128,160Zm109.94-52.79a8,8,0,0,0-3.89-5.4l-29.83-17-.12-33.62a8,8,0,0,0-2.83-6.08,111.91,111.91,0,0,0-36.72-20.67,8,8,0,0,0-6.46.59L128,41.85,97.88,25a8,8,0,0,0-6.47-.6A111.92,111.92,0,0,0,54.73,45.15a8,8,0,0,0-2.83,6.07l-.15,33.65-29.83,17a8,8,0,0,0-3.89,5.4,106.47,106.47,0,0,0,0,41.56,8,8,0,0,0,3.89,5.4l29.83,17,.12,33.63a8,8,0,0,0,2.83,6.08,111.91,111.91,0,0,0,36.72,20.67,8,8,0,0,0,6.46-.59L128,214.15,158.12,231a7.91,7.91,0,0,0,3.9,1,8.09,8.09,0,0,0,2.57-.42,112.1,112.1,0,0,0,36.68-20.73,8,8,0,0,0,2.83-6.07l.15-33.65,29.83-17a8,8,0,0,0,3.89-5.4A106.47,106.47,0,0,0,237.94,107.21Zm-15,34.91-28.57,16.25a8,8,0,0,0-3,3c-.58,1-1.19,2.06-1.81,3.06a7.94,7.94,0,0,0-1.22,4.21l-.15,32.25a95.89,95.89,0,0,1-25.37,14.3L134,199.13a8,8,0,0,0-3.91-1h-.19c-1.21,0-2.43,0-3.64,0a8.1,8.1,0,0,0-4.1,1l-28.84,16.1A96,96,0,0,1,67.88,201l-.11-32.2a8,8,0,0,0-1.22-4.22c-.62-1-1.23-2-1.8-3.06a8.09,8.09,0,0,0-3-3.06l-28.6-16.29a90.49,90.49,0,0,1,0-28.26L61.67,97.63a8,8,0,0,0,3-3c.58-1,1.19-2.06,1.81-3.06a7.94,7.94,0,0,0,1.22-4.21l.15-32.25a95.89,95.89,0,0,1,25.37-14.3L122,56.87a8,8,0,0,0,4.1,1c1.21,0,2.43,0,3.64,0a8,8,0,0,0,4.1-1l28.84-16.1A96,96,0,0,1,188.12,55l.11,32.2a8,8,0,0,0,1.22,4.22c.62,1,1.23,2,1.8,3.06a8.09,8.09,0,0,0,3,3.06l28.6,16.29A90.49,90.49,0,0,1,222.9,142.12Z"}))],["fill",a.createElement(a.Fragment,null,a.createElement("path",{d:"M237.94,107.21a8,8,0,0,0-3.89-5.4l-29.83-17-.12-33.62a8,8,0,0,0-2.83-6.08,111.91,111.91,0,0,0-36.72-20.67,8,8,0,0,0-6.46.59L128,41.85,97.88,25a8,8,0,0,0-6.47-.6A111.92,111.92,0,0,0,54.73,45.15a8,8,0,0,0-2.83,6.07l-.15,33.65-29.83,17a8,8,0,0,0-3.89,5.4,106.47,106.47,0,0,0,0,41.56,8,8,0,0,0,3.89,5.4l29.83,17,.12,33.63a8,8,0,0,0,2.83,6.08,111.91,111.91,0,0,0,36.72,20.67,8,8,0,0,0,6.46-.59L128,214.15,158.12,231a7.91,7.91,0,0,0,3.9,1,8.09,8.09,0,0,0,2.57-.42,112.1,112.1,0,0,0,36.68-20.73,8,8,0,0,0,2.83-6.07l.15-33.65,29.83-17a8,8,0,0,0,3.89-5.4A106.47,106.47,0,0,0,237.94,107.21ZM128,168a40,40,0,1,1,40-40A40,40,0,0,1,128,168Z"}))],["light",a.createElement(a.Fragment,null,a.createElement("path",{d:"M128,82a46,46,0,1,0,46,46A46.06,46.06,0,0,0,128,82Zm0,80a34,34,0,1,1,34-34A34,34,0,0,1,128,162Zm108-54.4a6,6,0,0,0-2.92-4L202.64,86.22l-.42-.71L202.1,51.2A6,6,0,0,0,200,46.64a110.12,110.12,0,0,0-36.07-20.31,6,6,0,0,0-4.84.45L128.46,43.86h-1L96.91,26.76a6,6,0,0,0-4.86-.44A109.92,109.92,0,0,0,56,46.68a6,6,0,0,0-2.12,4.55l-.16,34.34c-.14.23-.28.47-.41.71L22.91,103.57A6,6,0,0,0,20,107.62a104.81,104.81,0,0,0,0,40.78,6,6,0,0,0,2.92,4l30.42,17.33.42.71.12,34.31A6,6,0,0,0,56,209.36a110.12,110.12,0,0,0,36.07,20.31,6,6,0,0,0,4.84-.45l30.61-17.08h1l30.56,17.1A6.09,6.09,0,0,0,162,230a5.83,5.83,0,0,0,1.93-.32,109.92,109.92,0,0,0,36-20.36,6,6,0,0,0,2.12-4.55l.16-34.34c.14-.23.28-.47.41-.71l30.42-17.29a6,6,0,0,0,2.92-4.05A104.81,104.81,0,0,0,236,107.6Zm-11.25,35.79L195.32,160.1a6.07,6.07,0,0,0-2.28,2.3c-.59,1-1.21,2.11-1.86,3.14a6,6,0,0,0-.91,3.16l-.16,33.21a98.15,98.15,0,0,1-27.52,15.53L133,200.88a6,6,0,0,0-2.93-.77h-.14c-1.24,0-2.5,0-3.74,0a6,6,0,0,0-3.07.76L93.45,217.43a98,98,0,0,1-27.56-15.49l-.12-33.17a6,6,0,0,0-.91-3.16c-.64-1-1.27-2.08-1.86-3.14a6,6,0,0,0-2.27-2.3L31.3,143.4a93,93,0,0,1,0-30.79L60.68,95.9A6.07,6.07,0,0,0,63,93.6c.59-1,1.21-2.11,1.86-3.14a6,6,0,0,0,.91-3.16l.16-33.21A98.15,98.15,0,0,1,93.41,38.56L123,55.12a5.81,5.81,0,0,0,3.07.76c1.24,0,2.5,0,3.74,0a6,6,0,0,0,3.07-.76l29.65-16.56a98,98,0,0,1,27.56,15.49l.12,33.17a6,6,0,0,0,.91,3.16c.64,1,1.27,2.08,1.86,3.14a6,6,0,0,0,2.27,2.3L224.7,112.6A93,93,0,0,1,224.73,143.39Z"}))],["regular",a.createElement(a.Fragment,null,a.createElement("path",{d:"M128,80a48,48,0,1,0,48,48A48.05,48.05,0,0,0,128,80Zm0,80a32,32,0,1,1,32-32A32,32,0,0,1,128,160Zm109.94-52.79a8,8,0,0,0-3.89-5.4l-29.83-17-.12-33.62a8,8,0,0,0-2.83-6.08,111.91,111.91,0,0,0-36.72-20.67,8,8,0,0,0-6.46.59L128,41.85,97.88,25a8,8,0,0,0-6.47-.6A112.1,112.1,0,0,0,54.73,45.15a8,8,0,0,0-2.83,6.07l-.15,33.65-29.83,17a8,8,0,0,0-3.89,5.4,106.47,106.47,0,0,0,0,41.56,8,8,0,0,0,3.89,5.4l29.83,17,.12,33.62a8,8,0,0,0,2.83,6.08,111.91,111.91,0,0,0,36.72,20.67,8,8,0,0,0,6.46-.59L128,214.15,158.12,231a7.91,7.91,0,0,0,3.9,1,8.09,8.09,0,0,0,2.57-.42,112.1,112.1,0,0,0,36.68-20.73,8,8,0,0,0,2.83-6.07l.15-33.65,29.83-17a8,8,0,0,0,3.89-5.4A106.47,106.47,0,0,0,237.94,107.21Zm-15,34.91-28.57,16.25a8,8,0,0,0-3,3c-.58,1-1.19,2.06-1.81,3.06a7.94,7.94,0,0,0-1.22,4.21l-.15,32.25a95.89,95.89,0,0,1-25.37,14.3L134,199.13a8,8,0,0,0-3.91-1h-.19c-1.21,0-2.43,0-3.64,0a8.08,8.08,0,0,0-4.1,1l-28.84,16.1A96,96,0,0,1,67.88,201l-.11-32.2a8,8,0,0,0-1.22-4.22c-.62-1-1.23-2-1.8-3.06a8.09,8.09,0,0,0-3-3.06l-28.6-16.29a90.49,90.49,0,0,1,0-28.26L61.67,97.63a8,8,0,0,0,3-3c.58-1,1.19-2.06,1.81-3.06a7.94,7.94,0,0,0,1.22-4.21l.15-32.25a95.89,95.89,0,0,1,25.37-14.3L122,56.87a8,8,0,0,0,4.1,1c1.21,0,2.43,0,3.64,0a8.08,8.08,0,0,0,4.1-1l28.84-16.1A96,96,0,0,1,188.12,55l.11,32.2a8,8,0,0,0,1.22,4.22c.62,1,1.23,2,1.8,3.06a8.09,8.09,0,0,0,3,3.06l28.6,16.29A90.49,90.49,0,0,1,222.9,142.12Z"}))],["thin",a.createElement(a.Fragment,null,a.createElement("path",{d:"M128,84a44,44,0,1,0,44,44A44.05,44.05,0,0,0,128,84Zm0,80a36,36,0,1,1,36-36A36,36,0,0,1,128,164Zm106-56a4,4,0,0,0-2-2.7l-30.89-17.6q-.47-.82-1-1.62L200.1,51.2a3.94,3.94,0,0,0-1.42-3,107.8,107.8,0,0,0-35.41-19.94,4,4,0,0,0-3.23.29L129,45.87h-2l-31-17.36a4,4,0,0,0-3.23-.3,108.05,108.05,0,0,0-35.39,20,4,4,0,0,0-1.41,3l-.16,34.9-1,1.62L23.9,105.3A4,4,0,0,0,22,108a102.76,102.76,0,0,0,0,40,4,4,0,0,0,1.95,2.7l30.89,17.6q.47.83,1,1.62l.12,34.87a3.94,3.94,0,0,0,1.42,3,107.8,107.8,0,0,0,35.41,19.94,4,4,0,0,0,3.23-.29L127,210.13h2l31,17.36a4,4,0,0,0,3.23.3,108.05,108.05,0,0,0,35.39-20,4,4,0,0,0,1.41-3l.16-34.9,1-1.62L232.1,150.7a4,4,0,0,0,2-2.71A102.76,102.76,0,0,0,234,108Zm-7.48,36.67L196.3,161.84a4,4,0,0,0-1.51,1.53c-.61,1.09-1.25,2.17-1.91,3.24a3.92,3.92,0,0,0-.61,2.1l-.16,34.15a99.8,99.8,0,0,1-29.7,16.77l-30.4-17a4.06,4.06,0,0,0-2-.51H130c-1.28,0-2.57,0-3.84,0a4.1,4.1,0,0,0-2.05.51l-30.45,17A100.23,100.23,0,0,1,63.89,202.9l-.12-34.12a3.93,3.93,0,0,0-.61-2.11c-.66-1-1.3-2.14-1.91-3.23a4,4,0,0,0-1.51-1.53L29.49,144.68a94.78,94.78,0,0,1,0-33.34L59.7,94.16a4,4,0,0,0,1.51-1.53c.61-1.09,1.25-2.17,1.91-3.23a4,4,0,0,0,.61-2.11l.16-34.15a99.8,99.8,0,0,1,29.7-16.77l30.4,17a4.1,4.1,0,0,0,2.05.51c1.28,0,2.57,0,3.84,0a4,4,0,0,0,2.05-.51l30.45-17A100.23,100.23,0,0,1,192.11,53.1l.12,34.12a3.93,3.93,0,0,0,.61,2.11c.66,1,1.3,2.14,1.91,3.23a4,4,0,0,0,1.51,1.53l30.25,17.23A94.78,94.78,0,0,1,226.54,144.66Z"}))]]),j=new Map([["bold",a.createElement(a.Fragment,null,a.createElement("path",{d:"M224,44H32A20,20,0,0,0,12,64V192a20,20,0,0,0,20,20H224a20,20,0,0,0,20-20V64A20,20,0,0,0,224,44Zm-4,144H36V68H220ZM52,128a12,12,0,0,1,12-12H192a12,12,0,0,1,0,24H64A12,12,0,0,1,52,128Zm0-36A12,12,0,0,1,64,80H192a12,12,0,0,1,0,24H64A12,12,0,0,1,52,92Zm0,72a12,12,0,0,1,12-12h8a12,12,0,0,1,0,24H64A12,12,0,0,1,52,164Zm108,0a12,12,0,0,1-12,12H108a12,12,0,0,1,0-24h40A12,12,0,0,1,160,164Zm44,0a12,12,0,0,1-12,12h-8a12,12,0,0,1,0-24h8A12,12,0,0,1,204,164Z"}))],["duotone",a.createElement(a.Fragment,null,a.createElement("path",{d:"M232,64V192a8,8,0,0,1-8,8H32a8,8,0,0,1-8-8V64a8,8,0,0,1,8-8H224A8,8,0,0,1,232,64Z",opacity:"0.2"}),a.createElement("path",{d:"M224,48H32A16,16,0,0,0,16,64V192a16,16,0,0,0,16,16H224a16,16,0,0,0,16-16V64A16,16,0,0,0,224,48Zm0,144H32V64H224V192Zm-16-64a8,8,0,0,1-8,8H56a8,8,0,0,1,0-16H200A8,8,0,0,1,208,128Zm0-32a8,8,0,0,1-8,8H56a8,8,0,0,1,0-16H200A8,8,0,0,1,208,96ZM72,160a8,8,0,0,1-8,8H56a8,8,0,0,1,0-16h8A8,8,0,0,1,72,160Zm96,0a8,8,0,0,1-8,8H96a8,8,0,0,1,0-16h64A8,8,0,0,1,168,160Zm40,0a8,8,0,0,1-8,8h-8a8,8,0,0,1,0-16h8A8,8,0,0,1,208,160Z"}))],["fill",a.createElement(a.Fragment,null,a.createElement("path",{d:"M224,48H32A16,16,0,0,0,16,64V192a16,16,0,0,0,16,16H224a16,16,0,0,0,16-16V64A16,16,0,0,0,224,48ZM64,168H48a8,8,0,0,1,0-16H64a8,8,0,0,1,0,16Zm96,0H96a8,8,0,0,1,0-16h64a8,8,0,0,1,0,16Zm48,0H192a8,8,0,0,1,0-16h16a8,8,0,0,1,0,16Zm0-32H48a8,8,0,0,1,0-16H208a8,8,0,0,1,0,16Zm0-32H48a8,8,0,0,1,0-16H208a8,8,0,0,1,0,16Z"}))],["light",a.createElement(a.Fragment,null,a.createElement("path",{d:"M224,50H32A14,14,0,0,0,18,64V192a14,14,0,0,0,14,14H224a14,14,0,0,0,14-14V64A14,14,0,0,0,224,50Zm2,142a2,2,0,0,1-2,2H32a2,2,0,0,1-2-2V64a2,2,0,0,1,2-2H224a2,2,0,0,1,2,2Zm-20-64a6,6,0,0,1-6,6H56a6,6,0,0,1,0-12H200A6,6,0,0,1,206,128Zm0-32a6,6,0,0,1-6,6H56a6,6,0,0,1,0-12H200A6,6,0,0,1,206,96ZM70,160a6,6,0,0,1-6,6H56a6,6,0,0,1,0-12h8A6,6,0,0,1,70,160Zm96,0a6,6,0,0,1-6,6H96a6,6,0,0,1,0-12h64A6,6,0,0,1,166,160Zm40,0a6,6,0,0,1-6,6h-8a6,6,0,0,1,0-12h8A6,6,0,0,1,206,160Z"}))],["regular",a.createElement(a.Fragment,null,a.createElement("path",{d:"M224,48H32A16,16,0,0,0,16,64V192a16,16,0,0,0,16,16H224a16,16,0,0,0,16-16V64A16,16,0,0,0,224,48Zm0,144H32V64H224V192Zm-16-64a8,8,0,0,1-8,8H56a8,8,0,0,1,0-16H200A8,8,0,0,1,208,128Zm0-32a8,8,0,0,1-8,8H56a8,8,0,0,1,0-16H200A8,8,0,0,1,208,96ZM72,160a8,8,0,0,1-8,8H56a8,8,0,0,1,0-16h8A8,8,0,0,1,72,160Zm96,0a8,8,0,0,1-8,8H96a8,8,0,0,1,0-16h64A8,8,0,0,1,168,160Zm40,0a8,8,0,0,1-8,8h-8a8,8,0,0,1,0-16h8A8,8,0,0,1,208,160Z"}))],["thin",a.createElement(a.Fragment,null,a.createElement("path",{d:"M224,52H32A12,12,0,0,0,20,64V192a12,12,0,0,0,12,12H224a12,12,0,0,0,12-12V64A12,12,0,0,0,224,52Zm4,140a4,4,0,0,1-4,4H32a4,4,0,0,1-4-4V64a4,4,0,0,1,4-4H224a4,4,0,0,1,4,4Zm-24-64a4,4,0,0,1-4,4H56a4,4,0,0,1,0-8H200A4,4,0,0,1,204,128Zm0-32a4,4,0,0,1-4,4H56a4,4,0,0,1,0-8H200A4,4,0,0,1,204,96ZM68,160a4,4,0,0,1-4,4H56a4,4,0,0,1,0-8h8A4,4,0,0,1,68,160Zm96,0a4,4,0,0,1-4,4H96a4,4,0,0,1,0-8h64A4,4,0,0,1,164,160Zm40,0a4,4,0,0,1-4,4h-8a4,4,0,0,1,0-8h8A4,4,0,0,1,204,160Z"}))]]),m=a.forwardRef((l,c)=>a.createElement(o,{ref:c,...l,weights:E}));m.displayName="GearSixIcon";const g=m,p=a.forwardRef((l,c)=>a.createElement(o,{ref:c,...l,weights:j}));p.displayName="KeyboardIcon";const M=p;function f(){const[l,c]=a.useState("idle"),[r,i]=a.useState("");a.useEffect(()=>{chrome.tabs.query({active:!0,currentWindow:!0},([t])=>{if(t!=null&&t.url)try{i(new URL(t.url).hostname)}catch{i(t.url)}})},[]);async function h(){const[t]=await chrome.tabs.query({active:!0,currentWindow:!0});if(t!=null&&t.id){const n=l==="active"?"idle":"active";chrome.runtime.sendMessage({type:s.TOGGLE_INSPECT,payload:{active:n==="active"}}),c(n),n==="active"&&window.close()}}async function d(){chrome.runtime.sendMessage({type:s.SCAN_PAGE,payload:void 0}),chrome.runtime.sendMessage({type:s.OPEN_SIDE_PANEL,payload:void 0}),window.close()}async function A(){chrome.runtime.sendMessage({type:s.OPEN_SIDE_PANEL,payload:void 0}),window.close()}return e.jsxs("div",{className:"popup",children:[e.jsxs("header",{className:"popup-header",children:[e.jsxs("div",{className:"popup-logo",children:[e.jsxs("svg",{width:"20",height:"20",viewBox:"0 0 128 128",fill:"none",children:[e.jsx("circle",{cx:"56",cy:"56",r:"24",stroke:"#6366F1",strokeWidth:"6"}),e.jsx("line",{x1:"73",y1:"73",x2:"100",y2:"100",stroke:"#6366F1",strokeWidth:"6",strokeLinecap:"round"}),e.jsx("circle",{cx:"56",cy:"56",r:"8",fill:"#818CF8"})]}),e.jsx("span",{className:"popup-title",children:"PixelLens"})]}),r&&e.jsx("span",{className:"popup-url",children:r})]}),e.jsxs("div",{className:"popup-status",children:[e.jsx("div",{className:`popup-status-dot ${l==="active"?"active":""}`}),e.jsx("span",{children:l==="active"?"Inspecting":"Ready"})]}),e.jsxs("div",{className:"popup-actions",children:[e.jsxs("button",{className:"popup-btn popup-btn-primary",onClick:h,children:[e.jsx(Z,{size:18,weight:"bold"}),e.jsx("span",{children:l==="active"?"Stop Inspect":"Start Inspect"})]}),e.jsxs("button",{className:"popup-btn",onClick:d,children:[e.jsx(H,{size:18,weight:"bold"}),e.jsx("span",{children:"Scan this page"})]}),e.jsxs("button",{className:"popup-btn",onClick:A,children:[e.jsx(u,{size:18,weight:"bold"}),e.jsx("span",{children:"Last scan"})]})]}),e.jsxs("div",{className:"popup-shortcuts",children:[e.jsxs("div",{className:"popup-shortcuts-title",children:[e.jsx(M,{size:14,weight:"bold"}),e.jsx("span",{children:"Shortcuts"})]}),e.jsxs("div",{className:"popup-shortcut-row",children:[e.jsx("span",{children:"Toggle inspect"}),e.jsx("kbd",{children:"Ctrl+Shift+L"})]}),e.jsxs("div",{className:"popup-shortcut-row",children:[e.jsx("span",{children:"Open popup"}),e.jsx("kbd",{children:"Ctrl+Shift+P"})]})]}),e.jsxs("footer",{className:"popup-footer",children:[e.jsx("button",{className:"popup-footer-btn",title:"Settings",children:e.jsx(g,{size:16,weight:"bold"})}),e.jsx("span",{className:"popup-version",children:"v1.0.0"})]})]})}L.createRoot(document.getElementById("root")).render(e.jsx(x.StrictMode,{children:e.jsx(f,{})})); diff --git a/dist/assets/index.html-eJel1091.js b/dist/assets/index.html-eJel1091.js new file mode 100644 index 0000000..e619809 --- /dev/null +++ b/dist/assets/index.html-eJel1091.js @@ -0,0 +1,5 @@ +import{a as B}from"./ClockCounterClockwise.es-CQVwCTyJ.js";import{r as e,p as b,R as A,j as t,f as u0,s as f0,a as g0}from"./Scan.es-D0n8eUjn.js";import{M as w}from"./messages-CGxgbOds.js";import{s as b0}from"./Eyedropper.es-Cn4UL7iP.js";import{a as v0,b as V0,t as H0,s as Z0}from"./colors-Czz5EmDP.js";const j0=new Map([["bold",e.createElement(e.Fragment,null,e.createElement("path",{d:"M220,48V96a12,12,0,0,1-24,0V77l-39.51,39.52a12,12,0,0,1-17-17L179,60H160a12,12,0,0,1,0-24h48A12,12,0,0,1,220,48ZM99.51,139.51,60,179V160a12,12,0,0,0-24,0v48a12,12,0,0,0,12,12H96a12,12,0,0,0,0-24H77l39.52-39.51a12,12,0,0,0-17-17Z"}))],["duotone",e.createElement(e.Fragment,null,e.createElement("path",{d:"M224,48V208a16,16,0,0,1-16,16H48a16,16,0,0,1-16-16V48A16,16,0,0,1,48,32H208A16,16,0,0,1,224,48Z",opacity:"0.2"}),e.createElement("path",{d:"M216,48V96a8,8,0,0,1-16,0V67.31l-50.34,50.35a8,8,0,0,1-11.32-11.32L188.69,56H160a8,8,0,0,1,0-16h48A8,8,0,0,1,216,48ZM106.34,138.34,56,188.69V160a8,8,0,0,0-16,0v48a8,8,0,0,0,8,8H96a8,8,0,0,0,0-16H67.31l50.35-50.34a8,8,0,0,0-11.32-11.32Z"}))],["fill",e.createElement(e.Fragment,null,e.createElement("path",{d:"M117.66,138.34a8,8,0,0,1,0,11.32L83.31,184l18.35,18.34A8,8,0,0,1,96,216H48a8,8,0,0,1-8-8V160a8,8,0,0,1,13.66-5.66L72,172.69l34.34-34.35A8,8,0,0,1,117.66,138.34ZM208,40H160a8,8,0,0,0-5.66,13.66L172.69,72l-34.35,34.34a8,8,0,0,0,11.32,11.32L184,83.31l18.34,18.35A8,8,0,0,0,216,96V48A8,8,0,0,0,208,40Z"}))],["light",e.createElement(e.Fragment,null,e.createElement("path",{d:"M214,48V96a6,6,0,0,1-12,0V62.48l-53.76,53.76a6,6,0,0,1-8.48-8.48L193.52,54H160a6,6,0,0,1,0-12h48A6,6,0,0,1,214,48ZM107.76,139.76,54,193.52V160a6,6,0,0,0-12,0v48a6,6,0,0,0,6,6H96a6,6,0,0,0,0-12H62.48l53.76-53.76a6,6,0,0,0-8.48-8.48Z"}))],["regular",e.createElement(e.Fragment,null,e.createElement("path",{d:"M216,48V96a8,8,0,0,1-16,0V67.31l-50.34,50.35a8,8,0,0,1-11.32-11.32L188.69,56H160a8,8,0,0,1,0-16h48A8,8,0,0,1,216,48ZM106.34,138.34,56,188.69V160a8,8,0,0,0-16,0v48a8,8,0,0,0,8,8H96a8,8,0,0,0,0-16H67.31l50.35-50.34a8,8,0,0,0-11.32-11.32Z"}))],["thin",e.createElement(e.Fragment,null,e.createElement("path",{d:"M212,48V96a4,4,0,0,1-8,0V57.66l-57.17,57.17a4,4,0,0,1-5.66-5.66L198.34,52H160a4,4,0,0,1,0-8h48A4,4,0,0,1,212,48ZM109.17,141.17,52,198.34V160a4,4,0,0,0-8,0v48a4,4,0,0,0,4,4H96a4,4,0,0,0,0-8H57.66l57.17-57.17a4,4,0,0,0-5.66-5.66Z"}))]]),E0=new Map([["bold",e.createElement(e.Fragment,null,e.createElement("path",{d:"M208,100a20,20,0,0,0,20-20V48a20,20,0,0,0-20-20H176a20,20,0,0,0-20,20v4H100V48A20,20,0,0,0,80,28H48A20,20,0,0,0,28,48V80a20,20,0,0,0,20,20h4v56H48a20,20,0,0,0-20,20v32a20,20,0,0,0,20,20H80a20,20,0,0,0,20-20v-4h56v4a20,20,0,0,0,20,20h32a20,20,0,0,0,20-20V176a20,20,0,0,0-20-20h-4V100ZM180,52h24V76H180ZM52,52H76V76H52ZM76,204H52V180H76Zm128,0H180V180h24Zm-24-48h-4a20,20,0,0,0-20,20v4H100v-4a20,20,0,0,0-20-20H76V100h4a20,20,0,0,0,20-20V76h56v4a20,20,0,0,0,20,20h4Z"}))],["duotone",e.createElement(e.Fragment,null,e.createElement("path",{d:"M216,48V80a8,8,0,0,1-8,8H176a8,8,0,0,1-8-8V48a8,8,0,0,1,8-8h32A8,8,0,0,1,216,48ZM80,40H48a8,8,0,0,0-8,8V80a8,8,0,0,0,8,8H80a8,8,0,0,0,8-8V48A8,8,0,0,0,80,40ZM208,168H176a8,8,0,0,0-8,8v32a8,8,0,0,0,8,8h32a8,8,0,0,0,8-8V176A8,8,0,0,0,208,168ZM80,168H48a8,8,0,0,0-8,8v32a8,8,0,0,0,8,8H80a8,8,0,0,0,8-8V176A8,8,0,0,0,80,168Z",opacity:"0.2"}),e.createElement("path",{d:"M208,96a16,16,0,0,0,16-16V48a16,16,0,0,0-16-16H176a16,16,0,0,0-16,16v8H96V48A16,16,0,0,0,80,32H48A16,16,0,0,0,32,48V80A16,16,0,0,0,48,96h8v64H48a16,16,0,0,0-16,16v32a16,16,0,0,0,16,16H80a16,16,0,0,0,16-16v-8h64v8a16,16,0,0,0,16,16h32a16,16,0,0,0,16-16V176a16,16,0,0,0-16-16h-8V96ZM176,48h32V80H176ZM48,48H80V63.9a.51.51,0,0,0,0,.2V80H48ZM80,208H48V176H80v15.9a.51.51,0,0,0,0,.2V208Zm128,0H176V176h32Zm-24-48h-8a16,16,0,0,0-16,16v8H96v-8a16,16,0,0,0-16-16H72V96h8A16,16,0,0,0,96,80V72h64v8a16,16,0,0,0,16,16h8Z"}))],["fill",e.createElement(e.Fragment,null,e.createElement("path",{d:"M208,96a16,16,0,0,0,16-16V48a16,16,0,0,0-16-16H176a16,16,0,0,0-16,16v8H96V48A16,16,0,0,0,80,32H48A16,16,0,0,0,32,48V80A16,16,0,0,0,48,96h8v64H48a16,16,0,0,0-16,16v32a16,16,0,0,0,16,16H80a16,16,0,0,0,16-16v-8h64v8a16,16,0,0,0,16,16h32a16,16,0,0,0,16-16V176a16,16,0,0,0-16-16h-8V96Zm-24,64h-8a16,16,0,0,0-16,16v8H96v-8a16,16,0,0,0-16-16H72V96h8A16,16,0,0,0,96,80V72h64v8a16,16,0,0,0,16,16h8Z"}))],["light",e.createElement(e.Fragment,null,e.createElement("path",{d:"M208,94a14,14,0,0,0,14-14V48a14,14,0,0,0-14-14H176a14,14,0,0,0-14,14V58H94V48A14,14,0,0,0,80,34H48A14,14,0,0,0,34,48V80A14,14,0,0,0,48,94H58v68H48a14,14,0,0,0-14,14v32a14,14,0,0,0,14,14H80a14,14,0,0,0,14-14V198h68v10a14,14,0,0,0,14,14h32a14,14,0,0,0,14-14V176a14,14,0,0,0-14-14H198V94ZM174,48a2,2,0,0,1,2-2h32a2,2,0,0,1,2,2V80a2,2,0,0,1-2,2H176a2,2,0,0,1-2-2ZM46,80V48a2,2,0,0,1,2-2H80a2,2,0,0,1,2,2V80a2,2,0,0,1-2,2H48A2,2,0,0,1,46,80ZM82,208a2,2,0,0,1-2,2H48a2,2,0,0,1-2-2V176a2,2,0,0,1,2-2H80a2,2,0,0,1,2,2Zm128-32v32a2,2,0,0,1-2,2H176a2,2,0,0,1-2-2V176a2,2,0,0,1,2-2h32A2,2,0,0,1,210,176Zm-24-14H176a14,14,0,0,0-14,14v10H94V176a14,14,0,0,0-14-14H70V94H80A14,14,0,0,0,94,80V70h68V80a14,14,0,0,0,14,14h10Z"}))],["regular",e.createElement(e.Fragment,null,e.createElement("path",{d:"M208,96a16,16,0,0,0,16-16V48a16,16,0,0,0-16-16H176a16,16,0,0,0-16,16v8H96V48A16,16,0,0,0,80,32H48A16,16,0,0,0,32,48V80A16,16,0,0,0,48,96h8v64H48a16,16,0,0,0-16,16v32a16,16,0,0,0,16,16H80a16,16,0,0,0,16-16v-8h64v8a16,16,0,0,0,16,16h32a16,16,0,0,0,16-16V176a16,16,0,0,0-16-16h-8V96ZM176,48h32V80H176ZM48,48H80V63.9a.51.51,0,0,0,0,.2V80H48ZM80,208H48V176H80v15.9a.51.51,0,0,0,0,.2V208Zm128,0H176V176h32Zm-24-48h-8a16,16,0,0,0-16,16v8H96v-8a16,16,0,0,0-16-16H72V96h8A16,16,0,0,0,96,80V72h64v8a16,16,0,0,0,16,16h8Z"}))],["thin",e.createElement(e.Fragment,null,e.createElement("path",{d:"M208,92a12,12,0,0,0,12-12V48a12,12,0,0,0-12-12H176a12,12,0,0,0-12,12V60H92V48A12,12,0,0,0,80,36H48A12,12,0,0,0,36,48V80A12,12,0,0,0,48,92H60v72H48a12,12,0,0,0-12,12v32a12,12,0,0,0,12,12H80a12,12,0,0,0,12-12V196h72v12a12,12,0,0,0,12,12h32a12,12,0,0,0,12-12V176a12,12,0,0,0-12-12H196V92ZM172,48a4,4,0,0,1,4-4h32a4,4,0,0,1,4,4V80a4,4,0,0,1-4,4H176a4,4,0,0,1-4-4ZM44,80V48a4,4,0,0,1,4-4H80a4,4,0,0,1,4,4V80a4,4,0,0,1-4,4H48A4,4,0,0,1,44,80ZM84,208a4,4,0,0,1-4,4H48a4,4,0,0,1-4-4V176a4,4,0,0,1,4-4H80a4,4,0,0,1,4,4Zm128-32v32a4,4,0,0,1-4,4H176a4,4,0,0,1-4-4V176a4,4,0,0,1,4-4h32A4,4,0,0,1,212,176Zm-24-12H176a12,12,0,0,0-12,12v12H92V176a12,12,0,0,0-12-12H68V92H80A12,12,0,0,0,92,80V68h72V80a12,12,0,0,0,12,12h12Z"}))]]),M0=new Map([["bold",e.createElement(e.Fragment,null,e.createElement("path",{d:"M216.49,104.49l-80,80a12,12,0,0,1-17,0l-80-80a12,12,0,0,1,17-17L128,159l71.51-71.52a12,12,0,0,1,17,17Z"}))],["duotone",e.createElement(e.Fragment,null,e.createElement("path",{d:"M208,96l-80,80L48,96Z",opacity:"0.2"}),e.createElement("path",{d:"M215.39,92.94A8,8,0,0,0,208,88H48a8,8,0,0,0-5.66,13.66l80,80a8,8,0,0,0,11.32,0l80-80A8,8,0,0,0,215.39,92.94ZM128,164.69,67.31,104H188.69Z"}))],["fill",e.createElement(e.Fragment,null,e.createElement("path",{d:"M213.66,101.66l-80,80a8,8,0,0,1-11.32,0l-80-80A8,8,0,0,1,48,88H208a8,8,0,0,1,5.66,13.66Z"}))],["light",e.createElement(e.Fragment,null,e.createElement("path",{d:"M212.24,100.24l-80,80a6,6,0,0,1-8.48,0l-80-80a6,6,0,0,1,8.48-8.48L128,167.51l75.76-75.75a6,6,0,0,1,8.48,8.48Z"}))],["regular",e.createElement(e.Fragment,null,e.createElement("path",{d:"M213.66,101.66l-80,80a8,8,0,0,1-11.32,0l-80-80A8,8,0,0,1,53.66,90.34L128,164.69l74.34-74.35a8,8,0,0,1,11.32,11.32Z"}))],["thin",e.createElement(e.Fragment,null,e.createElement("path",{d:"M210.83,98.83l-80,80a4,4,0,0,1-5.66,0l-80-80a4,4,0,0,1,5.66-5.66L128,170.34l77.17-77.17a4,4,0,1,1,5.66,5.66Z"}))]]),A0=new Map([["bold",e.createElement(e.Fragment,null,e.createElement("path",{d:"M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z"}))],["duotone",e.createElement(e.Fragment,null,e.createElement("path",{d:"M232,56V200a16,16,0,0,1-16,16H40a16,16,0,0,1-16-16V56A16,16,0,0,1,40,40H216A16,16,0,0,1,232,56Z",opacity:"0.2"}),e.createElement("path",{d:"M205.66,85.66l-96,96a8,8,0,0,1-11.32,0l-40-40a8,8,0,0,1,11.32-11.32L104,164.69l90.34-90.35a8,8,0,0,1,11.32,11.32Z"}))],["fill",e.createElement(e.Fragment,null,e.createElement("path",{d:"M216,40H40A16,16,0,0,0,24,56V200a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A16,16,0,0,0,216,40ZM205.66,85.66l-96,96a8,8,0,0,1-11.32,0l-40-40a8,8,0,0,1,11.32-11.32L104,164.69l90.34-90.35a8,8,0,0,1,11.32,11.32Z"}))],["light",e.createElement(e.Fragment,null,e.createElement("path",{d:"M228.24,76.24l-128,128a6,6,0,0,1-8.48,0l-56-56a6,6,0,0,1,8.48-8.48L96,191.51,219.76,67.76a6,6,0,0,1,8.48,8.48Z"}))],["regular",e.createElement(e.Fragment,null,e.createElement("path",{d:"M229.66,77.66l-128,128a8,8,0,0,1-11.32,0l-56-56a8,8,0,0,1,11.32-11.32L96,188.69,218.34,66.34a8,8,0,0,1,11.32,11.32Z"}))],["thin",e.createElement(e.Fragment,null,e.createElement("path",{d:"M226.83,74.83l-128,128a4,4,0,0,1-5.66,0l-56-56a4,4,0,0,1,5.66-5.66L96,194.34,221.17,69.17a4,4,0,1,1,5.66,5.66Z"}))]]),y0=new Map([["bold",e.createElement(e.Fragment,null,e.createElement("path",{d:"M128,20A108,108,0,1,0,236,128,108.12,108.12,0,0,0,128,20Zm0,192a84,84,0,1,1,84-84A84.09,84.09,0,0,1,128,212Z"}))],["duotone",e.createElement(e.Fragment,null,e.createElement("path",{d:"M224,128a96,96,0,1,1-96-96A96,96,0,0,1,224,128Z",opacity:"0.2"}),e.createElement("path",{d:"M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.1,88.1,0,0,1,128,216Z"}))],["fill",e.createElement(e.Fragment,null,e.createElement("path",{d:"M232,128A104,104,0,1,1,128,24,104.13,104.13,0,0,1,232,128Z"}))],["light",e.createElement(e.Fragment,null,e.createElement("path",{d:"M128,26A102,102,0,1,0,230,128,102.12,102.12,0,0,0,128,26Zm0,192a90,90,0,1,1,90-90A90.1,90.1,0,0,1,128,218Z"}))],["regular",e.createElement(e.Fragment,null,e.createElement("path",{d:"M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.1,88.1,0,0,1,128,216Z"}))],["thin",e.createElement(e.Fragment,null,e.createElement("path",{d:"M128,28A100,100,0,1,0,228,128,100.11,100.11,0,0,0,128,28Zm0,192a92,92,0,1,1,92-92A92.1,92.1,0,0,1,128,220Z"}))]]),w0=new Map([["bold",e.createElement(e.Fragment,null,e.createElement("path",{d:"M71.68,97.22,34.74,128l36.94,30.78a12,12,0,1,1-15.36,18.44l-48-40a12,12,0,0,1,0-18.44l48-40A12,12,0,0,1,71.68,97.22Zm176,21.56-48-40a12,12,0,1,0-15.36,18.44L221.26,128l-36.94,30.78a12,12,0,1,0,15.36,18.44l48-40a12,12,0,0,0,0-18.44ZM164.1,28.72a12,12,0,0,0-15.38,7.18l-64,176a12,12,0,0,0,7.18,15.37A11.79,11.79,0,0,0,96,228a12,12,0,0,0,11.28-7.9l64-176A12,12,0,0,0,164.1,28.72Z"}))],["duotone",e.createElement(e.Fragment,null,e.createElement("path",{d:"M240,128l-48,40H64L16,128,64,88H192Z",opacity:"0.2"}),e.createElement("path",{d:"M69.12,94.15,28.5,128l40.62,33.85a8,8,0,1,1-10.24,12.29l-48-40a8,8,0,0,1,0-12.29l48-40a8,8,0,0,1,10.24,12.3Zm176,27.7-48-40a8,8,0,1,0-10.24,12.3L227.5,128l-40.62,33.85a8,8,0,1,0,10.24,12.29l48-40a8,8,0,0,0,0-12.29ZM162.73,32.48a8,8,0,0,0-10.25,4.79l-64,176a8,8,0,0,0,4.79,10.26A8.14,8.14,0,0,0,96,224a8,8,0,0,0,7.52-5.27l64-176A8,8,0,0,0,162.73,32.48Z"}))],["fill",e.createElement(e.Fragment,null,e.createElement("path",{d:"M216,40H40A16,16,0,0,0,24,56V200a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A16,16,0,0,0,216,40ZM92.8,145.6a8,8,0,1,1-9.6,12.8l-32-24a8,8,0,0,1,0-12.8l32-24a8,8,0,0,1,9.6,12.8L69.33,128Zm58.89-71.4-32,112a8,8,0,1,1-15.38-4.4l32-112a8,8,0,0,1,15.38,4.4Zm53.11,60.2-32,24a8,8,0,0,1-9.6-12.8L186.67,128,163.2,110.4a8,8,0,1,1,9.6-12.8l32,24a8,8,0,0,1,0,12.8Z"}))],["light",e.createElement(e.Fragment,null,e.createElement("path",{d:"M67.84,92.61,25.37,128l42.47,35.39a6,6,0,1,1-7.68,9.22l-48-40a6,6,0,0,1,0-9.22l48-40a6,6,0,0,1,7.68,9.22Zm176,30.78-48-40a6,6,0,1,0-7.68,9.22L230.63,128l-42.47,35.39a6,6,0,1,0,7.68,9.22l48-40a6,6,0,0,0,0-9.22Zm-81.79-89A6,6,0,0,0,154.36,38l-64,176A6,6,0,0,0,94,221.64a6.15,6.15,0,0,0,2,.36,6,6,0,0,0,5.64-3.95l64-176A6,6,0,0,0,162.05,34.36Z"}))],["regular",e.createElement(e.Fragment,null,e.createElement("path",{d:"M69.12,94.15,28.5,128l40.62,33.85a8,8,0,1,1-10.24,12.29l-48-40a8,8,0,0,1,0-12.29l48-40a8,8,0,0,1,10.24,12.3Zm176,27.7-48-40a8,8,0,1,0-10.24,12.3L227.5,128l-40.62,33.85a8,8,0,1,0,10.24,12.29l48-40a8,8,0,0,0,0-12.29ZM162.73,32.48a8,8,0,0,0-10.25,4.79l-64,176a8,8,0,0,0,4.79,10.26A8.14,8.14,0,0,0,96,224a8,8,0,0,0,7.52-5.27l64-176A8,8,0,0,0,162.73,32.48Z"}))],["thin",e.createElement(e.Fragment,null,e.createElement("path",{d:"M66.56,91.07,22.25,128l44.31,36.93A4,4,0,0,1,64,172a3.94,3.94,0,0,1-2.56-.93l-48-40a4,4,0,0,1,0-6.14l48-40a4,4,0,0,1,5.12,6.14Zm176,33.86-48-40a4,4,0,1,0-5.12,6.14L233.75,128l-44.31,36.93a4,4,0,1,0,5.12,6.14l48-40a4,4,0,0,0,0-6.14ZM161.37,36.24a4,4,0,0,0-5.13,2.39l-64,176a4,4,0,0,0,2.39,5.13A4.12,4.12,0,0,0,96,220a4,4,0,0,0,3.76-2.63l64-176A4,4,0,0,0,161.37,36.24Z"}))]]),N0=new Map([["bold",e.createElement(e.Fragment,null,e.createElement("path",{d:"M216,28H88A12,12,0,0,0,76,40V76H40A12,12,0,0,0,28,88V216a12,12,0,0,0,12,12H168a12,12,0,0,0,12-12V180h36a12,12,0,0,0,12-12V40A12,12,0,0,0,216,28ZM156,204H52V100H156Zm48-48H180V88a12,12,0,0,0-12-12H100V52H204Z"}))],["duotone",e.createElement(e.Fragment,null,e.createElement("path",{d:"M216,40V168H168V88H88V40Z",opacity:"0.2"}),e.createElement("path",{d:"M216,32H88a8,8,0,0,0-8,8V80H40a8,8,0,0,0-8,8V216a8,8,0,0,0,8,8H168a8,8,0,0,0,8-8V176h40a8,8,0,0,0,8-8V40A8,8,0,0,0,216,32ZM160,208H48V96H160Zm48-48H176V88a8,8,0,0,0-8-8H96V48H208Z"}))],["fill",e.createElement(e.Fragment,null,e.createElement("path",{d:"M216,32H88a8,8,0,0,0-8,8V80H40a8,8,0,0,0-8,8V216a8,8,0,0,0,8,8H168a8,8,0,0,0,8-8V176h40a8,8,0,0,0,8-8V40A8,8,0,0,0,216,32Zm-8,128H176V88a8,8,0,0,0-8-8H96V48H208Z"}))],["light",e.createElement(e.Fragment,null,e.createElement("path",{d:"M216,34H88a6,6,0,0,0-6,6V82H40a6,6,0,0,0-6,6V216a6,6,0,0,0,6,6H168a6,6,0,0,0,6-6V174h42a6,6,0,0,0,6-6V40A6,6,0,0,0,216,34ZM162,210H46V94H162Zm48-48H174V88a6,6,0,0,0-6-6H94V46H210Z"}))],["regular",e.createElement(e.Fragment,null,e.createElement("path",{d:"M216,32H88a8,8,0,0,0-8,8V80H40a8,8,0,0,0-8,8V216a8,8,0,0,0,8,8H168a8,8,0,0,0,8-8V176h40a8,8,0,0,0,8-8V40A8,8,0,0,0,216,32ZM160,208H48V96H160Zm48-48H176V88a8,8,0,0,0-8-8H96V48H208Z"}))],["thin",e.createElement(e.Fragment,null,e.createElement("path",{d:"M216,36H88a4,4,0,0,0-4,4V84H40a4,4,0,0,0-4,4V216a4,4,0,0,0,4,4H168a4,4,0,0,0,4-4V172h44a4,4,0,0,0,4-4V40A4,4,0,0,0,216,36ZM164,212H44V92H164Zm48-48H172V88a4,4,0,0,0-4-4H92V44H212Z"}))]]),S0=new Map([["bold",e.createElement(e.Fragment,null,e.createElement("path",{d:"M224.15,179.17l-46.82-46.82,37.92-13.51c.26-.09.51-.19.76-.3a20,20,0,0,0-1.76-37.27L54.16,29A20,20,0,0,0,29,54.16L81.27,214.24A20,20,0,0,0,118.54,216c.11-.25.21-.5.3-.76l13.51-37.92,46.83,46.82a20,20,0,0,0,28.28,0l16.69-16.68A20,20,0,0,0,224.15,179.17Zm-30.83,25.17-48.48-48.48A20,20,0,0,0,130.7,150a20.47,20.47,0,0,0-3.73.35A20,20,0,0,0,112.35,162c-.11.25-.2.5-.3.76L100.4,195.5,54.29,54.29,195.5,100.4l-32.71,11.65c-.25.09-.51.19-.76.3a20,20,0,0,0-6.16,32.48h0l48.48,48.48ZM84,16V12a12,12,0,0,1,24,0v4a12,12,0,0,1-24,0ZM12,108a12,12,0,0,1,0-24h4a12,12,0,0,1,0,24ZM120.62,24.21l4-12a12,12,0,0,1,22.77,7.58l-4,12a12,12,0,0,1-22.77-7.58Zm-81.23,104a12,12,0,0,1-7.59,15.17l-12,4a12,12,0,1,1-7.59-22.76l12-4A12,12,0,0,1,39.39,128.21Z"}))],["duotone",e.createElement(e.Fragment,null,e.createElement("path",{d:"M213.66,201,201,213.66a8,8,0,0,1-11.31,0l-51.31-51.31a8,8,0,0,0-13,2.46l-17.82,46.41a8,8,0,0,1-14.85-.71L40.41,50.44a8,8,0,0,1,10-10L210.51,92.68a8,8,0,0,1,.71,14.85l-46.41,17.82a8,8,0,0,0-2.46,13l51.31,51.31A8,8,0,0,1,213.66,201Z",opacity:"0.2"}),e.createElement("path",{d:"M88,24V16a8,8,0,0,1,16,0v8a8,8,0,0,1-16,0ZM16,104h8a8,8,0,0,0,0-16H16a8,8,0,0,0,0,16ZM124.42,39.16a8,8,0,0,0,10.74-3.58l8-16a8,8,0,0,0-14.31-7.16l-8,16A8,8,0,0,0,124.42,39.16Zm-96,81.69-16,8a8,8,0,0,0,7.16,14.31l16-8a8,8,0,1,0-7.16-14.31ZM219.31,184a16,16,0,0,1,0,22.63l-12.68,12.68a16,16,0,0,1-22.63,0L132.7,168,115,214.09c0,.1-.08.21-.13.32a15.83,15.83,0,0,1-14.6,9.59l-.79,0a15.83,15.83,0,0,1-14.41-11L32.8,52.92A16,16,0,0,1,52.92,32.8L213,85.07a16,16,0,0,1,1.41,29.8l-.32.13L168,132.69ZM208,195.31,156.69,144h0a16,16,0,0,1,4.93-26l.32-.14,45.95-17.64L48,48l52.2,159.86,17.65-46c0-.11.08-.22.13-.33a16,16,0,0,1,11.69-9.34,16.72,16.72,0,0,1,3-.28,16,16,0,0,1,11.3,4.69L195.31,208Z"}))],["fill",e.createElement(e.Fragment,null,e.createElement("path",{d:"M220.49,190.83a12,12,0,0,1,0,17L207.8,220.49a12,12,0,0,1-17,0l-56.56-56.57L115,214.09c0,.1-.08.21-.13.32a15.83,15.83,0,0,1-14.6,9.59l-.79,0a15.83,15.83,0,0,1-14.41-11L32.8,52.92A16,16,0,0,1,52.92,32.8L213,85.07a16,16,0,0,1,1.41,29.8l-.32.13-50.17,19.27ZM96,32a8,8,0,0,0,8-8V16a8,8,0,0,0-16,0v8A8,8,0,0,0,96,32ZM16,104h8a8,8,0,0,0,0-16H16a8,8,0,0,0,0,16ZM124.42,39.16a8,8,0,0,0,10.74-3.58l8-16a8,8,0,0,0-14.31-7.16l-8,16A8,8,0,0,0,124.42,39.16Zm-96,81.69-16,8a8,8,0,0,0,7.16,14.31l16-8a8,8,0,1,0-7.16-14.31Z"}))],["light",e.createElement(e.Fragment,null,e.createElement("path",{d:"M90,24V16a6,6,0,0,1,12,0v8a6,6,0,0,1-12,0ZM16,102h8a6,6,0,0,0,0-12H16a6,6,0,0,0,0,12ZM125.32,37.37a6,6,0,0,0,8.05-2.69l8-16a6,6,0,0,0-10.74-5.37l-8,16A6,6,0,0,0,125.32,37.37Zm-96,85.26-16,8a6,6,0,0,0,5.36,10.74l16-8a6,6,0,1,0-5.36-10.74ZM217.9,185.41a14,14,0,0,1,0,19.8L205.21,217.9a14,14,0,0,1-19.8,0L134.1,166.59a2,2,0,0,0-3.21.54l-17.75,46.24a2.44,2.44,0,0,0-.1.24A13.85,13.85,0,0,1,100.26,222c-.23,0-.45,0-.68,0A13.85,13.85,0,0,1,87,212.38L34.7,52.3A14,14,0,0,1,52.3,34.7L212.38,87A14,14,0,0,1,213.61,113l-.24.09-46.25,17.76a2,2,0,0,0-.53,3.21Zm-8.49,8.49L158.1,142.59h0a14,14,0,0,1,4.32-22.74l.24-.1L208.91,102a2,2,0,0,0-.26-3.61L48.58,46.11a2.33,2.33,0,0,0-.65-.11,2,2,0,0,0-1.82,2.58L98.38,208.65a1.84,1.84,0,0,0,1.77,1.35,1.81,1.81,0,0,0,1.84-1.09l17.76-46.25.1-.24a14,14,0,0,1,22.74-4.32l51.31,51.31a2,2,0,0,0,2.83,0l12.68-12.68A2,2,0,0,0,209.41,193.9Z"}))],["regular",e.createElement(e.Fragment,null,e.createElement("path",{d:"M88,24V16a8,8,0,0,1,16,0v8a8,8,0,0,1-16,0ZM16,104h8a8,8,0,0,0,0-16H16a8,8,0,0,0,0,16ZM124.42,39.16a8,8,0,0,0,10.74-3.58l8-16a8,8,0,0,0-14.31-7.16l-8,16A8,8,0,0,0,124.42,39.16Zm-96,81.69-16,8a8,8,0,0,0,7.16,14.31l16-8a8,8,0,1,0-7.16-14.31ZM219.31,184a16,16,0,0,1,0,22.63l-12.68,12.68a16,16,0,0,1-22.63,0L132.7,168,115,214.09c0,.1-.08.21-.13.32a15.83,15.83,0,0,1-14.6,9.59l-.79,0a15.83,15.83,0,0,1-14.41-11L32.8,52.92A16,16,0,0,1,52.92,32.8L213,85.07a16,16,0,0,1,1.41,29.8l-.32.13L168,132.69ZM208,195.31,156.69,144h0a16,16,0,0,1,4.93-26l.32-.14,45.95-17.64L48,48l52.2,159.86,17.65-46c0-.11.08-.22.13-.33a16,16,0,0,1,11.69-9.34,16.72,16.72,0,0,1,3-.28,16,16,0,0,1,11.3,4.69L195.31,208Z"}))],["thin",e.createElement(e.Fragment,null,e.createElement("path",{d:"M92,24V16a4,4,0,0,1,8,0v8a4,4,0,0,1-8,0ZM16,100h8a4,4,0,0,0,0-8H16a4,4,0,0,0,0,8ZM126.21,35.58a4,4,0,0,0,5.37-1.79l8-16a4,4,0,0,0-7.16-3.58l-8,16A4,4,0,0,0,126.21,35.58Zm-96,88.84-16,8a4,4,0,0,0,3.58,7.16l16-8a4,4,0,1,0-3.58-7.16Zm186.28,62.41a12,12,0,0,1,0,17L203.8,216.49a12,12,0,0,1-17,0l-51.31-51.31a3.93,3.93,0,0,0-3.58-1.11,4,4,0,0,0-2.89,2.27l-17.78,46.31a.77.77,0,0,1-.07.16A11.85,11.85,0,0,1,100.26,220h-.59a11.88,11.88,0,0,1-10.8-8.23L36.6,51.68A12,12,0,0,1,51.68,36.6L211.76,88.87a12,12,0,0,1,1.05,22.33l-.16.07-46.31,17.78a4,4,0,0,0-1.17,6.47Zm-5.66,5.66-51.31-51.32a12,12,0,0,1,3.7-19.49l.16-.06,46.31-17.79a3.95,3.95,0,0,0-.42-7.35L49.2,44.21a4,4,0,0,0-5,5L96.48,209.27a4,4,0,0,0,7.36.42l17.78-46.31a1.11,1.11,0,0,1,.07-.16,12,12,0,0,1,8.76-7,12.21,12.21,0,0,1,2.24-.21,12,12,0,0,1,8.49,3.52l51.31,51.31a4,4,0,0,0,5.65,0l12.69-12.69A4,4,0,0,0,210.83,192.49Z"}))]]),L0=new Map([["bold",e.createElement(e.Fragment,null,e.createElement("path",{d:"M228,144v64a12,12,0,0,1-12,12H40a12,12,0,0,1-12-12V144a12,12,0,0,1,24,0v52H204V144a12,12,0,0,1,24,0Zm-108.49,8.49a12,12,0,0,0,17,0l40-40a12,12,0,0,0-17-17L140,115V32a12,12,0,0,0-24,0v83L96.49,95.51a12,12,0,0,0-17,17Z"}))],["duotone",e.createElement(e.Fragment,null,e.createElement("path",{d:"M216,48V208H40V48A16,16,0,0,1,56,32H200A16,16,0,0,1,216,48Z",opacity:"0.2"}),e.createElement("path",{d:"M224,144v64a8,8,0,0,1-8,8H40a8,8,0,0,1-8-8V144a8,8,0,0,1,16,0v56H208V144a8,8,0,0,1,16,0Zm-101.66,5.66a8,8,0,0,0,11.32,0l40-40a8,8,0,0,0-11.32-11.32L136,124.69V32a8,8,0,0,0-16,0v92.69L93.66,98.34a8,8,0,0,0-11.32,11.32Z"}))],["fill",e.createElement(e.Fragment,null,e.createElement("path",{d:"M224,144v64a8,8,0,0,1-8,8H40a8,8,0,0,1-8-8V144a8,8,0,0,1,16,0v56H208V144a8,8,0,0,1,16,0Zm-101.66,5.66a8,8,0,0,0,11.32,0l40-40A8,8,0,0,0,168,96H136V32a8,8,0,0,0-16,0V96H88a8,8,0,0,0-5.66,13.66Z"}))],["light",e.createElement(e.Fragment,null,e.createElement("path",{d:"M222,144v64a6,6,0,0,1-6,6H40a6,6,0,0,1-6-6V144a6,6,0,0,1,12,0v58H210V144a6,6,0,0,1,12,0Zm-98.24,4.24a6,6,0,0,0,8.48,0l40-40a6,6,0,0,0-8.48-8.48L134,129.51V32a6,6,0,0,0-12,0v97.51L92.24,99.76a6,6,0,0,0-8.48,8.48Z"}))],["regular",e.createElement(e.Fragment,null,e.createElement("path",{d:"M224,144v64a8,8,0,0,1-8,8H40a8,8,0,0,1-8-8V144a8,8,0,0,1,16,0v56H208V144a8,8,0,0,1,16,0Zm-101.66,5.66a8,8,0,0,0,11.32,0l40-40a8,8,0,0,0-11.32-11.32L136,124.69V32a8,8,0,0,0-16,0v92.69L93.66,98.34a8,8,0,0,0-11.32,11.32Z"}))],["thin",e.createElement(e.Fragment,null,e.createElement("path",{d:"M220,144v64a4,4,0,0,1-4,4H40a4,4,0,0,1-4-4V144a4,4,0,0,1,8,0v60H212V144a4,4,0,0,1,8,0Zm-94.83,2.83a4,4,0,0,0,5.66,0l40-40a4,4,0,1,0-5.66-5.66L132,134.34V32a4,4,0,0,0-8,0V134.34L90.83,101.17a4,4,0,0,0-5.66,5.66Z"}))]]),F0=new Map([["bold",e.createElement(e.Fragment,null,e.createElement("path",{d:"M134.88,6.17a12,12,0,0,0-13.76,0,259,259,0,0,0-42.18,39C50.85,77.43,36,111.62,36,144a92,92,0,0,0,184,0C220,66.64,138.36,8.6,134.88,6.17ZM128,212a68.07,68.07,0,0,1-68-68c0-33.31,20-63.37,36.7-82.71A249.35,249.35,0,0,1,128,31.11a249.35,249.35,0,0,1,31.3,30.18C176,80.63,196,110.69,196,144A68.07,68.07,0,0,1,128,212Zm49.62-52.4a52,52,0,0,1-34,34,12.2,12.2,0,0,1-3.6.55,12,12,0,0,1-3.6-23.45,28,28,0,0,0,18.32-18.32,12,12,0,0,1,22.9,7.2Z"}))],["duotone",e.createElement(e.Fragment,null,e.createElement("path",{d:"M208,144a80,80,0,0,1-160,0c0-72,80-128,80-128S208,72,208,144Z",opacity:"0.2"}),e.createElement("path",{d:"M174,47.75a254.19,254.19,0,0,0-41.45-38.3,8,8,0,0,0-9.18,0A254.19,254.19,0,0,0,82,47.75C54.51,79.32,40,112.6,40,144a88,88,0,0,0,176,0C216,112.6,201.49,79.32,174,47.75ZM128,216a72.08,72.08,0,0,1-72-72c0-57.23,55.47-105,72-118,16.53,13,72,60.75,72,118A72.08,72.08,0,0,1,128,216Zm55.89-62.66a57.6,57.6,0,0,1-46.56,46.55A8.75,8.75,0,0,1,136,200a8,8,0,0,1-1.32-15.89c16.57-2.79,30.63-16.85,33.44-33.45a8,8,0,0,1,15.78,2.68Z"}))],["fill",e.createElement(e.Fragment,null,e.createElement("path",{d:"M174,47.75a254.19,254.19,0,0,0-41.45-38.3,8,8,0,0,0-9.18,0A254.19,254.19,0,0,0,82,47.75C54.51,79.32,40,112.6,40,144a88,88,0,0,0,176,0C216,112.6,201.49,79.32,174,47.75Zm9.85,105.59a57.6,57.6,0,0,1-46.56,46.55A8.75,8.75,0,0,1,136,200a8,8,0,0,1-1.32-15.89c16.57-2.79,30.63-16.85,33.44-33.45a8,8,0,0,1,15.78,2.68Z"}))],["light",e.createElement(e.Fragment,null,e.createElement("path",{d:"M172.53,49.06a252.86,252.86,0,0,0-41.09-38,6,6,0,0,0-6.88,0,252.86,252.86,0,0,0-41.09,38C56.34,80.26,42,113.09,42,144a86,86,0,0,0,172,0C214,113.09,199.66,80.26,172.53,49.06ZM128,218a74.09,74.09,0,0,1-74-74c0-59.62,59-108.93,74-120.51C143,35.07,202,84.38,202,144A74.09,74.09,0,0,1,128,218Zm53.92-65A55.58,55.58,0,0,1,137,197.92a7,7,0,0,1-1,.08,6,6,0,0,1-1-11.92c17.38-2.92,32.13-17.68,35.08-35.08a6,6,0,1,1,11.84,2Z"}))],["regular",e.createElement(e.Fragment,null,e.createElement("path",{d:"M174,47.75a254.19,254.19,0,0,0-41.45-38.3,8,8,0,0,0-9.18,0A254.19,254.19,0,0,0,82,47.75C54.51,79.32,40,112.6,40,144a88,88,0,0,0,176,0C216,112.6,201.49,79.32,174,47.75ZM128,216a72.08,72.08,0,0,1-72-72c0-57.23,55.47-105,72-118,16.53,13,72,60.75,72,118A72.08,72.08,0,0,1,128,216Zm55.89-62.66a57.6,57.6,0,0,1-46.56,46.55A8.75,8.75,0,0,1,136,200a8,8,0,0,1-1.32-15.89c16.57-2.79,30.63-16.85,33.44-33.45a8,8,0,0,1,15.78,2.68Z"}))],["thin",e.createElement(e.Fragment,null,e.createElement("path",{d:"M171,50.38a250,250,0,0,0-40.73-37.66,4,4,0,0,0-4.58,0A250,250,0,0,0,85,50.38C58.17,81.21,44,113.58,44,144a84,84,0,0,0,168,0C212,113.58,197.83,81.21,171,50.38ZM128,220a76.08,76.08,0,0,1-76-76c0-35.9,21.15-67.8,38.9-88.24A255,255,0,0,1,128,21a255,255,0,0,1,37.1,34.8C182.85,76.2,204,108.1,204,144A76.08,76.08,0,0,1,128,220Zm51.94-67.33a53.51,53.51,0,0,1-43.28,43.27,3.68,3.68,0,0,1-.66.06,4,4,0,0,1-.66-7.94c18.18-3.06,33.63-18.51,36.72-36.73a4,4,0,0,1,7.88,1.34Z"}))]]),$0=new Map([["bold",e.createElement(e.Fragment,null,e.createElement("path",{d:"M220,112v96a20,20,0,0,1-20,20H56a20,20,0,0,1-20-20V112A20,20,0,0,1,56,92H76a12,12,0,0,1,0,24H60v88H196V116H180a12,12,0,0,1,0-24h20A20,20,0,0,1,220,112ZM96.49,72.49,116,53v83a12,12,0,0,0,24,0V53l19.51,19.52a12,12,0,1,0,17-17l-40-40a12,12,0,0,0-17,0l-40,40a12,12,0,1,0,17,17Z"}))],["duotone",e.createElement(e.Fragment,null,e.createElement("path",{d:"M208,104V216H48V104Z",opacity:"0.2"}),e.createElement("path",{d:"M216,112v96a16,16,0,0,1-16,16H56a16,16,0,0,1-16-16V112A16,16,0,0,1,56,96H80a8,8,0,0,1,0,16H56v96H200V112H176a8,8,0,0,1,0-16h24A16,16,0,0,1,216,112ZM93.66,69.66,120,43.31V136a8,8,0,0,0,16,0V43.31l26.34,26.35a8,8,0,0,0,11.32-11.32l-40-40a8,8,0,0,0-11.32,0l-40,40A8,8,0,0,0,93.66,69.66Z"}))],["fill",e.createElement(e.Fragment,null,e.createElement("path",{d:"M216,112v96a16,16,0,0,1-16,16H56a16,16,0,0,1-16-16V112A16,16,0,0,1,56,96h64v48a8,8,0,0,0,16,0V96h64A16,16,0,0,1,216,112ZM136,43.31l26.34,26.35a8,8,0,0,0,11.32-11.32l-40-40a8,8,0,0,0-11.32,0l-40,40A8,8,0,0,0,93.66,69.66L120,43.31V96h16Z"}))],["light",e.createElement(e.Fragment,null,e.createElement("path",{d:"M214,112v96a14,14,0,0,1-14,14H56a14,14,0,0,1-14-14V112A14,14,0,0,1,56,98H80a6,6,0,0,1,0,12H56a2,2,0,0,0-2,2v96a2,2,0,0,0,2,2H200a2,2,0,0,0,2-2V112a2,2,0,0,0-2-2H176a6,6,0,0,1,0-12h24A14,14,0,0,1,214,112ZM92.24,68.24,122,38.49V136a6,6,0,0,0,12,0V38.49l29.76,29.75a6,6,0,1,0,8.48-8.48l-40-40a6,6,0,0,0-8.48,0l-40,40a6,6,0,1,0,8.48,8.48Z"}))],["regular",e.createElement(e.Fragment,null,e.createElement("path",{d:"M216,112v96a16,16,0,0,1-16,16H56a16,16,0,0,1-16-16V112A16,16,0,0,1,56,96H80a8,8,0,0,1,0,16H56v96H200V112H176a8,8,0,0,1,0-16h24A16,16,0,0,1,216,112ZM93.66,69.66,120,43.31V136a8,8,0,0,0,16,0V43.31l26.34,26.35a8,8,0,0,0,11.32-11.32l-40-40a8,8,0,0,0-11.32,0l-40,40A8,8,0,0,0,93.66,69.66Z"}))],["thin",e.createElement(e.Fragment,null,e.createElement("path",{d:"M212,112v96a12,12,0,0,1-12,12H56a12,12,0,0,1-12-12V112a12,12,0,0,1,12-12H80a4,4,0,0,1,0,8H56a4,4,0,0,0-4,4v96a4,4,0,0,0,4,4H200a4,4,0,0,0,4-4V112a4,4,0,0,0-4-4H176a4,4,0,0,1,0-8h24A12,12,0,0,1,212,112ZM90.83,66.83,124,33.66V136a4,4,0,0,0,8,0V33.66l33.17,33.17a4,4,0,1,0,5.66-5.66l-40-40a4,4,0,0,0-5.66,0l-40,40a4,4,0,0,0,5.66,5.66Z"}))]]),C0=new Map([["bold",e.createElement(e.Fragment,null,e.createElement("path",{d:"M180.49,143.51a12,12,0,0,1,0,17l-24,24a12,12,0,0,1-17-17L155,152l-15.52-15.51a12,12,0,1,1,17-17Zm-64-24a12,12,0,0,0-17,0l-24,24a12,12,0,0,0,0,17l24,24a12,12,0,0,0,17-17L101,152l15.52-15.51A12,12,0,0,0,116.49,119.51ZM220,88V216a20,20,0,0,1-20,20H56a20,20,0,0,1-20-20V40A20,20,0,0,1,56,20h96a12,12,0,0,1,8.49,3.52l56,56A12,12,0,0,1,220,88ZM160,57V80h23Zm36,155V104H148a12,12,0,0,1-12-12V44H60V212Z"}))],["duotone",e.createElement(e.Fragment,null,e.createElement("path",{d:"M208,88H152V32Z",opacity:"0.2"}),e.createElement("path",{d:"M181.66,146.34a8,8,0,0,1,0,11.32l-24,24a8,8,0,0,1-11.32-11.32L164.69,152l-18.35-18.34a8,8,0,0,1,11.32-11.32Zm-72-24a8,8,0,0,0-11.32,0l-24,24a8,8,0,0,0,0,11.32l24,24a8,8,0,0,0,11.32-11.32L91.31,152l18.35-18.34A8,8,0,0,0,109.66,122.34ZM216,88V216a16,16,0,0,1-16,16H56a16,16,0,0,1-16-16V40A16,16,0,0,1,56,24h96a8,8,0,0,1,5.66,2.34l56,56A8,8,0,0,1,216,88Zm-56-8h28.69L160,51.31Zm40,136V96H152a8,8,0,0,1-8-8V40H56V216H200Z"}))],["fill",e.createElement(e.Fragment,null,e.createElement("path",{d:"M213.66,82.34l-56-56A8,8,0,0,0,152,24H56A16,16,0,0,0,40,40V216a16,16,0,0,0,16,16H200a16,16,0,0,0,16-16V88A8,8,0,0,0,213.66,82.34Zm-104,88a8,8,0,0,1-11.32,11.32l-24-24a8,8,0,0,1,0-11.32l24-24a8,8,0,0,1,11.32,11.32L91.31,152Zm72-12.68-24,24a8,8,0,0,1-11.32-11.32L164.69,152l-18.35-18.34a8,8,0,0,1,11.32-11.32l24,24A8,8,0,0,1,181.66,157.66ZM152,88V44l44,44Z"}))],["light",e.createElement(e.Fragment,null,e.createElement("path",{d:"M180.24,147.76a6,6,0,0,1,0,8.48l-24,24a6,6,0,0,1-8.48-8.48L167.51,152l-19.75-19.76a6,6,0,1,1,8.48-8.48Zm-72-24a6,6,0,0,0-8.48,0l-24,24a6,6,0,0,0,0,8.48l24,24a6,6,0,1,0,8.48-8.48L88.49,152l19.75-19.76A6,6,0,0,0,108.24,123.76ZM214,88V216a14,14,0,0,1-14,14H56a14,14,0,0,1-14-14V40A14,14,0,0,1,56,26h96a6,6,0,0,1,4.25,1.76l56,56A6,6,0,0,1,214,88Zm-56-6h35.52L158,46.48Zm44,134V94H152a6,6,0,0,1-6-6V38H56a2,2,0,0,0-2,2V216a2,2,0,0,0,2,2H200A2,2,0,0,0,202,216Z"}))],["regular",e.createElement(e.Fragment,null,e.createElement("path",{d:"M181.66,146.34a8,8,0,0,1,0,11.32l-24,24a8,8,0,0,1-11.32-11.32L164.69,152l-18.35-18.34a8,8,0,0,1,11.32-11.32Zm-72-24a8,8,0,0,0-11.32,0l-24,24a8,8,0,0,0,0,11.32l24,24a8,8,0,0,0,11.32-11.32L91.31,152l18.35-18.34A8,8,0,0,0,109.66,122.34ZM216,88V216a16,16,0,0,1-16,16H56a16,16,0,0,1-16-16V40A16,16,0,0,1,56,24h96a8,8,0,0,1,5.66,2.34l56,56A8,8,0,0,1,216,88Zm-56-8h28.69L160,51.31Zm40,136V96H152a8,8,0,0,1-8-8V40H56V216H200Z"}))],["thin",e.createElement(e.Fragment,null,e.createElement("path",{d:"M178.83,149.17a4,4,0,0,1,0,5.66l-24,24a4,4,0,0,1-5.66-5.66L170.34,152l-21.17-21.17a4,4,0,1,1,5.66-5.66Zm-72-24a4,4,0,0,0-5.66,0l-24,24a4,4,0,0,0,0,5.66l24,24a4,4,0,1,0,5.66-5.66L85.66,152l21.17-21.17A4,4,0,0,0,106.83,125.17ZM212,88V216a12,12,0,0,1-12,12H56a12,12,0,0,1-12-12V40A12,12,0,0,1,56,28h96a4,4,0,0,1,2.83,1.17l56,56A4,4,0,0,1,212,88Zm-56-4h42.34L156,41.65Zm48,132V92H152a4,4,0,0,1-4-4V36H56a4,4,0,0,0-4,4V216a4,4,0,0,0,4,4H200A4,4,0,0,0,204,216Z"}))]]),k0=new Map([["bold",e.createElement(e.Fragment,null,e.createElement("path",{d:"M203.57,51A107.9,107.9,0,0,0,20,128c0,44.72,27.6,82.25,72,97.94A36,36,0,0,0,140,192a12,12,0,0,1,12-12h46.21a35.79,35.79,0,0,0,35.1-28A108.6,108.6,0,0,0,236,127.09,107.23,107.23,0,0,0,203.57,51Zm6.34,95.67a11.91,11.91,0,0,1-11.7,9.3H152a36,36,0,0,0-36,36,12,12,0,0,1-16,11.3c-16.65-5.88-30.65-15.76-40.48-28.56A76,76,0,0,1,44,128a84,84,0,0,1,83.13-84H128a84.35,84.35,0,0,1,84,83.29A84.72,84.72,0,0,1,209.91,146.71ZM144,76a16,16,0,1,1-16-16A16,16,0,0,1,144,76Zm-44,24A16,16,0,1,1,84,84,16,16,0,0,1,100,100Zm0,56a16,16,0,1,1-16-16A16,16,0,0,1,100,156Zm88-56a16,16,0,1,1-16-16A16,16,0,0,1,188,100Z"}))],["duotone",e.createElement(e.Fragment,null,e.createElement("path",{d:"M224,127.17a96.48,96.48,0,0,1-2.39,22.18A24,24,0,0,1,198.21,168H152a24,24,0,0,0-24,24,24,24,0,0,1-32,22.61C58.73,201.44,32,169.81,32,128a96,96,0,0,1,95-96C179.84,31.47,223.55,74.35,224,127.17Z",opacity:"0.2"}),e.createElement("path",{d:"M200.77,53.89A103.27,103.27,0,0,0,128,24h-1.07A104,104,0,0,0,24,128c0,43,26.58,79.06,69.36,94.17A32,32,0,0,0,136,192a16,16,0,0,1,16-16h46.21a31.81,31.81,0,0,0,31.2-24.88,104.43,104.43,0,0,0,2.59-24A103.28,103.28,0,0,0,200.77,53.89Zm13,93.71A15.89,15.89,0,0,1,198.21,160H152a32,32,0,0,0-32,32,16,16,0,0,1-21.31,15.07C62.49,194.3,40,164,40,128a88,88,0,0,1,87.09-88h.9a88.35,88.35,0,0,1,88,87.25A88.86,88.86,0,0,1,213.81,147.6ZM140,76a12,12,0,1,1-12-12A12,12,0,0,1,140,76ZM96,100A12,12,0,1,1,84,88,12,12,0,0,1,96,100Zm0,56a12,12,0,1,1-12-12A12,12,0,0,1,96,156Zm88-56a12,12,0,1,1-12-12A12,12,0,0,1,184,100Z"}))],["fill",e.createElement(e.Fragment,null,e.createElement("path",{d:"M200.77,53.89A103.27,103.27,0,0,0,128,24h-1.07A104,104,0,0,0,24,128c0,43,26.58,79.06,69.36,94.17A32,32,0,0,0,136,192a16,16,0,0,1,16-16h46.21a31.81,31.81,0,0,0,31.2-24.88,104.43,104.43,0,0,0,2.59-24A103.28,103.28,0,0,0,200.77,53.89ZM84,168a12,12,0,1,1,12-12A12,12,0,0,1,84,168Zm0-56a12,12,0,1,1,12-12A12,12,0,0,1,84,112Zm44-24a12,12,0,1,1,12-12A12,12,0,0,1,128,88Zm44,24a12,12,0,1,1,12-12A12,12,0,0,1,172,112Z"}))],["light",e.createElement(e.Fragment,null,e.createElement("path",{d:"M199.37,55.31A101.32,101.32,0,0,0,128,26h-1A102,102,0,0,0,26,128c0,42.09,26.07,77.44,68,92.26A30.21,30.21,0,0,0,104.11,222,30.06,30.06,0,0,0,134,192a18,18,0,0,1,18-18h46.21a29.82,29.82,0,0,0,29.25-23.31A102.71,102.71,0,0,0,230,127.11,101.25,101.25,0,0,0,199.37,55.31ZM215.76,148a17.89,17.89,0,0,1-17.55,14H152a30,30,0,0,0-30,30,18,18,0,0,1-24,17C61,195.86,38,164.85,38,128a90,90,0,0,1,89.07-90H128a90.34,90.34,0,0,1,90,89.22A90.46,90.46,0,0,1,215.76,148ZM138,76a10,10,0,1,1-10-10A10,10,0,0,1,138,76ZM94,100A10,10,0,1,1,84,90,10,10,0,0,1,94,100Zm0,56a10,10,0,1,1-10-10A10,10,0,0,1,94,156Zm88-56a10,10,0,1,1-10-10A10,10,0,0,1,182,100Z"}))],["regular",e.createElement(e.Fragment,null,e.createElement("path",{d:"M200.77,53.89A103.27,103.27,0,0,0,128,24h-1.07A104,104,0,0,0,24,128c0,43,26.58,79.06,69.36,94.17A32,32,0,0,0,136,192a16,16,0,0,1,16-16h46.21a31.81,31.81,0,0,0,31.2-24.88,104.43,104.43,0,0,0,2.59-24A103.28,103.28,0,0,0,200.77,53.89Zm13,93.71A15.89,15.89,0,0,1,198.21,160H152a32,32,0,0,0-32,32,16,16,0,0,1-21.31,15.07C62.49,194.3,40,164,40,128a88,88,0,0,1,87.09-88h.9a88.35,88.35,0,0,1,88,87.25A88.86,88.86,0,0,1,213.81,147.6ZM140,76a12,12,0,1,1-12-12A12,12,0,0,1,140,76ZM96,100A12,12,0,1,1,84,88,12,12,0,0,1,96,100Zm0,56a12,12,0,1,1-12-12A12,12,0,0,1,96,156Zm88-56a12,12,0,1,1-12-12A12,12,0,0,1,184,100Z"}))],["thin",e.createElement(e.Fragment,null,e.createElement("path",{d:"M198,56.74A99.31,99.31,0,0,0,128,28h-1A100,100,0,0,0,28,128c0,41.22,25.55,75.85,66.69,90.38a28.34,28.34,0,0,0,9.42,1.63A28,28,0,0,0,132,192a20,20,0,0,1,20-20h46.21a27.84,27.84,0,0,0,27.3-21.76,100.37,100.37,0,0,0,2.49-23.1A99.26,99.26,0,0,0,198,56.74Zm19.74,91.72A19.89,19.89,0,0,1,198.21,164H152a28,28,0,0,0-28,28,20,20,0,0,1-26.64,18.83C59.51,197.46,36,165.72,36,128a92,92,0,0,1,91.05-92H128a92,92,0,0,1,89.72,112.46ZM136,76a8,8,0,1,1-8-8A8,8,0,0,1,136,76ZM92,100a8,8,0,1,1-8-8A8,8,0,0,1,92,100Zm0,56a8,8,0,1,1-8-8A8,8,0,0,1,92,156Zm88-56a8,8,0,1,1-8-8A8,8,0,0,1,180,100Z"}))]]),R0=new Map([["bold",e.createElement(e.Fragment,null,e.createElement("path",{d:"M234.49,111.07,90.41,22.94A20,20,0,0,0,60,39.87V216.13a20,20,0,0,0,30.41,16.93l144.08-88.13a19.82,19.82,0,0,0,0-33.86ZM84,208.85V47.15L216.16,128Z"}))],["duotone",e.createElement(e.Fragment,null,e.createElement("path",{d:"M228.23,134.69,84.15,222.81A8,8,0,0,1,72,216.12V39.88a8,8,0,0,1,12.15-6.69l144.08,88.12A7.82,7.82,0,0,1,228.23,134.69Z",opacity:"0.2"}),e.createElement("path",{d:"M232.4,114.49,88.32,26.35a16,16,0,0,0-16.2-.3A15.86,15.86,0,0,0,64,39.87V216.13A15.94,15.94,0,0,0,80,232a16.07,16.07,0,0,0,8.36-2.35L232.4,141.51a15.81,15.81,0,0,0,0-27ZM80,215.94V40l143.83,88Z"}))],["fill",e.createElement(e.Fragment,null,e.createElement("path",{d:"M240,128a15.74,15.74,0,0,1-7.6,13.51L88.32,229.65a16,16,0,0,1-16.2.3A15.86,15.86,0,0,1,64,216.13V39.87a15.86,15.86,0,0,1,8.12-13.82,16,16,0,0,1,16.2.3L232.4,114.49A15.74,15.74,0,0,1,240,128Z"}))],["light",e.createElement(e.Fragment,null,e.createElement("path",{d:"M231.36,116.19,87.28,28.06a14,14,0,0,0-14.18-.27A13.69,13.69,0,0,0,66,39.87V216.13a13.69,13.69,0,0,0,7.1,12.08,14,14,0,0,0,14.18-.27l144.08-88.13a13.82,13.82,0,0,0,0-23.62Zm-6.26,13.38L81,217.7a2,2,0,0,1-2.06,0,1.78,1.78,0,0,1-1-1.61V39.87a1.78,1.78,0,0,1,1-1.61A2.06,2.06,0,0,1,80,38a2,2,0,0,1,1,.31L225.1,126.43a1.82,1.82,0,0,1,0,3.14Z"}))],["regular",e.createElement(e.Fragment,null,e.createElement("path",{d:"M232.4,114.49,88.32,26.35a16,16,0,0,0-16.2-.3A15.86,15.86,0,0,0,64,39.87V216.13A15.94,15.94,0,0,0,80,232a16.07,16.07,0,0,0,8.36-2.35L232.4,141.51a15.81,15.81,0,0,0,0-27ZM80,215.94V40l143.83,88Z"}))],["thin",e.createElement(e.Fragment,null,e.createElement("path",{d:"M230.32,117.9,86.24,29.79a11.91,11.91,0,0,0-12.17-.23A11.71,11.71,0,0,0,68,39.89V216.11a11.71,11.71,0,0,0,6.07,10.33,11.91,11.91,0,0,0,12.17-.23L230.32,138.1a11.82,11.82,0,0,0,0-20.2Zm-4.18,13.37L82.06,219.39a4,4,0,0,1-4.07.07,3.77,3.77,0,0,1-2-3.35V39.89a3.77,3.77,0,0,1,2-3.35,4,4,0,0,1,4.07.07l144.08,88.12a3.8,3.8,0,0,1,0,6.54Z"}))]]),z0=new Map([["bold",e.createElement(e.Fragment,null,e.createElement("path",{d:"M199,125.31l-49.88-18.39L130.69,57a19.92,19.92,0,0,0-37.38,0L74.92,106.92,25,125.31a19.92,19.92,0,0,0,0,37.38l49.88,18.39L93.31,231a19.92,19.92,0,0,0,37.38,0l18.39-49.88L199,162.69a19.92,19.92,0,0,0,0-37.38Zm-63.38,35.16a12,12,0,0,0-7.11,7.11L112,212.28l-16.47-44.7a12,12,0,0,0-7.11-7.11L43.72,144l44.7-16.47a12,12,0,0,0,7.11-7.11L112,75.72l16.47,44.7a12,12,0,0,0,7.11,7.11L180.28,144ZM140,40a12,12,0,0,1,12-12h12V16a12,12,0,0,1,24,0V28h12a12,12,0,0,1,0,24H188V64a12,12,0,0,1-24,0V52H152A12,12,0,0,1,140,40ZM252,88a12,12,0,0,1-12,12h-4v4a12,12,0,0,1-24,0v-4h-4a12,12,0,0,1,0-24h4V72a12,12,0,0,1,24,0v4h4A12,12,0,0,1,252,88Z"}))],["duotone",e.createElement(e.Fragment,null,e.createElement("path",{d:"M194.82,151.43l-55.09,20.3-20.3,55.09a7.92,7.92,0,0,1-14.86,0l-20.3-55.09-55.09-20.3a7.92,7.92,0,0,1,0-14.86l55.09-20.3,20.3-55.09a7.92,7.92,0,0,1,14.86,0l20.3,55.09,55.09,20.3A7.92,7.92,0,0,1,194.82,151.43Z",opacity:"0.2"}),e.createElement("path",{d:"M197.58,129.06,146,110l-19-51.62a15.92,15.92,0,0,0-29.88,0L78,110l-51.62,19a15.92,15.92,0,0,0,0,29.88L78,178l19,51.62a15.92,15.92,0,0,0,29.88,0L146,178l51.62-19a15.92,15.92,0,0,0,0-29.88ZM137,164.22a8,8,0,0,0-4.74,4.74L112,223.85,91.78,169A8,8,0,0,0,87,164.22L32.15,144,87,123.78A8,8,0,0,0,91.78,119L112,64.15,132.22,119a8,8,0,0,0,4.74,4.74L191.85,144ZM144,40a8,8,0,0,1,8-8h16V16a8,8,0,0,1,16,0V32h16a8,8,0,0,1,0,16H184V64a8,8,0,0,1-16,0V48H152A8,8,0,0,1,144,40ZM248,88a8,8,0,0,1-8,8h-8v8a8,8,0,0,1-16,0V96h-8a8,8,0,0,1,0-16h8V72a8,8,0,0,1,16,0v8h8A8,8,0,0,1,248,88Z"}))],["fill",e.createElement(e.Fragment,null,e.createElement("path",{d:"M208,144a15.78,15.78,0,0,1-10.42,14.94L146,178l-19,51.62a15.92,15.92,0,0,1-29.88,0L78,178l-51.62-19a15.92,15.92,0,0,1,0-29.88L78,110l19-51.62a15.92,15.92,0,0,1,29.88,0L146,110l51.62,19A15.78,15.78,0,0,1,208,144ZM152,48h16V64a8,8,0,0,0,16,0V48h16a8,8,0,0,0,0-16H184V16a8,8,0,0,0-16,0V32H152a8,8,0,0,0,0,16Zm88,32h-8V72a8,8,0,0,0-16,0v8h-8a8,8,0,0,0,0,16h8v8a8,8,0,0,0,16,0V96h8a8,8,0,0,0,0-16Z"}))],["light",e.createElement(e.Fragment,null,e.createElement("path",{d:"M196.89,130.94,144.4,111.6,125.06,59.11a13.92,13.92,0,0,0-26.12,0L79.6,111.6,27.11,130.94a13.92,13.92,0,0,0,0,26.12L79.6,176.4l19.34,52.49a13.92,13.92,0,0,0,26.12,0L144.4,176.4l52.49-19.34a13.92,13.92,0,0,0,0-26.12Zm-4.15,14.86-55.08,20.3a6,6,0,0,0-3.56,3.56l-20.3,55.08a1.92,1.92,0,0,1-3.6,0L89.9,169.66a6,6,0,0,0-3.56-3.56L31.26,145.8a1.92,1.92,0,0,1,0-3.6l55.08-20.3a6,6,0,0,0,3.56-3.56l20.3-55.08a1.92,1.92,0,0,1,3.6,0l20.3,55.08a6,6,0,0,0,3.56,3.56l55.08,20.3a1.92,1.92,0,0,1,0,3.6ZM146,40a6,6,0,0,1,6-6h18V16a6,6,0,0,1,12,0V34h18a6,6,0,0,1,0,12H182V64a6,6,0,0,1-12,0V46H152A6,6,0,0,1,146,40ZM246,88a6,6,0,0,1-6,6H230v10a6,6,0,0,1-12,0V94H208a6,6,0,0,1,0-12h10V72a6,6,0,0,1,12,0V82h10A6,6,0,0,1,246,88Z"}))],["regular",e.createElement(e.Fragment,null,e.createElement("path",{d:"M197.58,129.06,146,110l-19-51.62a15.92,15.92,0,0,0-29.88,0L78,110l-51.62,19a15.92,15.92,0,0,0,0,29.88L78,178l19,51.62a15.92,15.92,0,0,0,29.88,0L146,178l51.62-19a15.92,15.92,0,0,0,0-29.88ZM137,164.22a8,8,0,0,0-4.74,4.74L112,223.85,91.78,169A8,8,0,0,0,87,164.22L32.15,144,87,123.78A8,8,0,0,0,91.78,119L112,64.15,132.22,119a8,8,0,0,0,4.74,4.74L191.85,144ZM144,40a8,8,0,0,1,8-8h16V16a8,8,0,0,1,16,0V32h16a8,8,0,0,1,0,16H184V64a8,8,0,0,1-16,0V48H152A8,8,0,0,1,144,40ZM248,88a8,8,0,0,1-8,8h-8v8a8,8,0,0,1-16,0V96h-8a8,8,0,0,1,0-16h8V72a8,8,0,0,1,16,0v8h8A8,8,0,0,1,248,88Z"}))],["thin",e.createElement(e.Fragment,null,e.createElement("path",{d:"M196.2,132.81l-53.36-19.65L123.19,59.8a11.93,11.93,0,0,0-22.38,0L81.16,113.16,27.8,132.81a11.93,11.93,0,0,0,0,22.38l53.36,19.65,19.65,53.36a11.93,11.93,0,0,0,22.38,0l19.65-53.36,53.36-19.65a11.93,11.93,0,0,0,0-22.38Zm-2.77,14.87L138.35,168a4,4,0,0,0-2.37,2.37l-20.3,55.08a3.92,3.92,0,0,1-7.36,0L88,170.35A4,4,0,0,0,85.65,168l-55.08-20.3a3.92,3.92,0,0,1,0-7.36L85.65,120A4,4,0,0,0,88,117.65l20.3-55.08a3.92,3.92,0,0,1,7.36,0L136,117.65a4,4,0,0,0,2.37,2.37l55.08,20.3a3.92,3.92,0,0,1,0,7.36ZM148,40a4,4,0,0,1,4-4h20V16a4,4,0,0,1,8,0V36h20a4,4,0,0,1,0,8H180V64a4,4,0,0,1-8,0V44H152A4,4,0,0,1,148,40Zm96,48a4,4,0,0,1-4,4H228v12a4,4,0,0,1-8,0V92H208a4,4,0,0,1,0-8h12V72a4,4,0,0,1,8,0V84h12A4,4,0,0,1,244,88Z"}))]]),T0=new Map([["bold",e.createElement(e.Fragment,null,e.createElement("path",{d:"M212,56V88a12,12,0,0,1-24,0V68H140V188h20a12,12,0,0,1,0,24H96a12,12,0,0,1,0-24h20V68H68V88a12,12,0,0,1-24,0V56A12,12,0,0,1,56,44H200A12,12,0,0,1,212,56Z"}))],["duotone",e.createElement(e.Fragment,null,e.createElement("path",{d:"M200,56V184a16,16,0,0,1-16,16H72a16,16,0,0,1-16-16V56Z",opacity:"0.2"}),e.createElement("path",{d:"M208,56V88a8,8,0,0,1-16,0V64H136V192h24a8,8,0,0,1,0,16H96a8,8,0,0,1,0-16h24V64H64V88a8,8,0,0,1-16,0V56a8,8,0,0,1,8-8H200A8,8,0,0,1,208,56Z"}))],["fill",e.createElement(e.Fragment,null,e.createElement("path",{d:"M208,32H48A16,16,0,0,0,32,48V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V48A16,16,0,0,0,208,32ZM184,96a8,8,0,0,1-16,0V88H136v88h12a8,8,0,0,1,0,16H108a8,8,0,0,1,0-16h12V88H88v8a8,8,0,0,1-16,0V80a8,8,0,0,1,8-8h96a8,8,0,0,1,8,8Z"}))],["light",e.createElement(e.Fragment,null,e.createElement("path",{d:"M206,56V88a6,6,0,0,1-12,0V62H134V194h26a6,6,0,0,1,0,12H96a6,6,0,0,1,0-12h26V62H62V88a6,6,0,0,1-12,0V56a6,6,0,0,1,6-6H200A6,6,0,0,1,206,56Z"}))],["regular",e.createElement(e.Fragment,null,e.createElement("path",{d:"M208,56V88a8,8,0,0,1-16,0V64H136V192h24a8,8,0,0,1,0,16H96a8,8,0,0,1,0-16h24V64H64V88a8,8,0,0,1-16,0V56a8,8,0,0,1,8-8H200A8,8,0,0,1,208,56Z"}))],["thin",e.createElement(e.Fragment,null,e.createElement("path",{d:"M204,56V88a4,4,0,0,1-8,0V60H132V196h28a4,4,0,0,1,0,8H96a4,4,0,0,1,0-8h28V60H60V88a4,4,0,0,1-8,0V56a4,4,0,0,1,4-4H200A4,4,0,0,1,204,56Z"}))]]),I0=new Map([["bold",e.createElement(e.Fragment,null,e.createElement("path",{d:"M216,48H180V36A28,28,0,0,0,152,8H104A28,28,0,0,0,76,36V48H40a12,12,0,0,0,0,24h4V208a20,20,0,0,0,20,20H192a20,20,0,0,0,20-20V72h4a12,12,0,0,0,0-24ZM100,36a4,4,0,0,1,4-4h48a4,4,0,0,1,4,4V48H100Zm88,168H68V72H188ZM116,104v64a12,12,0,0,1-24,0V104a12,12,0,0,1,24,0Zm48,0v64a12,12,0,0,1-24,0V104a12,12,0,0,1,24,0Z"}))],["duotone",e.createElement(e.Fragment,null,e.createElement("path",{d:"M200,56V208a8,8,0,0,1-8,8H64a8,8,0,0,1-8-8V56Z",opacity:"0.2"}),e.createElement("path",{d:"M216,48H176V40a24,24,0,0,0-24-24H104A24,24,0,0,0,80,40v8H40a8,8,0,0,0,0,16h8V208a16,16,0,0,0,16,16H192a16,16,0,0,0,16-16V64h8a8,8,0,0,0,0-16ZM96,40a8,8,0,0,1,8-8h48a8,8,0,0,1,8,8v8H96Zm96,168H64V64H192ZM112,104v64a8,8,0,0,1-16,0V104a8,8,0,0,1,16,0Zm48,0v64a8,8,0,0,1-16,0V104a8,8,0,0,1,16,0Z"}))],["fill",e.createElement(e.Fragment,null,e.createElement("path",{d:"M216,48H176V40a24,24,0,0,0-24-24H104A24,24,0,0,0,80,40v8H40a8,8,0,0,0,0,16h8V208a16,16,0,0,0,16,16H192a16,16,0,0,0,16-16V64h8a8,8,0,0,0,0-16ZM112,168a8,8,0,0,1-16,0V104a8,8,0,0,1,16,0Zm48,0a8,8,0,0,1-16,0V104a8,8,0,0,1,16,0Zm0-120H96V40a8,8,0,0,1,8-8h48a8,8,0,0,1,8,8Z"}))],["light",e.createElement(e.Fragment,null,e.createElement("path",{d:"M216,50H174V40a22,22,0,0,0-22-22H104A22,22,0,0,0,82,40V50H40a6,6,0,0,0,0,12H50V208a14,14,0,0,0,14,14H192a14,14,0,0,0,14-14V62h10a6,6,0,0,0,0-12ZM94,40a10,10,0,0,1,10-10h48a10,10,0,0,1,10,10V50H94ZM194,208a2,2,0,0,1-2,2H64a2,2,0,0,1-2-2V62H194ZM110,104v64a6,6,0,0,1-12,0V104a6,6,0,0,1,12,0Zm48,0v64a6,6,0,0,1-12,0V104a6,6,0,0,1,12,0Z"}))],["regular",e.createElement(e.Fragment,null,e.createElement("path",{d:"M216,48H176V40a24,24,0,0,0-24-24H104A24,24,0,0,0,80,40v8H40a8,8,0,0,0,0,16h8V208a16,16,0,0,0,16,16H192a16,16,0,0,0,16-16V64h8a8,8,0,0,0,0-16ZM96,40a8,8,0,0,1,8-8h48a8,8,0,0,1,8,8v8H96Zm96,168H64V64H192ZM112,104v64a8,8,0,0,1-16,0V104a8,8,0,0,1,16,0Zm48,0v64a8,8,0,0,1-16,0V104a8,8,0,0,1,16,0Z"}))],["thin",e.createElement(e.Fragment,null,e.createElement("path",{d:"M216,52H172V40a20,20,0,0,0-20-20H104A20,20,0,0,0,84,40V52H40a4,4,0,0,0,0,8H52V208a12,12,0,0,0,12,12H192a12,12,0,0,0,12-12V60h12a4,4,0,0,0,0-8ZM92,40a12,12,0,0,1,12-12h48a12,12,0,0,1,12,12V52H92ZM196,208a4,4,0,0,1-4,4H64a4,4,0,0,1-4-4V60H196ZM108,104v64a4,4,0,0,1-8,0V104a4,4,0,0,1,8,0Zm48,0v64a4,4,0,0,1-8,0V104a4,4,0,0,1,8,0Z"}))]]),_=e.forwardRef((a,n)=>e.createElement(b,{ref:n,...a,weights:j0}));_.displayName="ArrowsOutSimpleIcon";const U=_,G=e.forwardRef((a,n)=>e.createElement(b,{ref:n,...a,weights:E0}));G.displayName="BoundingBoxIcon";const O0=G,W=e.forwardRef((a,n)=>e.createElement(b,{ref:n,...a,weights:M0}));W.displayName="CaretDownIcon";const P0=W,q=e.forwardRef((a,n)=>e.createElement(b,{ref:n,...a,weights:A0}));q.displayName="CheckIcon";const y=q,J=e.forwardRef((a,n)=>e.createElement(b,{ref:n,...a,weights:y0}));J.displayName="CircleIcon";const D0=J,Y=e.forwardRef((a,n)=>e.createElement(b,{ref:n,...a,weights:w0}));Y.displayName="CodeIcon";const B0=Y,K=e.forwardRef((a,n)=>e.createElement(b,{ref:n,...a,weights:N0}));K.displayName="CopyIcon";const S=K,X=e.forwardRef((a,n)=>e.createElement(b,{ref:n,...a,weights:S0}));X.displayName="CursorClickIcon";const _0=X,Q=e.forwardRef((a,n)=>e.createElement(b,{ref:n,...a,weights:L0}));Q.displayName="DownloadSimpleIcon";const U0=Q,e0=e.forwardRef((a,n)=>e.createElement(b,{ref:n,...a,weights:F0}));e0.displayName="DropIcon";const t0=e0,a0=e.forwardRef((a,n)=>e.createElement(b,{ref:n,...a,weights:$0}));a0.displayName="ExportIcon";const n0=a0,l0=e.forwardRef((a,n)=>e.createElement(b,{ref:n,...a,weights:C0}));l0.displayName="FileCodeIcon";const G0=l0,s0=e.forwardRef((a,n)=>e.createElement(b,{ref:n,...a,weights:k0}));s0.displayName="PaletteIcon";const N=s0,r0=e.forwardRef((a,n)=>e.createElement(b,{ref:n,...a,weights:R0}));r0.displayName="PlayIcon";const W0=r0,o0=e.forwardRef((a,n)=>e.createElement(b,{ref:n,...a,weights:z0}));o0.displayName="SparkleIcon";const q0=o0,c0=e.forwardRef((a,n)=>e.createElement(b,{ref:n,...a,weights:T0}));c0.displayName="TextTIcon";const F=c0,i0=e.forwardRef((a,n)=>e.createElement(b,{ref:n,...a,weights:I0}));i0.displayName="TrashIcon";const d0=i0,z=a=>{let n;const l=new Set,s=(x,r)=>{const d=typeof x=="function"?x(n):x;if(!Object.is(d,n)){const p=n;n=r??(typeof d!="object"||d===null)?d:Object.assign({},n,d),l.forEach(u=>u(n,p))}},c=()=>n,m={setState:s,getState:c,getInitialState:()=>h,subscribe:x=>(l.add(x),()=>l.delete(x))},h=n=a(s,c,m);return m},J0=(a=>a?z(a):z),Y0=a=>a;function K0(a,n=Y0){const l=A.useSyncExternalStore(a.subscribe,A.useCallback(()=>n(a.getState()),[a,n]),A.useCallback(()=>n(a.getInitialState()),[a,n]));return A.useDebugValue(l),l}const T=a=>{const n=J0(a),l=s=>K0(n,s);return Object.assign(l,n),l},X0=(a=>a?T(a):T),g=X0(a=>({activeMode:"inspect",inspectedElement:null,designSystem:null,scanProgress:null,colorFormat:"hex",history:[],setMode:n=>a({activeMode:n}),setInspectedElement:n=>a({inspectedElement:n}),setDesignSystem:n=>a({designSystem:n}),setScanProgress:n=>a({scanProgress:n}),setColorFormat:n=>a({colorFormat:n}),addToHistory:n=>a(l=>({history:[n,...l.history].slice(0,20)})),clearHistory:()=>a({history:[]})}));async function Z(a){await navigator.clipboard.writeText(a)}function Q0(a,n,l){const s=new Blob([a],{type:l}),c=URL.createObjectURL(s),o=document.createElement("a");o.href=c,o.download=n,o.click(),URL.revokeObjectURL(c)}function e1(a){const l=Math.min(a.length,8),s=Math.ceil(a.length/l),c=16,o=24,i=l*80+(l+1)*c,m=s*(80+o)+(s+1)*c,h=document.createElement("canvas");h.width=i,h.height=m;const x=h.getContext("2d");x.fillStyle="#0C0C0E",x.fillRect(0,0,i,m),a.forEach((u,f)=>{const j=f%l,x0=Math.floor(f/l),k=c+j*(80+c),R=c+x0*(80+o+c);x.fillStyle=u.hex,x.beginPath(),x.roundRect(k,R,80,80,8),x.fill(),x.fillStyle="#EDEDEF",x.font='11px "JetBrains Mono", monospace',x.textAlign="center",x.fillText(u.hex.toUpperCase(),k+80/2,R+80+16)});const r=h.toDataURL("image/png"),d=atob(r.split(",")[1]),p=new Uint8Array(d.length);for(let u=0;u.5?d/(2-h-x):d/(h+x);let u=0;return h===o?u=((i-m)/d+(iu.colorFormat),o=s||c,[i,m]=e.useState(!1),[h,x]=e.useState(!1),r=e.useRef(void 0),d=t1(a,o),p=async()=>{await Z(d),m(!0),r.current&&clearTimeout(r.current),r.current=setTimeout(()=>m(!1),1500)};return t.jsxs("div",{className:"relative inline-flex items-center gap-2",children:[t.jsx("button",{onClick:p,onMouseEnter:()=>x(!0),onMouseLeave:()=>x(!1),className:"rounded-full border border-panel-border transition-transform duration-200 hover:scale-[1.15] focus-visible:ring-2 focus-visible:ring-panel-accent focus-visible:ring-offset-1 focus-visible:ring-offset-panel-bg shrink-0",style:{width:n,height:n,backgroundColor:a},title:d,children:i&&t.jsx("span",{className:"flex items-center justify-center w-full h-full",children:t.jsx(y,{size:n*.45,weight:"bold",className:"text-white drop-shadow-md"})})}),h&&!i&&t.jsx("div",{className:"absolute bottom-full left-1/2 -translate-x-1/2 mb-1.5 px-2 py-1 bg-panel-bg border border-panel-border rounded text-[10px] font-mono text-panel-text whitespace-nowrap shadow-lg toast-enter z-10",children:d}),i&&t.jsx("div",{className:"absolute bottom-full left-1/2 -translate-x-1/2 mb-1.5 px-2 py-1 bg-success/90 rounded text-[10px] font-medium text-white whitespace-nowrap shadow-lg toast-enter z-10",children:"Copied!"}),l&&t.jsx("span",{className:"text-[11px] font-mono text-panel-text-dim",children:d})]})}function m0({typography:a,variant:n}){const[l,s]=e.useState(!1),c=a.fontFamily.split(",")[0].replace(/['"]/g,"").trim(),o=n!==void 0?[a.variants[n]]:a.variants,i=async()=>{await Z(a.fontFamily),s(!0),setTimeout(()=>s(!1),1500)};return t.jsxs("div",{className:"p-2.5 rounded-lg bg-panel-surface border border-panel-border",children:[t.jsx("p",{className:"text-[16px] text-panel-text mb-2 truncate",style:{fontFamily:a.fontFamily},children:"The quick brown fox jumps over"}),t.jsx("div",{className:"flex items-center gap-1.5 mb-2",children:t.jsxs("button",{onClick:i,className:"flex items-center gap-1 text-[11px] font-mono text-panel-accent hover:text-panel-accent-hover transition-colors duration-150",children:[l?t.jsx(y,{size:10,className:"text-success"}):t.jsx(S,{size:10}),c]})}),o.filter(Boolean).length>0&&t.jsx("div",{className:"flex flex-wrap gap-1.5",children:o.filter(Boolean).map((m,h)=>t.jsxs("span",{className:"text-[10px] font-mono text-panel-text-dim bg-panel-bg px-1.5 py-0.5 rounded",children:[m.fontSize," / ",m.fontWeight,m.lineHeight!=="normal"?` / ${m.lineHeight}`:""]},h))})]})}function v(a){const n=parseFloat(a);return isNaN(n)?"0":n===0?"-":String(Math.round(n))}function a1({boxModel:a,dimensions:n}){return t.jsx("div",{className:"flex items-center justify-center",children:t.jsxs("div",{className:"relative p-3 border border-dashed border-orange-500/40 rounded bg-orange-500/5 min-w-[200px]",children:[t.jsx(L,{text:"margin",position:"top-left",color:"text-orange-400/70"}),t.jsx(V,{val:v(a.margin.top),position:"top"}),t.jsx(V,{val:v(a.margin.right),position:"right"}),t.jsx(V,{val:v(a.margin.bottom),position:"bottom"}),t.jsx(V,{val:v(a.margin.left),position:"left"}),t.jsxs("div",{className:"relative p-3 border border-dashed border-blue-500/40 rounded bg-blue-500/5",children:[t.jsx(L,{text:"border",position:"top-left",color:"text-blue-400/70"}),t.jsx(V,{val:v(a.border.top),position:"top"}),t.jsx(V,{val:v(a.border.right),position:"right"}),t.jsx(V,{val:v(a.border.bottom),position:"bottom"}),t.jsx(V,{val:v(a.border.left),position:"left"}),t.jsxs("div",{className:"relative p-3 border border-dashed border-green-500/40 rounded bg-green-500/5",children:[t.jsx(L,{text:"padding",position:"top-left",color:"text-green-400/70"}),t.jsx(V,{val:v(a.padding.top),position:"top"}),t.jsx(V,{val:v(a.padding.right),position:"right"}),t.jsx(V,{val:v(a.padding.bottom),position:"bottom"}),t.jsx(V,{val:v(a.padding.left),position:"left"}),t.jsx("div",{className:"flex items-center justify-center py-2 px-4 bg-panel-accent/10 border border-panel-accent/30 rounded text-center",children:t.jsxs("span",{className:"text-[11px] font-mono text-panel-accent",children:[n.width," x ",n.height]})})]})]})]})})}function L({text:a,position:n,color:l}){const s=n==="top-left"?"top-0.5 left-1":"";return t.jsx("span",{className:`absolute ${s} text-[8px] font-mono ${l} uppercase tracking-wider`,children:a})}function V({val:a,position:n}){if(a==="-")return null;const l={top:"top-0.5 left-1/2 -translate-x-1/2",right:"right-0.5 top-1/2 -translate-y-1/2",bottom:"bottom-0.5 left-1/2 -translate-x-1/2",left:"left-0.5 top-1/2 -translate-y-1/2"};return t.jsx("span",{className:`absolute ${l[n]} text-[10px] font-mono text-panel-text-dim`,children:a})}function C({shadow:a}){const[n,l]=e.useState(!1),s=async()=>{await Z(a.value),l(!0),setTimeout(()=>l(!1),1500)};return t.jsxs("button",{onClick:s,className:"flex flex-col items-center gap-2 p-3 rounded-lg bg-panel-bg border border-panel-border hover:border-panel-accent/40 transition-all duration-200 group",children:[t.jsx("div",{className:"w-16 h-16 rounded-lg bg-panel-surface transition-transform duration-200 group-hover:scale-105",style:{boxShadow:a.value}}),t.jsxs("div",{className:"flex items-center gap-1",children:[n?t.jsx(y,{size:10,className:"text-success"}):t.jsx(S,{size:10,className:"text-panel-text-dim opacity-0 group-hover:opacity-100 transition-opacity duration-150"}),t.jsx("span",{className:`text-[9px] font-mono truncate max-w-[100px] ${n?"text-success":"text-panel-text-dim"}`,children:n?"Copied!":a.value})]})]})}function n1(a){return{html:a.replace(/&/g,"&").replace(//g,">").replace(/^(\s*)([\w-]+)(\s*:)/gm,'$1$2$3').replace(/:\s*(.+?);/g,': $1;').replace(/^([.#\w][\w\-.*#\[\]=~|^$:, ]*)\s*\{/gm,'$1 {').replace(/(".*?")/g,'$1').replace(/\b(\d+\.?\d*)(px|rem|em|%|vh|vw|s|ms)?\b/g,'$1$2')}}function p0({code:a,language:n="css"}){const[l,s]=e.useState(!1),c=async()=>{await Z(a),s(!0),setTimeout(()=>s(!1),1500)},o=a.split(` +`),{html:i}=n==="css"?n1(a):{html:""};return t.jsxs("div",{className:"relative rounded-lg bg-panel-surface border border-panel-border overflow-hidden",children:[t.jsx("button",{onClick:c,className:`absolute top-2 right-2 p-1.5 rounded-md transition-all duration-200 z-10 ${l?"bg-success/20 text-success":"bg-panel-bg/80 text-panel-text-dim hover:text-panel-text hover:bg-panel-bg"}`,title:l?"Copied!":"Copy",children:l?t.jsx(y,{size:12}):t.jsx(S,{size:12})}),t.jsx("div",{className:"max-h-[300px] overflow-y-auto p-3 pr-10",children:n==="css"?t.jsx("pre",{className:"text-[11px] leading-[1.6] font-mono whitespace-pre-wrap break-all",children:t.jsx("code",{dangerouslySetInnerHTML:{__html:i}})}):t.jsx("pre",{className:"text-[11px] leading-[1.6] font-mono whitespace-pre-wrap break-all",children:o.map((m,h)=>t.jsxs("div",{className:"flex",children:[t.jsx("span",{className:"text-panel-text-dim w-6 shrink-0 text-right mr-3 select-none",children:h+1}),t.jsx("span",{className:"text-panel-text",children:m})]},h))})})]})}function l1(a){const n=r1(a);return Object.entries(n).map(([l,s])=>` ${l}: ${s};`).join(` +`)}const s1=new Set(["all","animation","transition","-webkit-text-fill-color","-webkit-tap-highlight-color"]);function r1(a){const n={opacity:"1",visibility:"visible",display:"block",position:"static","box-shadow":"none","backdrop-filter":"none",transform:"none"},l={};for(const[s,c]of Object.entries(a))s1.has(s)||s.startsWith("-webkit-")&&!s.includes("backdrop")||c===""||c==="initial"||c==="normal"||c==="auto"||n[s]!==c&&(l[s]=c);return l}function o1(a){const n=["color","background-color","border-color","border-top-color","border-right-color","border-bottom-color","border-left-color"],l=[];for(const s of n){const c=a[s];!c||c==="transparent"||c==="rgba(0, 0, 0, 0)"||l.push({property:s,value:c,hex:H0(c),rgb:V0(c),hsl:v0(c)})}return l}function c1(a){return{fontFamily:a["font-family"]||"",fontSize:a["font-size"]||"",fontWeight:a["font-weight"]||"",lineHeight:a["line-height"]||"",letterSpacing:a["letter-spacing"]||""}}function i1(a){return{boxShadow:a["box-shadow"]||"none",opacity:a.opacity||"1",backdropFilter:a["backdrop-filter"]||"none",borderRadius:a["border-radius"]||"0px"}}function E({title:a,icon:n,defaultOpen:l=!0,children:s}){const[c,o]=e.useState(l);return t.jsxs("div",{className:"border-b border-panel-border",children:[t.jsxs("button",{onClick:()=>o(!c),className:"flex items-center gap-2 w-full px-3 py-2.5 text-left hover:bg-panel-surface transition-colors duration-150",children:[t.jsx("span",{className:"text-panel-text-dim",children:n}),t.jsx("span",{className:"text-[12px] font-medium text-panel-text flex-1",children:a}),t.jsx(P0,{size:12,className:`text-panel-text-dim transition-transform duration-300 ${c?"":"-rotate-90"}`})]}),t.jsx("div",{className:"grid transition-[grid-template-rows] duration-300 ease-out",style:{gridTemplateRows:c?"1fr":"0fr"},children:t.jsx("div",{className:"overflow-hidden",children:t.jsx("div",{className:"px-3 pb-3",children:s})})})]})}function d1(){const a=g(i=>i.inspectedElement);if(!a)return t.jsxs("div",{className:"flex flex-col items-center justify-center h-full gap-4 px-6 text-center",children:[t.jsx("div",{className:"w-16 h-16 rounded-2xl bg-panel-surface border border-panel-border flex items-center justify-center",children:t.jsx(_0,{size:28,className:"text-panel-text-dim"})}),t.jsxs("div",{children:[t.jsx("p",{className:"text-[13px] font-medium text-panel-text mb-1",children:"No element selected"}),t.jsx("p",{className:"text-[11px] text-panel-text-dim leading-relaxed",children:"Click on any element on the page to inspect its styles"})]})]});const n=o1(a.computedStyles),l=c1(a.computedStyles),s=i1(a.computedStyles),c=l1(a.computedStyles);let o=a.tagName;if(a.id&&(o+=`#${a.id}`),a.className){const i=a.className.split(/\s+/).filter(Boolean).slice(0,3);i.length&&(o+=`.${i.join(".")}`)}return t.jsxs("div",{children:[t.jsxs("div",{className:"px-3 py-2.5 border-b border-panel-border bg-panel-surface/50",children:[t.jsx("p",{className:"font-mono text-[11px] text-panel-accent truncate",children:o}),t.jsxs("p",{className:"font-mono text-[10px] text-panel-text-dim truncate mt-0.5",children:[Math.round(a.rect.width)," x ",Math.round(a.rect.height),"px"]})]}),n.length>0&&t.jsx(E,{title:"Colors",icon:t.jsx(b0,{size:14}),children:t.jsx("div",{className:"flex flex-col gap-2",children:n.map(i=>t.jsxs("div",{className:"flex items-center gap-2.5",children:[t.jsx($,{color:i.hex,size:24}),t.jsxs("div",{className:"flex-1 min-w-0",children:[t.jsx("p",{className:"text-[11px] text-panel-text-dim",children:i.property}),t.jsx("p",{className:"text-[12px] font-mono text-panel-text truncate",children:i.hex})]})]},i.property))})}),t.jsx(E,{title:"Typography",icon:t.jsx(F,{size:14}),children:t.jsx(m0,{typography:{fontFamily:l.fontFamily,variants:[{fontSize:l.fontSize,fontWeight:l.fontWeight,lineHeight:l.lineHeight,letterSpacing:l.letterSpacing}]}})}),t.jsx(E,{title:"Box Model",icon:t.jsx(O0,{size:14}),children:t.jsx(a1,{boxModel:a.boxModel,dimensions:{width:Math.round(a.rect.width),height:Math.round(a.rect.height)}})}),t.jsx(E,{title:"Effects",icon:t.jsx(q0,{size:14}),children:t.jsxs("div",{className:"flex flex-col gap-2 text-[12px]",children:[s.boxShadow!=="none"&&t.jsxs("div",{children:[t.jsx("p",{className:"text-panel-text-dim text-[11px] mb-1",children:"box-shadow"}),t.jsx(C,{shadow:{value:s.boxShadow,parsed:{x:"0",y:"0",blur:"0",spread:"0",color:""}}})]}),s.borderRadius!=="0px"&&t.jsxs("div",{className:"flex justify-between",children:[t.jsx("span",{className:"text-panel-text-dim",children:"border-radius"}),t.jsx("span",{className:"font-mono",children:s.borderRadius})]}),s.opacity!=="1"&&t.jsxs("div",{className:"flex justify-between",children:[t.jsx("span",{className:"text-panel-text-dim",children:"opacity"}),t.jsx("span",{className:"font-mono",children:s.opacity})]}),s.backdropFilter!=="none"&&t.jsxs("div",{className:"flex justify-between",children:[t.jsx("span",{className:"text-panel-text-dim",children:"backdrop-filter"}),t.jsx("span",{className:"font-mono text-[11px]",children:s.backdropFilter})]}),s.boxShadow==="none"&&s.borderRadius==="0px"&&s.opacity==="1"&&s.backdropFilter==="none"&&t.jsx("p",{className:"text-panel-text-dim text-[11px]",children:"No effects"})]})}),t.jsx(E,{title:"CSS",icon:t.jsx(B0,{size:14}),defaultOpen:!1,children:t.jsx(p0,{code:c,language:"css"})})]})}const m1=["primary","secondary","accent","neutral","background","text"],p1={primary:"Primary",secondary:"Secondary",accent:"Accent",neutral:"Neutrals",background:"Backgrounds",text:"Text"};function h1({colors:a}){const n=new Map;for(const s of a){const c=s.category;n.has(c)||n.set(c,[]),n.get(c).push(s)}for(const[,s]of n)s.sort((c,o)=>o.frequency-c.frequency);const l=m1.filter(s=>n.has(s));return a.length===0?t.jsx("p",{className:"text-[11px] text-panel-text-dim",children:"No colors found"}):t.jsx("div",{className:"flex flex-col gap-4",children:l.map(s=>t.jsxs("div",{children:[t.jsx("h4",{className:"text-[11px] font-medium text-panel-text-dim uppercase tracking-wider mb-2",children:p1[s]}),t.jsx("div",{className:"flex flex-wrap gap-2",children:n.get(s).map((c,o)=>t.jsx($,{color:c.hex,size:36},o))})]},s))})}function x1({spacings:a,baseUnit:n}){if(a.length===0)return t.jsx("p",{className:"text-[11px] text-panel-text-dim",children:"No spacing values found"});const l=Math.max(...a.map(s=>parseInt(s.value)||0),1);return t.jsx("div",{className:"flex flex-col gap-1.5",children:a.map(s=>{const c=parseInt(s.value)||0,o=Math.max(c/l*100,4),i=c===n;return t.jsxs("div",{className:`flex items-center gap-2.5 py-1 px-2 rounded-md ${i?"bg-panel-accent/10 border border-panel-accent/30":""}`,children:[t.jsx("span",{className:"text-[11px] font-mono text-panel-text w-10 shrink-0 text-right",children:s.value}),t.jsx("div",{className:"flex-1 h-6 flex items-center",children:t.jsx("div",{className:"h-5 rounded-sm transition-all duration-300",style:{width:`${o}%`,backgroundColor:`color-mix(in srgb, var(--color-panel-accent) ${Math.max(30,80-c/l*50)}%, transparent)`}})}),t.jsxs("span",{className:"text-[10px] text-panel-text-dim w-8 shrink-0 text-right",children:[s.frequency,"x"]}),i&&t.jsx("span",{className:"text-[9px] font-semibold text-panel-accent uppercase tracking-wider",children:"BASE"})]},s.value)})})}const I=[{id:"colors",label:"Colors",icon:N},{id:"fonts",label:"Fonts",icon:F},{id:"spacing",label:"Spacing",icon:U},{id:"shadows",label:"Shadows",icon:t0}];function u1(){const a=g(r=>r.scanProgress),n=g(r=>r.designSystem),l=g(r=>r.setMode),[s,c]=e.useState("colors"),o=e.useRef([]),[i,m]=e.useState({left:0,width:0});e.useEffect(()=>{const r=I.findIndex(p=>p.id===s),d=o.current[r];d&&m({left:d.offsetLeft,width:d.offsetWidth})},[s]);const h=()=>{Z0(w.SCAN_PAGE,void 0)};if(a)return t.jsx("div",{className:"flex flex-col items-center justify-center h-full gap-5 px-6",children:t.jsxs("div",{className:"w-full max-w-[220px]",children:[t.jsx("div",{className:"h-2 rounded-full bg-panel-surface overflow-hidden",children:t.jsx("div",{className:"h-full rounded-full shimmer-bar transition-[width] duration-300 ease-out",style:{width:`${a.percent}%`}})}),t.jsx("p",{className:"text-[11px] text-panel-text-dim text-center mt-2.5",children:a.phase}),t.jsxs("p",{className:"text-[10px] text-panel-text-dim text-center font-mono mt-1",children:[a.percent,"%"]})]})});if(!n)return t.jsxs("div",{className:"flex flex-col items-center justify-center h-full gap-4 px-6 text-center",children:[t.jsx("div",{className:"w-16 h-16 rounded-2xl bg-panel-surface border border-panel-border flex items-center justify-center",children:t.jsx(W0,{size:28,className:"text-panel-text-dim"})}),t.jsxs("div",{children:[t.jsx("p",{className:"text-[13px] font-medium text-panel-text mb-1",children:"Scan this page"}),t.jsx("p",{className:"text-[11px] text-panel-text-dim leading-relaxed mb-4",children:"Extract colors, fonts, spacing, and shadows from the entire page"}),t.jsx("button",{onClick:h,className:"px-4 py-2 rounded-lg bg-panel-accent text-white text-[12px] font-medium hover:bg-panel-accent-hover transition-colors duration-200 focus-visible:ring-2 focus-visible:ring-panel-accent focus-visible:ring-offset-2 focus-visible:ring-offset-panel-bg",children:"Start Scan"})]})]});const x=()=>{switch(s){case"colors":return t.jsx(h1,{colors:n.colors});case"fonts":return t.jsxs("div",{className:"flex flex-col gap-4",children:[n.typography.map(r=>t.jsx(m0,{typography:r},r.fontFamily)),n.typography.length===0&&t.jsx("p",{className:"text-[11px] text-panel-text-dim",children:"No fonts found"})]});case"spacing":return t.jsx(x1,{spacings:n.spacing,baseUnit:n.spacing[0]&&parseInt(n.spacing[0].value)||8});case"shadows":return t.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[n.shadows.map((r,d)=>t.jsx(C,{shadow:r},d)),n.shadows.length===0&&t.jsx("p",{className:"text-[11px] text-panel-text-dim col-span-2",children:"No shadows found"})]})}};return t.jsxs("div",{className:"flex flex-col h-full",children:[t.jsxs("nav",{className:"relative flex border-b border-panel-border px-3 pt-1 shrink-0",children:[t.jsx("div",{className:"absolute bottom-0 h-[2px] bg-panel-accent rounded-full transition-all duration-300 ease-out",style:{left:i.left,width:i.width}}),I.map((r,d)=>{const p=r.icon,u=s===r.id;return t.jsxs("button",{ref:f=>{o.current[d]=f},onClick:()=>c(r.id),className:`flex items-center gap-1 px-2.5 pb-2 pt-1 text-[11px] font-medium transition-colors duration-200 ${u?"text-panel-text":"text-panel-text-dim hover:text-panel-text"}`,children:[t.jsx(p,{size:12,weight:u?"bold":"regular"}),r.label]},r.id)})]}),t.jsx("div",{className:"flex-1 overflow-y-auto p-3",children:x()}),t.jsx("div",{className:"shrink-0 p-3 border-t border-panel-border",children:t.jsx("button",{onClick:()=>l("design-system"),className:"w-full py-2 rounded-lg bg-panel-accent text-white text-[12px] font-medium hover:bg-panel-accent-hover transition-colors duration-200 focus-visible:ring-2 focus-visible:ring-panel-accent focus-visible:ring-offset-2 focus-visible:ring-offset-panel-bg",children:"View Design System"})})]})}function f1(a){const n=[":root {"];for(const l of a.colors){const s=l.name||`${l.category}-${l.hex.slice(1)}`;n.push(` --color-${H(s)}: ${l.hex};`)}for(const l of a.typography){const s=H(l.fontFamily.split(",")[0].replace(/['"]/g,"").trim());n.push(` --font-${s}: ${l.fontFamily};`)}for(const l of a.spacing)n.push(` --spacing-${H(l.label)}: ${l.value};`);return a.borderRadius.forEach((l,s)=>{n.push(` --radius-${s+1}: ${l.value};`)}),a.shadows.forEach((l,s)=>{n.push(` --shadow-${s+1}: ${l.value};`)}),n.push("}"),n.join(` +`)}function g1(a){const n={};for(const i of a.colors){const m=i.name||`${i.category}-${i.hex.slice(1)}`;n[H(m)]=i.hex}const l={};for(const i of a.typography){const m=H(i.fontFamily.split(",")[0].replace(/['"]/g,"").trim());l[m]=i.fontFamily.split(",").map(h=>h.trim().replace(/['"]/g,""))}const s={};for(const i of a.spacing)s[H(i.label)]=i.value;const c={};a.borderRadius.forEach((i,m)=>{c[`r${m+1}`]=i.value});const o={};return a.shadows.forEach((i,m)=>{o[`s${m+1}`]=i.value}),{theme:{extend:{colors:n,fontFamily:l,spacing:s,borderRadius:c,boxShadow:o}}}}function b1(a){return{$schema:"https://design-tokens.github.io/community-group/format/",color:Object.fromEntries(a.colors.map(n=>[n.name||`${n.category}-${n.hex.slice(1)}`,{$value:n.hex,$type:"color",$description:`${n.category} — freq: ${n.frequency}`}])),fontFamily:Object.fromEntries(a.typography.map(n=>[H(n.fontFamily.split(",")[0].replace(/['"]/g,"").trim()),{$value:n.fontFamily,$type:"fontFamily"}])),spacing:Object.fromEntries(a.spacing.map(n=>[H(n.label),{$value:n.value,$type:"dimension"}])),borderRadius:Object.fromEntries(a.borderRadius.map((n,l)=>[`radius-${l+1}`,{$value:n.value,$type:"dimension"}])),boxShadow:Object.fromEntries(a.shadows.map((n,l)=>[`shadow-${l+1}`,{$value:n.value,$type:"shadow"}]))}}function h0(a,n){switch(n){case"css-variables":return f1(a);case"tailwind":return`/** @type {import('tailwindcss').Config} */ +module.exports = ${JSON.stringify(g1(a),null,2)}`;case"json":return JSON.stringify(b1(a),null,2);case"png":return""}}function H(a){return a.toLowerCase().replace(/\s+/g,"-").replace(/[^a-z0-9-]/g,"").replace(/-+/g,"-").replace(/^-|-$/g,"")}const v1=[{format:"css-variables",label:"CSS Variables"},{format:"tailwind",label:"Tailwind Config"},{format:"json",label:"JSON Tokens"},{format:"png",label:"PNG Palette"}];function V1({designSystem:a,onExport:n}){const[l,s]=e.useState(!1),[c,o]=e.useState(!1),[i,m]=e.useState([]),h=e.useRef(null),x=e.useRef(0);e.useEffect(()=>{if(!l)return;const p=u=>{h.current&&!h.current.contains(u.target)&&s(!1)};return document.addEventListener("mousedown",p),()=>document.removeEventListener("mousedown",p)},[l]);const r=()=>{const p=["#6366F1","#818CF8","#22C55E","#F59E0B"],u=Array.from({length:4},()=>({id:x.current++,x:(Math.random()-.5)*60,y:-(Math.random()*40+20),color:p[Math.floor(Math.random()*p.length)]}));m(u),setTimeout(()=>m([]),600)},d=async p=>{if(s(!1),p==="png"){const u=e1(a.colors),f=URL.createObjectURL(u),j=document.createElement("a");j.href=f,j.download="palette.png",j.click(),URL.revokeObjectURL(f)}else{const u=h0(a,p);await Z(u)}o(!0),r(),setTimeout(()=>o(!1),1500),n==null||n(p)};return t.jsxs("div",{className:"relative",ref:h,children:[t.jsxs("button",{onClick:()=>s(!l),className:`flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-[11px] font-medium transition-all duration-200 focus-visible:ring-2 focus-visible:ring-panel-accent focus-visible:ring-offset-1 focus-visible:ring-offset-panel-bg ${c?"bg-success text-white":"bg-panel-accent text-white hover:bg-panel-accent-hover"}`,children:[c?t.jsx(y,{size:12}):t.jsx(n0,{size:12}),c?"Done!":"Export"]}),i.map(p=>t.jsx("span",{className:"absolute top-0 left-1/2 w-1.5 h-1.5 rounded-full pointer-events-none",style:{backgroundColor:p.color,"--confetti-x":`${p.x}px`,"--confetti-y":`${p.y}px`,animation:"confetti-pop 500ms ease-out forwards"}},p.id)),l&&t.jsx("div",{className:"absolute top-full right-0 mt-1.5 w-44 bg-panel-surface border border-panel-border rounded-lg shadow-xl overflow-hidden z-20 toast-enter",children:v1.map(p=>t.jsx("button",{onClick:()=>d(p.format),className:"w-full px-3 py-2 text-left text-[11px] text-panel-text hover:bg-panel-accent/10 hover:text-panel-accent transition-colors duration-150",children:p.label},p.format))})]})}function H1(){const a=g(o=>o.designSystem),n=g(o=>o.setDesignSystem),l=g(o=>o.setMode);if(!a)return t.jsxs("div",{className:"flex flex-col items-center justify-center h-full gap-4 px-6 text-center",children:[t.jsx("div",{className:"w-16 h-16 rounded-2xl bg-panel-surface border border-panel-border flex items-center justify-center",children:t.jsx(N,{size:28,className:"text-panel-text-dim"})}),t.jsxs("div",{children:[t.jsx("p",{className:"text-[13px] font-medium text-panel-text mb-1",children:"No design system yet"}),t.jsx("p",{className:"text-[11px] text-panel-text-dim leading-relaxed mb-4",children:"Scan a page first to generate a design system"}),t.jsx("button",{onClick:()=>l("scan"),className:"px-4 py-2 rounded-lg bg-panel-accent text-white text-[12px] font-medium hover:bg-panel-accent-hover transition-colors duration-200 focus-visible:ring-2 focus-visible:ring-panel-accent focus-visible:ring-offset-2 focus-visible:ring-offset-panel-bg",children:"Go to Scan"})]})]});const s=o=>{const i={...a,colors:a.colors.filter((m,h)=>h!==o)};n(i)},c=(o,i)=>{const m={...a,colors:a.colors.map((h,x)=>x===o?{...h,name:i}:h)};n(m)};return t.jsxs("div",{className:"flex flex-col h-full",children:[t.jsxs("div",{className:"shrink-0 px-3 py-2.5 border-b border-panel-border bg-panel-surface/50 flex items-center justify-between",children:[t.jsxs("div",{children:[t.jsx("p",{className:"text-[12px] font-medium text-panel-text",children:a.metadata.title}),t.jsx("p",{className:"text-[10px] text-panel-text-dim font-mono truncate max-w-[180px]",children:a.metadata.url})]}),t.jsx(V1,{designSystem:a})]}),t.jsxs("div",{className:"flex-1 overflow-y-auto p-3 flex flex-col gap-5",children:[t.jsx(M,{title:"Palette",icon:t.jsx(N,{size:14}),count:a.colors.length,children:t.jsx("div",{className:"flex flex-col gap-2",children:a.colors.map((o,i)=>t.jsxs("div",{className:"flex items-center gap-2 group",children:[t.jsx($,{color:o.hex,size:28}),t.jsx(Z1,{value:o.name,onChange:m=>c(i,m)}),t.jsx("span",{className:"text-[10px] font-mono text-panel-text-dim ml-auto",children:o.hex}),t.jsx("button",{onClick:()=>s(i),className:"opacity-0 group-hover:opacity-100 p-0.5 text-panel-text-dim hover:text-red-400 transition-all duration-150",title:"Remove",children:t.jsx(d0,{size:12})})]},i))})}),t.jsx(M,{title:"Type Scale",icon:t.jsx(F,{size:14}),count:a.typography.length,children:t.jsx("div",{className:"flex flex-col gap-3",children:a.typography.map(o=>t.jsxs("div",{className:"p-2.5 rounded-lg bg-panel-surface border border-panel-border",children:[t.jsx("p",{className:"text-[14px] text-panel-text mb-1 truncate",style:{fontFamily:o.fontFamily},children:o.fontFamily.split(",")[0].replace(/['"]/g,"")}),t.jsx("div",{className:"flex flex-wrap gap-1.5",children:o.variants.map((i,m)=>t.jsxs("span",{className:"text-[10px] font-mono text-panel-text-dim bg-panel-bg px-1.5 py-0.5 rounded",children:[i.fontSize," / ",i.fontWeight]},m))})]},o.fontFamily))})}),t.jsx(M,{title:"Spacing",icon:t.jsx(U,{size:14}),count:a.spacing.length,children:t.jsx("div",{className:"flex flex-wrap gap-2",children:a.spacing.map(o=>t.jsxs("div",{className:"flex items-center gap-1.5 bg-panel-surface border border-panel-border rounded px-2 py-1",children:[t.jsx("div",{className:"h-3 rounded-sm bg-panel-accent/40",style:{width:Math.min(parseInt(o.value)||4,48)}}),t.jsx("span",{className:"text-[11px] font-mono text-panel-text",children:o.value})]},o.value))})}),t.jsx(M,{title:"Border Radius",icon:t.jsx(D0,{size:14}),count:a.borderRadius.length,children:t.jsx("div",{className:"flex flex-wrap gap-2",children:a.borderRadius.map(o=>t.jsxs("div",{className:"flex items-center gap-2 bg-panel-surface border border-panel-border rounded px-2.5 py-1.5",children:[t.jsx("div",{className:"w-6 h-6 border-2 border-panel-accent",style:{borderRadius:o.value}}),t.jsx("span",{className:"text-[11px] font-mono text-panel-text",children:o.value})]},o.value))})}),t.jsx(M,{title:"Shadows",icon:t.jsx(t0,{size:14}),count:a.shadows.length,children:t.jsx("div",{className:"grid grid-cols-2 gap-3",children:a.shadows.map((o,i)=>t.jsx(C,{shadow:o},i))})})]})]})}function M({title:a,icon:n,count:l,children:s}){return t.jsxs("section",{children:[t.jsxs("div",{className:"flex items-center gap-2 mb-2",children:[t.jsx("span",{className:"text-panel-text-dim",children:n}),t.jsx("h3",{className:"text-[12px] font-semibold text-panel-text",children:a}),t.jsx("span",{className:"text-[10px] text-panel-text-dim bg-panel-surface px-1.5 py-0.5 rounded-full",children:l})]}),s]})}function Z1({value:a,onChange:n}){const[l,s]=e.useState(!1),[c,o]=e.useState(a);return l?t.jsx("input",{className:"text-[11px] font-medium text-panel-text bg-panel-bg border border-panel-border rounded px-1.5 py-0.5 w-24 focus:outline-none focus:border-panel-accent",value:c,onChange:i=>o(i.target.value),onBlur:()=>{n(c),s(!1)},onKeyDown:i=>{i.key==="Enter"&&(n(c),s(!1)),i.key==="Escape"&&s(!1)},autoFocus:!0}):t.jsx("button",{onClick:()=>{o(a),s(!0)},className:"text-[11px] font-medium text-panel-text hover:text-panel-accent transition-colors duration-150 truncate max-w-[100px] text-left",title:"Click to rename",children:a||"unnamed"})}const O=[{id:"css-variables",label:"CSS Variables",ext:"css",mime:"text/css"},{id:"tailwind",label:"Tailwind",ext:"js",mime:"text/javascript"},{id:"json",label:"JSON",ext:"json",mime:"application/json"}];function j1(){const a=g(r=>r.designSystem),n=g(r=>r.setMode),[l,s]=e.useState("css-variables"),[c,o]=e.useState(!1);if(!a)return t.jsxs("div",{className:"flex flex-col items-center justify-center h-full gap-4 px-6 text-center",children:[t.jsx("div",{className:"w-16 h-16 rounded-2xl bg-panel-surface border border-panel-border flex items-center justify-center",children:t.jsx(G0,{size:28,className:"text-panel-text-dim"})}),t.jsxs("div",{children:[t.jsx("p",{className:"text-[13px] font-medium text-panel-text mb-1",children:"Nothing to export"}),t.jsx("p",{className:"text-[11px] text-panel-text-dim leading-relaxed mb-4",children:"Scan a page first to generate exportable tokens"}),t.jsx("button",{onClick:()=>n("scan"),className:"px-4 py-2 rounded-lg bg-panel-accent text-white text-[12px] font-medium hover:bg-panel-accent-hover transition-colors duration-200 focus-visible:ring-2 focus-visible:ring-panel-accent focus-visible:ring-offset-2 focus-visible:ring-offset-panel-bg",children:"Go to Scan"})]})]});const i=h0(a,l),m=O.find(r=>r.id===l),h=async()=>{await Z(i),o(!0),setTimeout(()=>o(!1),1500)},x=()=>{const r=`design-tokens.${m.ext}`;Q0(i,r,m.mime)};return t.jsxs("div",{className:"flex flex-col h-full",children:[t.jsx("div",{className:"shrink-0 px-3 py-3 border-b border-panel-border",children:t.jsx("div",{className:"flex gap-1 p-0.5 bg-panel-surface rounded-lg",children:O.map(r=>t.jsx("button",{onClick:()=>s(r.id),className:`flex-1 py-1.5 text-[11px] font-medium rounded-md transition-all duration-200 ${l===r.id?"bg-panel-accent text-white shadow-sm":"text-panel-text-dim hover:text-panel-text"}`,children:r.label},r.id))})}),t.jsx("div",{className:"flex-1 overflow-y-auto p-3",children:t.jsx(p0,{code:i,language:l==="json"?"json":l==="tailwind"?"js":"css"})}),t.jsxs("div",{className:"shrink-0 p-3 border-t border-panel-border flex gap-2",children:[t.jsxs("button",{onClick:h,className:`flex-1 flex items-center justify-center gap-1.5 py-2 rounded-lg text-[12px] font-medium transition-all duration-200 focus-visible:ring-2 focus-visible:ring-panel-accent focus-visible:ring-offset-2 focus-visible:ring-offset-panel-bg ${c?"bg-success text-white":"bg-panel-accent text-white hover:bg-panel-accent-hover"}`,children:[t.jsx(S,{size:14}),c?"Copied!":"Copy to Clipboard"]}),t.jsx("button",{onClick:x,className:"px-3 py-2 rounded-lg border border-panel-border text-panel-text-dim text-[12px] font-medium hover:bg-panel-surface hover:text-panel-text transition-colors duration-200 focus-visible:ring-2 focus-visible:ring-panel-accent focus-visible:ring-offset-2 focus-visible:ring-offset-panel-bg",title:"Download",children:t.jsx(U0,{size:14})})]})]})}const P="pixellens_scans";async function E1(){return(await chrome.storage.local.get(P))[P]||[]}function M1(a){const n=Date.now(),l=new Date(a).getTime(),s=n-l,c=Math.floor(s/6e4);if(c<1)return"just now";if(c<60)return`${c}m ago`;const o=Math.floor(c/60);return o<24?`${o}h ago`:`${Math.floor(o/24)}d ago`}function A1(){const a=g(r=>r.setDesignSystem),n=g(r=>r.setMode),l=g(r=>r.history),s=g(r=>r.clearHistory),[c,o]=e.useState([]),[i,m]=e.useState(!0);e.useEffect(()=>{E1().then(r=>{const d=[...r];for(const p of l)d.some(f=>f.metadata.url===p.metadata.url&&f.metadata.scannedAt===p.metadata.scannedAt)||d.push(p);d.sort((p,u)=>new Date(u.metadata.scannedAt).getTime()-new Date(p.metadata.scannedAt).getTime()),o(d)}).finally(()=>m(!1))},[l]);const h=r=>{a(r),n("design-system")},x=()=>{s(),o([])};return i?t.jsx("div",{className:"flex items-center justify-center h-full",children:t.jsx("span",{className:"text-[11px] text-panel-text-dim",children:"Loading..."})}):c.length===0?t.jsxs("div",{className:"flex flex-col items-center justify-center h-full gap-4 px-6 text-center",children:[t.jsx("div",{className:"w-16 h-16 rounded-2xl bg-panel-surface border border-panel-border flex items-center justify-center",children:t.jsx(B,{size:28,className:"text-panel-text-dim"})}),t.jsxs("div",{children:[t.jsx("p",{className:"text-[13px] font-medium text-panel-text mb-1",children:"No scan history"}),t.jsx("p",{className:"text-[11px] text-panel-text-dim leading-relaxed",children:"Your previous scans will appear here"})]})]}):t.jsxs("div",{className:"flex flex-col h-full",children:[t.jsx("div",{className:"flex-1 overflow-y-auto p-3 flex flex-col gap-2",children:c.map((r,d)=>t.jsxs("button",{onClick:()=>h(r),className:"flex items-center gap-3 p-2.5 rounded-lg bg-panel-surface border border-panel-border hover:border-panel-accent/50 transition-colors duration-200 text-left group",children:[t.jsx("div",{className:"flex -space-x-1.5 shrink-0",children:r.colors.slice(0,5).map((p,u)=>t.jsx("div",{className:"w-5 h-5 rounded-full border-2 border-panel-surface",style:{backgroundColor:p.hex}},u))}),t.jsxs("div",{className:"flex-1 min-w-0",children:[t.jsx("p",{className:"text-[12px] font-medium text-panel-text truncate",children:r.metadata.title||"Untitled"}),t.jsx("p",{className:"text-[10px] text-panel-text-dim font-mono truncate",children:r.metadata.url.replace(/^https?:\/\//,"").slice(0,40)})]}),t.jsx("span",{className:"text-[10px] text-panel-text-dim shrink-0",children:M1(r.metadata.scannedAt)})]},d))}),t.jsx("div",{className:"shrink-0 p-3 border-t border-panel-border",children:t.jsxs("button",{onClick:x,className:"flex items-center justify-center gap-1.5 w-full py-2 rounded-lg border border-panel-border text-panel-text-dim text-[11px] font-medium hover:border-red-500/50 hover:text-red-400 transition-colors duration-200",children:[t.jsx(d0,{size:12}),"Clear History"]})})]})}const D=[{mode:"inspect",label:"Inspect",icon:u0},{mode:"scan",label:"Scan",icon:f0},{mode:"design-system",label:"Design System",icon:N}],y1=[{mode:"export",icon:n0,label:"Export"},{mode:"history",icon:B,label:"History"}];function w1(){const a=g(r=>r.activeMode),n=g(r=>r.setMode),l=g(r=>r.setInspectedElement),s=g(r=>r.setDesignSystem),c=g(r=>r.setScanProgress),o=g(r=>r.addToHistory),i=e.useRef([]),[m,h]=e.useState({left:0,width:0});e.useEffect(()=>{const r=D.findIndex(p=>p.mode===a);if(r===-1)return;const d=i.current[r];d&&h({left:d.offsetLeft,width:d.offsetWidth})},[a]),e.useEffect(()=>{const r=(d,p,u)=>{if(d.type===w.ELEMENT_SELECTED){const f=d.payload;l(f.element),n("inspect"),u({received:!0})}if(d.type===w.SCAN_PROGRESS){const f=d.payload;c({percent:f.progress,phase:f.phase})}if(d.type===w.SCAN_COMPLETE){const f=d.payload;s(f.designSystem),o(f.designSystem),c(null),n("scan"),u({received:!0})}};return chrome.runtime.onMessage.addListener(r),()=>chrome.runtime.onMessage.removeListener(r)},[l,s,c,n,o]);const x=()=>{switch(a){case"inspect":return t.jsx(d1,{});case"scan":return t.jsx(u1,{});case"design-system":return t.jsx(H1,{});case"export":return t.jsx(j1,{});case"history":return t.jsx(A1,{})}};return t.jsxs("div",{className:"flex flex-col h-screen overflow-hidden bg-panel-bg",children:[t.jsxs("header",{className:"shrink-0 border-b border-panel-border px-3 pt-3 pb-0",children:[t.jsxs("div",{className:"flex items-center gap-2 mb-3",children:[t.jsx("div",{className:"w-5 h-5 rounded bg-panel-accent flex items-center justify-center",children:t.jsx("span",{className:"text-white text-[10px] font-semibold leading-none",children:"P"})}),t.jsx("h1",{className:"text-[16px] font-semibold text-panel-text tracking-tight",children:"PixelLens"})]}),t.jsxs("nav",{className:"relative flex gap-0",children:[t.jsx("div",{className:"absolute bottom-0 h-[2px] bg-panel-accent rounded-full transition-all duration-300 ease-out",style:{left:m.left,width:m.width}}),D.map((r,d)=>{const p=r.icon,u=a===r.mode;return t.jsxs("button",{ref:f=>{i.current[d]=f},onClick:()=>n(r.mode),className:`flex items-center gap-1.5 px-3 pb-2 pt-1 text-[12px] font-medium transition-colors duration-200 ${u?"text-panel-text":"text-panel-text-dim hover:text-panel-text"}`,children:[t.jsx(p,{size:14,weight:u?"bold":"regular"}),r.label]},r.mode)})]})]}),t.jsx("main",{className:"flex-1 overflow-y-auto overflow-x-hidden",children:x()}),t.jsxs("footer",{className:"shrink-0 border-t border-panel-border px-3 py-2 flex items-center justify-between",children:[t.jsx("div",{className:"flex items-center gap-1",children:y1.map(r=>{const d=r.icon,p=a===r.mode;return t.jsx("button",{onClick:()=>n(r.mode),className:`p-1.5 rounded-md transition-colors duration-200 ${p?"bg-panel-surface text-panel-accent":"text-panel-text-dim hover:text-panel-text hover:bg-panel-surface"}`,title:r.label,children:t.jsx(d,{size:16,weight:p?"fill":"regular"})},r.mode)})}),t.jsx("span",{className:"text-[10px] text-panel-text-dim font-mono",children:"v1.0.0"})]})]})}g0.createRoot(document.getElementById("root")).render(t.jsx(A.StrictMode,{children:t.jsx(w1,{})})); diff --git a/dist/assets/index.ts-loader-Bqx7lo3D.js b/dist/assets/index.ts-loader-Bqx7lo3D.js new file mode 100644 index 0000000..4dd37db --- /dev/null +++ b/dist/assets/index.ts-loader-Bqx7lo3D.js @@ -0,0 +1,13 @@ +(function () { + 'use strict'; + + const injectTime = performance.now(); + (async () => { + const { onExecute } = await import( + /* @vite-ignore */ + chrome.runtime.getURL("assets/index.ts-vezM8RYQ.js") + ); + onExecute?.({ perf: { injectTime, loadTime: performance.now() - injectTime } }); + })().catch(console.error); + +})(); diff --git a/dist/assets/index.ts-vezM8RYQ.js b/dist/assets/index.ts-vezM8RYQ.js new file mode 100644 index 0000000..5711df7 --- /dev/null +++ b/dist/assets/index.ts-vezM8RYQ.js @@ -0,0 +1,98 @@ +const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/ContentApp-DS3Bful2.js","assets/Scan.es-D0n8eUjn.js","assets/Eyedropper.es-Cn4UL7iP.js","assets/colors-Czz5EmDP.js","assets/messages-CGxgbOds.js"])))=>i.map(i=>d[i]); +var q=Object.defineProperty;var G=(r,t,e)=>t in r?q(r,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):r[t]=e;var h=(r,t,e)=>G(r,typeof t!="symbol"?t+"":t,e);import{s as T,i as U,t as X,c as W,a as Y,b as J,d as j,o as M}from"./colors-Czz5EmDP.js";import{M as w}from"./messages-CGxgbOds.js";const K="modulepreload",Q=function(r){return"/"+r},z={},Z=function(t,e,n){let o=Promise.resolve();if(e&&e.length>0){let i=function(a){return Promise.all(a.map(d=>Promise.resolve(d).then(m=>({status:"fulfilled",value:m}),m=>({status:"rejected",reason:m}))))};document.getElementsByTagName("link");const c=document.querySelector("meta[property=csp-nonce]"),l=(c==null?void 0:c.nonce)||(c==null?void 0:c.getAttribute("nonce"));o=i(e.map(a=>{if(a=Q(a),a in z)return;z[a]=!0;const d=a.endsWith(".css"),m=d?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${a}"]${m}`))return;const u=document.createElement("link");if(u.rel=d?"stylesheet":K,d||(u.as="script"),u.crossOrigin="",u.href=a,l&&u.setAttribute("nonce",l),document.head.appendChild(u),d)return new Promise((p,f)=>{u.addEventListener("load",p),u.addEventListener("error",()=>f(new Error(`Unable to preload CSS for ${a}`)))})}))}function s(i){const c=new Event("vite:preloadError",{cancelable:!0});if(c.payload=i,window.dispatchEvent(c),!c.defaultPrevented)throw i}return o.then(i=>{for(const c of i||[])c.status==="rejected"&&s(c.reason);return t().catch(s)})};function P(r){const t=window.getComputedStyle(r);if(t.display==="none"||t.visibility==="hidden"||t.opacity==="0")return!1;const e=r.getBoundingClientRect();return!(e.width===0&&e.height===0)}function tt(r=document.body){const t=[],e=document.createTreeWalker(r,NodeFilter.SHOW_ELEMENT,{acceptNode(o){const s=o;if(!P(s))return NodeFilter.FILTER_REJECT;const i=s.tagName.toLowerCase();return i==="script"||i==="style"||i==="noscript"||i==="link"||i==="meta"?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT}});let n;for(;n=e.nextNode();)t.push(n);return t}function N(r,t){return{top:r.getPropertyValue(`${t}-top`),right:r.getPropertyValue(`${t}-right`),bottom:r.getPropertyValue(`${t}-bottom`),left:r.getPropertyValue(`${t}-left`)}}function V(r){const t=window.getComputedStyle(r),e=r.getBoundingClientRect();return{margin:N(t,"margin"),padding:N(t,"padding"),border:{top:t.getPropertyValue("border-top-width"),right:t.getPropertyValue("border-right-width"),bottom:t.getPropertyValue("border-bottom-width"),left:t.getPropertyValue("border-left-width")},content:{width:`${e.width}px`,height:`${e.height}px`}}}function et(r){var o;const t=window.getComputedStyle(r),e=r.getBoundingClientRect(),n={};for(const s of t)n[s]=t.getPropertyValue(s);return{tagName:r.tagName.toLowerCase(),className:((o=r.className)==null?void 0:o.toString())||"",id:r.id||"",computedStyles:n,boxModel:V(r),rect:{top:e.top,left:e.left,width:e.width,height:e.height}}}class nt{constructor(t){h(this,"root");h(this,"overlays",null);h(this,"container",null);h(this,"currentElement",null);h(this,"rafId",null);h(this,"enabled",!1);h(this,"onMouseOver",t=>this.handleMouseOver(t));h(this,"onMouseOut",()=>this.handleMouseOut());h(this,"onScroll",()=>this.update());this.root=t}enable(){this.enabled||(this.enabled=!0,this.createOverlays(),document.addEventListener("mouseover",this.onMouseOver,!0),document.addEventListener("mouseout",this.onMouseOut,!0),window.addEventListener("scroll",this.onScroll,{passive:!0}),window.addEventListener("resize",this.onScroll,{passive:!0}))}destroy(){var t;this.enabled=!1,document.removeEventListener("mouseover",this.onMouseOver,!0),document.removeEventListener("mouseout",this.onMouseOut,!0),window.removeEventListener("scroll",this.onScroll),window.removeEventListener("resize",this.onScroll),this.rafId!==null&&cancelAnimationFrame(this.rafId),(t=this.container)==null||t.remove(),this.container=null,this.overlays=null,this.currentElement=null}createOverlays(){this.container=document.createElement("div"),this.container.style.cssText="position: absolute; top: 0; left: 0; pointer-events: none;";const t=e=>{const n=document.createElement("div");return n.className=e,n.style.opacity="0",this.container.appendChild(n),n};this.overlays={content:t("pixellens-overlay-content"),paddingTop:t("pixellens-overlay-padding"),paddingRight:t("pixellens-overlay-padding"),paddingBottom:t("pixellens-overlay-padding"),paddingLeft:t("pixellens-overlay-padding"),marginTop:t("pixellens-overlay-margin"),marginRight:t("pixellens-overlay-margin"),marginBottom:t("pixellens-overlay-margin"),marginLeft:t("pixellens-overlay-margin"),badge:t("pixellens-badge")},this.root.appendChild(this.container)}handleMouseOver(t){const e=t.target;!e||e===document.documentElement||e===document.body||this.isOwnElement(e)||(this.currentElement=e,this.update())}handleMouseOut(){this.currentElement=null,this.hideOverlays()}isOwnElement(t){let e=t;for(;e;){if(e.id==="pixellens-host")return!0;e=e.parentNode}return!1}update(){this.rafId!==null&&cancelAnimationFrame(this.rafId),this.rafId=requestAnimationFrame(()=>{this.rafId=null,!(!this.currentElement||!this.overlays)&&this.positionOverlays(this.currentElement)})}positionOverlays(t){if(!this.overlays)return;const e=t.getBoundingClientRect(),n=V(t),o=parseFloat(n.margin.top)||0,s=parseFloat(n.margin.right)||0,i=parseFloat(n.margin.bottom)||0,c=parseFloat(n.margin.left)||0,l=parseFloat(n.padding.top)||0,a=parseFloat(n.padding.right)||0,d=parseFloat(n.padding.bottom)||0,m=parseFloat(n.padding.left)||0,u=parseFloat(n.border.top)||0,p=parseFloat(n.border.right)||0,f=parseFloat(n.border.bottom)||0,y=parseFloat(n.border.left)||0,g=window.scrollX,v=window.scrollY,B=e.left+g+y+m,I=e.top+v+u+l,_=e.width-y-p-m-a,O=e.height-u-f-l-d;this.setRect(this.overlays.content,B,I,Math.max(0,_),Math.max(0,O)),this.setRect(this.overlays.paddingTop,e.left+g+y,e.top+v+u,e.width-y-p,l),this.setRect(this.overlays.paddingRight,e.left+g+e.width-p-a,e.top+v+u+l,a,Math.max(0,O)),this.setRect(this.overlays.paddingBottom,e.left+g+y,e.top+v+e.height-f-d,e.width-y-p,d),this.setRect(this.overlays.paddingLeft,e.left+g+y,e.top+v+u+l,m,Math.max(0,O)),this.setRect(this.overlays.marginTop,e.left+g-c,e.top+v-o,e.width+c+s,o),this.setRect(this.overlays.marginRight,e.left+g+e.width,e.top+v,s,e.height),this.setRect(this.overlays.marginBottom,e.left+g-c,e.top+v+e.height,e.width+c+s,i),this.setRect(this.overlays.marginLeft,e.left+g-c,e.top+v,c,e.height);const D=Math.round(e.width),H=Math.round(e.height);this.overlays.badge.textContent=`${D} × ${H}`,this.setRect(this.overlays.badge,e.left+g+e.width+4,e.top+v-2,NaN,NaN),this.overlays.badge.style.width="auto",this.overlays.badge.style.height="auto",this.showOverlays()}setRect(t,e,n,o,s){t.style.left=`${e}px`,t.style.top=`${n}px`,isNaN(o)||(t.style.width=`${o}px`),isNaN(s)||(t.style.height=`${s}px`)}showOverlays(){if(this.overlays)for(const t of Object.values(this.overlays))t.style.opacity="1"}hideOverlays(){if(this.overlays)for(const t of Object.values(this.overlays))t.style.opacity="0"}}class it{constructor(t){h(this,"root");h(this,"enabled",!1);h(this,"onClick",t=>this.handleClick(t));this.root=t}enable(){this.enabled||(this.enabled=!0,document.addEventListener("click",this.onClick,!0))}destroy(){this.enabled=!1,document.removeEventListener("click",this.onClick,!0)}handleClick(t){const e=t.target;if(!e||this.isOwnElement(e))return;t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.showPulseRing(e);const n=et(e);T(w.ELEMENT_SELECTED,{element:n})}showPulseRing(t){const e=t.getBoundingClientRect(),n=document.createElement("div");n.className="pixellens-pulse-ring",n.style.left=`${e.left+window.scrollX}px`,n.style.top=`${e.top+window.scrollY}px`,n.style.width=`${e.width}px`,n.style.height=`${e.height}px`,this.root.appendChild(n),n.addEventListener("animationend",()=>n.remove())}isOwnElement(t){let e=t;for(;e;){if(e.id==="pixellens-host")return!0;e=e.parentNode}return!1}}class st{constructor(t){h(this,"root");h(this,"state","IDLE");h(this,"elementA",null);h(this,"elementB",null);h(this,"outlineA",null);h(this,"outlineB",null);h(this,"svgOverlay",null);h(this,"measureLabel",null);h(this,"guideH",null);h(this,"guideV",null);h(this,"enabled",!1);h(this,"onClick",t=>this.handleClick(t));h(this,"onScroll",()=>this.updateVisuals());this.root=t}enable(){this.enabled||(this.enabled=!0,document.addEventListener("click",this.onClick,!0),window.addEventListener("scroll",this.onScroll,{passive:!0}),window.addEventListener("resize",this.onScroll,{passive:!0}))}destroy(){this.enabled=!1,document.removeEventListener("click",this.onClick,!0),window.removeEventListener("scroll",this.onScroll),window.removeEventListener("resize",this.onScroll),this.reset()}handleClick(t){const e=t.target;!e||this.isOwnElement(e)||(t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation(),this.state==="IDLE"?(this.elementA=e,this.outlineA=this.createOutline(e),this.state="FIRST_SELECTED"):this.state==="FIRST_SELECTED"?(this.elementB=e,this.outlineB=this.createOutline(e),this.state="MEASURING",this.drawMeasurement()):this.reset())}createOutline(t){const e=t.getBoundingClientRect(),n=document.createElement("div");return n.className="pixellens-measure-outline",n.style.left=`${e.left+window.scrollX}px`,n.style.top=`${e.top+window.scrollY}px`,n.style.width=`${e.width}px`,n.style.height=`${e.height}px`,this.root.appendChild(n),n}drawMeasurement(){if(!this.elementA||!this.elementB)return;const t=this.elementA.getBoundingClientRect(),e=this.elementB.getBoundingClientRect(),n=t.left+t.width/2,o=t.top+t.height/2,s=e.left+e.width/2,i=e.top+e.height/2,c=Math.round(Math.hypot(s-n,i-o));this.svgOverlay=document.createElementNS("http://www.w3.org/2000/svg","svg"),this.svgOverlay.setAttribute("class","pixellens-measure-line"),this.svgOverlay.style.cssText="position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; pointer-events: none; z-index: 2147483646;";const l=document.createElementNS("http://www.w3.org/2000/svg","line");l.setAttribute("x1",String(n)),l.setAttribute("y1",String(o)),l.setAttribute("x2",String(s)),l.setAttribute("y2",String(i)),l.setAttribute("stroke","#EF4444"),l.setAttribute("stroke-width","1.5"),l.setAttribute("stroke-dasharray","6 4");const a=Math.hypot(s-n,i-o);l.setAttribute("stroke-dashoffset",String(a));const d=document.createElementNS("http://www.w3.org/2000/svg","animate");d.setAttribute("attributeName","stroke-dashoffset"),d.setAttribute("from",String(a)),d.setAttribute("to","0"),d.setAttribute("dur","0.4s"),d.setAttribute("fill","freeze"),l.appendChild(d),this.svgOverlay.appendChild(l),this.root.appendChild(this.svgOverlay);const m=(n+s)/2,u=(o+i)/2;this.measureLabel=document.createElement("div"),this.measureLabel.className="pixellens-measure-label",this.measureLabel.textContent=`${c}px`,this.measureLabel.style.left=`${m+window.scrollX+8}px`,this.measureLabel.style.top=`${u+window.scrollY-10}px`,this.root.appendChild(this.measureLabel);const p=Math.abs(s-n),f=Math.abs(i-o);p>4&&(this.guideH=document.createElement("div"),this.guideH.style.cssText="position: fixed; height: 0; border-top: 1px dashed rgba(239,68,68,0.4); pointer-events: none; z-index: 2147483645;",this.guideH.style.left=`${Math.min(n,s)}px`,this.guideH.style.top=`${o}px`,this.guideH.style.width=`${p}px`,this.root.appendChild(this.guideH)),f>4&&(this.guideV=document.createElement("div"),this.guideV.style.cssText="position: fixed; width: 0; border-left: 1px dashed rgba(239,68,68,0.4); pointer-events: none; z-index: 2147483645;",this.guideV.style.left=`${s}px`,this.guideV.style.top=`${Math.min(o,i)}px`,this.guideV.style.height=`${f}px`,this.root.appendChild(this.guideV))}updateVisuals(){var t;this.state==="MEASURING"&&this.elementA&&this.elementB?(this.clearVisuals(),this.outlineA=this.createOutline(this.elementA),this.outlineB=this.createOutline(this.elementB),this.drawMeasurement()):this.state==="FIRST_SELECTED"&&this.elementA&&((t=this.outlineA)==null||t.remove(),this.outlineA=this.createOutline(this.elementA))}clearVisuals(){var t,e,n,o,s,i;(t=this.outlineA)==null||t.remove(),(e=this.outlineB)==null||e.remove(),(n=this.svgOverlay)==null||n.remove(),(o=this.measureLabel)==null||o.remove(),(s=this.guideH)==null||s.remove(),(i=this.guideV)==null||i.remove(),this.outlineA=null,this.outlineB=null,this.svgOverlay=null,this.measureLabel=null,this.guideH=null,this.guideV=null}reset(){this.clearVisuals(),this.elementA=null,this.elementB=null,this.state="IDLE"}isOwnElement(t){let e=t;for(;e;){if(e.id==="pixellens-host")return!0;e=e.parentNode}return!1}}class ot{constructor(t){h(this,"root");h(this,"canvas",null);h(this,"ctx",null);h(this,"gridSize",8);h(this,"visible",!1);h(this,"rafId",null);h(this,"onScroll",()=>this.scheduleRedraw());h(this,"onResize",()=>this.handleResize());this.root=t}show(t){t&&(this.gridSize=t),this.canvas||this.createCanvas(),this.visible=!0,this.canvas.style.display="block",this.draw(),window.addEventListener("scroll",this.onScroll,{passive:!0}),window.addEventListener("resize",this.onResize,{passive:!0})}hide(){this.visible=!1,this.canvas&&(this.canvas.style.display="none"),window.removeEventListener("scroll",this.onScroll),window.removeEventListener("resize",this.onResize),this.rafId!==null&&cancelAnimationFrame(this.rafId)}setGridSize(t){this.gridSize=t,this.visible&&this.draw()}destroy(){var t;this.hide(),(t=this.canvas)==null||t.remove(),this.canvas=null,this.ctx=null}createCanvas(){this.canvas=document.createElement("canvas"),this.canvas.className="pixellens-grid-canvas",this.canvas.style.display="none",this.root.appendChild(this.canvas),this.ctx=this.canvas.getContext("2d"),this.handleResize()}handleResize(){if(!this.canvas)return;const t=window.devicePixelRatio||1;this.canvas.width=window.innerWidth*t,this.canvas.height=window.innerHeight*t,this.canvas.style.width=`${window.innerWidth}px`,this.canvas.style.height=`${window.innerHeight}px`,this.ctx&&this.ctx.scale(t,t),this.visible&&this.draw()}scheduleRedraw(){this.rafId===null&&(this.rafId=requestAnimationFrame(()=>{this.rafId=null,this.draw()}))}draw(){if(!this.ctx||!this.canvas)return;const t=window.innerWidth,e=window.innerHeight,n=window.devicePixelRatio||1;this.ctx.clearRect(0,0,t*n,e*n),this.ctx.resetTransform(),this.ctx.scale(n,n);const o=window.scrollX%this.gridSize,s=window.scrollY%this.gridSize;this.ctx.strokeStyle="rgba(99, 102, 241, 0.05)",this.ctx.lineWidth=.5,this.ctx.beginPath();for(let i=-o;i<=t;i+=this.gridSize)this.ctx.moveTo(i,0),this.ctx.lineTo(i,e);for(let i=-s;i<=e;i+=this.gridSize)this.ctx.moveTo(0,i),this.ctx.lineTo(t,i);this.ctx.stroke()}}const rt=["color","background-color","border-color","outline-color"],at=new Set(["transparent","rgba(0, 0, 0, 0)","inherit","initial","currentcolor"]);class lt{extract(t){const e=new Map;for(const i of t){const c=window.getComputedStyle(i);for(const l of rt){const a=c.getPropertyValue(l);if(!a||at.has(a.toLowerCase())||U(a))continue;let d;try{d=X(a)}catch{continue}e.set(d,(e.get(d)||0)+1)}}const n=Array.from(e.entries()).map(([i,c])=>({hex:i,frequency:c})),s=W(n,5).map(i=>({name:"",hex:i.hex,rgb:J(i.hex),hsl:Y(i.hex),frequency:i.frequency,category:"accent"}));return j(s)}}const ct=new Set(["h1","h2","h3","h4","h5","h6","p","span","a","li","label","button","td","th","caption","blockquote"]),k=[1.067,1.125,1.2,1.25,1.333,1.414,1.5,1.618];class dt{extract(t){const e=new Map;for(const o of t){const s=o.tagName.toLowerCase();if(!ct.has(s))continue;const i=window.getComputedStyle(o),c=i.getPropertyValue("font-family"),l=i.getPropertyValue("font-size"),a=i.getPropertyValue("font-weight"),d=i.getPropertyValue("line-height"),m=i.getPropertyValue("letter-spacing");if(!c||!l)continue;const u=c.trim(),p=`${l}|${a}`;e.has(u)||e.set(u,new Map);const f=e.get(u);f.has(p)?f.get(p).count++:f.set(p,{fontSize:l,fontWeight:a,lineHeight:d,letterSpacing:m,count:1})}const n=[];for(const[o,s]of e){const i=Array.from(s.values()).sort((c,l)=>parseFloat(l.fontSize)-parseFloat(c.fontSize)).map(({fontSize:c,fontWeight:l,lineHeight:a,letterSpacing:d})=>({fontSize:c,fontWeight:l,lineHeight:a,letterSpacing:d}));n.push({fontFamily:o,variants:i})}return n.sort((o,s)=>s.variants.length-o.variants.length),n}detectTypeScaleRatio(t){const e=new Set;for(const l of t)for(const a of l.variants){const d=parseFloat(a.fontSize);d>0&&e.add(d)}const n=Array.from(e).sort((l,a)=>l-a);if(n.length<3)return null;const o=[];for(let l=1;ll-a);const s=o[Math.floor(o.length/2)];let i=k[0],c=Math.abs(s-i);for(const l of k){const a=Math.abs(s-l);aMath.round(n*a))),i=Array.from(e.entries()).sort((a,d)=>d[1]-a[1]),c=[],l=new Set;for(const a of s){const d=e.get(a)||0;d>0&&!l.has(a)&&(l.add(a),c.push({value:`${a}px`,frequency:d,label:this.getLabel(a,n)}))}for(const[a,d]of i)if(!l.has(a)){if(c.length>=16)break;l.add(a),c.push({value:`${a}px`,frequency:d,label:`space-${a}`})}return c.sort((a,d)=>parseFloat(a.value)-parseFloat(d.value)),c}roundSpacing(t){return Math.round(t/2)*2}detectBaseUnit(t){const e=t.get(4)||0,n=t.get(8)||0;let o=0,s=0,i=0;for(const[c,l]of t)i+=l,c%8===0&&(o+=l),c%4===0&&(s+=l);return i>0&&o/i>.6?8:i>0&&s/i>.6?4:n>=e?8:4}getLabel(t,e){const n=t/e;return n===.5?`space-${e}-half`:n===1?`space-${e}`:n===1.5?`space-${e}-1half`:Number.isInteger(n)?`space-${e}-x${n}`:`space-${t}`}}class pt{build(t,e,n,o){const s=this.extractShadows(o),i=this.extractBorderRadius(o);return{colors:t,typography:e,spacing:n,shadows:s,borderRadius:i,metadata:{url:window.location.href,title:document.title,scannedAt:new Date().toISOString()}}}extractShadows(t){const e=new Map;for(const n of t){const s=window.getComputedStyle(n).getPropertyValue("box-shadow");if(!s||s==="none"||e.has(s))continue;const i=this.parseShadow(s);i&&e.set(s,{value:s,parsed:i})}return Array.from(e.values())}parseShadow(t){const e=t.match(/(rgba?\([^)]+\))\s+(-?[\d.]+px)\s+(-?[\d.]+px)\s+([\d.]+px)\s*([\d.]+px)?/);if(e)return{color:e[1],x:e[2],y:e[3],blur:e[4],spread:e[5]||"0px"};const n=t.match(/(-?[\d.]+px)\s+(-?[\d.]+px)\s+([\d.]+px)\s*([\d.]+px)?\s+(rgba?\([^)]+\))/);return n?{x:n[1],y:n[2],blur:n[3],spread:n[4]||"0px",color:n[5]}:null}extractBorderRadius(t){const e=new Map;for(const n of t){const s=window.getComputedStyle(n).getPropertyValue("border-radius");!s||s==="0px"||e.set(s,(e.get(s)||0)+1)}return Array.from(e.entries()).map(([n,o])=>({value:n,frequency:o})).sort((n,o)=>o.frequency-n.frequency)}}class mt{constructor(){h(this,"colorExtractor",new lt);h(this,"typographyExtractor",new dt);h(this,"spacingExtractor",new ut);h(this,"builder",new pt)}async scan(t){t==null||t(5,"Scanning DOM elements...");const e=tt();t==null||t(15,`Found ${e.length} elements`),await this.yieldFrame(),t==null||t(20,"Extracting colors...");let n;try{n=this.colorExtractor.extract(e)}catch{n=[]}t==null||t(45,`Found ${n.length} colors`),await this.yieldFrame(),t==null||t(50,"Extracting typography...");let o;try{o=this.typographyExtractor.extract(e)}catch{o=[]}t==null||t(65,`Found ${o.length} font families`),await this.yieldFrame(),t==null||t(70,"Extracting spacing...");let s;try{s=this.spacingExtractor.extract(e)}catch{s=[]}t==null||t(85,`Found ${s.length} spacing values`),await this.yieldFrame(),t==null||t(90,"Building design system...");const i=this.builder.build(n,o,s,e);return t==null||t(100,"Scan complete"),i}yieldFrame(){return new Promise(t=>requestAnimationFrame(()=>t()))}}let F="off",x=null,b=null,E=null,L=null,$=null,S=null,C=null;function R(){if(C)return C;S=document.createElement("div"),S.id="pixellens-host",S.style.cssText="all: initial; position: fixed; z-index: 2147483647; top: 0; left: 0; width: 0; height: 0; pointer-events: none;",document.documentElement.appendChild(S),C=S.attachShadow({mode:"open"});const r=document.createElement("style");return r.textContent=vt(),C.appendChild(r),C}function A(r){F==="inspect"?(x==null||x.destroy(),b==null||b.destroy(),x=null,b=null):F==="measure"&&(E==null||E.destroy(),E=null),F=r,r==="inspect"?(x=new nt(R()),b=new it(R()),x.enable(),b.enable()):r==="measure"&&(E=new st(R()),E.enable()),ft(r)}function ft(r){document.dispatchEvent(new CustomEvent("pixellens:mode-change",{detail:{mode:r}}))}M(w.TOGGLE_INSPECT,r=>{r.active?A("inspect"):A("off")});M(w.TOGGLE_MEASURE,r=>{r.active?A("measure"):A("off")});M(w.TOGGLE_GRID,r=>{L||(L=new ot(R())),r.visible?L.show(r.size):L.hide()});M(w.SCAN_PAGE,(r,t,e)=>($||($=new mt),$.scan((n,o)=>{T(w.SCAN_PROGRESS,{progress:n,phase:o})}).then(n=>{T(w.SCAN_COMPLETE,{designSystem:n})}),!0));function gt(){const r=R(),t=document.createElement("div");t.id="pixellens-toolbar-root",t.style.cssText="position: fixed; bottom: 24px; left: 50%; transform: translateX(-50%); z-index: 2147483647; pointer-events: auto;",r.appendChild(t),Z(async()=>{const{mountContentApp:e}=await import("./ContentApp-DS3Bful2.js");return{mountContentApp:e}},__vite__mapDeps([0,1,2,3,4])).then(({mountContentApp:e})=>{e(t)})}function vt(){return` + .pixellens-overlay-content { + position: absolute; + background: rgba(59, 130, 246, 0.15); + pointer-events: none; + transition: opacity 100ms ease-out; + z-index: 2147483645; + } + .pixellens-overlay-padding { + position: absolute; + background: rgba(34, 197, 94, 0.15); + pointer-events: none; + transition: opacity 100ms ease-out; + z-index: 2147483644; + } + .pixellens-overlay-margin { + position: absolute; + background: rgba(249, 115, 22, 0.15); + pointer-events: none; + transition: opacity 100ms ease-out; + z-index: 2147483643; + } + .pixellens-badge { + position: absolute; + background: rgba(0, 0, 0, 0.85); + color: #EDEDEF; + font-family: 'JetBrains Mono', monospace; + font-size: 11px; + padding: 2px 6px; + border-radius: 4px; + white-space: nowrap; + pointer-events: none; + z-index: 2147483646; + } + .pixellens-pulse-ring { + position: absolute; + border: 2px solid #6366F1; + border-radius: 4px; + pointer-events: none; + animation: pixellens-pulse 0.6s ease-out forwards; + z-index: 2147483646; + } + @keyframes pixellens-pulse { + 0% { opacity: 1; transform: scale(1); } + 100% { opacity: 0; transform: scale(1.08); } + } + .pixellens-measure-line { + position: absolute; + pointer-events: none; + z-index: 2147483646; + } + .pixellens-measure-label { + position: absolute; + background: rgba(0, 0, 0, 0.85); + color: #EDEDEF; + font-family: 'JetBrains Mono', monospace; + font-size: 11px; + padding: 2px 8px; + border-radius: 4px; + white-space: nowrap; + pointer-events: none; + z-index: 2147483647; + } + .pixellens-measure-outline { + position: absolute; + border: 1px dashed #6366F1; + border-radius: 2px; + pointer-events: none; + z-index: 2147483644; + } + .pixellens-grid-canvas { + position: fixed; + top: 0; + left: 0; + width: 100vw; + height: 100vh; + pointer-events: none; + z-index: 2147483640; + } + .pixellens-tooltip { + position: fixed; + background: rgba(12, 12, 14, 0.95); + color: #EDEDEF; + font-family: 'JetBrains Mono', monospace; + font-size: 11px; + padding: 4px 8px; + border-radius: 6px; + box-shadow: 0 4px 12px rgba(0,0,0,0.4); + pointer-events: none; + z-index: 2147483647; + opacity: 0; + transition: opacity 100ms ease-out; + } + .pixellens-tooltip.visible { + opacity: 1; + } + `}gt(); diff --git a/dist/assets/messages-CGxgbOds.js b/dist/assets/messages-CGxgbOds.js new file mode 100644 index 0000000..c2a3262 --- /dev/null +++ b/dist/assets/messages-CGxgbOds.js @@ -0,0 +1 @@ +var S=(E=>(E.TOGGLE_INSPECT="TOGGLE_INSPECT",E.ELEMENT_SELECTED="ELEMENT_SELECTED",E.SCAN_PAGE="SCAN_PAGE",E.SCAN_PROGRESS="SCAN_PROGRESS",E.SCAN_COMPLETE="SCAN_COMPLETE",E.TOGGLE_GRID="TOGGLE_GRID",E.TOGGLE_MEASURE="TOGGLE_MEASURE",E.GET_PREFERENCES="GET_PREFERENCES",E.SET_PREFERENCES="SET_PREFERENCES",E.OPEN_SIDE_PANEL="OPEN_SIDE_PANEL",E))(S||{});export{S as M}; diff --git a/dist/assets/service-worker.ts-CY52Hvqa.js b/dist/assets/service-worker.ts-CY52Hvqa.js new file mode 100644 index 0000000..f6f5558 --- /dev/null +++ b/dist/assets/service-worker.ts-CY52Hvqa.js @@ -0,0 +1 @@ +import{M as a}from"./messages-CGxgbOds.js";chrome.sidePanel.setPanelBehavior({openPanelOnActionClick:!1});const i=new Map;chrome.commands.onCommand.addListener(async c=>{if(c==="toggle-inspect"){const[t]=await chrome.tabs.query({active:!0,currentWindow:!0});t!=null&&t.id&&u(t.id)}});chrome.runtime.onMessage.addListener((c,t,e)=>{var o;const{type:r,payload:n}=c;switch(r){case a.TOGGLE_INSPECT:{const s=(o=t.tab)==null?void 0:o.id;s&&u(s),e({success:!0});break}case a.OPEN_SIDE_PANEL:{h(t),e({success:!0});break}case a.ELEMENT_SELECTED:{chrome.runtime.sendMessage({type:a.ELEMENT_SELECTED,payload:n}).catch(()=>{}),e({received:!0});break}case a.SCAN_PAGE:{E(r,n),e({success:!0});break}case a.SCAN_PROGRESS:case a.SCAN_COMPLETE:{chrome.runtime.sendMessage({type:r,payload:n}).catch(()=>{}),e({success:!0});break}case a.TOGGLE_GRID:case a.TOGGLE_MEASURE:{E(r,n),e({success:!0});break}case a.GET_PREFERENCES:return chrome.storage.sync.get("pixellens_preferences",s=>{e(s.pixellens_preferences||{colorFormat:"hex",gridSize:8,theme:"dark"})}),!0;case a.SET_PREFERENCES:{const s=n;chrome.storage.sync.set({pixellens_preferences:s.preferences}),e({success:!0});break}}});async function u(c){const e=!(i.get(c)??!1);i.set(c,e),chrome.action.setBadgeText({text:e?"ON":"",tabId:c}),chrome.action.setBadgeBackgroundColor({color:"#6366F1",tabId:c}),chrome.tabs.sendMessage(c,{type:a.TOGGLE_INSPECT,payload:{active:e}}).catch(()=>{}),e&&chrome.sidePanel.open({tabId:c}).catch(()=>{})}async function E(c,t){const[e]=await chrome.tabs.query({active:!0,currentWindow:!0});e!=null&&e.id&&chrome.tabs.sendMessage(e.id,{type:c,payload:t}).catch(()=>{})}async function h(c){var e;const t=(e=c.tab)==null?void 0:e.id;if(t)chrome.sidePanel.open({tabId:t}).catch(()=>{});else{const[r]=await chrome.tabs.query({active:!0,currentWindow:!0});r!=null&&r.id&&chrome.sidePanel.open({tabId:r.id}).catch(()=>{})}} diff --git a/dist/icons/icon-128.png b/dist/icons/icon-128.png new file mode 100644 index 0000000..e996e31 Binary files /dev/null and b/dist/icons/icon-128.png differ diff --git a/dist/icons/icon-16.png b/dist/icons/icon-16.png new file mode 100644 index 0000000..004aaad Binary files /dev/null and b/dist/icons/icon-16.png differ diff --git a/dist/icons/icon-32.png b/dist/icons/icon-32.png new file mode 100644 index 0000000..8fe239b Binary files /dev/null and b/dist/icons/icon-32.png differ diff --git a/dist/icons/icon-48.png b/dist/icons/icon-48.png new file mode 100644 index 0000000..8795c57 Binary files /dev/null and b/dist/icons/icon-48.png differ diff --git a/dist/logo.svg b/dist/logo.svg new file mode 100644 index 0000000..d497a17 --- /dev/null +++ b/dist/logo.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/dist/manifest.json b/dist/manifest.json new file mode 100644 index 0000000..d1fbcd2 --- /dev/null +++ b/dist/manifest.json @@ -0,0 +1,70 @@ +{ + "manifest_version": 3, + "name": "PixelLens", + "version": "1.0.0", + "description": "Inspect any website. Copy any design system.", + "icons": { + "16": "icons/icon-16.png", + "32": "icons/icon-32.png", + "48": "icons/icon-48.png", + "128": "icons/icon-128.png" + }, + "permissions": [ + "activeTab", + "sidePanel", + "storage", + "clipboardWrite" + ], + "background": { + "service_worker": "service-worker-loader.js", + "type": "module" + }, + "content_scripts": [ + { + "js": [ + "assets/index.ts-loader-Bqx7lo3D.js" + ], + "matches": [ + "" + ], + "css": [] + } + ], + "side_panel": { + "default_path": "src/sidepanel/index.html" + }, + "action": { + "default_popup": "src/popup/index.html", + "default_icon": { + "16": "icons/icon-16.png", + "32": "icons/icon-32.png", + "48": "icons/icon-48.png", + "128": "icons/icon-128.png" + } + }, + "commands": { + "_execute_action": {}, + "toggle-inspect": { + "suggested_key": { + "default": "Ctrl+Shift+L" + }, + "description": "Toggle inspect mode" + } + }, + "web_accessible_resources": [ + { + "matches": [ + "" + ], + "resources": [ + "assets/colors-Czz5EmDP.js", + "assets/messages-CGxgbOds.js", + "assets/ContentApp-DS3Bful2.js", + "assets/Scan.es-D0n8eUjn.js", + "assets/Eyedropper.es-Cn4UL7iP.js", + "assets/index.ts-vezM8RYQ.js" + ], + "use_dynamic_url": false + } + ] +} diff --git a/dist/service-worker-loader.js b/dist/service-worker-loader.js new file mode 100644 index 0000000..9f73aa6 --- /dev/null +++ b/dist/service-worker-loader.js @@ -0,0 +1 @@ +import './assets/service-worker.ts-CY52Hvqa.js'; diff --git a/dist/src/popup/index.html b/dist/src/popup/index.html new file mode 100644 index 0000000..50ec778 --- /dev/null +++ b/dist/src/popup/index.html @@ -0,0 +1,16 @@ + + + + + + PixelLens + + + + + + + +
+ + diff --git a/dist/src/sidepanel/index.html b/dist/src/sidepanel/index.html new file mode 100644 index 0000000..588d7c5 --- /dev/null +++ b/dist/src/sidepanel/index.html @@ -0,0 +1,18 @@ + + + + + + PixelLens + + + + + + + + + +
+ + diff --git a/package-lock.json b/package-lock.json index d8f5986..b1af7e8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "dependencies": { "@phosphor-icons/react": "^2.1.7", "chroma-js": "^3.1.2", - "gsap": "^3.12.7", + "gsap": "^3.14.2", "react": "^19.1.0", "react-dom": "^19.1.0", "zustand": "^5.0.5" @@ -23,13 +23,55 @@ "@types/react": "^19.1.2", "@types/react-dom": "^19.1.2", "@vitejs/plugin-react": "^4.4.1", + "@vitest/coverage-v8": "^4.1.2", "autoprefixer": "^10.4.21", "eslint": "^9.25.0", + "jsdom": "^29.0.1", "tailwindcss": "^4.1.4", "typescript": "^5.8.3", - "vite": "^6.3.2" + "vite": "^6.3.2", + "vitest": "^4.1.2" } }, + "node_modules/@asamuzakjp/css-color": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-5.1.6.tgz", + "integrity": "sha512-BXWCh8dHs9GOfpo/fWGDJtDmleta2VePN9rn6WQt3GjEbxzutVF4t0x2pmH+7dbMCLtuv3MlwqRsAuxlzFXqFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@csstools/css-calc": "^3.1.1", + "@csstools/css-color-parser": "^4.0.2", + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, + "node_modules/@asamuzakjp/dom-selector": { + "version": "7.0.7", + "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-7.0.7.tgz", + "integrity": "sha512-d2BgqDUOS1Hfp4IzKUZqCNz+Kg3Y88AkaBvJK/ZVSQPU1f7OpPNi7nQTH6/oI47Dkdg+Z3e8Yp6ynOu4UMINAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@asamuzakjp/nwsapi": "^2.3.9", + "bidi-js": "^1.0.3", + "css-tree": "^3.2.1", + "is-potential-custom-element-name": "^1.0.1" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, + "node_modules/@asamuzakjp/nwsapi": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/@asamuzakjp/nwsapi/-/nwsapi-2.3.9.tgz", + "integrity": "sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==", + "dev": true, + "license": "MIT" + }, "node_modules/@babel/code-frame": { "version": "7.29.0", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", @@ -320,6 +362,29 @@ "node": ">=6.9.0" } }, + "node_modules/@bcoe/v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-1.0.2.tgz", + "integrity": "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@bramus/specificity": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@bramus/specificity/-/specificity-2.4.2.tgz", + "integrity": "sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "css-tree": "^3.0.0" + }, + "bin": { + "specificity": "bin/cli.js" + } + }, "node_modules/@crxjs/vite-plugin": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/@crxjs/vite-plugin/-/vite-plugin-2.4.0.tgz", @@ -348,6 +413,148 @@ "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/@csstools/color-helpers": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-6.0.2.tgz", + "integrity": "sha512-LMGQLS9EuADloEFkcTBR3BwV/CGHV7zyDxVRtVDTwdI2Ca4it0CCVTT9wCkxSgokjE5Ho41hEPgb8OEUwoXr6Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=20.19.0" + } + }, + "node_modules/@csstools/css-calc": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-3.1.1.tgz", + "integrity": "sha512-HJ26Z/vmsZQqs/o3a6bgKslXGFAungXGbinULZO3eMsOyNJHeBBZfup5FiZInOghgoM4Hwnmw+OgbJCNg1wwUQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0" + } + }, + "node_modules/@csstools/css-color-parser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-4.0.2.tgz", + "integrity": "sha512-0GEfbBLmTFf0dJlpsNU7zwxRIH0/BGEMuXLTCvFYxuL1tNhqzTbtnFICyJLTNK4a+RechKP75e7w42ClXSnJQw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/color-helpers": "^6.0.2", + "@csstools/css-calc": "^3.1.1" + }, + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0" + } + }, + "node_modules/@csstools/css-parser-algorithms": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-4.0.0.tgz", + "integrity": "sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "peer": true, + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^4.0.0" + } + }, + "node_modules/@csstools/css-syntax-patches-for-csstree": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.1.2.tgz", + "integrity": "sha512-5GkLzz4prTIpoyeUiIu3iV6CSG3Plo7xRVOFPKI7FVEJ3mZ0A8SwK0XU3Gl7xAkiQ+mDyam+NNp875/C5y+jSA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "peerDependencies": { + "css-tree": "^3.2.1" + }, + "peerDependenciesMeta": { + "css-tree": { + "optional": true + } + } + }, + "node_modules/@csstools/css-tokenizer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-4.0.0.tgz", + "integrity": "sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "peer": true, + "engines": { + "node": ">=20.19.0" + } + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", @@ -934,6 +1141,24 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@exodus/bytes": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@exodus/bytes/-/bytes-1.15.0.tgz", + "integrity": "sha512-UY0nlA+feH81UGSHv92sLEPLCeZFjXOuHhrIo0HQydScuQc8s0A7kL/UdgwgDq8g8ilksmuoF35YVTNphV2aBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + }, + "peerDependencies": { + "@noble/hashes": "^1.8.0 || ^2.0.0" + }, + "peerDependenciesMeta": { + "@noble/hashes": { + "optional": true + } + } + }, "node_modules/@humanfs/core": { "version": "0.19.1", "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", @@ -1458,6 +1683,13 @@ "win32" ] }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "dev": true, + "license": "MIT" + }, "node_modules/@tailwindcss/node": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.2.2.tgz", @@ -1775,6 +2007,17 @@ "@babel/types": "^7.28.2" } }, + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" + } + }, "node_modules/@types/chroma-js": { "version": "2.4.5", "resolved": "https://registry.npmjs.org/@types/chroma-js/-/chroma-js-2.4.5.tgz", @@ -1793,6 +2036,13 @@ "@types/har-format": "*" } }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", @@ -1883,6 +2133,167 @@ "node": ">=0.10.0" } }, + "node_modules/@vitest/coverage-v8": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.1.2.tgz", + "integrity": "sha512-sPK//PHO+kAkScb8XITeB1bf7fsk85Km7+rt4eeuRR3VS1/crD47cmV5wicisJmjNdfeokTZwjMk4Mj2d58Mgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@bcoe/v8-coverage": "^1.0.2", + "@vitest/utils": "4.1.2", + "ast-v8-to-istanbul": "^1.0.0", + "istanbul-lib-coverage": "^3.2.2", + "istanbul-lib-report": "^3.0.1", + "istanbul-reports": "^3.2.0", + "magicast": "^0.5.2", + "obug": "^2.1.1", + "std-env": "^4.0.0-rc.1", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@vitest/browser": "4.1.2", + "vitest": "4.1.2" + }, + "peerDependenciesMeta": { + "@vitest/browser": { + "optional": true + } + } + }, + "node_modules/@vitest/expect": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.2.tgz", + "integrity": "sha512-gbu+7B0YgUJ2nkdsRJrFFW6X7NTP44WlhiclHniUhxADQJH5Szt9mZ9hWnJPJ8YwOK5zUOSSlSvyzRf0u1DSBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.1.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.1.2", + "@vitest/utils": "4.1.2", + "chai": "^6.2.2", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.2.tgz", + "integrity": "sha512-Ize4iQtEALHDttPRCmN+FKqOl2vxTiNUhzobQFFt/BM1lRUTG7zRCLOykG/6Vo4E4hnUdfVLo5/eqKPukcWW7Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "4.1.2", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.21" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/mocker/node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/@vitest/pretty-format": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.2.tgz", + "integrity": "sha512-dwQga8aejqeuB+TvXCMzSQemvV9hNEtDDpgUKDzOmNQayl2OG241PSWeJwKRH3CiC+sESrmoFd49rfnq7T4RnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.2.tgz", + "integrity": "sha512-Gr+FQan34CdiYAwpGJmQG8PgkyFVmARK8/xSijia3eTFgVfpcpztWLuP6FttGNfPLJhaZVP/euvujeNYar36OQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "4.1.2", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.2.tgz", + "integrity": "sha512-g7yfUmxYS4mNxk31qbOYsSt2F4m1E02LFqO53Xpzg3zKMhLAPZAjjfyl9e6z7HrW6LvUdTwAQR3HHfLjpko16A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.2", + "@vitest/utils": "4.1.2", + "magic-string": "^0.30.21", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.2.tgz", + "integrity": "sha512-DU4fBnbVCJGNBwVA6xSToNXrkZNSiw59H8tcuUspVMsBDBST4nfvsPsEHDHGtWRRnqBERBQu7TrTKskmjqTXKA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.2.tgz", + "integrity": "sha512-xw2/TiX82lQHA06cgbqRKFb5lCAy3axQ4H4SoUFhUsg+wztiet+co86IAMDtF6Vm1hc7J6j09oh/rgDn+JdKIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.2", + "convert-source-map": "^2.0.0", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, "node_modules/@webcomponents/custom-elements": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/@webcomponents/custom-elements/-/custom-elements-1.6.0.tgz", @@ -1967,24 +2378,63 @@ "dev": true, "license": "Python-2.0" }, - "node_modules/autoprefixer": { - "version": "10.4.27", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.27.tgz", - "integrity": "sha512-NP9APE+tO+LuJGn7/9+cohklunJsXWiaWEfV3si4Gi/XHDwVNgkwr1J3RQYFIvPy76GmJ9/bW8vyoU1LcxwKHA==", + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/autoprefixer" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/ast-v8-to-istanbul": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-1.0.0.tgz", + "integrity": "sha512-1fSfIwuDICFA4LKkCzRPO7F0hzFf0B7+Xqrl27ynQaa+Rh0e1Es0v6kWHPott3lU10AyAr7oKHa65OppjLn3Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.31", + "estree-walker": "^3.0.3", + "js-tokens": "^10.0.0" + } + }, + "node_modules/ast-v8-to-istanbul/node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/ast-v8-to-istanbul/node_modules/js-tokens": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-10.0.0.tgz", + "integrity": "sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/autoprefixer": { + "version": "10.4.27", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.27.tgz", + "integrity": "sha512-NP9APE+tO+LuJGn7/9+cohklunJsXWiaWEfV3si4Gi/XHDwVNgkwr1J3RQYFIvPy76GmJ9/bW8vyoU1LcxwKHA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } ], "license": "MIT", "dependencies": { @@ -2024,6 +2474,16 @@ "node": ">=6.0.0" } }, + "node_modules/bidi-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz", + "integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==", + "dev": true, + "license": "MIT", + "dependencies": { + "require-from-string": "^2.0.2" + } + }, "node_modules/boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", @@ -2121,6 +2581,16 @@ ], "license": "CC-BY-4.0" }, + "node_modules/chai": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", + "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -2210,6 +2680,20 @@ "url": "https://github.com/sponsors/fb55" } }, + "node_modules/css-tree": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.2.1.tgz", + "integrity": "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mdn-data": "2.27.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, "node_modules/css-what": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", @@ -2230,6 +2714,20 @@ "devOptional": true, "license": "MIT" }, + "node_modules/data-urls": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-7.0.0.tgz", + "integrity": "sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-mimetype": "^5.0.0", + "whatwg-url": "^16.0.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", @@ -2248,6 +2746,13 @@ } } }, + "node_modules/decimal.js": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", + "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", + "dev": true, + "license": "MIT" + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -2592,6 +3097,16 @@ "node": ">=0.10.0" } }, + "node_modules/expect-type": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", + "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -2830,6 +3345,26 @@ "he": "bin/he" } }, + "node_modules/html-encoding-sniffer": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-6.0.0.tgz", + "integrity": "sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@exodus/bytes": "^1.6.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true, + "license": "MIT" + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -2900,6 +3435,13 @@ "node": ">=0.12.0" } }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true, + "license": "MIT" + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -2907,13 +3449,51 @@ "dev": true, "license": "ISC" }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/jiti": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", "dev": true, "license": "MIT", - "peer": true, "bin": { "jiti": "lib/jiti-cli.mjs" } @@ -2938,6 +3518,57 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsdom": { + "version": "29.0.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-29.0.1.tgz", + "integrity": "sha512-z6JOK5gRO7aMybVq/y/MlIpKh8JIi68FBKMUtKkK2KH/wMSRlCxQ682d08LB9fYXplyY/UXG8P4XXTScmdjApg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@asamuzakjp/css-color": "^5.0.1", + "@asamuzakjp/dom-selector": "^7.0.3", + "@bramus/specificity": "^2.4.2", + "@csstools/css-syntax-patches-for-csstree": "^1.1.1", + "@exodus/bytes": "^1.15.0", + "css-tree": "^3.2.1", + "data-urls": "^7.0.0", + "decimal.js": "^10.6.0", + "html-encoding-sniffer": "^6.0.0", + "is-potential-custom-element-name": "^1.0.1", + "lru-cache": "^11.2.7", + "parse5": "^8.0.0", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^6.0.1", + "undici": "^7.24.5", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^8.0.1", + "whatwg-mimetype": "^5.0.0", + "whatwg-url": "^16.0.1", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24.0.0" + }, + "peerDependencies": { + "canvas": "^3.0.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsdom/node_modules/lru-cache": { + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.3.2.tgz", + "integrity": "sha512-wgWa6FWQ3QRRJbIjbsldRJZxdxYngT/dO0I5Ynmlnin8qy7tC6xYzbcJjtN4wHLXtkbVwHzk0C+OejVw1XM+DQ==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, "node_modules/jsesc": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", @@ -3028,7 +3659,6 @@ "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", "dev": true, "license": "MPL-2.0", - "peer": true, "dependencies": { "detect-libc": "^2.0.3" }, @@ -3327,6 +3957,54 @@ "@jridgewell/sourcemap-codec": "^1.5.5" } }, + "node_modules/magicast": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.2.tgz", + "integrity": "sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", + "source-map-js": "^1.2.1" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mdn-data": { + "version": "2.27.1", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz", + "integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==", + "dev": true, + "license": "CC0-1.0" + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -3428,6 +4106,17 @@ "url": "https://github.com/fb55/nth-check?sponsor=1" } }, + "node_modules/obug": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", + "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT" + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -3491,6 +4180,32 @@ "node": ">=6" } }, + "node_modules/parse5": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.0.tgz", + "integrity": "sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==", + "dev": true, + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -3649,6 +4364,16 @@ "node": ">=0.10.0" } }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -3720,6 +4445,19 @@ "tslib": "^2.1.0" } }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, + "license": "ISC", + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } + }, "node_modules/scheduler": { "version": "0.27.0", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", @@ -3759,6 +4497,13 @@ "node": ">=8" } }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -3769,6 +4514,20 @@ "node": ">=0.10.0" } }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/std-env": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.0.0.tgz", + "integrity": "sha512-zUMPtQ/HBY3/50VbpkupYHbRroTRZJPRLvreamgErJVys0ceuzMkD44J/QjqhHjOzK42GQ3QZIeFG1OYfOtKqQ==", + "dev": true, + "license": "MIT" + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -3795,6 +4554,13 @@ "node": ">=8" } }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true, + "license": "MIT" + }, "node_modules/tailwindcss": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.2.2.tgz", @@ -3816,6 +4582,23 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.4.tgz", + "integrity": "sha512-u9r3uZC0bdpGOXtlxUIdwf9pkmvhqJdrVCH9fapQtgy/OeTTMZ1nqH7agtvEfmGui6e1XxjcdrlxvxJvc3sMqw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/tinyglobby": { "version": "0.2.15", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", @@ -3865,6 +4648,36 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/tinyrainbow": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.0.tgz", + "integrity": "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tldts": { + "version": "7.0.28", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.28.tgz", + "integrity": "sha512-+Zg3vWhRUv8B1maGSTFdev9mjoo8Etn2Ayfs4cnjlD3CsGkxXX4QyW3j2WJ0wdjYcYmy7Lx2RDsZMhgCWafKIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tldts-core": "^7.0.28" + }, + "bin": { + "tldts": "bin/cli.js" + } + }, + "node_modules/tldts-core": { + "version": "7.0.28", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.28.tgz", + "integrity": "sha512-7W5Efjhsc3chVdFhqtaU0KtK32J37Zcr9RKtID54nG+tIpcY79CQK/veYPODxtD/LJ4Lue66jvrQzIX2Z2/pUQ==", + "dev": true, + "license": "MIT" + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -3878,6 +4691,32 @@ "node": ">=8.0" } }, + "node_modules/tough-cookie": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.1.tgz", + "integrity": "sha512-LktZQb3IeoUWB9lqR5EWTHgW/VTITCXg4D21M+lvybRVdylLrRMnqaIONLVb5mav8vM19m44HIcGq4qASeu2Qw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tldts": "^7.0.5" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/tr46": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-6.0.0.tgz", + "integrity": "sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=20" + } + }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", @@ -3912,6 +4751,16 @@ "node": ">=14.17" } }, + "node_modules/undici": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.24.7.tgz", + "integrity": "sha512-H/nlJ/h0ggGC+uRL3ovD+G0i4bqhvsDOpbDv7At5eFLlj2b41L8QliGbnl2H7SnDiYhENphh1tQFJZf+MyfLsQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, "node_modules/universalify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", @@ -4116,6 +4965,157 @@ "fsevents": "~2.3.2" } }, + "node_modules/vitest": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.2.tgz", + "integrity": "sha512-xjR1dMTVHlFLh98JE3i/f/WePqJsah4A0FK9cc8Ehp9Udk0AZk6ccpIZhh1qJ/yxVWRZ+Q54ocnD8TXmkhspGg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@vitest/expect": "4.1.2", + "@vitest/mocker": "4.1.2", + "@vitest/pretty-format": "4.1.2", + "@vitest/runner": "4.1.2", + "@vitest/snapshot": "4.1.2", + "@vitest/spy": "4.1.2", + "@vitest/utils": "4.1.2", + "es-module-lexer": "^2.0.0", + "expect-type": "^1.3.0", + "magic-string": "^0.30.21", + "obug": "^2.1.1", + "pathe": "^2.0.3", + "picomatch": "^4.0.3", + "std-env": "^4.0.0-rc.1", + "tinybench": "^2.9.0", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.1.0", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.1.2", + "@vitest/browser-preview": "4.1.2", + "@vitest/browser-webdriverio": "4.1.2", + "@vitest/ui": "4.1.2", + "happy-dom": "*", + "jsdom": "*", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@opentelemetry/api": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser-playwright": { + "optional": true + }, + "@vitest/browser-preview": { + "optional": true + }, + "@vitest/browser-webdriverio": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + }, + "vite": { + "optional": false + } + } + }, + "node_modules/vitest/node_modules/es-module-lexer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", + "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", + "dev": true, + "license": "MIT" + }, + "node_modules/vitest/node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/webidl-conversions": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-8.0.1.tgz", + "integrity": "sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=20" + } + }, + "node_modules/whatwg-mimetype": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-5.0.0.tgz", + "integrity": "sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/whatwg-url": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-16.0.1.tgz", + "integrity": "sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@exodus/bytes": "^1.11.0", + "tr46": "^6.0.0", + "webidl-conversions": "^8.0.1" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -4132,6 +5132,23 @@ "node": ">= 8" } }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", @@ -4142,6 +5159,23 @@ "node": ">=0.10.0" } }, + "node_modules/xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true, + "license": "MIT" + }, "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", diff --git a/package.json b/package.json index 83b878d..70458e9 100644 --- a/package.json +++ b/package.json @@ -8,28 +8,34 @@ "dev": "vite", "build": "tsc && vite build", "preview": "vite preview", - "lint": "eslint src/" + "lint": "eslint src/", + "typecheck": "tsc --noEmit", + "test": "vitest", + "test:coverage": "vitest --coverage" }, "dependencies": { + "@phosphor-icons/react": "^2.1.7", + "chroma-js": "^3.1.2", + "gsap": "^3.14.2", "react": "^19.1.0", "react-dom": "^19.1.0", - "zustand": "^5.0.5", - "chroma-js": "^3.1.2", - "@phosphor-icons/react": "^2.1.7", - "gsap": "^3.12.7" + "zustand": "^5.0.5" }, "devDependencies": { - "typescript": "^5.8.3", + "@crxjs/vite-plugin": "^2.0.0-beta.33", + "@tailwindcss/vite": "^4.1.4", + "@types/chroma-js": "^2.4.4", + "@types/chrome": "^0.0.304", "@types/react": "^19.1.2", "@types/react-dom": "^19.1.2", - "@types/chrome": "^0.0.304", - "@types/chroma-js": "^2.4.4", - "vite": "^6.3.2", - "@crxjs/vite-plugin": "^2.0.0-beta.33", "@vitejs/plugin-react": "^4.4.1", - "tailwindcss": "^4.1.4", - "@tailwindcss/vite": "^4.1.4", + "@vitest/coverage-v8": "^4.1.2", "autoprefixer": "^10.4.21", - "eslint": "^9.25.0" + "eslint": "^9.25.0", + "jsdom": "^29.0.1", + "tailwindcss": "^4.1.4", + "typescript": "^5.8.3", + "vite": "^6.3.2", + "vitest": "^4.1.2" } } diff --git a/src/background/service-worker.ts b/src/background/service-worker.ts new file mode 100644 index 0000000..1792bb9 --- /dev/null +++ b/src/background/service-worker.ts @@ -0,0 +1,145 @@ +// PixelLens — Background Service Worker + +import { MessageType } from '@/types/messages' +import type { MessagePayloadMap } from '@/types/messages' + +// Prevent side panel from opening on action click (we control it manually) +chrome.sidePanel.setPanelBehavior({ openPanelOnActionClick: false }) + +// Track inspect mode per tab +const activeTabState = new Map() + +// Handle keyboard shortcuts +chrome.commands.onCommand.addListener(async (command) => { + if (command === 'toggle-inspect') { + const [tab] = await chrome.tabs.query({ active: true, currentWindow: true }) + if (tab?.id) { + toggleInspect(tab.id) + } + } +}) + +interface IncomingMessage { + type: MessageType + payload: unknown +} + +// Message routing between content script <-> side panel +chrome.runtime.onMessage.addListener((message: IncomingMessage, sender, sendResponse) => { + const { type, payload } = message + + switch (type) { + case MessageType.TOGGLE_INSPECT: { + const tabId = sender.tab?.id + if (tabId) { + toggleInspect(tabId) + } + sendResponse({ success: true }) + break + } + + case MessageType.OPEN_SIDE_PANEL: { + handleOpenSidePanel(sender) + sendResponse({ success: true }) + break + } + + case MessageType.ELEMENT_SELECTED: { + // Forward element data to the side panel + chrome.runtime.sendMessage({ + type: MessageType.ELEMENT_SELECTED, + payload, + }).catch(() => { + // Side panel not open yet — ignore + }) + sendResponse({ received: true }) + break + } + + case MessageType.SCAN_PAGE: { + // Forward scan request to content script + forwardToActiveTab(type, payload) + sendResponse({ success: true }) + break + } + + case MessageType.SCAN_PROGRESS: + case MessageType.SCAN_COMPLETE: { + // Forward scan results to the side panel + chrome.runtime.sendMessage({ type, payload }).catch(() => {}) + sendResponse({ success: true }) + break + } + + case MessageType.TOGGLE_GRID: + case MessageType.TOGGLE_MEASURE: { + forwardToActiveTab(type, payload) + sendResponse({ success: true }) + break + } + + case MessageType.GET_PREFERENCES: { + chrome.storage.sync.get('pixellens_preferences', (result) => { + sendResponse(result['pixellens_preferences'] || { + colorFormat: 'hex', + gridSize: 8, + theme: 'dark', + }) + }) + return true // async response + } + + case MessageType.SET_PREFERENCES: { + const prefs = payload as MessagePayloadMap[MessageType.SET_PREFERENCES] + chrome.storage.sync.set({ pixellens_preferences: prefs.preferences }) + sendResponse({ success: true }) + break + } + } +}) + +async function toggleInspect(tabId: number) { + const current = activeTabState.get(tabId) ?? false + const next = !current + activeTabState.set(tabId, next) + + // Update badge + chrome.action.setBadgeText({ + text: next ? 'ON' : '', + tabId, + }) + chrome.action.setBadgeBackgroundColor({ + color: '#6366F1', + tabId, + }) + + // Send toggle to content script + chrome.tabs.sendMessage(tabId, { + type: MessageType.TOGGLE_INSPECT, + payload: { active: next }, + }).catch(() => {}) + + // Open side panel when activating + if (next) { + chrome.sidePanel.open({ tabId }).catch(() => {}) + } +} + +async function forwardToActiveTab(type: MessageType, payload: unknown) { + const [tab] = await chrome.tabs.query({ active: true, currentWindow: true }) + if (tab?.id) { + chrome.tabs.sendMessage(tab.id, { type, payload }).catch(() => {}) + } +} + +async function handleOpenSidePanel(sender: chrome.runtime.MessageSender) { + const tabId = sender.tab?.id + if (tabId) { + chrome.sidePanel.open({ tabId }).catch(() => {}) + } else { + const [tab] = await chrome.tabs.query({ active: true, currentWindow: true }) + if (tab?.id) { + chrome.sidePanel.open({ tabId: tab.id }).catch(() => {}) + } + } +} diff --git a/src/content/index.ts b/src/content/index.ts new file mode 100644 index 0000000..e29b92b --- /dev/null +++ b/src/content/index.ts @@ -0,0 +1,237 @@ +// PixelLens — Content Script Entry Point + +import { onMessage } from '@/lib/messaging' +import { MessageType } from '@/types/messages' +import { ElementHighlighter } from './inspector/ElementHighlighter' +import { ElementSelector } from './inspector/ElementSelector' +import { DistanceMeasurer } from './inspector/DistanceMeasurer' +import { GridOverlay } from './inspector/GridOverlay' +import { PageScanner } from './scanner/PageScanner' +import { sendMessage } from '@/lib/messaging' + +type ContentMode = 'off' | 'inspect' | 'measure' | 'grid' + +let currentMode: ContentMode = 'off' +let highlighter: ElementHighlighter | null = null +let selector: ElementSelector | null = null +let measurer: DistanceMeasurer | null = null +let gridOverlay: GridOverlay | null = null +let scanner: PageScanner | null = null +let shadowHost: HTMLElement | null = null +let contentRoot: ShadowRoot | null = null + +function ensureShadowDOM(): ShadowRoot { + if (contentRoot) return contentRoot + + shadowHost = document.createElement('div') + shadowHost.id = 'pixellens-host' + shadowHost.style.cssText = 'all: initial; position: fixed; z-index: 2147483647; top: 0; left: 0; width: 0; height: 0; pointer-events: none;' + document.documentElement.appendChild(shadowHost) + + contentRoot = shadowHost.attachShadow({ mode: 'open' }) + + const style = document.createElement('style') + style.textContent = getContentStyles() + contentRoot.appendChild(style) + + return contentRoot +} + +function setMode(mode: ContentMode) { + // Cleanup previous mode + if (currentMode === 'inspect') { + highlighter?.destroy() + selector?.destroy() + highlighter = null + selector = null + } else if (currentMode === 'measure') { + measurer?.destroy() + measurer = null + } + + currentMode = mode + + // Setup new mode + if (mode === 'inspect') { + highlighter = new ElementHighlighter(ensureShadowDOM()) + selector = new ElementSelector(ensureShadowDOM()) + highlighter.enable() + selector.enable() + } else if (mode === 'measure') { + measurer = new DistanceMeasurer(ensureShadowDOM()) + measurer.enable() + } + + updateToolbarMode(mode) +} + +function updateToolbarMode(_mode: ContentMode) { + // Toolbar will read this via a custom event + document.dispatchEvent(new CustomEvent('pixellens:mode-change', { detail: { mode: _mode } })) +} + +// --- Message listeners --- + +onMessage(MessageType.TOGGLE_INSPECT, (payload) => { + if (payload.active) { + setMode('inspect') + } else { + setMode('off') + } +}) + +onMessage(MessageType.TOGGLE_MEASURE, (payload) => { + if (payload.active) { + setMode('measure') + } else { + setMode('off') + } +}) + +onMessage(MessageType.TOGGLE_GRID, (payload) => { + if (!gridOverlay) { + gridOverlay = new GridOverlay(ensureShadowDOM()) + } + if (payload.visible) { + gridOverlay.show(payload.size) + } else { + gridOverlay.hide() + } +}) + +onMessage(MessageType.SCAN_PAGE, (_payload, _sender, sendResponse) => { + if (!scanner) { + scanner = new PageScanner() + } + + scanner.scan((progress, phase) => { + sendMessage(MessageType.SCAN_PROGRESS, { progress, phase }) + }).then((designSystem) => { + sendMessage(MessageType.SCAN_COMPLETE, { designSystem }) + }) + + // Return true to keep the message channel open for async response + return true +}) + +// --- Mount UI --- + +function mountUI() { + const root = ensureShadowDOM() + + // Create toolbar container + const toolbarContainer = document.createElement('div') + toolbarContainer.id = 'pixellens-toolbar-root' + toolbarContainer.style.cssText = 'position: fixed; bottom: 24px; left: 50%; transform: translateX(-50%); z-index: 2147483647; pointer-events: auto;' + root.appendChild(toolbarContainer) + + // Dynamic import for React UI — loaded only when needed + import('./ui/ContentApp').then(({ mountContentApp }) => { + mountContentApp(toolbarContainer) + }) +} + +// --- Inline critical styles for overlays (non-React) --- + +function getContentStyles(): string { + return ` + .pixellens-overlay-content { + position: absolute; + background: rgba(59, 130, 246, 0.15); + pointer-events: none; + transition: opacity 100ms ease-out; + z-index: 2147483645; + } + .pixellens-overlay-padding { + position: absolute; + background: rgba(34, 197, 94, 0.15); + pointer-events: none; + transition: opacity 100ms ease-out; + z-index: 2147483644; + } + .pixellens-overlay-margin { + position: absolute; + background: rgba(249, 115, 22, 0.15); + pointer-events: none; + transition: opacity 100ms ease-out; + z-index: 2147483643; + } + .pixellens-badge { + position: absolute; + background: rgba(0, 0, 0, 0.85); + color: #EDEDEF; + font-family: 'JetBrains Mono', monospace; + font-size: 11px; + padding: 2px 6px; + border-radius: 4px; + white-space: nowrap; + pointer-events: none; + z-index: 2147483646; + } + .pixellens-pulse-ring { + position: absolute; + border: 2px solid #6366F1; + border-radius: 4px; + pointer-events: none; + animation: pixellens-pulse 0.6s ease-out forwards; + z-index: 2147483646; + } + @keyframes pixellens-pulse { + 0% { opacity: 1; transform: scale(1); } + 100% { opacity: 0; transform: scale(1.08); } + } + .pixellens-measure-line { + position: absolute; + pointer-events: none; + z-index: 2147483646; + } + .pixellens-measure-label { + position: absolute; + background: rgba(0, 0, 0, 0.85); + color: #EDEDEF; + font-family: 'JetBrains Mono', monospace; + font-size: 11px; + padding: 2px 8px; + border-radius: 4px; + white-space: nowrap; + pointer-events: none; + z-index: 2147483647; + } + .pixellens-measure-outline { + position: absolute; + border: 1px dashed #6366F1; + border-radius: 2px; + pointer-events: none; + z-index: 2147483644; + } + .pixellens-grid-canvas { + position: fixed; + top: 0; + left: 0; + width: 100vw; + height: 100vh; + pointer-events: none; + z-index: 2147483640; + } + .pixellens-tooltip { + position: fixed; + background: rgba(12, 12, 14, 0.95); + color: #EDEDEF; + font-family: 'JetBrains Mono', monospace; + font-size: 11px; + padding: 4px 8px; + border-radius: 6px; + box-shadow: 0 4px 12px rgba(0,0,0,0.4); + pointer-events: none; + z-index: 2147483647; + opacity: 0; + transition: opacity 100ms ease-out; + } + .pixellens-tooltip.visible { + opacity: 1; + } + ` +} + +// Auto-init +mountUI() diff --git a/src/content/inspector/DistanceMeasurer.ts b/src/content/inspector/DistanceMeasurer.ts new file mode 100644 index 0000000..ed18a85 --- /dev/null +++ b/src/content/inspector/DistanceMeasurer.ts @@ -0,0 +1,187 @@ +// PixelLens — Distance Measurer (click two elements to measure distance) + +import { isPixelLensElement } from '@/lib/dom-utils' + +type MeasureState = 'IDLE' | 'FIRST_SELECTED' | 'MEASURING' + +export class DistanceMeasurer { + private root: ShadowRoot + private state: MeasureState = 'IDLE' + private elementA: Element | null = null + private elementB: Element | null = null + private outlineA: HTMLDivElement | null = null + private outlineB: HTMLDivElement | null = null + private svgOverlay: SVGSVGElement | null = null + private measureLabel: HTMLDivElement | null = null + private guideH: HTMLDivElement | null = null + private guideV: HTMLDivElement | null = null + private enabled = false + + private onClick = (e: MouseEvent) => this.handleClick(e) + private onScroll = () => this.updateVisuals() + + constructor(root: ShadowRoot) { + this.root = root + } + + enable(): void { + if (this.enabled) return + this.enabled = true + document.addEventListener('click', this.onClick, true) + window.addEventListener('scroll', this.onScroll, { passive: true }) + window.addEventListener('resize', this.onScroll, { passive: true }) + } + + destroy(): void { + this.enabled = false + document.removeEventListener('click', this.onClick, true) + window.removeEventListener('scroll', this.onScroll) + window.removeEventListener('resize', this.onScroll) + this.reset() + } + + private handleClick(e: MouseEvent): void { + const target = e.target as Element + if (!target || isPixelLensElement(target)) return + + e.preventDefault() + e.stopPropagation() + e.stopImmediatePropagation() + + if (this.state === 'IDLE') { + this.elementA = target + this.outlineA = this.createOutline(target) + this.state = 'FIRST_SELECTED' + } else if (this.state === 'FIRST_SELECTED') { + this.elementB = target + this.outlineB = this.createOutline(target) + this.state = 'MEASURING' + this.drawMeasurement() + } else { + // Click elsewhere: reset + this.reset() + } + } + + private createOutline(el: Element): HTMLDivElement { + const rect = el.getBoundingClientRect() + const outline = document.createElement('div') + outline.className = 'pixellens-measure-outline' + outline.style.left = `${rect.left + window.scrollX}px` + outline.style.top = `${rect.top + window.scrollY}px` + outline.style.width = `${rect.width}px` + outline.style.height = `${rect.height}px` + this.root.appendChild(outline) + return outline + } + + private drawMeasurement(): void { + if (!this.elementA || !this.elementB) return + + const rectA = this.elementA.getBoundingClientRect() + const rectB = this.elementB.getBoundingClientRect() + + const centerAx = rectA.left + rectA.width / 2 + const centerAy = rectA.top + rectA.height / 2 + const centerBx = rectB.left + rectB.width / 2 + const centerBy = rectB.top + rectB.height / 2 + + const distance = Math.round(Math.hypot(centerBx - centerAx, centerBy - centerAy)) + + // SVG line with dash animation + this.svgOverlay = document.createElementNS('http://www.w3.org/2000/svg', 'svg') + this.svgOverlay.setAttribute('class', 'pixellens-measure-line') + this.svgOverlay.style.cssText = `position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; pointer-events: none; z-index: 2147483646;` + + const line = document.createElementNS('http://www.w3.org/2000/svg', 'line') + line.setAttribute('x1', String(centerAx)) + line.setAttribute('y1', String(centerAy)) + line.setAttribute('x2', String(centerBx)) + line.setAttribute('y2', String(centerBy)) + line.setAttribute('stroke', '#EF4444') + line.setAttribute('stroke-width', '1.5') + line.setAttribute('stroke-dasharray', '6 4') + + // Dash offset animation + const totalLen = Math.hypot(centerBx - centerAx, centerBy - centerAy) + line.setAttribute('stroke-dashoffset', String(totalLen)) + + const animate = document.createElementNS('http://www.w3.org/2000/svg', 'animate') + animate.setAttribute('attributeName', 'stroke-dashoffset') + animate.setAttribute('from', String(totalLen)) + animate.setAttribute('to', '0') + animate.setAttribute('dur', '0.4s') + animate.setAttribute('fill', 'freeze') + line.appendChild(animate) + + this.svgOverlay.appendChild(line) + this.root.appendChild(this.svgOverlay) + + // Distance label at midpoint + const midX = (centerAx + centerBx) / 2 + const midY = (centerAy + centerBy) / 2 + + this.measureLabel = document.createElement('div') + this.measureLabel.className = 'pixellens-measure-label' + this.measureLabel.textContent = `${distance}px` + this.measureLabel.style.left = `${midX + window.scrollX + 8}px` + this.measureLabel.style.top = `${midY + window.scrollY - 10}px` + this.root.appendChild(this.measureLabel) + + // Guides — horizontal and vertical dashed lines + const dx = Math.abs(centerBx - centerAx) + const dy = Math.abs(centerBy - centerAy) + + if (dx > 4) { + this.guideH = document.createElement('div') + this.guideH.style.cssText = `position: fixed; height: 0; border-top: 1px dashed rgba(239,68,68,0.4); pointer-events: none; z-index: 2147483645;` + this.guideH.style.left = `${Math.min(centerAx, centerBx)}px` + this.guideH.style.top = `${centerAy}px` + this.guideH.style.width = `${dx}px` + this.root.appendChild(this.guideH) + } + + if (dy > 4) { + this.guideV = document.createElement('div') + this.guideV.style.cssText = `position: fixed; width: 0; border-left: 1px dashed rgba(239,68,68,0.4); pointer-events: none; z-index: 2147483645;` + this.guideV.style.left = `${centerBx}px` + this.guideV.style.top = `${Math.min(centerAy, centerBy)}px` + this.guideV.style.height = `${dy}px` + this.root.appendChild(this.guideV) + } + } + + private updateVisuals(): void { + if (this.state === 'MEASURING' && this.elementA && this.elementB) { + this.clearVisuals() + this.outlineA = this.createOutline(this.elementA) + this.outlineB = this.createOutline(this.elementB) + this.drawMeasurement() + } else if (this.state === 'FIRST_SELECTED' && this.elementA) { + this.outlineA?.remove() + this.outlineA = this.createOutline(this.elementA) + } + } + + private clearVisuals(): void { + this.outlineA?.remove() + this.outlineB?.remove() + this.svgOverlay?.remove() + this.measureLabel?.remove() + this.guideH?.remove() + this.guideV?.remove() + this.outlineA = null + this.outlineB = null + this.svgOverlay = null + this.measureLabel = null + this.guideH = null + this.guideV = null + } + + private reset(): void { + this.clearVisuals() + this.elementA = null + this.elementB = null + this.state = 'IDLE' + } +} diff --git a/src/content/inspector/ElementHighlighter.ts b/src/content/inspector/ElementHighlighter.ts new file mode 100644 index 0000000..a4bc5bf --- /dev/null +++ b/src/content/inspector/ElementHighlighter.ts @@ -0,0 +1,193 @@ +// PixelLens — Element Highlighter (hover overlay for padding/margin/content) + +import { getBoxModel, isPixelLensElement } from '@/lib/dom-utils' + +interface OverlayElements { + content: HTMLDivElement + paddingTop: HTMLDivElement + paddingRight: HTMLDivElement + paddingBottom: HTMLDivElement + paddingLeft: HTMLDivElement + marginTop: HTMLDivElement + marginRight: HTMLDivElement + marginBottom: HTMLDivElement + marginLeft: HTMLDivElement + badge: HTMLDivElement +} + +export class ElementHighlighter { + private root: ShadowRoot + private overlays: OverlayElements | null = null + private container: HTMLDivElement | null = null + private currentElement: Element | null = null + private rafId: number | null = null + private enabled = false + + private onMouseOver = (e: MouseEvent) => this.handleMouseOver(e) + private onMouseOut = () => this.handleMouseOut() + private onScroll = () => this.update() + + constructor(root: ShadowRoot) { + this.root = root + } + + enable(): void { + if (this.enabled) return + this.enabled = true + this.createOverlays() + document.addEventListener('mouseover', this.onMouseOver, true) + document.addEventListener('mouseout', this.onMouseOut, true) + window.addEventListener('scroll', this.onScroll, { passive: true }) + window.addEventListener('resize', this.onScroll, { passive: true }) + } + + destroy(): void { + this.enabled = false + document.removeEventListener('mouseover', this.onMouseOver, true) + document.removeEventListener('mouseout', this.onMouseOut, true) + window.removeEventListener('scroll', this.onScroll) + window.removeEventListener('resize', this.onScroll) + if (this.rafId !== null) cancelAnimationFrame(this.rafId) + this.container?.remove() + this.container = null + this.overlays = null + this.currentElement = null + } + + private createOverlays(): void { + this.container = document.createElement('div') + this.container.style.cssText = 'position: absolute; top: 0; left: 0; pointer-events: none;' + + const make = (className: string): HTMLDivElement => { + const div = document.createElement('div') + div.className = className + div.style.opacity = '0' + this.container!.appendChild(div) + return div + } + + this.overlays = { + content: make('pixellens-overlay-content'), + paddingTop: make('pixellens-overlay-padding'), + paddingRight: make('pixellens-overlay-padding'), + paddingBottom: make('pixellens-overlay-padding'), + paddingLeft: make('pixellens-overlay-padding'), + marginTop: make('pixellens-overlay-margin'), + marginRight: make('pixellens-overlay-margin'), + marginBottom: make('pixellens-overlay-margin'), + marginLeft: make('pixellens-overlay-margin'), + badge: make('pixellens-badge'), + } + + this.root.appendChild(this.container) + } + + private handleMouseOver(e: MouseEvent): void { + const target = e.target as Element + if (!target || target === document.documentElement || target === document.body) return + // Ignore our own overlays + if (isPixelLensElement(target)) return + + this.currentElement = target + this.update() + } + + private handleMouseOut(): void { + this.currentElement = null + this.hideOverlays() + } + + private update(): void { + if (this.rafId !== null) cancelAnimationFrame(this.rafId) + this.rafId = requestAnimationFrame(() => { + this.rafId = null + if (!this.currentElement || !this.overlays) return + this.positionOverlays(this.currentElement) + }) + } + + private positionOverlays(el: Element): void { + if (!this.overlays) return + + const rect = el.getBoundingClientRect() + const boxModel = getBoxModel(el) + + const mt = parseFloat(boxModel.margin.top) || 0 + const mr = parseFloat(boxModel.margin.right) || 0 + const mb = parseFloat(boxModel.margin.bottom) || 0 + const ml = parseFloat(boxModel.margin.left) || 0 + + const pt = parseFloat(boxModel.padding.top) || 0 + const pr = parseFloat(boxModel.padding.right) || 0 + const pb = parseFloat(boxModel.padding.bottom) || 0 + const pl = parseFloat(boxModel.padding.left) || 0 + + const bt = parseFloat(boxModel.border.top) || 0 + const br = parseFloat(boxModel.border.right) || 0 + const bb = parseFloat(boxModel.border.bottom) || 0 + const bl = parseFloat(boxModel.border.left) || 0 + + const scrollX = window.scrollX + const scrollY = window.scrollY + + // Content area (inside padding + border) + const contentX = rect.left + scrollX + bl + pl + const contentY = rect.top + scrollY + bt + pt + const contentW = rect.width - bl - br - pl - pr + const contentH = rect.height - bt - bb - pt - pb + + this.setRect(this.overlays.content, contentX, contentY, Math.max(0, contentW), Math.max(0, contentH)) + + // Padding overlays (4 strips around content) + // Top padding + this.setRect(this.overlays.paddingTop, rect.left + scrollX + bl, rect.top + scrollY + bt, rect.width - bl - br, pt) + // Right padding + this.setRect(this.overlays.paddingRight, rect.left + scrollX + rect.width - br - pr, rect.top + scrollY + bt + pt, pr, Math.max(0, contentH)) + // Bottom padding + this.setRect(this.overlays.paddingBottom, rect.left + scrollX + bl, rect.top + scrollY + rect.height - bb - pb, rect.width - bl - br, pb) + // Left padding + this.setRect(this.overlays.paddingLeft, rect.left + scrollX + bl, rect.top + scrollY + bt + pt, pl, Math.max(0, contentH)) + + // Margin overlays (4 strips outside border) + // Top margin + this.setRect(this.overlays.marginTop, rect.left + scrollX - ml, rect.top + scrollY - mt, rect.width + ml + mr, mt) + // Right margin + this.setRect(this.overlays.marginRight, rect.left + scrollX + rect.width, rect.top + scrollY, mr, rect.height) + // Bottom margin + this.setRect(this.overlays.marginBottom, rect.left + scrollX - ml, rect.top + scrollY + rect.height, rect.width + ml + mr, mb) + // Left margin + this.setRect(this.overlays.marginLeft, rect.left + scrollX - ml, rect.top + scrollY, ml, rect.height) + + // Badge: show dimensions at top-right corner of the element + const w = Math.round(rect.width) + const h = Math.round(rect.height) + this.overlays.badge.textContent = `${w} × ${h}` + this.setRect(this.overlays.badge, rect.left + scrollX + rect.width + 4, rect.top + scrollY - 2, NaN, NaN) + this.overlays.badge.style.width = 'auto' + this.overlays.badge.style.height = 'auto' + + // Show all + this.showOverlays() + } + + private setRect(el: HTMLDivElement, x: number, y: number, w: number, h: number): void { + el.style.left = `${x}px` + el.style.top = `${y}px` + if (!isNaN(w)) el.style.width = `${w}px` + if (!isNaN(h)) el.style.height = `${h}px` + } + + private showOverlays(): void { + if (!this.overlays) return + for (const el of Object.values(this.overlays)) { + el.style.opacity = '1' + } + } + + private hideOverlays(): void { + if (!this.overlays) return + for (const el of Object.values(this.overlays)) { + el.style.opacity = '0' + } + } +} diff --git a/src/content/inspector/ElementSelector.ts b/src/content/inspector/ElementSelector.ts new file mode 100644 index 0000000..4eab0f6 --- /dev/null +++ b/src/content/inspector/ElementSelector.ts @@ -0,0 +1,60 @@ +// PixelLens — Element Selector (click to select and capture computed styles) + +import { getFullComputedStyles, isPixelLensElement } from '@/lib/dom-utils' +import { sendMessage } from '@/lib/messaging' +import { MessageType } from '@/types/messages' + +export class ElementSelector { + private root: ShadowRoot + private enabled = false + + private onClick = (e: MouseEvent) => this.handleClick(e) + + constructor(root: ShadowRoot) { + this.root = root + } + + enable(): void { + if (this.enabled) return + this.enabled = true + document.addEventListener('click', this.onClick, true) + } + + destroy(): void { + this.enabled = false + document.removeEventListener('click', this.onClick, true) + } + + private handleClick(e: MouseEvent): void { + const target = e.target as Element + if (!target || isPixelLensElement(target)) return + + // Prevent default navigation/action + e.preventDefault() + e.stopPropagation() + e.stopImmediatePropagation() + + // Pulse ring animation on the clicked element + this.showPulseRing(target) + + // Capture full computed styles + const inspectedElement = getFullComputedStyles(target) + + // Send to background → side panel + sendMessage(MessageType.ELEMENT_SELECTED, { element: inspectedElement }) + } + + private showPulseRing(el: Element): void { + const rect = el.getBoundingClientRect() + const ring = document.createElement('div') + ring.className = 'pixellens-pulse-ring' + ring.style.left = `${rect.left + window.scrollX}px` + ring.style.top = `${rect.top + window.scrollY}px` + ring.style.width = `${rect.width}px` + ring.style.height = `${rect.height}px` + + this.root.appendChild(ring) + + ring.addEventListener('animationend', () => ring.remove()) + } +} diff --git a/src/content/inspector/GridOverlay.ts b/src/content/inspector/GridOverlay.ts new file mode 100644 index 0000000..121c329 --- /dev/null +++ b/src/content/inspector/GridOverlay.ts @@ -0,0 +1,108 @@ +// PixelLens — Grid Overlay (configurable grid lines over the page) + +export class GridOverlay { + private root: ShadowRoot + private canvas: HTMLCanvasElement | null = null + private ctx: CanvasRenderingContext2D | null = null + private gridSize = 8 + private visible = false + private rafId: number | null = null + + private onScroll = () => this.scheduleRedraw() + private onResize = () => this.handleResize() + + constructor(root: ShadowRoot) { + this.root = root + } + + show(size?: number): void { + if (size) this.gridSize = size + if (!this.canvas) this.createCanvas() + this.visible = true + this.canvas!.style.display = 'block' + this.draw() + window.addEventListener('scroll', this.onScroll, { passive: true }) + window.addEventListener('resize', this.onResize, { passive: true }) + } + + hide(): void { + this.visible = false + if (this.canvas) this.canvas.style.display = 'none' + window.removeEventListener('scroll', this.onScroll) + window.removeEventListener('resize', this.onResize) + if (this.rafId !== null) cancelAnimationFrame(this.rafId) + } + + setGridSize(size: number): void { + this.gridSize = size + if (this.visible) this.draw() + } + + destroy(): void { + this.hide() + this.canvas?.remove() + this.canvas = null + this.ctx = null + } + + private createCanvas(): void { + this.canvas = document.createElement('canvas') + this.canvas.className = 'pixellens-grid-canvas' + this.canvas.style.display = 'none' + this.root.appendChild(this.canvas) + this.ctx = this.canvas.getContext('2d') + this.handleResize() + } + + private handleResize(): void { + if (!this.canvas) return + const dpr = window.devicePixelRatio || 1 + this.canvas.width = window.innerWidth * dpr + this.canvas.height = window.innerHeight * dpr + this.canvas.style.width = `${window.innerWidth}px` + this.canvas.style.height = `${window.innerHeight}px` + if (this.ctx) this.ctx.scale(dpr, dpr) + if (this.visible) this.draw() + } + + private scheduleRedraw(): void { + if (this.rafId !== null) return + this.rafId = requestAnimationFrame(() => { + this.rafId = null + this.draw() + }) + } + + private draw(): void { + if (!this.ctx || !this.canvas) return + const w = window.innerWidth + const h = window.innerHeight + const dpr = window.devicePixelRatio || 1 + + this.ctx.clearRect(0, 0, w * dpr, h * dpr) + this.ctx.resetTransform() + this.ctx.scale(dpr, dpr) + + const offsetX = window.scrollX % this.gridSize + const offsetY = window.scrollY % this.gridSize + + this.ctx.strokeStyle = 'rgba(99, 102, 241, 0.05)' + this.ctx.lineWidth = 0.5 + + this.ctx.beginPath() + + // Vertical lines + for (let x = -offsetX; x <= w; x += this.gridSize) { + this.ctx.moveTo(x, 0) + this.ctx.lineTo(x, h) + } + + // Horizontal lines + for (let y = -offsetY; y <= h; y += this.gridSize) { + this.ctx.moveTo(0, y) + this.ctx.lineTo(w, y) + } + + this.ctx.stroke() + } +} diff --git a/src/content/scanner/ColorExtractor.ts b/src/content/scanner/ColorExtractor.ts new file mode 100644 index 0000000..74952f0 --- /dev/null +++ b/src/content/scanner/ColorExtractor.ts @@ -0,0 +1,57 @@ +// PixelLens — Color Extractor (extract and cluster colors from the page) + +import { toHex, toRgb, toHsl, isTransparent, clusterColors, classifyColors } from '@/lib/colors' +import type { ColorToken } from '@/types/design-system' + +const COLOR_PROPS = ['color', 'background-color', 'border-color', 'outline-color'] as const + +const SKIP_VALUES = new Set([ + 'transparent', 'rgba(0, 0, 0, 0)', 'inherit', 'initial', 'currentcolor', +]) + +export class ColorExtractor { + extract(elements: Element[]): ColorToken[] { + const freqMap = new Map() + + for (const el of elements) { + const computed = window.getComputedStyle(el) + + for (const prop of COLOR_PROPS) { + const value = computed.getPropertyValue(prop) + if (!value || SKIP_VALUES.has(value.toLowerCase())) continue + if (isTransparent(value)) continue + + let hex: string + try { + hex = toHex(value) + } catch { + continue + } + + freqMap.set(hex, (freqMap.get(hex) || 0) + 1) + } + } + + // Convert to array for clustering + const rawColors = Array.from(freqMap.entries()).map(([hex, frequency]) => ({ + hex, + frequency, + })) + + // Cluster similar colors (deltaE < 5) + const clustered = clusterColors(rawColors, 5) + + // Build ColorToken array + const tokens: ColorToken[] = clustered.map((c) => ({ + name: '', + hex: c.hex, + rgb: toRgb(c.hex), + hsl: toHsl(c.hex), + frequency: c.frequency, + category: 'accent' as const, + })) + + // Classify into primary/secondary/neutral/bg/text + return classifyColors(tokens) + } +} diff --git a/src/content/scanner/DesignSystemBuilder.ts b/src/content/scanner/DesignSystemBuilder.ts new file mode 100644 index 0000000..2daba9e --- /dev/null +++ b/src/content/scanner/DesignSystemBuilder.ts @@ -0,0 +1,103 @@ +// PixelLens — Design System Builder (assemble all extraction results) + +import type { + DesignSystem, + ColorToken, + TypographyToken, + SpacingToken, + ShadowToken, + ShadowParsed, + BorderRadiusToken, +} from '@/types/design-system' + +export class DesignSystemBuilder { + build( + colors: ColorToken[], + typography: TypographyToken[], + spacing: SpacingToken[], + elements: Element[], + ): DesignSystem { + const shadows = this.extractShadows(elements) + const borderRadius = this.extractBorderRadius(elements) + + return { + colors, + typography, + spacing, + shadows, + borderRadius, + metadata: { + url: window.location.href, + title: document.title, + scannedAt: new Date().toISOString(), + }, + } + } + + private extractShadows(elements: Element[]): ShadowToken[] { + const shadowSet = new Map() + + for (const el of elements) { + const computed = window.getComputedStyle(el) + const shadow = computed.getPropertyValue('box-shadow') + + if (!shadow || shadow === 'none') continue + + // Deduplicate by raw value + if (shadowSet.has(shadow)) continue + + const parsed = this.parseShadow(shadow) + if (parsed) { + shadowSet.set(shadow, { value: shadow, parsed }) + } + } + + return Array.from(shadowSet.values()) + } + + private parseShadow(shadow: string): ShadowParsed | null { + // Basic shadow parsing: + // Computed values always resolve to rgb() format + const rgbMatch = shadow.match(/(rgba?\([^)]+\))\s+(-?[\d.]+px)\s+(-?[\d.]+px)\s+([\d.]+px)\s*([\d.]+px)?/) + if (rgbMatch) { + return { + color: rgbMatch[1], + x: rgbMatch[2], + y: rgbMatch[3], + blur: rgbMatch[4], + spread: rgbMatch[5] || '0px', + } + } + + // Alternate order: offsets first then color + const altMatch = shadow.match(/(-?[\d.]+px)\s+(-?[\d.]+px)\s+([\d.]+px)\s*([\d.]+px)?\s+(rgba?\([^)]+\))/) + if (altMatch) { + return { + x: altMatch[1], + y: altMatch[2], + blur: altMatch[3], + spread: altMatch[4] || '0px', + color: altMatch[5], + } + } + + return null + } + + private extractBorderRadius(elements: Element[]): BorderRadiusToken[] { + const freqMap = new Map() + + for (const el of elements) { + const computed = window.getComputedStyle(el) + const br = computed.getPropertyValue('border-radius') + + if (!br || br === '0px') continue + + freqMap.set(br, (freqMap.get(br) || 0) + 1) + } + + return Array.from(freqMap.entries()) + .map(([value, frequency]) => ({ value, frequency })) + .sort((a, b) => b.frequency - a.frequency) + } +} diff --git a/src/content/scanner/PageScanner.ts b/src/content/scanner/PageScanner.ts new file mode 100644 index 0000000..cf200df --- /dev/null +++ b/src/content/scanner/PageScanner.ts @@ -0,0 +1,74 @@ +// PixelLens — Page Scanner (orchestrates full page scan) + +import { getVisibleElements } from '@/lib/dom-utils' +import { ColorExtractor } from './ColorExtractor' +import { TypographyExtractor } from './TypographyExtractor' +import { SpacingExtractor } from './SpacingExtractor' +import { DesignSystemBuilder } from './DesignSystemBuilder' +import type { DesignSystem, ColorToken, TypographyToken, SpacingToken } from '@/types/design-system' + +type ProgressCallback = (percent: number, phase: string) => void + +export class PageScanner { + private colorExtractor = new ColorExtractor() + private typographyExtractor = new TypographyExtractor() + private spacingExtractor = new SpacingExtractor() + private builder = new DesignSystemBuilder() + + async scan(onProgress?: ProgressCallback): Promise { + // Phase 1: DOM traversal + onProgress?.(5, 'Scanning DOM elements...') + const elements = getVisibleElements() + onProgress?.(15, `Found ${elements.length} elements`) + + // Yield to main thread between heavy phases + await this.yieldFrame() + + // Phase 2: Color extraction + onProgress?.(20, 'Extracting colors...') + let colors: ColorToken[] + try { + colors = this.colorExtractor.extract(elements) + } catch { + colors = [] + } + onProgress?.(45, `Found ${colors.length} colors`) + + await this.yieldFrame() + + // Phase 3: Typography extraction + onProgress?.(50, 'Extracting typography...') + let typography: TypographyToken[] + try { + typography = this.typographyExtractor.extract(elements) + } catch { + typography = [] + } + onProgress?.(65, `Found ${typography.length} font families`) + + await this.yieldFrame() + + // Phase 4: Spacing extraction + onProgress?.(70, 'Extracting spacing...') + let spacing: SpacingToken[] + try { + spacing = this.spacingExtractor.extract(elements) + } catch { + spacing = [] + } + onProgress?.(85, `Found ${spacing.length} spacing values`) + + await this.yieldFrame() + + // Phase 5: Build design system (includes shadow + border-radius) + onProgress?.(90, 'Building design system...') + const designSystem = this.builder.build(colors, typography, spacing, elements) + onProgress?.(100, 'Scan complete') + + return designSystem + } + + private yieldFrame(): Promise { + return new Promise((resolve) => requestAnimationFrame(() => resolve())) + } +} diff --git a/src/content/scanner/SpacingExtractor.ts b/src/content/scanner/SpacingExtractor.ts new file mode 100644 index 0000000..bdffea9 --- /dev/null +++ b/src/content/scanner/SpacingExtractor.ts @@ -0,0 +1,112 @@ +// PixelLens — Spacing Extractor (extract spacing patterns from the page) + +import type { SpacingToken } from '@/types/design-system' + +const SPACING_PROPS = [ + 'margin-top', 'margin-right', 'margin-bottom', 'margin-left', + 'padding-top', 'padding-right', 'padding-bottom', 'padding-left', +] as const + +export class SpacingExtractor { + extract(elements: Element[]): SpacingToken[] { + const freqMap = new Map() + + for (const el of elements) { + const computed = window.getComputedStyle(el) + + for (const prop of SPACING_PROPS) { + const raw = computed.getPropertyValue(prop) + const px = parseFloat(raw) + if (isNaN(px) || px === 0) continue + + // Round to nearest even number + const rounded = this.roundSpacing(Math.abs(px)) + if (rounded === 0) continue + + freqMap.set(rounded, (freqMap.get(rounded) || 0) + 1) + } + } + + // Detect base unit + const baseUnit = this.detectBaseUnit(freqMap) + + // Build spacing scale from base unit + const multipliers = [0.5, 1, 1.5, 2, 3, 4, 6, 8, 12, 16] + const scaleValues = new Set(multipliers.map((m) => Math.round(baseUnit * m))) + + // Collect all values sorted by frequency + const allValues = Array.from(freqMap.entries()) + .sort((a, b) => b[1] - a[1]) + + const tokens: SpacingToken[] = [] + const seen = new Set() + + // First add scale values that appear in the data + for (const scaleVal of scaleValues) { + const freq = freqMap.get(scaleVal) || 0 + if (freq > 0 && !seen.has(scaleVal)) { + seen.add(scaleVal) + tokens.push({ + value: `${scaleVal}px`, + frequency: freq, + label: this.getLabel(scaleVal, baseUnit), + }) + } + } + + // Then add top non-scale values + for (const [val, freq] of allValues) { + if (seen.has(val)) continue + if (tokens.length >= 16) break + seen.add(val) + tokens.push({ + value: `${val}px`, + frequency: freq, + label: `space-${val}`, + }) + } + + tokens.sort((a, b) => parseFloat(a.value) - parseFloat(b.value)) + return tokens + } + + private roundSpacing(px: number): number { + // Round to nearest multiple of 2 + return Math.round(px / 2) * 2 + } + + private detectBaseUnit(freqMap: Map): number { + // Check frequency of common base units (4 and 8) + const freq4 = freqMap.get(4) || 0 + const freq8 = freqMap.get(8) || 0 + + // Count how many values are multiples of 8 vs 4 + let multOf8 = 0 + let multOf4 = 0 + let total = 0 + + for (const [val, freq] of freqMap) { + total += freq + if (val % 8 === 0) multOf8 += freq + if (val % 4 === 0) multOf4 += freq + } + + // If >60% of values are multiples of 8, base is 8 + if (total > 0 && multOf8 / total > 0.6) return 8 + // If >60% of values are multiples of 4, base is 4 + if (total > 0 && multOf4 / total > 0.6) return 4 + + // Fallback: whichever of 4 or 8 is more frequent + return freq8 >= freq4 ? 8 : 4 + } + + private getLabel(value: number, base: number): string { + const ratio = value / base + // Clean ratio labels + if (ratio === 0.5) return `space-${base}-half` + if (ratio === 1) return `space-${base}` + if (ratio === 1.5) return `space-${base}-1half` + if (Number.isInteger(ratio)) return `space-${base}-x${ratio}` + return `space-${value}` + } +} diff --git a/src/content/scanner/TypographyExtractor.ts b/src/content/scanner/TypographyExtractor.ts new file mode 100644 index 0000000..4ae0ca2 --- /dev/null +++ b/src/content/scanner/TypographyExtractor.ts @@ -0,0 +1,110 @@ +// PixelLens — Typography Extractor (extract fonts and type scale from the page) + +import type { TypographyToken, TypographyVariant } from '@/types/design-system' + +const TEXT_TAGS = new Set([ + 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', + 'p', 'span', 'a', 'li', 'label', 'button', + 'td', 'th', 'caption', 'blockquote', +]) + +const KNOWN_RATIOS = [1.067, 1.125, 1.2, 1.25, 1.333, 1.414, 1.5, 1.618] as const + +export class TypographyExtractor { + extract(elements: Element[]): TypographyToken[] { + // Family → Map<"size|weight" → variant with count> + const familyMap = new Map>() + + for (const el of elements) { + const tag = el.tagName.toLowerCase() + if (!TEXT_TAGS.has(tag)) continue + + const computed = window.getComputedStyle(el) + const fontFamily = computed.getPropertyValue('font-family') + const fontSize = computed.getPropertyValue('font-size') + const fontWeight = computed.getPropertyValue('font-weight') + const lineHeight = computed.getPropertyValue('line-height') + const letterSpacing = computed.getPropertyValue('letter-spacing') + + if (!fontFamily || !fontSize) continue + + const familyKey = fontFamily.trim() + const variantKey = `${fontSize}|${fontWeight}` + + if (!familyMap.has(familyKey)) { + familyMap.set(familyKey, new Map()) + } + + const variants = familyMap.get(familyKey)! + if (variants.has(variantKey)) { + variants.get(variantKey)!.count++ + } else { + variants.set(variantKey, { + fontSize, + fontWeight, + lineHeight, + letterSpacing, + count: 1, + }) + } + } + + // Convert to TypographyToken[] + const tokens: TypographyToken[] = [] + + for (const [fontFamily, variantsMap] of familyMap) { + const variants: TypographyVariant[] = Array.from(variantsMap.values()) + .sort((a, b) => parseFloat(b.fontSize) - parseFloat(a.fontSize)) + .map(({ fontSize, fontWeight, lineHeight, letterSpacing }) => ({ + fontSize, + fontWeight, + lineHeight, + letterSpacing, + })) + + tokens.push({ fontFamily, variants }) + } + + // Sort by total variant count (most used family first) + tokens.sort((a, b) => b.variants.length - a.variants.length) + + return tokens + } + + detectTypeScaleRatio(tokens: TypographyToken[]): number | null { + // Collect all unique font sizes across all families + const sizes = new Set() + for (const token of tokens) { + for (const v of token.variants) { + const px = parseFloat(v.fontSize) + if (px > 0) sizes.add(px) + } + } + + const sorted = Array.from(sizes).sort((a, b) => a - b) + if (sorted.length < 3) return null + + // Compute ratios between consecutive sizes + const ratios: number[] = [] + for (let i = 1; i < sorted.length; i++) { + ratios.push(sorted[i] / sorted[i - 1]) + } + + // Find the median ratio + ratios.sort((a, b) => a - b) + const median = ratios[Math.floor(ratios.length / 2)] + + // Match to nearest known ratio + let closest: number = KNOWN_RATIOS[0] + let minDiff = Math.abs(median - closest) + for (const r of KNOWN_RATIOS) { + const diff = Math.abs(median - r) + if (diff < minDiff) { + minDiff = diff + closest = r + } + } + + return minDiff < 0.1 ? closest : null + } +} diff --git a/src/content/ui/ContentApp.tsx b/src/content/ui/ContentApp.tsx new file mode 100644 index 0000000..388a9b6 --- /dev/null +++ b/src/content/ui/ContentApp.tsx @@ -0,0 +1,122 @@ +// PixelLens — Content App (Shadow DOM React wrapper) + +import React, { useState, useEffect, useCallback } from 'react' +import { createRoot } from 'react-dom/client' +import { FloatingToolbar } from './FloatingToolbar' +import { InspectorTooltip } from './InspectorTooltip' +import { sendMessage } from '@/lib/messaging' +import { MessageType } from '@/types/messages' + +type ContentMode = 'off' | 'inspect' | 'measure' | 'grid' + +interface TooltipData { + tagName: string + className: string + width: number + height: number + x: number + y: number +} + +function ContentApp() { + const [mode, setMode] = useState('off') + const [tooltip, setTooltip] = useState(null) + const [gridVisible, setGridVisible] = useState(false) + + // Listen for mode changes from content/index.ts + useEffect(() => { + const handler = (e: Event) => { + const detail = (e as CustomEvent).detail + setMode(detail.mode) + } + document.addEventListener('pixellens:mode-change', handler) + return () => document.removeEventListener('pixellens:mode-change', handler) + }, []) + + // Tooltip tracking on mousemove during inspect mode + useEffect(() => { + if (mode !== 'inspect') { + setTooltip(null) + return + } + + const handler = (e: MouseEvent) => { + const target = e.target as Element + if (!target || isPixelLensElement(target)) { + setTooltip(null) + return + } + + const rect = target.getBoundingClientRect() + const className = target.className?.toString() || '' + const truncated = className.length > 30 ? className.slice(0, 30) + '...' : className + + setTooltip({ + tagName: target.tagName.toLowerCase(), + className: truncated, + width: Math.round(rect.width), + height: Math.round(rect.height), + x: e.clientX, + y: e.clientY, + }) + } + + document.addEventListener('mousemove', handler, { passive: true }) + return () => document.removeEventListener('mousemove', handler) + }, [mode]) + + const handleModeChange = useCallback((newMode: ContentMode) => { + if (newMode === mode) { + // Toggle off + setMode('off') + sendMessage(MessageType.TOGGLE_INSPECT, { active: false }) + return + } + + setMode(newMode) + + if (newMode === 'inspect') { + sendMessage(MessageType.TOGGLE_INSPECT, { active: true }) + } else if (newMode === 'measure') { + sendMessage(MessageType.TOGGLE_INSPECT, { active: false }) + sendMessage(MessageType.TOGGLE_MEASURE, { active: true }) + } + }, [mode]) + + const handleGridToggle = useCallback(() => { + const next = !gridVisible + setGridVisible(next) + sendMessage(MessageType.TOGGLE_GRID, { visible: next }) + }, [gridVisible]) + + const handleScan = useCallback(() => { + sendMessage(MessageType.SCAN_PAGE, undefined) + }, []) + + return ( + <> + + {tooltip && } + + ) +} + +function isPixelLensElement(el: Element): boolean { + let node: Node | null = el + while (node) { + if ((node as HTMLElement).id === 'pixellens-host') return true + node = node.parentNode + } + return false +} + +export function mountContentApp(container: HTMLElement): void { + const root = createRoot(container) + root.render() +} diff --git a/src/content/ui/FloatingToolbar.tsx b/src/content/ui/FloatingToolbar.tsx new file mode 100644 index 0000000..f89d546 --- /dev/null +++ b/src/content/ui/FloatingToolbar.tsx @@ -0,0 +1,205 @@ +// PixelLens — Floating Toolbar (bottom of page, mode selector) + +import React, { useRef, useEffect, useState, useCallback } from 'react' +import { + MagnifyingGlass, + Ruler, + GridFour, + Eyedropper, + Scan, +} from '@phosphor-icons/react' +import gsap from 'gsap' + +type ContentMode = 'off' | 'inspect' | 'measure' | 'grid' + +interface FloatingToolbarProps { + mode: ContentMode + gridVisible: boolean + onModeChange: (mode: ContentMode) => void + onGridToggle: () => void + onScan: () => void +} + +const STORAGE_KEY = 'pixellens_toolbar_pos' + +export function FloatingToolbar({ + mode, + gridVisible, + onModeChange, + onGridToggle, + onScan, +}: FloatingToolbarProps) { + const toolbarRef = useRef(null) + const [dragging, setDragging] = useState(false) + const [position, setPosition] = useState<{ x: number; y: number } | null>(null) + const dragOffset = useRef({ x: 0, y: 0 }) + + // GSAP slide-up + fade-in on mount + useEffect(() => { + // Load saved position + try { + const saved = localStorage.getItem(STORAGE_KEY) + if (saved) setPosition(JSON.parse(saved)) + } catch { /* ignore */ } + + const el = toolbarRef.current + if (!el) return + + gsap.fromTo( + el, + { y: 30, opacity: 0 }, + { + y: 0, + opacity: 1, + duration: 0.4, + ease: 'power3.out', + delay: 0.05, + }, + ) + }, []) + + // Save position on change + useEffect(() => { + if (position) { + try { + localStorage.setItem(STORAGE_KEY, JSON.stringify(position)) + } catch { /* ignore */ } + } + }, [position]) + + // Drag handling + const onMouseDown = useCallback((e: React.MouseEvent) => { + if (!toolbarRef.current) return + const rect = toolbarRef.current.getBoundingClientRect() + dragOffset.current = { x: e.clientX - rect.left, y: e.clientY - rect.top } + setDragging(true) + }, []) + + useEffect(() => { + if (!dragging) return + + const onMouseMove = (e: MouseEvent) => { + setPosition({ + x: e.clientX - dragOffset.current.x, + y: e.clientY - dragOffset.current.y, + }) + } + + const onMouseUp = () => setDragging(false) + + window.addEventListener('mousemove', onMouseMove) + window.addEventListener('mouseup', onMouseUp) + return () => { + window.removeEventListener('mousemove', onMouseMove) + window.removeEventListener('mouseup', onMouseUp) + } + }, [dragging]) + + const style: React.CSSProperties = position + ? { left: position.x, top: position.y, transform: 'none' } + : {} + + const buttons: { + icon: React.ReactNode + label: string + active: boolean + onClick: () => void + }[] = [ + { + icon: , + label: 'Inspect', + active: mode === 'inspect', + onClick: () => onModeChange('inspect'), + }, + { + icon: , + label: 'Measure', + active: mode === 'measure', + onClick: () => onModeChange('measure'), + }, + { + icon: , + label: 'Grid', + active: gridVisible, + onClick: onGridToggle, + }, + { + icon: , + label: 'Picker', + active: false, + onClick: () => {}, + }, + { + icon: , + label: 'Scan', + active: false, + onClick: onScan, + }, + ] + + return ( +
+ {buttons.map((btn) => ( + + ))} +
+ ) +} diff --git a/src/content/ui/InspectorTooltip.tsx b/src/content/ui/InspectorTooltip.tsx new file mode 100644 index 0000000..ce76260 --- /dev/null +++ b/src/content/ui/InspectorTooltip.tsx @@ -0,0 +1,52 @@ +// PixelLens — Inspector Tooltip (follows cursor during inspect mode) + +import React from 'react' + +interface TooltipData { + tagName: string + className: string + width: number + height: number + x: number + y: number +} + +interface InspectorTooltipProps { + data: TooltipData +} + +export function InspectorTooltip({ data }: InspectorTooltipProps) { + const label = data.className + ? `${data.tagName}.${data.className.split(/\s+/)[0]}` + : data.tagName + + const truncated = label.length > 35 ? label.slice(0, 35) + '...' : label + + return ( +
+ {truncated} + + {data.width} x {data.height} + +
+ ) +} diff --git a/src/lib/__tests__/colors.test.ts b/src/lib/__tests__/colors.test.ts new file mode 100644 index 0000000..e4a5e2c --- /dev/null +++ b/src/lib/__tests__/colors.test.ts @@ -0,0 +1,180 @@ +import { describe, it, expect } from 'vitest'; +import { + toHex, + toRgb, + toHsl, + isNeutral, + isTransparent, + deltaE, + clusterColors, + classifyColors, + getContrastRatio, +} from '../colors'; +import type { ColorToken } from '@/types/design-system'; + +describe('toHex', () => { + it('converts rgb string to hex', () => { + expect(toHex('rgb(255, 0, 0)')).toBe('#ff0000'); + }); + + it('converts hsl string to hex', () => { + const hex = toHex('hsl(120, 100%, 50%)'); + expect(hex).toBe('#00ff00'); + }); + + it('returns input for invalid color', () => { + expect(toHex('not-a-color')).toBe('not-a-color'); + }); + + it('passes through hex values', () => { + expect(toHex('#abcdef')).toBe('#abcdef'); + }); +}); + +describe('toRgb', () => { + it('converts hex to rgb', () => { + expect(toRgb('#ff0000')).toEqual({ r: 255, g: 0, b: 0 }); + }); + + it('converts named color', () => { + expect(toRgb('white')).toEqual({ r: 255, g: 255, b: 255 }); + }); + + it('returns black for invalid color', () => { + expect(toRgb('invalid')).toEqual({ r: 0, g: 0, b: 0 }); + }); +}); + +describe('toHsl', () => { + it('converts red to hsl', () => { + const hsl = toHsl('#ff0000'); + expect(hsl.h).toBe(0); + expect(hsl.s).toBe(100); + expect(hsl.l).toBe(50); + }); + + it('handles achromatic colors (hue = NaN)', () => { + const hsl = toHsl('#808080'); + expect(hsl.h).toBe(0); + expect(hsl.s).toBe(0); + }); + + it('returns zeros for invalid color', () => { + expect(toHsl('invalid')).toEqual({ h: 0, s: 0, l: 0 }); + }); +}); + +describe('isNeutral', () => { + it('returns true for grays (low saturation)', () => { + expect(isNeutral('#808080')).toBe(true); + expect(isNeutral('#ffffff')).toBe(true); + expect(isNeutral('#000000')).toBe(true); + }); + + it('returns false for vivid colors', () => { + expect(isNeutral('#ff0000')).toBe(false); + expect(isNeutral('#00ff00')).toBe(false); + }); + + it('returns false for invalid color', () => { + expect(isNeutral('invalid')).toBe(false); + }); +}); + +describe('isTransparent', () => { + it('returns true for fully transparent', () => { + expect(isTransparent('rgba(0,0,0,0)')).toBe(true); + expect(isTransparent('transparent')).toBe(true); + }); + + it('returns false for opaque colors', () => { + expect(isTransparent('#ff0000')).toBe(false); + expect(isTransparent('rgb(0,0,0)')).toBe(false); + }); +}); + +describe('deltaE', () => { + it('returns 0 for identical colors', () => { + expect(deltaE('#ff0000', '#ff0000')).toBe(0); + }); + + it('returns > 0 for different colors', () => { + expect(deltaE('#ff0000', '#00ff00')).toBeGreaterThan(0); + }); + + it('returns Infinity for invalid colors', () => { + expect(deltaE('invalid', '#ff0000')).toBe(Infinity); + }); +}); + +describe('getContrastRatio', () => { + it('returns 21 for black on white', () => { + expect(getContrastRatio('#000000', '#ffffff')).toBe(21); + }); + + it('returns 1 for same color', () => { + expect(getContrastRatio('#ffffff', '#ffffff')).toBe(1); + }); + + it('returns 0 for invalid color', () => { + expect(getContrastRatio('invalid', '#fff')).toBe(0); + }); +}); + +describe('clusterColors', () => { + it('returns empty array for empty input', () => { + expect(clusterColors([])).toEqual([]); + }); + + it('clusters similar colors together', () => { + const colors = [ + { hex: '#ff0000', frequency: 5 }, + { hex: '#ff0102', frequency: 3 }, + { hex: '#00ff00', frequency: 2 }, + ]; + const result = clusterColors(colors); + // Red shades should cluster, green stays separate + expect(result.length).toBe(2); + // Most frequent cluster first + expect(result[0].frequency).toBe(8); + }); + + it('keeps distinct colors separate', () => { + const colors = [ + { hex: '#ff0000', frequency: 1 }, + { hex: '#00ff00', frequency: 1 }, + { hex: '#0000ff', frequency: 1 }, + ]; + const result = clusterColors(colors); + expect(result.length).toBe(3); + }); +}); + +describe('classifyColors', () => { + it('classifies chromatic colors as primary/secondary/accent', () => { + const colors: ColorToken[] = [ + { name: '', hex: '#ff0000', rgb: { r: 255, g: 0, b: 0 }, hsl: { h: 0, s: 100, l: 50 }, frequency: 10, category: 'primary' }, + { name: '', hex: '#00ff00', rgb: { r: 0, g: 255, b: 0 }, hsl: { h: 120, s: 100, l: 50 }, frequency: 5, category: 'primary' }, + { name: '', hex: '#0000ff', rgb: { r: 0, g: 0, b: 255 }, hsl: { h: 240, s: 100, l: 50 }, frequency: 2, category: 'primary' }, + ]; + const result = classifyColors(colors); + expect(result[0].category).toBe('primary'); + expect(result[1].category).toBe('secondary'); + expect(result[2].category).toBe('accent'); + }); + + it('classifies neutrals by luminance', () => { + const colors: ColorToken[] = [ + { name: '', hex: '#ffffff', rgb: { r: 255, g: 255, b: 255 }, hsl: { h: 0, s: 0, l: 100 }, frequency: 10, category: 'primary' }, + { name: '', hex: '#000000', rgb: { r: 0, g: 0, b: 0 }, hsl: { h: 0, s: 0, l: 0 }, frequency: 5, category: 'primary' }, + { name: '', hex: '#808080', rgb: { r: 128, g: 128, b: 128 }, hsl: { h: 0, s: 0, l: 50 }, frequency: 3, category: 'primary' }, + ]; + const result = classifyColors(colors); + const white = result.find((c) => c.hex === '#ffffff')!; + const black = result.find((c) => c.hex === '#000000')!; + const gray = result.find((c) => c.hex === '#808080')!; + expect(white.category).toBe('background'); + expect(black.category).toBe('text'); + expect(gray.category).toBe('neutral'); + }); +}); diff --git a/src/lib/__tests__/css-parser.test.ts b/src/lib/__tests__/css-parser.test.ts new file mode 100644 index 0000000..25f996c --- /dev/null +++ b/src/lib/__tests__/css-parser.test.ts @@ -0,0 +1,102 @@ +import { describe, it, expect } from 'vitest'; +import { + formatCSSProperty, + generateCSSBlock, + shorthandToLonghand, +} from '../css-parser'; + +describe('formatCSSProperty', () => { + it('formats a property-value pair with semicolon', () => { + expect(formatCSSProperty('color', 'red')).toBe('color: red;'); + }); + + it('handles complex values', () => { + expect(formatCSSProperty('font-family', '"Helvetica", sans-serif')).toBe( + 'font-family: "Helvetica", sans-serif;', + ); + }); +}); + +describe('generateCSSBlock', () => { + it('generates indented CSS lines from styles', () => { + const styles = { color: '#ff0000', 'font-size': '16px' }; + const result = generateCSSBlock(styles); + expect(result).toContain('color: #ff0000;'); + expect(result).toContain('font-size: 16px;'); + // Each line should be indented + for (const line of result.split('\n')) { + expect(line).toMatch(/^\s{2}/); + } + }); + + it('filters out default/skip properties', () => { + const styles = { + opacity: '1', // default — should be filtered + color: '#ff0000', // non-default — should be kept + }; + const result = generateCSSBlock(styles); + expect(result).not.toContain('opacity'); + expect(result).toContain('color'); + }); + + it('filters out auto/initial/normal values', () => { + const styles = { + 'margin-top': 'auto', + 'font-style': 'normal', + display: 'initial', + color: '#000', + }; + const result = generateCSSBlock(styles); + expect(result).not.toContain('margin-top'); + expect(result).not.toContain('font-style'); + expect(result).not.toContain('display'); + expect(result).toContain('color'); + }); +}); + +describe('shorthandToLonghand', () => { + it('expands margin with 4 values', () => { + const result = shorthandToLonghand('margin', '10px 20px 30px 40px'); + expect(result).toEqual({ + 'margin-top': '10px', + 'margin-right': '20px', + 'margin-bottom': '30px', + 'margin-left': '40px', + }); + }); + + it('expands padding with 1 value', () => { + const result = shorthandToLonghand('padding', '8px'); + expect(result).toEqual({ + 'padding-top': '8px', + 'padding-right': '8px', + 'padding-bottom': '8px', + 'padding-left': '8px', + }); + }); + + it('expands margin with 2 values', () => { + const result = shorthandToLonghand('margin', '10px 20px'); + expect(result).toEqual({ + 'margin-top': '10px', + 'margin-right': '20px', + 'margin-bottom': '10px', + 'margin-left': '20px', + }); + }); + + it('expands border-radius with 4 values', () => { + const result = shorthandToLonghand('border-radius', '1px 2px 3px 4px'); + expect(result).toEqual({ + 'border-top-left-radius': '1px', + 'border-top-right-radius': '2px', + 'border-bottom-right-radius': '3px', + 'border-bottom-left-radius': '4px', + }); + }); + + it('returns original for unknown properties', () => { + const result = shorthandToLonghand('color', '#ff0000'); + expect(result).toEqual({ color: '#ff0000' }); + }); +}); diff --git a/src/lib/__tests__/design-tokens.test.ts b/src/lib/__tests__/design-tokens.test.ts new file mode 100644 index 0000000..40fbae1 --- /dev/null +++ b/src/lib/__tests__/design-tokens.test.ts @@ -0,0 +1,123 @@ +import { describe, it, expect } from 'vitest'; +import { + toCSSVariables, + toTailwindConfig, + toJSONTokens, + formatExport, +} from '../design-tokens'; +import type { DesignSystem } from '@/types/design-system'; + +const mockDS: DesignSystem = { + colors: [ + { + name: 'Brand Red', + hex: '#ff0000', + rgb: { r: 255, g: 0, b: 0 }, + hsl: { h: 0, s: 100, l: 50 }, + frequency: 10, + category: 'primary', + }, + ], + typography: [ + { + fontFamily: '"Inter", sans-serif', + variants: [{ fontSize: '16px', fontWeight: '400', lineHeight: '1.5', letterSpacing: '0px' }], + }, + ], + spacing: [{ value: '8px', frequency: 20, label: 'Small' }], + borderRadius: [{ value: '4px', frequency: 10 }], + shadows: [{ value: '0 2px 4px rgba(0,0,0,0.1)', parsed: { x: '0', y: '2px', blur: '4px', spread: '0', color: 'rgba(0,0,0,0.1)' } }], + metadata: { url: 'https://example.com', title: 'Test', scannedAt: '2026-01-01' }, +}; + +describe('toCSSVariables', () => { + it('generates valid CSS with :root block', () => { + const css = toCSSVariables(mockDS); + expect(css).toContain(':root {'); + expect(css).toContain('}'); + }); + + it('includes color variables', () => { + const css = toCSSVariables(mockDS); + expect(css).toContain('--color-brand-red: #ff0000;'); + }); + + it('includes font variables', () => { + const css = toCSSVariables(mockDS); + expect(css).toContain('--font-inter:'); + }); + + it('includes spacing variables', () => { + const css = toCSSVariables(mockDS); + expect(css).toContain('--spacing-small: 8px;'); + }); + + it('includes radius and shadow variables', () => { + const css = toCSSVariables(mockDS); + expect(css).toContain('--radius-1: 4px;'); + expect(css).toContain('--shadow-1:'); + }); +}); + +describe('toTailwindConfig', () => { + it('returns theme.extend structure', () => { + const config = toTailwindConfig(mockDS) as any; + expect(config.theme.extend).toBeDefined(); + expect(config.theme.extend.colors).toBeDefined(); + expect(config.theme.extend.fontFamily).toBeDefined(); + expect(config.theme.extend.spacing).toBeDefined(); + }); + + it('maps colors by slugified name', () => { + const config = toTailwindConfig(mockDS) as any; + expect(config.theme.extend.colors['brand-red']).toBe('#ff0000'); + }); + + it('maps font families as arrays', () => { + const config = toTailwindConfig(mockDS) as any; + expect(config.theme.extend.fontFamily['inter']).toEqual(['Inter', 'sans-serif']); + }); +}); + +describe('toJSONTokens', () => { + it('returns valid JSON structure with $schema', () => { + const tokens = toJSONTokens(mockDS); + expect(tokens.$schema).toBeDefined(); + }); + + it('includes color tokens with $value and $type', () => { + const tokens = toJSONTokens(mockDS) as any; + const colorEntry = tokens.color['Brand Red']; + expect(colorEntry.$value).toBe('#ff0000'); + expect(colorEntry.$type).toBe('color'); + }); + + it('includes spacing tokens', () => { + const tokens = toJSONTokens(mockDS) as any; + expect(tokens.spacing['small'].$value).toBe('8px'); + expect(tokens.spacing['small'].$type).toBe('dimension'); + }); +}); + +describe('formatExport', () => { + it('dispatches to css-variables format', () => { + const result = formatExport(mockDS, 'css-variables'); + expect(result).toContain(':root {'); + }); + + it('dispatches to tailwind format', () => { + const result = formatExport(mockDS, 'tailwind'); + expect(result).toContain('module.exports'); + expect(result).toContain('"theme"'); + }); + + it('dispatches to json format', () => { + const result = formatExport(mockDS, 'json'); + const parsed = JSON.parse(result); + expect(parsed.$schema).toBeDefined(); + }); + + it('returns empty string for png format', () => { + expect(formatExport(mockDS, 'png')).toBe(''); + }); +}); diff --git a/src/lib/__tests__/dom-utils.test.ts b/src/lib/__tests__/dom-utils.test.ts new file mode 100644 index 0000000..9412336 --- /dev/null +++ b/src/lib/__tests__/dom-utils.test.ts @@ -0,0 +1,133 @@ +import { describe, it, expect, beforeEach, vi } from 'vitest'; +import { isElementVisible, isPixelLensElement, getElementPath } from '../dom-utils'; + +function mockRect(el: Element, width: number, height: number) { + vi.spyOn(el, 'getBoundingClientRect').mockReturnValue({ + width, + height, + top: 0, + left: 0, + bottom: height, + right: width, + x: 0, + y: 0, + toJSON: () => ({}), + }); +} + +describe('isElementVisible', () => { + beforeEach(() => { + document.body.innerHTML = ''; + }); + + it('returns true for a visible element', () => { + const el = document.createElement('div'); + el.style.display = 'block'; + document.body.appendChild(el); + mockRect(el, 100, 100); + expect(isElementVisible(el)).toBe(true); + }); + + it('returns false for display:none', () => { + const el = document.createElement('div'); + el.style.display = 'none'; + document.body.appendChild(el); + mockRect(el, 0, 0); + expect(isElementVisible(el)).toBe(false); + }); + + it('returns false for visibility:hidden', () => { + const el = document.createElement('div'); + el.style.visibility = 'hidden'; + document.body.appendChild(el); + mockRect(el, 100, 100); + expect(isElementVisible(el)).toBe(false); + }); + + it('returns false for opacity:0', () => { + const el = document.createElement('div'); + el.style.opacity = '0'; + document.body.appendChild(el); + mockRect(el, 100, 100); + expect(isElementVisible(el)).toBe(false); + }); + + it('returns false for zero-size element', () => { + const el = document.createElement('div'); + document.body.appendChild(el); + mockRect(el, 0, 0); + expect(isElementVisible(el)).toBe(false); + }); +}); + +describe('isPixelLensElement', () => { + beforeEach(() => { + document.body.innerHTML = ''; + }); + + it('returns true for elements inside #pixellens-host', () => { + const host = document.createElement('div'); + host.id = 'pixellens-host'; + const child = document.createElement('span'); + host.appendChild(child); + document.body.appendChild(host); + expect(isPixelLensElement(child)).toBe(true); + }); + + it('returns true for the host element itself', () => { + const host = document.createElement('div'); + host.id = 'pixellens-host'; + document.body.appendChild(host); + expect(isPixelLensElement(host)).toBe(true); + }); + + it('returns false for elements outside #pixellens-host', () => { + const el = document.createElement('div'); + document.body.appendChild(el); + expect(isPixelLensElement(el)).toBe(false); + }); +}); + +describe('getElementPath', () => { + beforeEach(() => { + document.body.innerHTML = ''; + }); + + it('returns tag name for simple element', () => { + const el = document.createElement('div'); + document.body.appendChild(el); + const path = getElementPath(el); + expect(path).toContain('div'); + }); + + it('includes id when present and stops there', () => { + const parent = document.createElement('div'); + parent.id = 'main'; + const child = document.createElement('span'); + parent.appendChild(child); + document.body.appendChild(parent); + const path = getElementPath(child); + expect(path).toContain('div#main'); + expect(path).toContain('span'); + }); + + it('includes class names', () => { + const el = document.createElement('div'); + el.className = 'foo bar'; + document.body.appendChild(el); + const path = getElementPath(el); + expect(path).toContain('.foo'); + expect(path).toContain('.bar'); + }); + + it('includes nth-of-type for siblings', () => { + const parent = document.createElement('div'); + const child1 = document.createElement('span'); + const child2 = document.createElement('span'); + parent.appendChild(child1); + parent.appendChild(child2); + document.body.appendChild(parent); + const path = getElementPath(child2); + expect(path).toContain('nth-of-type(2)'); + }); +}); diff --git a/src/lib/__tests__/storage.test.ts b/src/lib/__tests__/storage.test.ts new file mode 100644 index 0000000..41cb081 --- /dev/null +++ b/src/lib/__tests__/storage.test.ts @@ -0,0 +1,110 @@ +import { describe, it, expect, beforeEach, vi } from 'vitest'; + +// Mock chrome.storage before importing the module +let mockStorage: Record = {}; + +Object.defineProperty(globalThis, 'chrome', { + value: { + storage: { + sync: { + get: vi.fn((keys: string | string[]) => { + if (typeof keys === 'string') { + return Promise.resolve({ [keys]: mockStorage[keys] }); + } + const result: Record = {}; + for (const k of keys) { + if (k in mockStorage) result[k] = mockStorage[k]; + } + return Promise.resolve(result); + }), + set: vi.fn((items: Record) => { + Object.assign(mockStorage, items); + return Promise.resolve(); + }), + }, + local: { + get: vi.fn((keys: string | string[]) => { + if (typeof keys === 'string') { + return Promise.resolve({ [keys]: mockStorage[keys] }); + } + const result: Record = {}; + for (const k of keys) { + if (k in mockStorage) result[k] = mockStorage[k]; + } + return Promise.resolve(result); + }), + set: vi.fn((items: Record) => { + Object.assign(mockStorage, items); + return Promise.resolve(); + }), + }, + }, + }, + writable: true, +}); + +import { + getPreferences, + setPreferences, + saveDesignSystem, + getDesignSystems, +} from '../storage'; +import type { DesignSystem } from '@/types/design-system'; + +const mockDS: DesignSystem = { + colors: [], + typography: [], + spacing: [], + shadows: [], + borderRadius: [], + metadata: { url: 'https://example.com', title: 'Test', scannedAt: '2026-01-01' }, +}; + +describe('getPreferences / setPreferences', () => { + beforeEach(() => { + mockStorage = {}; + }); + + it('returns default preferences when none stored', async () => { + const prefs = await getPreferences(); + expect(prefs.colorFormat).toBe('hex'); + expect(prefs.gridSize).toBe(8); + expect(prefs.theme).toBe('dark'); + }); + + it('round-trips preferences correctly', async () => { + await setPreferences({ colorFormat: 'rgb', gridSize: 4 }); + const prefs = await getPreferences(); + expect(prefs.colorFormat).toBe('rgb'); + expect(prefs.gridSize).toBe(4); + expect(prefs.theme).toBe('dark'); // unchanged + }); +}); + +describe('saveDesignSystem / getDesignSystems', () => { + beforeEach(() => { + mockStorage = {}; + }); + + it('saves and retrieves a design system', async () => { + await saveDesignSystem(mockDS); + const systems = await getDesignSystems(); + expect(systems).toHaveLength(1); + expect(systems[0].metadata.url).toBe('https://example.com'); + }); + + it('prepends new scans (newest first)', async () => { + const ds1 = { ...mockDS, metadata: { ...mockDS.metadata, title: 'First' } }; + const ds2 = { ...mockDS, metadata: { ...mockDS.metadata, title: 'Second' } }; + await saveDesignSystem(ds1); + await saveDesignSystem(ds2); + const systems = await getDesignSystems(); + expect(systems[0].metadata.title).toBe('Second'); + expect(systems[1].metadata.title).toBe('First'); + }); + + it('returns empty array when none stored', async () => { + const systems = await getDesignSystems(); + expect(systems).toEqual([]); + }); +}); diff --git a/src/lib/colors.ts b/src/lib/colors.ts new file mode 100644 index 0000000..6cd7f4d --- /dev/null +++ b/src/lib/colors.ts @@ -0,0 +1,128 @@ +// PixelLens — Color Utilities (Chroma.js wrappers) + +import chroma from 'chroma-js' +import type { ColorToken, ColorCategory } from '@/types/design-system' + +export function toHex(color: string): string { + try { + return chroma(color).hex() + } catch { + return color + } +} + +export function toRgb(color: string): { r: number; g: number; b: number } { + try { + const [r, g, b] = chroma(color).rgb() + return { r, g, b } + } catch { + return { r: 0, g: 0, b: 0 } + } +} + +export function toHsl(color: string): { h: number; s: number; l: number } { + try { + const [h, s, l] = chroma(color).hsl() + return { + h: Math.round(isNaN(h) ? 0 : h), + s: Math.round(s * 100), + l: Math.round(l * 100), + } + } catch { + return { h: 0, s: 0, l: 0 } + } +} + +export function deltaE(c1: string, c2: string): number { + try { + return chroma.deltaE(c1, c2) + } catch { + return Infinity + } +} + +export function getContrastRatio(fg: string, bg: string): number { + try { + return chroma.contrast(fg, bg) + } catch { + return 0 + } +} + +export function isNeutral(color: string): boolean { + try { + const [, s] = chroma(color).hsl() + return s < 0.1 + } catch { + return false + } +} + +export function isTransparent(color: string): boolean { + try { + return chroma(color).alpha() === 0 + } catch { + return color === 'transparent' || color === 'rgba(0, 0, 0, 0)' + } +} + +export function clusterColors( + colors: { hex: string; frequency: number }[], + threshold = 5, +): { hex: string; frequency: number }[] { + if (colors.length === 0) return [] + + const sorted = [...colors].sort((a, b) => b.frequency - a.frequency) + const clusters: { hex: string; frequency: number }[] = [] + + for (const color of sorted) { + const existing = clusters.find((c) => deltaE(c.hex, color.hex) < threshold) + if (existing) { + existing.frequency += color.frequency + } else { + clusters.push({ ...color }) + } + } + + return clusters.sort((a, b) => b.frequency - a.frequency) +} + +export function classifyColors(colors: ColorToken[]): ColorToken[] { + const sorted = [...colors].sort((a, b) => b.frequency - a.frequency) + + const neutrals: ColorToken[] = [] + const chromatic: ColorToken[] = [] + + for (const color of sorted) { + if (isNeutral(color.hex)) { + neutrals.push(color) + } else { + chromatic.push(color) + } + } + + // Classify neutrals + for (const color of neutrals) { + const lightness = chroma(color.hex).luminance() + if (lightness > 0.85) { + color.category = 'background' + } else if (lightness < 0.15) { + color.category = 'text' + } else { + color.category = 'neutral' + } + } + + // Classify chromatic colors + chromatic.forEach((color, i) => { + if (i === 0) { + color.category = 'primary' + } else if (i === 1) { + color.category = 'secondary' + } else { + color.category = 'accent' + } + }) + + return [...chromatic, ...neutrals] +} diff --git a/src/lib/css-parser.ts b/src/lib/css-parser.ts new file mode 100644 index 0000000..c7e023c --- /dev/null +++ b/src/lib/css-parser.ts @@ -0,0 +1,147 @@ +// PixelLens — CSS Parser Utilities + +import type { ColorInfo, TypographyInfo, EffectsInfo } from '@/types/inspection' +import { toHex, toRgb, toHsl } from './colors' + +const COLOR_PROPERTIES = [ + 'color', + 'background-color', + 'border-color', + 'border-top-color', + 'border-right-color', + 'border-bottom-color', + 'border-left-color', + 'outline-color', + 'text-decoration-color', +] + +const TYPOGRAPHY_PROPERTIES = [ + 'font-family', + 'font-size', + 'font-weight', + 'line-height', + 'letter-spacing', +] + +const EFFECT_PROPERTIES = [ + 'box-shadow', + 'opacity', + 'backdrop-filter', + 'border-radius', +] + +export interface ParsedStyles { + colors: ColorInfo[] + typography: TypographyInfo + effects: EffectsInfo + allProperties: Record +} + +export function parseComputedStyles(element: Element): ParsedStyles { + const computed = window.getComputedStyle(element) + const allProperties: Record = {} + + for (const prop of computed) { + allProperties[prop] = computed.getPropertyValue(prop) + } + + const colors: ColorInfo[] = COLOR_PROPERTIES + .map((prop) => { + const value = computed.getPropertyValue(prop) + if (!value || value === 'transparent' || value === 'rgba(0, 0, 0, 0)') return null + return { + property: prop, + value, + hex: toHex(value), + rgb: toRgb(value), + hsl: toHsl(value), + } + }) + .filter((c): c is ColorInfo => c !== null) + + const typography: TypographyInfo = { + fontFamily: computed.getPropertyValue('font-family'), + fontSize: computed.getPropertyValue('font-size'), + fontWeight: computed.getPropertyValue('font-weight'), + lineHeight: computed.getPropertyValue('line-height'), + letterSpacing: computed.getPropertyValue('letter-spacing'), + } + + const effects: EffectsInfo = { + boxShadow: computed.getPropertyValue('box-shadow'), + opacity: computed.getPropertyValue('opacity'), + backdropFilter: computed.getPropertyValue('backdrop-filter'), + borderRadius: computed.getPropertyValue('border-radius'), + } + + return { colors, typography, effects, allProperties } +} + +export function formatCSSProperty(prop: string, value: string): string { + return `${prop}: ${value};` +} + +export function generateCSSBlock(styles: Record): string { + const relevant = filterRelevantStyles(styles) + return Object.entries(relevant) + .map(([prop, value]) => ` ${prop}: ${value};`) + .join('\n') +} + +export function shorthandToLonghand( + prop: string, + value: string, +): Record { + const parts = value.split(/\s+/) + + if (prop === 'margin' || prop === 'padding') { + const [top, right = top, bottom = top, left = right] = parts + return { + [`${prop}-top`]: top, + [`${prop}-right`]: right, + [`${prop}-bottom`]: bottom, + [`${prop}-left`]: left, + } + } + + if (prop === 'border-radius') { + const [tl, tr = tl, br = tl, bl = tr] = parts + return { + 'border-top-left-radius': tl, + 'border-top-right-radius': tr, + 'border-bottom-right-radius': br, + 'border-bottom-left-radius': bl, + } + } + + return { [prop]: value } +} + +const SKIP_PROPERTIES = new Set([ + 'all', 'animation', 'transition', + '-webkit-text-fill-color', '-webkit-tap-highlight-color', +]) + +function filterRelevantStyles(styles: Record): Record { + const defaults: Record = { + 'opacity': '1', + 'visibility': 'visible', + 'display': 'block', + 'position': 'static', + 'box-shadow': 'none', + 'backdrop-filter': 'none', + 'transform': 'none', + } + + const result: Record = {} + + for (const [prop, value] of Object.entries(styles)) { + if (SKIP_PROPERTIES.has(prop)) continue + if (prop.startsWith('-webkit-') && !prop.includes('backdrop')) continue + if (value === '' || value === 'initial' || value === 'normal' || value === 'auto') continue + if (defaults[prop] === value) continue + result[prop] = value + } + + return result +} diff --git a/src/lib/design-tokens.ts b/src/lib/design-tokens.ts new file mode 100644 index 0000000..2d3af28 --- /dev/null +++ b/src/lib/design-tokens.ts @@ -0,0 +1,136 @@ +// PixelLens — Design Token Export Utilities + +import type { DesignSystem, ExportFormat } from '@/types/design-system' + +export function toCSSVariables(ds: DesignSystem): string { + const lines: string[] = [':root {'] + + // Colors + for (const color of ds.colors) { + const name = color.name || `${color.category}-${color.hex.slice(1)}` + lines.push(` --color-${slugify(name)}: ${color.hex};`) + } + + // Typography + for (const font of ds.typography) { + const familyName = slugify(font.fontFamily.split(',')[0].replace(/['"]/g, '').trim()) + lines.push(` --font-${familyName}: ${font.fontFamily};`) + } + + // Spacing + for (const space of ds.spacing) { + lines.push(` --spacing-${slugify(space.label)}: ${space.value};`) + } + + // Border radius + ds.borderRadius.forEach((br, i) => { + lines.push(` --radius-${i + 1}: ${br.value};`) + }) + + // Shadows + ds.shadows.forEach((shadow, i) => { + lines.push(` --shadow-${i + 1}: ${shadow.value};`) + }) + + lines.push('}') + return lines.join('\n') +} + +export function toTailwindConfig(ds: DesignSystem): Record { + const colors: Record = {} + for (const color of ds.colors) { + const name = color.name || `${color.category}-${color.hex.slice(1)}` + colors[slugify(name)] = color.hex + } + + const fontFamily: Record = {} + for (const font of ds.typography) { + const familyName = slugify(font.fontFamily.split(',')[0].replace(/['"]/g, '').trim()) + fontFamily[familyName] = font.fontFamily.split(',').map((f) => f.trim().replace(/['"]/g, '')) + } + + const spacing: Record = {} + for (const space of ds.spacing) { + spacing[slugify(space.label)] = space.value + } + + const borderRadius: Record = {} + ds.borderRadius.forEach((br, i) => { + borderRadius[`r${i + 1}`] = br.value + }) + + const boxShadow: Record = {} + ds.shadows.forEach((shadow, i) => { + boxShadow[`s${i + 1}`] = shadow.value + }) + + return { + theme: { + extend: { + colors, + fontFamily, + spacing, + borderRadius, + boxShadow, + }, + }, + } +} + +export function toJSONTokens(ds: DesignSystem): Record { + return { + $schema: 'https://design-tokens.github.io/community-group/format/', + color: Object.fromEntries( + ds.colors.map((c) => [ + c.name || `${c.category}-${c.hex.slice(1)}`, + { $value: c.hex, $type: 'color', $description: `${c.category} — freq: ${c.frequency}` }, + ]), + ), + fontFamily: Object.fromEntries( + ds.typography.map((t) => [ + slugify(t.fontFamily.split(',')[0].replace(/['"]/g, '').trim()), + { $value: t.fontFamily, $type: 'fontFamily' }, + ]), + ), + spacing: Object.fromEntries( + ds.spacing.map((s) => [ + slugify(s.label), + { $value: s.value, $type: 'dimension' }, + ]), + ), + borderRadius: Object.fromEntries( + ds.borderRadius.map((br, i) => [ + `radius-${i + 1}`, + { $value: br.value, $type: 'dimension' }, + ]), + ), + boxShadow: Object.fromEntries( + ds.shadows.map((s, i) => [ + `shadow-${i + 1}`, + { $value: s.value, $type: 'shadow' }, + ]), + ), + } +} + +export function formatExport(ds: DesignSystem, format: ExportFormat): string { + switch (format) { + case 'css-variables': + return toCSSVariables(ds) + case 'tailwind': + return `/** @type {import('tailwindcss').Config} */\nmodule.exports = ${JSON.stringify(toTailwindConfig(ds), null, 2)}` + case 'json': + return JSON.stringify(toJSONTokens(ds), null, 2) + case 'png': + return '' // handled separately via generatePalettePNG + } +} + +function slugify(str: string): string { + return str + .toLowerCase() + .replace(/\s+/g, '-') + .replace(/[^a-z0-9-]/g, '') + .replace(/-+/g, '-') + .replace(/^-|-$/g, '') +} diff --git a/src/lib/dom-utils.ts b/src/lib/dom-utils.ts new file mode 100644 index 0000000..5f01da6 --- /dev/null +++ b/src/lib/dom-utils.ts @@ -0,0 +1,137 @@ +// PixelLens — DOM Utility Functions + +import type { InspectedElement, BoxModel, BoxModelSide } from '@/types/inspection' + +export function isPixelLensElement(el: Element): boolean { + let node: Node | null = el + while (node) { + if ((node as HTMLElement).id === 'pixellens-host') return true + node = node.parentNode + } + return false +} + +export function isElementVisible(el: Element): boolean { + const style = window.getComputedStyle(el) + if (style.display === 'none') return false + if (style.visibility === 'hidden') return false + if (style.opacity === '0') return false + + const rect = el.getBoundingClientRect() + if (rect.width === 0 && rect.height === 0) return false + + return true +} + +export function getVisibleElements(root: Element = document.body): Element[] { + const elements: Element[] = [] + const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT, { + acceptNode(node) { + const el = node as Element + if (!isElementVisible(el)) return NodeFilter.FILTER_REJECT + const tag = el.tagName.toLowerCase() + if (tag === 'script' || tag === 'style' || tag === 'noscript' || tag === 'link' || tag === 'meta') { + return NodeFilter.FILTER_REJECT + } + return NodeFilter.FILTER_ACCEPT + }, + }) + + let node: Node | null + while ((node = walker.nextNode())) { + elements.push(node as Element) + } + + return elements +} + +function parseSides(computed: CSSStyleDeclaration, prefix: string): BoxModelSide { + return { + top: computed.getPropertyValue(`${prefix}-top`), + right: computed.getPropertyValue(`${prefix}-right`), + bottom: computed.getPropertyValue(`${prefix}-bottom`), + left: computed.getPropertyValue(`${prefix}-left`), + } +} + +export function getBoxModel(el: Element): BoxModel { + const computed = window.getComputedStyle(el) + const rect = el.getBoundingClientRect() + + return { + margin: parseSides(computed, 'margin'), + padding: parseSides(computed, 'padding'), + border: { + top: computed.getPropertyValue('border-top-width'), + right: computed.getPropertyValue('border-right-width'), + bottom: computed.getPropertyValue('border-bottom-width'), + left: computed.getPropertyValue('border-left-width'), + }, + content: { + width: `${rect.width}px`, + height: `${rect.height}px`, + }, + } +} + +export function getFullComputedStyles(el: Element): InspectedElement { + const computed = window.getComputedStyle(el) + const rect = el.getBoundingClientRect() + const styles: Record = {} + + for (const prop of computed) { + styles[prop] = computed.getPropertyValue(prop) + } + + return { + tagName: el.tagName.toLowerCase(), + className: el.className?.toString() || '', + id: el.id || '', + computedStyles: styles, + boxModel: getBoxModel(el), + rect: { + top: rect.top, + left: rect.left, + width: rect.width, + height: rect.height, + }, + } +} + +export function getElementPath(el: Element): string { + const parts: string[] = [] + let current: Element | null = el + + while (current && current !== document.body) { + let selector = current.tagName.toLowerCase() + + if (current.id) { + selector += `#${current.id}` + parts.unshift(selector) + break + } + + if (current.className && typeof current.className === 'string') { + const classes = current.className.trim().split(/\s+/).slice(0, 2) + if (classes.length > 0 && classes[0]) { + selector += `.${classes.join('.')}` + } + } + + const parent = current.parentElement + if (parent) { + const siblings = Array.from(parent.children).filter( + (c) => c.tagName === current!.tagName, + ) + if (siblings.length > 1) { + const index = siblings.indexOf(current) + 1 + selector += `:nth-of-type(${index})` + } + } + + parts.unshift(selector) + current = current.parentElement + } + + return parts.join(' > ') +} diff --git a/src/lib/export.ts b/src/lib/export.ts new file mode 100644 index 0000000..f1ae137 --- /dev/null +++ b/src/lib/export.ts @@ -0,0 +1,66 @@ +// PixelLens — Export Utilities + +import type { ColorToken } from '@/types/design-system' + +export async function copyToClipboard(text: string): Promise { + await navigator.clipboard.writeText(text) +} + +export function downloadFile(content: string, filename: string, mime: string): void { + const blob = new Blob([content], { type: mime }) + const url = URL.createObjectURL(blob) + const a = document.createElement('a') + a.href = url + a.download = filename + a.click() + URL.revokeObjectURL(url) +} + +export function generatePalettePNG(colors: ColorToken[]): Blob { + const swatchSize = 80 + const cols = Math.min(colors.length, 8) + const rows = Math.ceil(colors.length / cols) + const padding = 16 + const labelHeight = 24 + + const width = cols * swatchSize + (cols + 1) * padding + const height = rows * (swatchSize + labelHeight) + (rows + 1) * padding + + const canvas = document.createElement('canvas') + canvas.width = width + canvas.height = height + const ctx = canvas.getContext('2d')! + + // Background + ctx.fillStyle = '#0C0C0E' + ctx.fillRect(0, 0, width, height) + + // Swatches + colors.forEach((color, i) => { + const col = i % cols + const row = Math.floor(i / cols) + const x = padding + col * (swatchSize + padding) + const y = padding + row * (swatchSize + labelHeight + padding) + + // Rounded swatch + ctx.fillStyle = color.hex + ctx.beginPath() + ctx.roundRect(x, y, swatchSize, swatchSize, 8) + ctx.fill() + + // Label + ctx.fillStyle = '#EDEDEF' + ctx.font = '11px "JetBrains Mono", monospace' + ctx.textAlign = 'center' + ctx.fillText(color.hex.toUpperCase(), x + swatchSize / 2, y + swatchSize + 16) + }) + + // Convert canvas to blob synchronously via toBlob workaround + const dataUrl = canvas.toDataURL('image/png') + const binary = atob(dataUrl.split(',')[1]) + const bytes = new Uint8Array(binary.length) + for (let i = 0; i < binary.length; i++) { + bytes[i] = binary.charCodeAt(i) + } + return new Blob([bytes], { type: 'image/png' }) +} diff --git a/src/lib/messaging.ts b/src/lib/messaging.ts new file mode 100644 index 0000000..dd8daa9 --- /dev/null +++ b/src/lib/messaging.ts @@ -0,0 +1,40 @@ +// PixelLens — Chrome Messaging Wrapper + +import type { MessageType, MessagePayloadMap, MessageResponse } from '@/types/messages' + +export function sendMessage( + type: T, + payload: MessagePayloadMap[T], +): Promise> { + return chrome.runtime.sendMessage({ type, payload }) +} + +export function onMessage( + type: T, + handler: ( + payload: MessagePayloadMap[T], + sender: chrome.runtime.MessageSender, + sendResponse: (response: MessageResponse) => void, + ) => void | boolean, +): void { + chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { + if (message.type === type) { + return handler(message.payload, sender, sendResponse) + } + }) +} + +export function sendToContent( + tabId: number, + type: T, + payload: MessagePayloadMap[T], +): Promise> { + return chrome.tabs.sendMessage(tabId, { type, payload }) +} + +export function sendToPanel( + type: T, + payload: MessagePayloadMap[T], +): Promise> { + return chrome.runtime.sendMessage({ type, payload }) +} diff --git a/src/lib/storage.ts b/src/lib/storage.ts new file mode 100644 index 0000000..0e5efd8 --- /dev/null +++ b/src/lib/storage.ts @@ -0,0 +1,44 @@ +// PixelLens — Chrome Storage Wrapper + +import type { DesignSystem } from '@/types/design-system' +import type { Preferences } from '@/types/messages' + +const PREFS_KEY = 'pixellens_preferences' +const SCANS_KEY = 'pixellens_scans' + +const DEFAULT_PREFERENCES: Preferences = { + colorFormat: 'hex', + gridSize: 8, + theme: 'dark', +} + +export async function getPreferences(): Promise { + const result = await chrome.storage.sync.get(PREFS_KEY) + return { ...DEFAULT_PREFERENCES, ...result[PREFS_KEY] } +} + +export async function setPreferences(prefs: Partial): Promise { + const current = await getPreferences() + await chrome.storage.sync.set({ + [PREFS_KEY]: { ...current, ...prefs }, + }) +} + +export async function saveDesignSystem(ds: DesignSystem): Promise { + const result = await chrome.storage.local.get(SCANS_KEY) + const scans: DesignSystem[] = result[SCANS_KEY] || [] + scans.unshift(ds) + // Keep last 20 scans + const trimmed = scans.slice(0, 20) + await chrome.storage.local.set({ [SCANS_KEY]: trimmed }) +} + +export async function getDesignSystems(): Promise { + const result = await chrome.storage.local.get(SCANS_KEY) + return result[SCANS_KEY] || [] +} + +export async function getLatestDesignSystem(): Promise { + const scans = await getDesignSystems() + return scans[0] || null +} diff --git a/src/popup/Popup.tsx b/src/popup/Popup.tsx new file mode 100644 index 0000000..9ab34d5 --- /dev/null +++ b/src/popup/Popup.tsx @@ -0,0 +1,128 @@ +import { useState, useEffect } from 'react' +import { + MagnifyingGlass, + Scan, + ClockCounterClockwise, + Keyboard, + GearSix, +} from '@phosphor-icons/react' +import { MessageType } from '@/types/messages' + +type InspectStatus = 'idle' | 'active' + +export function Popup() { + const [status, setStatus] = useState('idle') + const [currentUrl, setCurrentUrl] = useState('') + + useEffect(() => { + chrome.tabs.query({ active: true, currentWindow: true }, ([tab]) => { + if (tab?.url) { + try { + setCurrentUrl(new URL(tab.url).hostname) + } catch { + setCurrentUrl(tab.url) + } + } + }) + }, []) + + async function handleInspect() { + const [tab] = await chrome.tabs.query({ active: true, currentWindow: true }) + if (tab?.id) { + const next = status === 'active' ? 'idle' : 'active' + chrome.runtime.sendMessage({ + type: MessageType.TOGGLE_INSPECT, + payload: { active: next === 'active' }, + }) + setStatus(next) + if (next === 'active') window.close() + } + } + + async function handleScan() { + chrome.runtime.sendMessage({ + type: MessageType.SCAN_PAGE, + payload: undefined, + }) + chrome.runtime.sendMessage({ + type: MessageType.OPEN_SIDE_PANEL, + payload: undefined, + }) + window.close() + } + + async function handleLastScan() { + chrome.runtime.sendMessage({ + type: MessageType.OPEN_SIDE_PANEL, + payload: undefined, + }) + window.close() + } + + return ( +
+ {/* Header */} +
+
+ + + + + + PixelLens +
+ {currentUrl && ( + {currentUrl} + )} +
+ + {/* Status */} +
+
+ {status === 'active' ? 'Inspecting' : 'Ready'} +
+ + {/* Actions */} +
+ + + + + +
+ + {/* Shortcuts */} +
+
+ + Shortcuts +
+
+ Toggle inspect + Ctrl+Shift+L +
+
+ Open popup + Ctrl+Shift+P +
+
+ + {/* Footer */} +
+ + v1.0.0 +
+
+ ) +} diff --git a/src/popup/index.html b/src/popup/index.html new file mode 100644 index 0000000..e81190b --- /dev/null +++ b/src/popup/index.html @@ -0,0 +1,12 @@ + + + + + + PixelLens + + +
+ + + diff --git a/src/popup/main.tsx b/src/popup/main.tsx new file mode 100644 index 0000000..bd7612d --- /dev/null +++ b/src/popup/main.tsx @@ -0,0 +1,11 @@ +import React from 'react' +import { createRoot } from 'react-dom/client' +import { Popup } from './Popup' +import '../styles/globals.css' +import './styles/popup.css' + +createRoot(document.getElementById('root')!).render( + + + , +) diff --git a/src/popup/styles/popup.css b/src/popup/styles/popup.css new file mode 100644 index 0000000..dc6eaa1 --- /dev/null +++ b/src/popup/styles/popup.css @@ -0,0 +1,199 @@ +@import "../../styles/globals.css"; + +body { + margin: 0; + width: 320px; + min-height: 400px; + background: var(--color-panel-bg); + color: var(--color-panel-text); + font-family: var(--font-sans); + font-size: 13px; + -webkit-font-smoothing: antialiased; +} + +.popup { + display: flex; + flex-direction: column; + min-height: 400px; + padding: 16px; + gap: 16px; +} + +/* Header */ +.popup-header { + display: flex; + justify-content: space-between; + align-items: center; +} + +.popup-logo { + display: flex; + align-items: center; + gap: 8px; +} + +.popup-title { + font-weight: 600; + font-size: 15px; + letter-spacing: -0.01em; +} + +.popup-url { + color: var(--color-panel-text-dim); + font-size: 11px; + font-family: var(--font-mono); + max-width: 140px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +/* Status */ +.popup-status { + display: flex; + align-items: center; + gap: 8px; + padding: 10px 12px; + background: var(--color-panel-surface); + border: 1px solid var(--color-panel-border); + border-radius: 8px; + font-size: 12px; + color: var(--color-panel-text-dim); +} + +.popup-status-dot { + width: 8px; + height: 8px; + border-radius: 50%; + background: var(--color-panel-text-dim); + transition: background-color 200ms ease; +} + +.popup-status-dot.active { + background: var(--color-success); + box-shadow: 0 0 8px rgba(34, 197, 94, 0.4); +} + +/* Action buttons */ +.popup-actions { + display: flex; + flex-direction: column; + gap: 8px; +} + +.popup-btn { + display: flex; + align-items: center; + gap: 10px; + width: 100%; + padding: 11px 14px; + background: var(--color-panel-surface); + border: 1px solid var(--color-panel-border); + border-radius: 8px; + color: var(--color-panel-text); + font-size: 13px; + font-family: var(--font-sans); + cursor: pointer; + transition: background-color 150ms ease, border-color 150ms ease; +} + +.popup-btn:hover { + background: var(--color-panel-border); + border-color: var(--color-panel-text-dim); +} + +.popup-btn:focus-visible { + outline: none; + box-shadow: 0 0 0 2px var(--color-panel-accent); +} + +.popup-btn-primary { + background: var(--color-panel-accent); + border-color: var(--color-panel-accent); + font-weight: 500; +} + +.popup-btn-primary:hover { + background: var(--color-panel-accent-hover); + border-color: var(--color-panel-accent-hover); +} + +/* Shortcuts */ +.popup-shortcuts { + display: flex; + flex-direction: column; + gap: 8px; + padding: 12px; + background: var(--color-panel-surface); + border: 1px solid var(--color-panel-border); + border-radius: 8px; +} + +.popup-shortcuts-title { + display: flex; + align-items: center; + gap: 6px; + font-size: 11px; + font-weight: 500; + color: var(--color-panel-text-dim); + text-transform: uppercase; + letter-spacing: 0.05em; +} + +.popup-shortcut-row { + display: flex; + justify-content: space-between; + align-items: center; + font-size: 12px; + color: var(--color-panel-text-dim); +} + +.popup-shortcut-row kbd { + padding: 2px 6px; + background: var(--color-panel-bg); + border: 1px solid var(--color-panel-border); + border-radius: 4px; + font-family: var(--font-mono); + font-size: 10px; + color: var(--color-panel-text); +} + +/* Footer */ +.popup-footer { + display: flex; + justify-content: space-between; + align-items: center; + margin-top: auto; + padding-top: 12px; + border-top: 1px solid var(--color-panel-border); +} + +.popup-footer-btn { + display: flex; + align-items: center; + justify-content: center; + width: 28px; + height: 28px; + background: none; + border: 1px solid transparent; + border-radius: 6px; + color: var(--color-panel-text-dim); + cursor: pointer; + transition: color 150ms ease, border-color 150ms ease; +} + +.popup-footer-btn:hover { + color: var(--color-panel-text); + border-color: var(--color-panel-border); +} + +.popup-footer-btn:focus-visible { + outline: none; + box-shadow: 0 0 0 2px var(--color-panel-accent); +} + +.popup-version { + font-size: 10px; + font-family: var(--font-mono); + color: var(--color-panel-text-dim); +} diff --git a/src/sidepanel/App.tsx b/src/sidepanel/App.tsx new file mode 100644 index 0000000..681ebc8 --- /dev/null +++ b/src/sidepanel/App.tsx @@ -0,0 +1,183 @@ +import { useEffect, useRef, useState } from 'react' +import { + MagnifyingGlass, + Scan, + Palette, + Export, + ClockCounterClockwise, +} from '@phosphor-icons/react' +import gsap from 'gsap' +import { usePanelStore, type PanelMode } from './store' +import { MessageType } from '@/types/messages' +import InspectorView from './views/InspectorView' +import ScanView from './views/ScanView' +import DesignSystemView from './views/DesignSystemView' +import ExportView from './views/ExportView' +import HistoryView from './views/HistoryView' + +const MAIN_TABS: { mode: PanelMode; label: string; icon: typeof MagnifyingGlass }[] = [ + { mode: 'inspect', label: 'Inspect', icon: MagnifyingGlass }, + { mode: 'scan', label: 'Scan', icon: Scan }, + { mode: 'design-system', label: 'Design System', icon: Palette }, +] + +const FOOTER_TABS: { mode: PanelMode; icon: typeof Export; label: string }[] = [ + { mode: 'export', icon: Export, label: 'Export' }, + { mode: 'history', icon: ClockCounterClockwise, label: 'History' }, +] + +function App() { + const activeMode = usePanelStore((s) => s.activeMode) + const setMode = usePanelStore((s) => s.setMode) + const setInspectedElement = usePanelStore((s) => s.setInspectedElement) + const setDesignSystem = usePanelStore((s) => s.setDesignSystem) + const setScanProgress = usePanelStore((s) => s.setScanProgress) + const addToHistory = usePanelStore((s) => s.addToHistory) + + const tabsRef = useRef<(HTMLButtonElement | null)[]>([]) + const indicatorRef = useRef(null) + const isFirstRender = useRef(true) + + // GSAP sliding indicator + useEffect(() => { + const idx = MAIN_TABS.findIndex((t) => t.mode === activeMode) + if (idx === -1) return + const el = tabsRef.current[idx] + const indicator = indicatorRef.current + if (!el || !indicator) return + + if (isFirstRender.current) { + gsap.set(indicator, { left: el.offsetLeft, width: el.offsetWidth }) + isFirstRender.current = false + } else { + gsap.to(indicator, { + left: el.offsetLeft, + width: el.offsetWidth, + duration: 0.3, + ease: 'power3.out', + }) + } + }, [activeMode]) + + // Listen for Chrome runtime messages + useEffect(() => { + const listener = ( + message: { type: string; payload: unknown }, + _sender: chrome.runtime.MessageSender, + sendResponse: (response: unknown) => void, + ) => { + if (message.type === MessageType.ELEMENT_SELECTED) { + const payload = message.payload as { element: import('@/types/inspection').InspectedElement } + setInspectedElement(payload.element) + setMode('inspect') + sendResponse({ received: true }) + } + + if (message.type === MessageType.SCAN_PROGRESS) { + const payload = message.payload as { progress: number; phase: string } + setScanProgress({ percent: payload.progress, phase: payload.phase }) + } + + if (message.type === MessageType.SCAN_COMPLETE) { + const payload = message.payload as { designSystem: import('@/types/design-system').DesignSystem } + setDesignSystem(payload.designSystem) + addToHistory(payload.designSystem) + setScanProgress(null) + setMode('scan') + sendResponse({ received: true }) + } + } + + chrome.runtime.onMessage.addListener(listener) + return () => chrome.runtime.onMessage.removeListener(listener) + }, [setInspectedElement, setDesignSystem, setScanProgress, setMode, addToHistory]) + + const renderView = () => { + switch (activeMode) { + case 'inspect': + return + case 'scan': + return + case 'design-system': + return + case 'export': + return + case 'history': + return + } + } + + return ( +
+ {/* Header */} +
+
+
+ P +
+

+ PixelLens +

+
+ + {/* Mode tabs with GSAP sliding indicator */} + +
+ + {/* Content */} +
+ {renderView()} +
+ + {/* Footer */} +
+
+ {FOOTER_TABS.map((tab) => { + const Icon = tab.icon + const isActive = activeMode === tab.mode + return ( + + ) + })} +
+ v1.0.0 +
+
+ ) +} + +export default App diff --git a/src/sidepanel/components/BoxModelViz.tsx b/src/sidepanel/components/BoxModelViz.tsx new file mode 100644 index 0000000..9d93835 --- /dev/null +++ b/src/sidepanel/components/BoxModelViz.tsx @@ -0,0 +1,79 @@ +import type { BoxModel } from '@/types/inspection' + +interface BoxModelVizProps { + boxModel: BoxModel + dimensions: { width: number; height: number } +} + +function parseNum(val: string): string { + const n = parseFloat(val) + return isNaN(n) ? '0' : n === 0 ? '-' : String(Math.round(n)) +} + +function BoxModelViz({ boxModel, dimensions }: BoxModelVizProps) { + return ( +
+ {/* Margin */} +
+
+
+ ) +} + +function Label({ text, position, color }: { text: string; position: string; color: string }) { + const posClass = position === 'top-left' ? 'top-0.5 left-1' : '' + return ( + + {text} + + ) +} + +function Side({ val, position }: { val: string; position: 'top' | 'right' | 'bottom' | 'left' }) { + if (val === '-') return null + + const posMap = { + top: 'top-0.5 left-1/2 -translate-x-1/2', + right: 'right-0.5 top-1/2 -translate-y-1/2', + bottom: 'bottom-0.5 left-1/2 -translate-x-1/2', + left: 'left-0.5 top-1/2 -translate-y-1/2', + } + + return ( + + {val} + + ) +} + +export default BoxModelViz diff --git a/src/sidepanel/components/CSSBlock.tsx b/src/sidepanel/components/CSSBlock.tsx new file mode 100644 index 0000000..7f4cf19 --- /dev/null +++ b/src/sidepanel/components/CSSBlock.tsx @@ -0,0 +1,97 @@ +import { useState } from 'react' +import { Copy, Check } from '@phosphor-icons/react' +import { copyToClipboard } from '@/lib/export' + +interface CSSBlockProps { + code: string + language?: 'css' | 'json' | 'js' +} + +function highlightCSS(code: string): { html: string } { + // Basic syntax highlighting via spans + const escaped = code + .replace(/&/g, '&') + .replace(//g, '>') + + const html = escaped + // CSS property names + .replace( + /^(\s*)([\w-]+)(\s*:)/gm, + '$1$2$3', + ) + // CSS values after colon + .replace( + /:\s*(.+?);/g, + ': $1;', + ) + // Selectors and braces + .replace( + /^([.#\w][\w\-.*#\[\]=~|^$:, ]*)\s*\{/gm, + '$1 {', + ) + // Strings + .replace( + /(".*?")/g, + '$1', + ) + // Numbers + .replace( + /\b(\d+\.?\d*)(px|rem|em|%|vh|vw|s|ms)?\b/g, + '$1$2', + ) + + return { html } +} + +function CSSBlock({ code, language = 'css' }: CSSBlockProps) { + const [copied, setCopied] = useState(false) + + const handleCopy = async () => { + await copyToClipboard(code) + setCopied(true) + setTimeout(() => setCopied(false), 1500) + } + + const lines = code.split('\n') + const { html } = language === 'css' ? highlightCSS(code) : { html: '' } + + return ( +
+ {/* Copy button */} + + + {/* Code */} +
+ {language === 'css' ? ( +
+            
+          
+ ) : ( +
+            {lines.map((line, i) => (
+              
+ + {i + 1} + + {line} +
+ ))} +
+ )} +
+
+ ) +} + +export default CSSBlock diff --git a/src/sidepanel/components/ColorPalette.tsx b/src/sidepanel/components/ColorPalette.tsx new file mode 100644 index 0000000..259c820 --- /dev/null +++ b/src/sidepanel/components/ColorPalette.tsx @@ -0,0 +1,56 @@ +import type { ColorToken, ColorCategory } from '@/types/design-system' +import ColorSwatch from './ColorSwatch' + +interface ColorPaletteProps { + colors: ColorToken[] +} + +const CATEGORY_ORDER: ColorCategory[] = ['primary', 'secondary', 'accent', 'neutral', 'background', 'text'] +const CATEGORY_LABELS: Record = { + primary: 'Primary', + secondary: 'Secondary', + accent: 'Accent', + neutral: 'Neutrals', + background: 'Backgrounds', + text: 'Text', +} + +function ColorPalette({ colors }: ColorPaletteProps) { + // Group by category + const grouped = new Map() + for (const color of colors) { + const cat = color.category + if (!grouped.has(cat)) grouped.set(cat, []) + grouped.get(cat)!.push(color) + } + + // Sort each group by frequency + for (const [, group] of grouped) { + group.sort((a, b) => b.frequency - a.frequency) + } + + const categories = CATEGORY_ORDER.filter((cat) => grouped.has(cat)) + + if (colors.length === 0) { + return

No colors found

+ } + + return ( +
+ {categories.map((cat) => ( +
+

+ {CATEGORY_LABELS[cat]} +

+
+ {grouped.get(cat)!.map((color, i) => ( + + ))} +
+
+ ))} +
+ ) +} + +export default ColorPalette diff --git a/src/sidepanel/components/ColorSwatch.tsx b/src/sidepanel/components/ColorSwatch.tsx new file mode 100644 index 0000000..89bc294 --- /dev/null +++ b/src/sidepanel/components/ColorSwatch.tsx @@ -0,0 +1,118 @@ +import { useState, useRef, useCallback } from 'react' +import { Check } from '@phosphor-icons/react' +import gsap from 'gsap' +import { copyToClipboard } from '@/lib/export' +import { usePanelStore } from '../store' + +interface ColorSwatchProps { + color: string + size?: number + showLabel?: boolean + format?: 'hex' | 'rgb' | 'hsl' +} + +function formatColor(hex: string, format: 'hex' | 'rgb' | 'hsl'): string { + if (format === 'hex') return hex + // Simple conversion for display + const r = parseInt(hex.slice(1, 3), 16) + const g = parseInt(hex.slice(3, 5), 16) + const b = parseInt(hex.slice(5, 7), 16) + if (format === 'rgb') return `rgb(${r}, ${g}, ${b})` + // HSL + const rn = r / 255, gn = g / 255, bn = b / 255 + const max = Math.max(rn, gn, bn), min = Math.min(rn, gn, bn) + const l = (max + min) / 2 + if (max === min) return `hsl(0, 0%, ${Math.round(l * 100)}%)` + const d = max - min + const s = l > 0.5 ? d / (2 - max - min) : d / (max + min) + let h = 0 + if (max === rn) h = ((gn - bn) / d + (gn < bn ? 6 : 0)) / 6 + else if (max === gn) h = ((bn - rn) / d + 2) / 6 + else h = ((rn - gn) / d + 4) / 6 + return `hsl(${Math.round(h * 360)}, ${Math.round(s * 100)}%, ${Math.round(l * 100)}%)` +} + +function ColorSwatch({ color, size = 32, showLabel = false, format }: ColorSwatchProps) { + const storeFormat = usePanelStore((s) => s.colorFormat) + const activeFormat = format || storeFormat + const [copied, setCopied] = useState(false) + const [showTooltip, setShowTooltip] = useState(false) + const timeoutRef = useRef>(undefined) + const btnRef = useRef(null) + + const displayValue = formatColor(color, activeFormat) + + const handleClick = async () => { + await copyToClipboard(displayValue) + setCopied(true) + if (timeoutRef.current) clearTimeout(timeoutRef.current) + timeoutRef.current = setTimeout(() => setCopied(false), 1500) + } + + const handleMouseEnter = useCallback(() => { + setShowTooltip(true) + if (btnRef.current) { + gsap.to(btnRef.current, { + scale: 1.15, + duration: 0.25, + ease: 'back.out(2)', + }) + } + }, []) + + const handleMouseLeave = useCallback(() => { + setShowTooltip(false) + if (btnRef.current) { + gsap.to(btnRef.current, { + scale: 1, + duration: 0.2, + ease: 'power2.out', + }) + } + }, []) + + return ( +
+ + + {/* Tooltip */} + {showTooltip && !copied && ( +
+ {displayValue} +
+ )} + + {/* Copied toast */} + {copied && ( +
+ Copied! +
+ )} + + {showLabel && ( + {displayValue} + )} +
+ ) +} + +export default ColorSwatch diff --git a/src/sidepanel/components/ExportButton.tsx b/src/sidepanel/components/ExportButton.tsx new file mode 100644 index 0000000..a5c5a35 --- /dev/null +++ b/src/sidepanel/components/ExportButton.tsx @@ -0,0 +1,139 @@ +import { useState, useRef, useEffect, useCallback } from 'react' +import { Export, Check } from '@phosphor-icons/react' +import gsap from 'gsap' +import { formatExport } from '@/lib/design-tokens' +import { copyToClipboard, downloadFile, generatePalettePNG } from '@/lib/export' +import type { DesignSystem, ExportFormat } from '@/types/design-system' + +interface ExportButtonProps { + designSystem: DesignSystem + onExport?: (format: ExportFormat) => void +} + +const EXPORT_OPTIONS: { format: ExportFormat; label: string }[] = [ + { format: 'css-variables', label: 'CSS Variables' }, + { format: 'tailwind', label: 'Tailwind Config' }, + { format: 'json', label: 'JSON Tokens' }, + { format: 'png', label: 'PNG Palette' }, +] + +const CONFETTI_COLORS = ['#6366F1', '#818CF8', '#22C55E', '#F59E0B'] + +function ExportButton({ designSystem, onExport }: ExportButtonProps) { + const [open, setOpen] = useState(false) + const [success, setSuccess] = useState(false) + const dropdownRef = useRef(null) + const confettiContainerRef = useRef(null) + + // Close on outside click + useEffect(() => { + if (!open) return + const handler = (e: MouseEvent) => { + if (dropdownRef.current && !dropdownRef.current.contains(e.target as Node)) { + setOpen(false) + } + } + document.addEventListener('mousedown', handler) + return () => document.removeEventListener('mousedown', handler) + }, [open]) + + const spawnConfetti = useCallback(() => { + const container = confettiContainerRef.current + if (!container) return + + // Create 4 particle elements + const particles = Array.from({ length: 4 }, () => { + const el = document.createElement('span') + el.style.cssText = ` + position: absolute; + top: 0; + left: 50%; + width: 6px; + height: 6px; + border-radius: 50%; + pointer-events: none; + background: ${CONFETTI_COLORS[Math.floor(Math.random() * CONFETTI_COLORS.length)]}; + ` + container.appendChild(el) + return el + }) + + // Animate each particle with GSAP + particles.forEach((el) => { + const xDrift = (Math.random() - 0.5) * 60 + const yFly = -(Math.random() * 40 + 20) + + gsap.fromTo( + el, + { x: 0, y: 0, scale: 1, opacity: 1 }, + { + x: xDrift, + y: yFly, + scale: 0, + opacity: 0, + duration: 0.5, + ease: 'power2.out', + onComplete: () => el.remove(), + }, + ) + }) + }, []) + + const handleExport = async (format: ExportFormat) => { + setOpen(false) + + if (format === 'png') { + const blob = generatePalettePNG(designSystem.colors) + const url = URL.createObjectURL(blob) + const a = document.createElement('a') + a.href = url + a.download = 'palette.png' + a.click() + URL.revokeObjectURL(url) + } else { + const output = formatExport(designSystem, format) + await copyToClipboard(output) + } + + setSuccess(true) + spawnConfetti() + setTimeout(() => setSuccess(false), 1500) + onExport?.(format) + } + + return ( +
+ + + {/* Confetti container */} +
+ + {/* Dropdown */} + {open && ( +
+ {EXPORT_OPTIONS.map((opt) => ( + + ))} +
+ )} +
+ ) +} + +export default ExportButton diff --git a/src/sidepanel/components/ShadowPreview.tsx b/src/sidepanel/components/ShadowPreview.tsx new file mode 100644 index 0000000..a4efd50 --- /dev/null +++ b/src/sidepanel/components/ShadowPreview.tsx @@ -0,0 +1,45 @@ +import { useState } from 'react' +import { Check, Copy } from '@phosphor-icons/react' +import { copyToClipboard } from '@/lib/export' +import type { ShadowToken } from '@/types/design-system' + +interface ShadowPreviewProps { + shadow: ShadowToken +} + +function ShadowPreview({ shadow }: ShadowPreviewProps) { + const [copied, setCopied] = useState(false) + + const handleClick = async () => { + await copyToClipboard(shadow.value) + setCopied(true) + setTimeout(() => setCopied(false), 1500) + } + + return ( + + ) +} + +export default ShadowPreview diff --git a/src/sidepanel/components/SpacingScale.tsx b/src/sidepanel/components/SpacingScale.tsx new file mode 100644 index 0000000..113bbc0 --- /dev/null +++ b/src/sidepanel/components/SpacingScale.tsx @@ -0,0 +1,54 @@ +import type { SpacingToken } from '@/types/design-system' + +interface SpacingScaleProps { + spacings: SpacingToken[] + baseUnit: number +} + +function SpacingScale({ spacings, baseUnit }: SpacingScaleProps) { + if (spacings.length === 0) { + return

No spacing values found

+ } + + const maxValue = Math.max(...spacings.map((s) => parseInt(s.value) || 0), 1) + + return ( +
+ {spacings.map((spacing) => { + const numValue = parseInt(spacing.value) || 0 + const widthPercent = Math.max((numValue / maxValue) * 100, 4) + const isBase = numValue === baseUnit + + return ( +
+ + {spacing.value} + +
+
+
+ + {spacing.frequency}x + + {isBase && ( + + BASE + + )} +
+ ) + })} +
+ ) +} + +export default SpacingScale diff --git a/src/sidepanel/components/TypeSpecimen.tsx b/src/sidepanel/components/TypeSpecimen.tsx new file mode 100644 index 0000000..ae4ccf1 --- /dev/null +++ b/src/sidepanel/components/TypeSpecimen.tsx @@ -0,0 +1,61 @@ +import { useState } from 'react' +import { Check, Copy } from '@phosphor-icons/react' +import { copyToClipboard } from '@/lib/export' +import type { TypographyToken } from '@/types/design-system' + +interface TypeSpecimenProps { + typography: TypographyToken + variant?: number +} + +function TypeSpecimen({ typography, variant }: TypeSpecimenProps) { + const [copied, setCopied] = useState(false) + const familyName = typography.fontFamily.split(',')[0].replace(/['"]/g, '').trim() + const displayVariants = variant !== undefined ? [typography.variants[variant]] : typography.variants + + const handleCopy = async () => { + await copyToClipboard(typography.fontFamily) + setCopied(true) + setTimeout(() => setCopied(false), 1500) + } + + return ( +
+ {/* Preview text */} +

+ The quick brown fox jumps over +

+ + {/* Font family + copy */} +
+ +
+ + {/* Variants */} + {displayVariants.filter(Boolean).length > 0 && ( +
+ {displayVariants.filter(Boolean).map((v, i) => ( + + {v.fontSize} / {v.fontWeight} + {v.lineHeight !== 'normal' ? ` / ${v.lineHeight}` : ''} + + ))} +
+ )} +
+ ) +} + +export default TypeSpecimen diff --git a/src/sidepanel/index.html b/src/sidepanel/index.html new file mode 100644 index 0000000..e81190b --- /dev/null +++ b/src/sidepanel/index.html @@ -0,0 +1,12 @@ + + + + + + PixelLens + + +
+ + + diff --git a/src/sidepanel/main.tsx b/src/sidepanel/main.tsx new file mode 100644 index 0000000..6d9bfb5 --- /dev/null +++ b/src/sidepanel/main.tsx @@ -0,0 +1,10 @@ +import React from 'react' +import ReactDOM from 'react-dom/client' +import App from './App' +import './styles/panel.css' + +ReactDOM.createRoot(document.getElementById('root')!).render( + + + , +) diff --git a/src/sidepanel/store.ts b/src/sidepanel/store.ts new file mode 100644 index 0000000..ffdca37 --- /dev/null +++ b/src/sidepanel/store.ts @@ -0,0 +1,45 @@ +import { create } from 'zustand' +import type { InspectedElement } from '@/types/inspection' +import type { DesignSystem } from '@/types/design-system' + +export type PanelMode = 'inspect' | 'scan' | 'design-system' | 'export' | 'history' + +export interface ScanProgress { + percent: number + phase: string +} + +interface PanelState { + activeMode: PanelMode + inspectedElement: InspectedElement | null + designSystem: DesignSystem | null + scanProgress: ScanProgress | null + colorFormat: 'hex' | 'rgb' | 'hsl' + history: DesignSystem[] + + setMode: (mode: PanelMode) => void + setInspectedElement: (el: InspectedElement | null) => void + setDesignSystem: (ds: DesignSystem | null) => void + setScanProgress: (progress: ScanProgress | null) => void + setColorFormat: (format: 'hex' | 'rgb' | 'hsl') => void + addToHistory: (ds: DesignSystem) => void + clearHistory: () => void +} + +export const usePanelStore = create((set) => ({ + activeMode: 'inspect', + inspectedElement: null, + designSystem: null, + scanProgress: null, + colorFormat: 'hex', + history: [], + + setMode: (mode) => set({ activeMode: mode }), + setInspectedElement: (el) => set({ inspectedElement: el }), + setDesignSystem: (ds) => set({ designSystem: ds }), + setScanProgress: (progress) => set({ scanProgress: progress }), + setColorFormat: (format) => set({ colorFormat: format }), + addToHistory: (ds) => + set((state) => ({ history: [ds, ...state.history].slice(0, 20) })), + clearHistory: () => set({ history: [] }), +})) diff --git a/src/sidepanel/styles/panel.css b/src/sidepanel/styles/panel.css new file mode 100644 index 0000000..ec9dd2e --- /dev/null +++ b/src/sidepanel/styles/panel.css @@ -0,0 +1,115 @@ +@import "tailwindcss"; +@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=JetBrains+Mono:wght@400&display=swap'); + +@theme { + --color-panel-bg: #0C0C0E; + --color-panel-surface: #161618; + --color-panel-border: #222225; + --color-panel-text: #EDEDEF; + --color-panel-text-dim: #7E7E85; + --color-panel-accent: #6366F1; + --color-panel-accent-hover: #818CF8; + --color-success: #22C55E; + --font-sans: "Inter", ui-sans-serif, system-ui, sans-serif; + --font-mono: "JetBrains Mono", ui-monospace, monospace; +} + +/* Base */ +body { + background-color: var(--color-panel-bg); + color: var(--color-panel-text); + font-family: var(--font-sans); + font-size: 13px; + line-height: 1.5; + margin: 0; + padding: 0; + overflow: hidden; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +#root { + height: 100vh; + display: flex; + flex-direction: column; +} + +/* Custom scrollbar */ +::-webkit-scrollbar { + width: 6px; +} + +::-webkit-scrollbar-track { + background: transparent; +} + +::-webkit-scrollbar-thumb { + background: var(--color-panel-border); + border-radius: 3px; +} + +::-webkit-scrollbar-thumb:hover { + background: var(--color-panel-text-dim); +} + +/* Toast animation */ +@keyframes toast-slide-up { + from { + transform: translateY(8px); + opacity: 0; + } + to { + transform: translateY(0); + opacity: 1; + } +} + +@keyframes toast-fade-out { + from { + opacity: 1; + } + to { + opacity: 0; + } +} + +/* Shimmer for progress bar */ +@keyframes shimmer { + 0% { + background-position: -200% 0; + } + 100% { + background-position: 200% 0; + } +} + +/* Confetti particle */ +@keyframes confetti-pop { + 0% { + transform: translate(0, 0) scale(1); + opacity: 1; + } + 100% { + transform: translate(var(--confetti-x), var(--confetti-y)) scale(0); + opacity: 0; + } +} + +.toast-enter { + animation: toast-slide-up 200ms ease-out; +} + +.toast-exit { + animation: toast-fade-out 200ms ease-in forwards; +} + +.shimmer-bar { + background: linear-gradient( + 90deg, + var(--color-panel-accent) 0%, + var(--color-panel-accent-hover) 50%, + var(--color-panel-accent) 100% + ); + background-size: 200% 100%; + animation: shimmer 1.5s ease-in-out infinite; +} diff --git a/src/sidepanel/views/DesignSystemView.tsx b/src/sidepanel/views/DesignSystemView.tsx new file mode 100644 index 0000000..ae3a8a5 --- /dev/null +++ b/src/sidepanel/views/DesignSystemView.tsx @@ -0,0 +1,226 @@ +import { useState } from 'react' +import { Palette, TextT, ArrowsOutSimple, Circle, Drop, Trash } from '@phosphor-icons/react' +import { usePanelStore } from '../store' +import ExportButton from '../components/ExportButton' +import ColorSwatch from '../components/ColorSwatch' +import ShadowPreview from '../components/ShadowPreview' +import type { DesignSystem } from '@/types/design-system' + +function DesignSystemView() { + const designSystem = usePanelStore((s) => s.designSystem) + const setDesignSystem = usePanelStore((s) => s.setDesignSystem) + const setMode = usePanelStore((s) => s.setMode) + + if (!designSystem) { + return ( +
+
+ +
+
+

No design system yet

+

+ Scan a page first to generate a design system +

+ +
+
+ ) + } + + const handleRemoveColor = (index: number) => { + const updated: DesignSystem = { + ...designSystem, + colors: designSystem.colors.filter((_, i) => i !== index), + } + setDesignSystem(updated) + } + + const handleRenameColor = (index: number, newName: string) => { + const updated: DesignSystem = { + ...designSystem, + colors: designSystem.colors.map((c, i) => (i === index ? { ...c, name: newName } : c)), + } + setDesignSystem(updated) + } + + return ( +
+ {/* Header with export */} +
+
+

{designSystem.metadata.title}

+

+ {designSystem.metadata.url} +

+
+ +
+ + {/* Content */} +
+ {/* Colors */} + } count={designSystem.colors.length}> +
+ {designSystem.colors.map((color, i) => ( +
+ + handleRenameColor(i, v)} + /> + + {color.hex} + + +
+ ))} +
+
+ + {/* Typography */} + } count={designSystem.typography.length}> +
+ {designSystem.typography.map((font) => ( +
+

+ {font.fontFamily.split(',')[0].replace(/['"]/g, '')} +

+
+ {font.variants.map((v, i) => ( + + {v.fontSize} / {v.fontWeight} + + ))} +
+
+ ))} +
+
+ + {/* Spacing */} + } count={designSystem.spacing.length}> +
+ {designSystem.spacing.map((s) => ( +
+
+ {s.value} +
+ ))} +
+ + + {/* Border Radius */} + } count={designSystem.borderRadius.length}> +
+ {designSystem.borderRadius.map((br) => ( +
+
+ {br.value} +
+ ))} +
+ + + {/* Shadows */} + } count={designSystem.shadows.length}> +
+ {designSystem.shadows.map((shadow, i) => ( + + ))} +
+
+
+
+ ) +} + +function DSSection({ + title, + icon, + count, + children, +}: { + title: string + icon: React.ReactNode + count: number + children: React.ReactNode +}) { + return ( +
+
+ {icon} +

{title}

+ + {count} + +
+ {children} +
+ ) +} + +function EditableLabel({ + value, + onChange, +}: { + value: string + onChange: (v: string) => void +}) { + const [editing, setEditing] = useState(false) + const [draft, setDraft] = useState(value) + + if (editing) { + return ( + setDraft(e.target.value)} + onBlur={() => { + onChange(draft) + setEditing(false) + }} + onKeyDown={(e) => { + if (e.key === 'Enter') { + onChange(draft) + setEditing(false) + } + if (e.key === 'Escape') setEditing(false) + }} + autoFocus + /> + ) + } + + return ( + + ) +} + +export default DesignSystemView diff --git a/src/sidepanel/views/ExportView.tsx b/src/sidepanel/views/ExportView.tsx new file mode 100644 index 0000000..d79a27c --- /dev/null +++ b/src/sidepanel/views/ExportView.tsx @@ -0,0 +1,111 @@ +import { useState } from 'react' +import { Copy, DownloadSimple, FileCode } from '@phosphor-icons/react' +import { usePanelStore } from '../store' +import CSSBlock from '../components/CSSBlock' +import { formatExport } from '@/lib/design-tokens' +import { copyToClipboard, downloadFile } from '@/lib/export' +import type { ExportFormat } from '@/types/design-system' + +const FORMATS: { id: ExportFormat; label: string; ext: string; mime: string }[] = [ + { id: 'css-variables', label: 'CSS Variables', ext: 'css', mime: 'text/css' }, + { id: 'tailwind', label: 'Tailwind', ext: 'js', mime: 'text/javascript' }, + { id: 'json', label: 'JSON', ext: 'json', mime: 'application/json' }, +] + +function ExportView() { + const designSystem = usePanelStore((s) => s.designSystem) + const setMode = usePanelStore((s) => s.setMode) + const [format, setFormat] = useState('css-variables') + const [copied, setCopied] = useState(false) + + if (!designSystem) { + return ( +
+
+ +
+
+

Nothing to export

+

+ Scan a page first to generate exportable tokens +

+ +
+
+ ) + } + + const output = formatExport(designSystem, format) + const currentFormat = FORMATS.find((f) => f.id === format)! + + const handleCopy = async () => { + await copyToClipboard(output) + setCopied(true) + setTimeout(() => setCopied(false), 1500) + } + + const handleDownload = () => { + const filename = `design-tokens.${currentFormat.ext}` + downloadFile(output, filename, currentFormat.mime) + } + + return ( +
+ {/* Format selector */} +
+
+ {FORMATS.map((f) => ( + + ))} +
+
+ + {/* Code preview */} +
+ +
+ + {/* Actions */} +
+ + +
+
+ ) +} + +export default ExportView diff --git a/src/sidepanel/views/HistoryView.tsx b/src/sidepanel/views/HistoryView.tsx new file mode 100644 index 0000000..ec38fb9 --- /dev/null +++ b/src/sidepanel/views/HistoryView.tsx @@ -0,0 +1,133 @@ +import { useEffect, useState } from 'react' +import { ClockCounterClockwise, Trash } from '@phosphor-icons/react' +import { usePanelStore } from '../store' +import { getDesignSystems } from '@/lib/storage' +import type { DesignSystem } from '@/types/design-system' + +function timeAgo(dateStr: string): string { + const now = Date.now() + const then = new Date(dateStr).getTime() + const diff = now - then + const minutes = Math.floor(diff / 60000) + if (minutes < 1) return 'just now' + if (minutes < 60) return `${minutes}m ago` + const hours = Math.floor(minutes / 60) + if (hours < 24) return `${hours}h ago` + const days = Math.floor(hours / 24) + return `${days}d ago` +} + +function HistoryView() { + const setDesignSystem = usePanelStore((s) => s.setDesignSystem) + const setMode = usePanelStore((s) => s.setMode) + const storeHistory = usePanelStore((s) => s.history) + const clearHistory = usePanelStore((s) => s.clearHistory) + const [history, setHistory] = useState([]) + const [loading, setLoading] = useState(true) + + useEffect(() => { + getDesignSystems() + .then((scans) => { + // Merge store history with storage, deduplicate by url+time + const allScans = [...scans] + for (const ds of storeHistory) { + const exists = allScans.some( + (s) => s.metadata.url === ds.metadata.url && s.metadata.scannedAt === ds.metadata.scannedAt, + ) + if (!exists) allScans.push(ds) + } + allScans.sort( + (a, b) => new Date(b.metadata.scannedAt).getTime() - new Date(a.metadata.scannedAt).getTime(), + ) + setHistory(allScans) + }) + .finally(() => setLoading(false)) + }, [storeHistory]) + + const handleSelect = (ds: DesignSystem) => { + setDesignSystem(ds) + setMode('design-system') + } + + const handleClear = () => { + clearHistory() + setHistory([]) + } + + if (loading) { + return ( +
+ Loading... +
+ ) + } + + if (history.length === 0) { + return ( +
+
+ +
+
+

No scan history

+

+ Your previous scans will appear here +

+
+
+ ) + } + + return ( +
+
+ {history.map((ds, i) => ( + + ))} +
+ + {/* Clear button */} +
+ +
+
+ ) +} + +export default HistoryView diff --git a/src/sidepanel/views/InspectorView.tsx b/src/sidepanel/views/InspectorView.tsx new file mode 100644 index 0000000..0e7dd00 --- /dev/null +++ b/src/sidepanel/views/InspectorView.tsx @@ -0,0 +1,231 @@ +import { useState } from 'react' +import { + CaretDown, + Eyedropper, + TextT, + BoundingBox, + Sparkle, + Code, + CursorClick, +} from '@phosphor-icons/react' +import { usePanelStore } from '../store' +import type { ColorInfo, TypographyInfo, EffectsInfo } from '@/types/inspection' +import ColorSwatch from '../components/ColorSwatch' +import TypeSpecimen from '../components/TypeSpecimen' +import BoxModelViz from '../components/BoxModelViz' +import ShadowPreview from '../components/ShadowPreview' +import CSSBlock from '../components/CSSBlock' +import { generateCSSBlock } from '@/lib/css-parser' +import { toHex, toRgb, toHsl } from '@/lib/colors' + +// Extract color, typography, effects from computed styles +function extractColors(styles: Record): ColorInfo[] { + const colorProps = [ + 'color', 'background-color', 'border-color', + 'border-top-color', 'border-right-color', + 'border-bottom-color', 'border-left-color', + ] + const colors: ColorInfo[] = [] + for (const prop of colorProps) { + const value = styles[prop] + if (!value || value === 'transparent' || value === 'rgba(0, 0, 0, 0)') continue + colors.push({ + property: prop, + value, + hex: toHex(value), + rgb: toRgb(value), + hsl: toHsl(value), + }) + } + return colors +} + +function extractTypography(styles: Record): TypographyInfo { + return { + fontFamily: styles['font-family'] || '', + fontSize: styles['font-size'] || '', + fontWeight: styles['font-weight'] || '', + lineHeight: styles['line-height'] || '', + letterSpacing: styles['letter-spacing'] || '', + } +} + +function extractEffects(styles: Record): EffectsInfo { + return { + boxShadow: styles['box-shadow'] || 'none', + opacity: styles['opacity'] || '1', + backdropFilter: styles['backdrop-filter'] || 'none', + borderRadius: styles['border-radius'] || '0px', + } +} + +interface SectionProps { + title: string + icon: React.ReactNode + defaultOpen?: boolean + children: React.ReactNode +} + +function Section({ title, icon, defaultOpen = true, children }: SectionProps) { + const [open, setOpen] = useState(defaultOpen) + + return ( +
+ +
+
+
{children}
+
+
+
+ ) +} + +function InspectorView() { + const element = usePanelStore((s) => s.inspectedElement) + + if (!element) { + return ( +
+
+ +
+
+

No element selected

+

+ Click on any element on the page to inspect its styles +

+
+
+ ) + } + + const colors = extractColors(element.computedStyles) + const typo = extractTypography(element.computedStyles) + const effects = extractEffects(element.computedStyles) + const cssCode = generateCSSBlock(element.computedStyles) + + // Build element path string + let elementPath = element.tagName + if (element.id) elementPath += `#${element.id}` + if (element.className) { + const classes = element.className.split(/\s+/).filter(Boolean).slice(0, 3) + if (classes.length) elementPath += `.${classes.join('.')}` + } + + return ( +
+ {/* Element info bar */} +
+

{elementPath}

+

+ {Math.round(element.rect.width)} x {Math.round(element.rect.height)}px +

+
+ + {/* Colors */} + {colors.length > 0 && ( +
}> +
+ {colors.map((c) => ( +
+ +
+

{c.property}

+

{c.hex}

+
+
+ ))} +
+
+ )} + + {/* Typography */} +
}> + +
+ + {/* Box Model */} +
}> + +
+ + {/* Effects */} +
}> +
+ {effects.boxShadow !== 'none' && ( +
+

box-shadow

+ +
+ )} + {effects.borderRadius !== '0px' && ( +
+ border-radius + {effects.borderRadius} +
+ )} + {effects.opacity !== '1' && ( +
+ opacity + {effects.opacity} +
+ )} + {effects.backdropFilter !== 'none' && ( +
+ backdrop-filter + {effects.backdropFilter} +
+ )} + {effects.boxShadow === 'none' && + effects.borderRadius === '0px' && + effects.opacity === '1' && + effects.backdropFilter === 'none' && ( +

No effects

+ )} +
+
+ + {/* Raw CSS */} +
} defaultOpen={false}> + +
+
+ ) +} + +export default InspectorView diff --git a/src/sidepanel/views/ScanView.tsx b/src/sidepanel/views/ScanView.tsx new file mode 100644 index 0000000..a88db83 --- /dev/null +++ b/src/sidepanel/views/ScanView.tsx @@ -0,0 +1,208 @@ +import { useState, useRef, useEffect } from 'react' +import { Play, Palette, TextT, ArrowsOutSimple, Drop } from '@phosphor-icons/react' +import gsap from 'gsap' +import { usePanelStore } from '../store' +import { sendMessage } from '@/lib/messaging' +import { MessageType } from '@/types/messages' +import ColorPalette from '../components/ColorPalette' +import TypeSpecimen from '../components/TypeSpecimen' +import SpacingScale from '../components/SpacingScale' +import ShadowPreview from '../components/ShadowPreview' + +type ScanTab = 'colors' | 'fonts' | 'spacing' | 'shadows' + +const TABS: { id: ScanTab; label: string; icon: typeof Palette }[] = [ + { id: 'colors', label: 'Colors', icon: Palette }, + { id: 'fonts', label: 'Fonts', icon: TextT }, + { id: 'spacing', label: 'Spacing', icon: ArrowsOutSimple }, + { id: 'shadows', label: 'Shadows', icon: Drop }, +] + +function ScanView() { + const scanProgress = usePanelStore((s) => s.scanProgress) + const designSystem = usePanelStore((s) => s.designSystem) + const setMode = usePanelStore((s) => s.setMode) + const [activeTab, setActiveTab] = useState('colors') + const tabsRef = useRef<(HTMLButtonElement | null)[]>([]) + const [indicatorStyle, setIndicatorStyle] = useState({ left: 0, width: 0 }) + const progressBarRef = useRef(null) + const shimmerRef = useRef(null) + + useEffect(() => { + const idx = TABS.findIndex((t) => t.id === activeTab) + const el = tabsRef.current[idx] + if (!el) return + setIndicatorStyle({ left: el.offsetLeft, width: el.offsetWidth }) + }, [activeTab]) + + // GSAP: animate progress bar width + gradient shimmer + useEffect(() => { + const bar = progressBarRef.current + if (!bar || !scanProgress) return + + gsap.to(bar, { + width: `${scanProgress.percent}%`, + duration: 0.3, + ease: 'power2.out', + }) + + // Shimmer loop — only create once + if (!shimmerRef.current) { + shimmerRef.current = gsap.fromTo( + bar, + { backgroundPosition: '-200% 0' }, + { + backgroundPosition: '200% 0', + duration: 1.5, + ease: 'none', + repeat: -1, + }, + ) + } + + return () => { + if (shimmerRef.current) { + shimmerRef.current.kill() + shimmerRef.current = null + } + } + }, [scanProgress]) + + const handleStartScan = () => { + sendMessage(MessageType.SCAN_PAGE, undefined) + } + + // Scanning in progress + if (scanProgress) { + return ( +
+
+
+
+
+

+ {scanProgress.phase} +

+

+ {scanProgress.percent}% +

+
+
+ ) + } + + // No scan results yet + if (!designSystem) { + return ( +
+
+ +
+
+

Scan this page

+

+ Extract colors, fonts, spacing, and shadows from the entire page +

+ +
+
+ ) + } + + // Scan results with tabs + const renderTabContent = () => { + switch (activeTab) { + case 'colors': + return + case 'fonts': + return ( +
+ {designSystem.typography.map((font) => ( + + ))} + {designSystem.typography.length === 0 && ( +

No fonts found

+ )} +
+ ) + case 'spacing': + return ( + + ) + case 'shadows': + return ( +
+ {designSystem.shadows.map((shadow, i) => ( + + ))} + {designSystem.shadows.length === 0 && ( +

No shadows found

+ )} +
+ ) + } + } + + return ( +
+ {/* Scan result tabs */} + + + {/* Tab content */} +
+ {renderTabContent()} +
+ + {/* Generate DS button */} +
+ +
+
+ ) +} + +export default ScanView diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 0000000..c43c20b --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,15 @@ +import { defineConfig } from 'vitest/config'; +import path from 'path'; + +export default defineConfig({ + test: { + environment: 'jsdom', + globals: true, + include: ['src/**/*.test.ts', 'src/**/*.test.tsx'], + }, + resolve: { + alias: { + '@': path.resolve(__dirname, './src'), + }, + }, +});