Group-1-5010/NotebookLM
1
1"""Dark theme, custom CSS, and logo SVGs for the NotebookLM Gradio app."""2 3import base644import gradio as gr5 6# ── Logo SVGs ────────────────────────────────────────────────────────────────7 8LOGO_SVG = """<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 280 60">9 <defs>10 <linearGradient id="lg1" x1="0%" y1="0%" x2="100%" y2="100%">11 <stop offset="0%" style="stop-color:#667eea"/>12 <stop offset="100%" style="stop-color:#764ba2"/>13 </linearGradient>14 <linearGradient id="lg2" x1="0%" y1="0%" x2="100%" y2="100%">15 <stop offset="0%" style="stop-color:#a78bfa"/>16 <stop offset="100%" style="stop-color:#667eea"/>17 </linearGradient>18 <linearGradient id="sp" x1="0%" y1="0%" x2="100%" y2="100%">19 <stop offset="0%" style="stop-color:#fbbf24"/>20 <stop offset="100%" style="stop-color:#f59e0b"/>21 </linearGradient>22 </defs>23 <g transform="translate(4,6)">24 <rect x="2" y="4" width="36" height="44" rx="4" fill="url(#lg1)"/>25 <rect x="2" y="4" width="8" height="44" rx="3" fill="url(#lg2)" opacity="0.7"/>26 <line x1="16" y1="16" x2="32" y2="16" stroke="rgba(255,255,255,0.5)" stroke-width="1.8" stroke-linecap="round"/>27 <line x1="16" y1="23" x2="30" y2="23" stroke="rgba(255,255,255,0.4)" stroke-width="1.8" stroke-linecap="round"/>28 <line x1="16" y1="30" x2="32" y2="30" stroke="rgba(255,255,255,0.5)" stroke-width="1.8" stroke-linecap="round"/>29 <line x1="16" y1="37" x2="28" y2="37" stroke="rgba(255,255,255,0.4)" stroke-width="1.8" stroke-linecap="round"/>30 <g transform="translate(32,2)">31 <path d="M6 0 L7.5 4.5 L12 6 L7.5 7.5 L6 12 L4.5 7.5 L0 6 L4.5 4.5 Z" fill="url(#sp)"/>32 <path d="M14 8 L14.8 10.2 L17 11 L14.8 11.8 L14 14 L13.2 11.8 L11 11 L13.2 10.2 Z" fill="#fbbf24" opacity="0.7"/>33 </g>34 </g>35 <text x="56" y="28" font-family="Inter,-apple-system,sans-serif" font-size="22" font-weight="700">36 <tspan fill="url(#lg1)">Notebook</tspan><tspan fill="#a78bfa" font-weight="800">LM</tspan>37 </text>38 <text x="57" y="46" font-family="Inter,-apple-system,sans-serif" font-size="10.5" fill="#8888aa" font-weight="400" letter-spacing="0.8">39 AI-Powered Study Companion40 </text>41</svg>"""42 43LOGO_ICON_SVG = """<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 52 60">44 <defs>45 <linearGradient id="ig1" x1="0%" y1="0%" x2="100%" y2="100%">46 <stop offset="0%" style="stop-color:#667eea"/>47 <stop offset="100%" style="stop-color:#764ba2"/>48 </linearGradient>49 <linearGradient id="ig2" x1="0%" y1="0%" x2="100%" y2="100%">50 <stop offset="0%" style="stop-color:#a78bfa"/>51 <stop offset="100%" style="stop-color:#667eea"/>52 </linearGradient>53 <linearGradient id="isp" x1="0%" y1="0%" x2="100%" y2="100%">54 <stop offset="0%" style="stop-color:#fbbf24"/>55 <stop offset="100%" style="stop-color:#f59e0b"/>56 </linearGradient>57 </defs>58 <g transform="translate(2,4)">59 <rect x="2" y="4" width="36" height="44" rx="5" fill="url(#ig1)"/>60 <rect x="2" y="4" width="9" height="44" rx="4" fill="url(#ig2)" opacity="0.7"/>61 <line x1="16" y1="16" x2="32" y2="16" stroke="rgba(255,255,255,0.55)" stroke-width="2" stroke-linecap="round"/>62 <line x1="16" y1="23" x2="30" y2="23" stroke="rgba(255,255,255,0.4)" stroke-width="2" stroke-linecap="round"/>63 <line x1="16" y1="30" x2="32" y2="30" stroke="rgba(255,255,255,0.55)" stroke-width="2" stroke-linecap="round"/>64 <line x1="16" y1="37" x2="28" y2="37" stroke="rgba(255,255,255,0.4)" stroke-width="2" stroke-linecap="round"/>65 <g transform="translate(30,0)">66 <path d="M7 0 L8.8 5.3 L14 7 L8.8 8.8 L7 14 L5.2 8.8 L0 7 L5.2 5.3 Z" fill="url(#isp)"/>67 <path d="M16 9 L17 11.5 L19.5 12.5 L17 13.5 L16 16 L15 13.5 L12.5 12.5 L15 11.5 Z" fill="#fbbf24" opacity="0.7"/>68 </g>69 </g>70</svg>"""71 72 73def get_logo_b64(svg_str: str) -> str:74 return base64.b64encode(svg_str.encode()).decode()75 76 77LOGO_B64 = get_logo_b64(LOGO_SVG)78ICON_B64 = get_logo_b64(LOGO_ICON_SVG)79 80# ── Gradio Dark Theme ────────────────────────────────────────────────────────81 82dark_theme = gr.themes.Base(83 primary_hue=gr.themes.colors.indigo,84 secondary_hue=gr.themes.colors.purple,85 neutral_hue=gr.themes.colors.slate,86 font=gr.themes.GoogleFont("Inter"),87).set(88 body_background_fill="#0e1117",89 body_background_fill_dark="#0e1117",90 block_background_fill="rgba(255,255,255,0.02)",91 block_background_fill_dark="rgba(255,255,255,0.02)",92 block_border_color="rgba(255,255,255,0.08)",93 block_border_color_dark="rgba(255,255,255,0.08)",94 block_label_text_color="#a0a0b8",95 block_label_text_color_dark="#a0a0b8",96 block_title_text_color="#e0e0f0",97 block_title_text_color_dark="#e0e0f0",98 body_text_color="#c8c8d8",99 body_text_color_dark="#c8c8d8",100 button_primary_background_fill="linear-gradient(135deg, #667eea 0%, #764ba2 100%)",101 button_primary_background_fill_dark="linear-gradient(135deg, #667eea 0%, #764ba2 100%)",102 button_primary_text_color="white",103 button_primary_text_color_dark="white",104 button_secondary_background_fill="rgba(255,255,255,0.04)",105 button_secondary_background_fill_dark="rgba(255,255,255,0.04)",106 button_secondary_border_color="rgba(255,255,255,0.12)",107 button_secondary_border_color_dark="rgba(255,255,255,0.12)",108 button_secondary_text_color="#d0d0e0",109 button_secondary_text_color_dark="#d0d0e0",110 border_color_primary="rgba(255,255,255,0.08)",111 border_color_primary_dark="rgba(255,255,255,0.08)",112 input_background_fill="rgba(255,255,255,0.03)",113 input_background_fill_dark="rgba(255,255,255,0.03)",114 input_border_color="rgba(255,255,255,0.1)",115 input_border_color_dark="rgba(255,255,255,0.1)",116 shadow_drop="none",117 shadow_drop_lg="none",118 shadow_spread="none",119)120 121# ── Custom CSS ───────────────────────────────────────────────────────────────122 123CUSTOM_CSS = """124/* ── Import Google Font ── */125@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');126 127/* ── Sidebar ── */128#sidebar {129 background: linear-gradient(180deg, #1a1a2e 0%, #16213e 100%) !important;130 border-right: 1px solid rgba(255,255,255,0.06);131 padding: 16px !important;132 min-height: 100vh;133 position: sticky;134 top: 0;135 align-self: flex-start;136 max-height: 100vh;137 overflow-y: auto;138 border-radius: 0 !important;139}140#sidebar .gr-button-primary {141 background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;142 border: none !important;143 border-radius: 10px !important;144}145#sidebar .gr-button-secondary {146 background: rgba(255,255,255,0.05) !important;147 border: 1px solid rgba(255,255,255,0.1) !important;148 border-radius: 10px !important;149 color: #d0d0e0 !important;150}151 152/* ── Notebook selector radio ── */153#notebook-selector label {154 border-radius: 10px !important;155 padding: 8px 14px !important;156 transition: all 0.2s ease !important;157 font-size: 0.85rem !important;158}159#notebook-selector label.selected {160 background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;161 color: white !important;162}163 164/* ── Tab styling ── */165.tabs > .tab-nav > button {166 border-radius: 10px !important;167 padding: 10px 24px !important;168 font-weight: 500 !important;169 font-size: 0.9rem !important;170}171.tabs > .tab-nav > button.selected {172 background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;173 color: white !important;174}175 176/* ── Chat ── */177#chatbot {178 border-radius: 14px !important;179 border: 1px solid rgba(255,255,255,0.08) !important;180}181#chatbot .message {182 border-radius: 14px !important;183 padding: 14px 18px !important;184}185/* User bubble — shrink to fit content */186#chatbot .bot-row { justify-content: flex-start !important; }187#chatbot .user-row { justify-content: flex-end !important; }188#chatbot .user-row .message-bubble-border {189 max-width: fit-content !important;190}191#chatbot .message.user {192 background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;193 color: white !important;194 border: none !important;195 box-shadow: 0 4px 14px rgba(102,126,234,0.25);196 max-width: fit-content !important;197}198/* Assistant bubble */199#chatbot .message.bot {200 background: rgba(40, 44, 66, 0.85) !important;201 border: 1px solid rgba(102, 126, 234, 0.3) !important;202 color: #c8c8d8 !important;203 box-shadow: 0 4px 12px rgba(102, 126, 234, 0.25);204 border-radius: 14px !important;205 padding: 14px 18px !important;206 backdrop-filter: blur(6px);207}208 209/* ── Cards ── */210.source-card {211 display: flex;212 align-items: center;213 gap: 16px;214 padding: 16px 20px;215 background: rgba(255,255,255,0.02);216 border: 1px solid rgba(255,255,255,0.08);217 border-radius: 14px;218 margin-bottom: 10px;219 transition: all 0.2s ease;220}221.source-card:hover {222 border-color: rgba(102,126,234,0.3);223 background: rgba(255,255,255,0.04);224}225.source-icon {226 width: 48px; height: 48px; border-radius: 12px;227 display: flex; align-items: center; justify-content: center;228 font-size: 1.5rem; flex-shrink: 0;229}230.source-icon.pdf { background: rgba(239,68,68,0.15); }231.source-icon.pptx { background: rgba(249,115,22,0.15); }232.source-icon.txt { background: rgba(59,130,246,0.15); }233.source-icon.url { background: rgba(34,197,94,0.15); }234.source-icon.youtube { background: rgba(239,68,68,0.15); }235.source-info { flex: 1; min-width: 0; }236.source-info .name {237 font-weight: 600; font-size: 0.95rem; color: #e0e0f0;238 white-space: nowrap; overflow: hidden; text-overflow: ellipsis;239}240.source-info .meta { font-size: 0.8rem; color: #707088; margin-top: 2px; }241.source-badge {242 padding: 4px 12px; border-radius: 20px; font-size: 0.75rem;243 font-weight: 600; letter-spacing: 0.3px;244}245.source-badge.ready { background: rgba(34,197,94,0.15); color: #22c55e; }246.source-badge.processing {247 background: rgba(234,179,8,0.15); color: #eab308;248 animation: pulse-badge 1.5s ease-in-out infinite;249}250.source-badge.failed { background: rgba(239,68,68,0.15); color: #ef4444; cursor: help; }251@keyframes pulse-badge {252 0%, 100% { opacity: 1; }253 50% { opacity: 0.5; }254}255 256/* ── Welcome hero ── */257.welcome-hero {258 text-align: center; padding: 80px 40px;259 background: linear-gradient(135deg, rgba(102,126,234,0.08) 0%, rgba(118,75,162,0.08) 100%);260 border-radius: 20px; border: 1px solid rgba(102,126,234,0.15); margin: 20px 0;261}262.welcome-hero h1 {263 background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);264 -webkit-background-clip: text; -webkit-text-fill-color: transparent;265 font-size: 2.5rem; font-weight: 700; margin-bottom: 12px;266}267.welcome-hero p { color: #9090a8; font-size: 1.1rem; line-height: 1.6; }268 269/* ── Empty state ── */270.empty-state {271 text-align: center; padding: 60px 30px; color: #707088;272}273.empty-state h3 { color: #a0a0b8; margin-bottom: 8px; font-weight: 600; }274.empty-state p { font-size: 0.95rem; line-height: 1.5; }275 276/* ── Notebook header ── */277.notebook-header {278 padding: 0 0 16px 0; margin-bottom: 16px;279 border-bottom: 1px solid rgba(255,255,255,0.06);280}281.notebook-header h2 {282 font-weight: 700; font-size: 1.5rem; margin: 0; color: #e8e8f8;283}284.notebook-header .meta { font-size: 0.85rem; color: #707088; margin-top: 4px; }285 286/* ── Citation chip ── */287.citation-chip {288 display: inline-flex; align-items: center; gap: 6px;289 padding: 6px 14px; background: rgba(102,126,234,0.1);290 border: 1px solid rgba(102,126,234,0.2); border-radius: 20px;291 font-size: 0.8rem; color: #a0b0f0; margin: 3px 4px;292}293 294/* ── Artifact section header ── */295.artifact-section-header {296 display: flex; align-items: center; gap: 10px; margin-bottom: 12px;297}298.artifact-section-icon {299 width: 36px; height: 36px; border-radius: 10px;300 display: flex; align-items: center; justify-content: center; font-size: 1.1rem;301}302 303/* ── Locked state ── */304.locked-state {305 text-align: center; padding: 50px 30px;306 background: rgba(255,255,255,0.02);307 border: 1px solid rgba(255,255,255,0.06);308 border-radius: 16px;309}310 311/* ── File uploader ── */312.gr-file-upload {313 border-radius: 14px !important;314 border: 2px dashed rgba(102,126,234,0.3) !important;315 background: rgba(102,126,234,0.03) !important;316}317 318/* ── Primary button ── */319.gr-button-primary {320 background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;321 border: none !important; border-radius: 10px !important;322 font-weight: 600 !important;323}324.gr-button-primary:hover {325 opacity: 0.9 !important;326 transform: translateY(-1px) !important;327 box-shadow: 0 4px 15px rgba(102,126,234,0.3) !important;328}329 330/* ── Source delete dropdown ── */331#source-delete-dropdown {332 border: 1px solid rgba(102,126,234,0.3);333 border-radius: 12px;334 background: rgba(102,126,234,0.06);335}336#source-delete-dropdown label {337 color: #a0a0f0 !important;338 font-weight: 600;339}340#source-delete-dropdown input, #source-delete-dropdown .wrap {341 background: rgba(14,17,23,0.8) !important;342 border-color: rgba(102,126,234,0.25) !important;343 color: #e0e0f0 !important;344 border-radius: 10px !important;345}346#source-delete-dropdown ul {347 background: #1a1d2e !important;348 border: 1px solid rgba(102,126,234,0.3) !important;349 border-radius: 10px !important;350}351#source-delete-dropdown li {352 color: #c0c0e0 !important;353}354#source-delete-dropdown li:hover, #source-delete-dropdown li.selected {355 background: rgba(102,126,234,0.15) !important;356 color: #e0e0f0 !important;357}358 359/* ── Scrollbar ── */360::-webkit-scrollbar { width: 6px; }361::-webkit-scrollbar-track { background: transparent; }362::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.15); border-radius: 3px; }363::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,0.25); }364 365/* ── Hide Gradio footer ── */366footer { display: none !important; }367 368/* ── Auth gate ── */369#auth-gate { max-width: 500px; margin: 100px auto; }370"""371 372# ── Reusable HTML Templates ──────────────────────────────────────────────────373 374WELCOME_HTML = f"""375<div class="welcome-hero">376 <img src="data:image/svg+xml;base64,{ICON_B64}" style="width:64px; margin-bottom:16px;" />377 <h1>NotebookLM</h1>378 <p>Your AI-powered study companion.<br>379 Sign in with your Hugging Face account to get started.</p>380</div>381"""382 383NO_NOTEBOOKS_HTML = """384<div class="welcome-hero">385 <h1>NotebookLM</h1>386 <p>Create a notebook from the sidebar to get started.</p>387</div>388"""389 390SIDEBAR_LOGO_HTML = f"""391<div style="padding: 8px 0 4px 0;">392 <img src="data:image/svg+xml;base64,{LOGO_B64}" style="width:100%; max-width:240px;" />393</div>394"""395 