1<!DOCTYPE html> 2<html lang="en"> 3<head> 4<!-- Google Tag Manager -->
5<script>
vendor: 327 bytes, lines 5-9
5(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': 6new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], 7j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 8'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); 9})(window,document,'script','dataLayer','
9GTM-PWM9KJTJ
vendor: 3 bytes, line 9
9');
9</script>
9 10<!-- End Google Tag Manager --> 11<meta charset="UTF-8"/> 12<meta name="viewport" content="width=device-width, initial-scale=1.0"/> 13<title>Forge -- One question. Eight minds. One decision.</title> 14<link rel="preconnect" href="https://fonts.googleapis.com"/> 15<link href="https://fonts.googleapis.com/css2?family=Syne:wght@400;700;800&family=DM+Sans:opsz,[email protected],400;9..40,500&display=swap" rel="stylesheet"/> 16<link rel="stylesheet" href="/css/forge.css"/> 17<style> 18.session-pill{display:inline-flex;align-items:center;gap:8px;background:rgba(34,197,94,0.08);border:1px solid rgba(34,197,94,0.22);border-radius:50px;padding:6px 14px;font-size:13px;color:#22c55e;margin-bottom:16px;} 19.session-pill .pill-dot{width:7px;height:7px;border-radius:50%;background:#22c55e;} 20.session-pill .pill-expand{color:rgba(255,255,255,0.4);font-size:11px;cursor:pointer;margin-left:4px;} 21.session-pill .pill-expand:hover{color:#f97316;} 22.hero-title-new{display:none;font-size:clamp(2rem,5vw,3.2rem);font-weight:800;line-height:1.1;margin-bottom:0.5rem;} 23.hero-title-new em{color:#f97316;font-style:normal;} 24body.state-new .hero-title{display:none;} 25body.state-new .hero-title-new{display:block;} 26body.state-new .hero-sub{display:none;} 27body.state-new .perspectives{display:none;} 28body.state-new .mode-tabs{display:none;} 29body.state-new .starters{display:none;} 30body.state-new #statusBar{display:none!important;} 31body.state-new #quickPromptChips{display:none!important;} 32body.state-returning .hero-title-new{display:none;} 33body.state-returning .perspectives{display:block;} 34body.state-returning .mode-tabs{display:flex;} 35body.state-returning .starters{display:flex;} 36body.state-returning #statusBar{display:none!important;} 37body.state-post-query .hero-title-new{display:none;} 38body.state-post-query .perspectives{display:block;} 39body.state-post-query .mode-tabs{display:flex;} 40body.state-post-query .starters{display:none;} 41body.state-post-query #statusBar{display:none!important;} 42.hero-sub-new{display:none;font-size:15px;color:var(--muted,#9494aa);line-height:1.6;margin-bottom:1rem;max-width:520px;margin-left:auto;margin-right:auto;} 43body.state-new .hero-sub-new{display:block;} 44 45/* === WELCOME MODAL ===*/ 46 47/* ============================================================ 48 FORGE WELCOME MODAL â CSS SYSTEM 49 3-step onboarding: Install â Connect â First Question 50 Trigger this modal on first login (no prior session detected). 51 Dismiss it permanently once the user completes Step 3 52 or manually closes. Store state in localStorage: forge_onboarded=true 53 ============================================================ */ 54 55/* --- Onboarding modal ------------------------------------- */ 56.forge-onboard-overlay { 57 position: fixed; inset: 0; background: rgba(0,0,0,0.75); 58 backdrop-filter: blur(6px); z-index: 9999; 59 display: flex; align-items: center; justify-content: center; 60 padding: 20px; animation: fadeInOverlay 0.3s ease; 61} 62@keyframes fadeInOverlay { from { opacity:0; } to { opacity:1; } } 63.forge-onboard-modal { 64 background: #111118; border: 1px solid rgba(255,255,255,0.1); 65 border-radius: 20px; padding: 40px 36px; max-width: 520px; width: 100%; 66 text-align: center; animation: slideUpModal 0.3s ease; 67} 68@keyframes slideUpModal { from { transform:translateY(20px);opacity:0; } to { transform:translateY(0);opacity:1; } } 69.forge-onboard-modal__flame { font-size: 36px; margin-bottom: 16px; } 70.forge-onboard-modal__title { 71 font-family: 'Syne', sans-serif; font-size: 22px; font-weight: 800; 72 color: #f4f4fa; margin-bottom: 8px; line-height: 1.3; 73} 74.forge-onboard-modal__sub { 75 font-size: 14px; color: #6b6b88; margin-bottom: 32px; line-height: 1.6; 76} 77.forge-onboard-modal__choices { 78 display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 20px; 79} 80.forge-onboard-choice { 81 background: rgba(255,255,255,0.03); border: 1px solid rgba(255,255,255,0.1); 82 border-radius: 14px; padding: 20px 16px; cursor: pointer; 83 transition: all 0.2s; text-align: left; 84} 85.forge-onboard-choice:hover { border-color: #f97316; background: rgba(249,115,22,0.06); } 86.forge-onboard-choice__icon { font-size: 24px; margin-bottom: 10px; } 87.forge-onboard-choice__title { 88 font-size: 14px; font-weight: 700; color: #f4f4fa; margin-bottom: 6px; 89} 90.forge-onboard-choice__desc { font-size: 12px; color: #6b6b88; line-height: 1.5; } 91.forge-onboard-modal__skip { 92 font-size: 12px; color: #6b6b88; cursor: pointer; 93 background: none; border: none; padding: 4px; font-family: inherit; 94} 95.forge-onboard-modal__skip:hover { color: #9494aa; } 96@media (max-width: 480px) { 97 .forge-onboard-modal__choices { grid-template-columns: 1fr; } 98 .forge-onboard-modal { padding: 28px 20px; } 99} 100 101/* --- Reset ------------------------------------------------ */ 102*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } 103 104:root { 105 /* Brand */ 106 --f-orange: #E8652A; 107 --f-orange-hover: #d45a22; 108 --f-green: #10A37F; 109 110 /* AI provider colours */ 111 --ai-claude: #E8652A; 112 --ai-chatgpt: #10A37F; 113 --ai-gemini: #4A8EF4; 114 --ai-mistral: #EF9F27; 115 --ai-deepseek: #6366f1; 116 --ai-perplexity: #1D9E75; 117 --ai-grok: #ff6b6b; 118 --ai-meta: #0866FF; 119
120 /* Surfaces */ 121 --bg-overlay: rgba(0, 0, 0, 0.72); 122} 123 124/* Theme overrides disabled */ 125body[data-theme="light"] { 126 --bg-page: #f8f9fc; --bg-modal: #ffffff; --bg-surf-1: #f0f0f8; --bg-surf-2: #e8e8f4; 127 --text-primary: #111122; --text-secondary: #444455; --text-muted: #8888a0; 128 --border-subtle: rgba(0,0,0,0.1); --border: rgba(0,0,0,0.1); 129 background: #f8f9fc; color: #111122; 130} 131body[data-theme="sand"] { 132 --bg-page: #faf7f2; --bg-modal: #fff8ee; --bg-surf-1: #f5f0e8; --bg-surf-2: #ede8e0; 133 --text-primary: #2a2018; --text-secondary: #5a5048; --text-muted: #9a8878; 134 --border-subtle: rgba(0,0,0,0.1); --border: rgba(0,0,0,0.1); 135 background: #faf7f2; color: #2a2018; 136} 137body[data-theme="midnight"] { 138 --bg-page: #0a0a1a; --bg-modal: #10102a; --bg-surf-1: #16163a; --bg-surf-2: #1c1c42; 139 --text-primary: #e0e0ff; --text-secondary: #a0a0cc; --text-muted: #6060a0; 140 background: #0a0a1a; color: #e0e0ff; 141} 142body[data-theme="plum"] { 143 --bg-page: #0f0810; --bg-modal: #180d1a; --bg-surf-1: #201228; --bg-surf-2: #281830; 144 --text-primary: #f0e0f8; --text-secondary: #c0a0d0; --text-muted: #806090; 145 background: #0f0810; color: #f0e0f8; 146} 147body[data-theme="forest"] { 148 --bg-page: #0a0f0a; --bg-modal: #111811; --bg-surf-1: #182018; --bg-surf-2: #1e281e; 149 --text-primary: #e0f0e0; --text-secondary: #a0c0a0; --text-muted: #507050; 150 background: #0a0f0a; color: #e0f0e0; 151} 152body[data-theme="ember"] { 153 --bg-page: #0f0a06; --bg-modal: #1a1208; --bg-surf-1: #221810; --bg-surf-2: #2a1e18; 154 --text-primary: #f8ede0; --text-secondary: #c0a080; --text-muted: #806040; 155 background: #0f0a06; color: #f8ede0; 156} 157body[data-theme="slate"] { 158 --bg-page: #0c0d10; --bg-modal: #141520; --bg-surf-1: #1c1d2a; --bg-surf-2: #222338; 159 --text-primary: #d8dae8; --text-secondary: #9898b8; --text-muted: #585a78; 160 background: #0c0d10; color: #d8dae8; 161} 162 --bg-overlay: rgba(0, 0, 0, 0.72); 163 --bg-modal: #141414; 164 --bg-surf-1: #1c1c1c; 165 --bg-surf-2: #222222; 166 167 /* Borders */ 168 --bdr-1: #242424; 169 --bdr-2: #2e2e2e; 170 --bdr-3: #3a3a3a; 171 172 /* Text */ 173 --tx-primary: #ffffff; 174 --tx-secondary: #888888; 175 --tx-muted: #555555; 176 177 /* Success (session ready) */ 178 --ready-bg: #0d2a20; 179 --ready-bdr: #1a4a30; 180 --ready-tx: #10A37F; 181 182 /* Typography */ 183 font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; 184 -webkit-font-smoothing: antialiased; 185/* ============================================================ 186 OVERLAY 187 Full-screen backdrop. Centres the modal vertically. 188 ============================================================ */ 189.forge-overlay { 190 position: fixed; 191 inset: 0; 192 background: var(--bg-overlay); 193 display: flex; 194 align-items: center; 195 justify-content: center; 196 z-index: 9999; 197 padding: 20px; 198 199 /* Fade in */ 200 animation: overlayIn 0.2s ease; 201} 202@keyframes overlayIn { 203 from { opacity: 0; } 204 to { opacity: 1; } 205} 206 207 208/* ============================================================ 209 MODAL SHELL 210 ============================================================ */ 211.forge-modal { 212 background: var(--bg-modal); 213 overflow-y: auto; 214 max-height: 85vh; 215 border: 1px solid var(--bdr-2); 216 border-radius: 16px; 217 width: 100%; 218 max-width: 480px; 219 overflow: hidden; 220 221 /* Slide up */ 222 animation: modalIn 0.25s ease; 223} 224@keyframes modalIn { 225 from { opacity: 0; transform: translateY(16px); } 226 to { opacity: 1; transform: translateY(0); } 227} 228 229 230/* --- Modal header ----------------------------------------- */ 231.forge-modal__header { 232 display: flex; 233 align-items: center; 234 justify-content: space-between; 235 padding: 20px 24px 0; 236} 237 238.forge-modal__logo { 239 display: flex; 240 align-items: center; 241 gap: 8px; 242 text-decoration: none; 243} 244.forge-modal__logo-icon { 245 width: 24px; 246 height: 24px; 247 background: var(--f-orange); 248 border-radius: 6px; 249 display: flex; 250 align-items: center; 251 justify-content: center; 252 flex-shrink: 0; 253} 254.forge-modal__logo-icon svg { 255 width: 11px; 256 height: 11px; 257 fill: #fff; 258} 259.forge-modal__logo-name { 260 font-size: 15px; 261 font-weight: 600; 262 color: var(--tx-primary); 263} 264 265.forge-modal__close { 266 background: transparent; 267 border: none; 268 color: var(--tx-muted); 269 font-size: 20px; 270 line-height: 1; 271 cursor: pointer; 272 padding: 4px; 273 border-radius: 4px; 274 transition: color 0.15s; 275} 276.forge-modal__close:hover { color: var(--tx-secondary); } 277 278 279/* --- Modal body ------------------------------------------- */ 280.forge-modal__body { 281 padding: 20px 24px 24px; 282} 283 284.forge-modal__welcome { 285 font-size: 12px; 286 color: var(--tx-secondary); 287 margin-bottom: 4px; 288} 289.forge-modal__title { 290 font-size: 21px; 291 font-weight: 700; 292 color: var(--tx-primary); 293 line-height: 1.25; 294 margin-bottom: 20px; 295} 296.forge-modal__title span { color: var(--f-orange); } 297 298 299/* ============================================================ 300 STEP LIST 301 Vertical stepper with connector lines. 302 Each .step contains a left column (number + connector) 303 and a right column (content). 304 ============================================================ */ 305.forge-steps { 306 display: flex; 307 flex-direction: column; 308 margin-bottom: 20px; 309} 310 311.forge-step { 312 display: flex; 313 gap: 14px; 314 align-items: flex-start; 315 padding: 14px 0; 316 border-bottom: 1px solid var(--bdr-1); 317} 318.forge-step:last-child { border-bottom: none; } 319 320/* Left column: number circle + connector line */ 321.forge-step__left { 322 display: flex; 323 flex-direction: column; 324 align-items: center; 325 flex-shrink: 0; 326 gap: 0; 327} 328.forge-step__num { 329 width: 28px; 330 height: 28px; 331 border-radius: 50%; 332 display: flex; 333 align-items: center; 334 justify-content: center; 335 font-size: 12px; 336 font-weight: 600; 337 flex-shrink: 0; 338} 339 340/* State variants */ 341.forge-step__num--active { 342 background: var(--f-orange); 343 border: 1px solid var(--f-orange); 344 color: #fff; 345} 346.forge-step__num--done { 347 background: var(--ready-bg); 348 border: 1px solid var(--ready-bdr); 349 color: var(--ready-tx); 350 font-size: 14px; /* icon size */ 351} 352.forge-step__num--pending { 353 background: var(--bg-surf-2); 354 border: 1px solid var(--bdr-2); 355 color: var(--tx-muted); 356} 357 358/* Vertical connector between steps */ 359.forge-step__connector { 360 width: 1px; 361 background: var(--bdr-2); 362 flex: 1; 363 min-height: 10px; 364 margin-top: 4px; 365} 366 367/* Right column: label, title, description, sub-components */ 368.forge-step__right { 369 flex: 1; 370 padding-top: 3px; 371} 372.forge-step__label { 373 font-size: 11px; 374 color: var(--tx-muted); 375 margin-bottom: 2px; 376} 377.forge-step__name { 378 font-size: 14px; 379 font-weight: 600; 380 color: var(--tx-primary); 381 margin-bottom: 6px; 382} 383.forge-step__name--dim { color: var(--tx-muted); font-weight: 400; } 384.forge-step__name--done { color: var(--ready-tx); } 385.forge-step__desc { 386 font-size: 12px; 387 color: var(--tx-secondary); 388 line-height: 1.65; 389 margin-bottom: 12px; 390} 391 392 393/* ============================================================ 394 STEP 1 â INSTALL: Extension badge 395 ============================================================ */ 396.forge-ext-badge { 397 display: inline-flex; 398 align-items: center; 399 gap: 7px; 400 background: var(--bg-surf-2); 401 border: 1px solid var(--bdr-2); 402 border-radius: 8px; 403 padding: 6px 12px; 404 font-size: 12px; 405 color: var(--tx-secondary); 406 margin-bottom: 12px; 407} 408.forge-ext-badge__icon { 409 /* Chrome logo placeholder â replace with actual Chrome SVG */ 410 width: 16px; 411 height: 16px; 412 background: var(--f-orange); 413 border-radius: 50%; 414 flex-shrink: 0; 415} 416 417 418/* ============================================================ 419 STEP 2 â CONNECT: AI session detection grid 420 ============================================================ */ 421.forge-ai-grid { 422 display: grid; 423 grid-template-columns: repeat(4, 1fr); 424 gap: 6px; 425 margin-top: 2px; 426} 427 428.forge-ai-chip { 429 display: flex; 430 align-items: center; 431 gap: 5px; 432 padding: 6px 7px; 433 background: var(--bg-surf-2); 434 border: 1px solid var(--bdr-2); 435 border-radius: 8px; 436 font-size: 10px; 437 color: var(--tx-muted); 438 transition: border-color 0.2s, background 0.2s; 439 min-width: 0; 440 max-width: 100%; 441 overflow: hidden; 442} 443 444/* Ready state â populated by JS when session detected */ 445.forge-ai-chip--ready { 446 background: var(--ready-bg); 447 border-color: var(--ready-bdr); 448} 449.forge-ai-chip--ready .forge-ai-chip__name { 450 color: var(--ready-tx); 451} 452 453/* Pending state â not yet detected */ 454.forge-ai-chip--pending .forge-ai-chip__name { 455 color: var(--tx-muted); 456} 457 458.forge-ai-chip__dot { 459 width: 6px; 460 height: 6px; 461 border-radius: 50%; 462 flex-shrink: 0; 463} 464.forge-ai-chip__name { 465 font-size: 10px; 466 flex: 1; 467 white-space: nowrap; 468 overflow: hidden; 469 text-overflow: ellipsis; 470} 471.forge-ai-chip__check { 472 font-size: 11px; 473 color: var(--ready-tx); 474 flex-shrink: 0; 475} 476 477/* Session count tag â shown above the grid */ 478.forge-session-count { 479 display: inline-flex; 480 align-items: center; 481 gap: 5px; 482 font-size: 11px; 483 color: var(--ready-tx); 484 margin-bottom: 10px; 485} 486.forge-session-count__dot { 487 width: 6px; 488 height: 6px; 489 border-radius: 50%; 490 background: var(--ready-tx); 491 animation: pulse 1.5s infinite; 492} 493@keyframes pulse { 494 0%, 100% { opacity: 1; } 495 50% { opacity: 0.4; } 496} 497 498 499/* ============================================================ 500 STEP 3 â FIRST QUESTION: Suggested prompts 501 ============================================================ */ 502.forge-suggestions { 503 display: flex; 504 flex-direction: column; 505 gap: 6px; 506 margin-bottom: 4px; 507} 508 509.forge-suggestion { 510 padding: 10px 14px; 511 background: var(--bg-surf-2); 512 border: 1px solid var(--bdr-2); 513 border-radius: 10px; 514 font-size: 12px; 515 color: var(--tx-secondary); 516 cursor: pointer; 517 text-align: left; 518 width: 100%; 519 transition: border-color 0.15s, color 0.15s, background 0.15s; 520 line-height: 1.4; 521} 522.forge-suggestion:hover { 523 border-color: var(--f-orange); 524 color: var(--tx-primary); 525 background: var(--bg-surf-1); 526} 527.forge-suggestion--selected { 528 border-color: var(--f-orange); 529 color: var(--tx-primary); 530 background: var(--bg-surf-1); 531} 532 533 534/* ============================================================ 535 BUTTONS 536 ============================================================ */ 537.forge-btn { 538 display: flex; 539 align-items: center; 540 justify-content: center; 541 gap: 8px; 542 width: 100%; 543 padding: 12px 16px; 544 border-radius: 10px; 545 font-size: 13px; 546 font-weight: 600; 547 cursor: pointer; 548 border: none; 549 transition: background 0.15s, opacity 0.15s; 550} 551 552.forge-btn--primary { 553 background: var(--f-orange); 554 color: #fff; 555} 556.forge-btn--primary:hover { background: var(--f-orange-hover); } 557 558.forge-btn--ghost { 559 background: transparent; 560 border: 1px solid var(--bdr-3); 561 color: var(--tx-secondary); 562 margin-top: 8px; 563 font-weight: 400; 564} 565.forge-btn--ghost:hover { 566 border-color: var(--bdr-3); 567 color: var(--tx-primary); 568 background: var(--bg-surf-2); 569} 570 571 572/* ============================================================ 573 PROGRESS DOTS 574 ============================================================ */ 575.forge-progress { 576 display: flex; 577 align-items: center; 578 justify-content: center; 579 gap: 6px; 580 padding-top: 16px; 581 margin-top: 16px; 582 border-top: 1px solid var(--bdr-1); 583} 584.forge-progress__dot { 585 width: 6px; 586 height: 6px; 587 border-radius: 50%; 588 background: var(--bdr-2); 589 transition: background 0.2s; 590} 591.forge-progress__dot--active { background: var(--f-orange); } 592.forge-progress__dot--done { background: var(--ready-tx); } 593.forge-progress__label { 594 font-size: 11px; 595 color: var(--tx-muted); 596 margin-left: 6px; 597} 598 599 600/* ============================================================ 601 SKIP HINT (Step 1 only) 602 ============================================================ */ 603.forge-skip { 604 font-size: 11px; 605 color: var(--tx-muted); 606 text-align: center; 607 margin-top: 12px; 608} 609.forge-skip a { 610 color: var(--f-orange); 611 text-decoration: none; 612 cursor: pointer; 613} 614.forge-skip a:hover { text-decoration: underline; } 615 616 617/* ============================================================ 618 RESPONSIVE â MOBILE (â¤480px) 619 ============================================================ */ 620@media (max-width: 480px) { 621 .forge-overlay { padding: 12px; align-items: flex-end; } 622 623 .forge-modal { 624 border-bottom-left-radius: 0; 625 border-bottom-right-radius: 0; 626 max-width: 100%; 627 } 628 629 .forge-ai-grid { 630 grid-template-columns: repeat(4, 1fr); 631 gap: 4px; 632 } 633 .forge-ai-chip { 634 padding: 4px 4px !important; 635 gap: 3px !important; 636 font-size: 9px !important; 637 } 638 .forge-ai-chip__name { font-size: 9px !important; } 639 .forge-ai-chip__dot { width: 5px !important; height: 5px !important; } 640 .forge-ai-chip__check { font-size: 9px !important; } 641 .forge-ai-chip__name { max-width: 48px !important; overflow: hidden !important; text-overflow: ellipsis !important; white-space: nowrap !important; } 642 643 .forge-modal__title { font-size: 18px; } 644} 645 646 647.provider-locked{opacity:0.45;filter:grayscale(0.4)}.provider-locked:hover{opacity:0.65;border-color:var(--orange)!important;transition:all .15s} 648</style>
649<script> 650// Save last visited page for return after login 651localStorage.setItem('forge_last_page', window.location.pathname); 652</script>
vendor: 1 bytes, line 652
652
653<script type="text/javascript"> 654 (function(c,l,a,r,i,t,y){ 655 c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)}; 656 t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i; 657 y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y); 658 })(window, document, "clarity", "script", "wwtuvo1ddx"); 659</script>
659 660 <link rel="stylesheet" href="/forge-mobile.css?v=2"> 661</head> 662<body><a href="https://forge.projectcoachai.com/cdn-cgi/content?id=zPZUlCCWFmoXrPZP4dx17wU8VgPPjDRPxR_iedEe5lM-1790905186.4730504-1.2.1.1-LhGqouwv7DpM1luJhpBCSPZbtuk1E.6OAyEL_YZ_uySdePvjftUgnFACcdt8Sihu" aria-hidden="true" rel="nofollow noopener" style="display: none !important; visibility: hidden !important"></a> 663<!-- Google Tag Manager (noscript) -->
vendor: 68 bytes, lines 663-664
663 664<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=
664GTM-PWM9KJTJ
vendor: 83 bytes, lines 664-665
664" 665height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
666<!-- End Google Tag Manager (noscript) --> 667<!-- v4 Sidebar --> 668<div id="v4Sidebar" style="display:none;position:fixed;top:0;left:0;width:260px;height:100vh;background:#111118;border-right:1px solid rgba(255,255,255,0.08);z-index:9998;flex-direction:column;padding:0;overflow:hidden"> 669 <div style="padding:16px;border-bottom:1px solid rgba(255,255,255,0.08);display:flex;align-items:center;justify-content:space-between"> 670 <span style="font-size:13px;font-weight:700;color:#fff">Forge</span> 671 <button onclick="toggleSidebar()" style="background:none;border:none;cursor:pointer;color:#888;font-size:18px;line-height:1">Ã</button> 672 </div> 673 <div style="padding:12px"> 674 <input id="sidebarSearch" placeholder="Search queries..." oninput="filterSidebar(this.value)" style="width:100%;background:rgba(255,255,255,0.06);border:1px solid rgba(255,255,255,0.1);border-radius:8px;padding:8px 12px;font-size:12px;color:#fff;outline:none;box-sizing:border-box"/> 675 </div> 676 <div style="flex:1;overflow-y:auto;padding:0 8px" id="sidebarRecents"> 677 <div style="font-size:10px;font-weight:700;letter-spacing:1px;color:#555;text-transform:uppercase;padding:4px 8px 8px">Recent</div> 678 <div id="sidebarRecentList"></div> 679 </div> 680 <!-- Featured promo section --> 681 <div style="padding:8px;border-top:1px solid rgba(255,255,255,0.08);border-bottom:1px solid rgba(255,255,255,0.08)"> 682 <div style="font-size:10px;font-weight:700;letter-spacing:1px;color:#555;text-transform:uppercase;padding:4px 8px 6px">Featured</div> 683 <div style="border-radius:10px;padding:12px;background:linear-gradient(135deg,rgba(249,115,22,0.1),rgba(124,58,237,0.06));border:1px solid rgba(249,115,22,0.25)"> 684 <div id="sidebarPromoContent"></div> 685 </div> 686 </div> 687 688 <div style="border-top:1px solid rgba(255,255,255,0.08);padding:8px"> 689 <a href="/perspectives?quickchat=1" style="display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:8px;color:#888;text-decoration:none;font-size:13px;transition:background .15s" onmouseover="this.style.background='rgba(255,255,255,0.05)'" onmouseout="this.style.background='none'"> 690 <span>â¡</span> 691 <span><span style="display:block;color:#e8e8f0;font-weight:600">Quick Answer</span><span style="display:block;font-size:11px;color:#555;margin-top:1px">Switch between 8 AIs in one tab</span></span> 692 </a> 693 <a href="/synthesis.html" style="display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:8px;color:#888;text-decoration:none;font-size:13px;transition:background .15s" onmouseover="this.style.background='rgba(255,255,255,0.05)'" onmouseout="this.style.background='none'">⦠Synthesis</a> 694 <a href="/broadcast.html" style="display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:8px;color:#888;text-decoration:none;font-size:13px;transition:background .15s" onmouseover="this.style.background='rgba(255,255,255,0.05)'" onmouseout="this.style.background='none'">â Sweep</a> 695 <a href="/excel.html" style="display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:8px;color:#888;text-decoration:none;font-size:13px;transition:background .15s" onmouseover="this.style.background='rgba(255,255,255,0.05)'" onmouseout="this.style.background='none'">ð Excel</a> 696 <a id="sidebarDocsLink" href="/documents.html" style="display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:8px;color:#888;text-decoration:none;font-size:13px;transition:background .15s" onmouseover="this.style.background='rgba(255,255,255,0.05)'" onmouseout="this.style.background='none'">ð Documents</a> 697 <a href="/diary.html" style="display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:8px;color:#888;text-decoration:none;font-size:13px;transition:background .15s" onmouseover="this.style.background='rgba(255,255,255,0.05)'" onmouseout="this.style.background='none'">ð Diary</a> 698 </div> 699 <!-- Sidebar footer â logout --> 700 <div style="border-top:1px solid rgba(255,255,255,0.08);padding:8px" id="sidebarLogout" style="display:none"> 701 <button onclick="if(typeof Forge!=='undefined'&&Forge.auth)Forge.auth.signout().then(function(){window.location.href='/'})" style="display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:8px;color:#888;background:none;border:none;font-size:13px;
701cursor:pointer;width:100%;text-align:left;font-family:inherit;transition:background .15s" onmouseover="this.style.background='rgba(255,255,255,0.05)'" onmouseout="this.style.background='none'">â Sign Out</button> 702 </div> 703</div> 704<div id="v4SidebarOverlay" onclick="toggleSidebar()" style="display:none;position:fixed;inset:0;background:rgba(0,0,0,0.4);z-index:9997"></div> 705 706<header class="header" style="position:relative"> 707 <a href="/" class="logo"><div class="logo-flame">ð¥</div>Forge<span class="logo-sub">Full Decision Workspace</span></a> 708 <div style="position:absolute;left:0;right:0;text-align:center;pointer-events:none"><span style="font-size:12px;font-weight:600;letter-spacing:1.5px;color:rgba(255,255,255,0.6);text-transform:uppercase;white-space:nowrap;border:1px solid rgba(255,255,255,0.12);border-radius:6px;padding:4px 12px;background:rgba(255,255,255,0.03)">FORGE â THE DECISION LAYER ON TOP OF AI</span></div> 709 <div class="header-right" id="headerAuth"></div> 710 <!-- theme switcher temporarily disabled --> 711 <button class="mob-nav-btn" onclick="document.getElementById('mobNavDrawer').classList.toggle('open')" aria-label="Menu">☰</button> 712</header> 713<div id="installStrip" class="install-strip"> 714 <span style="flex:1">Already use Claude or ChatGPT? <strong>Install Forge</strong> â ask all your AIs at once. Free.</span> 715 <button class="install-strip__btn" onclick="window.open('https://chromewebstore.google.com/detail/forge/onlaamgggkmmnpbkcllnhdpecaidfpml','_blank')">Install extension âº</button> 716 <button onclick="document.getElementById('installStrip').style.display='none'" style="background:none;border:none;color:#555;cursor:pointer;font-size:16px;padding:0 4px">Ã</button> 717</div> 718<div style="height:32px;border-bottom:1px solid rgba(255,255,255,0.06);display:flex;align-items:center;padding:0 16px;background:var(--bg,#09090f)"> 719 <button id="sidebarToggle" onclick="toggleSidebar()" style="background:none;border:none;cursor:pointer;color:var(--muted,#666);display:flex;align-items:center;gap:8px;font-size:11px;font-weight:600;letter-spacing:.5px;text-transform:uppercase;padding:0" title="Recent queries"> 720 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="12" x2="21" y2="12"/><line x1="3" y1="18" x2="21" y2="18"/></svg> 721 Recent 722 </button> 723</div> 724 <div class="mob-nav-drawer" id="mobNavDrawer"> 725 <a href="/forge.html">⇋ Sweep</a> 726 <a href="/perspectives.html">🌐 Perspectives</a> 727 <a href="/perspectives.html?quickchat=1">⚡ Quick Answer</a> 728 <!-- Split hidden â available via Chrome extension only --> 729 <a href="/synthesis.html">✦ Synthesis</a> 730 <a href="/excel.html">📊 Excel</a> 731 <a href="/documents.html">📄 Documents</a> 732 <a href="/diary.html">📖 Diary</a> 733 <a href="/pricing.html">💰 Pricing</a> 734 <a href="/profile.html">👤 Profile</a> 735 <!-- Signal nav hidden â launching soon 736 <a href="/signal.html">⚡ Forge Signal</a> 737 --> 738 <a href="/referral.html">🆕 Refer & Earn</a> 739 <a href="/help.html">❓ Help</a> 740 </div> 741 742<style> 743/* Install strip */ 744.install-strip { 745 display:flex;align-items:center;gap:12px; 746 padding:9px 32px;background:rgba(255,255,255,0.03); 747 border-bottom:1px solid rgba(255,255,255,0.06); 748 font-size:12px;color:#9494aa; 749} 750.install-strip strong { color:#f97316;font-weight:500; } 751.install-strip__btn { 752 padding:4px 12px;background:none;border:1px solid rgba(255,255,255,0.12); 753 border-radius:6px;color:#fff;font-size:11px;font-weight:600; 754 cursor:pointer;white-space:nowrap; 755} 756@media(max-width:600px){ .install-strip { display:none; } } 757@media (max-width: 600px) { 758 .header { padding: 0 8px !important; } 759 .header .logo-sub { display: none !important; } 760 .header > div[style*="position:absolute"] { display: none !important; } 761 .header > div[style*="text-align:center"] { display: none !important; } 762 .header-right { flex-shrink: 0 !important; } 763 #kbHint { display: none !important; } 764 #forge-role-badge { display: none !important; } 765 #v4Sidebar { width: 85vw !important; } 766 .hero { padding: 60px 16px 0 !important; } 767 /* Fix 1: title wraps on mobile */ 768 .hero h1, .section h1 { white-space: normal !important; font-size: clamp(1.1rem,5vw,1.6rem) !important; } 769 /* Fix 2: prompt wrap goes vertical, button inside */ 770 .prompt-wrap { padding: 12px !important; display: flex !important; flex-direction: column !important; overflow: visible !important; } 771 .prompt-footer { flex-direction: column !important; align-items: stretch !important; gap: 8px !important; } 772 .prompt-footer > div { width: 100% !important; } 773 .prompt-footer .btn-compare, #compareBtn { width: 100% !important; max-width: 100% !important; margin-top: 4px !important; box-sizing: border-box !important; flex-shrink: 1 !important; min-width: 0 !important; } 774 .prompt-wrap { overflow: visible !important; box-sizing: border-box !important; width: 100% !important; max-width: 100% !important; } 775 #providerChips.provider-chips { max-width: 100% !important; flex-wrap: nowrap !important; overflow: hidden !important; } 776} 777 778/* Mobile landscape â short viewport height, wide width */ 779@media (max-height: 500px) and (orientation: landscape) { 780 .header { padding: 0 12px !important; height: 44px !important; } 781 .header .logo-sub { display: none !important; } 782 .header > div[style*="position:absolute"] { display: none !important; } 783 .header > div[style*="text-align:center"] { display: none !important; } 784 #kbHint, #forge-role-badge { display: none !important; } 785 #v4Sidebar { width: 50vw !important; max-width: 320px !important; } 786 787 /* Hero â compact vertically, allow side-by-side content */ 788 .hero { min-height: auto !important; padding: 16px 24px 12px !important; justify-content: flex-start !important; } 789 .forge-flame-wrap, .forge-flame-anim { font-size: 1.6rem !important; } 790 .hero h1, .section h1 { font-size: clamp(1rem,3.5vw,1.4rem) !important; white-space: normal !important; margin-bottom: 4px !important; } 791 .hero p { font-size: 12px !important; margin-bottom: 8px !important; max-width: 90% !important; } 792 #providerChips.provider-chips { margin-bottom: 10px !important; } 793 794 /* Prompt area â keep horizontal layout, reduce padding */ 795 .prompt-wrap { padding: 10px 16px !important; max-width: 92% !important; } 796 .prompt-input { font-size: 13px !important; min-height: 36px !important; } 797 .prompt-footer { flex-direction: row !important; align-items: center !important; } 798 .prompt-footer .btn-compare, #compareBtn { width: auto !important; max-width: none !important; margin-top: 0 !important; } 799 800 /* Results â use horizontal space, reduce vertical chrome */ 801 .results-section { padding-top: 4px !important; } 802 .result-card { font-size: 12px !important; } 803 .synth-strip { padding: 10px 14px !important; } 804 805 /* Sidebar â fit within shorter viewport */ 806 .sidebar-section { margin-bottom: 6px !important; } 807 .sidebar-item { padding: 4px 8px !important; font-size: 12px !important; } 808} 809/* v4 chatbot layout override */ 810/* Small compact chips inside input footer */ 811#providerChips.provider-chips { 812 display: flex !important; 813 flex-direction: row !important; 814 flex-wrap: wrap !important; 815 gap: 4px !important; 816 margin-bottom: 0 !important; 817 grid-template-columns: unset !important; 818 justify-content: flex-start !important; 819 align-items: center !important; 820 max-width: 400px !important; 821} 822#providerChips .provider-chip { 823 padding: 2px 8px !important; 824 font-size: 11px !important; 825 gap: 4px !important; 826 border-radius: 20px !important; 827} 828#providerChips .chip-dot { 829 width: 5px !important; 830 height: 5px !important; 831} 832#providerChips .chip-status { 833 display: none !important; 834} 835/* Separator between textarea and footer */ 836.prompt-footer { 837 border-top: 1px solid var(--border) !important; 838 padding-top: 8px !important; 839 margin-top: 8px !important; 840} 841/* Compact floating provider picker */ 842#providerPicker { 843 position: fixed !important; 844 z-index: 9999 !important; 845 background: var(--bg-modal, #141414) !important; 846 border: 1px solid var(--border, rgba(255,255,255,0.12)) !important; 847 border-radius: 12px !important; 848 padding: 8px !important; 849 width: 220px !important; 850 box-shadow: 0 8px 32px rgba(0,0,0,0.6) !important; 851 bottom: 200px !important; 852 left: 50% !important; 853 transform: translateX(-50%) !important; 854} 855#providerPicker .provider-chip { 856 width: 100% !important; 857 border-radius: 8px !important; 858 padding: 6px 10px !important; 859 font-size: 12px !important; 860 margin-bottom: 2px !important; 861 justify-content: space-between !important; 862} 863.sidebar-item { 864 padding: 8px 10px; 865 border-radius: 8px; 866 font-size: 12px; 867 color: #aaa; 868 cursor: pointer; 869 white-space: nowrap; 870 overflow: hidden; 871 text-overflow: ellipsis; 872} 873.sidebar-item:hover { background: rgba(255,255,255,0.05); } 874/* +5 more toggle button */ 875#toggleChipsBtn { 876 display: inline-flex !important; 877 padding: 2px 8px !important; 878 font-size: 11px !important; 879} 880#providerPicker { display: none !important; } 881#addToolBtn { display: none !important; } 882.section-label, 883.perspectives .add-tool, 884.perspectives .reset-link, 885#quickPromptToggle, 886#quickPromptChips, 887#toggleChipsBtn, 888#resetLink { 889 display: none !important; 890} 891.perspectives { 892 margin: 0 !important; 893 padding: 0 !important; 894} 895/* Smaller advanced grid buttons */ 896.adv-grid .provider-chip { 897 padding: 4px 10px !important; 898 font-size: 11px !important; 899 gap: 4px !important; 900} 901.adv-grid .chip-dot { 902 width: 5px !important; 903 height: 5px !important; 904} 905/* File tags visible */ 906#perspFileTags { min-height: 0; } 907.prompt-wrap { 908 padding: 18px 26px !important; 909 max-width: 860px; 910 margin-left: auto; 911 margin-right: auto; 912 width: 100%; 913 overflow: visible; 914 box-sizing: border-box; 915} 916.hero { 917 min-height: calc(100vh - 56px); 918 display: flex; 919 flex-direction: column; 920 justify-content: flex-start; 921 align-items: center; 922 padding: 60px 8px 0; 923 text-align: center; 924} 925.hero-title-wrap { width: 100%; text-align: center; margin-left: 0; margin-right: 0; } 926/* prompt-wrap consolidated above */ 927 928/* Forge flame animation */ 929@keyframes forgeFlicker { 930 0%,100% { transform: scale(1) rotate(-2deg);
930 opacity: 1; } 931 25% { transform: scale(1.08) rotate(2deg); opacity: 0.9; } 932 50% { transform: scale(1.12) rotate(-1deg); opacity: 1; } 933 75% { transform: scale(1.06) rotate(1deg); opacity: 0.95; } 934} 935@keyframes forgePulse { 936 0%,100% { box-shadow: 0 0 0 0 rgba(249,115,22,0); } 937 50% { box-shadow: 0 0 32px 8px rgba(249,115,22,0.18); } 938} 939@keyframes forgeOrbit { 940 from { transform: rotate(0deg) translateX(48px) rotate(0deg); } 941 to { transform: rotate(360deg) translateX(48px) rotate(-360deg); } 942} 943.forge-flame-anim { 944 display: inline-block; 945 animation: forgeFlicker 2.4s ease-in-out infinite; 946 font-size: 2.8rem; 947 line-height: 1; 948 filter: drop-shadow(0 0 12px rgba(249,115,22,0.6)); 949} 950.forge-flame-wrap { 951 display: flex; 952 justify-content: center; 953 align-items: center; 954 margin-bottom: 20px; 955 animation: forgePulse 2.4s ease-in-out infinite; 956 width: fit-content; 957 margin-left: auto; 958 margin-right: auto; 959 border-radius: 50%; 960 padding: 8px; 961} 962</style> 963<section class="hero"> 964 <div class="hero-title-wrap" style="text-align:center;margin-bottom:20px"> 965 <div class="forge-flame-wrap"> 966 <span class="forge-flame-anim">ð¥</span> 967 </div> 968 <h1 style="font-family:var(--font-display,Syne,sans-serif);font-size:clamp(1rem,2.8vw,2.4rem);font-weight:800;line-height:1.1;margin-bottom:16px;color:var(--text,#fff);text-align:center;width:100%;white-space:normal">One question. <em style="color:#f97316;font-style:italic">Eight minds.</em> One decision.</h1> 969 <p style="font-size:17px;color:var(--muted,#9494aa);margin-bottom:28px;max-width:600px;margin-left:auto;margin-right:auto;text-align:center">Get 8 AI perspectives at once, forge the best answer, then go deeper with the AI that resonated most â all in one session.</p> 970 </div> 971 972 <div class="status-bar" id="statusBar" style="display:none"> 973 <div class="status-dot"></div><span id="statusText">8 AI engines active</span> 974 </div> 975 976 <div class="perspectives"> 977 <div class="section-label">Your Perspectives</div> 978 979 <button class="add-tool" onclick="togglePicker()" id="addToolBtn" style="display:none">+ Add more minds</button> 980 <div class="provider-picker" id="providerPicker" style="display:none"></div> 981 <span class="reset-link" id="resetLink" onclick="resetToDefault()">Reset to default</span> 982 </div> 983 984 <div style="margin-bottom:4px"> 985 <button id="quickPromptToggle" onclick="toggleQuickPromptChips()" style="font-size:11px;color:var(--muted);background:none;border:none;cursor:pointer;padding:2px 0;font-family:var(--font-body)">▶ Your Top Prompts</button> 986 </div> 987 <div id="quickPromptChips" style="display:none;margin-bottom:8px;flex-wrap:wrap;gap:6px;align-items:center"></div> 988<!-- Auth state markers --> 989 <div id="v4-cta-signedout" style="display:block"></div> 990 <div id="v4-cta-signedin" style="display:none"></div> 991 <div id="v4-welcome" style="display:none"></div> 992 993<!-- Row 1: AI chips above input â centered, single line --> 994 <div style="display:flex;align-items:center;justify-content:center;gap:5px;flex-wrap:nowrap;margin-bottom:28px;width:100%;overflow:hidden"> 995 <div class="provider-chips" id="providerChips" style="display:flex;gap:4px;flex-wrap:nowrap;align-items:center;justify-content:center;overflow:hidden;max-width:calc(100% - 32px)"></div> 996 <button id="moreMindsBtn" onclick="togglePickerV4()" title="Add or remove AI minds" style="white-space:nowrap;flex-shrink:0;background:none;border:none;color:#f97316;font-size:18px;font-weight:300;cursor:pointer;font-family:inherit;display:inline-flex;align-items:center;justify-content:center;padding:0 2px;line-height:1">+</button> 997 </div> 998 999<div class="prompt-wrap"> 1000 <input type="file" id="perspFileInput" accept=".pdf,.png,.jpg,.jpeg,.txt,.csv,.docx" style="display:none" onchange="handlePerspFile(this)" multiple/> 1001 <div style="flex:1;display:flex;flex-direction:column;gap:6px"> 1002 <div id="perspFilePreview" style="display:none;align-items:center;gap:8px;background:rgba(249,115,22,0.08);border:1px solid rgba(249,115,22,0.25);border-radius:8px;padding:6px 10px;margin-bottom:2px;max-width:fit-content"></div> 1003 <textarea class="prompt-input" id="promptInput" placeholder="Ask anything. Get 8 AI perspectives instantly." rows="1" style="min-height:44px;max-height:400px;width:100%;overflow-y:hidden;resize:none;font-size:13px;display:block;box-sizing:border-box" oninput="autoResizePrompt(this)"></textarea> 1004 </div> 1005 <div class="prompt-footer" style="display:flex;align-items:center;justify-content:space-between;gap:8px"> 1006 <!-- Left: paperclip · mic · ââµ (Ansh #2) --> 1007 <div style="display:flex;align-items:center;gap:6px;flex-shrink:0"> 1008 <label for="perspFileInput" title="Attach file" style="cursor:pointer;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;color:var(--muted,#888);font-size:13px;transition:color .15s;padding:2px" onmouseover="this.style.color='#f97316'" onmouseout="this.style.color='var(--muted,#888)'"> 1009 <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"/></svg> 1010 </label> 1011 <button id="micBtn" onclick="toggleMic()" title="Voice input" style="background:none;border:none;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;padding:2px;color:var(--muted,#888);transition:color .15s"> 1012 <svg id="micIcon" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"/><path d="M19 10v2a7 7 0 0 1-14 0v-2"/><line x1="12" y1="19" x2="12" y2="23"/><line x1="8" y1="23" x2="16" y2="23"/></svg> 1013 </button>
1014 <span id="kbHint" style="font-size:11px;color:var(--muted,#666);white-space:nowrap;flex-shrink:0">⌘↵</span> 1015 </div> 1016 <!-- Right: Save · Library · Get Perspectives (Ansh #3) --> 1017 <div style="display:flex;align-items:center;gap:6px;flex-shrink:0"> 1018 <button class="icon-btn" id="savePromptBtn" title="Save to library">💾</button> 1019 <button class="icon-btn" id="loadPromptBtn" style="white-space:nowrap;flex-shrink:0">📚 Library</button> 1020 <button class="btn btn-primary btn-compare" id="compareBtn" disabled style="padding:8px 20px;font-size:13px;border-radius:8px;white-space:nowrap;flex-shrink:0">Get Perspectives â</button> 1021 </div> 1022 </div> 1023 </div> 1024 1025 <div class="action-row" style="display:none"> 1026 <button class="btn btn-primary btn-compare" style="display:none">Get Perspectives</button> 1027 </div> 1028 1029 <div class="counter-bar" id="counterBar" style="display:none">8 minds ready</div> 1030 1031 <div class="mode-tabs"> 1032 <button class="mode-tab active" onclick="setMode('compare')">Perspectives</button> 1033 <span class="mode-sep">·</span> 1034 <button class="mode-tab" onclick="setMode('synthesize')">✦ Synthesize</button> 1035 </div> 1036 1037 <div id="perspFileTags" style="display:flex;flex-wrap:wrap;gap:6px;align-items:center;margin-bottom:4px"></div> 1038 <div class="starters"> 1039 <div class="starter" onclick="fillStarter(this)">What's the best way to...</div> 1040 <div class="starter" onclick="fillStarter(this)">Get Perspectives on these options...</div> 1041 <div class="starter" onclick="fillStarter(this)">Summarize this and tell me what to do next...</div> 1042 </div> 1043 1044 <div id="diaryAwarenessBar" style="display:flex;align-items:center;gap:10px;margin:12px 0;padding:10px 14px;background:rgba(249,115,22,0.07);border:1px solid rgba(249,115,22,0.2);border-radius:10px;font-size:13px;color:var(--muted)"> 1045 <span style="font-size:16px">ð¥</span> 1046 <span><strong style="color:var(--text)">Find any AI answer in seconds.</strong> â Every response saved and searchable, across Claude, ChatGPT, Gemini and more.</span> 1047 <a href="/diary.html" style="margin-left:auto;white-space:nowrap;color:#f97316;font-weight:600;text-decoration:none;font-size:12px">Forge Diary â</a> 1048 <button onclick="document.getElementById('diaryAwarenessBar').style.display='none';try{localStorage.setItem('forge_diary_bar_seen','1');}catch(e){}" style="background:none;border:none;color:var(--muted);cursor:pointer;font-size:16px;padding:0;line-height:1;flex-shrink:0">Ã</button> 1049 </div> 1050
1050<script>try{if(localStorage.getItem('forge_diary_bar_seen'))document.getElementById('diaryAwarenessBar').style.display='none';}catch(e){}</script>
1050 1051 1052 1053 1054<!-- v4 AI picker modal --> 1055<div id="v4PickerModal" style="display:none;position:absolute;z-index:9999;background:#141414;border:1px solid rgba(255,255,255,0.12);border-radius:12px;padding:8px;width:220px;box-shadow:0 8px 32px rgba(0,0,0,0.6)"> 1056 <div id="v4PickerList"></div> 1057</div> 1058 1059</section> 1060 1061<section class="results-section" id="resultsSection" style="display:none;padding-top:8px"> 1062 <div class="results-top"> 1063 <div> 1064 <div class="results-heading" id="resultsHeading">Incoming responses</div> 1065 <div class="results-sub" id="resultsSub">Collecting perspectives...</div> 1066 </div> 1067 <button class="btn btn-ghost" onclick="clearResults()">✕ Clear</button> 1068 </div> 1069 <div class="progress-wrap"><div class="progress-fill" id="progressFill" style="width:0%"></div></div> 1070 <div id="synthGapIndicator" style="display:none;padding:10px 0;font-size:13px;color:var(--accent);font-weight:600;text-align:center;letter-spacing:0.02em"></div> 1071 <div class="responses-grid" id="responsesGrid"></div> 1072 1073 <div class="synthesis-strip" id="synthStrip" style="display:none"> 1074 <div> 1075 <div class="synth-title">✦ Synthesis ready</div> 1076 <div class="synth-sub" id="synthSub">Responses synthesised into one decision-ready answer.</div> 1077 </div> 1078 <div class="conf-block" id="confBlock" style="display:none"> 1079 <div class="conf-score" id="confScore">-</div> 1080 <div class="conf-bar"><div class="conf-fill" id="confFill" style="width:0%"></div></div> 1081 <div class="conf-label">Consensus</div> 1082 </div> 1083 </div> 1084 1085 1086 <div class="continue-row" id="continueRow" style="display:none"> 1087 <div class="followup-chips" id="followupChips"></div> 1088 <input type="file" id="followupFileInput" accept=".pdf,.png,.jpg,.jpeg,.txt,.csv,.docx" style="display:none" onchange="handleFollowupFile(this)"/> 1089 <div id="followupFilePreview" style="display:none;align-items:center;gap:8px;background:rgba(249,115,22,0.08);border:1px solid rgba(249,115,22,0.25);border-radius:8px;padding:6px 10px;margin-top:10px;max-width:fit-content"></div> 1090 <div style="display:flex;gap:8px;margin-top:10px;width:100%;align-items:center"> 1091 <label for="followupFileInput" title="Attach file" style="cursor:pointer;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;color:var(--muted,#888);font-size:13px;transition:color .15s;padding:2px" onmouseover="this.style.color='#f97316'" onmouseout="this.style.color='var(--muted,#888)'"> 1092 <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"/></svg> 1093 </label> 1094 <input id="followupInput" placeholder="Ask a follow-up question..." style="flex:1;background:var(--surface);border:1px solid var(--border);border-radius:8px;padding:10px 14px;color:var(--text);font-size:14px;outline:none" onkeydown="if(event.key==='Enter'&&!event.shiftKey){submitFollowup();event.preventDefault();}"/> 1095 <button onclick="submitFollowup()" class="btn btn-primary" style="white-space:nowrap">Follow Up</button> 1096 </div> 1097 <a href="/synthesis.html" class="btn btn-primary" style="margin-top:8px">Continue â Synthesis</a> 1098 </div> 1099</section> 1100 1101<!-- Quick Answer Modal --> 1102<div class="modal-overlay" id="qaModal" onclick="if(event.target===this)closeQA()"> 1103 <div class="modal"> 1104 <div class="modal-hdr"><div class="modal-title">⚡ Quick Answer</div><button class="modal-x" onclick="closeQA()">✕</button></div> 1105 <div style="font-size:12px;color:#6b6b88;padding:0 16px 12px;">Choose an AI below. <strong style="color:#ff6b35">Click the Forge bar at the top of the AI's page</strong> on the provider page to return to Forge.</div> 1106 <div id="qaList"></div> 1107 </div> 1108</div> 1109 1110<!-- Prompt Library Modal --> 1111<div class="modal-overlay" id="plModal" onclick="if(event.target===this)closePL()"> 1112 <div class="modal" style="max-width:560px"> 1113 <div class="modal-hdr"><div class="modal-title">📚 Prompt Library</div><button class="modal-x" onclick="closePL()">✕</button></div> 1114 <input class="pl-search" id="plSearch" placeholder="Search prompts..." oninput="filterPL()"/> 1115 <div class="pl-list" id="plList"></div> 1116 </div> 1117</div> 1118
1119<script src="/js/forge-api.js"></script>
vendor: 1 bytes, line 1119
1119
1120<script src="/js/home.js"></script>
1120 1121 1122<footer class="forge-footer"> 1123 <div class="footer-tagline">The decision layer on top of AI.<br>Local-first. Your accounts. Your data.</div> 1124 <div class="footer-links"> 1125 <a href="/pricing.html">Pricing</a><span class="sep">·</span> 1126 <a href="/why-forge.html">Why Forge</a><span class="sep">·</span> 1127 <a href="/why-excel.html">Why Excel</a><span class="sep">·</span> 1128 <a href="/help.html">Help</a><span class="sep">·</span> 1129 <a href="/contact.html">Contact</a><span class="sep">·</span> 1130 <a href="/profile.html">Profile</a><span class="sep">·</span> 1131 <a href="/students.html">Students</a> 1132 <a href="/referral.html" style="color:inherit;text-decoration:none;">Referrals</a><span class="sep">·</span> 1133 <a href="/network.html" style="color:var(--accent);font-weight:600">ð¥ Network</a><span class="sep">·</span> 1134 <a href="/privacy.html">Privacy</a><span class="sep">·</span> 1135 <a href="/terms.html">Terms</a><span class="sep">·</span> 1136 <a href="#" onclick="inviteColleague();return false;" style="color:var(--accent);font-weight:600">🎉 Invite a Colleague</a> 1137 </div> 1138</footer>
1139<script> 1140async function inviteColleague() { 1141 let user = Forge.getUser ? Forge.getUser() : null; 1142 if (!user && Forge.restoreSession) user = await Forge.restoreSession().catch(()=>null); 1143 if (!user) { window.location.href = '/signin.html?return=' + encodeURIComponent(window.location.pathname); return; } 1144 try { 1145 const r = await Forge.request('POST', '/api/invite/generate'); 1146 if (r.ok && r.data?.url) { 1147 await navigator.clipboard?.writeText(r.data.url); 1148 alert('Invite link copied! Paste it to share Forge with a colleague.\n\n' + r.data.url); 1149 } 1150 } catch(_) { alert('Sign in to generate an invite link.'); } 1151} 1152</script>
vendor: 1 bytes, line 1152
1152
1153<script> 1154const CURATED_PROMPTS = [ 1155 "What are the pros and cons of this decision?", 1156 "What would you do in my situation?", 1157 "Summarize this and tell me what to do next", 1158 "What am I missing that I should consider?", 1159 "Give me a second opinion on this" 1160]; 1161async function loadQuickPromptChips() { 1162 const chips = document.getElementById('quickPromptChips'); 1163 if (!chips) return; 1164 const isAuth = Forge.isAuthenticated && Forge.isAuthenticated(); 1165 if (!isAuth) { 1166 // Show curated example prompts for logged-out users 1167 chips.style.display = 'none'; 1168 chips.innerHTML = '<span style="font-size:11px;color:var(--muted);font-weight:600;white-space:nowrap">TRY:</span>' + 1169 CURATED_PROMPTS.map(p => `<button onclick="loadQuickPrompt(${JSON.stringify(p)})" style="padding:4px 10px;border-radius:20px;font-size:11px;cursor:pointer;background:rgba(255,107,53,0.06);border:1px solid rgba(255,107,53,0.2);color:rgba(255,107,53,0.9);white-space:nowrap;max-width:220px;overflow:hidden;text-overflow:ellipsis">${p.slice(0,38)}${p.length>38?"...":""}</button>` 1170 ).join(''); 1171 return; 1172 } 1173 try { 1174 const r = await Forge.request('GET', '/api/prompts?limit=5'); 1175 if (!r.ok || !r.data?.prompts?.length) { 1176 // Logged in but no prompts yet â show curated 1177 chips.style.display = 'none'; 1178 chips.innerHTML = '<span style="font-size:11px;color:var(--muted);font-weight:600;white-space:nowrap">TRY:</span>' + 1179 CURATED_PROMPTS.slice(0,3).map(p => `<button onclick="loadQuickPrompt(${JSON.stringify(p)})" style="padding:4px 10px;border-radius:20px;font-size:11px;cursor:pointer;background:rgba(255,107,53,0.06);border:1px solid rgba(255,107,53,0.2);color:rgba(255,107,53,0.9);white-space:nowrap;max-width:220px;overflow:hidden;text-overflow:ellipsis">${p.slice(0,38)}${p.length>38?"...":""}</button>` 1180 ).join(''); 1181 return; 1182 } 1183 const top = r.data.prompts.slice(0,5); 1184 chips.style.display = 'none'; 1185 chips.innerHTML = '<span style="font-size:11px;color:var(--muted);font-weight:600;white-space:nowrap">YOUR TOP:</span>' + 1186 top.map(p => `<button onclick="loadQuickPrompt(${JSON.stringify(p.text||p)})" style="padding:4px 10px;border-radius:20px;font-size:11px;cursor:pointer;background:rgba(255,107,53,0.06);border:1px solid rgba(255,107,53,0.2);color:rgba(255,107,53,0.9);white-space:nowrap;max-width:200px;overflow:hidden;text-overflow:ellipsis">${(p.text||p).slice(0,40)}${(p.text||p).length>40?"...":""}</button>` 1187 ).join(''); 1188 } catch(_) {} 1189} 1190 1191function loadQuickPrompt(text) { 1192 const input = document.getElementById('promptInput'); 1193 if (input) { input.value = text; input.focus(); } 1194} 1195window.loadQuickPrompt = loadQuickPrompt; 1196 1197function toggleQuickPromptChips() { 1198 const chips = document.getElementById('quickPromptChips'); 1199 const btn = document.getElementById('quickPromptToggle'); 1200 if (!chips) return; 1201 const visible = chips.style.display === 'flex'; 1202 chips.style.display = visible ? 'none' : 'flex'; 1203 if (btn) btn.innerHTML = (visible ? '▶' : '▼') + ' Your Top Prompts'; 1204} 1205window.toggleQuickPromptChips = toggleQuickPromptChips; 1206 1207</script>
vendor: 1 bytes, line 1207
1207
1208<script> 1209(function(){ 1210var body=document.body; 1211function applyState(s){body.classList.remove("state-new","state-returning","state-post-query");body.classList.add(s);sessionStorage.setItem("forgeState",s);} 1212function updatePill(names){ 1213 var el=document.getElementById("sessionPillText"); 1214 var ex=document.getElementById("pillExpand"); 1215 if(!el)return; 1216 if(names&&names.length){ 1217 var txt=""; 1218 if(names.length===1){txt="Forge found your "+names[0]+" session â 6 more engines ready";} 1219 else if(names.length===2){txt="Forge found your "+names[0]+" and "+names[1]+" sessions";} 1220 else{txt="Forge found your "+names.slice(0,-1).join(", ")+" and "+names[names.length-1]+" sessions";} 1221 el.textContent=txt; 1222 if(ex){ex.textContent="+ add more minds";ex.style.display="inline";} 1223 } else { 1224 el.textContent="8 minds ready â no subscriptions required"; 1225 if(ex){ex.textContent="show minds âº";ex.style.display="inline";} 1226 } 1227} 1228window.toggleEngines=function(){ 1229 var p=document.querySelector(".perspectives"); 1230 var ex=document.getElementById("pillExpand"); 1231 if(!p)return; 1232 var hidden=window.getComputedStyle(p).display==="none"; 1233 p.style.display=hidden?"block":"none"; 1234 if(ex)ex.textContent=hidden?"hide minds â¹":"show minds âº"; 1235}; 1236function init(){ 1237 var auth=typeof Forge!=="undefined"&&Forge.isAuthenticated&&Forge.isAuthenticated(); 1238 var last=sessionStorage.getItem("forgeState"); 1239 if(auth){ 1240 // Restore a query that was typed before the user was asked to sign in 1241 try { 1242 var pendingQuery = localStorage.getItem('forge_pending_query'); 1243 if (pendingQuery) { 1244 localStorage.removeItem('forge_pending_query'); 1245 var restoreInput = document.getElementById('promptInput'); 1246 if (restoreInput && !restoreInput.value.trim()) restoreInput.value = pendingQuery; 1247 } 1248 } catch(e) {} 1249 // Restore diary context from "Use in Forge" 1250 try { 1251 var diaryCtx = JSON.parse(localStorage.getItem('forge_diary_context') || 'null'); 1252 if (diaryCtx && new URLSearchParams(window.location.search).get('from') === 'diary') { 1253 localStorage.removeItem('forge_diary_context'); 1254 var diaryInput = document.getElementById('promptInput'); 1255 if (diaryInput && !diaryInput.value.trim()) { 1256 diaryInput.value = diaryCtx.prompt || ('Tell me more about: ' + (diaryCtx.title || diaryCtx.content || '').slice(0, 120)); 1257 // Show context banner 1258 var banner = document.createElement('div'); 1259 banner.style.cssText = 'background:rgba(249,115,22,0.08);border:1px solid rgba(249,115,22,0.25);border-radius:10px;padding:10px 14px;font-size:12px;color:#f97316;margin-bottom:10px;display:flex;align-items:center;gap:8px;'; 1260 banner.innerHTML = '<span>💡</span><span><strong>From your Forge Diary:</strong> ' + (diaryCtx.title || (diaryCtx.content || '').slice(0, 80) + '...') + '</span>'; 1261 var inputWrap = diaryInput.closest('.prompt-wrap') || diaryInput.parentNode; 1262 if (inputWrap) inputWrap.insertBefore(banner, inputWrap.firstChild); 1263 } 1264 } 1265 } catch(e) {} 1266 var detected=[]; 1267 if(typeof connectedProviders!=="undefined"&&connectedProviders.size>0){connectedProviders.forEach(function(p){detected.push(p);});} 1268 updatePill(detected); 1269 applyState(last==="state-post-query"?"state-post-query":"state-returning"); 1270 }else{updatePill([]);applyState("state-new");showOnboardingIfNeeded();} 1271} 1272 1273function showOnboardingIfNeeded() { 1274 try { if (localStorage.getItem('forge_onboarded')) return; } catch(e) { return; } 1275 var overlay = document.createElement('div'); 1276 overlay.className = 'forge-onboard-overlay'; 1277 overlay.id = 'forgeOnboardOverlay'; 1278 var modal = document.createElement('div'); 1279 modal.className = 'forge-onboard-modal'; 1280 modal.innerHTML = '<div class="forge-onboard-modal__flame">ð¥</div>' 1281 + '<div class="forge-onboard-modal__title">What are you looking for today?</div>' 1282 + '<div class="forge-onboard-modal__sub">Weâll take you straight there. You can always explore the other mode later.</div>' 1283 + '<div class="forge-onboard-modal__choices">' 1284 + '<div class="forge-onboard-choice" id="onboard-sweep"><div class="forge-onboard-choice__icon">â¡</div><div class="forge-onboard-choice__title">Give me the best answer</div><div class="forge-onboard-choice__desc">8 AIs answer your question. Forge picks the strongest response â fast.</div></div>' 1285 + '<div class="forge-onboard-choice" id="onboard-persp"><div class="forge-onboard-choice__icon">ð§ </div><div class="forge-onboard-choice__title">Show me all perspectives</div><div class="forge-onboard-choice__desc">See how 8 different AIs approach the same question â side by side.</div></div>' 1286 + '</div>' 1287 + '<button class="forge-onboard-modal__skip" id="onboard-skip">Skip â Iâll explore on my own</button>'; 1288 overlay.appendChild(modal); 1289 document.body.appendChild(overlay); 1290 document.getElementById('onboard-sweep').onclick = function() { dismissOnboarding('sweep'); }; 1291 document.getElementById('onboard-persp').onclick = function() { dismissOnboarding('perspectives'); }; 1292 document.getElementById('onboard-skip').onclick = function() { dismissOnboarding(null); }; 1293} 1294window.showOnboardingIfNeeded = showOnboardingIfNeeded; 1295 1296function dismissOnboarding(choice) { 1297 try { localStorage.setItem('forge_onboarded', '1'); } catch(e) {}
1298 var overlay = document.getElementById('forgeOnboardOverlay'); 1299 if (overlay) overlay.remove(); 1300 if (choice === 'sweep') { 1301 window.location.href = '/broadcast.html'; 1302 } 1303 // 'perspectives' or null â stay on current page 1304} 1305window.dismissOnboarding = dismissOnboarding; 1306document.addEventListener("forge:first-response",function(){ 1307 applyState("state-post-query"); 1308 var el=document.getElementById("sessionPillText"); 1309 if(el)el.textContent="8 of 8 responded · AI perspectives ready"; 1310}); 1311var _cr=window.clearResults; 1312window.clearResults=function(){if(_cr)_cr();var a=typeof Forge!=="undefined"&&Forge.isAuthenticated&&Forge.isAuthenticated();applyState(a?"state-returning":"state-new");updatePill([]);}; 1313window.addEventListener("forge:signout",function(){applyState("state-new");updatePill([]);}); 1314window.addEventListener("forge:auth-expired",function(){applyState("state-new");updatePill([]);}); 1315if(document.readyState==="loading"){document.addEventListener("DOMContentLoaded",function(){setTimeout(init,300);});}else{setTimeout(init,300);} 1316})(); 1317</script>
vendor: 1 bytes, line 1317
1317
1318<script> 1319// ===== WELCOME MODAL ===== 1320function showWelcomeStep(n) { 1321 ['step1','step2','step3'].forEach(function(id,i) { 1322 var el = document.getElementById(id); 1323 if(el) el.style.display = i===n-1 ? 'flex' : 'none'; 1324 }); 1325} 1326function dismissModal() { 1327 ['step1','step2','step3'].forEach(function(id) { 1328 var el = document.getElementById(id); 1329 if(el) el.style.display = 'none'; 1330 }); 1331} 1332function completeOnboarding(prompt) { 1333 localStorage.setItem('forge_onboarded','true'); 1334 sessionStorage.setItem('forge_modal_complete','true'); 1335 dismissModal(); 1336 if(prompt) { 1337 location.href = '/perspectives.html?prompt=' + encodeURIComponent(prompt); 1338 } else { 1339 location.href = '/perspectives'; 1340 } 1341} 1342document.addEventListener('DOMContentLoaded', function() { 1343 document.querySelectorAll('.forge-modal__close').forEach(function(btn) { 1344 btn.addEventListener('click', dismissModal); 1345 }); 1346 var s1btn = document.querySelector('#step1 .forge-btn--primary'); 1347 if(s1btn) s1btn.addEventListener('click', function(e) { 1348 e.preventDefault(); 1349 window.open('https://chromewebstore.google.com/detail/forge/onlaamgggkmmnpbkcllnhdpecaidfpml','_blank'); 1350 setTimeout(function(){ showWelcomeStep(2); }, 1000); 1351 }); 1352 document.querySelectorAll('.forge-skip a').forEach(function(a) { 1353 a.addEventListener('click', function(){ showWelcomeStep(2); }); 1354 }); 1355 var s2btn = document.getElementById('step2-cta'); 1356 if(s2btn) s2btn.addEventListener('click', function(){ showWelcomeStep(3); }); 1357 var selPrompt = 'Should I use Claude or ChatGPT for my work?'; 1358 document.querySelectorAll('.forge-suggestion').forEach(function(btn) { 1359 btn.addEventListener('click', function() { 1360 document.querySelectorAll('.forge-suggestion').forEach(function(b){ b.classList.remove('forge-suggestion--selected'); }); 1361 btn.classList.add('forge-suggestion--selected'); 1362 selPrompt = btn.getAttribute('data-prompt'); 1363 }); 1364 }); 1365 var s3p = document.querySelector('#step3 .forge-btn--primary'); 1366 if(s3p) s3p.addEventListener('click', function(){ completeOnboarding(selPrompt); }); 1367 var s3g = document.querySelector('#step3 .forge-btn--ghost'); 1368 if(s3g) s3g.addEventListener('click', function(){ completeOnboarding(null); }); 1369 // Show modal for new users only â check onboarded flag FIRST 1370 var onboarded = localStorage.getItem('forge_onboarded') === 'true'; 1371 if(onboarded) return; // already onboarded â never show again 1372 // Check if this is a new user (registered in last 30 min) 1373 var u = typeof Forge !== 'undefined' ? Forge.getUser() : null; 1374 if(u) { 1375 var created = new Date(u.createdAt || u.created_at || 0); 1376 var ageMs = Date.now() - created.getTime(); 1377 if(ageMs < 30 * 60 * 1000) { 1378 // New user â but only show if NOT coming from modal completion 1379 var fromModal = sessionStorage.getItem('forge_modal_complete') === 'true'; 1380 if(!fromModal) { 1381 var isMobile = /Android|iPhone|iPad|iPod|Mobile/i.test(navigator.userAgent); 1382 var extInstalled = typeof chrome !== 'undefined' && chrome.runtime; 1383 if (isMobile) { 1384 showWelcomeStep(3); // Mobile â skip extension steps, go straight to first question 1385 } else { 1386 showWelcomeStep(extInstalled ? 2 : 1); 1387 } 1388 } 1389 } else { 1390 localStorage.setItem('forge_onboarded','true'); 1391 } 1392 } 1393}); 1394// ===== END WELCOME MODAL ===== 1395</script>
1395 1396 1397<!-- Welcome Modal Steps --> 1398 1399<div class="forge-overlay" id="step1" style="display:none"> 1400 <div class="forge-modal" role="dialog" aria-modal="true" aria-labelledby="step1-title"> 1401 1402 <div class="forge-modal__header"> 1403 <div class="forge-modal__logo"> 1404 <div class="forge-modal__logo-icon"> 1405 <svg viewBox="0 0 10 10" aria-hidden="true"><polygon points="5,1 9,9 1,9"/></svg> 1406 </div> 1407 <span class="forge-modal__logo-name">Forge</span> 1408 </div> 1409 <button class="forge-modal__close" aria-label="Close">×</button> 1410 </div> 1411 1412 <div class="forge-modal__body"> 1413 <div class="forge-modal__welcome">Welcome to Forge</div> 1414 <h1 class="forge-modal__title" id="step1-title"> 1415 Let's get you set up<br>in <span>60 seconds.</span> 1416 </h1> 1417 1418 <div class="forge-steps"> 1419 1420 <!-- Step 1: active --> 1421 <div class="forge-step"> 1422 <div class="forge-step__left"> 1423 <div class="forge-step__num forge-step__num--active">1</div> 1424 <div class="forge-step__connector"></div> 1425 </div> 1426 <div class="forge-step__right"> 1427 <div class="forge-step__label">Step 1 of 3</div> 1428 <div class="forge-step__name">Install Forge Dock</div> 1429 <div class="forge-step__desc"> 1430 Add the Chrome extension. Forge reads your existing AI sessions â 1431 no new accounts, no passwords required. 1432 </div> 1433 <div class="forge-ext-badge"> 1434 <div class="forge-ext-badge__icon" aria-hidden="true"></div> 1435 Forge Dock for Chrome 1436 </div> 1437 <button class="forge-btn forge-btn--primary" onclick="showStep(2)"> 1438 <!-- Replace onclick with actual Chrome Web Store link --> 1439 Add to Chrome â Free 1440 </button> 1441 </div> 1442 </div> 1443 1444 <!-- Step 2: pending --> 1445 <div class="forge-step"> 1446 <div class="forge-step__left"> 1447 <div class="forge-step__num forge-step__num--pending">2</div> 1448 <div class="forge-step__connector"></div> 1449 </div> 1450 <div class="forge-step__right" style="padding-top:3px"> 1451 <div class="forge-step__name forge-step__name--dim">Connect your AIs</div> 1452 </div> 1453 </div> 1454 1455 <!-- Step 3: pending --> 1456 <div class="forge-step"> 1457 <div class="forge-step__left"> 1458 <div class="forge-step__num forge-step__num--pending">3</div> 1459 </div> 1460 <div class="forge-step__right" style="padding-top:3px"> 1461 <div class="forge-step__name forge-step__name--dim">Ask your first question</div> 1462 </div> 1463 </div> 1464 1465 </div><!-- /forge-steps --> 1466 1467 <div class="forge-progress"> 1468 <div class="forge-progress__dot forge-progress__dot--active"></div> 1469 <div class="forge-progress__dot"></div> 1470 <div class="forge-progress__dot"></div> 1471 <span class="forge-progress__label">Step 1 of 3</span> 1472 </div> 1473 1474 <div class="forge-skip"> 1475 Already installed? 1476 <a onclick="showStep(2)">Skip to next step ›</a> 1477 </div> 1478 1479 </div><!-- /body --> 1480 </div><!-- /modal --> 1481</div><!-- /overlay --> 1482<div class="forge-overlay" id="step2" style="display:none"> 1483 <div class="forge-modal" role="dialog" aria-modal="true" aria-labelledby="step2-title"> 1484 1485 <div class="forge-modal__header"> 1486 <div class="forge-modal__logo"> 1487 <div class="forge-modal__logo-icon"> 1488 <svg viewBox="0 0 10 10" aria-hidden="true"><polygon points="5,1 9,9 1,9"/></svg> 1489 </div> 1490 <span class="forge-modal__logo-name">Forge</span> 1491 </div> 1492 <button class="forge-modal__close" aria-label="Close">×</button> 1493 </div> 1494 1495 <div class="forge-modal__body"> 1496 <div class="forge-modal__welcome">Step 2 of 3</div> 1497 <h1 class="forge-modal__title" id="step2-title"> 1498 Detecting your<br><span>AI sessions...</span> 1499 </h1> 1500 1501 <div class="forge-steps"> 1502 1503 <!-- Step 1: done --> 1504 <div class="forge-step"> 1505 <div class="forge-step__left"> 1506 <div class="forge-step__num forge-step__num--done">✓</div> 1507 <div class="forge-step__connector"></div> 1508 </div> 1509 <div class="forge-step__right" style="padding-top:3px"> 1510 <div class="forge-step__name forge-step__name--done">Forge Dock installed</div> 1511 </div> 1512 </div> 1513 1514 <!-- Step 2: active --> 1515 <div class="forge-step"> 1516 <div class="forge-step__left"> 1517 <div class="forge-step__num forge-step__num--active">2</div> 1518 <div class="forge-step__connector"></div> 1519 </div> 1520 <div class="forge-step__right"> 1521 <div class="forge-step__label">Step 2 of 3</div> 1522 <div class="forge-step__name">Your AIs detected</div> 1523 <div class="forge-step__desc"> 1524 Forge found these active sessions in your browser. 1525 Log into any AI below to add it. 1526 </div> 1527 1528 <!-- 1529 SESSION COUNT â update text dynamically: 1530 e.g. "4 of 8 AIs ready" as sessions are found. 1531 --> 1532 <div class="forge-session-count"> 1533 <div class="forge-session-count__dot" aria-hidden="true"></div> 1534 4 of 8 AIs ready 1535 </div> 1536 1537 <!-- 1538 AI GRID â add/remove forge-ai-chip--ready via JS 1539 when your extension posts session data back to the page. 1540 Each chip has a data-ai attribute for easy selection. 1541 --> 1542 <div class="forge-ai-grid"> 1543 1544 <div class="forge-ai-chip forge-ai-chip--ready" data-ai="claude"> 1545 <div class="forge-ai-chip__dot" style="background:var(--ai-claude)"></div>
1546 <span class="forge-ai-chip__name">Claude</span> 1547 <span class="forge-ai-chip__check">✓</span> 1548 </div> 1549 1550 <div class="forge-ai-chip forge-ai-chip--ready" data-ai="chatgpt"> 1551 <div class="forge-ai-chip__dot" style="background:var(--ai-chatgpt)"></div> 1552 <span class="forge-ai-chip__name">ChatGPT</span> 1553 <span class="forge-ai-chip__check">✓</span> 1554 </div> 1555 1556 <div class="forge-ai-chip forge-ai-chip--ready" data-ai="gemini"> 1557 <div class="forge-ai-chip__dot" style="background:var(--ai-gemini)"></div> 1558 <span class="forge-ai-chip__name">Gemini</span> 1559 <span class="forge-ai-chip__check">✓</span> 1560 </div> 1561 1562 <div class="forge-ai-chip forge-ai-chip--pending" data-ai="mistral"> 1563 <div class="forge-ai-chip__dot" style="background:var(--tx-muted)"></div> 1564 <span class="forge-ai-chip__name">Mistral</span> 1565 </div> 1566 1567 <div class="forge-ai-chip forge-ai-chip--pending" data-ai="grok"> 1568 <div class="forge-ai-chip__dot" style="background:var(--tx-muted)"></div> 1569 <span class="forge-ai-chip__name">Grok</span> 1570 </div> 1571 1572 <div class="forge-ai-chip forge-ai-chip--pending" data-ai="deepseek"> 1573 <div class="forge-ai-chip__dot" style="background:var(--tx-muted)"></div> 1574 <span class="forge-ai-chip__name">DeepSeek</span> 1575 </div> 1576 1577 <div class="forge-ai-chip forge-ai-chip--ready" data-ai="perplexity"> 1578 <div class="forge-ai-chip__dot" style="background:var(--ai-perplexity)"></div> 1579 <span class="forge-ai-chip__name">Perplexity</span> 1580 <span class="forge-ai-chip__check">✓</span> 1581 </div> 1582 1583 <div class="forge-ai-chip forge-ai-chip--pending" data-ai="meta"> 1584 <div class="forge-ai-chip__dot" style="background:var(--tx-muted)"></div> 1585 <span class="forge-ai-chip__name">Meta AI</span> 1586 </div> 1587 1588 </div><!-- /forge-ai-grid --> 1589 </div> 1590 </div> 1591 1592 <!-- Step 3: pending --> 1593 <div class="forge-step"> 1594 <div class="forge-step__left"> 1595 <div class="forge-step__num forge-step__num--pending">3</div> 1596 </div> 1597 <div class="forge-step__right" style="padding-top:3px"> 1598 <div class="forge-step__name forge-step__name--dim">Ask your first question</div> 1599 </div> 1600 </div> 1601 1602 </div><!-- /forge-steps --> 1603 1604 <!-- 1605 CTA text updates dynamically based on ready count: 1606 "Continue â 4 AIs ready" 1607 Disable button if readyCount < 1. 1608 --> 1609 <button class="forge-btn forge-btn--primary" id="step2-cta" onclick="showStep(3)"> 1610 Continue â 4 AIs ready → 1611 </button> 1612 1613 <div class="forge-progress"> 1614 <div class="forge-progress__dot forge-progress__dot--done"></div> 1615 <div class="forge-progress__dot forge-progress__dot--active"></div> 1616 <div class="forge-progress__dot"></div> 1617 <span class="forge-progress__label">Step 2 of 3</span> 1618 </div> 1619 1620 </div><!-- /body --> 1621 </div><!-- /modal --> 1622</div><!-- /overlay --> 1623<div class="forge-overlay" id="step3" style="display:none"> 1624 <div class="forge-modal" role="dialog" aria-modal="true" aria-labelledby="step3-title"> 1625 1626 <div class="forge-modal__header"> 1627 <div class="forge-modal__logo"> 1628 <div class="forge-modal__logo-icon"> 1629 <svg viewBox="0 0 10 10" aria-hidden="true"><polygon points="5,1 9,9 1,9"/></svg> 1630 </div> 1631 <span class="forge-modal__logo-name">Forge</span> 1632 </div> 1633 <button class="forge-modal__close" aria-label="Close">×</button> 1634 </div> 1635 1636 <div class="forge-modal__body"> 1637 <div class="forge-modal__welcome">Step 3 of 3 â you're ready</div> 1638 <h1 class="forge-modal__title" id="step3-title"> 1639 <span>4 AIs ready.</span><br>Ask your first question. 1640 </h1> 1641 1642 <div class="forge-steps"> 1643 1644 <!-- Step 1: done --> 1645 <div class="forge-step"> 1646 <div class="forge-step__left"> 1647 <div class="forge-step__num forge-step__num--done">✓</div> 1648 <div class="forge-step__connector"></div> 1649 </div> 1650 <div class="forge-step__right" style="padding-top:3px"> 1651 <div class="forge-step__name forge-step__name--done">Forge Dock installed</div> 1652 </div> 1653 </div> 1654 1655 <!-- Step 2: done --> 1656 <div class="forge-step"> 1657 <div class="forge-step__left"> 1658 <div class="forge-step__num forge-step__num--done">✓</div> 1659 <div class="forge-step__connector"></div> 1660 </div> 1661 <div class="forge-step__right" style="padding-top:3px"> 1662 <div class="forge-step__name forge-step__name--done">4 AIs connected</div> 1663 </div> 1664 </div> 1665 1666 <!-- Step 3: active --> 1667 <div class="forge-step"> 1668 <div class="forge-step__left"> 1669 <div class="forge-step__num forge-step__num--active">3</div> 1670 </div> 1671 <div class="forge-step__right"> 1672 <div class="forge-step__label">Step 3 of 3</div> 1673 <div class="forge-step__name">Try a sample question</div> 1674 <div class="forge-step__desc"> 1675 Tap one below or type your own â all 4 AIs answer simultaneously. 1676 </div> 1677 1678 <!-- 1679 SUGGESTED PROMPTS 1680 On click: add forge-suggestion--selected, store value, 1681 update CTA to "Get Perspectives â [truncated question]" 1682 --> 1683 <div class="forge-suggestions"> 1684 <button class="forge-suggestion forge-suggestion--selected" data-prompt="Should I use Claude or ChatGPT for my work?"> 1685 Should I use Claude or ChatGPT for my work? 1686 </button> 1687 <button class="forge-suggestion" data-prompt="What is the best programming language to learn in 2026?"> 1688 What is the best programming language to learn in 2026? 1689 </button> 1690 <button class="forge-suggestion" data-prompt="Summarise the pros and cons of remote work."> 1691 Summarise the pros and cons of remote work. 1692 </button> 1693 </div> 1694 1695 </div> 1696 </div> 1697 1698 </div><!-- /forge-steps --> 1699 1700 <!-- 1701 Primary CTA: closes modal, pre-fills workspace input 1702 with the selected suggestion, fires Get Perspectives. 1703 Set localStorage.forge_onboarded = 'true' on click. 1704 --> 1705 <button class="forge-btn forge-btn--primary"> 1706 Get Perspectives â all 4 AIs 1707 </button> 1708 1709 <!-- 1710 Ghost CTA: closes modal without pre-filling a question. 1711 User lands on the clean workspace (State 2). 1712 Still set localStorage.forge_onboarded = 'true'. 1713 --> 1714 <button class="forge-btn forge-btn--ghost"> 1715 Go to workspace instead 1716 </button> 1717 1718 <div class="forge-progress"> 1719 <div class="forge-progress__dot forge-progress__dot--done"></div> 1720 <div class="forge-progress__dot forge-progress__dot--done"></div> 1721 <div class="forge-progress__dot forge-progress__dot--active"></div>
1722 <span class="forge-progress__label">All set</span> 1723 </div> 1724 1725 </div><!-- /body --> 1726 </div><!-- /modal --> 1727</div><!-- /overlay --> 1728
1729<script> 1730(function() { 1731 // Role badge â shown for admin and super_admin users 1732 var token = (document.cookie.match(/forge_token=([^;]+)/)||[])[1] 1733 || localStorage.getItem('forge_token') 1734 || (sessionStorage.getItem('forge_auth') && JSON.parse(sessionStorage.getItem('forge_auth') || '{}').token); 1735 if (!token) return; 1736 1737 fetch((window.location.hostname==='localhost'||window.location.hostname==='127.0.0.1'?'http://localhost:3001':'https://api.projectcoachai.com') + '/api/auth/me', { headers: { 'Authorization': 'Bearer ' + token } }) 1738 .then(function(r) { return r.json(); }) 1739 .then(function(d) { 1740 var role = d.user?.role || d.role; 1741 if (!role || role === 'user') return; 1742 var isSuperAdmin = role === 'super_admin'; 1743 var badge = document.createElement('div'); 1744 badge.id = 'forge-role-badge'; 1745 badge.innerHTML = isSuperAdmin ? '👑 Super Admin' : '🛡 Admin'; 1746 badge.style.cssText = [ 1747 'position:fixed', 1748 'top:12px', 1749 'right:16px', 1750 'z-index:9999', 1751 'padding:5px 12px', 1752 'border-radius:20px', 1753 'font-size:11px', 1754 'font-weight:700', 1755 'letter-spacing:.5px', 1756 'font-family:DM Sans,sans-serif', 1757 'cursor:pointer', 1758 isSuperAdmin 1759 ? 'background:rgba(249,115,22,0.15);border:1px solid rgba(249,115,22,0.4);color:#f97316' 1760 : 'background:rgba(99,102,241,0.15);border:1px solid rgba(99,102,241,0.4);color:#818cf8', 1761 ].join(';'); 1762 badge.title = 'Go to Command Center'; 1763 badge.onclick = function() { window.location.href = '/command-center.html'; }; 1764 document.body.appendChild(badge); 1765 }) 1766 .catch(function() {}); 1767})(); 1768</script>
1768 1769 1770<!-- mob-nav-close -->
1770<script> 1771(function(){ 1772 // Close mobile nav when any drawer link is clicked 1773 var drawer = document.getElementById('mobNavDrawer'); 1774 if (drawer) { 1775 drawer.querySelectorAll('a').forEach(function(a){ 1776 a.addEventListener('click', function(){ drawer.classList.remove('open'); }); 1777 }); 1778 } 1779 // Close on outside click 1780 document.addEventListener('click', function(e){ 1781 if (!drawer) return; 1782 var btn = document.querySelector('.mob-nav-btn'); 1783 if (drawer.classList.contains('open') && !drawer.contains(e.target) && btn && !btn.contains(e.target)) 1784 drawer.classList.remove('open'); 1785 }); 1786})(); 1787 1788function autoResizePrompt(el) { 1789 el.style.height = 'auto'; 1790 el.style.height = Math.min(el.scrollHeight, 400) + 'px'; 1791 el.style.overflowY = el.scrollHeight > 400 ? 'auto' : 'hidden'; 1792} 1793// Wire autoResize on page load 1794document.addEventListener('DOMContentLoaded', function() { 1795 var ta = document.getElementById('promptInput'); 1796 if (ta) { 1797 ta.addEventListener('input', function() { autoResizePrompt(ta); }); 1798 autoResizePrompt(ta); 1799 } 1800}); 1801</script>
1801 1802<!-- <div id="forgThemePicker" style="display:none;position:fixed;top:52px;right:8px;z-index:9999;background:#111118;border:1px solid rgba(255,255,255,0.1);border-radius:12px;padding:12px;flex-wrap:wrap;gap:8px;width:200px;box-shadow:0 8px 32px rgba(0,0,0,0.5)"> 1803 <div style="font-size:9px;font-weight:700;color:#6b6b88;text-transform:uppercase;letter-spacing:1px;width:100%;margin-bottom:4px">Dark</div> 1804 <button onclick="setForgeTheme('dark')" style="width:30px;height:30px;border-radius:50%;background:#09090f;border:2px solid #ff6b35;cursor:pointer" title="Dark"></button> 1805 <button onclick="setForgeTheme('slate')" style="width:30px;height:30px;border-radius:50%;background:#0c0d10;border:2px solid #94a3b8;cursor:pointer" title="Slate"></button> 1806 <button onclick="setForgeTheme('midnight')" style="width:30px;height:30px;border-radius:50%;background:#0a0a1a;border:2px solid #7c6bff;cursor:pointer" title="Midnight"></button> 1807 <button onclick="setForgeTheme('plum')" style="width:30px;height:30px;border-radius:50%;background:#0f0810;border:2px solid #c084fc;cursor:pointer" title="Plum"></button> 1808 <div style="font-size:9px;font-weight:700;color:#6b6b88;text-transform:uppercase;letter-spacing:1px;width:100%;margin-top:6px;margin-bottom:4px">Light</div> 1809 <button onclick="setForgeTheme('light')" style="width:30px;height:30px;border-radius:50%;background:#f8f9fc;border:2px solid #ff6b35;cursor:pointer" title="Light"></button> 1810 <button onclick="setForgeTheme('sand')" style="width:30px;height:30px;border-radius:50%;background:#faf7f2;border:2px solid #d4640a;cursor:pointer" title="Sand"></button> 1811 <button onclick="setForgeTheme('forest')" style="width:30px;height:30px;border-radius:50%;background:#0a0f0a;border:2px solid #4caf50;cursor:pointer" title="Forest"></button> 1812 <button onclick="setForgeTheme('ember')" style="width:30px;height:30px;border-radius:50%;background:#0f0a06;border:2px solid #f59e0b;cursor:pointer" title="Ember"></button> 1813</div> 1814--> 1815<div id="__forge_bridge__" style="display:none"></div> 1816<div id="plModal" class="modal-overlay" onclick="if(event.target===this)closePL()" style="display:none"> 1817 <div class="modal" style="max-width:560px"> 1818 <div class="modal-hdr"><div class="modal-title">📚 Prompt Library</div><button class="modal-x" onclick="closePL()">✕</button></div> 1819 <input class="pl-search" id="plSearch" placeholder="Search prompts..." oninput="filterPL()"/> 1820 <div class="pl-list" id="plList"></div> 1821 </div> 1822</div>
1823<script> 1824(function() { 1825 var recognition = null; 1826 var isListening = false; 1827 1828 window.toggleMic = function() { 1829 var btn = document.getElementById('micBtn'); 1830 var SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition; 1831 if (!SpeechRecognition) { 1832 alert('Voice input is not supported in this browser. Try Chrome.'); 1833 return; 1834 } 1835 if (isListening) { 1836 if (recognition) recognition.stop(); 1837 return; 1838 } 1839 recognition = new SpeechRecognition(); 1840 recognition.continuous = true; 1841 recognition.interimResults = true; 1842 recognition.lang = 'en-US'; 1843 1844 recognition.onstart = function() { 1845 isListening = true; 1846 if (btn) btn.style.color = '#f97316'; 1847 if (btn) btn.style.animation = 'micPulse 1s infinite'; 1848 }; 1849 recognition.onresult = function(e) { 1850 var final = ''; 1851 var interim = ''; 1852 for (var i = 0; i < e.results.length; i++) { 1853 if (e.results[i].isFinal) { 1854 var t = e.results[i][0].transcript.trim(); 1855 // Capitalise first letter 1856 t = t.charAt(0).toUpperCase() + t.slice(1); 1857 // Add punctuation if missing 1858 if (t && !/[.!?]$/.test(t)) { 1859 t = t.endsWith('?') ? t : (t.toLowerCase().startsWith('what') || t.toLowerCase().startsWith('how') || t.toLowerCase().startsWith('why') || t.toLowerCase().startsWith('when') || t.toLowerCase().startsWith('where') || t.toLowerCase().startsWith('who') || t.toLowerCase().startsWith('which') || t.toLowerCase().startsWith('can') || t.toLowerCase().startsWith('do') || t.toLowerCase().startsWith('is') || t.toLowerCase().startsWith('are') || t.toLowerCase().startsWith('will') || t.toLowerCase().startsWith('should') ? t + '?' : t + '.'); 1860 } 1861 final += t + ' '; 1862 } else { 1863 interim += e.results[i][0].transcript; 1864 } 1865 } 1866 var input = document.getElementById('promptInput'); 1867 if (input) { 1868 input.value = (final + interim).trim(); 1869 if (typeof autoResizePrompt === 'function') autoResizePrompt(input); 1870 if (typeof updateCounter === 'function') updateCounter(); 1871 } 1872 }; 1873 recognition.onend = function() { 1874 isListening = false; 1875 if (btn) { btn.style.color = ''; btn.style.animation = ''; } 1876 }; 1877 recognition.onerror = function() { 1878 isListening = false; 1879 if (btn) { btn.style.color = ''; btn.style.animation = ''; } 1880 }; 1881 recognition.start(); 1882 }; 1883})(); 1884</script>
1884 1885<style> 1886@keyframes micPulse { 1887 0%, 100% { opacity: 1; } 1888 50% { opacity: 0.4; } 1889} 1890</style>
1891<script> 1892function togglePickerV4() { 1893 var btn = document.getElementById('moreMindsBtn'); 1894 var modal = document.getElementById('v4PickerModal'); 1895 var wrap = document.querySelector('.prompt-wrap'); 1896 if (!modal) return; 1897 var isOpen = modal.style.display === 'block'; 1898 if (isOpen) { 1899 modal.style.display = 'none'; 1900 if (btn) btn.textContent = '+'; 1901 } else { 1902 renderV4Picker(); 1903 modal.style.display = 'block'; 1904 if (btn) btn.textContent = 'Ã'; 1905 // Position below the + button using page coordinates 1906 if (btn) { 1907 var rect = btn.getBoundingClientRect(); 1908 modal.style.display = 'block'; 1909 var modalW = 240; 1910 modal.style.width = modalW + 'px'; 1911 var scrollY = window.pageYOffset || document.documentElement.scrollTop; 1912 var left = Math.min(rect.right - modalW, window.innerWidth - modalW - 8); 1913 modal.style.left = Math.max(8, left) + 'px'; 1914 modal.style.top = (rect.bottom + scrollY + 8) + 'px'; 1915 } 1916 } 1917} 1918 1919function renderV4Picker() { 1920 var list = document.getElementById('v4PickerList'); 1921 if (!list || typeof Forge === 'undefined' || !Forge.PROVIDERS) return; 1922 list.innerHTML = Forge.PROVIDERS.map(function(p) { 1923 var isSel = typeof selectedProviders !== 'undefined' && selectedProviders.has(p.id); 1924 return '<div onclick="toggleV4Provider(\'' + p.id + '\')" style="display:flex;align-items:center;justify-content:space-between;padding:6px 10px;border-radius:8px;cursor:pointer;border:1px solid ' + (isSel ? p.color + '66' : 'rgba(255,255,255,0.06)') + ';background:' + (isSel ? p.color + '18' : 'transparent') + ';margin-bottom:2px" id="v4chip-' + p.id + '">' + 1925 '<span style="display:flex;align-items:center;gap:7px;font-size:12px;color:' + (isSel ? p.color : '#888') + '"><span style="width:7px;height:7px;border-radius:50%;background:' + p.color + ';display:inline-block"></span>' + p.name + '</span>' + 1926 (isSel ? '<span style="font-size:10px;color:' + p.color + '">â On</span>' : '') + 1927 '</div>'; 1928 }).join(''); 1929} 1930 1931function toggleV4Provider(id) { 1932 var modal = document.getElementById('v4PickerModal'); 1933 if (typeof toggleProvider === 'function') toggleProvider(id); 1934 // Keep modal open and re-render 1935 if (modal) modal.style.display = 'block'; 1936 setTimeout(function() { 1937 renderV4Picker(); 1938 if (modal) modal.style.display = 'block'; 1939 }, 50); 1940} 1941window.toggleV4Provider = toggleV4Provider; 1942 1943// Close on outside click 1944document.addEventListener('click', function(e) { 1945 var modal = document.getElementById('v4PickerModal'); 1946 var btn = document.getElementById('moreMindsBtn'); 1947 if (!modal || modal.style.display !== 'block') return; 1948 if (!modal.contains(e.target) && e.target !== btn) { 1949 modal.style.display = 'none'; 1950 if (btn) btn.textContent = '+'; 1951 } 1952}); 1953document.addEventListener('click', function(e) { 1954 var picker = document.getElementById('providerPicker'); 1955 var btn = document.getElementById('moreMindsBtn'); 1956 if (!picker || picker.style.display === 'none') return; 1957 if (!picker.contains(e.target) && e.target !== btn) { 1958 picker.style.display = 'none'; 1959 if (btn) btn.textContent = '+ more'; 1960 } 1961}); 1962</script>
vendor: 1 bytes, line 1962
1962
1963<script> 1964function toggleSidebar() { 1965 var sb = document.getElementById('v4Sidebar'); 1966 var ov = document.getElementById('v4SidebarOverlay'); 1967 var isOpen = sb.style.display === 'flex'; 1968 sb.style.display = isOpen ? 'none' : 'flex'; 1969 sb.style.flexDirection = 'column'; 1970 ov.style.display = isOpen ? 'none' : 'block'; 1971 if (!isOpen) { loadSidebarRecents(); loadSidebarPromo(); } 1972} 1973 1974function loadSidebarPromo() { 1975 var allPromos = [ 1976 { icon: 'ð', label: 'PDF â Excel', title: 'Offers arrive as PDFs.', sub: 'Extract every line item to Excel in one click.', link: '/documents.html', cta: 'Try it now â' }, 1977 { icon: 'ð', label: 'Excel Intelligence', title: '1 billion Excel users.', sub: 'Ask 8 AI minds what your data means.', link: '/excel.html', cta: 'Analyse your data â' }, 1978 { icon: 'â¡', label: 'Quick Answer', title: 'One tab. Eight AIs.', sub: 'Switch between ChatGPT, Claude, Gemini and more without opening new tabs.', link: '/quick-chat.html', cta: 'Try Quick Answer â' }, 1979 { icon: 'ð¥', label: 'Forge Diary', title: 'Never lose an AI insight.', sub: 'Every response saved, searchable, and shareable. Your AI memory layer.', link: '/diary.html', cta: 'Open your Diary â' } 1980 ]; 1981 // Rotate promos â show Quick Answer or Diary if not seen recently 1982 var seen = []; 1983 try { seen = JSON.parse(localStorage.getItem('forge_promo_seen') || '[]'); } catch(e) {} 1984 var unseen = allPromos.filter(function(p) { return !seen.includes(p.label); }); 1985 if (unseen.length < 2) { seen = []; unseen = allPromos; try { localStorage.removeItem('forge_promo_seen'); } catch(e) {} } 1986 var promo = unseen[0]; 1987 var promo2 = unseen[1]; 1988 try { localStorage.setItem('forge_promo_seen', JSON.stringify(seen.concat([promo.label, promo2.label]))); } catch(e) {} 1989 var promos = [promo, promo2]; 1990 var el = document.getElementById('sidebarPromoContent'); 1991 if (!el) return; 1992 function promoCard(p, idSuffix) { 1993 return '<div style="background:rgba(255,255,255,0.03);border:1px solid rgba(255,255,255,0.06);border-left:3px solid #f97316;border-radius:8px;padding:10px 12px;margin-bottom:' + (idSuffix==='1'?'10px':'0') + '">' + 1994 '<div style="display:flex;align-items:center;gap:6px;margin-bottom:5px">' + 1995 '<span style="font-size:16px">' + p.icon + '</span>' + 1996 '<span style="font-size:11px;font-weight:800;letter-spacing:0.5px;text-transform:uppercase;color:#f97316">' + p.label + '</span>' + 1997 '</div>' + 1998 '<div style="font-size:14px;font-weight:800;color:#fff;margin-bottom:3px;line-height:1.3">' + p.title + '</div>' + 1999 '<div style="font-size:12px;color:#aaa;margin-bottom:10px;line-height:1.45">' + p.sub + '</div>' + 2000 '<a id="promoCtaLink' + idSuffix + '" href="' + p.link + '" style="display:inline-flex;align-items:center;justify-content:center;width:100%;padding:7px 12px;background:#f97316;color:#fff;border-radius:6px;font-size:12px;font-weight:700;text-decoration:none;box-sizing:border-box">' + p.cta + '</a>' + 2001 '</div>'; 2002 } 2003 el.innerHTML = promoCard(promo, '1') + promoCard(promo2, '2'); 2004 // Wire promo CTA auth check 2005 ['promoCtaLink1','promoCtaLink2'].forEach(function(id) { 2006 var link = document.getElementById(id); 2007 if (link) link.addEventListener('click', function(e) { if (!requireAuthModal()) e.preventDefault(); }); 2008 }); 2009 // Wire Documents link auth check 2010 var docsLink = document.getElementById('sidebarDocsLink'); 2011 if (docsLink) { 2012 docsLink.onclick = null; 2013 docsLink.addEventListener('click', function(e) { if (!requireAuthModal()) e.preventDefault(); }); 2014 } 2015} 2016 2017function loadSidebarRecents() { 2018 var list = document.getElementById('sidebarRecentList'); 2019 if (!list) return; 2020 var recents = JSON.parse(localStorage.getItem('forge_recent_queries') || '[]'); 2021 if (!recents.length) { 2022 list.innerHTML = '<div style="font-size:12px;color:#555;padding:8px 10px">No recent queries yet</div>'; 2023 return; 2024 } 2025 list.innerHTML = recents.slice(0,20).map(function(q, i) { 2026 return '<div class="sidebar-item" style="display:flex;align-items:center;justify-content:space-between;gap:6px">' + 2027 '<span onclick="loadRecentQuery(' + JSON.stringify(q) + ')" style="flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;cursor:pointer">' + q.substring(0,45) + (q.length>45?'...':'') + '</span>' + 2028 '<button onclick="deleteRecentQuery(' + i + ')" style="background:none;border:none;color:#555;
2028cursor:pointer;font-size:14px;flex-shrink:0;padding:0 2px;line-height:1" title="Delete">Ã</button>' + 2029 '</div>'; 2030 }).join(''); 2031} 2032 2033function loadRecentQuery(q) { 2034 var input = document.getElementById('promptInput'); 2035 if (input) { 2036 input.value = q; 2037 if (typeof autoResizePrompt === 'function') autoResizePrompt(input); 2038 if (typeof updateCounter === 'function') updateCounter(); 2039 } 2040 toggleSidebar(); 2041} 2042window.loadRecentQuery = loadRecentQuery; 2043 2044// Auth modal trigger 2045function showStep(n) { 2046 ['step1','step2','step3'].forEach(function(id, i) { 2047 var el = document.getElementById(id); 2048 if (el) el.style.display = i === n - 1 ? 'flex' : 'none'; 2049 }); 2050 ['tab1','tab2','tab3'].forEach(function(id, i) { 2051 var el = document.getElementById(id); 2052 if (el) { el.style.background = i === n - 1 ? '#E8652A' : 'transparent'; el.style.color = i === n - 1 ? '#fff' : '#888'; } 2053 }); 2054} 2055window.showStep = showStep; 2056 2057function requireAuthModal() { 2058 var signedinEl = document.getElementById('v4-cta-signedin'); 2059 var isLoggedIn = signedinEl && (signedinEl.style.display === 'block' || signedinEl.style.display === 'flex'); 2060 if (!isLoggedIn) { 2061 // Allow up to 2 free anonymous tries before gating â runCompare() in home.js increments the counter 2062 var freeTryCount = 0; 2063 try { freeTryCount = parseInt(localStorage.getItem('forge_anon_free_count') || '0'); } catch(e) {} 2064 if (freeTryCount < 2) return true; 2065 // Save the typed query so it can be restored after signin/signup â otherwise it's lost entirely 2066 var pendingInput = document.getElementById('promptInput'); 2067 if (pendingInput && pendingInput.value.trim()) { 2068 try { localStorage.setItem('forge_pending_query', pendingInput.value.trim()); } catch(e) {} 2069 } 2070 window.location.href = '/signin.html?return=' + encodeURIComponent('/perspectives'); 2071 return false; 2072 } 2073 return true; 2074} 2075window.requireAuthModal = requireAuthModal; 2076 2077function deleteRecentQuery(index) { 2078 var recents = JSON.parse(localStorage.getItem('forge_recent_queries') || '[]'); 2079 recents.splice(index, 1); 2080 localStorage.setItem('forge_recent_queries', JSON.stringify(recents)); 2081 loadSidebarRecents(); 2082} 2083window.deleteRecentQuery = deleteRecentQuery; 2084 2085function filterSidebar(val) { 2086 var list = document.getElementById('sidebarRecentList'); 2087 if (!list) return; 2088 var recents = JSON.parse(localStorage.getItem('forge_recent_queries') || '[]'); 2089 var filtered = val ? recents.filter(function(q){ return q.toLowerCase().includes(val.toLowerCase()); }) : recents; 2090 list.innerHTML = filtered.slice(0,20).map(function(q) { 2091 return '<div onclick="loadRecentQuery(' + JSON.stringify(q) + ')" style="padding:8px 10px;border-radius:8px;font-size:12px;color:#aaa;cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis" onmouseover=\'this.style.background=\"rgba(255,255,255,0.05)\"\' onmouseout=\'this.style.background=\"none\"\' >' + q.substring(0,50) + (q.length>50?'...':'') + '</div>'; 2092 }).join('') || '<div style="font-size:12px;color:#555;padding:8px 10px">No results</div>'; 2093} 2094 2095// Save query to recent when Get Perspectives is clicked 2096document.addEventListener('DOMContentLoaded', function() { 2097 setTimeout(function() { 2098 var btn = document.getElementById('compareBtn'); 2099 if (btn) { 2100 btn.addEventListener('click', function(e) { 2101 if (!requireAuthModal()) { e.stopImmediatePropagation(); return; } 2102 var input = document.getElementById('promptInput'); 2103 if (input && input.value.trim()) { 2104 var recents = JSON.parse(localStorage.getItem('forge_recent_queries') || '[]'); 2105 recents = recents.filter(function(q){ return q !== input.value.trim(); }); 2106 recents.unshift(input.value.trim()); 2107 localStorage.setItem('forge_recent_queries', JSON.stringify(recents.slice(0,50))); 2108 } 2109 }); 2110 } 2111 }, 500); 2112}); 2113</script>
vendor: 1 bytes, line 2113
2113
2114<script> 2115(async function() { 2116 if (typeof Forge === 'undefined') return; 2117 try { 2118 var user = await Forge.restoreSession(); 2119 if (user) { 2120 var out = document.getElementById('v4-cta-signedout'); 2121 var inn = document.getElementById('v4-cta-signedin'); 2122 var strip = document.getElementById('installStrip'); 2123 if (out) out.style.display = 'none'; 2124 if (inn) inn.style.display = 'block'; 2125 if (strip) strip.style.display = 'none'; 2126 var logout = document.getElementById('sidebarLogout'); 2127 if (logout) logout.style.display = 'block'; 2128 var welcome = document.getElementById('v4-welcome'); 2129 if (welcome) { 2130 var age = user.created_at ? (Date.now() - new Date(user.created_at).getTime()) : 99999999; 2131 var isNew = age < 30 * 60 * 1000; 2132 var name = (user.name || user.email || 'there').split(' ')[0]; 2133 welcome.textContent = (isNew ? 'Welcome, ' : 'Welcome back, ') + name; 2134 } 2135 } 2136 } catch(e) {} 2137})(); 2138</script>
vendor: 1 bytes, line 2138
2138
2139<script type="module" src="https://static.cloudflareinsights.com/beacon.min.js/v31edd6df95cf4e85bb4c19e7a9bdbcba1788362987495" integrity="sha512-iIg7k2xntmwu6/uSb5tpc/hySgZc4eoL31yB29W6tJFo2akwjPWcEqnCEdJvGexCL0KEQwVYv5BlowfhVz26hg==" data-cf-beacon='{"version":"2024.11.0","token":"4cfb390dbfb74417aa12b4d282f2d7bb","r":1,"spa":2}' crossorigin="anonymous"></script>
vendor: 1 bytes, line 2139
2139
2140<script>(function(){function c(){var b=a.contentDocument||(a.contentWindow&&a.contentWindow.document);if(b){var d=b.createElement('script');d.innerHTML="window.__CF$cv$params={r:'a43ffec77babeaf3',t:'MTc5MDkwNTE4Ng=='};var a=document.createElement('script');a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);";b.getElementsByTagName('head')[0].appendChild(d)}}if(document.body){var a=document.createElement('iframe');a.height=1;a.width=1;a.style.position='absolute';a.style.top=0;a.style.left=0;a.style.border='none';a.style.visibility='hidden';document.body.appendChild(a);if('loading'!==document.readyState)c();else if(window.addEventListener)document.addEventListener('DOMContentLoaded',c);else{var e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);'loading'!==document.readyState&&(document.onreadystatechange=e,c())}}}})();</script>
2140</body> 2141</html> 2142 2143
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.