firefox + llama.cpp == very good prose.
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 382 lines 9.0 kB view raw
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 <title>shakespeare prose.</title> 7 <style> 8 * { margin: 0; padding: 0; box-sizing: border-box; } 9 10 body { 11 font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; 12 background: #1a1a2e; 13 color: #e0e0e0; 14 padding: 20px; 15 min-height: 100vh; 16 } 17 18 h1 { 19 font-size: 14px; 20 font-weight: 600; 21 color: #8888aa; 22 text-transform: uppercase; 23 letter-spacing: 0.5px; 24 margin-bottom: 16px; 25 } 26 27 /* ─── Loading spinner ──────────────────────────────────────────── */ 28 29 #loading { 30 display: flex; 31 flex-direction: column; 32 align-items: center; 33 justify-content: center; 34 padding: 60px 0; 35 gap: 16px; 36 } 37 38 .spinner { 39 width: 36px; 40 height: 36px; 41 border: 3px solid #333; 42 border-top-color: #6c63ff; 43 border-radius: 50%; 44 animation: spin 0.8s linear infinite; 45 } 46 47 @keyframes spin { to { transform: rotate(360deg); } } 48 49 #loading p { 50 font-size: 14px; 51 color: #8888aa; 52 } 53 54 /* ─── Error display ────────────────────────────────────────────── */ 55 56 #error { 57 display: none; 58 background: #3a1a1a; 59 border: 1px solid #6b2a2a; 60 border-radius: 8px; 61 padding: 16px; 62 color: #ff8888; 63 font-size: 14px; 64 line-height: 1.5; 65 } 66 67 #error h2 { 68 font-size: 13px; 69 font-weight: 600; 70 margin-bottom: 8px; 71 color: #ff6666; 72 } 73 74 /* ─── Result display ───────────────────────────────────────────── */ 75 76 #result { 77 display: none; 78 } 79 80 .section { 81 margin-bottom: 16px; 82 } 83 84 .section-label { 85 font-size: 11px; 86 font-weight: 600; 87 color: #6c63ff; 88 text-transform: uppercase; 89 letter-spacing: 0.5px; 90 margin-bottom: 8px; 91 display: inline; 92 } 93 94 .retry-icon { 95 display: none; 96 margin-left: 6px; 97 font-size: 13px; 98 cursor: pointer; 99 color: #6c63ff; 100 vertical-align: middle; 101 transition: color 0.15s, transform 0.15s; 102 } 103 104 .retry-icon:hover { 105 color: #aaffaa; 106 transform: rotate(90deg); 107 } 108 109 .retry-icon.show { 110 display: inline; 111 } 112 113 .latency { 114 display: none; 115 margin-left: 6px; 116 font-size: 10px; 117 color: #666; 118 font-family: monospace; 119 vertical-align: middle; 120 } 121 122 .latency.show { 123 display: inline; 124 } 125 126 .tokens { 127 display: none; 128 margin-left: 6px; 129 font-size: 10px; 130 color: #666; 131 font-family: monospace; 132 vertical-align: middle; 133 } 134 135 .tokens.show { 136 display: inline; 137 } 138 139 .section-error { 140 color: #ff8888; 141 font-size: 13px; 142 font-style: italic; 143 } 144 145 .section-content { 146 background: #16213e; 147 border: 1px solid #2a2a4a; 148 border-radius: 8px; 149 padding: 14px; 150 font-size: 14px; 151 line-height: 1.6; 152 white-space: pre-wrap; 153 word-break: break-word; 154 } 155 156 .section-content.original { 157 color: #aaaacc; 158 text-decoration: line-through; 159 text-decoration-color: #665566; 160 } 161 162 .section-content.corrected { 163 color: #aaffaa; 164 border-color: #2a4a2a; 165 cursor: pointer; 166 transition: border-color 0.2s, background 0.2s; 167 } 168 169 .section-content.corrected.copied { 170 border-color: #4caf50; 171 background: #1a2e1a; 172 } 173 174 .section-content.suggested { 175 color: #aaddff; 176 border-color: #2a3a5a; 177 cursor: pointer; 178 transition: border-color 0.2s, background 0.2s; 179 } 180 181 .section-content.suggested.copied { 182 border-color: #4caf50; 183 background: #1a2e2a; 184 } 185 186 /* ─── Streaming indicator (bouncing dots) ──────────────────────── */ 187 188 .streaming-indicator { 189 display: inline-flex; 190 align-items: center; 191 gap: 4px; 192 padding: 4px 0; 193 } 194 195 .streaming-indicator.hidden { 196 display: none; 197 } 198 199 .streaming-indicator span { 200 display: inline-block; 201 width: 6px; 202 height: 6px; 203 border-radius: 50%; 204 background: #6c63ff; 205 animation: bounce 1.2s ease-in-out infinite; 206 } 207 208 .streaming-indicator span:nth-child(2) { 209 animation-delay: 0.15s; 210 } 211 212 .streaming-indicator span:nth-child(3) { 213 animation-delay: 0.3s; 214 } 215 216 @keyframes bounce { 217 0%, 60%, 100% { transform: translateY(0); opacity: 0.4; } 218 30% { transform: translateY(-6px); opacity: 1; } 219 } 220 221 /* ─── Settings bar ─────────────────────────────────────────────── */ 222 223 .settings-bar { 224 display: flex; 225 align-items: center; 226 gap: 8px; 227 padding: 8px 12px; 228 background: #16213e; 229 border: 1px solid #2a2a4a; 230 border-radius: 8px; 231 margin-bottom: 16px; 232 } 233 234 .settings-bar label { 235 font-size: 11px; 236 font-weight: 600; 237 color: #6c63ff; 238 text-transform: uppercase; 239 letter-spacing: 0.5px; 240 white-space: nowrap; 241 } 242 243 .settings-bar input { 244 flex: 1; 245 background: #1a1a2e; 246 border: 1px solid #2a2a4a; 247 border-radius: 4px; 248 padding: 4px 8px; 249 color: #e0e0e0; 250 font-size: 12px; 251 font-family: monospace; 252 outline: none; 253 transition: border-color 0.15s; 254 } 255 256 .settings-bar input:focus { 257 border-color: #6c63ff; 258 } 259 260 .checkmark { 261 opacity: 0; 262 visibility: hidden; 263 color: #4caf50; 264 font-size: 16px; 265 font-weight: 700; 266 transition: opacity 0.2s, visibility 0.2s; 267 } 268 269 .checkmark.show { 270 opacity: 1; 271 visibility: visible; 272 } 273 274 .health-dot { 275 display: none; 276 width: 8px; 277 height: 8px; 278 border-radius: 50%; 279 vertical-align: middle; 280 } 281 282 .health-dot.ok { 283 display: inline-block; 284 background: #4caf50; 285 } 286 287 .health-dot.fail { 288 display: inline-block; 289 background: #ff5555; 290 } 291 292 .lang-toggle { 293 display: flex; 294 margin-left: auto; 295 border: 1px solid #2a2a4a; 296 border-radius: 4px; 297 overflow: hidden; 298 } 299 300 .lang-btn { 301 background: #1a1a2e; 302 border: none; 303 padding: 3px 8px; 304 font-size: 11px; 305 font-weight: 600; 306 color: #888; 307 cursor: pointer; 308 transition: background 0.15s, color 0.15s; 309 } 310 311 .lang-btn + .lang-btn { 312 border-left: 1px solid #2a2a4a; 313 } 314 315 .lang-btn.active { 316 background: #6c63ff; 317 color: #fff; 318 } 319 320 .lang-btn:hover:not(.active) { 321 background: #2a2a4a; 322 color: #ccc; 323 } 324 </style> 325</head> 326<body> 327 <div class="settings-bar"> 328 <label for="api-url">API</label> 329 <input type="text" id="api-url" placeholder="http://localhost:8080" spellcheck="false"> 330 <span id="api-saved" class="checkmark">&#10003;</span> 331 <span id="health-dot" class="health-dot"></span> 332 <div class="lang-toggle"> 333 <button id="lang-en" class="lang-btn active" type="button">EN</button> 334 <button id="lang-fr" class="lang-btn" type="button">FR</button> 335 </div> 336 </div> 337 <div id="loading"> 338 <div class="spinner"></div> 339 <p>Correcting text...</p> 340 </div> 341 342 <div id="error"> 343 <h2>Error</h2> 344 <p id="error-message"></p> 345 </div> 346 347 <div id="result"> 348 <div class="section"> 349 <div class="section-label">Original</div> 350 <div class="section-content original" id="original-text"></div> 351 </div> 352 <div class="section"> 353 <div class="section-header"> 354 <span class="section-label">Corrected</span> 355 <span class="retry-icon" id="retry-corrected">&#8635;</span> 356 <span class="latency" id="latency-corrected"></span> 357 <span class="tokens" id="tokens-corrected"></span> 358 </div> 359 <div class="section-content corrected" id="corrected-text"> 360 <div id="corrected-indicator" class="streaming-indicator hidden"> 361 <span></span><span></span><span></span> 362 </div> 363 </div> 364 </div> 365 <div class="section"> 366 <div class="section-header"> 367 <span class="section-label">Suggested</span> 368 <span class="retry-icon" id="retry-suggested">&#8635;</span> 369 <span class="latency" id="latency-suggested"></span> 370 <span class="tokens" id="tokens-suggested"></span> 371 </div> 372 <div class="section-content suggested" id="suggested-text"> 373 <div id="suggested-indicator" class="streaming-indicator hidden"> 374 <span></span><span></span><span></span> 375 </div> 376 </div> 377 </div> 378 </div> 379 380 <script src="result.js"></script> 381</body> 382</html>