A browser extension that lets you summarize any webpage and ask questions using AI.
1
fork

Configure Feed

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

Add YouTube video unsupported warning

- Add isYoutubeUrl() function to detect YouTube video URLs
- Add showYoutubeError() function to display error message
- Add CSS styles for YouTube error styling
- Display warning when user is on a YouTube video page

+658 -488
+603 -483
popup/popup.css
··· 1 1 * { 2 - margin: 0; 3 - padding: 0; 4 - box-sizing: border-box; 2 + margin: 0; 3 + padding: 0; 4 + box-sizing: border-box; 5 5 } 6 6 7 7 /* ── CSS variables – Light (default) ── */ 8 8 :root { 9 - --bg: #f5f0e8; 10 - --bg-subtle: #ede8de; 11 - --border: #e0d8cc; 12 - --border-hover: #c8c0b4; 13 - --text: #1a1a1a; 14 - --text-secondary:#2a2a2a; 15 - --text-muted: #aaa; 16 - --text-faint: #ccc; 17 - --text-em: #666; 18 - --icon-btn: #aaa; 19 - --icon-btn-hover:#555; 20 - --primary-bg: #1a1a1a; 21 - --primary-bg-hover:#333; 22 - --primary-bg-active:#000; 23 - --primary-text: #f5f0e8; 24 - --secondary-color:#aaa; 25 - --scrollbar: #d8d0c4; 26 - --spinner-track: #e0d8cc; 27 - --spinner-head: #888; 28 - --error-bg: #fdf0f0; 29 - --error-border: #f0d8d8; 30 - --error-text: #c05050; 31 - --toast-bg: #1a1a1a; 32 - --toast-text: #f5f0e8; 33 - --code-bg: #ede8de; 34 - --code-text: #555; 35 - --pre-text: #444; 36 - --table-th: #ede8de; 37 - --link: #555; 38 - --link-hover: #111; 39 - --heading: #111; 40 - --strong: #111; 41 - --blockquote: #888; 42 - --brand: #F15B2F; 43 - --brand-hover: #D94E27; 44 - --brand-active: #BF4522; 9 + --bg: #f5f0e8; 10 + --bg-subtle: #ede8de; 11 + --border: #e0d8cc; 12 + --border-hover: #c8c0b4; 13 + --text: #1a1a1a; 14 + --text-secondary: #2a2a2a; 15 + --text-muted: #aaa; 16 + --text-faint: #ccc; 17 + --text-em: #666; 18 + --icon-btn: #aaa; 19 + --icon-btn-hover: #555; 20 + --primary-bg: #1a1a1a; 21 + --primary-bg-hover: #333; 22 + --primary-bg-active: #000; 23 + --primary-text: #f5f0e8; 24 + --secondary-color: #aaa; 25 + --scrollbar: #d8d0c4; 26 + --spinner-track: #e0d8cc; 27 + --spinner-head: #888; 28 + --error-bg: #fdf0f0; 29 + --error-border: #f0d8d8; 30 + --error-text: #c05050; 31 + --toast-bg: #1a1a1a; 32 + --toast-text: #f5f0e8; 33 + --code-bg: #ede8de; 34 + --code-text: #555; 35 + --pre-text: #444; 36 + --table-th: #ede8de; 37 + --link: #555; 38 + --link-hover: #111; 39 + --heading: #111; 40 + --strong: #111; 41 + --blockquote: #888; 42 + --brand: #f15b2f; 43 + --brand-hover: #d94e27; 44 + --brand-active: #bf4522; 45 45 } 46 46 47 47 /* ── Dark theme ── */ 48 48 [data-theme="dark"] { 49 - --bg: #1a1a1a; 50 - --bg-subtle: #252525; 51 - --border: #2e2e2e; 52 - --border-hover: #444; 53 - --text: #e8e3db; 54 - --text-secondary:#d0cbc3; 55 - --text-muted: #666; 56 - --text-faint: #444; 57 - --text-em: #999; 58 - --icon-btn: #555; 59 - --icon-btn-hover:#bbb; 60 - --primary-bg: #e8e3db; 61 - --primary-bg-hover:#ccc8c0; 62 - --primary-bg-active:#fff; 63 - --primary-text: #1a1a1a; 64 - --secondary-color:#555; 65 - --scrollbar: #333; 66 - --spinner-track: #2e2e2e; 67 - --spinner-head: #888; 68 - --error-bg: #2a1a1a; 69 - --error-border: #4a2a2a; 70 - --error-text: #e08080; 71 - --toast-bg: #e8e3db; 72 - --toast-text: #1a1a1a; 73 - --code-bg: #252525; 74 - --code-text: #aaa; 75 - --pre-text: #bbb; 76 - --table-th: #252525; 77 - --link: #aaa; 78 - --link-hover: #e8e3db; 79 - --heading: #e8e3db; 80 - --strong: #e8e3db; 81 - --blockquote: #666; 82 - --brand: #F15B2F; 83 - --brand-hover: #D94E27; 84 - --brand-active: #BF4522; 49 + --bg: #1a1a1a; 50 + --bg-subtle: #252525; 51 + --border: #2e2e2e; 52 + --border-hover: #444; 53 + --text: #e8e3db; 54 + --text-secondary: #d0cbc3; 55 + --text-muted: #666; 56 + --text-faint: #444; 57 + --text-em: #999; 58 + --icon-btn: #555; 59 + --icon-btn-hover: #bbb; 60 + --primary-bg: #e8e3db; 61 + --primary-bg-hover: #ccc8c0; 62 + --primary-bg-active: #fff; 63 + --primary-text: #1a1a1a; 64 + --secondary-color: #555; 65 + --scrollbar: #333; 66 + --spinner-track: #2e2e2e; 67 + --spinner-head: #888; 68 + --error-bg: #2a1a1a; 69 + --error-border: #4a2a2a; 70 + --error-text: #e08080; 71 + --toast-bg: #e8e3db; 72 + --toast-text: #1a1a1a; 73 + --code-bg: #252525; 74 + --code-text: #aaa; 75 + --pre-text: #bbb; 76 + --table-th: #252525; 77 + --link: #aaa; 78 + --link-hover: #e8e3db; 79 + --heading: #e8e3db; 80 + --strong: #e8e3db; 81 + --blockquote: #666; 82 + --brand: #f15b2f; 83 + --brand-hover: #d94e27; 84 + --brand-active: #bf4522; 85 85 } 86 86 87 87 body { 88 - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; 89 - width: 400px; 90 - height: 560px; 91 - background: var(--bg); 92 - color: var(--text); 93 - overflow: hidden; 94 - transition: background 0.15s, color 0.15s; 88 + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; 89 + width: 400px; 90 + height: 560px; 91 + background: var(--bg); 92 + color: var(--text); 93 + overflow: hidden; 94 + transition: 95 + background 0.15s, 96 + color 0.15s; 95 97 } 96 98 97 99 .app { 98 - display: flex; 99 - flex-direction: column; 100 - height: 100%; 100 + display: flex; 101 + flex-direction: column; 102 + height: 100%; 101 103 } 102 104 103 105 /* ── Header ── */ 104 106 .header { 105 - display: flex; 106 - justify-content: space-between; 107 - align-items: center; 108 - padding: 13px 18px; 109 - border-bottom: 1px solid var(--border); 110 - flex-shrink: 0; 107 + display: flex; 108 + justify-content: space-between; 109 + align-items: center; 110 + padding: 13px 18px; 111 + border-bottom: 1px solid var(--border); 112 + flex-shrink: 0; 111 113 } 112 114 113 115 .header-left { 114 - display: flex; 115 - align-items: center; 116 - gap: 7px; 116 + display: flex; 117 + align-items: center; 118 + gap: 7px; 117 119 } 118 120 119 121 .header-right { 120 - display: flex; 121 - align-items: center; 122 - gap: 2px; 122 + display: flex; 123 + align-items: center; 124 + gap: 2px; 123 125 } 124 126 125 127 .logo-mark { 126 - width: 13px; 127 - height: 13px; 128 - display: inline-flex; 129 - align-items: center; 130 - justify-content: center; 128 + width: 13px; 129 + height: 13px; 130 + display: inline-flex; 131 + align-items: center; 132 + justify-content: center; 131 133 } 132 134 133 135 .logo-mark .brand-icon { 134 - width: 100%; 135 - height: 100%; 136 - display: block; 137 - background: var(--brand); 138 - -webkit-mask: url("../lightning.svg") center / contain no-repeat; 139 - mask: url("../lightning.svg") center / contain no-repeat; 136 + width: 100%; 137 + height: 100%; 138 + display: block; 139 + background: var(--brand); 140 + -webkit-mask: url("../lightning.svg") center / contain no-repeat; 141 + mask: url("../lightning.svg") center / contain no-repeat; 140 142 } 141 143 142 144 .logo-text { 143 - font-size: 13px; 144 - font-weight: 600; 145 - color: var(--text); 146 - letter-spacing: 0.01em; 145 + font-size: 13px; 146 + font-weight: 600; 147 + color: var(--text); 148 + letter-spacing: 0.01em; 147 149 } 148 150 149 151 .icon-btn { 150 - background: transparent; 151 - border: none; 152 - cursor: pointer; 153 - color: var(--icon-btn); 154 - width: 28px; 155 - height: 28px; 156 - display: flex; 157 - align-items: center; 158 - justify-content: center; 159 - border-radius: 6px; 160 - transition: color 0.1s; 161 - flex-shrink: 0; 152 + background: transparent; 153 + border: none; 154 + cursor: pointer; 155 + color: var(--icon-btn); 156 + width: 28px; 157 + height: 28px; 158 + display: flex; 159 + align-items: center; 160 + justify-content: center; 161 + border-radius: 6px; 162 + transition: color 0.1s; 163 + flex-shrink: 0; 162 164 } 163 165 164 166 .icon-btn:hover { 165 - color: var(--icon-btn-hover); 167 + color: var(--icon-btn-hover); 166 168 } 167 169 168 170 /* ── Content area ── */ 169 171 .content-container { 170 - flex: 1; 171 - overflow-y: auto; 172 - padding: 18px; 173 - scrollbar-width: thin; 174 - scrollbar-color: var(--scrollbar) transparent; 172 + flex: 1; 173 + overflow-y: auto; 174 + padding: 18px; 175 + scrollbar-width: thin; 176 + scrollbar-color: var(--scrollbar) transparent; 175 177 } 176 178 177 - .content-container::-webkit-scrollbar { width: 3px; } 178 - .content-container::-webkit-scrollbar-track { background: transparent; } 179 - .content-container::-webkit-scrollbar-thumb { background: var(--scrollbar); border-radius: 3px; } 179 + .content-container::-webkit-scrollbar { 180 + width: 3px; 181 + } 182 + .content-container::-webkit-scrollbar-track { 183 + background: transparent; 184 + } 185 + .content-container::-webkit-scrollbar-thumb { 186 + background: var(--scrollbar); 187 + border-radius: 3px; 188 + } 180 189 181 190 /* ── Initial state ── */ 182 191 .initial-state { 183 - display: flex; 184 - flex-direction: column; 185 - align-items: flex-start; 186 - justify-content: flex-end; 187 - height: 100%; 188 - padding-bottom: 4px; 189 - gap: 5px; 192 + display: flex; 193 + flex-direction: column; 194 + align-items: flex-start; 195 + justify-content: flex-end; 196 + height: 100%; 197 + padding-bottom: 4px; 198 + gap: 5px; 190 199 } 191 200 192 - .initial-state.hidden { display: none; } 201 + .initial-state.hidden { 202 + display: none; 203 + } 193 204 194 205 .initial-icon { 195 - width: 18px; 196 - height: 18px; 197 - margin-bottom: 4px; 206 + width: 18px; 207 + height: 18px; 208 + margin-bottom: 4px; 198 209 } 199 210 200 211 .initial-icon .brand-icon { 201 - width: 100%; 202 - height: 100%; 203 - display: block; 204 - background: var(--brand); 205 - -webkit-mask: url("../lightning.svg") center / contain no-repeat; 206 - mask: url("../lightning.svg") center / contain no-repeat; 212 + width: 100%; 213 + height: 100%; 214 + display: block; 215 + background: var(--brand); 216 + -webkit-mask: url("../lightning.svg") center / contain no-repeat; 217 + mask: url("../lightning.svg") center / contain no-repeat; 207 218 } 208 219 209 220 .initial-title { 210 - font-size: 15px; 211 - font-weight: 600; 212 - color: var(--text); 221 + font-size: 15px; 222 + font-weight: 600; 223 + color: var(--text); 213 224 } 214 225 215 226 .initial-sub { 216 - font-size: 12px; 217 - color: var(--text-muted); 218 - line-height: 1.5; 227 + font-size: 12px; 228 + color: var(--text-muted); 229 + line-height: 1.5; 219 230 } 220 231 221 232 /* ── Loading ── */ 222 233 .loading-wrap { 223 - display: flex; 224 - flex-direction: column; 225 - align-items: center; 226 - justify-content: center; 227 - height: 100%; 228 - gap: 12px; 234 + display: flex; 235 + flex-direction: column; 236 + align-items: center; 237 + justify-content: center; 238 + height: 100%; 239 + gap: 12px; 229 240 } 230 241 231 242 .spinner { 232 - width: 18px; 233 - height: 18px; 234 - border: 1.5px solid var(--spinner-track); 235 - border-top-color: var(--spinner-head); 236 - border-radius: 50%; 237 - animation: spin 0.75s linear infinite; 243 + width: 18px; 244 + height: 18px; 245 + border: 1.5px solid var(--spinner-track); 246 + border-top-color: var(--spinner-head); 247 + border-radius: 50%; 248 + animation: spin 0.75s linear infinite; 238 249 } 239 250 240 - @keyframes spin { to { transform: rotate(360deg); } } 251 + @keyframes spin { 252 + to { 253 + transform: rotate(360deg); 254 + } 255 + } 241 256 242 257 .loading-label { 243 - font-size: 11px; 244 - color: var(--text-muted); 245 - letter-spacing: 0.05em; 246 - text-transform: uppercase; 258 + font-size: 11px; 259 + color: var(--text-muted); 260 + letter-spacing: 0.05em; 261 + text-transform: uppercase; 247 262 } 248 263 249 264 /* ── Result ── */ 250 265 .result { 251 - font-size: 14px; 252 - line-height: 1.7; 253 - color: var(--text-secondary); 254 - animation: fadeUp 0.2s ease; 266 + font-size: 14px; 267 + line-height: 1.7; 268 + color: var(--text-secondary); 269 + animation: fadeUp 0.2s ease; 255 270 } 256 271 257 - .result.hidden { display: none; } 272 + .result.hidden { 273 + display: none; 274 + } 258 275 259 276 /* ── Truncation Warning ── */ 260 277 .truncation-warning { 261 - display: flex; 262 - align-items: center; 263 - gap: 8px; 264 - padding: 10px 12px; 265 - margin-bottom: 16px; 266 - background: var(--bg-subtle); 267 - border: 1px solid var(--border); 268 - border-radius: 6px; 269 - font-size: 12px; 270 - color: var(--text-muted); 278 + display: flex; 279 + align-items: center; 280 + gap: 8px; 281 + padding: 10px 12px; 282 + margin-bottom: 16px; 283 + background: var(--bg-subtle); 284 + border: 1px solid var(--border); 285 + border-radius: 6px; 286 + font-size: 12px; 287 + color: var(--text-muted); 271 288 } 272 289 273 290 .truncation-warning svg { 274 - flex-shrink: 0; 275 - color: var(--text-muted); 291 + flex-shrink: 0; 292 + color: var(--text-muted); 276 293 } 277 294 278 295 @keyframes fadeUp { 279 - from { opacity: 0; transform: translateY(3px); } 280 - to { opacity: 1; transform: translateY(0); } 296 + from { 297 + opacity: 0; 298 + transform: translateY(3px); 299 + } 300 + to { 301 + opacity: 1; 302 + transform: translateY(0); 303 + } 281 304 } 282 305 283 306 /* ── Markdown ── */ 284 307 .result > * + * { 285 - margin-top: 10px; 308 + margin-top: 10px; 286 309 } 287 310 288 311 .result > *:first-child { 289 - margin-top: 0; 312 + margin-top: 0; 290 313 } 291 314 292 315 .result h1, ··· 295 318 .result h4, 296 319 .result h5, 297 320 .result h6 { 298 - font-weight: 600; 299 - color: var(--heading); 300 - line-height: 1.3; 321 + font-weight: 600; 322 + color: var(--heading); 323 + line-height: 1.3; 301 324 } 302 325 303 - .result h1 { font-size: 16px; margin-top: 16px; } 304 - .result h2 { font-size: 14px; margin-top: 14px; } 305 - .result h3 { font-size: 13px; margin-top: 12px; } 306 - .result h4, .result h5, .result h6 { font-size: 13px; color: var(--text-muted); margin-top: 10px; } 326 + .result h1 { 327 + font-size: 16px; 328 + margin-top: 16px; 329 + } 330 + .result h2 { 331 + font-size: 14px; 332 + margin-top: 14px; 333 + } 334 + .result h3 { 335 + font-size: 13px; 336 + margin-top: 12px; 337 + } 338 + .result h4, 339 + .result h5, 340 + .result h6 { 341 + font-size: 13px; 342 + color: var(--text-muted); 343 + margin-top: 10px; 344 + } 307 345 308 - .result p { line-height: 1.65; } 309 - .result p + p { margin-top: 6px; } 346 + .result p { 347 + line-height: 1.65; 348 + } 349 + .result p + p { 350 + margin-top: 6px; 351 + } 310 352 311 - .result ul, .result ol { 312 - padding-left: 18px; 353 + .result ul, 354 + .result ol { 355 + padding-left: 18px; 313 356 } 314 357 315 - .result li { line-height: 1.6; } 316 - .result li + li { margin-top: 2px; } 317 - .result li::marker { color: var(--text-faint); } 358 + .result li { 359 + line-height: 1.6; 360 + } 361 + .result li + li { 362 + margin-top: 2px; 363 + } 364 + .result li::marker { 365 + color: var(--text-faint); 366 + } 318 367 319 - .result strong { font-weight: 600; color: var(--strong); } 320 - .result em { font-style: italic; color: var(--text-em); } 368 + .result strong { 369 + font-weight: 600; 370 + color: var(--strong); 371 + } 372 + .result em { 373 + font-style: italic; 374 + color: var(--text-em); 375 + } 321 376 322 377 .result code { 323 - font-family: 'SF Mono', 'Cascadia Code', monospace; 324 - font-size: 11.5px; 325 - background: var(--code-bg); 326 - padding: 1px 5px; 327 - border-radius: 3px; 328 - color: var(--code-text); 378 + font-family: "SF Mono", "Cascadia Code", monospace; 379 + font-size: 11.5px; 380 + background: var(--code-bg); 381 + padding: 1px 5px; 382 + border-radius: 3px; 383 + color: var(--code-text); 329 384 } 330 385 331 386 .result pre { 332 - background: var(--code-bg); 333 - padding: 10px 12px; 334 - border-radius: 5px; 335 - overflow-x: auto; 387 + background: var(--code-bg); 388 + padding: 10px 12px; 389 + border-radius: 5px; 390 + overflow-x: auto; 336 391 } 337 392 338 393 .result pre code { 339 - background: transparent; 340 - padding: 0; 341 - color: var(--pre-text); 394 + background: transparent; 395 + padding: 0; 396 + color: var(--pre-text); 342 397 } 343 398 344 399 .result blockquote { 345 - border-left: 2px solid var(--border); 346 - padding: 2px 12px; 347 - color: var(--blockquote); 348 - font-style: italic; 400 + border-left: 2px solid var(--border); 401 + padding: 2px 12px; 402 + color: var(--blockquote); 403 + font-style: italic; 349 404 } 350 405 351 406 .result blockquote + blockquote { 352 - margin-top: 6px; 407 + margin-top: 6px; 353 408 } 354 409 355 - .result a { color: var(--link); text-decoration: underline; } 356 - .result a:hover { color: var(--brand); } 410 + .result a { 411 + color: var(--link); 412 + text-decoration: underline; 413 + } 414 + .result a:hover { 415 + color: var(--brand); 416 + } 357 417 358 418 .result hr { 359 - border: none; 360 - border-top: 1px solid var(--border); 419 + border: none; 420 + border-top: 1px solid var(--border); 361 421 } 362 422 363 423 .result table { 364 - border-collapse: collapse; 365 - width: 100%; 366 - font-size: 12.5px; 424 + border-collapse: collapse; 425 + width: 100%; 426 + font-size: 12.5px; 367 427 } 368 428 369 - .result th, .result td { 370 - border: 1px solid var(--border); 371 - padding: 5px 9px; 372 - text-align: left; 429 + .result th, 430 + .result td { 431 + border: 1px solid var(--border); 432 + padding: 5px 9px; 433 + text-align: left; 373 434 } 374 435 375 436 .result th { 376 - background: var(--table-th); 377 - font-weight: 600; 437 + background: var(--table-th); 438 + font-weight: 600; 378 439 } 379 440 380 441 /* Streaming content - match .result styling for consistency */ 381 442 .streaming-content { 382 - font-size: 14px; 383 - line-height: 1.7; 384 - color: var(--text-secondary); 443 + font-size: 14px; 444 + line-height: 1.7; 445 + color: var(--text-secondary); 385 446 } 386 447 387 448 .streaming-content > * + * { 388 - margin-top: 10px; 449 + margin-top: 10px; 389 450 } 390 451 391 452 .streaming-content > *:first-child { 392 - margin-top: 0; 453 + margin-top: 0; 393 454 } 394 455 395 456 /* Loading placeholder before first token */ 396 457 .streaming-placeholder { 397 - display: flex; 398 - align-items: center; 399 - gap: 4px; 400 - padding: 4px 0; 458 + display: flex; 459 + align-items: center; 460 + gap: 4px; 461 + padding: 4px 0; 401 462 } 402 463 403 464 .streaming-placeholder .pulse-dot { 404 - width: 6px; 405 - height: 6px; 406 - background: var(--text-muted); 407 - border-radius: 50%; 408 - animation: pulse-dot 1.4s ease-in-out infinite; 465 + width: 6px; 466 + height: 6px; 467 + background: var(--text-muted); 468 + border-radius: 50%; 469 + animation: pulse-dot 1.4s ease-in-out infinite; 409 470 } 410 471 411 472 .streaming-placeholder .pulse-dot:nth-child(2) { 412 - animation-delay: 0.2s; 473 + animation-delay: 0.2s; 413 474 } 414 475 415 476 .streaming-placeholder .pulse-dot:nth-child(3) { 416 - animation-delay: 0.4s; 477 + animation-delay: 0.4s; 417 478 } 418 479 419 480 @keyframes pulse-dot { 420 - 0%, 80%, 100% { 421 - transform: scale(0.6); 422 - opacity: 0.4; 423 - } 424 - 40% { 425 - transform: scale(1); 426 - opacity: 1; 427 - } 481 + 0%, 482 + 80%, 483 + 100% { 484 + transform: scale(0.6); 485 + opacity: 0.4; 486 + } 487 + 40% { 488 + transform: scale(1); 489 + opacity: 1; 490 + } 428 491 } 429 492 430 493 /* ── Footer ── */ 431 494 .footer { 432 - display: flex; 433 - padding: 11px 18px; 434 - border-top: 1px solid var(--border); 435 - flex-shrink: 0; 436 - align-items: center; 495 + display: flex; 496 + padding: 11px 18px; 497 + border-top: 1px solid var(--border); 498 + flex-shrink: 0; 499 + align-items: center; 437 500 } 438 501 439 502 .footer-btn { 440 - display: flex; 441 - align-items: center; 442 - justify-content: center; 443 - padding: 8px 16px; 444 - border-radius: 6px; 445 - font-family: inherit; 446 - font-size: 12.5px; 447 - font-weight: 500; 448 - cursor: pointer; 449 - transition: all 0.1s ease; 450 - border: none; 451 - flex: 1; 452 - background: var(--primary-bg); 453 - color: var(--primary-text); 503 + display: flex; 504 + align-items: center; 505 + justify-content: center; 506 + padding: 8px 16px; 507 + border-radius: 6px; 508 + font-family: inherit; 509 + font-size: 12.5px; 510 + font-weight: 500; 511 + cursor: pointer; 512 + transition: all 0.1s ease; 513 + border: none; 514 + flex: 1; 515 + background: var(--primary-bg); 516 + color: var(--primary-text); 454 517 } 455 518 456 - .footer-btn:hover { background: var(--primary-bg-hover); } 457 - .footer-btn:active { background: var(--primary-bg-active); } 519 + .footer-btn:hover { 520 + background: var(--primary-bg-hover); 521 + } 522 + .footer-btn:active { 523 + background: var(--primary-bg-active); 524 + } 458 525 .footer-btn:disabled { 459 - opacity: 0.35; 460 - cursor: not-allowed; 526 + opacity: 0.35; 527 + cursor: not-allowed; 461 528 } 462 529 463 530 .footer-btn.primary { 464 - background: var(--brand); 465 - color: #fff; 531 + background: var(--brand); 532 + color: #fff; 466 533 } 467 534 468 535 .footer-btn.primary:hover { 469 - background: var(--brand-hover); 536 + background: var(--brand-hover); 470 537 } 471 538 472 539 .footer-btn.primary:active { 473 - background: var(--brand-active); 540 + background: var(--brand-active); 474 541 } 475 542 476 543 .hidden { 477 - display: none !important; 544 + display: none !important; 478 545 } 479 546 480 547 /* ── Error ── */ 481 548 .error-message { 482 - background: var(--error-bg); 483 - border: 1px solid var(--error-border); 484 - color: var(--error-text); 485 - padding: 11px 14px; 486 - border-radius: 6px; 487 - font-size: 12px; 488 - line-height: 1.5; 549 + background: var(--error-bg); 550 + border: 1px solid var(--error-border); 551 + color: var(--error-text); 552 + padding: 11px 14px; 553 + border-radius: 6px; 554 + font-size: 12px; 555 + line-height: 1.5; 489 556 } 490 557 491 558 /* ── PDF Error ── */ 492 559 .pdf-error { 493 - display: flex; 494 - flex-direction: column; 495 - align-items: center; 496 - justify-content: center; 497 - height: 100%; 498 - text-align: center; 499 - padding: 40px 20px; 500 - gap: 12px; 560 + display: flex; 561 + flex-direction: column; 562 + align-items: center; 563 + justify-content: center; 564 + height: 100%; 565 + text-align: center; 566 + padding: 40px 20px; 567 + gap: 12px; 501 568 } 502 569 503 570 .pdf-error-icon { 504 - font-size: 48px; 505 - font-weight: 300; 506 - color: var(--text-muted); 507 - margin-bottom: 8px; 508 - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; 571 + font-size: 48px; 572 + font-weight: 300; 573 + color: var(--text-muted); 574 + margin-bottom: 8px; 575 + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; 509 576 } 510 577 511 578 .pdf-error-title { 512 - font-size: 16px; 513 - font-weight: 600; 514 - color: var(--text); 579 + font-size: 16px; 580 + font-weight: 600; 581 + color: var(--text); 515 582 } 516 583 517 584 .pdf-error-message { 518 - font-size: 13px; 519 - color: var(--text-muted); 520 - line-height: 1.6; 521 - max-width: 280px; 585 + font-size: 13px; 586 + color: var(--text-muted); 587 + line-height: 1.6; 588 + max-width: 280px; 589 + } 590 + 591 + /* ── YouTube Error ── */ 592 + .youtube-error { 593 + display: flex; 594 + flex-direction: column; 595 + align-items: center; 596 + justify-content: center; 597 + height: 100%; 598 + text-align: center; 599 + padding: 40px 20px; 600 + gap: 12px; 601 + } 602 + 603 + .youtube-error-icon { 604 + font-size: 48px; 605 + font-weight: 300; 606 + color: var(--text-muted); 607 + margin-bottom: 8px; 608 + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; 609 + } 610 + 611 + .youtube-error-title { 612 + font-size: 16px; 613 + font-weight: 600; 614 + color: var(--text); 615 + } 616 + 617 + .youtube-error-message { 618 + font-size: 13px; 619 + color: var(--text-muted); 620 + line-height: 1.6; 621 + max-width: 280px; 522 622 } 523 623 524 624 /* ── Toast ── */ 525 625 .toast { 526 - position: fixed; 527 - bottom: 68px; 528 - left: 50%; 529 - transform: translateX(-50%); 530 - background: var(--toast-bg); 531 - color: var(--toast-text); 532 - padding: 6px 14px; 533 - border-radius: 20px; 534 - font-size: 11px; 535 - z-index: 100; 536 - white-space: nowrap; 537 - animation: toast-in 0.15s ease; 626 + position: fixed; 627 + bottom: 68px; 628 + left: 50%; 629 + transform: translateX(-50%); 630 + background: var(--toast-bg); 631 + color: var(--toast-text); 632 + padding: 6px 14px; 633 + border-radius: 20px; 634 + font-size: 11px; 635 + z-index: 100; 636 + white-space: nowrap; 637 + animation: toast-in 0.15s ease; 538 638 } 539 639 540 640 @keyframes toast-in { 541 - from { opacity: 0; transform: translateX(-50%) translateY(4px); } 542 - to { opacity: 1; transform: translateX(-50%) translateY(0); } 641 + from { 642 + opacity: 0; 643 + transform: translateX(-50%) translateY(4px); 644 + } 645 + to { 646 + opacity: 1; 647 + transform: translateX(-50%) translateY(0); 648 + } 543 649 } 544 650 545 651 /* ── Chat ── */ 546 652 .chat-container { 547 - padding: 12px 18px; 548 - border-top: 1px solid var(--border); 549 - flex-shrink: 0; 653 + padding: 12px 18px; 654 + border-top: 1px solid var(--border); 655 + flex-shrink: 0; 550 656 } 551 657 552 658 .chat-container.hidden { 553 - display: none; 659 + display: none; 554 660 } 555 661 556 662 /* Chat suggestions */ 557 663 .chat-suggestions { 558 - display: flex; 559 - flex-wrap: wrap; 560 - gap: 6px; 561 - margin-bottom: 10px; 664 + display: flex; 665 + flex-wrap: wrap; 666 + gap: 6px; 667 + margin-bottom: 10px; 562 668 } 563 669 564 670 .suggestion-btn { 565 - padding: 5px 10px; 566 - border-radius: 14px; 567 - border: 1px solid var(--border); 568 - background: var(--bg-subtle); 569 - color: var(--text-muted); 570 - font-family: inherit; 571 - font-size: 11px; 572 - cursor: pointer; 573 - transition: all 0.1s; 574 - white-space: nowrap; 671 + padding: 5px 10px; 672 + border-radius: 14px; 673 + border: 1px solid var(--border); 674 + background: var(--bg-subtle); 675 + color: var(--text-muted); 676 + font-family: inherit; 677 + font-size: 11px; 678 + cursor: pointer; 679 + transition: all 0.1s; 680 + white-space: nowrap; 575 681 } 576 682 577 683 .suggestion-btn:hover { 578 - border-color: var(--brand); 579 - color: var(--brand); 580 - background: var(--bg); 684 + border-color: var(--brand); 685 + color: var(--brand); 686 + background: var(--bg); 581 687 } 582 688 583 689 /* Suggestion skeleton placeholder */ 584 690 .suggestion-skeleton { 585 - padding: 5px 10px; 586 - border-radius: 14px; 587 - border: 1px solid var(--border); 588 - background: var(--bg-subtle); 589 - width: 120px; 590 - height: 24px; 591 - animation: skeleton-pulse 1.5s ease-in-out infinite; 691 + padding: 5px 10px; 692 + border-radius: 14px; 693 + border: 1px solid var(--border); 694 + background: var(--bg-subtle); 695 + width: 120px; 696 + height: 24px; 697 + animation: skeleton-pulse 1.5s ease-in-out infinite; 592 698 } 593 699 594 700 @keyframes skeleton-pulse { 595 - 0%, 100% { opacity: 0.4; } 596 - 50% { opacity: 0.7; } 701 + 0%, 702 + 100% { 703 + opacity: 0.4; 704 + } 705 + 50% { 706 + opacity: 0.7; 707 + } 597 708 } 598 709 599 710 /* Chat messages are rendered inside .result, sharing the same scroll */ 600 711 .chat-divider { 601 - margin: 20px 0 16px 0; 602 - border: none; 603 - border-top: 1px solid var(--border); 712 + margin: 20px 0 16px 0; 713 + border: none; 714 + border-top: 1px solid var(--border); 604 715 } 605 716 606 717 .chat-message { 607 - animation: fadeUp 0.2s ease; 718 + animation: fadeUp 0.2s ease; 608 719 } 609 720 610 721 .chat-message + .chat-message { 611 - margin-top: 14px; 722 + margin-top: 14px; 612 723 } 613 724 614 725 /* User messages as bubbles */ 615 726 .chat-message.user { 616 - background: var(--primary-bg); 617 - color: var(--primary-text); 618 - padding: 10px 14px; 619 - border-radius: 12px; 620 - border-bottom-right-radius: 4px; 621 - font-size: 13px; 622 - line-height: 1.5; 623 - max-width: 85%; 624 - margin-left: auto; 727 + background: var(--primary-bg); 728 + color: var(--primary-text); 729 + padding: 10px 14px; 730 + border-radius: 12px; 731 + border-bottom-right-radius: 4px; 732 + font-size: 13px; 733 + line-height: 1.5; 734 + max-width: 85%; 735 + margin-left: auto; 625 736 } 626 737 627 738 /* Assistant messages styled like summary content */ 628 739 .chat-message.assistant { 629 - font-size: 14px; 630 - line-height: 1.7; 631 - color: var(--text-secondary); 740 + font-size: 14px; 741 + line-height: 1.7; 742 + color: var(--text-secondary); 632 743 } 633 744 634 745 .chat-message.assistant.loading { 635 - display: flex; 636 - align-items: center; 637 - justify-content: center; 638 - padding: 20px 0; 746 + display: flex; 747 + align-items: center; 748 + justify-content: center; 749 + padding: 20px 0; 639 750 } 640 751 641 752 .chat-message.assistant.error { 642 - background: var(--error-bg); 643 - border: 1px solid var(--error-border); 644 - color: var(--error-text); 645 - padding: 10px 14px; 646 - border-radius: 6px; 753 + background: var(--error-bg); 754 + border: 1px solid var(--error-border); 755 + color: var(--error-text); 756 + padding: 10px 14px; 757 + border-radius: 6px; 647 758 } 648 759 649 760 .chat-spinner { 650 - width: 18px; 651 - height: 18px; 652 - border: 1.5px solid var(--spinner-track); 653 - border-top-color: var(--spinner-head); 654 - border-radius: 50%; 655 - animation: spin 0.75s linear infinite; 761 + width: 18px; 762 + height: 18px; 763 + border: 1.5px solid var(--spinner-track); 764 + border-top-color: var(--spinner-head); 765 + border-radius: 50%; 766 + animation: spin 0.75s linear infinite; 656 767 } 657 768 658 769 /* Chat message markdown (assistant uses same styles as .result) */ 659 770 .chat-message.assistant > * + * { 660 - margin-top: 10px; 771 + margin-top: 10px; 661 772 } 662 773 663 774 .chat-message.assistant h1, ··· 666 777 .chat-message.assistant h4, 667 778 .chat-message.assistant h5, 668 779 .chat-message.assistant h6 { 669 - font-weight: 600; 670 - color: var(--heading); 671 - line-height: 1.3; 780 + font-weight: 600; 781 + color: var(--heading); 782 + line-height: 1.3; 672 783 } 673 784 674 - .chat-message.assistant h1 { font-size: 16px; margin-top: 16px; } 675 - .chat-message.assistant h2 { font-size: 14px; margin-top: 14px; } 676 - .chat-message.assistant h3 { font-size: 13px; margin-top: 12px; } 785 + .chat-message.assistant h1 { 786 + font-size: 16px; 787 + margin-top: 16px; 788 + } 789 + .chat-message.assistant h2 { 790 + font-size: 14px; 791 + margin-top: 14px; 792 + } 793 + .chat-message.assistant h3 { 794 + font-size: 13px; 795 + margin-top: 12px; 796 + } 677 797 678 798 .chat-message.assistant p { 679 - line-height: 1.65; 799 + line-height: 1.65; 680 800 } 681 801 682 802 .chat-message.assistant p + p { 683 - margin-top: 6px; 803 + margin-top: 6px; 684 804 } 685 805 686 806 .chat-message.assistant ul, 687 807 .chat-message.assistant ol { 688 - padding-left: 18px; 808 + padding-left: 18px; 689 809 } 690 810 691 811 .chat-message.assistant li { 692 - line-height: 1.6; 812 + line-height: 1.6; 693 813 } 694 814 695 815 .chat-message.assistant li + li { 696 - margin-top: 2px; 816 + margin-top: 2px; 697 817 } 698 818 699 819 .chat-message.assistant strong { 700 - font-weight: 600; 701 - color: var(--strong); 820 + font-weight: 600; 821 + color: var(--strong); 702 822 } 703 823 704 824 .chat-message.assistant code { 705 - font-family: 'SF Mono', 'Cascadia Code', monospace; 706 - font-size: 11.5px; 707 - background: var(--code-bg); 708 - padding: 1px 5px; 709 - border-radius: 3px; 710 - color: var(--code-text); 825 + font-family: "SF Mono", "Cascadia Code", monospace; 826 + font-size: 11.5px; 827 + background: var(--code-bg); 828 + padding: 1px 5px; 829 + border-radius: 3px; 830 + color: var(--code-text); 711 831 } 712 832 713 833 .chat-message.assistant pre { 714 - background: var(--code-bg); 715 - padding: 10px 12px; 716 - border-radius: 5px; 717 - overflow-x: auto; 834 + background: var(--code-bg); 835 + padding: 10px 12px; 836 + border-radius: 5px; 837 + overflow-x: auto; 718 838 } 719 839 720 840 .chat-message.assistant pre code { 721 - background: transparent; 722 - padding: 0; 723 - color: var(--pre-text); 841 + background: transparent; 842 + padding: 0; 843 + color: var(--pre-text); 724 844 } 725 845 726 846 .chat-message.assistant blockquote { 727 - border-left: 2px solid var(--border); 728 - padding: 2px 12px; 729 - color: var(--blockquote); 730 - font-style: italic; 847 + border-left: 2px solid var(--border); 848 + padding: 2px 12px; 849 + color: var(--blockquote); 850 + font-style: italic; 731 851 } 732 852 733 853 .chat-message.assistant a { 734 - color: var(--link); 735 - text-decoration: underline; 854 + color: var(--link); 855 + text-decoration: underline; 736 856 } 737 857 738 858 .chat-message.assistant a:hover { 739 - color: var(--brand); 859 + color: var(--brand); 740 860 } 741 861 742 862 /* User message markdown */ 743 863 .chat-message.user p { 744 - margin: 0; 864 + margin: 0; 745 865 } 746 866 747 867 .chat-message.user p + p { 748 - margin-top: 4px; 868 + margin-top: 4px; 749 869 } 750 870 751 871 .chat-message.user strong { 752 - font-weight: 600; 872 + font-weight: 600; 753 873 } 754 874 755 875 .chat-input-wrap { 756 - display: flex; 757 - gap: 8px; 758 - align-items: center; 876 + display: flex; 877 + gap: 8px; 878 + align-items: center; 759 879 } 760 880 761 881 .chat-input { 762 - flex: 1; 763 - padding: 8px 12px; 764 - border: 1px solid var(--border); 765 - border-radius: 6px; 766 - background: var(--bg); 767 - color: var(--text); 768 - font-family: inherit; 769 - font-size: 13px; 770 - outline: none; 771 - transition: border-color 0.1s; 882 + flex: 1; 883 + padding: 8px 12px; 884 + border: 1px solid var(--border); 885 + border-radius: 6px; 886 + background: var(--bg); 887 + color: var(--text); 888 + font-family: inherit; 889 + font-size: 13px; 890 + outline: none; 891 + transition: border-color 0.1s; 772 892 } 773 893 774 894 .chat-input:focus { 775 - border-color: var(--brand); 895 + border-color: var(--brand); 776 896 } 777 897 778 898 .chat-input::placeholder { 779 - color: var(--text-muted); 899 + color: var(--text-muted); 780 900 } 781 901 782 902 .chat-send-btn { 783 - width: 32px; 784 - height: 32px; 785 - border-radius: 6px; 786 - border: none; 787 - background: var(--brand); 788 - color: #fff; 789 - cursor: pointer; 790 - display: flex; 791 - align-items: center; 792 - justify-content: center; 793 - transition: all 0.1s; 794 - flex-shrink: 0; 903 + width: 32px; 904 + height: 32px; 905 + border-radius: 6px; 906 + border: none; 907 + background: var(--brand); 908 + color: #fff; 909 + cursor: pointer; 910 + display: flex; 911 + align-items: center; 912 + justify-content: center; 913 + transition: all 0.1s; 914 + flex-shrink: 0; 795 915 } 796 916 797 917 .chat-send-btn:hover { 798 - background: var(--brand-hover); 918 + background: var(--brand-hover); 799 919 } 800 920 801 921 .chat-send-btn:disabled { 802 - opacity: 0.35; 803 - cursor: not-allowed; 922 + opacity: 0.35; 923 + cursor: not-allowed; 804 924 } 805 925 806 926 /* Summary action buttons container */ 807 927 .summary-actions { 808 - display: flex; 809 - gap: 8px; 810 - margin-top: 16px; 928 + display: flex; 929 + gap: 8px; 930 + margin-top: 16px; 811 931 } 812 932 813 933 /* Copy/regenerate button under summary */ 814 934 .copy-summary-btn { 815 - display: inline-flex; 816 - align-items: center; 817 - gap: 6px; 818 - padding: 6px 12px; 819 - border-radius: 6px; 820 - border: 1px solid var(--border); 821 - background: transparent; 822 - color: var(--text-muted); 823 - font-family: inherit; 824 - font-size: 12px; 825 - font-weight: 500; 826 - cursor: pointer; 827 - transition: all 0.1s; 935 + display: inline-flex; 936 + align-items: center; 937 + gap: 6px; 938 + padding: 6px 12px; 939 + border-radius: 6px; 940 + border: 1px solid var(--border); 941 + background: transparent; 942 + color: var(--text-muted); 943 + font-family: inherit; 944 + font-size: 12px; 945 + font-weight: 500; 946 + cursor: pointer; 947 + transition: all 0.1s; 828 948 } 829 949 830 950 .copy-summary-btn:hover { 831 - border-color: var(--border-hover); 832 - color: var(--text); 951 + border-color: var(--border-hover); 952 + color: var(--text); 833 953 } 834 954 835 955 .copy-summary-btn.copied { 836 - color: var(--text); 837 - border-color: var(--border-hover); 956 + color: var(--text); 957 + border-color: var(--border-hover); 838 958 }
+55 -5
popup/popup.js
··· 320 320 return; 321 321 } 322 322 323 + // Check if this is a YouTube video 324 + if (isYoutubeUrl(currentTabUrl)) { 325 + showYoutubeError(); 326 + return; 327 + } 328 + 323 329 // Check for cached summary for this tab 324 330 const cached = await chrome.storage.session.get([ 325 331 QUICK_SUMMARY_CACHE_PREFIX + currentTabId, ··· 341 347 setSummarizeLabel("Loading..."); 342 348 343 349 // Check auto-summarize setting 344 - const { autoSummarize } = await chrome.storage.sync.get({ autoSummarize: API_SETTINGS_DEFAULTS.autoSummarize }); 350 + const { autoSummarize } = await chrome.storage.sync.get({ 351 + autoSummarize: API_SETTINGS_DEFAULTS.autoSummarize, 352 + }); 345 353 346 354 // If we have cached content for this tab, restore it 347 355 if (cachedContent && cachedContent.url === currentTabUrl) { ··· 384 392 } else { 385 393 // No summaries yet - check if we should auto-summarize 386 394 setSummarizeLabel("Quick Summary"); 387 - if ((autoSummarize || shouldAutoSummarize) && !isLoading && !isExtracting && currentPageContent) { 395 + if ( 396 + (autoSummarize || shouldAutoSummarize) && 397 + !isLoading && 398 + !isExtracting && 399 + currentPageContent 400 + ) { 388 401 await generateQuickSummary(); 389 402 } 390 403 } ··· 396 409 setSummarizeLabel("Quick Summary"); 397 410 398 411 // Check if we should auto-trigger summarize (from keyboard shortcut, context menu, or auto-summarize setting) 399 - if ((autoSummarize || shouldAutoSummarize) && !isLoading && !isExtracting && currentPageContent) { 412 + if ( 413 + (autoSummarize || shouldAutoSummarize) && 414 + !isLoading && 415 + !isExtracting && 416 + currentPageContent 417 + ) { 400 418 await generateQuickSummary(); 401 419 } 402 420 } ··· 1278 1296 // Check for .pdf extension or PDF in the URL path 1279 1297 const urlObj = new URL(url); 1280 1298 const pathname = urlObj.pathname.toLowerCase(); 1281 - return pathname.endsWith('.pdf') || pathname.includes('.pdf?'); 1299 + return pathname.endsWith(".pdf") || pathname.includes(".pdf?"); 1300 + } 1301 + 1302 + function isYoutubeUrl(url) { 1303 + if (!url) return false; 1304 + // Check for YouTube video URLs (youtube.com/watch or youtu.be/short) 1305 + const urlObj = new URL(url); 1306 + const hostname = urlObj.hostname.toLowerCase(); 1307 + const pathname = urlObj.pathname.toLowerCase(); 1308 + // Match youtube.com/watch?v= or youtu.be/VIDEO_ID 1309 + return ( 1310 + ((hostname === "www.youtube.com" || hostname === "youtube.com") && 1311 + pathname === "/watch") || 1312 + hostname === "youtu.be" 1313 + ); 1282 1314 } 1283 1315 1284 1316 function showPdfError() { ··· 1293 1325 <div class="pdf-error-icon">:(</div> 1294 1326 <div class="pdf-error-title">PDF files aren't supported</div> 1295 1327 <div class="pdf-error-message"> 1296 - This extension can't extract text from PDFs. 1328 + This extension can't extract text from PDFs. 1297 1329 To summarize this document, download the file and upload it to a tool like ChatGPT. 1298 1330 </div> 1299 1331 </div> 1300 1332 `; 1301 1333 } 1334 + 1335 + function showYoutubeError() { 1336 + // Hide initial state and show error 1337 + initialState.classList.add("hidden"); 1338 + resultContainer.classList.remove("hidden"); 1339 + footer.classList.add("hidden"); 1340 + chatContainer.classList.add("hidden"); 1341 + 1342 + resultContainer.innerHTML = ` 1343 + <div class="youtube-error"> 1344 + <div class="youtube-error-icon">:(</div> 1345 + <div class="youtube-error-title">YouTube videos aren't supported</div> 1346 + <div class="youtube-error-message"> 1347 + This extension can't extract text from YouTube videos at the moment. 1348 + </div> 1349 + </div> 1350 + `; 1351 + }