Spaces:
Sleeping
Sleeping
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8" /> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
| <title>MeetIQ β Business Meeting Preparation Agent</title> | |
| <link rel="preconnect" href="https://fonts.googleapis.com" /> | |
| <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> | |
| <link href="https://fonts.googleapis.com/css2?family=Syne:wght@400;600;700;800&family=DM+Sans:ital,wght@0,300;0,400;0,500;1,300&display=swap" rel="stylesheet" /> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/marked/9.1.6/marked.min.js"></script> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js"></script> | |
| <style> | |
| /* ββ Reset & tokens βββββββββββββββββββββββββββββββββββββββββββββββββββ */ | |
| *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } | |
| :root { | |
| --bg: #05091a; | |
| --surface: #0b1228; | |
| --glass: rgba(255,255,255,0.04); | |
| --glass-b: rgba(255,255,255,0.08); | |
| --glass-hover: rgba(255,255,255,0.07); | |
| --blue: #3b82f6; | |
| --blue-glow: #60a5fa; | |
| --blue-dim: #1d4ed8; | |
| --cyan: #06b6d4; | |
| --violet: #7c3aed; | |
| --violet-light: #a78bfa; | |
| --green: #10b981; | |
| --yellow: #f59e0b; | |
| --red: #f43f5e; | |
| --txt: #f0f4ff; | |
| --txt-m: #94a3b8; | |
| --txt-f: #475569; | |
| --r: 16px; | |
| --r-sm: 10px; | |
| } | |
| html { scroll-behavior: smooth; } | |
| body { | |
| font-family: 'DM Sans', sans-serif; | |
| background: var(--bg); | |
| color: var(--txt); | |
| min-height: 100vh; | |
| overflow-x: hidden; | |
| } | |
| /* ββ Animated background ββββββββββββββββββββββββββββββββββββββββββββββ */ | |
| .bg-canvas { | |
| position: fixed; inset: 0; z-index: 0; | |
| overflow: hidden; pointer-events: none; | |
| } | |
| .bg-canvas::before { | |
| content: ''; position: absolute; | |
| width: 900px; height: 900px; border-radius: 50%; | |
| background: radial-gradient(circle, rgba(59,130,246,.13) 0%, transparent 70%); | |
| top: -300px; left: -200px; | |
| animation: drift1 18s ease-in-out infinite alternate; | |
| } | |
| .bg-canvas::after { | |
| content: ''; position: absolute; | |
| width: 700px; height: 700px; border-radius: 50%; | |
| background: radial-gradient(circle, rgba(6,182,212,.08) 0%, transparent 70%); | |
| bottom: -200px; right: -100px; | |
| animation: drift2 22s ease-in-out infinite alternate; | |
| } | |
| .bg-orb3 { | |
| position: absolute; width: 500px; height: 500px; border-radius: 50%; | |
| background: radial-gradient(circle, rgba(124,58,237,.09) 0%, transparent 70%); | |
| top: 50%; left: 55%; transform: translate(-50%,-50%); | |
| animation: drift3 25s ease-in-out infinite alternate; | |
| } | |
| @keyframes drift1 { to { transform: translate(80px,60px) scale(1.1); } } | |
| @keyframes drift2 { to { transform: translate(-60px,-80px) scale(1.15); } } | |
| @keyframes drift3 { to { transform: translate(-45%,-55%) scale(.9); } } | |
| .bg-grid { | |
| position: absolute; inset: 0; | |
| background-image: | |
| linear-gradient(rgba(59,130,246,.03) 1px, transparent 1px), | |
| linear-gradient(90deg, rgba(59,130,246,.03) 1px, transparent 1px); | |
| background-size: 60px 60px; | |
| } | |
| /* ββ Layout βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */ | |
| .wrapper { | |
| position: relative; z-index: 1; | |
| max-width: 880px; margin: 0 auto; | |
| padding: 60px 24px 100px; | |
| } | |
| /* ββ Header βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */ | |
| .header { text-align: center; margin-bottom: 52px; animation: fadeDown .7s ease both; } | |
| .header-badge { | |
| display: inline-flex; align-items: center; gap: 8px; | |
| background: rgba(59,130,246,.1); | |
| border: 1px solid rgba(59,130,246,.25); | |
| border-radius: 999px; padding: 6px 16px; | |
| font-size: 11px; font-weight: 500; color: var(--blue-glow); | |
| letter-spacing: .08em; text-transform: uppercase; margin-bottom: 20px; | |
| } | |
| .header-badge .dot { | |
| width: 6px; height: 6px; border-radius: 50%; | |
| background: var(--blue-glow); | |
| animation: pulse-dot 2s ease infinite; | |
| } | |
| @keyframes pulse-dot { | |
| 0%,100% { opacity:1; transform:scale(1); } | |
| 50% { opacity:.4; transform:scale(.7); } | |
| } | |
| h1 { | |
| font-family: 'Syne', sans-serif; | |
| font-size: clamp(2rem,5vw,3.2rem); | |
| font-weight: 800; line-height: 1.1; letter-spacing: -.02em; | |
| background: linear-gradient(135deg,#f0f4ff 20%,#60a5fa 60%,#06b6d4 100%); | |
| -webkit-background-clip: text; -webkit-text-fill-color: transparent; | |
| background-clip: text; margin-bottom: 14px; | |
| } | |
| .header-sub { | |
| color: var(--txt-m); font-size: 15px; font-weight: 300; | |
| max-width: 540px; margin: 0 auto; line-height: 1.7; | |
| } | |
| /* ββ Agent pipeline pills ββββββββββββββββββββββββββββββββββββββββββββββ */ | |
| .pipeline-pills { | |
| display: flex; align-items: center; justify-content: center; | |
| flex-wrap: wrap; gap: 6px; margin-top: 22px; | |
| } | |
| .pill { | |
| display: inline-flex; align-items: center; gap: 5px; | |
| background: rgba(255,255,255,.04); | |
| border: 1px solid rgba(255,255,255,.08); | |
| border-radius: 999px; padding: 4px 12px; | |
| font-size: 11px; color: var(--txt-m); | |
| } | |
| .pill-arrow { color: var(--txt-f); font-size: 12px; } | |
| /* ββ Glass card βββββββββββββββββββββββββββββββββββββββββββββββββββββββ */ | |
| .glass-card { | |
| background: var(--glass); border: 1px solid var(--glass-b); | |
| border-radius: var(--r); backdrop-filter: blur(20px); | |
| -webkit-backdrop-filter: blur(20px); | |
| padding: 36px; margin-bottom: 18px; | |
| animation: fadeUp .6s ease both; | |
| } | |
| .glass-card:nth-child(2) { animation-delay: .1s; } | |
| @keyframes fadeUp { from { opacity:0; transform:translateY(24px); } to { opacity:1; transform:translateY(0); } } | |
| @keyframes fadeDown { from { opacity:0; transform:translateY(-16px); } to { opacity:1; transform:translateY(0); } } | |
| .section-label { | |
| font-family: 'Syne', sans-serif; font-size: 11px; | |
| font-weight: 700; letter-spacing: .12em; text-transform: uppercase; | |
| color: var(--blue-glow); margin-bottom: 22px; | |
| display: flex; align-items: center; gap: 10px; | |
| } | |
| .section-label::after { | |
| content: ''; flex: 1; height: 1px; | |
| background: linear-gradient(90deg, rgba(59,130,246,.3), transparent); | |
| } | |
| /* ββ Form βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */ | |
| .form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; } | |
| .form-grid .span-2 { grid-column: 1 / -1; } | |
| .field { display: flex; flex-direction: column; gap: 7px; } | |
| label { font-size: 12px; font-weight: 500; color: var(--txt-m); letter-spacing: .04em; } | |
| input, textarea, select { | |
| background: rgba(255,255,255,.03); border: 1px solid var(--glass-b); | |
| border-radius: var(--r-sm); color: var(--txt); | |
| font-family: 'DM Sans', sans-serif; font-size: 14px; | |
| padding: 12px 16px; transition: border-color .2s, box-shadow .2s, background .2s; | |
| outline: none; width: 100%; | |
| } | |
| input::placeholder, textarea::placeholder { color: var(--txt-f); } | |
| input:focus, textarea:focus { | |
| border-color: rgba(59,130,246,.5); | |
| background: rgba(59,130,246,.04); | |
| box-shadow: 0 0 0 3px rgba(59,130,246,.1); | |
| } | |
| textarea { resize: vertical; min-height: 88px; line-height: 1.6; } | |
| /* duration slider */ | |
| .duration-row { display: flex; align-items: center; gap: 14px; } | |
| .duration-row input[type="range"] { | |
| flex: 1; -webkit-appearance: none; height: 4px; | |
| background: linear-gradient(90deg, var(--blue) var(--pct,33%), rgba(255,255,255,.1) var(--pct,33%)); | |
| border-radius: 99px; padding: 0; border: none; box-shadow: none; cursor: pointer; | |
| } | |
| .duration-row input[type="range"]::-webkit-slider-thumb { | |
| -webkit-appearance: none; width: 18px; height: 18px; border-radius: 50%; | |
| background: white; box-shadow: 0 0 8px rgba(59,130,246,.6); transition: transform .15s; | |
| } | |
| .duration-row input[type="range"]::-webkit-slider-thumb:hover { transform: scale(1.2); } | |
| .duration-badge { | |
| min-width: 64px; text-align: center; | |
| background: rgba(59,130,246,.12); border: 1px solid rgba(59,130,246,.25); | |
| border-radius: 8px; padding: 8px 10px; | |
| font-family: 'Syne', sans-serif; font-size: 14px; font-weight: 700; | |
| color: var(--blue-glow); line-height: 1; | |
| } | |
| /* submit button */ | |
| .btn-submit { | |
| width: 100%; padding: 16px 24px; | |
| background: linear-gradient(135deg, var(--blue) 0%, var(--blue-dim) 100%); | |
| border: none; border-radius: var(--r-sm); color: white; | |
| font-family: 'Syne', sans-serif; font-size: 15px; | |
| font-weight: 700; letter-spacing: .04em; cursor: pointer; | |
| position: relative; overflow: hidden; | |
| transition: transform .2s, box-shadow .2s; margin-top: 10px; | |
| } | |
| .btn-submit::before { | |
| content: ''; position: absolute; inset: 0; | |
| background: linear-gradient(135deg, rgba(255,255,255,.15) 0%, transparent 60%); | |
| opacity: 0; transition: opacity .2s; | |
| } | |
| .btn-submit:hover:not(:disabled) { transform: translateY(-2px); box-shadow: 0 8px 32px rgba(59,130,246,.4); } | |
| .btn-submit:hover:not(:disabled)::before { opacity: 1; } | |
| .btn-submit:active:not(:disabled) { transform: translateY(0); } | |
| .btn-submit:disabled { opacity: .55; cursor: not-allowed; } | |
| /* error toast */ | |
| #error-toast { | |
| display: none; background: rgba(244,63,94,.1); | |
| border: 1px solid rgba(244,63,94,.3); border-radius: var(--r-sm); | |
| padding: 14px 18px; color: #fda4af; font-size: 14px; | |
| margin-top: 16px; animation: fadeUp .3s ease both; | |
| } | |
| #error-toast.active { display: flex; align-items: flex-start; gap: 10px; } | |
| /* ββ Loader βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */ | |
| #loader { display: none; } | |
| #loader.active { display: block; } | |
| .loader-card { | |
| background: var(--glass); border: 1px solid rgba(59,130,246,.2); | |
| border-radius: var(--r); backdrop-filter: blur(20px); | |
| padding: 48px 36px; text-align: center; animation: fadeUp .4s ease both; | |
| } | |
| .orbit-wrap { position: relative; width: 100px; height: 100px; margin: 0 auto 32px; } | |
| .orbit-ring { position: absolute; inset: 0; border-radius: 50%; border: 2px solid transparent; } | |
| .orbit-ring-1 { border-top-color: var(--blue); border-right-color: rgba(59,130,246,.2); animation: spin 1.4s linear infinite; } | |
| .orbit-ring-2 { inset: 12px; border-top-color: var(--cyan); border-left-color: rgba(6,182,212,.2); animation: spin 2s linear infinite reverse; } | |
| .orbit-ring-3 { inset: 26px; border-bottom-color: rgba(255,255,255,.4); border-right-color: rgba(255,255,255,.1); animation: spin 1.8s linear infinite; } | |
| .orbit-center { | |
| position: absolute; inset: 38px; border-radius: 50%; | |
| background: radial-gradient(circle, rgba(59,130,246,.5), rgba(59,130,246,.1)); | |
| animation: breathe 2s ease-in-out infinite; | |
| } | |
| @keyframes spin { to { transform: rotate(360deg); } } | |
| @keyframes breathe { 0%,100% { transform:scale(1); opacity:.8; } 50% { transform:scale(1.2); opacity:1; } } | |
| .loader-title { font-family:'Syne',sans-serif; font-size:20px; font-weight:700; margin-bottom:8px; } | |
| .loader-sub { color: var(--txt-m); font-size:14px; margin-bottom:8px; min-height:20px; } | |
| /* ββ Live elapsed timer in loader βββββββββββββββββββββββββββββββββββββ */ | |
| .loader-timer { | |
| font-family: 'Syne', sans-serif; font-size: 12px; | |
| color: var(--txt-f); margin-bottom: 28px; | |
| letter-spacing: .06em; | |
| } | |
| .loader-timer span { color: var(--blue-glow); font-weight: 700; } | |
| .agent-steps { display:flex; flex-direction:column; gap:8px; text-align:left; max-width:420px; margin:0 auto; } | |
| .agent-step { | |
| display: flex; align-items: center; gap: 12px; | |
| padding: 10px 14px; border-radius: 10px; | |
| background: rgba(255,255,255,.03); border: 1px solid rgba(255,255,255,.06); | |
| font-size: 13px; color: var(--txt-f); transition: all .4s ease; | |
| } | |
| .agent-step.active { color:var(--txt); background:rgba(59,130,246,.08); border-color:rgba(59,130,246,.2); } | |
| .agent-step.done { color:var(--green); background:rgba(16,185,129,.06); border-color:rgba(16,185,129,.15); } | |
| .step-icon { | |
| width:22px; height:22px; border-radius:50%; | |
| display:flex; align-items:center; justify-content:center; | |
| font-size:11px; flex-shrink:0; | |
| background:rgba(255,255,255,.06); border:1px solid rgba(255,255,255,.1); | |
| } | |
| .agent-step.active .step-icon { background:rgba(59,130,246,.2); border-color:var(--blue); animation:pulse-icon 1.5s ease infinite; } | |
| .agent-step.done .step-icon { background:rgba(16,185,129,.15); border-color:var(--green); } | |
| @keyframes pulse-icon { 0%,100% { box-shadow:0 0 0 0 rgba(59,130,246,.4); } 50% { box-shadow:0 0 0 6px rgba(59,130,246,0); } } | |
| /* ββ Result section βββββββββββββββββββββββββββββββββββββββββββββββββββ */ | |
| #result-section { display:none; } | |
| #result-section.active { display:block; animation:fadeUp .6s ease both; } | |
| .result-header { | |
| display:flex; align-items:center; justify-content:space-between; | |
| margin-bottom:24px; flex-wrap:wrap; gap:12px; | |
| } | |
| .result-title { font-family:'Syne',sans-serif; font-size:20px; font-weight:700; } | |
| .result-title span { color:var(--blue-glow); } | |
| /* elapsed badge in result header */ | |
| .elapsed-badge { | |
| display: inline-flex; align-items: center; gap: 6px; | |
| background: rgba(16,185,129,.1); border: 1px solid rgba(16,185,129,.2); | |
| border-radius: 999px; padding: 4px 12px; | |
| font-size: 11px; color: #34d399; font-family: 'Syne', sans-serif; | |
| font-weight: 700; letter-spacing: .06em; | |
| } | |
| .result-actions { display:flex; gap:10px; flex-wrap:wrap; align-items:center; } | |
| .btn-reset { | |
| background:rgba(255,255,255,.06); border:1px solid rgba(255,255,255,.12); | |
| border-radius:8px; color:var(--txt-m); font-family:'DM Sans',sans-serif; | |
| font-size:13px; padding:8px 16px; cursor:pointer; transition:all .2s; | |
| } | |
| .btn-reset:hover { background:rgba(255,255,255,.1); color:var(--txt); } | |
| .btn-download { | |
| background:linear-gradient(135deg,#10b981,#059669); border:none; | |
| border-radius:8px; color:white; font-family:'Syne',sans-serif; | |
| font-size:13px; font-weight:700; padding:8px 18px; | |
| cursor:pointer; transition:transform .2s, box-shadow .2s; letter-spacing:.03em; | |
| } | |
| .btn-download:hover:not(:disabled) { transform:translateY(-2px); box-shadow:0 6px 20px rgba(16,185,129,.35); } | |
| .btn-download:disabled { opacity:.55; cursor:not-allowed; } | |
| /* ββ Meta cards (Decision + Memory) βββββββββββββββββββββββββββββββββββ */ | |
| .meta-row { display:grid; grid-template-columns:1fr 1fr; gap:16px; margin-bottom:18px; } | |
| .meta-card { | |
| background: var(--glass); border: 1px solid var(--glass-b); | |
| border-radius: var(--r-sm); padding: 20px 22px; | |
| animation: fadeUp .5s ease both; | |
| } | |
| .meta-card-title { | |
| font-family:'Syne',sans-serif; font-size:10px; font-weight:700; | |
| letter-spacing:.12em; text-transform:uppercase; | |
| margin-bottom:14px; display:flex; align-items:center; gap:8px; | |
| } | |
| .meta-card-title.blue { color:var(--blue-glow); } | |
| .meta-card-title.violet { color:var(--violet-light); } | |
| .meta-card-title::after { content:''; flex:1; height:1px; background:currentColor; opacity:.2; } | |
| .decision-rows { display:flex; flex-direction:column; gap:8px; } | |
| .decision-row { display:flex; align-items:center; justify-content:space-between; font-size:13px; } | |
| .decision-row-label { color:var(--txt-m); } | |
| .decision-badge { | |
| font-family:'Syne',sans-serif; font-size:11px; font-weight:700; | |
| letter-spacing:.06em; padding:3px 10px; border-radius:999px; | |
| } | |
| .badge-yes { background:rgba(16,185,129,.15); color:#34d399; border:1px solid rgba(16,185,129,.3); } | |
| .badge-no { background:rgba(100,116,139,.12); color:var(--txt-f); border:1px solid rgba(100,116,139,.2); } | |
| .badge-purple { background:rgba(124,58,237,.15); color:var(--violet-light); border:1px solid rgba(124,58,237,.3); } | |
| .badge-yellow { background:rgba(245,158,11,.12); color:#fcd34d; border:1px solid rgba(245,158,11,.25); } | |
| .badge-cyan { background:rgba(6,182,212,.12); color:#67e8f9; border:1px solid rgba(6,182,212,.25); } | |
| .reasoning-text { | |
| margin-top:12px; font-size:12px; color:var(--txt-m); | |
| line-height:1.6; border-top:1px solid rgba(255,255,255,.06); padding-top:10px; | |
| font-style:italic; | |
| } | |
| .memory-indicator { display:flex; align-items:center; gap:12px; } | |
| .memory-icon { | |
| width:40px; height:40px; border-radius:10px; | |
| display:flex; align-items:center; justify-content:center; font-size:20px; | |
| flex-shrink:0; | |
| } | |
| .memory-icon.active-mem { background:rgba(16,185,129,.12); border:1px solid rgba(16,185,129,.25); } | |
| .memory-icon.inactive-mem { background:rgba(100,116,139,.1); border:1px solid rgba(100,116,139,.2); } | |
| .memory-status { font-family:'Syne',sans-serif; font-size:13px; font-weight:700; } | |
| .memory-status.yes { color:var(--green); } | |
| .memory-status.no { color:var(--txt-f); } | |
| .memory-sub { font-size:12px; color:var(--txt-m); margin-top:3px; line-height:1.5; } | |
| /* ββ Main brief body βββββββββββββββββββββββββββββββββββββββββββββββββββ */ | |
| .result-body { color:var(--txt); line-height:1.75; font-size:15px; } | |
| .result-body h1 { | |
| font-family:'Syne',sans-serif; font-size:1.6rem; font-weight:800; color:#f0f4ff; | |
| margin:28px 0 12px; padding-bottom:10px; border-bottom:1px solid rgba(255,255,255,.08); | |
| } | |
| .result-body h2 { font-family:'Syne',sans-serif; font-size:1.15rem; font-weight:700; color:var(--blue-glow); margin:24px 0 10px; } | |
| .result-body h3 { font-family:'Syne',sans-serif; font-size:1rem; font-weight:600; color:var(--cyan); margin:18px 0 8px; } | |
| .result-body p { margin-bottom:14px; } | |
| .result-body ul, .result-body ol { padding-left:22px; margin-bottom:14px; } | |
| .result-body li { margin-bottom:6px; } | |
| .result-body strong { color:#e2e8f0; } | |
| .result-body em { color:var(--txt-m); } | |
| .result-body code { background:rgba(255,255,255,.07); border:1px solid rgba(255,255,255,.1); border-radius:5px; padding:2px 7px; font-size:.88em; color:var(--cyan); } | |
| .result-body blockquote { border-left:3px solid var(--blue); padding:10px 16px; background:rgba(59,130,246,.06); border-radius:0 8px 8px 0; margin:16px 0; color:var(--txt-m); } | |
| .result-body hr { border:none; border-top:1px solid rgba(255,255,255,.08); margin:24px 0; } | |
| /* make links in brief visible and clickable */ | |
| .result-body a { color: var(--blue-glow); text-decoration: underline; word-break: break-all; } | |
| .result-body a:hover { color: var(--cyan); } | |
| /* ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| SEARCH LINKS PANEL (new) | |
| ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */ | |
| .search-panel { | |
| background: var(--glass); border: 1px solid var(--glass-b); | |
| border-radius: var(--r); backdrop-filter: blur(20px); | |
| padding: 28px 32px; margin-bottom: 18px; | |
| animation: fadeUp .7s ease .15s both; | |
| } | |
| .search-row { | |
| display: flex; gap: 12px; align-items: flex-end; | |
| } | |
| .search-row .field { flex: 1; } | |
| .btn-search { | |
| padding: 12px 22px; white-space: nowrap; | |
| background: linear-gradient(135deg, var(--cyan), #0891b2); | |
| border: none; border-radius: var(--r-sm); color: #0f172a; | |
| font-family: 'Syne', sans-serif; font-size: 13px; font-weight: 700; | |
| cursor: pointer; transition: transform .2s, box-shadow .2s; | |
| letter-spacing: .04em; flex-shrink: 0; | |
| } | |
| .btn-search:hover:not(:disabled) { transform: translateY(-2px); box-shadow: 0 6px 20px rgba(6,182,212,.35); } | |
| .btn-search:disabled { opacity: .5; cursor: not-allowed; } | |
| /* search results output */ | |
| #search-output { display: none; margin-top: 20px; } | |
| #search-output.active { display: block; animation: fadeUp .4s ease both; } | |
| .search-result-header { | |
| display: flex; align-items: center; justify-content: space-between; | |
| margin-bottom: 14px; flex-wrap: wrap; gap: 8px; | |
| } | |
| .search-result-title { | |
| font-family: 'Syne', sans-serif; font-size: 12px; font-weight: 700; | |
| letter-spacing: .1em; text-transform: uppercase; color: var(--cyan); | |
| display: flex; align-items: center; gap: 8px; | |
| } | |
| .search-elapsed { | |
| font-size: 11px; color: var(--txt-f); | |
| font-family: 'Syne', sans-serif; letter-spacing: .06em; | |
| } | |
| .search-elapsed span { color: var(--cyan); font-weight: 700; } | |
| .search-body { | |
| background: rgba(6,182,212,.04); border: 1px solid rgba(6,182,212,.15); | |
| border-radius: var(--r-sm); padding: 20px 22px; | |
| font-size: 14px; line-height: 1.75; color: var(--txt); | |
| } | |
| /* links inside search results */ | |
| .search-body a { | |
| color: var(--blue-glow); text-decoration: underline; | |
| word-break: break-all; | |
| } | |
| .search-body a:hover { color: var(--cyan); } | |
| .search-body h1,.search-body h2,.search-body h3 { | |
| font-family: 'Syne', sans-serif; color: var(--blue-glow); | |
| margin: 14px 0 8px; font-size: 1rem; | |
| } | |
| .search-body ul,.search-body ol { padding-left: 20px; margin-bottom: 12px; } | |
| .search-body li { margin-bottom: 8px; } | |
| .search-body strong { color: #e2e8f0; } | |
| /* search error */ | |
| #search-error { | |
| display: none; background: rgba(244,63,94,.08); | |
| border: 1px solid rgba(244,63,94,.25); border-radius: var(--r-sm); | |
| padding: 12px 16px; color: #fda4af; font-size: 13px; | |
| margin-top: 14px; gap: 8px; | |
| } | |
| #search-error.active { display: flex; align-items: center; } | |
| /* ββ Footer βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */ | |
| footer { text-align:center; padding-top:48px; color:var(--txt-f); font-size:12px; } | |
| footer span { color:var(--txt-m); } | |
| /* ββ Responsive βββββββββββββββββββββββββββββββββββββββββββββββββββββββ */ | |
| @media (max-width:640px) { | |
| .form-grid { grid-template-columns:1fr; } | |
| .form-grid .span-2 { grid-column:1; } | |
| .glass-card { padding:22px 18px; } | |
| .meta-row { grid-template-columns:1fr; } | |
| .pipeline-pills { gap:4px; } | |
| .search-row { flex-direction: column; } | |
| .btn-search { width: 100%; } | |
| } | |
| /* ββ Print / PDF ββββββββββββββββββββββββββββββββββββββββββββββββββββββ */ | |
| @media print { | |
| body { background:white ; } | |
| .bg-canvas, .wrapper > header, #form-section, .result-header, | |
| .meta-row, footer, #loader, .search-panel { display:none ; } | |
| .wrapper { padding:0 ; } | |
| #result-section { display:block ; } | |
| .glass-card { background:white ; border:none ; box-shadow:none ; padding:0 ; } | |
| #print-area, #print-area * { visibility:visible ; color:black ; background:white ; -webkit-text-fill-color:black ; font-family:'Times New Roman',serif ; text-shadow:none ; } | |
| #print-area { font-size:12pt; line-height:1.6; } | |
| #print-area h1 { font-size:22pt; border-bottom:2px solid black; padding-bottom:8px; margin-bottom:15px; } | |
| #print-area h2 { font-size:16pt; margin-top:20px; } | |
| #print-area h3 { font-size:13pt; margin-top:15px; } | |
| #print-area p, #print-area li { margin-bottom:10px; } | |
| @page { margin:20mm; size:A4; } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="bg-canvas"> | |
| <div class="bg-grid"></div> | |
| <div class="bg-orb3"></div> | |
| </div> | |
| <div class="wrapper"> | |
| <!-- ββ Header ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ --> | |
| <header class="header"> | |
| <div class="header-badge"><span class="dot"></span> MeetIQ Intelligence</div> | |
| <h1>MeetIQ</h1> | |
| <p class="header-sub"> | |
| A focused business meeting preparation agent designed to help you plan, strategize, | |
| and execute high-impact meetings with clarity and confidence. | |
| </p> | |
| <div class="pipeline-pills"> | |
| <span class="pill">π― Objective</span> | |
| <span class="pill-arrow">β</span> | |
| <span class="pill">π Research</span> | |
| <span class="pill-arrow">β</span> | |
| <span class="pill">π Insights</span> | |
| <span class="pill-arrow">β</span> | |
| <span class="pill">π§ Strategy</span> | |
| <span class="pill-arrow">β</span> | |
| <span class="pill">π Agenda</span> | |
| <span class="pill-arrow">β</span> | |
| <span class="pill">β Brief</span> | |
| </div> | |
| </header> | |
| <!-- ββ Form ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ --> | |
| <div id="form-section"> | |
| <!-- Meeting input card --> | |
| <div class="glass-card"> | |
| <div class="section-label">Meeting Details</div> | |
| <div class="form-grid"> | |
| <div class="field"> | |
| <label for="company">Company Name</label> | |
| <input type="text" id="company" placeholder="e.g. Acme Corporation" autocomplete="off" /> | |
| </div> | |
| <div class="field"> | |
| <label for="objective">Meeting Objective</label> | |
| <input type="text" id="objective" placeholder="e.g. Explore partnership opportunities" autocomplete="off" /> | |
| </div> | |
| <div class="field span-2"> | |
| <label for="attendees">Attendees & Roles <span style="color:var(--txt-f);font-weight:300">(one per line)</span></label> | |
| <textarea id="attendees" placeholder="John Doe β CEO Jane Smith β Head of Product Alex Ray β Legal Counsel"></textarea> | |
| </div> | |
| <div class="field span-2"> | |
| <label for="duration">Meeting Duration</label> | |
| <div class="duration-row"> | |
| <input type="range" id="duration" min="15" max="180" step="15" value="60" /> | |
| <div class="duration-badge" id="duration-label">60 min</div> | |
| </div> | |
| </div> | |
| <div class="field span-2"> | |
| <label for="focus">Focus Areas & Concerns</label> | |
| <input type="text" id="focus" placeholder="e.g. Budget constraints, Q4 timeline, technical feasibility" autocomplete="off" /> | |
| </div> | |
| </div> | |
| <button class="btn-submit" id="submit-btn" onclick="runAgent()"> | |
| β‘ Prepare My Meeting | |
| </button> | |
| <div id="error-toast"> | |
| <span style="font-size:16px">β </span> | |
| <span id="error-msg">Something went wrong. Please try again.</span> | |
| </div> | |
| </div> | |
| <!-- ββ Search Links panel (always visible in form section) ββββββββββββ --> | |
| <div class="search-panel"> | |
| <div class="section-label">π Quick Link Research</div> | |
| <p style="color:var(--txt-m);font-size:13px;margin-bottom:18px;line-height:1.6;"> | |
| Use the standalone search agent to instantly fetch relevant links and references | |
| for any topic β company, industry, technology, or competitor. | |
| </p> | |
| <div class="search-row"> | |
| <div class="field"> | |
| <label for="search-query">Search Query</label> | |
| <input | |
| type="text" | |
| id="search-query" | |
| placeholder="e.g. OpenAI latest funding round, EV battery supply chain 2024β¦" | |
| autocomplete="off" | |
| /> | |
| </div> | |
| <button class="btn-search" id="search-btn" onclick="runSearch()"> | |
| π Search | |
| </button> | |
| </div> | |
| <!-- error message --> | |
| <div id="search-error"> | |
| <span>β </span> | |
| <span id="search-error-msg">Search failed. Please try again.</span> | |
| </div> | |
| <!-- results panel --> | |
| <div id="search-output"> | |
| <div class="search-result-header"> | |
| <div class="search-result-title">π Search Results</div> | |
| <div class="search-elapsed">Completed in <span id="search-elapsed-val">β</span>s Β· Model: gemini-2.0-flash-lite</div> | |
| </div> | |
| <div class="search-body" id="search-body"></div> | |
| </div> | |
| </div> | |
| </div><!-- end #form-section --> | |
| <!-- ββ Loader βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ --> | |
| <div id="loader"> | |
| <div class="loader-card"> | |
| <div class="orbit-wrap"> | |
| <div class="orbit-ring orbit-ring-1"></div> | |
| <div class="orbit-ring orbit-ring-2"></div> | |
| <div class="orbit-ring orbit-ring-3"></div> | |
| <div class="orbit-center"></div> | |
| </div> | |
| <div class="loader-title">MeetIQ is preparing your meetingβ¦</div> | |
| <div class="loader-sub" id="loader-sub-text">Understanding your meeting objectiveβ¦</div> | |
| <div class="loader-timer">Elapsed: <span id="elapsed-clock">0s</span></div> | |
| <div class="agent-steps"> | |
| <div class="agent-step active" id="step-1"> | |
| <div class="step-icon">π§ </div> | |
| <span>Understanding your meeting objectiveβ¦</span> | |
| </div> | |
| <div class="agent-step" id="step-2"> | |
| <div class="step-icon">π</div> | |
| <span>Researching company and contextβ¦</span> | |
| </div> | |
| <div class="agent-step" id="step-3"> | |
| <div class="step-icon">π</div> | |
| <span>Analyzing market insightsβ¦</span> | |
| </div> | |
| <div class="agent-step" id="step-4"> | |
| <div class="step-icon">πΊοΈ</div> | |
| <span>Building strategy and talking pointsβ¦</span> | |
| </div> | |
| <div class="agent-step" id="step-5"> | |
| <div class="step-icon">π</div> | |
| <span>Structuring your meeting agendaβ¦</span> | |
| </div> | |
| <div class="agent-step" id="step-6"> | |
| <div class="step-icon">β¨</div> | |
| <span>Finalizing your executive briefβ¦</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- ββ Result βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ --> | |
| <div id="result-section"> | |
| <!-- Decision + Memory meta row --> | |
| <div class="meta-row"> | |
| <!-- Decision card --> | |
| <div class="meta-card"> | |
| <div class="meta-card-title blue">π§ Decision Agent Output</div> | |
| <div class="decision-rows"> | |
| <div class="decision-row"> | |
| <span class="decision-row-label">Web Search</span> | |
| <span class="decision-badge" id="badge-search">β</span> | |
| </div> | |
| <div class="decision-row"> | |
| <span class="decision-row-label">Search Mode</span> | |
| <span class="decision-badge badge-cyan" id="badge-search-mode">β</span> | |
| </div> | |
| <div class="decision-row"> | |
| <span class="decision-row-label">Memory Injection</span> | |
| <span class="decision-badge" id="badge-memory-flag">β</span> | |
| </div> | |
| <div class="decision-row"> | |
| <span class="decision-row-label">Priority Focus</span> | |
| <span class="decision-badge badge-purple" id="badge-priority">β</span> | |
| </div> | |
| <div class="decision-row"> | |
| <span class="decision-row-label">Brief Depth</span> | |
| <span class="decision-badge badge-yellow" id="badge-depth">β</span> | |
| </div> | |
| </div> | |
| <div class="reasoning-text" id="decision-reasoning">β</div> | |
| </div> | |
| <!-- Memory card --> | |
| <div class="meta-card"> | |
| <div class="meta-card-title violet">π Session Memory</div> | |
| <div class="memory-indicator"> | |
| <div class="memory-icon inactive-mem" id="memory-icon">π</div> | |
| <div class="memory-text-wrap"> | |
| <div class="memory-status no" id="memory-status-text">Not used</div> | |
| <div class="memory-sub" id="memory-sub-text"> | |
| No past interactions were injected into this run. | |
| </div> | |
| </div> | |
| </div> | |
| <!-- elapsed time --> | |
| <div style="margin-top:18px;padding-top:14px;border-top:1px solid rgba(255,255,255,.06);"> | |
| <div style="font-size:11px;color:var(--txt-f);letter-spacing:.06em;text-transform:uppercase;margin-bottom:6px;">Total Run Time</div> | |
| <div id="result-elapsed" style="font-family:'Syne',sans-serif;font-size:18px;font-weight:700;color:var(--green);">β</div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Brief card --> | |
| <div class="glass-card"> | |
| <div class="result-header"> | |
| <div class="result-title">MeetIQ Brief<span>Ready</span> β</div> | |
| <div class="result-actions"> | |
| <button class="btn-download" id="download-btn" onclick="downloadPDF()">β¬ Download PDF</button> | |
| <button class="btn-reset" onclick="resetForm()">β Start Over</button> | |
| </div> | |
| </div> | |
| <div class="result-body" id="print-area"></div> | |
| </div> | |
| </div> | |
| <footer> | |
| MeetIQ Β· Business Meeting Preparation Agent | |
| </footer> | |
| </div> | |
| <!-- ββ JavaScript ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ --> | |
| <script> | |
| /* ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| MARKED GLOBAL RENDERER β all links open in a new tab | |
| Without this, sites block loading inside the same window/iframe | |
| and the browser shows "refused to connect". | |
| ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */ | |
| (function setupMarked() { | |
| const renderer = new marked.Renderer(); | |
| renderer.link = function(href, title, text) { | |
| // href can be an object in newer marked versions | |
| const url = (typeof href === 'object' && href !== null) ? (href.href || '') : (href || ''); | |
| const label = (typeof href === 'object' && href !== null) ? (href.text || text || url) : (text || url); | |
| const tip = (typeof href === 'object' && href !== null) ? (href.title || title || '') : (title || ''); | |
| const titleAttr = tip ? ` title="${tip}"` : ''; | |
| return `<a href="${url}" target="_blank" rel="noopener noreferrer"${titleAttr}>${label}</a>`; | |
| }; | |
| marked.setOptions({ renderer }); | |
| })(); | |
| /* ββ Duration slider ββββββββββββββββββββββββββββββββββββββββββββββββββββ */ | |
| const durInput = document.getElementById('duration'); | |
| const durLabel = document.getElementById('duration-label'); | |
| function updateSlider() { | |
| const min = parseInt(durInput.min), max = parseInt(durInput.max), val = parseInt(durInput.value); | |
| durInput.style.setProperty('--pct', ((val - min) / (max - min) * 100) + '%'); | |
| durLabel.textContent = val + ' min'; | |
| } | |
| durInput.addEventListener('input', updateSlider); | |
| updateSlider(); | |
| /* ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| LOADER β step cycle + live clock | |
| Each agent typically runs 20β60 s, so we tick every 25 s. | |
| The clock is always accurate because it tracks wall time. | |
| ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */ | |
| const STEP_TEXTS = [ | |
| 'Initialising decision engineβ¦', | |
| 'Researching company context β running web searchesβ¦', | |
| 'Analysing industry trends & competitorsβ¦', | |
| 'Drafting agenda & talking pointsβ¦', | |
| 'Composing executive briefβ¦', | |
| 'Reflecting & polishing final outputβ¦', | |
| ]; | |
| const STEP_COUNT = 6; | |
| const STEP_INTERVAL_MS = 25000; // 25 s per step β 6 steps β 2.5 min total | |
| let stepTimer = null; | |
| let clockTimer = null; | |
| let currentStep = 0; | |
| let loaderStart = 0; | |
| function startStepCycle() { | |
| currentStep = 0; | |
| loaderStart = Date.now(); | |
| resetSteps(); | |
| setStep(0); | |
| stepTimer = setInterval(() => { | |
| if (currentStep < STEP_COUNT - 1) { | |
| markDone(currentStep); | |
| currentStep++; | |
| setStep(currentStep); | |
| } | |
| }, STEP_INTERVAL_MS); | |
| // Live elapsed clock | |
| clockTimer = setInterval(() => { | |
| const sec = Math.floor((Date.now() - loaderStart) / 1000); | |
| const el = document.getElementById('elapsed-clock'); | |
| if (el) el.textContent = sec < 60 ? sec + 's' : Math.floor(sec/60) + 'm ' + (sec % 60) + 's'; | |
| }, 1000); | |
| } | |
| function setStep(i) { | |
| const el = document.getElementById(`step-${i + 1}`); | |
| if (el) { | |
| el.classList.add('active'); | |
| document.getElementById('loader-sub-text').textContent = STEP_TEXTS[i]; | |
| } | |
| } | |
| function markDone(i) { | |
| const el = document.getElementById(`step-${i + 1}`); | |
| if (el) { | |
| el.classList.remove('active'); | |
| el.classList.add('done'); | |
| el.querySelector('.step-icon').textContent = 'β'; | |
| } | |
| } | |
| function stopStepCycle() { | |
| clearInterval(stepTimer); | |
| clearInterval(clockTimer); | |
| for (let i = 0; i < STEP_COUNT; i++) markDone(i); | |
| } | |
| function resetSteps() { | |
| const icons = ['π§ ','π','π','πΊοΈ','π','β¨']; | |
| for (let i = 0; i < STEP_COUNT; i++) { | |
| const el = document.getElementById(`step-${i + 1}`); | |
| el.classList.remove('active','done'); | |
| el.querySelector('.step-icon').textContent = icons[i]; | |
| } | |
| const clk = document.getElementById('elapsed-clock'); | |
| if (clk) clk.textContent = '0s'; | |
| } | |
| /* ββ UI state helpers βββββββββββββββββββββββββββββββββββββββββββββββββββ */ | |
| function showLoader() { | |
| document.getElementById('form-section').style.display = 'none'; | |
| document.getElementById('loader').classList.add('active'); | |
| document.getElementById('result-section').classList.remove('active'); | |
| document.getElementById('error-toast').classList.remove('active'); | |
| startStepCycle(); | |
| } | |
| function showResult(briefHtml, decisionText, memoryUsed, flags, elapsedSec) { | |
| stopStepCycle(); | |
| document.getElementById('loader').classList.remove('active'); | |
| // Populate brief | |
| document.getElementById('print-area').innerHTML = briefHtml; | |
| // ββ Parse + populate Decision card βββββββββββββββββββββββββββββββββββ | |
| const upper = decisionText.toUpperCase(); | |
| const searchYes = !/SEARCH\s*[:=]\s*NO/.test(upper) && !/SEARCH\s*[:=]\s*MINIMAL/.test(upper); | |
| const memoryYes = !/MEMORY\s*[:=]\s*NO/.test(upper); | |
| // Extract individual flags (prefer server flags if available) | |
| const searchMode = (flags && flags.search_mode) || ( | |
| /SEARCH\s*[:=]\s*ALWAYS/.test(upper) ? 'ALWAYS' : | |
| /SEARCH\s*[:=]\s*LIGHT/.test(upper) ? 'LIGHT' : 'MINIMAL' | |
| ); | |
| const priority = (flags && flags.priority) || ( | |
| /PRIORITY\s*[:=]\s*INDUSTRY/.test(upper) ? 'Industry' : | |
| /PRIORITY\s*[:=]\s*STRATEGY/.test(upper) ? 'Strategy' : 'Context' | |
| ); | |
| const depth = (flags && flags.depth) || ( | |
| /DEPTH\s*[:=]\s*DEEP/.test(upper) ? 'DEEP' : | |
| /DEPTH\s*[:=]\s*SHORT/.test(upper) ? 'SHORT' : 'NORMAL' | |
| ); | |
| // Extract reasoning line | |
| const reasonMatch = decisionText.match(/REASONING\s*[:=]\s*(.+)/i); | |
| const reasoning = reasonMatch ? reasonMatch[1].trim() : 'β'; | |
| setDecisionBadge('badge-search', searchYes ? 'YES' : 'NO', searchYes ? 'badge-yes' : 'badge-no'); | |
| setDecisionBadge('badge-search-mode', searchMode, 'badge-cyan'); | |
| setDecisionBadge('badge-memory-flag', memoryUsed ? 'YES' : 'NO', memoryUsed ? 'badge-yes' : 'badge-no'); | |
| setDecisionBadge('badge-priority', priority, 'badge-purple'); | |
| setDecisionBadge('badge-depth', depth, 'badge-yellow'); | |
| document.getElementById('decision-reasoning').textContent = reasoning; | |
| // ββ Memory card βββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| const memIcon = document.getElementById('memory-icon'); | |
| const memStat = document.getElementById('memory-status-text'); | |
| const memSub = document.getElementById('memory-sub-text'); | |
| if (memoryUsed) { | |
| memIcon.className = 'memory-icon active-mem'; | |
| memIcon.textContent = 'β '; | |
| memStat.className = 'memory-status yes'; | |
| memStat.textContent = 'Memory Active'; | |
| memSub.textContent = 'Past interaction history was injected into the agents to improve context accuracy.'; | |
| } else { | |
| memIcon.className = 'memory-icon inactive-mem'; | |
| memIcon.textContent = 'π'; | |
| memStat.className = 'memory-status no'; | |
| memStat.textContent = 'Not used'; | |
| memSub.textContent = 'No relevant past interactions were available or applicable for this run.'; | |
| } | |
| // ββ Elapsed time ββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| if (elapsedSec !== undefined) { | |
| const mins = Math.floor(elapsedSec / 60); | |
| const secs = Math.round(elapsedSec % 60); | |
| document.getElementById('result-elapsed').textContent = | |
| mins > 0 ? `${mins}m ${secs}s` : `${secs}s`; | |
| } | |
| document.getElementById('result-section').classList.add('active'); | |
| document.getElementById('result-section').scrollIntoView({ behavior: 'smooth', block: 'start' }); | |
| } | |
| function setDecisionBadge(id, label, cls) { | |
| const el = document.getElementById(id); | |
| el.textContent = label; | |
| el.className = 'decision-badge ' + cls; | |
| } | |
| function showForm() { | |
| document.getElementById('form-section').style.display = 'block'; | |
| document.getElementById('loader').classList.remove('active'); | |
| document.getElementById('result-section').classList.remove('active'); | |
| document.getElementById('submit-btn').disabled = false; | |
| } | |
| function showError(msg) { | |
| stopStepCycle(); | |
| document.getElementById('loader').classList.remove('active'); | |
| document.getElementById('form-section').style.display = 'block'; | |
| document.getElementById('error-toast').classList.add('active'); | |
| document.getElementById('error-msg').textContent = msg; | |
| document.getElementById('submit-btn').disabled = false; | |
| } | |
| /* ββ Main agent fetch βββββββββββββββββββββββββββββββββββββββββββββββββββ */ | |
| async function runAgent() { | |
| const company = document.getElementById('company').value.trim(); | |
| const objective = document.getElementById('objective').value.trim(); | |
| const attendees = document.getElementById('attendees').value.trim(); | |
| const duration = parseInt(document.getElementById('duration').value); | |
| const focus = document.getElementById('focus').value.trim(); | |
| if (!company || !objective || !attendees || !focus) { | |
| document.getElementById('error-toast').classList.add('active'); | |
| document.getElementById('error-msg').textContent = | |
| 'Please fill in all fields before preparing your meeting.'; | |
| return; | |
| } | |
| document.getElementById('submit-btn').disabled = true; | |
| document.getElementById('error-toast').classList.remove('active'); | |
| showLoader(); | |
| try { | |
| const response = await fetch('/run-agent', { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify({ | |
| company_name: company, | |
| meeting_objective: objective, | |
| attendees: attendees, | |
| meeting_duration: duration, | |
| focus_areas: focus, | |
| }), | |
| }); | |
| const data = await response.json(); | |
| if (!response.ok) throw new Error(data.error || `Server error ${response.status}`); | |
| const briefHtml = marked.parse(data.result || ''); | |
| const decisionText = data.decision || ''; | |
| const memoryUsed = data.memory_used === true; | |
| const flags = data.flags || {}; | |
| const elapsedSec = data.elapsed_sec; | |
| showResult(briefHtml, decisionText, memoryUsed, flags, elapsedSec); | |
| } catch (err) { | |
| if (err.name === 'TypeError' && err.message.includes('fetch')) { | |
| showError('Could not reach the server. Make sure the app is running.'); | |
| } else { | |
| showError(err.message || 'Unexpected error. Please try again.'); | |
| } | |
| } | |
| } | |
| /* ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| STANDALONE SEARCH LINKS β calls /search-links and renders results | |
| ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */ | |
| async function runSearch() { | |
| const query = document.getElementById('search-query').value.trim(); | |
| if (!query) { | |
| document.getElementById('search-error').classList.add('active'); | |
| document.getElementById('search-error-msg').textContent = 'Please enter a search query.'; | |
| return; | |
| } | |
| const btn = document.getElementById('search-btn'); | |
| btn.disabled = true; | |
| btn.textContent = 'β³ Searchingβ¦'; | |
| document.getElementById('search-error').classList.remove('active'); | |
| document.getElementById('search-output').classList.remove('active'); | |
| try { | |
| const response = await fetch('/search-links', { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify({ query }), | |
| }); | |
| const data = await response.json(); | |
| if (!response.ok) throw new Error(data.error || `Server error ${response.status}`); | |
| // Render markdown result into the search body | |
| const html = marked.parse(data.links || '_No results returned._'); | |
| document.getElementById('search-body').innerHTML = html; | |
| document.getElementById('search-elapsed-val').textContent = | |
| data.elapsed_sec !== undefined ? data.elapsed_sec : 'β'; | |
| document.getElementById('search-output').classList.add('active'); | |
| } catch (err) { | |
| document.getElementById('search-error').classList.add('active'); | |
| document.getElementById('search-error-msg').textContent = | |
| err.message || 'Search failed. Please try again.'; | |
| } finally { | |
| btn.disabled = false; | |
| btn.innerHTML = 'π Search'; | |
| } | |
| } | |
| /* ββ PDF download βββββββββββββββββββββββββββββββββββββββββββββββββββββββ */ | |
| function downloadPDF() { | |
| const sourceEl = document.getElementById('print-area'); | |
| const companyName = document.getElementById('company').value.trim() || 'Meeting'; | |
| const wrapper = document.createElement('div'); | |
| wrapper.style.cssText = [ | |
| 'position:fixed','top:-9999px','left:-9999px', | |
| 'width:800px','padding:40px 48px', | |
| 'background:#ffffff','color:#1a1a2e', | |
| 'font-family:Georgia,serif','font-size:13pt','line-height:1.75', | |
| 'z-index:-1', | |
| ].join(';'); | |
| wrapper.innerHTML = ` | |
| <style> | |
| .pdf-clone * { box-sizing:border-box; } | |
| .pdf-clone { color:#1a1a2e !important; background:#fff !important; } | |
| .pdf-clone h1 { font-size:22pt; font-weight:800; color:#0f172a !important; | |
| border-bottom:2px solid #334155; padding-bottom:10px; margin:0 0 18px; } | |
| .pdf-clone h2 { font-size:15pt; font-weight:700; color:#1e3a5f !important; margin:24px 0 10px; } | |
| .pdf-clone h3 { font-size:12pt; font-weight:700; color:#1e3a5f !important; margin:18px 0 8px; } | |
| .pdf-clone p { color:#1a1a2e !important; margin-bottom:12px; } | |
| .pdf-clone ul, .pdf-clone ol { padding-left:22px; margin-bottom:12px; } | |
| .pdf-clone li { color:#1a1a2e !important; margin-bottom:5px; } | |
| .pdf-clone strong { color:#0f172a !important; font-weight:700; } | |
| .pdf-clone em { color:#334155 !important; } | |
| .pdf-clone code { background:#f1f5f9 !important; color:#0369a1 !important; | |
| border:1px solid #cbd5e1; border-radius:4px; padding:2px 6px; font-size:10pt; } | |
| .pdf-clone blockquote { border-left:3px solid #3b82f6 !important; background:#f0f7ff !important; | |
| color:#334155 !important; padding:10px 16px; margin:14px 0; border-radius:0 6px 6px 0; } | |
| .pdf-clone hr { border:none; border-top:1px solid #cbd5e1; margin:20px 0; } | |
| .pdf-clone * { -webkit-text-fill-color:initial !important; text-shadow:none !important; } | |
| </style> | |
| <div class="pdf-clone">${sourceEl.innerHTML}</div>`; | |
| document.body.appendChild(wrapper); | |
| const clone = wrapper.querySelector('.pdf-clone'); | |
| const btn = document.getElementById('download-btn'); | |
| btn.disabled = true; | |
| btn.textContent = 'β³ Generatingβ¦'; | |
| html2pdf() | |
| .set({ | |
| margin: [0.6,0.6,0.6,0.6], | |
| filename: `${companyName}_Executive_Brief.pdf`, | |
| image: { type:'jpeg', quality:0.98 }, | |
| html2canvas: { scale:2, useCORS:true, backgroundColor:'#ffffff', logging:false, scrollY:0 }, | |
| jsPDF: { unit:'in', format:'letter', orientation:'portrait' }, | |
| }) | |
| .from(clone) | |
| .save() | |
| .finally(() => { | |
| document.body.removeChild(wrapper); | |
| btn.disabled = false; | |
| btn.innerHTML = 'β¬ Download PDF'; | |
| }); | |
| } | |
| /* ββ Reset ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */ | |
| function resetForm() { | |
| document.getElementById('print-area').innerHTML = ''; | |
| showForm(); | |
| } | |
| /* ββ Enter key shortcuts ββββββββββββββββββββββββββββββββββββββββββββββββ */ | |
| ['company','objective','focus'].forEach(id => { | |
| document.getElementById(id).addEventListener('keydown', e => { | |
| if (e.key === 'Enter') runAgent(); | |
| }); | |
| }); | |
| document.getElementById('search-query').addEventListener('keydown', e => { | |
| if (e.key === 'Enter') runSearch(); | |
| }); | |
| </script> | |
| </body> | |
| </html> |