Tools for the Atmosphere tools.slices.network
quickslice atproto html

feat: add lexicon-validator HTML shell with light theme CSS

+279
+279
lexicon-validator.html
··· 1 + <!doctype html> 2 + <html lang="en"> 3 + <head> 4 + <meta charset="UTF-8" /> 5 + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 6 + <meta 7 + http-equiv="Content-Security-Policy" 8 + content="default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net; style-src 'self' 'unsafe-inline';" 9 + /> 10 + <title>Lexicon Validator</title> 11 + <style> 12 + /* CSS Reset */ 13 + *, *::before, *::after { box-sizing: border-box; } 14 + * { margin: 0; } 15 + body { line-height: 1.5; -webkit-font-smoothing: antialiased; } 16 + input, button, textarea { font: inherit; } 17 + 18 + /* Light Theme */ 19 + :root { 20 + --bg-primary: #f5f5f5; 21 + --bg-card: #ffffff; 22 + --bg-input: #fafafa; 23 + --text-primary: #1a1a1a; 24 + --text-secondary: #666666; 25 + --accent: #0066cc; 26 + --accent-hover: #0052a3; 27 + --border: #e0e0e0; 28 + --border-focus: #0066cc; 29 + --error-bg: #fef2f2; 30 + --error-border: #fca5a5; 31 + --error-text: #dc2626; 32 + --success-bg: #f0fdf4; 33 + --success-border: #86efac; 34 + --success-text: #16a34a; 35 + } 36 + 37 + body { 38 + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; 39 + background: var(--bg-primary); 40 + color: var(--text-primary); 41 + min-height: 100vh; 42 + padding: 2rem 1rem; 43 + } 44 + 45 + #app { 46 + max-width: 700px; 47 + margin: 0 auto; 48 + } 49 + 50 + header { 51 + text-align: center; 52 + margin-bottom: 2rem; 53 + } 54 + 55 + header h1 { 56 + font-size: 2rem; 57 + color: var(--text-primary); 58 + margin-bottom: 0.25rem; 59 + } 60 + 61 + .tagline { 62 + color: var(--text-secondary); 63 + font-size: 0.875rem; 64 + } 65 + 66 + /* Sections */ 67 + .section { 68 + background: var(--bg-card); 69 + border-radius: 0.5rem; 70 + padding: 1rem; 71 + margin-bottom: 1rem; 72 + border: 1px solid var(--border); 73 + box-shadow: 0 1px 3px rgba(0,0,0,0.05); 74 + } 75 + 76 + .section-header { 77 + display: flex; 78 + justify-content: space-between; 79 + align-items: center; 80 + margin-bottom: 0.75rem; 81 + } 82 + 83 + .section-title { 84 + font-weight: 600; 85 + font-size: 0.875rem; 86 + text-transform: uppercase; 87 + letter-spacing: 0.05em; 88 + color: var(--text-secondary); 89 + } 90 + 91 + /* Buttons */ 92 + .btn { 93 + padding: 0.5rem 1rem; 94 + border: none; 95 + border-radius: 0.375rem; 96 + font-size: 0.875rem; 97 + font-weight: 500; 98 + cursor: pointer; 99 + transition: background-color 0.15s, opacity 0.15s; 100 + } 101 + 102 + .btn-primary { 103 + background: var(--accent); 104 + color: #ffffff; 105 + } 106 + 107 + .btn-primary:hover { 108 + background: var(--accent-hover); 109 + } 110 + 111 + .btn-secondary { 112 + background: var(--bg-card); 113 + color: var(--text-primary); 114 + border: 1px solid var(--border); 115 + } 116 + 117 + .btn-secondary:hover { 118 + background: var(--bg-primary); 119 + } 120 + 121 + .btn-small { 122 + padding: 0.25rem 0.5rem; 123 + font-size: 0.75rem; 124 + } 125 + 126 + .btn-danger { 127 + background: var(--error-bg); 128 + color: var(--error-text); 129 + border: 1px solid var(--error-border); 130 + } 131 + 132 + .btn-danger:hover { 133 + background: #fee2e2; 134 + } 135 + 136 + .btn:disabled { 137 + opacity: 0.5; 138 + cursor: not-allowed; 139 + } 140 + 141 + /* Editors */ 142 + .editor-card { 143 + background: var(--bg-input); 144 + border: 1px solid var(--border); 145 + border-radius: 0.375rem; 146 + margin-bottom: 0.75rem; 147 + } 148 + 149 + .editor-header { 150 + display: flex; 151 + justify-content: space-between; 152 + align-items: center; 153 + padding: 0.5rem 0.75rem; 154 + border-bottom: 1px solid var(--border); 155 + background: var(--bg-card); 156 + border-radius: 0.375rem 0.375rem 0 0; 157 + } 158 + 159 + .editor-label { 160 + font-size: 0.75rem; 161 + color: var(--text-secondary); 162 + font-weight: 500; 163 + } 164 + 165 + textarea { 166 + width: 100%; 167 + min-height: 200px; 168 + padding: 0.75rem; 169 + background: var(--bg-input); 170 + border: none; 171 + color: var(--text-primary); 172 + font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace; 173 + font-size: 0.8125rem; 174 + resize: vertical; 175 + border-radius: 0 0 0.375rem 0.375rem; 176 + } 177 + 178 + textarea:focus { 179 + outline: none; 180 + background: #ffffff; 181 + } 182 + 183 + textarea::placeholder { 184 + color: var(--text-secondary); 185 + opacity: 0.6; 186 + } 187 + 188 + /* NSID Input */ 189 + .nsid-row { 190 + display: flex; 191 + align-items: center; 192 + gap: 0.75rem; 193 + margin-bottom: 0.75rem; 194 + } 195 + 196 + .nsid-label { 197 + font-size: 0.875rem; 198 + color: var(--text-secondary); 199 + white-space: nowrap; 200 + } 201 + 202 + input[type="text"] { 203 + flex: 1; 204 + padding: 0.5rem 0.75rem; 205 + background: var(--bg-input); 206 + border: 1px solid var(--border); 207 + border-radius: 0.375rem; 208 + color: var(--text-primary); 209 + font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace; 210 + font-size: 0.8125rem; 211 + } 212 + 213 + input[type="text"]:focus { 214 + outline: none; 215 + border-color: var(--border-focus); 216 + background: #ffffff; 217 + } 218 + 219 + input[type="text"]::placeholder { 220 + color: var(--text-secondary); 221 + opacity: 0.6; 222 + } 223 + 224 + /* Results */ 225 + .result { 226 + padding: 1rem; 227 + border-radius: 0.375rem; 228 + font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace; 229 + font-size: 0.8125rem; 230 + white-space: pre-wrap; 231 + word-break: break-word; 232 + } 233 + 234 + .result-success { 235 + background: var(--success-bg); 236 + border: 1px solid var(--success-border); 237 + color: var(--success-text); 238 + } 239 + 240 + .result-error { 241 + background: var(--error-bg); 242 + border: 1px solid var(--error-border); 243 + color: var(--error-text); 244 + } 245 + 246 + .result:empty { 247 + display: none; 248 + } 249 + 250 + /* Button row */ 251 + .button-row { 252 + display: flex; 253 + gap: 0.5rem; 254 + margin-top: 0.75rem; 255 + } 256 + 257 + .hidden { 258 + display: none !important; 259 + } 260 + </style> 261 + </head> 262 + <body> 263 + <div id="app"> 264 + <header> 265 + <h1>Lexicon Validator</h1> 266 + <p class="tagline">AT Protocol Lexicon Validator</p> 267 + </header> 268 + <main> 269 + <div id="lexicons-section" class="section"></div> 270 + <div id="record-section" class="section"></div> 271 + <div id="results-section"></div> 272 + </main> 273 + </div> 274 + <script src="https://cdn.jsdelivr.net/gh/bigmoves/honk@main/dist/honk.min.js"></script> 275 + <script> 276 + // JavaScript will be added in subsequent tasks 277 + </script> 278 + </body> 279 + </html>