| 1 | <html> |
| 2 | |
| 3 | <head> |
| 4 | <title>Email Integration</title> |
| 5 | <script type="module"> |
| 6 | import { store } from "/plugins/_email_integration/webui/email-config-store.js"; |
| 7 | </script> |
| 8 | </head> |
| 9 | |
| 10 | <body> |
| 11 | <div x-data x-init="$store.emailConfig.init(config, context)" x-destroy="$store.emailConfig.cleanup()"> |
| 12 | <template x-if="config"> |
| 13 | <div class="email-settings"> |
| 14 | <div class="section-title">Email</div> |
| 15 | |
| 16 | <template x-if="$store.emailConfig.didInit && $store.emailConfig.handlers.length === 0"> |
| 17 | <div class="email-empty"> |
| 18 | <div class="email-empty-title">Connect Agent Zero and your email account</div> |
| 19 | <div class="email-empty-copy"> |
| 20 | Most people only need a provider, an email address, and an app password. |
| 21 | </div> |
| 22 | <button class="btn btn-field" @click="$store.emailConfig.addHandler()"> |
| 23 | Connect |
| 24 | </button> |
| 25 | </div> |
| 26 | </template> |
| 27 | |
| 28 | <template x-for="(handler, idx) in $store.emailConfig.handlers" :key="idx"> |
| 29 | <div class="email-card"> |
| 30 | <div class="email-card-header" @click="$store.emailConfig.toggleEditing(idx)"> |
| 31 | <div class="email-card-heading"> |
| 32 | <div class="email-card-title" x-text="$store.emailConfig.handlerTitle(handler, idx)"> |
| 33 | </div> |
| 34 | <div class="email-card-subtitle" x-text="$store.emailConfig.handlerSubtitle(handler)"> |
| 35 | </div> |
| 36 | </div> |
| 37 | <div class="email-card-actions"> |
| 38 | <span class="email-status-pill" |
| 39 | :class="'tone-' + $store.emailConfig.statusTone(handler)" |
| 40 | x-text="$store.emailConfig.statusLabel(handler)"></span> |
| 41 | <button class="btn btn-action delete" |
| 42 | @click.stop="$confirmClick($event, () => $store.emailConfig.removeHandler(idx))" |
| 43 | title="Remove inbox"> |
| 44 | <x-icon name="delete"></x-icon> |
| 45 | </button> |
| 46 | <x-icon class="email-card-chevron" |
| 47 | :class="{ 'is-open': $store.emailConfig.editing === idx }" name="expand_more"></x-icon> |
| 48 | </div> |
| 49 | </div> |
| 50 | |
| 51 | <template x-if="$store.emailConfig.editing === idx"> |
| 52 | <div class="email-card-body"> |
| 53 | <div class="email-provider-panel" |
| 54 | :class="{ 'has-provider': $store.emailConfig.hasProvider(handler) }"> |
| 55 | <div class="email-provider-topline"> |
| 56 | <div class="email-provider-copy"> |
| 57 | <div class="email-provider-title" |
| 58 | x-text="$store.emailConfig.hasProvider(handler) ? $store.emailConfig.providerLabel($store.emailConfig.providerValue(handler)) : 'Choose your email provider'"> |
| 59 | </div> |
| 60 | <div class="email-provider-description" |
| 61 | x-text="$store.emailConfig.hasProvider(handler) ? $store.emailConfig.providerHint(handler) : 'Pick a provider and Agent Zero will prepare the usual incoming and outgoing mail settings.'"> |
| 62 | </div> |
| 63 | <template x-if="$store.emailConfig.providerHelpUrl(handler)"> |
| 64 | <a class="email-intro-link" |
| 65 | :href="$store.emailConfig.providerHelpUrl(handler)" |
| 66 | target="_blank" |
| 67 | rel="noopener" |
| 68 | x-text="$store.emailConfig.providerHelpLabel(handler)"></a> |
| 69 | </template> |
| 70 | </div> |
| 71 | <template x-if="$store.emailConfig.hasProvider(handler)"> |
| 72 | <button type="button" class="btn btn-field email-change-provider" |
| 73 | @click.stop="$store.emailConfig.changeProvider(idx)" |
| 74 | x-text="$store.emailConfig.showProviderChoices(handler, idx) ? 'Done' : 'Change'"> |
| 75 | </button> |
| 76 | </template> |
| 77 | </div> |
| 78 | |
| 79 | <div class="email-provider-grid" |
| 80 | x-show="$store.emailConfig.showProviderChoices(handler, idx)"> |
| 81 | <template x-for="provider in $store.emailConfig.providerOptions" |
| 82 | :key="provider.value"> |
| 83 | <button type="button" class="email-provider-option" |
| 84 | :class="($store.emailConfig.providerValue(handler) === provider.value ? 'is-selected ' : '') + 'logo-' + provider.logo" |
| 85 | :aria-pressed="$store.emailConfig.providerValue(handler) === provider.value ? 'true' : 'false'" |
| 86 | :title="provider.label" |
| 87 | @click.stop="$store.emailConfig.selectProvider(handler, provider.value, idx)"> |
| 88 | <span class="email-provider-logo" aria-hidden="true"> |
| 89 | <template x-if="provider.logo === 'microsoft365'"> |
| 90 | <span class="email-microsoft-mark"> |
| 91 | <span></span> |
| 92 | <span></span> |
| 93 | <span></span> |
| 94 | <span></span> |
| 95 | </span> |
| 96 | </template> |
| 97 | <template |
| 98 | x-if="provider.logo !== 'microsoft365' && (provider.logo === 'icloud' || provider.logo === 'custom-imap')"> |
| 99 | <x-icon |
| 100 | :name="provider.logoText"></x-icon> |
| 101 | </template> |
| 102 | <template |
| 103 | x-if="provider.logo !== 'microsoft365' && provider.logo !== 'icloud' && provider.logo !== 'custom-imap'"> |
| 104 | <span x-text="provider.logoText"></span> |
| 105 | </template> |
| 106 | </span> |
| 107 | <span class="email-provider-name" x-text="provider.label"></span> |
| 108 | <span class="email-provider-hint" x-text="provider.hint"></span> |
| 109 | </button> |
| 110 | </template> |
| 111 | </div> |
| 112 | </div> |
| 113 | |
| 114 | <div class="email-post-provider" x-show="$store.emailConfig.hasProvider(handler)"> |
| 115 | <div class="field"> |
| 116 | <div class="field-label"> |
| 117 | <div class="field-title">Turn on this inbox</div> |
| 118 | <div class="field-description">Enable when you are ready for Agent Zero to |
| 119 | start checking mail.</div> |
| 120 | </div> |
| 121 | <div class="field-control"> |
| 122 | <label class="toggle"> |
| 123 | <input type="checkbox" x-model="handler.enabled" /> |
| 124 | <span class="toggler"></span> |
| 125 | </label> |
| 126 | </div> |
| 127 | </div> |
| 128 | |
| 129 | <div class="field"> |
| 130 | <div class="field-label"> |
| 131 | <div class="field-title">Email address</div> |
| 132 | <div class="field-description">Usually the full address for this inbox.</div> |
| 133 | </div> |
| 134 | <div class="field-control"> |
| 135 | <input type="text" x-model="handler.username" |
| 136 | @input="$store.emailConfig.maybeAutoname(handler)" |
| 137 | placeholder="name@company.com" /> |
| 138 | </div> |
| 139 | </div> |
| 140 | |
| 141 | <div class="field"> |
| 142 | <div class="field-label"> |
| 143 | <div class="field-title">Password</div> |
| 144 | <div class="field-description">An app password is best. Many mail providers |
| 145 | block regular account passwords.</div> |
| 146 | </div> |
| 147 | <div class="field-control"> |
| 148 | <input type="password" x-model="handler.password" /> |
| 149 | </div> |
| 150 | </div> |
| 151 | |
| 152 | <template x-if="$store.emailConfig.showExchangeServer(handler)"> |
| 153 | <div> |
| 154 | <div class="field"> |
| 155 | <div class="field-label"> |
| 156 | <div class="field-title" |
| 157 | x-text="$store.emailConfig.incomingLabel(handler)"></div> |
| 158 | <div class="field-description" |
| 159 | x-text="$store.emailConfig.incomingDescription(handler)"></div> |
| 160 | </div> |
| 161 | <div class="field-control"> |
| 162 | <input type="text" x-model="handler.imap_server" |
| 163 | :placeholder="$store.emailConfig.incomingPlaceholder(handler)" /> |
| 164 | </div> |
| 165 | </div> |
| 166 | </div> |
| 167 | </template> |
| 168 | |
| 169 | <template x-if="$store.emailConfig.showManualServers(handler)"> |
| 170 | <div class="email-grid"> |
| 171 | <div class="field"> |
| 172 | <div class="field-label"> |
| 173 | <div class="field-title">Incoming mail server</div> |
| 174 | <div class="field-description">The IMAP server for this inbox.</div> |
| 175 | </div> |
| 176 | <div class="field-control"> |
| 177 | <input type="text" x-model="handler.imap_server" |
| 178 | placeholder="imap.your-provider.com" /> |
| 179 | </div> |
| 180 | </div> |
| 181 | |
| 182 | <div class="field"> |
| 183 | <div class="field-label"> |
| 184 | <div class="field-title">Incoming port</div> |
| 185 | <div class="field-description">993 is the usual SSL port.</div> |
| 186 | </div> |
| 187 | <div class="field-control"> |
| 188 | <input type="number" x-model.number="handler.imap_port" |
| 189 | placeholder="993" /> |
| 190 | </div> |
| 191 | </div> |
| 192 | |
| 193 | <div class="field"> |
| 194 | <div class="field-label"> |
| 195 | <div class="field-title">Outgoing mail server</div> |
| 196 | <div class="field-description">The SMTP server used for replies. |
| 197 | </div> |
| 198 | </div> |
| 199 | <div class="field-control"> |
| 200 | <input type="text" x-model="handler.smtp_server" |
| 201 | placeholder="smtp.your-provider.com" /> |
| 202 | </div> |
| 203 | </div> |
| 204 | |
| 205 | <div class="field"> |
| 206 | <div class="field-label"> |
| 207 | <div class="field-title">Outgoing port</div> |
| 208 | <div class="field-description">587 is the usual TLS port.</div> |
| 209 | </div> |
| 210 | <div class="field-control"> |
| 211 | <input type="number" x-model.number="handler.smtp_port" |
| 212 | placeholder="587" /> |
| 213 | </div> |
| 214 | </div> |
| 215 | </div> |
| 216 | </template> |
| 217 | |
| 218 | <template |
| 219 | x-if="!$store.emailConfig.showManualServers(handler) && !$store.emailConfig.showExchangeServer(handler) && $store.emailConfig.providerValue(handler)"> |
| 220 | <div class="email-note"> |
| 221 | Server settings are filled in for <span |
| 222 | x-text="$store.emailConfig.providerLabel($store.emailConfig.providerValue(handler))"></span>. |
| 223 | You can change them any time in Advanced. |
| 224 | </div> |
| 225 | </template> |
| 226 | |
| 227 | <div class="email-missing" |
| 228 | x-show="$store.emailConfig.missingBits(handler).length > 0"> |
| 229 | Still needed: |
| 230 | <span x-text="$store.emailConfig.missingBits(handler).join(', ')"></span> |
| 231 | </div> |
| 232 | |
| 233 | <div class="field"> |
| 234 | <div class="field-label"> |
| 235 | <div class="field-title">Routing instructions</div> |
| 236 | <div class="field-description">Extra guidance for how incoming email should be |
| 237 | routed into chats.</div> |
| 238 | </div> |
| 239 | <div class="field-control"> |
| 240 | <textarea x-model="handler.dispatcher_instructions" rows="3" |
| 241 | placeholder="Always start a new chat for invoices or billing questions."></textarea> |
| 242 | </div> |
| 243 | </div> |
| 244 | |
| 245 | <div class="field"> |
| 246 | <div class="field-label"> |
| 247 | <div class="field-title">Reply instructions</div> |
| 248 | <div class="field-description">Extra guidance for the agent when it replies by |
| 249 | email.</div> |
| 250 | </div> |
| 251 | <div class="field-control"> |
| 252 | <textarea x-model="handler.agent_instructions" rows="3" |
| 253 | placeholder="Reply in a calm, concise tone."></textarea> |
| 254 | </div> |
| 255 | </div> |
| 256 | |
| 257 | <div class="email-test-panel"> |
| 258 | <div class="email-test-copy"> |
| 259 | <div class="email-test-title">Check the connection</div> |
| 260 | <div class="email-test-description" |
| 261 | x-text="$store.emailConfig.testIntro(handler)"></div> |
| 262 | </div> |
| 263 | <button class="btn btn-field" @click.stop="$store.emailConfig.testConnection(idx)" |
| 264 | :disabled="$store.emailConfig.testing === idx || !$store.emailConfig.canTest(handler)"> |
| 265 | <span x-text="$store.emailConfig.testButtonLabel(handler, idx)"></span> |
| 266 | </button> |
| 267 | </div> |
| 268 | |
| 269 | <template |
| 270 | x-if="$store.emailConfig.testResults && $store.emailConfig.testResultsFor === idx"> |
| 271 | <div class="email-results" |
| 272 | :class="{ 'is-error': !$store.emailConfig.testResults.success }"> |
| 273 | <template x-for="result in $store.emailConfig.testResults.results" |
| 274 | :key="result.test + result.message"> |
| 275 | <div class="email-result-row"> |
| 276 | <span class="email-result-icon" x-text="result.ok ? '✓' : '✗'"></span> |
| 277 | <div class="email-result-copy"> |
| 278 | <div class="email-result-title" |
| 279 | x-text="$store.emailConfig.resultTitle(result)"></div> |
| 280 | <div class="email-result-message" |
| 281 | x-text="$store.emailConfig.resultMessage(result)"></div> |
| 282 | </div> |
| 283 | </div> |
| 284 | </template> |
| 285 | </div> |
| 286 | </template> |
| 287 | </div> |
| 288 | |
| 289 | <details class="email-advanced" x-show="$store.emailConfig.hasProvider(handler)"> |
| 290 | <summary> |
| 291 | <span>Advanced</span> |
| 292 | <x-icon class="email-advanced-chevron" |
| 293 | aria-hidden="true" name="keyboard_arrow_down"></x-icon> |
| 294 | </summary> |
| 295 | <div class="email-advanced-body"> |
| 296 | <div class="field"> |
| 297 | <div class="field-label"> |
| 298 | <div class="field-title">Inbox name</div> |
| 299 | <div class="field-description">A friendly internal label for this |
| 300 | connection.</div> |
| 301 | </div> |
| 302 | <div class="field-control"> |
| 303 | <input type="text" x-model="handler.name" placeholder="support" /> |
| 304 | </div> |
| 305 | </div> |
| 306 | |
| 307 | <div class="email-grid"> |
| 308 | <div class="field"> |
| 309 | <div class="field-label"> |
| 310 | <div class="field-title">Incoming mail server</div> |
| 311 | <div class="field-description">Override the auto-filled incoming |
| 312 | server if needed.</div> |
| 313 | </div> |
| 314 | <div class="field-control"> |
| 315 | <input type="text" x-model="handler.imap_server" |
| 316 | placeholder="imap.your-provider.com" /> |
| 317 | </div> |
| 318 | </div> |
| 319 | |
| 320 | <div class="field"> |
| 321 | <div class="field-label"> |
| 322 | <div class="field-title">Incoming port</div> |
| 323 | <div class="field-description">993 is the common SSL port.</div> |
| 324 | </div> |
| 325 | <div class="field-control"> |
| 326 | <input type="number" x-model.number="handler.imap_port" |
| 327 | placeholder="993" /> |
| 328 | </div> |
| 329 | </div> |
| 330 | |
| 331 | <div class="field"> |
| 332 | <div class="field-label"> |
| 333 | <div class="field-title">Outgoing mail server</div> |
| 334 | <div class="field-description">Override the auto-filled reply server |
| 335 | if needed.</div> |
| 336 | </div> |
| 337 | <div class="field-control"> |
| 338 | <input type="text" x-model="handler.smtp_server" |
| 339 | placeholder="smtp.your-provider.com" /> |
| 340 | </div> |
| 341 | </div> |
| 342 | |
| 343 | <div class="field"> |
| 344 | <div class="field-label"> |
| 345 | <div class="field-title">Outgoing port</div> |
| 346 | <div class="field-description">587 is the common TLS port.</div> |
| 347 | </div> |
| 348 | <div class="field-control"> |
| 349 | <input type="number" x-model.number="handler.smtp_port" |
| 350 | placeholder="587" /> |
| 351 | </div> |
| 352 | </div> |
| 353 | </div> |
| 354 | |
| 355 | <div class="field"> |
| 356 | <div class="field-label"> |
| 357 | <div class="field-title">Project</div> |
| 358 | <div class="field-description">Open email conversations inside a |
| 359 | specific project.</div> |
| 360 | </div> |
| 361 | <div class="field-control"> |
| 362 | <select :value="handler.project" |
| 363 | @change="handler.project = $event.target.value"> |
| 364 | <option value="">No project</option> |
| 365 | <template x-for="proj in $store.emailConfig.projects" |
| 366 | :key="proj.name"> |
| 367 | <option :value="proj.name" x-text="proj.title || proj.name" |
| 368 | :selected="handler.project === proj.name"></option> |
| 369 | </template> |
| 370 | </select> |
| 371 | </div> |
| 372 | </div> |
| 373 | |
| 374 | <div class="field"> |
| 375 | <div class="field-label"> |
| 376 | <div class="field-title">Allowed senders</div> |
| 377 | <div class="field-description">Leave empty to allow anyone. Wildcards |
| 378 | like *@company.com work.</div> |
| 379 | </div> |
| 380 | <div class="field-control"> |
| 381 | <input type="text" :value="$store.emailConfig.whitelistText(handler)" |
| 382 | @input="$store.emailConfig.setWhitelist(handler, $event.target.value)" |
| 383 | placeholder="*@company.com, founder@company.com" /> |
| 384 | </div> |
| 385 | </div> |
| 386 | |
| 387 | <div class="field"> |
| 388 | <div class="field-label"> |
| 389 | <div class="field-title">Catch up on unread mail</div> |
| 390 | <div class="field-description">On startup, process unread mail from the |
| 391 | last N days. Use 0 for brand-new mail only.</div> |
| 392 | </div> |
| 393 | <div class="field-control"> |
| 394 | <input type="number" x-model.number="handler.process_unread_days" |
| 395 | min="0" placeholder="0" /> |
| 396 | </div> |
| 397 | </div> |
| 398 | |
| 399 | <div class="field"> |
| 400 | <div class="field-label"> |
| 401 | <div class="field-title">Check for new mail</div> |
| 402 | <div class="field-description" |
| 403 | x-text="$store.emailConfig.frequencyHint(handler)"></div> |
| 404 | </div> |
| 405 | <div class="field-control"> |
| 406 | <select :value="$store.emailConfig.frequencyValue(handler)" |
| 407 | @change="$store.emailConfig.applyFrequency(handler, $event.target.value)"> |
| 408 | <option value="15">Every 15 seconds</option> |
| 409 | <option value="30">Every 30 seconds</option> |
| 410 | <option value="60">Every minute</option> |
| 411 | <option value="300">Every 5 minutes</option> |
| 412 | <option value="900">Every 15 minutes</option> |
| 413 | <option value="custom">Custom schedule</option> |
| 414 | </select> |
| 415 | </div> |
| 416 | </div> |
| 417 | |
| 418 | <div class="field" |
| 419 | x-show="$store.emailConfig.frequencyValue(handler) === 'custom'"> |
| 420 | <div class="field-label"> |
| 421 | <div class="field-title">Scheduling mode</div> |
| 422 | <div class="field-description">Use seconds for a simple interval, or |
| 423 | switch to cron for full control.</div> |
| 424 | </div> |
| 425 | <div class="field-control"> |
| 426 | <select x-model="handler.poll_mode"> |
| 427 | <option value="seconds">Seconds</option> |
| 428 | <option value="cron">Cron</option> |
| 429 | </select> |
| 430 | </div> |
| 431 | </div> |
| 432 | |
| 433 | <div class="field" |
| 434 | x-show="$store.emailConfig.frequencyValue(handler) === 'custom' && handler.poll_mode === 'seconds'"> |
| 435 | <div class="field-label"> |
| 436 | <div class="field-title">Poll interval (seconds)</div> |
| 437 | <div class="field-description">The exact delay between inbox checks. |
| 438 | </div> |
| 439 | </div> |
| 440 | <div class="field-control"> |
| 441 | <input type="number" x-model.number="handler.poll_interval_seconds" |
| 442 | min="5" placeholder="60" /> |
| 443 | </div> |
| 444 | </div> |
| 445 | |
| 446 | <div class="field" |
| 447 | x-show="$store.emailConfig.frequencyValue(handler) === 'custom' && handler.poll_mode === 'cron'"> |
| 448 | <div class="field-label"> |
| 449 | <div class="field-title">Cron expression</div> |
| 450 | <div class="field-description">For example, */2 * * * * checks every two |
| 451 | minutes.</div> |
| 452 | </div> |
| 453 | <div class="field-control"> |
| 454 | <input type="text" x-model="handler.poll_interval_cron" |
| 455 | placeholder="*/2 * * * *" /> |
| 456 | </div> |
| 457 | </div> |
| 458 | |
| 459 | <div class="field"> |
| 460 | <div class="field-label"> |
| 461 | <div class="field-title">Routing model</div> |
| 462 | <div class="field-description">Utility is faster. Chat is more capable |
| 463 | when routing gets nuanced.</div> |
| 464 | </div> |
| 465 | <div class="field-control"> |
| 466 | <select x-model="handler.dispatcher_model"> |
| 467 | <option value="utility">Utility</option> |
| 468 | <option value="chat">Chat</option> |
| 469 | </select> |
| 470 | </div> |
| 471 | </div> |
| 472 | |
| 473 | <div class="field"> |
| 474 | <div class="field-label"> |
| 475 | <div class="field-title">Conversation config</div> |
| 476 | <div class="field-description">Optional model preset for new chats created from this inbox.</div> |
| 477 | </div> |
| 478 | <div class="field-control"> |
| 479 | <select x-model="handler.chat_model_preset"> |
| 480 | <option value="">Default</option> |
| 481 | <template x-for="preset in $store.emailConfig.modelPresets" :key="preset.name"> |
| 482 | <option :value="preset.name" x-text="preset.name"></option> |
| 483 | </template> |
| 484 | </select> |
| 485 | </div> |
| 486 | </div> |
| 487 | |
| 488 | </div> |
| 489 | </details> |
| 490 | </div> |
| 491 | </template> |
| 492 | </div> |
| 493 | </template> |
| 494 | |
| 495 | <template x-if="$store.emailConfig.handlers.length > 0"> |
| 496 | <button class="btn btn-field email-add-another" @click="$store.emailConfig.addHandler()"> |
| 497 | Connect another inbox |
| 498 | </button> |
| 499 | </template> |
| 500 | </div> |
| 501 | </template> |
| 502 | </div> |
| 503 | |
| 504 | <style> |
| 505 | .email-settings { |
| 506 | display: flex; |
| 507 | flex-direction: column; |
| 508 | gap: 0.9rem; |
| 509 | } |
| 510 | |
| 511 | .email-advanced summary { |
| 512 | cursor: pointer; |
| 513 | list-style: none; |
| 514 | font-weight: 700; |
| 515 | display: flex; |
| 516 | align-items: center; |
| 517 | gap: 0.75rem; |
| 518 | } |
| 519 | |
| 520 | .email-advanced summary::-webkit-details-marker { |
| 521 | display: none; |
| 522 | } |
| 523 | |
| 524 | .email-advanced summary { |
| 525 | padding: 0.95rem 1rem; |
| 526 | } |
| 527 | |
| 528 | .email-advanced-chevron { |
| 529 | margin-left: auto; |
| 530 | flex: 0 0 auto; |
| 531 | transition: transform 0.18s ease, opacity 0.18s ease; |
| 532 | opacity: 0.72; |
| 533 | } |
| 534 | |
| 535 | .email-advanced[open] .email-advanced-chevron { |
| 536 | transform: rotate(180deg); |
| 537 | opacity: 1; |
| 538 | } |
| 539 | |
| 540 | .email-guide-card { |
| 541 | border: 1px solid color-mix(in srgb, var(--color-border) 80%, white 20%); |
| 542 | border-radius: 12px; |
| 543 | padding: 0.9rem 1rem; |
| 544 | background: color-mix(in srgb, var(--color-background) 88%, white 12%); |
| 545 | } |
| 546 | |
| 547 | .email-guide-title { |
| 548 | font-weight: 700; |
| 549 | margin-bottom: 0.55rem; |
| 550 | } |
| 551 | |
| 552 | .email-guide-list { |
| 553 | margin: 0; |
| 554 | padding-left: 1.1rem; |
| 555 | color: var(--color-text-secondary); |
| 556 | line-height: 1.55; |
| 557 | } |
| 558 | |
| 559 | .email-empty { |
| 560 | border-radius: 0.5rem; |
| 561 | padding: 1rem; |
| 562 | background: color-mix(in srgb, var(--color-background) 94%, white 6%); |
| 563 | } |
| 564 | |
| 565 | .email-empty-title { |
| 566 | font-size: 1.05rem; |
| 567 | font-weight: 700; |
| 568 | } |
| 569 | |
| 570 | .email-empty-copy { |
| 571 | margin-top: 0.35rem; |
| 572 | margin-bottom: 0.9rem; |
| 573 | color: var(--color-text-secondary); |
| 574 | line-height: 1.5; |
| 575 | } |
| 576 | |
| 577 | .email-card { |
| 578 | border-radius: 0.5rem; |
| 579 | overflow: hidden; |
| 580 | } |
| 581 | |
| 582 | .email-card-header { |
| 583 | display: flex; |
| 584 | justify-content: space-between; |
| 585 | gap: 1rem; |
| 586 | align-items: flex-start; |
| 587 | padding: var(--spacing-sm) 0; |
| 588 | border-bottom: 1px solid var(--color-border); |
| 589 | cursor: pointer; |
| 590 | } |
| 591 | |
| 592 | .email-card-heading { |
| 593 | min-width: 0; |
| 594 | flex: 1 1 auto; |
| 595 | } |
| 596 | |
| 597 | .email-card-title { |
| 598 | font-weight: 700; |
| 599 | font-size: 1rem; |
| 600 | line-height: 1.35; |
| 601 | overflow-wrap: anywhere; |
| 602 | } |
| 603 | |
| 604 | .email-card-subtitle { |
| 605 | margin-top: 0.3rem; |
| 606 | color: var(--color-text-secondary); |
| 607 | font-size: var(--font-size-small); |
| 608 | line-height: 1.45; |
| 609 | } |
| 610 | |
| 611 | .email-card-actions { |
| 612 | display: flex; |
| 613 | align-items: center; |
| 614 | gap: 0.45rem; |
| 615 | flex: 0 0 auto; |
| 616 | } |
| 617 | |
| 618 | .email-card-chevron { |
| 619 | transition: transform 0.18s ease; |
| 620 | opacity: 0.7; |
| 621 | } |
| 622 | |
| 623 | .email-card-chevron.is-open { |
| 624 | transform: rotate(180deg); |
| 625 | } |
| 626 | |
| 627 | .email-provider-panel { |
| 628 | margin: 1rem 0; |
| 629 | padding: 0.95rem; |
| 630 | border: 1px solid color-mix(in srgb, var(--color-border) 86%, white 14%); |
| 631 | border-radius: 0.5rem; |
| 632 | background: color-mix(in srgb, var(--color-background) 92%, white 8%); |
| 633 | } |
| 634 | |
| 635 | .email-provider-panel.has-provider { |
| 636 | background: color-mix(in srgb, var(--color-background) 88%, white 12%); |
| 637 | } |
| 638 | |
| 639 | .email-provider-topline { |
| 640 | display: flex; |
| 641 | align-items: flex-start; |
| 642 | justify-content: space-between; |
| 643 | gap: 1rem; |
| 644 | } |
| 645 | |
| 646 | .email-provider-copy { |
| 647 | min-width: 0; |
| 648 | } |
| 649 | |
| 650 | .email-provider-title { |
| 651 | font-size: 1rem; |
| 652 | font-weight: 800; |
| 653 | line-height: 1.35; |
| 654 | } |
| 655 | |
| 656 | .email-provider-description { |
| 657 | margin-top: 0.35rem; |
| 658 | color: var(--color-text-secondary); |
| 659 | line-height: 1.5; |
| 660 | } |
| 661 | |
| 662 | .email-change-provider { |
| 663 | flex: 0 0 auto; |
| 664 | } |
| 665 | |
| 666 | .email-provider-grid { |
| 667 | display: grid; |
| 668 | grid-template-columns: repeat(3, minmax(0, 1fr)); |
| 669 | gap: 0.7rem; |
| 670 | margin-top: 0.95rem; |
| 671 | } |
| 672 | |
| 673 | .email-provider-option { |
| 674 | appearance: none; |
| 675 | width: 100%; |
| 676 | min-height: 5.5rem; |
| 677 | border: 1px solid color-mix(in srgb, var(--color-border) 84%, white 16%); |
| 678 | border-radius: 0.5rem; |
| 679 | padding: 0.8rem; |
| 680 | background: color-mix(in srgb, var(--color-background) 96%, white 4%); |
| 681 | color: var(--color-text); |
| 682 | display: grid; |
| 683 | grid-template-columns: auto minmax(0, 1fr); |
| 684 | grid-template-rows: auto auto; |
| 685 | align-items: center; |
| 686 | column-gap: 0.75rem; |
| 687 | row-gap: 0.15rem; |
| 688 | font: inherit; |
| 689 | text-align: left; |
| 690 | cursor: pointer; |
| 691 | transition: border-color 0.16s ease, background 0.16s ease, transform 0.16s ease; |
| 692 | } |
| 693 | |
| 694 | .email-provider-option:hover, |
| 695 | .email-provider-option:focus-visible { |
| 696 | border-color: color-mix(in srgb, var(--color-highlight) 58%, var(--color-border) 42%); |
| 697 | background: color-mix(in srgb, var(--color-background) 88%, white 12%); |
| 698 | transform: translateY(-1px); |
| 699 | outline: none; |
| 700 | } |
| 701 | |
| 702 | .email-provider-option.is-selected { |
| 703 | border-color: color-mix(in srgb, var(--color-highlight) 78%, white 22%); |
| 704 | background: color-mix(in srgb, var(--color-highlight) 10%, var(--color-background) 90%); |
| 705 | } |
| 706 | |
| 707 | .email-provider-logo { |
| 708 | grid-row: 1 / span 2; |
| 709 | width: 2.7rem; |
| 710 | height: 2.7rem; |
| 711 | border-radius: 0.5rem; |
| 712 | display: inline-flex; |
| 713 | align-items: center; |
| 714 | justify-content: center; |
| 715 | overflow: hidden; |
| 716 | font-size: 1.1rem; |
| 717 | font-weight: 900; |
| 718 | letter-spacing: 0; |
| 719 | } |
| 720 | |
| 721 | .email-provider-logo .material-symbols-outlined { |
| 722 | font-size: 1.45rem; |
| 723 | } |
| 724 | |
| 725 | .logo-gmail .email-provider-logo { |
| 726 | background: #ffffff; |
| 727 | color: #ea4335; |
| 728 | border: 1px solid rgba(234, 67, 53, 0.45); |
| 729 | } |
| 730 | |
| 731 | .logo-icloud .email-provider-logo { |
| 732 | background: linear-gradient(135deg, #e0f2fe, #ffffff); |
| 733 | color: #2563eb; |
| 734 | } |
| 735 | |
| 736 | .logo-yahoo .email-provider-logo { |
| 737 | background: #6001d2; |
| 738 | color: #ffffff; |
| 739 | } |
| 740 | |
| 741 | .logo-exchange .email-provider-logo { |
| 742 | background: #0078d4; |
| 743 | color: #ffffff; |
| 744 | } |
| 745 | |
| 746 | .logo-custom-imap .email-provider-logo { |
| 747 | background: color-mix(in srgb, var(--color-background) 72%, white 28%); |
| 748 | color: var(--color-text-secondary); |
| 749 | } |
| 750 | |
| 751 | .email-microsoft-mark { |
| 752 | width: 1.55rem; |
| 753 | height: 1.55rem; |
| 754 | display: grid; |
| 755 | grid-template-columns: repeat(2, minmax(0, 1fr)); |
| 756 | gap: 0.16rem; |
| 757 | } |
| 758 | |
| 759 | .email-microsoft-mark span:nth-child(1) { |
| 760 | background: #f25022; |
| 761 | } |
| 762 | |
| 763 | .email-microsoft-mark span:nth-child(2) { |
| 764 | background: #7fba00; |
| 765 | } |
| 766 | |
| 767 | .email-microsoft-mark span:nth-child(3) { |
| 768 | background: #00a4ef; |
| 769 | } |
| 770 | |
| 771 | .email-microsoft-mark span:nth-child(4) { |
| 772 | background: #ffb900; |
| 773 | } |
| 774 | |
| 775 | .email-provider-name { |
| 776 | min-width: 0; |
| 777 | font-weight: 800; |
| 778 | line-height: 1.25; |
| 779 | overflow-wrap: anywhere; |
| 780 | } |
| 781 | |
| 782 | .email-provider-hint { |
| 783 | min-width: 0; |
| 784 | color: var(--color-text-secondary); |
| 785 | font-size: var(--font-size-small); |
| 786 | line-height: 1.35; |
| 787 | overflow-wrap: anywhere; |
| 788 | } |
| 789 | |
| 790 | .email-post-provider { |
| 791 | margin-top: 0.3rem; |
| 792 | } |
| 793 | |
| 794 | .email-intro-copy { |
| 795 | margin: 1rem 0; |
| 796 | padding: 0.85rem 0.95rem; |
| 797 | border-radius: 12px; |
| 798 | background: color-mix(in srgb, #3b82f6 12%, var(--color-background) 88%); |
| 799 | color: var(--color-text-secondary); |
| 800 | line-height: 1.5; |
| 801 | } |
| 802 | |
| 803 | .email-intro-link { |
| 804 | display: inline-flex; |
| 805 | margin-top: 0.55rem; |
| 806 | color: var(--color-highlight); |
| 807 | font-weight: 600; |
| 808 | text-decoration: none; |
| 809 | } |
| 810 | |
| 811 | .email-intro-link:hover { |
| 812 | text-decoration: underline; |
| 813 | } |
| 814 | |
| 815 | .email-grid { |
| 816 | display: grid; |
| 817 | grid-template-columns: repeat(2, minmax(0, 1fr)); |
| 818 | gap: 0.85rem; |
| 819 | } |
| 820 | |
| 821 | .email-note, |
| 822 | .email-missing { |
| 823 | margin-top: 0.2rem; |
| 824 | margin-bottom: 0.85rem; |
| 825 | padding: 0.8rem 0.9rem; |
| 826 | border-radius: 12px; |
| 827 | font-size: var(--font-size-small); |
| 828 | line-height: 1.5; |
| 829 | } |
| 830 | |
| 831 | .email-note { |
| 832 | background: color-mix(in srgb, var(--color-background) 82%, white 18%); |
| 833 | color: var(--color-text-secondary); |
| 834 | } |
| 835 | |
| 836 | .email-missing { |
| 837 | background: color-mix(in srgb, #f59e0b 14%, var(--color-background) 86%); |
| 838 | color: var(--color-text-secondary); |
| 839 | } |
| 840 | |
| 841 | .email-advanced { |
| 842 | margin-top: 0.95rem; |
| 843 | border: 1px solid color-mix(in srgb, var(--color-border) 88%, white 12%); |
| 844 | border-radius: 14px; |
| 845 | overflow: hidden; |
| 846 | } |
| 847 | |
| 848 | .email-advanced summary { |
| 849 | padding: 0.9rem 1rem; |
| 850 | background: color-mix(in srgb, var(--color-background) 88%, white 12%); |
| 851 | } |
| 852 | |
| 853 | .email-advanced-body { |
| 854 | padding: 1rem; |
| 855 | display: flex; |
| 856 | flex-direction: column; |
| 857 | gap: 0.2rem; |
| 858 | } |
| 859 | |
| 860 | .email-test-panel { |
| 861 | margin-top: 1rem; |
| 862 | padding: var(--spacing-xs) 0; |
| 863 | display: flex; |
| 864 | justify-content: space-between; |
| 865 | align-items: center; |
| 866 | gap: 1rem; |
| 867 | } |
| 868 | |
| 869 | .email-test-copy { |
| 870 | min-width: 0; |
| 871 | } |
| 872 | |
| 873 | .email-test-title { |
| 874 | font-weight: 700; |
| 875 | margin-bottom: 0.25rem; |
| 876 | } |
| 877 | |
| 878 | .email-test-description { |
| 879 | color: var(--color-text-secondary); |
| 880 | line-height: 1.5; |
| 881 | font-size: var(--font-size-small); |
| 882 | } |
| 883 | |
| 884 | .email-results { |
| 885 | margin-top: 0.9rem; |
| 886 | border-radius: 14px; |
| 887 | border: 1px solid color-mix(in srgb, #22c55e 28%, var(--color-border) 72%); |
| 888 | background: color-mix(in srgb, #22c55e 8%, var(--color-background) 92%); |
| 889 | padding: 0.35rem 0.9rem; |
| 890 | } |
| 891 | |
| 892 | .email-results.is-error { |
| 893 | border-color: color-mix(in srgb, #ef4444 28%, var(--color-border) 72%); |
| 894 | background: color-mix(in srgb, #ef4444 8%, var(--color-background) 92%); |
| 895 | } |
| 896 | |
| 897 | .email-result-row { |
| 898 | display: flex; |
| 899 | align-items: flex-start; |
| 900 | gap: 0.8rem; |
| 901 | padding: 0.7rem 0; |
| 902 | } |
| 903 | |
| 904 | .email-result-row+.email-result-row { |
| 905 | border-top: 1px solid color-mix(in srgb, var(--color-border) 85%, white 15%); |
| 906 | } |
| 907 | |
| 908 | .email-result-icon { |
| 909 | width: 1.25rem; |
| 910 | font-weight: 800; |
| 911 | line-height: 1.3; |
| 912 | } |
| 913 | |
| 914 | .email-result-copy { |
| 915 | min-width: 0; |
| 916 | } |
| 917 | |
| 918 | .email-result-title { |
| 919 | font-weight: 700; |
| 920 | margin-bottom: 0.18rem; |
| 921 | } |
| 922 | |
| 923 | .email-result-message { |
| 924 | color: var(--color-text-secondary); |
| 925 | line-height: 1.5; |
| 926 | font-size: var(--font-size-small); |
| 927 | overflow-wrap: anywhere; |
| 928 | } |
| 929 | |
| 930 | .email-status-pill { |
| 931 | display: inline-flex; |
| 932 | align-items: center; |
| 933 | justify-content: center; |
| 934 | min-width: 5.25rem; |
| 935 | padding: 0.35rem 0.7rem; |
| 936 | border-radius: 999px; |
| 937 | font-size: 0.8rem; |
| 938 | font-weight: 700; |
| 939 | letter-spacing: 0.01em; |
| 940 | } |
| 941 | |
| 942 | .email-status-pill.tone-success { |
| 943 | background: rgba(34, 197, 94, 0.14); |
| 944 | color: #7ee7a4; |
| 945 | } |
| 946 | |
| 947 | .email-status-pill.tone-ready { |
| 948 | background: rgba(59, 130, 246, 0.16); |
| 949 | color: #93c5fd; |
| 950 | } |
| 951 | |
| 952 | .email-status-pill.tone-warning { |
| 953 | background: rgba(245, 158, 11, 0.16); |
| 954 | color: #fcd34d; |
| 955 | } |
| 956 | |
| 957 | .email-status-pill.tone-muted { |
| 958 | background: rgba(148, 163, 184, 0.14); |
| 959 | color: #cbd5e1; |
| 960 | } |
| 961 | |
| 962 | .email-add-another { |
| 963 | align-self: flex-start; |
| 964 | } |
| 965 | |
| 966 | @media (max-width: 900px) { |
| 967 | |
| 968 | .email-provider-grid { |
| 969 | grid-template-columns: repeat(2, minmax(0, 1fr)); |
| 970 | } |
| 971 | |
| 972 | .email-guide-body, |
| 973 | .email-grid { |
| 974 | grid-template-columns: minmax(0, 1fr); |
| 975 | } |
| 976 | } |
| 977 | |
| 978 | @media (max-width: 640px) { |
| 979 | |
| 980 | .email-card-header, |
| 981 | .email-test-panel { |
| 982 | flex-direction: column; |
| 983 | align-items: stretch; |
| 984 | } |
| 985 | |
| 986 | .email-card-actions { |
| 987 | justify-content: space-between; |
| 988 | width: 100%; |
| 989 | } |
| 990 | |
| 991 | .email-provider-topline { |
| 992 | flex-direction: column; |
| 993 | align-items: stretch; |
| 994 | } |
| 995 | |
| 996 | .email-provider-grid, |
| 997 | .email-grid { |
| 998 | grid-template-columns: minmax(0, 1fr); |
| 999 | } |
| 1000 | |
| 1001 | .email-change-provider { |
| 1002 | align-self: flex-start; |
| 1003 | } |
| 1004 | |
| 1005 | .email-status-pill { |
| 1006 | min-width: 0; |
| 1007 | } |
| 1008 | } |
| 1009 | </style> |
| 1010 | </body> |
| 1011 | |
| 1012 | </html> |