@apliteni/apliteni-ui 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@apliteni/apliteni-ui",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "description": "Apliteni shared design system & UI kit — tokens, components and the deck theme, framework-agnostic (HTML + CSS).",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
@@ -16,10 +16,12 @@
16
16
  },
17
17
  "exports": {
18
18
  ".": "./src/index.js",
19
+ "./motion": "./src/motion.js",
19
20
  "./inline": "./src/inline.js",
20
21
  "./css": "./src/index.css",
21
22
  "./tokens": "./src/tokens/tokens.css",
22
- "./accents": "./src/tokens/accents.css"
23
+ "./accents": "./src/tokens/accents.css",
24
+ "./brand": "./src/tokens/brand.generated.css"
23
25
  },
24
26
  "files": [
25
27
  "src",
@@ -32,7 +34,10 @@
32
34
  "scripts": {
33
35
  "storybook": "storybook dev -p 6006 --no-open",
34
36
  "build-storybook": "storybook build -o storybook-static",
35
- "test": "node --test"
37
+ "test": "node --test",
38
+ "tokens:sync": "node scripts/sync-brand-tokens.mjs",
39
+ "tokens:check": "node scripts/sync-brand-tokens.mjs --check",
40
+ "tokens:drift": "node scripts/brand-drift.mjs"
36
41
  },
37
42
  "engines": {
38
43
  "node": ">=20"
@@ -0,0 +1,27 @@
1
+ <svg width="263" height="74" viewBox="0 0 263 74" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M112.948 45.7844H100.478L98.4151 51.7427H91.8213L103.08 20.4281H110.392L121.65 51.7427H115.012L112.948 45.7844ZM111.244 40.7669L106.713 27.6856L102.183 40.7669H111.244Z" fill="#191919"/>
3
+ <path d="M132.138 30.5079C132.946 29.373 134.052 28.4322 135.458 27.6856C136.893 26.909 138.523 26.5208 140.347 26.5208C142.47 26.5208 144.384 27.0434 146.089 28.0888C147.823 29.1341 149.184 30.6274 150.17 32.5687C151.187 34.4801 151.696 36.7051 151.696 39.2437C151.696 41.7824 151.187 44.0373 150.17 46.0084C149.184 47.9497 147.823 49.4579 146.089 50.5331C144.384 51.6083 142.47 52.1459 140.347 52.1459C138.523 52.1459 136.908 51.7726 135.503 51.0259C134.127 50.2793 133.006 49.3385 132.138 48.2036V63.5697H125.859V26.924H132.138V30.5079ZM145.281 39.2437C145.281 37.7504 144.967 36.4662 144.339 35.391C143.741 34.286 142.934 33.4497 141.917 32.8823C140.93 32.3148 139.854 32.0311 138.687 32.0311C137.551 32.0311 136.475 32.3297 135.458 32.9271C134.471 33.4945 133.664 34.3308 133.036 35.4358C132.438 36.5409 132.138 37.84 132.138 39.3333C132.138 40.8266 132.438 42.1258 133.036 43.2309C133.664 44.3359 134.471 45.1871 135.458 45.7844C136.475 46.3519 137.551 46.6356 138.687 46.6356C139.854 46.6356 140.93 46.3369 141.917 45.7396C142.934 45.1423 143.741 44.2911 144.339 43.1861C144.967 42.081 145.281 40.7669 145.281 39.2437Z" fill="#191919"/>
4
+ <path d="M162.539 18.5913V51.7427H156.259V18.5913H162.539Z" fill="#191919"/>
5
+ <path d="M171.928 23.9672C170.821 23.9672 169.894 23.6238 169.147 22.9369C168.429 22.2201 168.07 21.339 168.07 20.2937C168.07 19.2484 168.429 18.3823 169.147 17.6954C169.894 16.9786 170.821 16.6202 171.928 16.6202C173.034 16.6202 173.946 16.9786 174.664 17.6954C175.412 18.3823 175.785 19.2484 175.785 20.2937C175.785 21.339 175.412 22.2201 174.664 22.9369C173.946 23.6238 173.034 23.9672 171.928 23.9672ZM175.023 26.924V51.7427H168.743V26.924H175.023Z" fill="#191919"/>
6
+ <path d="M188.539 32.0759V44.0821C188.539 44.9183 188.733 45.5306 189.122 45.9188C189.541 46.2772 190.228 46.4564 191.185 46.4564H194.101V51.7427H190.154C184.861 51.7427 182.214 49.1742 182.214 44.0373V32.0759H179.254V26.924H182.214V20.7865H188.539V26.924H194.101V32.0759H188.539Z" fill="#191919"/>
7
+ <path d="M221.718 38.7958C221.718 39.6917 221.659 40.4981 221.539 41.2149H203.372C203.522 43.0069 204.15 44.4106 205.256 45.426C206.363 46.4415 207.723 46.9492 209.338 46.9492C211.671 46.9492 213.33 45.9487 214.317 43.9477H221.09C220.373 46.3369 218.997 48.3081 216.964 49.8611C214.93 51.3843 212.433 52.1459 209.473 52.1459C207.08 52.1459 204.927 51.6232 203.014 50.5779C201.13 49.5027 199.649 47.9945 198.573 46.0532C197.526 44.1119 197.003 41.872 197.003 39.3333C197.003 36.7649 197.526 34.51 198.573 32.5687C199.619 30.6274 201.085 29.1341 202.969 28.0888C204.853 27.0434 207.021 26.5208 209.473 26.5208C211.835 26.5208 213.943 27.0285 215.797 28.044C217.681 29.0594 219.132 30.5079 220.148 32.3895C221.195 34.2412 221.718 36.3766 221.718 38.7958ZM215.214 37.0038C215.184 35.391 214.601 34.1068 213.465 33.1511C212.329 32.1655 210.938 31.6727 209.293 31.6727C207.738 31.6727 206.423 32.1505 205.346 33.1063C204.299 34.0321 203.657 35.3313 203.417 37.0038H215.214Z" fill="#191919"/>
8
+ <path d="M240.073 26.5656C243.033 26.5656 245.426 27.5064 247.25 29.3879C249.074 31.2396 249.986 33.838 249.986 37.183V51.7427H243.706V38.0342C243.706 36.063 243.213 34.5548 242.226 33.5095C241.239 32.4343 239.893 31.8967 238.189 31.8967C236.454 31.8967 235.079 32.4343 234.062 33.5095C233.075 34.5548 232.582 36.063 232.582 38.0342V51.7427H226.302V26.924H232.582V30.0151C233.419 28.9399 234.481 28.1037 235.767 27.5064C237.082 26.8792 238.518 26.5656 240.073 26.5656Z" fill="#191919"/>
9
+ <path d="M259.142 23.9672C258.036 23.9672 257.109 23.6238 256.361 22.9369C255.644 22.2201 255.285 21.339 255.285 20.2937C255.285 19.2484 255.644 18.3823 256.361 17.6954C257.109 16.9786 258.036 16.6202 259.142 16.6202C260.249 16.6202 261.161 16.9786 261.879 17.6954C262.626 18.3823 263 19.2484 263 20.2937C263 21.339 262.626 22.2201 261.879 22.9369C261.161 23.6238 260.249 23.9672 259.142 23.9672ZM262.237 26.924V51.7427H255.958V26.924H262.237Z" fill="#191919"/>
10
+ <g clip-path="url(#clip0_8584_3)">
11
+ <path d="M49.9674 73.4308C49.6804 74.3567 51.5816 68.8367 52.0837 64.9906C54.5588 46.2939 51.6174 28.2026 33.0366 13.3877C23.8179 6.01581 11.8372 2.13402 0 2.66821C4.26857 3.55853 6.85124 8.01012 7.53277 12.3193C8.21431 16.5928 7.4969 20.9732 7.99909 25.2823C9.00346 33.9362 15.0297 41.6642 22.8494 45.6528C29.9159 49.2497 38.2378 49.962 46.0575 48.3594C46.0575 48.3594 38.4171 29.1997 24.2842 23.3592C24.2842 23.3592 43.3673 29.0929 48.8913 47.5403C52.5501 59.8979 49.9674 73.4308 49.9674 73.4308Z" fill="url(#paint0_linear_8584_3)"/>
12
+ <path d="M52.9804 36.9619C52.9445 36.855 52.9087 36.7482 52.8728 36.677C54.7381 29.1271 61.4458 21.8621 66.109 19.6541C61.3741 19.8321 53.4109 27.1327 50.9358 31.62C49.4293 28.2367 47.5281 25.0316 45.2324 22.0045C53.6978 13.0301 73.1754 13.0301 76.7983 -0.00418091C78.1614 8.40043 78.1614 20.8293 74.6461 28.5929C71.3102 35.9291 64.3154 46.3993 54.8098 45.1528C54.4152 42.3038 53.8054 39.5616 52.9804 36.9619Z" fill="url(#paint1_linear_8584_3)"/>
13
+ </g>
14
+ <defs>
15
+ <linearGradient id="paint0_linear_8584_3" x1="46.1388" y1="27.7919" x2="15.268" y2="43.0653" gradientUnits="userSpaceOnUse">
16
+ <stop stop-color="#8CC63F"/>
17
+ <stop offset="1" stop-color="#009245"/>
18
+ </linearGradient>
19
+ <linearGradient id="paint1_linear_8584_3" x1="77.6788" y1="22.617" x2="45.2565" y2="22.617" gradientUnits="userSpaceOnUse">
20
+ <stop stop-color="#8CC63F"/>
21
+ <stop offset="1" stop-color="#009245"/>
22
+ </linearGradient>
23
+ <clipPath id="clip0_8584_3">
24
+ <rect width="77.6952" height="73.5404" fill="#191919"/>
25
+ </clipPath>
26
+ </defs>
27
+ </svg>
@@ -0,0 +1,27 @@
1
+ <svg width="263" height="74" viewBox="0 0 263 74" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M112.948 45.7844H100.478L98.4151 51.7427H91.8213L103.08 20.4281H110.392L121.65 51.7427H115.012L112.948 45.7844ZM111.244 40.7669L106.713 27.6856L102.183 40.7669H111.244Z" fill="white"/>
3
+ <path d="M132.138 30.5079C132.946 29.373 134.052 28.4322 135.458 27.6856C136.893 26.909 138.523 26.5208 140.347 26.5208C142.47 26.5208 144.384 27.0434 146.089 28.0888C147.823 29.1341 149.184 30.6274 150.17 32.5687C151.187 34.4801 151.696 36.7051 151.696 39.2437C151.696 41.7824 151.187 44.0373 150.17 46.0084C149.184 47.9497 147.823 49.4579 146.089 50.5331C144.384 51.6083 142.47 52.1459 140.347 52.1459C138.523 52.1459 136.908 51.7726 135.503 51.0259C134.127 50.2793 133.006 49.3385 132.138 48.2036V63.5697H125.859V26.924H132.138V30.5079ZM145.281 39.2437C145.281 37.7504 144.967 36.4662 144.339 35.391C143.741 34.286 142.934 33.4497 141.917 32.8823C140.93 32.3148 139.854 32.0311 138.687 32.0311C137.551 32.0311 136.475 32.3297 135.458 32.9271C134.471 33.4945 133.664 34.3308 133.036 35.4358C132.438 36.5409 132.138 37.84 132.138 39.3333C132.138 40.8266 132.438 42.1258 133.036 43.2309C133.664 44.3359 134.471 45.1871 135.458 45.7844C136.475 46.3519 137.551 46.6356 138.687 46.6356C139.854 46.6356 140.93 46.3369 141.917 45.7396C142.934 45.1423 143.741 44.2911 144.339 43.1861C144.967 42.081 145.281 40.7669 145.281 39.2437Z" fill="white"/>
4
+ <path d="M162.539 18.5913V51.7427H156.259V18.5913H162.539Z" fill="white"/>
5
+ <path d="M171.928 23.9672C170.821 23.9672 169.894 23.6238 169.147 22.9369C168.429 22.2201 168.07 21.339 168.07 20.2937C168.07 19.2484 168.429 18.3823 169.147 17.6954C169.894 16.9786 170.821 16.6202 171.928 16.6202C173.034 16.6202 173.946 16.9786 174.664 17.6954C175.412 18.3823 175.785 19.2484 175.785 20.2937C175.785 21.339 175.412 22.2201 174.664 22.9369C173.946 23.6238 173.034 23.9672 171.928 23.9672ZM175.023 26.924V51.7427H168.743V26.924H175.023Z" fill="white"/>
6
+ <path d="M188.539 32.0759V44.0821C188.539 44.9183 188.733 45.5306 189.122 45.9188C189.541 46.2772 190.228 46.4564 191.185 46.4564H194.101V51.7427H190.154C184.861 51.7427 182.214 49.1742 182.214 44.0373V32.0759H179.254V26.924H182.214V20.7865H188.539V26.924H194.101V32.0759H188.539Z" fill="white"/>
7
+ <path d="M221.718 38.7958C221.718 39.6917 221.659 40.4981 221.539 41.2149H203.372C203.522 43.0069 204.15 44.4106 205.256 45.426C206.363 46.4415 207.723 46.9492 209.338 46.9492C211.671 46.9492 213.33 45.9487 214.317 43.9477H221.09C220.373 46.3369 218.997 48.3081 216.964 49.8611C214.93 51.3843 212.433 52.1459 209.473 52.1459C207.08 52.1459 204.927 51.6232 203.014 50.5779C201.13 49.5027 199.649 47.9945 198.573 46.0532C197.526 44.1119 197.003 41.872 197.003 39.3333C197.003 36.7649 197.526 34.51 198.573 32.5687C199.619 30.6274 201.085 29.1341 202.969 28.0888C204.853 27.0434 207.021 26.5208 209.473 26.5208C211.835 26.5208 213.943 27.0285 215.797 28.044C217.681 29.0594 219.132 30.5079 220.148 32.3895C221.195 34.2412 221.718 36.3766 221.718 38.7958ZM215.214 37.0038C215.184 35.391 214.601 34.1068 213.465 33.1511C212.329 32.1655 210.938 31.6727 209.293 31.6727C207.738 31.6727 206.423 32.1505 205.346 33.1063C204.299 34.0321 203.657 35.3313 203.417 37.0038H215.214Z" fill="white"/>
8
+ <path d="M240.073 26.5656C243.033 26.5656 245.426 27.5064 247.25 29.3879C249.074 31.2396 249.986 33.838 249.986 37.183V51.7427H243.706V38.0342C243.706 36.063 243.213 34.5548 242.226 33.5095C241.239 32.4343 239.893 31.8967 238.189 31.8967C236.454 31.8967 235.079 32.4343 234.062 33.5095C233.075 34.5548 232.582 36.063 232.582 38.0342V51.7427H226.302V26.924H232.582V30.0151C233.419 28.9399 234.481 28.1037 235.767 27.5064C237.082 26.8792 238.518 26.5656 240.073 26.5656Z" fill="white"/>
9
+ <path d="M259.142 23.9672C258.036 23.9672 257.109 23.6238 256.361 22.9369C255.644 22.2201 255.285 21.339 255.285 20.2937C255.285 19.2484 255.644 18.3823 256.361 17.6954C257.109 16.9786 258.036 16.6202 259.142 16.6202C260.249 16.6202 261.161 16.9786 261.879 17.6954C262.626 18.3823 263 19.2484 263 20.2937C263 21.339 262.626 22.2201 261.879 22.9369C261.161 23.6238 260.249 23.9672 259.142 23.9672ZM262.237 26.924V51.7427H255.958V26.924H262.237Z" fill="white"/>
10
+ <g clip-path="url(#clip0_8584_3)">
11
+ <path d="M49.9674 73.4308C49.6804 74.3567 51.5816 68.8367 52.0837 64.9906C54.5588 46.2939 51.6174 28.2026 33.0366 13.3877C23.8179 6.01581 11.8372 2.13402 0 2.66821C4.26857 3.55853 6.85124 8.01012 7.53277 12.3193C8.21431 16.5928 7.4969 20.9732 7.99909 25.2823C9.00346 33.9362 15.0297 41.6642 22.8494 45.6528C29.9159 49.2497 38.2378 49.962 46.0575 48.3594C46.0575 48.3594 38.4171 29.1997 24.2842 23.3592C24.2842 23.3592 43.3673 29.0929 48.8913 47.5403C52.5501 59.8979 49.9674 73.4308 49.9674 73.4308Z" fill="url(#paint0_linear_8584_3)"/>
12
+ <path d="M52.9804 36.9619C52.9445 36.855 52.9087 36.7482 52.8728 36.677C54.7381 29.1271 61.4458 21.8621 66.109 19.6541C61.3741 19.8321 53.4109 27.1327 50.9358 31.62C49.4293 28.2367 47.5281 25.0316 45.2324 22.0045C53.6978 13.0301 73.1754 13.0301 76.7983 -0.00418091C78.1614 8.40043 78.1614 20.8293 74.6461 28.5929C71.3102 35.9291 64.3154 46.3993 54.8098 45.1528C54.4152 42.3038 53.8054 39.5616 52.9804 36.9619Z" fill="url(#paint1_linear_8584_3)"/>
13
+ </g>
14
+ <defs>
15
+ <linearGradient id="paint0_linear_8584_3" x1="46.1388" y1="27.7919" x2="15.268" y2="43.0653" gradientUnits="userSpaceOnUse">
16
+ <stop stop-color="#8CC63F"/>
17
+ <stop offset="1" stop-color="#009245"/>
18
+ </linearGradient>
19
+ <linearGradient id="paint1_linear_8584_3" x1="77.6788" y1="22.617" x2="45.2565" y2="22.617" gradientUnits="userSpaceOnUse">
20
+ <stop stop-color="#8CC63F"/>
21
+ <stop offset="1" stop-color="#009245"/>
22
+ </linearGradient>
23
+ <clipPath id="clip0_8584_3">
24
+ <rect width="77.6952" height="73.5404" fill="white"/>
25
+ </clipPath>
26
+ </defs>
27
+ </svg>
@@ -0,0 +1,19 @@
1
+ <svg width="102" height="102" viewBox="0 0 102 102" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <g clip-path="url(#clip0_8584_19)">
3
+ <path d="M58.9674 90.4307C58.6804 91.3567 60.5816 85.8367 61.0837 81.9905C63.5588 63.2938 60.6174 45.2025 42.0366 30.3876C32.8179 23.0158 20.8372 19.134 9 19.6682C13.2686 20.5585 15.8512 25.0101 16.5328 29.3192C17.2143 33.5928 16.4969 37.9731 16.9991 42.2823C18.0035 50.9362 24.0297 58.6642 31.8494 62.6528C38.9159 66.2497 47.2378 66.9619 55.0575 65.3594C55.0575 65.3594 47.4171 46.1997 33.2842 40.3592C33.2842 40.3592 52.3673 46.0929 57.8913 64.5403C61.5501 76.8979 58.9674 90.4307 58.9674 90.4307Z" fill="url(#paint0_linear_8584_19)"/>
4
+ <path d="M61.9804 53.9619C61.9445 53.855 61.9087 53.7482 61.8728 53.677C63.7381 46.127 70.4458 38.862 75.109 36.6541C70.3741 36.8321 62.4109 44.1327 59.9358 48.6199C58.4293 45.2367 56.5281 42.0316 54.2324 39.0045C62.6978 30.0301 82.1754 30.0301 85.7983 16.9958C87.1614 25.4004 87.1614 37.8293 83.6461 45.5929C80.3102 52.9291 73.3154 63.3992 63.8098 62.1528C63.4152 59.3038 62.8054 56.5616 61.9804 53.9619Z" fill="url(#paint1_linear_8584_19)"/>
5
+ </g>
6
+ <defs>
7
+ <linearGradient id="paint0_linear_8584_19" x1="55.1388" y1="44.7919" x2="24.268" y2="60.0653" gradientUnits="userSpaceOnUse">
8
+ <stop stop-color="#8CC63F"/>
9
+ <stop offset="1" stop-color="#009245"/>
10
+ </linearGradient>
11
+ <linearGradient id="paint1_linear_8584_19" x1="86.6788" y1="39.617" x2="54.2565" y2="39.617" gradientUnits="userSpaceOnUse">
12
+ <stop stop-color="#8CC63F"/>
13
+ <stop offset="1" stop-color="#009245"/>
14
+ </linearGradient>
15
+ <clipPath id="clip0_8584_19">
16
+ <rect width="77.6952" height="73.5404" fill="white" transform="translate(9 17)"/>
17
+ </clipPath>
18
+ </defs>
19
+ </svg>
@@ -0,0 +1,5 @@
1
+ // BRAND MARKS (generated, do not edit) — synced from apliteni/design-system.
2
+ // The umbrella wordmark + seedling mark. The kit's own `prism` stays in brand.js.
3
+ export const apliteniLogo = "<svg width=\"263\" height=\"74\" viewBox=\"0 0 263 74\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n<path d=\"M112.948 45.7844H100.478L98.4151 51.7427H91.8213L103.08 20.4281H110.392L121.65 51.7427H115.012L112.948 45.7844ZM111.244 40.7669L106.713 27.6856L102.183 40.7669H111.244Z\" fill=\"white\"/>\n<path d=\"M132.138 30.5079C132.946 29.373 134.052 28.4322 135.458 27.6856C136.893 26.909 138.523 26.5208 140.347 26.5208C142.47 26.5208 144.384 27.0434 146.089 28.0888C147.823 29.1341 149.184 30.6274 150.17 32.5687C151.187 34.4801 151.696 36.7051 151.696 39.2437C151.696 41.7824 151.187 44.0373 150.17 46.0084C149.184 47.9497 147.823 49.4579 146.089 50.5331C144.384 51.6083 142.47 52.1459 140.347 52.1459C138.523 52.1459 136.908 51.7726 135.503 51.0259C134.127 50.2793 133.006 49.3385 132.138 48.2036V63.5697H125.859V26.924H132.138V30.5079ZM145.281 39.2437C145.281 37.7504 144.967 36.4662 144.339 35.391C143.741 34.286 142.934 33.4497 141.917 32.8823C140.93 32.3148 139.854 32.0311 138.687 32.0311C137.551 32.0311 136.475 32.3297 135.458 32.9271C134.471 33.4945 133.664 34.3308 133.036 35.4358C132.438 36.5409 132.138 37.84 132.138 39.3333C132.138 40.8266 132.438 42.1258 133.036 43.2309C133.664 44.3359 134.471 45.1871 135.458 45.7844C136.475 46.3519 137.551 46.6356 138.687 46.6356C139.854 46.6356 140.93 46.3369 141.917 45.7396C142.934 45.1423 143.741 44.2911 144.339 43.1861C144.967 42.081 145.281 40.7669 145.281 39.2437Z\" fill=\"white\"/>\n<path d=\"M162.539 18.5913V51.7427H156.259V18.5913H162.539Z\" fill=\"white\"/>\n<path d=\"M171.928 23.9672C170.821 23.9672 169.894 23.6238 169.147 22.9369C168.429 22.2201 168.07 21.339 168.07 20.2937C168.07 19.2484 168.429 18.3823 169.147 17.6954C169.894 16.9786 170.821 16.6202 171.928 16.6202C173.034 16.6202 173.946 16.9786 174.664 17.6954C175.412 18.3823 175.785 19.2484 175.785 20.2937C175.785 21.339 175.412 22.2201 174.664 22.9369C173.946 23.6238 173.034 23.9672 171.928 23.9672ZM175.023 26.924V51.7427H168.743V26.924H175.023Z\" fill=\"white\"/>\n<path d=\"M188.539 32.0759V44.0821C188.539 44.9183 188.733 45.5306 189.122 45.9188C189.541 46.2772 190.228 46.4564 191.185 46.4564H194.101V51.7427H190.154C184.861 51.7427 182.214 49.1742 182.214 44.0373V32.0759H179.254V26.924H182.214V20.7865H188.539V26.924H194.101V32.0759H188.539Z\" fill=\"white\"/>\n<path d=\"M221.718 38.7958C221.718 39.6917 221.659 40.4981 221.539 41.2149H203.372C203.522 43.0069 204.15 44.4106 205.256 45.426C206.363 46.4415 207.723 46.9492 209.338 46.9492C211.671 46.9492 213.33 45.9487 214.317 43.9477H221.09C220.373 46.3369 218.997 48.3081 216.964 49.8611C214.93 51.3843 212.433 52.1459 209.473 52.1459C207.08 52.1459 204.927 51.6232 203.014 50.5779C201.13 49.5027 199.649 47.9945 198.573 46.0532C197.526 44.1119 197.003 41.872 197.003 39.3333C197.003 36.7649 197.526 34.51 198.573 32.5687C199.619 30.6274 201.085 29.1341 202.969 28.0888C204.853 27.0434 207.021 26.5208 209.473 26.5208C211.835 26.5208 213.943 27.0285 215.797 28.044C217.681 29.0594 219.132 30.5079 220.148 32.3895C221.195 34.2412 221.718 36.3766 221.718 38.7958ZM215.214 37.0038C215.184 35.391 214.601 34.1068 213.465 33.1511C212.329 32.1655 210.938 31.6727 209.293 31.6727C207.738 31.6727 206.423 32.1505 205.346 33.1063C204.299 34.0321 203.657 35.3313 203.417 37.0038H215.214Z\" fill=\"white\"/>\n<path d=\"M240.073 26.5656C243.033 26.5656 245.426 27.5064 247.25 29.3879C249.074 31.2396 249.986 33.838 249.986 37.183V51.7427H243.706V38.0342C243.706 36.063 243.213 34.5548 242.226 33.5095C241.239 32.4343 239.893 31.8967 238.189 31.8967C236.454 31.8967 235.079 32.4343 234.062 33.5095C233.075 34.5548 232.582 36.063 232.582 38.0342V51.7427H226.302V26.924H232.582V30.0151C233.419 28.9399 234.481 28.1037 235.767 27.5064C237.082 26.8792 238.518 26.5656 240.073 26.5656Z\" fill=\"white\"/>\n<path d=\"M259.142 23.9672C258.036 23.9672 257.109 23.6238 256.361 22.9369C255.644 22.2201 255.285 21.339 255.285 20.2937C255.285 19.2484 255.644 18.3823 256.361 17.6954C257.109 16.9786 258.036 16.6202 259.142 16.6202C260.249 16.6202 261.161 16.9786 261.879 17.6954C262.626 18.3823 263 19.2484 263 20.2937C263 21.339 262.626 22.2201 261.879 22.9369C261.161 23.6238 260.249 23.9672 259.142 23.9672ZM262.237 26.924V51.7427H255.958V26.924H262.237Z\" fill=\"white\"/>\n<g clip-path=\"url(#clip0_8584_3)\">\n<path d=\"M49.9674 73.4308C49.6804 74.3567 51.5816 68.8367 52.0837 64.9906C54.5588 46.2939 51.6174 28.2026 33.0366 13.3877C23.8179 6.01581 11.8372 2.13402 0 2.66821C4.26857 3.55853 6.85124 8.01012 7.53277 12.3193C8.21431 16.5928 7.4969 20.9732 7.99909 25.2823C9.00346 33.9362 15.0297 41.6642 22.8494 45.6528C29.9159 49.2497 38.2378 49.962 46.0575 48.3594C46.0575 48.3594 38.4171 29.1997 24.2842 23.3592C24.2842 23.3592 43.3673 29.0929 48.8913 47.5403C52.5501 59.8979 49.9674 73.4308 49.9674 73.4308Z\" fill=\"url(#paint0_linear_8584_3)\"/>\n<path d=\"M52.9804 36.9619C52.9445 36.855 52.9087 36.7482 52.8728 36.677C54.7381 29.1271 61.4458 21.8621 66.109 19.6541C61.3741 19.8321 53.4109 27.1327 50.9358 31.62C49.4293 28.2367 47.5281 25.0316 45.2324 22.0045C53.6978 13.0301 73.1754 13.0301 76.7983 -0.00418091C78.1614 8.40043 78.1614 20.8293 74.6461 28.5929C71.3102 35.9291 64.3154 46.3993 54.8098 45.1528C54.4152 42.3038 53.8054 39.5616 52.9804 36.9619Z\" fill=\"url(#paint1_linear_8584_3)\"/>\n</g>\n<defs>\n<linearGradient id=\"paint0_linear_8584_3\" x1=\"46.1388\" y1=\"27.7919\" x2=\"15.268\" y2=\"43.0653\" gradientUnits=\"userSpaceOnUse\">\n<stop stop-color=\"#8CC63F\"/>\n<stop offset=\"1\" stop-color=\"#009245\"/>\n</linearGradient>\n<linearGradient id=\"paint1_linear_8584_3\" x1=\"77.6788\" y1=\"22.617\" x2=\"45.2565\" y2=\"22.617\" gradientUnits=\"userSpaceOnUse\">\n<stop stop-color=\"#8CC63F\"/>\n<stop offset=\"1\" stop-color=\"#009245\"/>\n</linearGradient>\n<clipPath id=\"clip0_8584_3\">\n<rect width=\"77.6952\" height=\"73.5404\" fill=\"white\"/>\n</clipPath>\n</defs>\n</svg>";
4
+ export const apliteniLogoDark = "<svg width=\"263\" height=\"74\" viewBox=\"0 0 263 74\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n<path d=\"M112.948 45.7844H100.478L98.4151 51.7427H91.8213L103.08 20.4281H110.392L121.65 51.7427H115.012L112.948 45.7844ZM111.244 40.7669L106.713 27.6856L102.183 40.7669H111.244Z\" fill=\"#191919\"/>\n<path d=\"M132.138 30.5079C132.946 29.373 134.052 28.4322 135.458 27.6856C136.893 26.909 138.523 26.5208 140.347 26.5208C142.47 26.5208 144.384 27.0434 146.089 28.0888C147.823 29.1341 149.184 30.6274 150.17 32.5687C151.187 34.4801 151.696 36.7051 151.696 39.2437C151.696 41.7824 151.187 44.0373 150.17 46.0084C149.184 47.9497 147.823 49.4579 146.089 50.5331C144.384 51.6083 142.47 52.1459 140.347 52.1459C138.523 52.1459 136.908 51.7726 135.503 51.0259C134.127 50.2793 133.006 49.3385 132.138 48.2036V63.5697H125.859V26.924H132.138V30.5079ZM145.281 39.2437C145.281 37.7504 144.967 36.4662 144.339 35.391C143.741 34.286 142.934 33.4497 141.917 32.8823C140.93 32.3148 139.854 32.0311 138.687 32.0311C137.551 32.0311 136.475 32.3297 135.458 32.9271C134.471 33.4945 133.664 34.3308 133.036 35.4358C132.438 36.5409 132.138 37.84 132.138 39.3333C132.138 40.8266 132.438 42.1258 133.036 43.2309C133.664 44.3359 134.471 45.1871 135.458 45.7844C136.475 46.3519 137.551 46.6356 138.687 46.6356C139.854 46.6356 140.93 46.3369 141.917 45.7396C142.934 45.1423 143.741 44.2911 144.339 43.1861C144.967 42.081 145.281 40.7669 145.281 39.2437Z\" fill=\"#191919\"/>\n<path d=\"M162.539 18.5913V51.7427H156.259V18.5913H162.539Z\" fill=\"#191919\"/>\n<path d=\"M171.928 23.9672C170.821 23.9672 169.894 23.6238 169.147 22.9369C168.429 22.2201 168.07 21.339 168.07 20.2937C168.07 19.2484 168.429 18.3823 169.147 17.6954C169.894 16.9786 170.821 16.6202 171.928 16.6202C173.034 16.6202 173.946 16.9786 174.664 17.6954C175.412 18.3823 175.785 19.2484 175.785 20.2937C175.785 21.339 175.412 22.2201 174.664 22.9369C173.946 23.6238 173.034 23.9672 171.928 23.9672ZM175.023 26.924V51.7427H168.743V26.924H175.023Z\" fill=\"#191919\"/>\n<path d=\"M188.539 32.0759V44.0821C188.539 44.9183 188.733 45.5306 189.122 45.9188C189.541 46.2772 190.228 46.4564 191.185 46.4564H194.101V51.7427H190.154C184.861 51.7427 182.214 49.1742 182.214 44.0373V32.0759H179.254V26.924H182.214V20.7865H188.539V26.924H194.101V32.0759H188.539Z\" fill=\"#191919\"/>\n<path d=\"M221.718 38.7958C221.718 39.6917 221.659 40.4981 221.539 41.2149H203.372C203.522 43.0069 204.15 44.4106 205.256 45.426C206.363 46.4415 207.723 46.9492 209.338 46.9492C211.671 46.9492 213.33 45.9487 214.317 43.9477H221.09C220.373 46.3369 218.997 48.3081 216.964 49.8611C214.93 51.3843 212.433 52.1459 209.473 52.1459C207.08 52.1459 204.927 51.6232 203.014 50.5779C201.13 49.5027 199.649 47.9945 198.573 46.0532C197.526 44.1119 197.003 41.872 197.003 39.3333C197.003 36.7649 197.526 34.51 198.573 32.5687C199.619 30.6274 201.085 29.1341 202.969 28.0888C204.853 27.0434 207.021 26.5208 209.473 26.5208C211.835 26.5208 213.943 27.0285 215.797 28.044C217.681 29.0594 219.132 30.5079 220.148 32.3895C221.195 34.2412 221.718 36.3766 221.718 38.7958ZM215.214 37.0038C215.184 35.391 214.601 34.1068 213.465 33.1511C212.329 32.1655 210.938 31.6727 209.293 31.6727C207.738 31.6727 206.423 32.1505 205.346 33.1063C204.299 34.0321 203.657 35.3313 203.417 37.0038H215.214Z\" fill=\"#191919\"/>\n<path d=\"M240.073 26.5656C243.033 26.5656 245.426 27.5064 247.25 29.3879C249.074 31.2396 249.986 33.838 249.986 37.183V51.7427H243.706V38.0342C243.706 36.063 243.213 34.5548 242.226 33.5095C241.239 32.4343 239.893 31.8967 238.189 31.8967C236.454 31.8967 235.079 32.4343 234.062 33.5095C233.075 34.5548 232.582 36.063 232.582 38.0342V51.7427H226.302V26.924H232.582V30.0151C233.419 28.9399 234.481 28.1037 235.767 27.5064C237.082 26.8792 238.518 26.5656 240.073 26.5656Z\" fill=\"#191919\"/>\n<path d=\"M259.142 23.9672C258.036 23.9672 257.109 23.6238 256.361 22.9369C255.644 22.2201 255.285 21.339 255.285 20.2937C255.285 19.2484 255.644 18.3823 256.361 17.6954C257.109 16.9786 258.036 16.6202 259.142 16.6202C260.249 16.6202 261.161 16.9786 261.879 17.6954C262.626 18.3823 263 19.2484 263 20.2937C263 21.339 262.626 22.2201 261.879 22.9369C261.161 23.6238 260.249 23.9672 259.142 23.9672ZM262.237 26.924V51.7427H255.958V26.924H262.237Z\" fill=\"#191919\"/>\n<g clip-path=\"url(#clip0_8584_3)\">\n<path d=\"M49.9674 73.4308C49.6804 74.3567 51.5816 68.8367 52.0837 64.9906C54.5588 46.2939 51.6174 28.2026 33.0366 13.3877C23.8179 6.01581 11.8372 2.13402 0 2.66821C4.26857 3.55853 6.85124 8.01012 7.53277 12.3193C8.21431 16.5928 7.4969 20.9732 7.99909 25.2823C9.00346 33.9362 15.0297 41.6642 22.8494 45.6528C29.9159 49.2497 38.2378 49.962 46.0575 48.3594C46.0575 48.3594 38.4171 29.1997 24.2842 23.3592C24.2842 23.3592 43.3673 29.0929 48.8913 47.5403C52.5501 59.8979 49.9674 73.4308 49.9674 73.4308Z\" fill=\"url(#paint0_linear_8584_3)\"/>\n<path d=\"M52.9804 36.9619C52.9445 36.855 52.9087 36.7482 52.8728 36.677C54.7381 29.1271 61.4458 21.8621 66.109 19.6541C61.3741 19.8321 53.4109 27.1327 50.9358 31.62C49.4293 28.2367 47.5281 25.0316 45.2324 22.0045C53.6978 13.0301 73.1754 13.0301 76.7983 -0.00418091C78.1614 8.40043 78.1614 20.8293 74.6461 28.5929C71.3102 35.9291 64.3154 46.3993 54.8098 45.1528C54.4152 42.3038 53.8054 39.5616 52.9804 36.9619Z\" fill=\"url(#paint1_linear_8584_3)\"/>\n</g>\n<defs>\n<linearGradient id=\"paint0_linear_8584_3\" x1=\"46.1388\" y1=\"27.7919\" x2=\"15.268\" y2=\"43.0653\" gradientUnits=\"userSpaceOnUse\">\n<stop stop-color=\"#8CC63F\"/>\n<stop offset=\"1\" stop-color=\"#009245\"/>\n</linearGradient>\n<linearGradient id=\"paint1_linear_8584_3\" x1=\"77.6788\" y1=\"22.617\" x2=\"45.2565\" y2=\"22.617\" gradientUnits=\"userSpaceOnUse\">\n<stop stop-color=\"#8CC63F\"/>\n<stop offset=\"1\" stop-color=\"#009245\"/>\n</linearGradient>\n<clipPath id=\"clip0_8584_3\">\n<rect width=\"77.6952\" height=\"73.5404\" fill=\"#191919\"/>\n</clipPath>\n</defs>\n</svg>";
5
+ export const apliteniMark = "<svg width=\"102\" height=\"102\" viewBox=\"0 0 102 102\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n<g clip-path=\"url(#clip0_8584_19)\">\n<path d=\"M58.9674 90.4307C58.6804 91.3567 60.5816 85.8367 61.0837 81.9905C63.5588 63.2938 60.6174 45.2025 42.0366 30.3876C32.8179 23.0158 20.8372 19.134 9 19.6682C13.2686 20.5585 15.8512 25.0101 16.5328 29.3192C17.2143 33.5928 16.4969 37.9731 16.9991 42.2823C18.0035 50.9362 24.0297 58.6642 31.8494 62.6528C38.9159 66.2497 47.2378 66.9619 55.0575 65.3594C55.0575 65.3594 47.4171 46.1997 33.2842 40.3592C33.2842 40.3592 52.3673 46.0929 57.8913 64.5403C61.5501 76.8979 58.9674 90.4307 58.9674 90.4307Z\" fill=\"url(#paint0_linear_8584_19)\"/>\n<path d=\"M61.9804 53.9619C61.9445 53.855 61.9087 53.7482 61.8728 53.677C63.7381 46.127 70.4458 38.862 75.109 36.6541C70.3741 36.8321 62.4109 44.1327 59.9358 48.6199C58.4293 45.2367 56.5281 42.0316 54.2324 39.0045C62.6978 30.0301 82.1754 30.0301 85.7983 16.9958C87.1614 25.4004 87.1614 37.8293 83.6461 45.5929C80.3102 52.9291 73.3154 63.3992 63.8098 62.1528C63.4152 59.3038 62.8054 56.5616 61.9804 53.9619Z\" fill=\"url(#paint1_linear_8584_19)\"/>\n</g>\n<defs>\n<linearGradient id=\"paint0_linear_8584_19\" x1=\"55.1388\" y1=\"44.7919\" x2=\"24.268\" y2=\"60.0653\" gradientUnits=\"userSpaceOnUse\">\n<stop stop-color=\"#8CC63F\"/>\n<stop offset=\"1\" stop-color=\"#009245\"/>\n</linearGradient>\n<linearGradient id=\"paint1_linear_8584_19\" x1=\"86.6788\" y1=\"39.617\" x2=\"54.2565\" y2=\"39.617\" gradientUnits=\"userSpaceOnUse\">\n<stop stop-color=\"#8CC63F\"/>\n<stop offset=\"1\" stop-color=\"#009245\"/>\n</linearGradient>\n<clipPath id=\"clip0_8584_19\">\n<rect width=\"77.6952\" height=\"73.5404\" fill=\"white\" transform=\"translate(9 17)\"/>\n</clipPath>\n</defs>\n</svg>";
@@ -1,39 +1,121 @@
1
- // Line-icon set (24×24, stroke=currentColor). Feather-style, 1.7 stroke.
2
- // Returned as inner SVG markup; wrap in <svg viewBox="0 0 24 24">…</svg> via icon().
1
+ // Line-icon set 24×24, stroke=currentColor, 1.7 weight, round caps/joins.
2
+ // House style is Feather/Lucide (Lucide is the maintained Feather; our glyphs
3
+ // match it 1:1). Delivery is inline SVG strings: no runtime dependency, works
4
+ // in any framework, and every glyph inherits `currentColor` + a consistent
5
+ // stroke so it sits right next to our type.
6
+ //
7
+ // Each value is the INNER markup; icon() wraps it in the shared <svg>. Glyphs
8
+ // are grouped by domain — the flat ICONS map is what icon() looks up, and
9
+ // iconCategories drives the Storybook grid. Add a glyph to the right group.
3
10
 
4
- const P = {
5
- gear: '<circle cx="12" cy="12" r="3"/><path d="M19.4 13a7.9 7.9 0 0 0 0-2l1.6-1.3-1.6-2.7-1.9.8a7.6 7.6 0 0 0-1.7-1L15.5 5h-3l-.3 1.8a7.6 7.6 0 0 0-1.7 1l-1.9-.8-1.6 2.7L8.6 11a7.9 7.9 0 0 0 0 2l-1.6 1.3 1.6 2.7 1.9-.8a7.6 7.6 0 0 0 1.7 1l.3 1.8h3l.3-1.8a7.6 7.6 0 0 0 1.7-1l1.9.8 1.6-2.7z"/>',
6
- key: '<rect x="4" y="10" width="16" height="10" rx="2"/><path d="M8 10V7a4 4 0 0 1 8 0v3"/>',
7
- chat: '<path d="M21 15a2 2 0 0 1-2 2H8l-4 4V5a2 2 0 0 1 2-2h13a2 2 0 0 1 2 2z"/>',
8
- logout: '<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><path d="M16 17l5-5-5-5"/><path d="M21 12H9"/>',
9
- mail: '<rect x="3" y="5" width="18" height="14" rx="2"/><path d="m3 7 9 6 9-6"/>',
10
- lock: '<rect x="5" y="11" width="14" height="10" rx="2"/><path d="M8 11V7a4 4 0 0 1 8 0v4"/>',
11
- user: '<circle cx="12" cy="8" r="4"/><path d="M4 21a8 8 0 0 1 16 0"/>',
12
- check: '<path d="M20 6 9 17l-5-5"/>',
11
+ const NAV = {
12
+ chevronDown: '<path d="m6 9 6 6 6-6"/>',
13
+ chevronUp: '<path d="m18 15-6-6-6 6"/>',
14
+ chevronLeft: '<path d="m15 6-6 6 6 6"/>',
15
+ chevronRight: '<path d="m9 6 6 6-6 6"/>',
16
+ arrowRight: '<path d="M5 12h14M13 6l6 6-6 6"/>',
17
+ arrowLeft: '<path d="M19 12H5M11 6l-6 6 6 6"/>',
18
+ arrowUp: '<path d="M12 19V5M6 11l6-6 6 6"/>',
19
+ arrowDown: '<path d="M12 5v14M6 13l6 6 6-6"/>',
20
+ menu: '<path d="M3 6h18M3 12h18M3 18h18"/>',
13
21
  x: '<path d="M18 6 6 18M6 6l12 12"/>',
22
+ externalLink: '<path d="M15 3h6v6"/><path d="M10 14 21 3"/><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>',
23
+ home: '<path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><path d="M9 22V12h6v10"/>',
24
+ search: '<circle cx="11" cy="11" r="7"/><path d="m21 21-4.3-4.3"/>',
25
+ compass: '<circle cx="12" cy="12" r="9"/><path d="m15 9-2 6-4 2 2-6z"/>',
26
+ globe: '<circle cx="12" cy="12" r="9"/><path d="M3 12h18M12 3a15 15 0 0 1 0 18 15 15 0 0 1 0-18z"/>',
27
+ };
28
+
29
+ const ACTIONS = {
30
+ plus: '<path d="M12 5v14M5 12h14"/>',
31
+ minus: '<path d="M5 12h14"/>',
32
+ check: '<path d="M20 6 9 17l-5-5"/>',
33
+ edit: '<path d="M12 20h9"/><path d="M16.5 3.5a2.1 2.1 0 0 1 3 3L7 19l-4 1 1-4z"/>',
14
34
  copy: '<rect x="9" y="9" width="12" height="12" rx="2"/><path d="M5 15V5a2 2 0 0 1 2-2h10"/>',
35
+ trash: '<path d="M3 6h18"/><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/><path d="M6 6v14a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V6"/><path d="M10 11v6M14 11v6"/>',
36
+ download: '<path d="M12 3v12"/><path d="m7 10 5 5 5-5"/><path d="M5 21h14"/>',
37
+ upload: '<path d="M12 21V9"/><path d="m7 14 5-5 5 5"/><path d="M5 3h14"/>',
38
+ share: '<circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/><path d="m8.6 13.5 6.8 4M15.4 6.5l-6.8 4"/>',
39
+ refresh: '<path d="M21 12a9 9 0 1 1-2.6-6.3L21 8"/><path d="M21 3v5h-5"/>',
40
+ filter: '<path d="M3 4h18l-7 8v6l-4 2v-8z"/>',
41
+ gear: '<circle cx="12" cy="12" r="3"/><path d="M19.4 13a7.9 7.9 0 0 0 0-2l1.6-1.3-1.6-2.7-1.9.8a7.6 7.6 0 0 0-1.7-1L15.5 5h-3l-.3 1.8a7.6 7.6 0 0 0-1.7 1l-1.9-.8-1.6 2.7L8.6 11a7.9 7.9 0 0 0 0 2l-1.6 1.3 1.6 2.7 1.9-.8a7.6 7.6 0 0 0 1.7 1l.3 1.8h3l.3-1.8a7.6 7.6 0 0 0 1.7-1l1.9.8 1.6-2.7z"/>',
42
+ link: '<path d="M10 13a5 5 0 0 0 7 0l3-3a5 5 0 0 0-7-7l-1 1"/><path d="M14 11a5 5 0 0 0-7 0l-3 3a5 5 0 0 0 7 7l1-1"/>',
43
+ moreHorizontal: '<circle cx="5" cy="12" r="1.3"/><circle cx="12" cy="12" r="1.3"/><circle cx="19" cy="12" r="1.3"/>',
44
+ moreVertical: '<circle cx="12" cy="5" r="1.3"/><circle cx="12" cy="12" r="1.3"/><circle cx="12" cy="19" r="1.3"/>',
45
+ };
46
+
47
+ const STATUS = {
48
+ circleCheck: '<circle cx="12" cy="12" r="9"/><path d="m8.5 12 2.5 2.5 5-5"/>',
49
+ circleAlert: '<circle cx="12" cy="12" r="9"/><path d="M12 8v4M12 16h.01"/>',
50
+ alert: '<path d="M12 3 2 20h20z"/><path d="M12 9v5M12 17h.01"/>',
51
+ info: '<circle cx="12" cy="12" r="9"/><path d="M12 8h.01M11 12h1v4h1"/>',
52
+ bell: '<path d="M18 8a6 6 0 0 0-12 0c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.7 21a2 2 0 0 1-3.4 0"/>',
53
+ clock: '<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/>',
15
54
  eye: '<path d="M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7-10-7-10-7z"/><circle cx="12" cy="12" r="3"/>',
16
- bolt: '<path d="M13 2 3 14h8l-1 8 10-12h-8z"/>',
55
+ eyeOff: '<path d="M9.9 4.2A9.6 9.6 0 0 1 12 4c6.5 0 10 8 10 8a13.2 13.2 0 0 1-2.2 2.9M6.6 6.6A13.2 13.2 0 0 0 2 12s3.5 7 10 7a9.6 9.6 0 0 0 4-.9"/><path d="M9.9 9.9a3 3 0 0 0 4.2 4.2"/><path d="m2 2 20 20"/>',
56
+ lock: '<rect x="5" y="11" width="14" height="10" rx="2"/><path d="M8 11V7a4 4 0 0 1 8 0v4"/>',
57
+ unlock: '<rect x="5" y="11" width="14" height="10" rx="2"/><path d="M8 11V7a4 4 0 0 1 7.5-2"/>',
17
58
  shield: '<path d="M12 3 4 6v6c0 5 3.5 8 8 9 4.5-1 8-4 8-9V6z"/>',
59
+ key: '<rect x="4" y="10" width="16" height="10" rx="2"/><path d="M8 10V7a4 4 0 0 1 8 0v3"/>',
60
+ star: '<path d="m12 3 2.9 5.9 6.5.9-4.7 4.6 1.1 6.5L12 18l-5.8 3 1.1-6.5L2.6 9.8l6.5-.9z"/>',
61
+ heart: '<path d="M12 21s-7-4.5-9.4-9A5 5 0 0 1 12 6a5 5 0 0 1 9.4 6c-2.4 4.5-9.4 9-9.4 9z"/>',
62
+ };
63
+
64
+ const DATA = {
65
+ card: '<rect x="2" y="5" width="20" height="14" rx="2"/><path d="M2 10h20M6 15h4"/>',
66
+ wallet: '<path d="M4 6a2 2 0 0 1 2-2h11a1 1 0 0 1 1 1v3"/><path d="M4 6v12a2 2 0 0 0 2 2h13a1 1 0 0 0 1-1v-3"/><path d="M21 11h-4a2 2 0 0 0 0 4h4a1 1 0 0 0 1-1v-2a1 1 0 0 0-1-1z"/>',
67
+ chart: '<path d="M3 3v18h18"/><path d="M8 17v-5M13 17V8M18 17v-8"/>',
68
+ trendingUp: '<path d="m3 17 7-7 4 4 7-7"/><path d="M17 7h4v4"/>',
69
+ trendingDown: '<path d="m3 7 7 7 4-4 7 7"/><path d="M17 17h4v-4"/>',
70
+ table: '<rect x="3" y="4" width="18" height="16" rx="2"/><path d="M3 10h18M3 15h18M9 4v16M15 4v16"/>',
71
+ database: '<ellipse cx="12" cy="5" rx="8" ry="3"/><path d="M4 5v6c0 1.7 3.6 3 8 3s8-1.3 8-3V5"/><path d="M4 11v6c0 1.7 3.6 3 8 3s8-1.3 8-3v-6"/>',
72
+ layers: '<path d="m12 2 9 5-9 5-9-5z"/><path d="m3 12 9 5 9-5M3 17l9 5 9-5"/>',
18
73
  cube: '<path d="M12 2 3 7v10l9 5 9-5V7z"/><path d="M3 7l9 5 9-5M12 12v10"/>',
19
- compass: '<circle cx="12" cy="12" r="9"/><path d="m15 9-2 6-4 2 2-6z"/>',
20
- info: '<circle cx="12" cy="12" r="9"/><path d="M12 8h.01M11 12h1v4h1"/>',
21
- alert: '<path d="M12 3 2 20h20z"/><path d="M12 9v5M12 17h.01"/>',
22
- arrowRight: '<path d="M5 12h14M13 6l6 6-6 6"/>',
74
+ bolt: '<path d="M13 2 3 14h8l-1 8 10-12h-8z"/>',
75
+ };
76
+
77
+ const FILES = {
78
+ doc: '<path d="M14 3H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"/><path d="M14 3v6h6M8 13h8M8 17h5"/>',
79
+ folder: '<path d="M4 5h5l2 2h9a1 1 0 0 1 1 1v10a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V6a1 1 0 0 1 1-1z"/>',
80
+ image: '<rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/><path d="m21 15-5-5L5 21"/>',
81
+ play: '<path d="M7 4v16l13-8z"/>',
82
+ pause: '<rect x="7" y="4" width="3.5" height="16" rx="1"/><rect x="13.5" y="4" width="3.5" height="16" rx="1"/>',
83
+ calendar: '<rect x="3" y="5" width="18" height="16" rx="2"/><path d="M3 9h18M8 3v4M16 3v4"/>',
84
+ };
85
+
86
+ const COMMS = {
87
+ mail: '<rect x="3" y="5" width="18" height="14" rx="2"/><path d="m3 7 9 6 9-6"/>',
88
+ chat: '<path d="M21 15a2 2 0 0 1-2 2H8l-4 4V5a2 2 0 0 1 2-2h13a2 2 0 0 1 2 2z"/>',
89
+ phone: '<path d="M6 3h3l2 5-2.5 1.5a11 11 0 0 0 5 5L16 13l5 2v3a2 2 0 0 1-2 2A16 16 0 0 1 3 5a2 2 0 0 1 2-2z"/>',
90
+ user: '<circle cx="12" cy="8" r="4"/><path d="M4 21a8 8 0 0 1 16 0"/>',
91
+ logout: '<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><path d="M16 17l5-5-5-5"/><path d="M21 12H9"/>',
23
92
  plug: '<path d="M9 2v6M15 2v6M7 8h10v3a5 5 0 0 1-10 0z"/><path d="M12 16v6"/>',
24
- layers: '<path d="m12 2 9 5-9 5-9-5z"/><path d="m3 12 9 5 9-5M3 17l9 5 9-5"/>',
25
- search: '<circle cx="11" cy="11" r="7"/><path d="m21 21-4.3-4.3"/>',
26
- globe: '<circle cx="12" cy="12" r="9"/><path d="M3 12h18M12 3a15 15 0 0 1 0 18 15 15 0 0 1 0-18z"/>',
27
93
  sparkle: '<path d="M12 3v4M12 17v4M3 12h4M17 12h4M6 6l2 2M16 16l2 2M18 6l-2 2M8 16l-2 2"/>',
28
- card: '<rect x="2" y="5" width="20" height="14" rx="2"/><path d="M2 10h20M6 15h4"/>',
29
- doc: '<path d="M14 3H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"/><path d="M14 3v6h6M8 13h8M8 17h5"/>',
30
- chart: '<path d="M3 3v18h18"/><path d="M8 17v-5M13 17V8M18 17v-8"/>',
31
94
  };
32
95
 
96
+ const BRAND = {
97
+ github: '<path d="M9 19c-4 1.4-4-2.2-6-2.6m12 5v-3.4a3 3 0 0 0-.8-2.3c2.7-.3 5.5-1.3 5.5-6a4.6 4.6 0 0 0-1.3-3.2 4.3 4.3 0 0 0-.1-3.2s-1-.3-3.4 1.3a11.6 11.6 0 0 0-6 0C6.9 2.7 5.9 3 5.9 3a4.3 4.3 0 0 0-.1 3.2A4.6 4.6 0 0 0 4.5 9.4c0 4.6 2.8 5.6 5.5 6a3 3 0 0 0-.8 2.3V21"/>',
98
+ linkedin: '<path d="M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-4 0v7h-4v-7a6 6 0 0 1 6-6z"/><rect x="2" y="9" width="4" height="12"/><circle cx="4" cy="4" r="2"/>',
99
+ };
100
+
101
+ const ICONS = { ...NAV, ...ACTIONS, ...STATUS, ...DATA, ...FILES, ...COMMS, ...BRAND };
102
+
103
+ // Category order + membership for the Storybook grid. Names stay in sync with
104
+ // the group consts above, so a new glyph is catalogued the moment it's added.
105
+ export const iconCategories = [
106
+ { name: 'Navigation', names: Object.keys(NAV) },
107
+ { name: 'Actions', names: Object.keys(ACTIONS) },
108
+ { name: 'Status', names: Object.keys(STATUS) },
109
+ { name: 'Finance & data', names: Object.keys(DATA) },
110
+ { name: 'Media & files', names: Object.keys(FILES) },
111
+ { name: 'Communication', names: Object.keys(COMMS) },
112
+ { name: 'Brand', names: Object.keys(BRAND) },
113
+ ];
114
+
33
115
  export const icon = (name, cls = '') =>
34
- `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"${cls ? ` class="${cls}"` : ''}>${P[name] || ''}</svg>`;
116
+ `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"${cls ? ` class="${cls}"` : ''}>${ICONS[name] || ''}</svg>`;
35
117
 
36
- export const iconNames = Object.keys(P);
118
+ export const iconNames = Object.keys(ICONS);
37
119
 
38
120
  export const sun = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4"/></svg>';
39
121
  export const moon = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8z"/></svg>';
@@ -0,0 +1,68 @@
1
+ // Duotone spot illustrations for empty states (132×110). Feather-style line
2
+ // work in the current accent (`.ui-illo__stroke` + soft `.ui-illo__fill`) with
3
+ // a small Apliteni-green spark (`.ui-illo__spark`). Returned as full <svg>
4
+ // markup so the portal can server-render them with no framework — same idiom
5
+ // as icons.js. Colours come from empty.css, so they track the active accent.
6
+
7
+ // A 4-point sparkle placed at (x, y) — the brand-green accent detail.
8
+ const spark = (x, y) =>
9
+ `<path class="ui-illo__spark" transform="translate(${x} ${y})" d="M0 0c.6 4 2.6 6 6.5 7-3.9.6-5.9 2.6-6.5 6.5-.6-3.9-2.6-5.9-6.5-6.5 3.9-.8 5.9-2.6 6.5-7z"/>`;
10
+
11
+ const svg = (inner) =>
12
+ `<svg class="ui-illo" width="132" height="110" viewBox="0 0 132 110" fill="none" aria-hidden="true">${inner}</svg>`;
13
+
14
+ const ILLO = {
15
+ // A member card with an avatar — People, contributors, team.
16
+ people: svg(`
17
+ <rect class="ui-illo__fill" x="22" y="34" width="70" height="56" rx="9"/>
18
+ <rect class="ui-illo__stroke" x="34" y="24" width="70" height="56" rx="9"/>
19
+ <circle class="ui-illo__stroke" cx="69" cy="45" r="9"/>
20
+ <path class="ui-illo__stroke" d="M53 70c0-9 7-13 16-13s16 4 16 13"/>
21
+ ${spark(104, 20)}`),
22
+
23
+ // A document under a magnifier — Invoices, filtered lists with no match.
24
+ invoices: svg(`
25
+ <rect class="ui-illo__fill" x="28" y="26" width="58" height="70" rx="7"/>
26
+ <rect class="ui-illo__stroke" x="40" y="16" width="58" height="70" rx="7"/>
27
+ <path class="ui-illo__stroke" d="M52 34h34M52 48h34M52 62h22"/>
28
+ <circle class="ui-illo__stroke" cx="92" cy="76" r="14"/>
29
+ <path class="ui-illo__stroke" d="M102 86l11 11"/>
30
+ ${spark(112, 18)}`),
31
+
32
+ // A statement with an exchange glyph — Transactions, payouts, ledgers.
33
+ transactions: svg(`
34
+ <rect class="ui-illo__fill" x="24" y="32" width="72" height="56" rx="9"/>
35
+ <rect class="ui-illo__stroke" x="34" y="22" width="72" height="56" rx="9"/>
36
+ <path class="ui-illo__stroke" d="M46 40h26M46 52h34M46 64h18"/>
37
+ <path class="ui-illo__stroke" d="M96 46h14l-5-5M110 60H96l5 5"/>
38
+ ${spark(112, 20)}`),
39
+
40
+ // A magnifier over a couple of rows — search / no results.
41
+ search: svg(`
42
+ <circle class="ui-illo__fill" cx="58" cy="50" r="30"/>
43
+ <circle class="ui-illo__stroke" cx="58" cy="50" r="30"/>
44
+ <path class="ui-illo__stroke" d="M48 44h20M48 54h12"/>
45
+ <path class="ui-illo__stroke" d="M80 72l17 17"/>
46
+ ${spark(96, 16)}`),
47
+
48
+ // A robot head — Agents, connections, integrations.
49
+ agents: svg(`
50
+ <rect class="ui-illo__fill" x="30" y="38" width="64" height="48" rx="13"/>
51
+ <rect class="ui-illo__stroke" x="40" y="30" width="64" height="48" rx="13"/>
52
+ <circle class="ui-illo__stroke" cx="60" cy="54" r="4"/>
53
+ <circle class="ui-illo__stroke" cx="84" cy="54" r="4"/>
54
+ <path class="ui-illo__stroke" d="M60 66h24"/>
55
+ <path class="ui-illo__stroke" d="M72 30v-8M72 16v.01"/>
56
+ ${spark(108, 24)}`),
57
+
58
+ // A classic inbox tray — generic fallback for "nothing here yet".
59
+ inbox: svg(`
60
+ <path class="ui-illo__fill" d="M30 52h72l-9 28a7 7 0 0 1-6.6 5H45.6a7 7 0 0 1-6.6-5z"/>
61
+ <path class="ui-illo__stroke" d="M30 52l9-24a7 7 0 0 1 6.6-4.5h40.8A7 7 0 0 1 93 28l9 24"/>
62
+ <path class="ui-illo__stroke" d="M30 52h20l4 11h24l4-11h20"/>
63
+ ${spark(108, 20)}`),
64
+ };
65
+
66
+ // illo(name) → SVG markup. Unknown names fall back to the neutral inbox tray.
67
+ export const illo = (name) => ILLO[name] || ILLO.inbox;
68
+ export const illoNames = Object.keys(ILLO);
@@ -0,0 +1,200 @@
1
+ // Drawer — the kit's edge-anchored overlay panel (a.k.a. Sheet / Slide-over): a
2
+ // panel that slides in from any screen edge over a scrim. Header (title + close)
3
+ // / scrollable body / footer actions. Sizes sm|md|lg — full-height for
4
+ // left|right, full-width for top|bottom.
5
+ //
6
+ // container.innerHTML = drawer({ side: 'right', title: 'Filters', body });
7
+ // wireDrawer(container); // scrim/Esc/close-button + focus trap
8
+ //
9
+ // A page trigger opens it by id: <button data-drawer-open="ID">…</button>
10
+ // (or call openDrawer(rootEl) directly). Pass `open: true` to render it already
11
+ // open — handy for specimens/screenshots.
12
+ //
13
+ // This deliberately shares its scrim + focus-trap concept with a future Modal /
14
+ // Dialog: both are "content over a scrim, focus-trapped, Esc-dismissable". The
15
+ // data hooks ([data-drawer]/[data-drawer-scrim]/[data-drawer-close]) and the
16
+ // wireDrawer trap below are the primitive a Modal would reuse (centered instead
17
+ // of edge-anchored). Kept as one component for now per issue #34.
18
+ import { esc, icon } from './index.js';
19
+
20
+ const cx = (...a) => a.filter(Boolean).join(' ');
21
+
22
+ // Module counter (never Date/random) → stable, unique ids for aria-labelledby.
23
+ let _uid = 0;
24
+ const nextId = (p = 'drawer') => `${p}-${++_uid}`;
25
+
26
+ // The public factory. Returns an HTML string; wire it with wireDrawer().
27
+ // side 'right' (default) | 'left' | 'top' | 'bottom' — the edge it hugs
28
+ // size 'sm' | 'md' (default) | 'lg' — panel extent along the slide axis
29
+ // title header heading (also the dialog's accessible name)
30
+ // body scrollable body HTML (trusted markup)
31
+ // footer pinned footer actions HTML (trusted markup)
32
+ // open render already-open (specimens / screenshots)
33
+ // id root id — a [data-drawer-open="id"] trigger targets it
34
+ // ariaLabel accessible name when there's no visible title
35
+ // dismissible show the close button + allow scrim/Esc dismiss (default true)
36
+ // closeLabel accessible name for the close button (default 'Close')
37
+ export function drawer({
38
+ side = 'right', size = 'md', title, body = '', footer = '',
39
+ open = false, id, ariaLabel, dismissible = true, closeLabel = 'Close',
40
+ } = {}) {
41
+ const titleId = title ? nextId('drawer-title') : null;
42
+ const nameAttr = titleId
43
+ ? `aria-labelledby="${titleId}"`
44
+ : `aria-label="${esc(ariaLabel || 'Dialog')}"`;
45
+
46
+ const closeBtn = dismissible
47
+ ? `<button type="button" class="ui-drawer__close" data-drawer-close aria-label="${esc(closeLabel)}">${icon('x')}</button>`
48
+ : '';
49
+ const header = (title || dismissible)
50
+ ? `<header class="ui-drawer__header">`
51
+ + (title ? `<h2 class="ui-drawer__title" id="${titleId}">${esc(title)}</h2>` : '<span></span>')
52
+ + `${closeBtn}</header>`
53
+ : '';
54
+ const bodyEl = `<div class="ui-drawer__body">${body}</div>`;
55
+ const footEl = footer ? `<footer class="ui-drawer__footer">${footer}</footer>` : '';
56
+
57
+ const rootCls = cx('ui-drawer', `ui-drawer--${side}`, `ui-drawer--${size}`, open && 'is-open');
58
+ return `<div class="${rootCls}" data-drawer data-drawer-side="${esc(side)}"`
59
+ + `${dismissible ? '' : ' data-drawer-static'}${id ? ` id="${esc(id)}"` : ''}>`
60
+ + `<div class="ui-drawer__scrim" data-drawer-scrim></div>`
61
+ + `<aside class="ui-drawer__panel" role="dialog" aria-modal="true" ${nameAttr} tabindex="-1" data-drawer-panel>`
62
+ + `${header}${bodyEl}${footEl}`
63
+ + `</aside></div>`;
64
+ }
65
+
66
+ // ---- Shared behaviour ----------------------------------------------------
67
+ // One open/close/scrim/Esc/focus-trap implementation for every drawer in the
68
+ // kit. Per-instance handlers are attached once (guarded by a flag on the node);
69
+ // document-level Esc + the [data-drawer-open] delegation are attached once per
70
+ // document (guarded by a flag on the document node, so multiple documents each
71
+ // get their own). Safe to call repeatedly (Storybook re-renders).
72
+
73
+ const FOCUSABLE = [
74
+ 'a[href]', 'button:not([disabled])', 'input:not([disabled])',
75
+ 'select:not([disabled])', 'textarea:not([disabled])',
76
+ '[tabindex]:not([tabindex="-1"])',
77
+ ].join(',');
78
+
79
+ // Focusable controls inside the panel, in DOM order. Scoped to the panel, so
80
+ // nothing outside the trap is returned; hidden closed drawers are never queried
81
+ // (we only call this while open).
82
+ function focusablesIn(panel) {
83
+ return Array.from(panel.querySelectorAll(FOCUSABLE));
84
+ }
85
+
86
+ // Hide everything *outside* the drawer from AT + tab order: walk root→body and
87
+ // mark each ancestor's other children inert + aria-hidden, remembering prior
88
+ // state so close can restore it exactly. The scrim + panel live inside the root,
89
+ // so they stay interactive. This is the focus-trap primitive a Modal reuses.
90
+ function inertOutside(root, on) {
91
+ if (on) {
92
+ const touched = [];
93
+ let node = root;
94
+ while (node && node.parentElement && node !== document.body) {
95
+ for (const sib of node.parentElement.children) {
96
+ if (sib === node || sib.hasAttribute('data-drawer')) continue;
97
+ touched.push([sib, sib.getAttribute('aria-hidden'), sib.hasAttribute('inert')]);
98
+ sib.setAttribute('aria-hidden', 'true');
99
+ sib.setAttribute('inert', '');
100
+ sib.inert = true;
101
+ }
102
+ node = node.parentElement;
103
+ }
104
+ root.__drawerInert = touched;
105
+ } else {
106
+ (root.__drawerInert || []).forEach(([el, ariaHidden, hadInert]) => {
107
+ if (ariaHidden == null) el.removeAttribute('aria-hidden');
108
+ else el.setAttribute('aria-hidden', ariaHidden);
109
+ if (!hadInert) { el.removeAttribute('inert'); el.inert = false; }
110
+ });
111
+ root.__drawerInert = null;
112
+ }
113
+ }
114
+
115
+ export function openDrawer(root, returnFocusTo) {
116
+ if (!root || root.classList.contains('is-open')) return;
117
+ root.__drawerReturn = returnFocusTo
118
+ || (document.activeElement instanceof HTMLElement ? document.activeElement : null);
119
+ root.classList.add('is-open');
120
+ inertOutside(root, true);
121
+ const panel = root.querySelector('[data-drawer-panel]');
122
+ // Focus the first focusable control, else the panel itself.
123
+ const first = panel && focusablesIn(panel)[0];
124
+ (first || panel)?.focus();
125
+ }
126
+
127
+ export function closeDrawer(root) {
128
+ if (!root || !root.classList.contains('is-open')) return;
129
+ root.classList.remove('is-open');
130
+ inertOutside(root, false);
131
+ const back = root.__drawerReturn;
132
+ root.__drawerReturn = null;
133
+ if (back && typeof back.focus === 'function') back.focus();
134
+ }
135
+
136
+ // Trap Tab within the panel while open; wrap at both ends.
137
+ function trapTab(root, e) {
138
+ if (e.key !== 'Tab') return;
139
+ const panel = root.querySelector('[data-drawer-panel]');
140
+ if (!panel) return;
141
+ const items = focusablesIn(panel);
142
+ if (!items.length) { e.preventDefault(); panel.focus(); return; }
143
+ const first = items[0];
144
+ const last = items[items.length - 1];
145
+ const active = document.activeElement;
146
+ if (e.shiftKey && (active === first || active === panel)) {
147
+ e.preventDefault(); last.focus();
148
+ } else if (!e.shiftKey && active === last) {
149
+ e.preventDefault(); first.focus();
150
+ }
151
+ }
152
+
153
+ // Topmost open drawer (last in document order) — Esc closes that one.
154
+ function topOpenDrawer(doc = document) {
155
+ const open = doc.querySelectorAll('[data-drawer].is-open');
156
+ return open.length ? open[open.length - 1] : null;
157
+ }
158
+
159
+ export function wireDrawer(root = document) {
160
+ const scope = root === document ? document : root;
161
+ scope.querySelectorAll('[data-drawer]').forEach((dr) => {
162
+ if (dr.__drawerWired) return;
163
+ dr.__drawerWired = true;
164
+ const dismissible = !dr.hasAttribute('data-drawer-static');
165
+
166
+ dr.querySelector('[data-drawer-scrim]')?.addEventListener('click', () => {
167
+ if (dismissible) closeDrawer(dr);
168
+ });
169
+ dr.querySelectorAll('[data-drawer-close]').forEach((btn) =>
170
+ btn.addEventListener('click', () => closeDrawer(dr)));
171
+
172
+ dr.addEventListener('keydown', (e) => {
173
+ if (!dr.classList.contains('is-open')) return;
174
+ if (e.key === 'Escape' && dismissible) {
175
+ e.preventDefault(); e.stopPropagation(); closeDrawer(dr);
176
+ } else if (e.key === 'Tab') {
177
+ trapTab(dr, e);
178
+ }
179
+ });
180
+ });
181
+
182
+ const doc = root === document ? document : (root.ownerDocument || document);
183
+ if (!doc.__drawerGlobalWired) {
184
+ doc.__drawerGlobalWired = true;
185
+ // Any [data-drawer-open="ID"] trigger opens the matching drawer.
186
+ doc.addEventListener('click', (e) => {
187
+ const opener = e.target.closest?.('[data-drawer-open]');
188
+ if (!opener) return;
189
+ e.preventDefault();
190
+ const target = doc.getElementById(opener.getAttribute('data-drawer-open'));
191
+ if (target) openDrawer(target, opener);
192
+ });
193
+ // Esc closes the topmost open drawer even when focus escaped the panel.
194
+ doc.addEventListener('keydown', (e) => {
195
+ if (e.key !== 'Escape') return;
196
+ const top = topOpenDrawer(doc);
197
+ if (top && !top.hasAttribute('data-drawer-static')) { e.preventDefault(); closeDrawer(top); }
198
+ });
199
+ }
200
+ }