@digital-ai/dot-illustrations 2.0.36 → 2.0.38

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/demo/index.html CHANGED
@@ -3,226 +3,306 @@
3
3
  <head>
4
4
  <meta charset="UTF-8" />
5
5
  <title>Dot Illustrations Library</title>
6
- <!-- Tailwind CSS CDN -->
7
6
  <script src="https://cdn.tailwindcss.com"></script>
8
- <!-- Heroicons CDN for Tailwind icons -->
9
- <script src="https://unpkg.com/@heroicons/vue@2.0.18/dist/heroicons.min.js"></script>
10
7
  <link rel="stylesheet" href="../index.css" />
11
8
  <link rel="stylesheet" href="./demo.css" />
12
9
  <script src="./github-upload.js" defer></script>
13
10
  <script src="script.js" defer></script>
14
- <script>
15
- // Tailwind dark mode config
16
- tailwind.config = { darkMode: 'class' };
17
- </script>
11
+ <script>tailwind.config = { darkMode: 'class' };</script>
18
12
  </head>
19
- <body class="bg-gray-50 dark:bg-gray-900 min-h-screen transition-colors duration-300">
20
- <div id="floating-bar" class="fixed top-0 left-0 w-full z-50 flex items-center justify-center bg-white/90 dark:bg-gray-900/90 shadow-md px-2 py-1 transition-transform duration-300 -translate-y-full" style="backdrop-filter: blur(6px);">
21
- <div class="flex flex-row items-center gap-2 w-full max-w-5xl">
22
- <input class="floating-search flex-1 px-2 py-1 border border-gray-300 dark:border-gray-700 rounded focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-800 text-gray-900 dark:text-white text-sm" type="text" id="floatingInput" autocomplete="off" placeholder="Search...">
23
- <nav class="inline-flex rounded shadow overflow-hidden border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 overflow-x-auto" id="floating-tabs" role="tablist">
24
- <button class="floating-tab tab-btn whitespace-nowrap px-3 py-1 text-xs font-medium focus:outline-none transition-colors duration-200 text-blue-600 dark:text-blue-400 bg-blue-100 dark:bg-blue-900" id="floating-tab-all" data-tab="all" aria-selected="true" role="tab">All</button>
25
- <button class="floating-tab tab-btn whitespace-nowrap px-3 py-1 text-xs font-medium focus:outline-none transition-colors duration-200 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700" id="floating-tab-global" data-tab="global" aria-selected="false" role="tab">Global</button>
26
- <button class="floating-tab tab-btn whitespace-nowrap px-3 py-1 text-xs font-medium focus:outline-none transition-colors duration-200 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700" id="floating-tab-dashboards" data-tab="dashboards" aria-selected="false" role="tab">Dashboards</button>
27
- <button class="floating-tab tab-btn whitespace-nowrap px-3 py-1 text-xs font-medium focus:outline-none transition-colors duration-200 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700" id="floating-tab-integrations" data-tab="integrations" aria-selected="false" role="tab">Integrations</button>
28
- <button class="floating-tab tab-btn whitespace-nowrap px-3 py-1 text-xs font-medium focus:outline-none transition-colors duration-200 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700" id="floating-tab-favourites" data-tab="favourites" aria-selected="false" role="tab">Favourites</button>
29
- <button class="floating-tab tab-btn whitespace-nowrap px-3 py-1 text-xs font-medium focus:outline-none transition-colors duration-200 text-green-700 dark:text-green-400 hover:bg-green-50 dark:hover:bg-green-900/40" id="floating-tab-upload" data-tab="upload" aria-selected="false" role="tab">+ Upload</button>
13
+
14
+ <body class="bg-gray-50 dark:bg-gray-950 min-h-screen transition-colors duration-300 antialiased">
15
+
16
+ <!-- ── Sticky top bar (appears on scroll) ────────────────────────────── -->
17
+ <div id="floating-bar" class="fixed top-0 left-0 w-full z-50 bg-white/95 dark:bg-gray-900/95 border-b border-gray-200 dark:border-gray-800 px-4 py-2 shadow-sm" style="backdrop-filter:blur(8px);">
18
+ <div class="flex items-center gap-3 max-w-7xl mx-auto">
19
+ <input id="floatingInput" type="text" autocomplete="off" placeholder="Search…"
20
+ class="flex-1 min-w-0 px-3 py-1.5 text-sm bg-gray-100 dark:bg-gray-800 border border-transparent focus:border-blue-500 focus:bg-white dark:focus:bg-gray-900 rounded-lg outline-none text-gray-900 dark:text-white transition">
21
+ <div class="flex gap-1 shrink-0" id="floating-section-btns">
22
+ <button data-section="illustrations" class="floating-section-btn px-3 py-1.5 text-xs font-medium rounded-lg bg-blue-600 text-white focus:outline-none transition">Illustrations</button>
23
+ <button data-section="integrations" class="floating-section-btn px-3 py-1.5 text-xs font-medium rounded-lg bg-transparent text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 focus:outline-none transition">Integrations</button>
24
+ </div>
25
+ <nav id="floating-tabs" class="hidden items-center gap-0.5 bg-gray-100 dark:bg-gray-800 rounded-lg p-0.5" role="tablist">
26
+ <!-- injected by JS -->
30
27
  </nav>
31
28
  </div>
32
29
  </div>
33
- <div class="container mx-auto px-4 py-8">
34
- <div class="flex flex-col md:flex-row items-center justify-between mb-6 gap-4">
35
- <h1 class="text-3xl md:text-5xl font-bold text-center md:text-left text-gray-900 dark:text-white">Dot Illustrations</h1>
36
- <div class="flex items-center gap-3">
37
- <!-- GitHub connect -->
38
- <div id="gh-auth-area">
39
- <button id="gh-connect-btn" class="flex items-center gap-2 px-3 py-2 bg-gray-900 dark:bg-gray-700 text-white rounded-full shadow hover:bg-gray-700 dark:hover:bg-gray-600 transition text-sm focus:outline-none focus:ring-2 focus:ring-blue-500">
40
- <svg class="w-4 h-4" fill="currentColor" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23A11.509 11.509 0 0 1 12 5.803c1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222 0 1.606-.015 2.898-.015 3.293 0 .322.216.694.825.576C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg>
30
+
31
+ <!-- ── Main header ────────────────────────────────────────────────────── -->
32
+ <header class="bg-white dark:bg-gray-900 border-b border-gray-200 dark:border-gray-800 px-4 py-4">
33
+ <div class="max-w-7xl mx-auto flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3">
34
+
35
+ <!-- Title + subtitle -->
36
+ <div>
37
+ <h1 class="text-2xl font-bold text-gray-900 dark:text-white tracking-tight">Dot Illustrations</h1>
38
+ <p class="text-xs text-gray-500 dark:text-gray-400 mt-0.5">
39
+ <a href="https://github.com/digital-ai/dot-illustrations" target="_blank" class="hover:text-blue-600 dark:hover:text-blue-400 transition">github.com/digital-ai/dot-illustrations</a>
40
+ &nbsp;·&nbsp;
41
+ <code class="font-mono">link rel="stylesheet" href="./index.css"</code>
42
+ </p>
43
+ </div>
44
+
45
+ <!-- Toolbar: Upload · GitHub · Theme -->
46
+ <div class="flex items-center gap-2 shrink-0">
47
+
48
+ <!-- Upload New -->
49
+ <button id="upload-new-btn"
50
+ class="flex items-center gap-1.5 px-3 py-2 bg-blue-600 hover:bg-blue-700 text-white text-sm font-medium rounded-lg shadow-sm transition focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-1">
51
+ <svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M3 16.5v2.25A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75V16.5m-13.5-9L12 3m0 0l4.5 4.5M12 3v13.5"/></svg>
52
+ Upload New
53
+ </button>
54
+
55
+ <!-- GitHub auth -->
56
+ <div id="gh-auth-area" class="flex">
57
+ <button id="gh-connect-btn"
58
+ class="flex items-center gap-1.5 px-3 py-2 bg-gray-900 dark:bg-gray-700 hover:bg-gray-800 dark:hover:bg-gray-600 text-white text-sm font-medium rounded-lg shadow-sm transition focus:outline-none focus:ring-2 focus:ring-gray-500">
59
+ <svg class="w-4 h-4" fill="currentColor" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23A11.509 11.509 0 0112 5.803c1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222 0 1.606-.015 2.898-.015 3.293 0 .322.216.694.825.576C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg>
41
60
  Connect GitHub
42
61
  </button>
43
- <span id="gh-user-badge" class="hidden items-center gap-2 px-3 py-2 bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200 rounded-full text-sm">
44
- <svg class="w-4 h-4" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/></svg>
62
+ <span id="gh-user-badge" class="hidden items-center gap-2 px-3 py-2 bg-green-50 dark:bg-green-900/30 border border-green-200 dark:border-green-800 text-green-800 dark:text-green-300 text-sm font-medium rounded-lg">
63
+ <svg class="w-4 h-4 text-green-500" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/></svg>
45
64
  <span id="gh-user-name"></span>
46
- <button id="gh-logout-btn" class="ml-1 text-xs underline opacity-70 hover:opacity-100">Log out</button>
65
+ <button id="gh-logout-btn" class="ml-1 text-xs opacity-50 hover:opacity-100 transition">Log out</button>
47
66
  </span>
48
67
  </div>
49
- <!-- Dark mode toggle -->
50
- <button id="theme-toggle" aria-label="Toggle dark mode" class="flex items-center gap-2 px-4 py-2 bg-gray-200 dark:bg-gray-800 text-gray-800 dark:text-gray-200 rounded-full shadow hover:bg-gray-300 dark:hover:bg-gray-700 transition focus:outline-none focus:ring-2 focus:ring-blue-500">
51
- <span id="theme-icon" class="transition-transform duration-300"></span>
52
- <span class="hidden sm:inline">Switch theme</span>
68
+
69
+ <!-- Dark mode -->
70
+ <button id="theme-toggle" aria-label="Toggle dark mode"
71
+ class="p-2 bg-gray-100 dark:bg-gray-800 hover:bg-gray-200 dark:hover:bg-gray-700 text-gray-600 dark:text-gray-300 rounded-lg transition focus:outline-none focus:ring-2 focus:ring-gray-400">
72
+ <span id="theme-icon"></span>
53
73
  </button>
54
74
  </div>
55
75
  </div>
56
- <p class="text-center text-gray-700 dark:text-gray-300 mb-2">
57
- For more details please see
58
- <a href="https://github.com/digital-ai/dot-illustrations" target="_blank" class="text-blue-600 dark:text-blue-400 underline hover:text-blue-800 dark:hover:text-blue-200 transition">https://github.com/digital-ai/dot-illustrations</a>
59
- </p>
60
- <p class="text-center text-gray-600 dark:text-gray-400 mb-6">For using illustrations as HTML include <code class="bg-gray-200 dark:bg-gray-800 px-2 py-1 rounded text-sm font-mono">link rel="stylesheet" href="./index.css"</code></p>
61
- <div class="flex flex-col md:flex-row items-center justify-center gap-4 mb-8 relative">
62
- <input class="search-wrapper w-full md:w-1/2 px-4 py-2 border border-gray-300 dark:border-gray-700 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-800 text-gray-900 dark:text-white transition" type="text" id="myInput" autocomplete="off" placeholder="Search for illustrations...">
63
- <div id="search-suggestions" class="absolute top-full left-1/2 -translate-x-1/2 w-full md:w-1/2 z-50 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-b-lg shadow-lg hidden max-h-72 overflow-y-auto"></div>
64
- </div>
65
- <!-- Tabs -->
66
- <div class="mb-4 flex justify-center overflow-x-auto">
67
- <nav class="inline-flex rounded-lg shadow overflow-hidden border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 shrink-0" role="tablist" id="main-tabs">
68
- <button class="tab-btn whitespace-nowrap px-5 py-2 text-sm font-medium focus:outline-none transition-colors duration-200 text-blue-600 dark:text-blue-400 bg-blue-100 dark:bg-blue-900" id="tab-all" data-tab="all" aria-selected="true" role="tab">All Illustrations</button>
69
- <button class="tab-btn whitespace-nowrap px-5 py-2 text-sm font-medium focus:outline-none transition-colors duration-200 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700" id="tab-global" data-tab="global" aria-selected="false" role="tab">Global</button>
70
- <button class="tab-btn whitespace-nowrap px-5 py-2 text-sm font-medium focus:outline-none transition-colors duration-200 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700" id="tab-dashboards" data-tab="dashboards" aria-selected="false" role="tab">Dashboards</button>
71
- <button class="tab-btn whitespace-nowrap px-5 py-2 text-sm font-medium focus:outline-none transition-colors duration-200 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700" id="tab-integrations" data-tab="integrations" aria-selected="false" role="tab">Integrations</button>
72
- <button class="tab-btn whitespace-nowrap px-5 py-2 text-sm font-medium focus:outline-none transition-colors duration-200 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700" id="tab-favourites" data-tab="favourites" aria-selected="false" role="tab">Favourites</button>
73
- <button class="tab-btn whitespace-nowrap px-5 py-2 text-sm font-medium focus:outline-none transition-colors duration-200 text-green-700 dark:text-green-400 hover:bg-green-50 dark:hover:bg-green-900/40" id="tab-upload" data-tab="upload" aria-selected="false" role="tab">+ Upload New</button>
74
- </nav>
76
+ </header>
77
+
78
+ <!-- ── Page body ──────────────────────────────────────────────────────── -->
79
+ <main class="max-w-7xl mx-auto px-4 py-6">
80
+
81
+ <!-- Row 1: Search + Section switcher -->
82
+ <div class="flex items-center gap-3 mb-4">
83
+ <div class="relative flex-1">
84
+ <svg class="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400 pointer-events-none" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607z"/></svg>
85
+ <input id="myInput" type="text" autocomplete="off" placeholder="Search…"
86
+ class="w-full pl-10 pr-4 py-2.5 bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded-xl text-sm text-gray-900 dark:text-white outline-none focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 transition">
87
+ <div id="search-suggestions" class="absolute top-full left-0 right-0 z-50 mt-1 bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded-xl shadow-lg hidden max-h-64 overflow-y-auto"></div>
88
+ </div>
89
+ <!-- Section switcher inline with search -->
90
+ <div class="flex items-center bg-gray-100 dark:bg-gray-800 rounded-xl p-1 shrink-0" id="section-switcher">
91
+ <button id="section-illustrations" data-section="illustrations"
92
+ class="section-btn px-4 py-1.5 text-sm font-semibold rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white shadow-sm focus:outline-none transition whitespace-nowrap">
93
+ Illustrations
94
+ </button>
95
+ <button id="section-integrations" data-section="integrations"
96
+ class="section-btn px-4 py-1.5 text-sm font-semibold rounded-lg text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white focus:outline-none transition whitespace-nowrap">
97
+ Integrations
98
+ </button>
99
+ </div>
75
100
  </div>
76
101
 
77
- <!-- Alphabet filter strip -->
78
- <div id="alphabet-strip" class="hidden mb-4 flex flex-wrap justify-center gap-1 px-2">
79
- <button class="alpha-btn px-2 py-0.5 text-xs rounded font-mono bg-blue-600 text-white" data-letter="all">All</button>
102
+ <!-- Row 2: Sub-tabs (illustrations) + Alphabet strip -->
103
+ <div class="flex items-center justify-between gap-4 mb-4 flex-wrap">
104
+ <div id="illus-sub-tabs" class="flex items-center gap-1 bg-gray-100 dark:bg-gray-800 rounded-xl p-1 w-fit" role="tablist">
105
+ <button class="tab-btn px-3 py-1.5 text-sm font-medium rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white shadow-sm focus:outline-none transition" data-tab="all" role="tab">All</button>
106
+ <button class="tab-btn px-3 py-1.5 text-sm font-medium rounded-lg text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white focus:outline-none transition" data-tab="global" role="tab">Global</button>
107
+ <button class="tab-btn px-3 py-1.5 text-sm font-medium rounded-lg text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white focus:outline-none transition" data-tab="dashboards" role="tab">Dashboards</button>
108
+ <button class="tab-btn px-3 py-1.5 text-sm font-medium rounded-lg text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white focus:outline-none transition" data-tab="favourites" role="tab">Favourites</button>
109
+ </div>
110
+ <div id="alphabet-strip" class="hidden items-center flex-wrap gap-0.5"></div>
80
111
  </div>
81
112
 
82
- <!-- Result count + integration note -->
83
- <p id="result-count" class="text-center text-sm text-gray-500 dark:text-gray-400 mb-4"></p>
84
- <p id="integrations-note" class="hidden text-center text-xs text-gray-500 dark:text-gray-400 mb-4">
85
- Integration logos are single-theme (no dark variant). Use <code class="font-mono bg-gray-200 dark:bg-gray-800 px-1 rounded">.dot-integration</code> wrapper.
86
- </p>
113
+ <!-- Result count -->
114
+ <p id="result-count" class="text-xs text-gray-400 dark:text-gray-500 mb-3"></p>
87
115
 
88
116
  <!-- Grid -->
89
- <div id="illustration-list" class="demo-wrapper dot-illustration grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-5 xl:grid-cols-6 gap-6 max-h-[calc(100vh-320px)] overflow-y-auto px-2">
90
- <!-- injected by JS -->
117
+ <div id="illustration-list"
118
+ class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 xl:grid-cols-6 gap-3 max-h-[calc(100vh-280px)] overflow-y-auto pr-1">
91
119
  </div>
92
120
 
93
- <!-- Upload panel -->
94
- <div id="upload-panel" class="hidden mt-8">
95
- <div class="max-w-2xl mx-auto grid md:grid-cols-2 gap-6">
121
+ <!-- Upload modal — rendered as fixed overlay, NOT inline -->
122
+ <div id="upload-panel" class="hidden fixed inset-0 z-50 flex items-center justify-center bg-black/40 dark:bg-black/60 backdrop-blur-sm p-4">
96
123
 
97
- <!-- Illustration upload -->
98
- <div class="bg-white dark:bg-gray-800 rounded-xl shadow-lg p-6 border border-gray-200 dark:border-gray-700 flex flex-col gap-4">
99
- <h2 class="text-lg font-semibold text-gray-900 dark:text-white">Upload Illustration PR</h2>
100
- <div id="upload-illus-auth-gate" class="p-3 bg-yellow-50 dark:bg-yellow-900/30 border border-yellow-200 dark:border-yellow-700 rounded-lg text-sm text-yellow-800 dark:text-yellow-200">
101
- Connect GitHub (header) to enable.
102
- </div>
103
- <div id="upload-illus-form" class="hidden flex flex-col gap-3">
104
- <div>
105
- <label class="text-xs font-medium text-gray-700 dark:text-gray-300 mb-1 block">Illustration ID <span class="text-red-500">*</span></label>
106
- <input id="upload-illus-id" type="text" placeholder="e.g. my-illustration" class="w-full px-3 py-1.5 border border-gray-300 dark:border-gray-700 rounded-lg bg-white dark:bg-gray-900 text-gray-900 dark:text-white text-sm focus:outline-none focus:ring-2 focus:ring-blue-500" />
107
- </div>
108
- <div>
109
- <label class="text-xs font-medium text-gray-700 dark:text-gray-300 mb-1 block">Category</label>
110
- <select id="upload-illus-category" class="w-full px-3 py-1.5 border border-gray-300 dark:border-gray-700 rounded-lg bg-white dark:bg-gray-900 text-gray-900 dark:text-white text-sm focus:outline-none focus:ring-2 focus:ring-blue-500">
111
- <option value="global" selected>Global</option>
112
- <option value="dashboards">Dashboards</option>
113
- </select>
114
- </div>
115
- <div class="grid grid-cols-2 gap-3">
116
- <div>
117
- <label class="text-xs font-medium text-gray-700 dark:text-gray-300 mb-1 block">☀️ Light SVG <span class="text-red-500">*</span></label>
118
- <div id="illus-light-drop" class="border-2 border-dashed border-gray-300 dark:border-gray-600 rounded-lg p-3 text-center cursor-pointer hover:border-blue-400 transition text-xs text-gray-500 dark:text-gray-400">
119
- Drop or click
120
- <input id="illus-light-input" type="file" accept=".svg" class="hidden" />
121
- </div>
122
- <p id="illus-light-name" class="text-xs text-green-600 dark:text-green-400 mt-1 truncate hidden"></p>
123
- </div>
124
- <div>
125
- <label class="text-xs font-medium text-gray-700 dark:text-gray-300 mb-1 block">🌙 Dark SVG <span class="text-red-500">*</span></label>
126
- <div id="illus-dark-drop" class="border-2 border-dashed border-gray-300 dark:border-gray-600 rounded-lg p-3 text-center cursor-pointer hover:border-blue-400 transition text-xs text-gray-500 dark:text-gray-400">
127
- Drop or click
128
- <input id="illus-dark-input" type="file" accept=".svg" class="hidden" />
129
- </div>
130
- <p id="illus-dark-name" class="text-xs text-green-600 dark:text-green-400 mt-1 truncate hidden"></p>
131
- </div>
124
+ <!-- Modal inner container -->
125
+ <div class="relative bg-white dark:bg-gray-900 rounded-2xl shadow-2xl border border-gray-200 dark:border-gray-700 w-full max-w-md max-h-[90vh] overflow-y-auto">
126
+ <button id="upload-modal-close" class="absolute top-4 right-4 z-10 p-1.5 rounded-lg text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-800 transition">
127
+ <svg class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/></svg>
128
+ </button>
129
+
130
+ <!-- Step 1: choose type -->
131
+ <div id="upload-type-picker" class="p-6">
132
+ <h2 class="text-base font-semibold text-gray-900 dark:text-white mb-1">What do you want to upload?</h2>
133
+ <p class="text-xs text-gray-400 dark:text-gray-500 mb-5">A PR will be created automatically once you fill in the details.</p>
134
+ <div class="grid grid-cols-2 gap-3">
135
+ <button id="pick-illustration"
136
+ class="flex flex-col items-center gap-3 p-5 rounded-xl border-2 border-gray-200 dark:border-gray-700 hover:border-blue-500 dark:hover:border-blue-400 hover:bg-blue-50 dark:hover:bg-blue-900/20 transition group focus:outline-none focus:border-blue-500">
137
+ <span class="text-4xl">🖼</span>
138
+ <div class="text-center">
139
+ <p class="text-sm font-semibold text-gray-900 dark:text-white group-hover:text-blue-700 dark:group-hover:text-blue-300 transition">Illustration</p>
140
+ <p class="text-xs text-gray-400 dark:text-gray-500 mt-0.5">Light + dark SVG variants</p>
132
141
  </div>
133
- <button id="upload-illus-btn" class="w-full px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg font-medium text-sm transition focus:outline-none focus:ring-2 focus:ring-blue-500 disabled:opacity-50">Create PR</button>
134
- <div id="upload-illus-status" class="hidden text-sm text-center"></div>
135
- <div id="upload-illus-pr-link" class="hidden text-center">
136
- <a id="upload-illus-pr-anchor" href="#" target="_blank" class="inline-flex items-center gap-2 px-3 py-1.5 bg-green-600 hover:bg-green-700 text-white rounded-lg font-medium text-sm transition">View Pull Request ↗</a>
142
+ </button>
143
+ <button id="pick-integration"
144
+ class="flex flex-col items-center gap-3 p-5 rounded-xl border-2 border-gray-200 dark:border-gray-700 hover:border-blue-500 dark:hover:border-blue-400 hover:bg-blue-50 dark:hover:bg-blue-900/20 transition group focus:outline-none focus:border-blue-500">
145
+ <span class="text-4xl">🔌</span>
146
+ <div class="text-center">
147
+ <p class="text-sm font-semibold text-gray-900 dark:text-white group-hover:text-blue-700 dark:group-hover:text-blue-300 transition">Integration</p>
148
+ <p class="text-xs text-gray-400 dark:text-gray-500 mt-0.5">Single SVG, no dark variant</p>
137
149
  </div>
138
- </div>
150
+ </button>
139
151
  </div>
152
+ </div>
140
153
 
141
- <!-- Integration upload -->
142
- <div class="bg-white dark:bg-gray-800 rounded-xl shadow-lg p-6 border border-gray-200 dark:border-gray-700 flex flex-col gap-4">
143
- <h2 class="text-lg font-semibold text-gray-900 dark:text-white">Upload Integration → PR</h2>
144
- <div id="upload-integ-auth-gate" class="p-3 bg-yellow-50 dark:bg-yellow-900/30 border border-yellow-200 dark:border-yellow-700 rounded-lg text-sm text-yellow-800 dark:text-yellow-200">
145
- Connect GitHub (header) to enable.
154
+ <!-- Step 2a: Illustration form -->
155
+ <div id="upload-illus-panel" class="hidden p-6 flex flex-col gap-4">
156
+ <div class="flex items-center gap-3 mb-1">
157
+ <button id="back-from-illus" class="text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 transition">
158
+ <svg class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M10.5 19.5L3 12m0 0l7.5-7.5M3 12h18"/></svg>
159
+ </button>
160
+ <div>
161
+ <h2 class="text-base font-semibold text-gray-900 dark:text-white">🖼 Upload Illustration</h2>
162
+ <p class="text-xs text-gray-400 dark:text-gray-500">Requires light and dark SVG variants</p>
146
163
  </div>
147
- <div id="upload-integ-form" class="hidden flex flex-col gap-3">
164
+ </div>
165
+
166
+ <div id="upload-illus-auth-gate" class="flex items-center gap-2 p-3 bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800 rounded-lg text-xs text-amber-700 dark:text-amber-300">
167
+ <svg class="w-4 h-4 shrink-0" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z"/></svg>
168
+ Connect GitHub to enable uploads
169
+ </div>
170
+ <div id="upload-illus-form" class="hidden flex flex-col gap-3">
171
+ <input id="upload-illus-id" type="text" placeholder="Illustration ID (e.g. my-illustration)"
172
+ class="w-full px-3 py-2 text-sm bg-gray-50 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg text-gray-900 dark:text-white outline-none focus:border-blue-500 transition">
173
+ <select id="upload-illus-category"
174
+ class="w-full px-3 py-2 text-sm bg-gray-50 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg text-gray-900 dark:text-white outline-none focus:border-blue-500 transition">
175
+ <option value="global">Global</option>
176
+ <option value="dashboards">Dashboards</option>
177
+ </select>
178
+ <div class="grid grid-cols-2 gap-3">
148
179
  <div>
149
- <label class="text-xs font-medium text-gray-700 dark:text-gray-300 mb-1 block">Integration ID <span class="text-red-500">*</span></label>
150
- <input id="upload-integ-id" type="text" placeholder="e.g. my-tool" class="w-full px-3 py-1.5 border border-gray-300 dark:border-gray-700 rounded-lg bg-white dark:bg-gray-900 text-gray-900 dark:text-white text-sm focus:outline-none focus:ring-2 focus:ring-blue-500" />
180
+ <p class="text-xs text-gray-500 dark:text-gray-400 mb-1">☀️ Light SVG <span class="text-red-400">*</span></p>
181
+ <div id="illus-light-drop" class="border-2 border-dashed border-gray-200 dark:border-gray-700 rounded-lg p-4 text-center text-xs text-gray-400 cursor-pointer hover:border-blue-400 transition">
182
+ Drop or click<input id="illus-light-input" type="file" accept=".svg" class="hidden">
183
+ </div>
184
+ <p id="illus-light-name" class="hidden text-xs text-green-600 dark:text-green-400 mt-1 truncate"></p>
151
185
  </div>
152
186
  <div>
153
- <label class="text-xs font-medium text-gray-700 dark:text-gray-300 mb-1 block">SVG file (single, no dark variant) <span class="text-red-500">*</span></label>
154
- <div id="integ-svg-drop" class="border-2 border-dashed border-gray-300 dark:border-gray-600 rounded-lg p-4 text-center cursor-pointer hover:border-blue-400 transition text-sm text-gray-500 dark:text-gray-400">
155
- Drop SVG here or click to browse
156
- <input id="integ-svg-input" type="file" accept=".svg" class="hidden" />
187
+ <p class="text-xs text-gray-500 dark:text-gray-400 mb-1">🌙 Dark SVG <span class="text-red-400">*</span></p>
188
+ <div id="illus-dark-drop" class="border-2 border-dashed border-gray-200 dark:border-gray-700 rounded-lg p-4 text-center text-xs text-gray-400 cursor-pointer hover:border-blue-400 transition">
189
+ Drop or click<input id="illus-dark-input" type="file" accept=".svg" class="hidden">
157
190
  </div>
158
- <p id="integ-svg-name" class="text-xs text-green-600 dark:text-green-400 mt-1 truncate hidden"></p>
159
- </div>
160
- <div class="p-3 bg-blue-50 dark:bg-blue-900/30 border border-blue-200 dark:border-blue-700 rounded-lg text-xs text-blue-800 dark:text-blue-200">
161
- Integration logos have no dark variant. Use a square, brand-accurate SVG.
162
- </div>
163
- <button id="upload-integ-btn" class="w-full px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg font-medium text-sm transition focus:outline-none focus:ring-2 focus:ring-blue-500 disabled:opacity-50">Create PR</button>
164
- <div id="upload-integ-status" class="hidden text-sm text-center"></div>
165
- <div id="upload-integ-pr-link" class="hidden text-center">
166
- <a id="upload-integ-pr-anchor" href="#" target="_blank" class="inline-flex items-center gap-2 px-3 py-1.5 bg-green-600 hover:bg-green-700 text-white rounded-lg font-medium text-sm transition">View Pull Request ↗</a>
191
+ <p id="illus-dark-name" class="hidden text-xs text-green-600 dark:text-green-400 mt-1 truncate"></p>
167
192
  </div>
168
193
  </div>
194
+ <button id="upload-illus-btn" class="w-full px-4 py-2.5 bg-blue-600 hover:bg-blue-700 text-white text-sm font-medium rounded-lg transition disabled:opacity-50">Create Pull Request</button>
195
+ <div id="upload-illus-status" class="hidden text-xs text-center"></div>
196
+ <div id="upload-illus-pr-link" class="hidden">
197
+ <a id="upload-illus-pr-anchor" href="#" target="_blank" class="flex items-center justify-center gap-2 px-4 py-2 bg-green-600 hover:bg-green-700 text-white text-sm font-medium rounded-lg transition">View Pull Request ↗</a>
198
+ </div>
169
199
  </div>
170
200
  </div>
171
- </div>
172
- </div>
173
- <!-- Modal for illustration details -->
174
- <div id="illustration-modal" class="fixed inset-0 z-50 flex items-center justify-center bg-black/50 dark:bg-black/70 hidden">
175
- <div class="bg-white dark:bg-gray-900 rounded-xl shadow-2xl max-w-lg w-full p-6 relative flex flex-col items-center">
176
- <button id="modal-close" class="absolute top-3 right-3 text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 text-2xl font-bold focus:outline-none">&times;</button>
177
- <h2 class="text-xl font-semibold mb-4 w-full text-center text-gray-900 dark:text-gray-100">Illustration preview</h2>
178
- <div id="modal-image" class="mb-4"></div>
179
- <div class="w-full flex flex-col gap-2 mb-2">
180
- <div class="text-base font-semibold text-center text-gray-800 dark:text-gray-100 mb-1" id="modal-illustration-name"></div>
181
- </div>
182
- <div class="w-full flex flex-col gap-2 mb-2">
183
- <label class="text-xs font-medium text-gray-500 dark:text-gray-400" for="modal-dot-code">Dot Code</label>
184
- <div class="flex flex-row items-center gap-2">
185
- <textarea id="modal-dot-code" class="flex-1 px-2 py-1 border border-gray-300 dark:border-gray-700 rounded bg-gray-100 dark:bg-gray-800 text-gray-900 dark:text-white text-xs font-mono resize-none" rows="2" readonly></textarea>
186
- <button id="modal-copy-dot-code" class="button flex items-center justify-center px-2 py-1 text-xs text-gray-400 border border-gray-300 dark:border-gray-700 rounded bg-white dark:bg-gray-800 font-normal hover:bg-blue-100 dark:hover:bg-blue-900 transition relative text-center" title="Copy Dot Code">Copy Dot Code</button>
201
+
202
+ <!-- Step 2b: Integration form -->
203
+ <div id="upload-integ-panel" class="hidden p-6 flex flex-col gap-4">
204
+ <div class="flex items-center gap-3 mb-1">
205
+ <button id="back-from-integ" class="text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 transition">
206
+ <svg class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M10.5 19.5L3 12m0 0l7.5-7.5M3 12h18"/></svg>
207
+ </button>
208
+ <div>
209
+ <h2 class="text-base font-semibold text-gray-900 dark:text-white">🔌 Upload Integration</h2>
210
+ <p class="text-xs text-gray-400 dark:text-gray-500">Single SVG — no dark variant required</p>
211
+ </div>
212
+ </div>
213
+
214
+ <div id="upload-integ-auth-gate" class="flex items-center gap-2 p-3 bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800 rounded-lg text-xs text-amber-700 dark:text-amber-300">
215
+ <svg class="w-4 h-4 shrink-0" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z"/></svg>
216
+ Connect GitHub to enable uploads
217
+ </div>
218
+ <div id="upload-integ-form" class="hidden flex flex-col gap-3">
219
+ <input id="upload-integ-id" type="text" placeholder="Integration ID (e.g. my-tool)"
220
+ class="w-full px-3 py-2 text-sm bg-gray-50 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg text-gray-900 dark:text-white outline-none focus:border-blue-500 transition">
221
+ <div id="integ-svg-drop" class="border-2 border-dashed border-gray-200 dark:border-gray-700 rounded-xl p-6 text-center text-sm text-gray-400 cursor-pointer hover:border-blue-400 transition">
222
+ Drop SVG here or click to browse<input id="integ-svg-input" type="file" accept=".svg" class="hidden">
223
+ </div>
224
+ <p id="integ-svg-name" class="hidden text-xs text-green-600 dark:text-green-400 truncate"></p>
225
+ <button id="upload-integ-btn" class="w-full px-4 py-2.5 bg-blue-600 hover:bg-blue-700 text-white text-sm font-medium rounded-lg transition disabled:opacity-50">Create Pull Request</button>
226
+ <div id="upload-integ-status" class="hidden text-xs text-center"></div>
227
+ <div id="upload-integ-pr-link" class="hidden">
228
+ <a id="upload-integ-pr-anchor" href="#" target="_blank" class="flex items-center justify-center gap-2 px-4 py-2 bg-green-600 hover:bg-green-700 text-white text-sm font-medium rounded-lg transition">View Pull Request ↗</a>
229
+ </div>
187
230
  </div>
188
231
  </div>
189
- <div class="w-full flex flex-col gap-2 mb-2">
190
- <label class="text-xs font-medium text-gray-500 dark:text-gray-400" for="modal-code">HTML Code</label>
191
- <div class="flex flex-row items-center gap-2">
192
- <textarea id="modal-code" class="flex-1 px-2 py-1 border border-gray-300 dark:border-gray-700 rounded bg-gray-100 dark:bg-gray-800 text-gray-900 dark:text-white text-xs font-mono resize-none" rows="2" readonly></textarea>
193
- <button id="modal-copy-code" class="button flex items-center justify-center px-2 py-1 text-xs text-gray-400 border border-gray-300 dark:border-gray-700 rounded bg-white dark:bg-gray-800 font-normal hover:bg-blue-100 dark:hover:bg-blue-900 transition relative text-center">Copy Code</button>
232
+
233
+ </div><!-- /modal inner container -->
234
+ </div><!-- /upload-panel modal overlay -->
235
+
236
+ </main>
237
+
238
+ <!-- ── Illustration detail modal ──────────────────────────────────────── -->
239
+ <div id="illustration-modal" class="fixed inset-0 z-50 flex items-center justify-center bg-black/40 dark:bg-black/60 backdrop-blur-sm hidden">
240
+ <div class="bg-white dark:bg-gray-900 rounded-2xl shadow-2xl max-w-md w-full mx-4 p-6 relative flex flex-col items-center border border-gray-200 dark:border-gray-700">
241
+ <button id="modal-close" class="absolute top-4 right-4 text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 transition">
242
+ <svg class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/></svg>
243
+ </button>
244
+ <div id="modal-image" class="mb-4 p-4 bg-gray-50 dark:bg-gray-800 rounded-xl"></div>
245
+ <p class="text-base font-semibold text-gray-900 dark:text-white mb-4" id="modal-illustration-name"></p>
246
+ <div class="w-full space-y-3 mb-4">
247
+ <div>
248
+ <label class="text-xs font-medium text-gray-500 dark:text-gray-400 mb-1 block">Dot Code</label>
249
+ <div class="flex gap-2">
250
+ <textarea id="modal-dot-code" readonly rows="2"
251
+ class="flex-1 px-3 py-2 text-xs font-mono bg-gray-50 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg text-gray-900 dark:text-white resize-none outline-none"></textarea>
252
+ <button id="modal-copy-dot-code"
253
+ class="px-3 py-1 text-xs bg-gray-100 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 text-gray-700 dark:text-gray-300 rounded-lg hover:bg-blue-50 dark:hover:bg-blue-900/30 transition">Copy</button>
254
+ </div>
255
+ </div>
256
+ <div>
257
+ <label class="text-xs font-medium text-gray-500 dark:text-gray-400 mb-1 block">HTML Code</label>
258
+ <div class="flex gap-2">
259
+ <textarea id="modal-code" readonly rows="2"
260
+ class="flex-1 px-3 py-2 text-xs font-mono bg-gray-50 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg text-gray-900 dark:text-white resize-none outline-none"></textarea>
261
+ <button id="modal-copy-code"
262
+ class="px-3 py-1 text-xs bg-gray-100 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 text-gray-700 dark:text-gray-300 rounded-lg hover:bg-blue-50 dark:hover:bg-blue-900/30 transition">Copy</button>
263
+ </div>
194
264
  </div>
195
265
  </div>
196
- <button id="modal-close-bottom" class="mt-4 px-4 py-2 rounded bg-gray-200 dark:bg-gray-700 text-gray-800 dark:text-gray-200 font-medium hover:bg-gray-300 dark:hover:bg-gray-600 transition">Close</button>
266
+ <button id="modal-close-bottom"
267
+ class="px-5 py-2 text-sm bg-gray-100 dark:bg-gray-800 text-gray-700 dark:text-gray-300 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-700 transition">Close</button>
197
268
  </div>
198
269
  </div>
199
- <!-- GitHub Device Flow modal -->
200
- <div id="gh-device-modal" class="fixed inset-0 z-50 flex items-center justify-center bg-black/50 dark:bg-black/70 hidden">
201
- <div class="bg-white dark:bg-gray-900 rounded-xl shadow-2xl max-w-sm w-full p-6 relative flex flex-col items-center mx-4">
202
- <button id="gh-device-close" class="absolute top-3 right-3 text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 text-2xl font-bold focus:outline-none">&times;</button>
203
- <svg class="w-10 h-10 mb-4 text-gray-800 dark:text-gray-200" fill="currentColor" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23A11.509 11.509 0 0 1 12 5.803c1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222 0 1.606-.015 2.898-.015 3.293 0 .322.216.694.825.576C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg>
204
- <h2 class="text-xl font-bold text-gray-900 dark:text-white mb-2">Connect GitHub</h2>
205
- <div id="gh-device-step-code" class="w-full flex flex-col items-center gap-3">
206
- <p class="text-sm text-gray-600 dark:text-gray-400 text-center">Open the URL below and enter the code to authorise.</p>
207
- <a id="gh-device-uri" href="#" target="_blank" class="text-blue-600 dark:text-blue-400 underline text-sm font-medium"></a>
208
- <div class="flex items-center gap-2">
209
- <code id="gh-device-code" class="text-2xl font-mono tracking-widest bg-gray-100 dark:bg-gray-800 px-4 py-2 rounded-lg text-gray-900 dark:text-white"></code>
210
- <button id="gh-copy-code-btn" class="text-xs px-2 py-1 bg-gray-200 dark:bg-gray-700 rounded hover:bg-gray-300 dark:hover:bg-gray-600 transition">Copy</button>
270
+
271
+ <!-- ── GitHub Device Flow modal ───────────────────────────────────────── -->
272
+ <div id="gh-device-modal" class="fixed inset-0 z-50 flex items-center justify-center bg-black/40 dark:bg-black/60 backdrop-blur-sm hidden">
273
+ <div class="bg-white dark:bg-gray-900 rounded-2xl shadow-2xl max-w-sm w-full mx-4 p-6 relative border border-gray-200 dark:border-gray-700">
274
+ <button id="gh-device-close" class="absolute top-4 right-4 text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 transition">
275
+ <svg class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/></svg>
276
+ </button>
277
+ <div class="flex flex-col items-center gap-4">
278
+ <svg class="w-10 h-10 text-gray-800 dark:text-white" fill="currentColor" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23A11.509 11.509 0 0112 5.803c1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222 0 1.606-.015 2.898-.015 3.293 0 .322.216.694.825.576C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg>
279
+ <h2 class="text-xl font-bold text-gray-900 dark:text-white">Connect GitHub</h2>
280
+
281
+ <div id="gh-device-step-code" class="w-full flex flex-col items-center gap-3">
282
+ <p class="text-sm text-gray-500 dark:text-gray-400 text-center">Open the URL below and enter the code.</p>
283
+ <a id="gh-device-uri" href="#" target="_blank" class="text-sm text-blue-600 dark:text-blue-400 underline font-medium"></a>
284
+ <div class="flex items-center gap-2">
285
+ <code id="gh-device-code" class="text-2xl font-mono tracking-widest bg-gray-100 dark:bg-gray-800 px-4 py-2 rounded-xl text-gray-900 dark:text-white"></code>
286
+ <button id="gh-copy-code-btn" class="text-xs px-2 py-1 bg-gray-200 dark:bg-gray-700 rounded-lg hover:bg-gray-300 dark:hover:bg-gray-600 transition">Copy</button>
287
+ </div>
288
+ <div class="flex items-center gap-2 text-gray-400 text-sm">
289
+ <svg class="animate-spin w-4 h-4" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v8z"></path></svg>
290
+ Waiting for authorisation…
291
+ </div>
211
292
  </div>
212
- <div class="flex items-center gap-2 text-gray-500 dark:text-gray-400 text-sm">
213
- <svg class="animate-spin w-4 h-4" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v8z"></path></svg>
214
- Waiting for authorisation…
293
+
294
+ <div id="gh-device-step-pat" class="w-full flex flex-col gap-3 hidden">
295
+ <p class="text-sm text-gray-500 dark:text-gray-400 text-center">Enter a GitHub Personal Access Token with <code class="font-mono text-xs bg-gray-100 dark:bg-gray-800 px-1 rounded">public_repo</code> scope.</p>
296
+ <input id="gh-pat-input" type="password" placeholder="ghp_…"
297
+ class="w-full px-3 py-2 text-sm bg-gray-50 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg text-gray-900 dark:text-white outline-none focus:border-blue-500 transition">
298
+ <a href="https://github.com/settings/tokens/new?scopes=public_repo&description=dot-illustrations+demo" target="_blank" class="text-xs text-blue-600 dark:text-blue-400 underline text-center">Create token on GitHub ↗</a>
299
+ <button id="gh-pat-submit" class="w-full px-4 py-2 bg-gray-900 dark:bg-gray-700 hover:bg-gray-800 dark:hover:bg-gray-600 text-white text-sm font-medium rounded-lg transition">Connect</button>
215
300
  </div>
301
+
302
+ <div id="gh-device-error" class="hidden text-xs text-red-600 dark:text-red-400 text-center"></div>
216
303
  </div>
217
- <div id="gh-device-step-pat" class="w-full flex flex-col gap-3 hidden">
218
- <p class="text-sm text-gray-600 dark:text-gray-400 text-center">Enter a GitHub Personal Access Token with <code class="font-mono text-xs">public_repo</code> scope.</p>
219
- <input id="gh-pat-input" type="password" placeholder="ghp_…" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-700 rounded-lg bg-white dark:bg-gray-900 text-gray-900 dark:text-white text-sm focus:outline-none focus:ring-2 focus:ring-blue-500" />
220
- <a href="https://github.com/settings/tokens/new?scopes=public_repo&description=dot-illustrations+demo+upload" target="_blank" class="text-xs text-blue-600 dark:text-blue-400 underline text-center">Create a token on GitHub ↗</a>
221
- <button id="gh-pat-submit" class="w-full px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg font-medium transition">Connect with token</button>
222
- </div>
223
- <div id="gh-device-error" class="hidden mt-2 text-sm text-red-600 dark:text-red-400 text-center"></div>
224
304
  </div>
225
305
  </div>
226
306
 
227
307
  </body>
228
- </html>
308
+ </html>