Perplexity Widescreen & Compact & Code Collapser

V1.7.8: 聊天間距極致壓縮 | toolbar改絕對定位不覆蓋文字

26.03.2026 itibariyledir. En son verisyonu görün.

Bu betiği kurabilmeniz için Tampermonkey, Greasemonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği yüklemek için Tampermonkey gibi bir uzantı yüklemeniz gerekir.

Bu betiği kurabilmeniz için Tampermonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği kurabilmeniz için Tampermonkey ya da Userscripts gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği indirebilmeniz için ayrıca Tampermonkey gibi bir eklenti kurmanız gerekmektedir.

Bu komut dosyasını yüklemek için bir kullanıcı komut dosyası yöneticisi uzantısı yüklemeniz gerekecek.

(Zaten bir kullanıcı komut dosyası yöneticim var, kurmama izin verin!)

Bu stili yüklemek için Stylus gibi bir uzantı yüklemeniz gerekir.

Bu stili yüklemek için Stylus gibi bir uzantı kurmanız gerekir.

Bu stili yükleyebilmek için Stylus gibi bir uzantı yüklemeniz gerekir.

Bu stili yüklemek için bir kullanıcı stili yöneticisi uzantısı yüklemeniz gerekir.

Bu stili yüklemek için bir kullanıcı stili yöneticisi uzantısı kurmanız gerekir.

Bu stili yükleyebilmek için bir kullanıcı stili yöneticisi uzantısı yüklemeniz gerekir.

(Zateb bir user-style yöneticim var, yükleyeyim!)

// ==UserScript==
// @name         Perplexity Widescreen & Compact & Code Collapser
// @namespace    http://tampermonkey.net/
// @version      1.7.8
// @description  V1.7.8: 聊天間距極致壓縮 | toolbar改絕對定位不覆蓋文字
// @author       Custom
// @match        https://www.perplexity.ai/*
// @grant        GM_addStyle
// @grant        GM_setValue
// @grant        GM_getValue
// @run-at       document-end
// ==/UserScript==

(function () {
    'use strict';

    const MIN_W = 140, MAX_W = 380;
    let savedWidth = 185;
    try { savedWidth = Math.min(Math.max(GM_getValue('pplx_sidebar_width', 185), MIN_W), MAX_W); } catch(e){}

    const css = `
        /* SCROLLBAR */
        *::-webkit-scrollbar{display:none!important;width:0!important;height:0!important}
        *{scrollbar-width:none!important;-ms-overflow-style:none!important}
        .scrollable-container::-webkit-scrollbar{display:block!important;width:4px!important}
        .scrollable-container::-webkit-scrollbar-thumb{background:rgba(128,128,128,.25)!important;border-radius:2px!important}
        .scrollable-container{scrollbar-width:thin!important;-ms-overflow-style:auto!important}

        /* WIDESCREEN */
        html,body{max-width:100%!important;overflow-x:hidden!important}
        .scrollable-container{max-width:100%!important;width:100%!important;padding-left:16px!important;padding-right:12px!important}
        .scrollable-container>div{max-width:100%!important;width:100%!important}
        .scrollable-container div[class*="max-w-"],
        .scrollable-container section[class*="max-w-"],
        .scrollable-container article[class*="max-w-"],
        .scrollable-container main[class*="max-w-"]{max-width:100%!important}
        .scrollable-container .container,.scrollable-container .container.isolate{max-width:100%!important;width:100%!important;padding-left:0!important;padding-right:0!important}
        .scrollable-container .erp-sidecar,.scrollable-container [class*="erp-sidecar"]{max-width:100%!important;width:100%!important}
        .prose,.prose>*{max-width:100%!important;width:100%!important}

        /* HEADER */
        [class*="h-headerHeight"]{height:auto!important;min-height:0!important}
        [class*="containerheader"],[class*="container"][class*="header"]{height:auto!important;min-height:0!important;max-height:none!important}
        [role="tablist"] button[role="tab"]{padding-top:2px!important;padding-bottom:2px!important}
        [role="tablist"]{height:auto!important;gap:12px!important}

        /* PILL V0 極窄 */
        div[data-ask-input-container="true"]{max-width:520px!important;margin-left:auto!important;margin-right:auto!important}
        #ask-input{max-height:30vh!important;overflow-y:auto!important}
        div:has(>div[data-ask-input-container="true"]){padding-top:2px!important;padding-bottom:2px!important;margin-top:0!important;margin-bottom:0!important}

        /* ============================================================
           v1.7.8 CHAT SPACING — 黃框極致壓縮
           針對 scrollable-container 內的 flex gap 與 prose 間距
           ============================================================ */

        /* Q&A 區塊之間的縱向間距 */
        .scrollable-container .gap-y-lg{row-gap:6px!important}
        .scrollable-container .gap-y-md{row-gap:4px!important}
        .scrollable-container .gap-y-sm{row-gap:2px!important}

        /* 回答內部 flex 子項目間距 */
        .scrollable-container .gap-5{gap:6px!important}
        .scrollable-container .gap-4{gap:4px!important}
        .scrollable-container .gap-md{gap:4px!important}
        .scrollable-container .gap-sm{gap:2px!important}

        /* User query bubble 內距壓縮 */
        .scrollable-container .bg-subtle.rounded-2xl{padding:4px 10px!important}

        /* 回答 action bar (分享/複製/…) 上下距離 */
        .scrollable-container .flex.items-center.justify-between{padding-top:0!important;margin-top:0!important}

        /* 「已完成 X 個步驟」按鈕列 */
        .scrollable-container button.flex.items-center[class*="gap-sm"][class*="text-quiet"]{margin-top:0!important;margin-bottom:0!important;padding-top:0!important;padding-bottom:0!important}

        /* 「已使用 ... 準備」文字列 */
        .scrollable-container .text-sm.text-quiet[class*="font-sans"]{margin-top:0!important;margin-bottom:0!important;line-height:1.2!important}

        /* PROSE */
        .prose p,.prose li,.prose blockquote{line-height:1.35!important;margin-top:0!important;margin-bottom:2px!important;margin-block-start:0!important;margin-block-end:2px!important;padding-top:0!important;padding-bottom:0!important}
        .prose{margin-top:2px!important}
        .prose h1,.prose h2,.prose h3,.prose h4{margin-top:4px!important;margin-bottom:2px!important;line-height:1.25!important}
        .prose ul,.prose ol{margin-top:0!important;margin-bottom:2px!important;padding-left:1.2em!important}
        .prose li{margin:0!important}
        .prose hr{margin-top:4px!important;margin-bottom:4px!important}

        /* USER BUBBLE */
        main [class*="justify-end"]{position:relative!important}
        main [class*="justify-end"]>[class*="invisible"]{position:absolute!important;right:4px!important;top:4px!important;left:auto!important;z-index:20!important}
        main [class*="justify-end"]>div:last-child,
        main [class*="justify-end"]>*:last-child:not(button):not(svg){width:100%!important;max-width:100%!important;text-align:left!important}
        main [class*="ml-auto"]:not(button):not(svg):not(input){max-width:100%!important}
        main [class*="ms-auto"]:not(button):not(svg):not(input){max-width:100%!important}
        [class*="UserQuery"],[class*="user-query"],[class*="human"]{max-width:100%!important}

        /* SIDEBAR */
        div.w-sideBarWidth{flex-shrink:0!important;transition:width .05s!important}
        nav.groupsidebar,nav[class*="groupsidebar"]{overflow-x:hidden!important}
        nav span.w-full.overflow-hidden{display:block!important;white-space:nowrap!important;overflow:hidden!important;-webkit-mask-image:none!important;mask-image:none!important;line-height:1.3!important;max-height:1.3em!important}
        nav [class*="-ml-md"][class*="px-12px"]{width:9999px!important;min-width:unset!important;max-width:unset!important}

        /* COMPACT NAV */
        nav .flex.flex-none.flex-col{height:auto!important;min-height:0!important;gap:0!important;padding:0!important}
        nav a,nav button{padding-top:0!important;padding-bottom:0!important;margin-top:0!important;margin-bottom:0!important;min-height:0!important}
        nav a[href],nav button{height:auto!important;max-height:22px!important;line-height:1.2!important}
        nav a svg,nav button svg{width:14px!important;height:14px!important}
        nav [class*="gap-"]{gap:0!important}
        nav [class*="py-"]{padding-top:0!important;padding-bottom:0!important}
        nav [class*="my-"]{margin-top:0!important;margin-bottom:0!important}
        nav [class*="mt-"]{margin-top:0!important}
        nav [class*="mb-"]{margin-bottom:0!important}
        nav [class*="pt-"]{padding-top:0!important}
        nav [class*="pb-"]{padding-bottom:0!important}
        nav [class*="space-y"]>*{margin-top:1px!important}
        nav [class*="px-md"]{padding-left:4px!important;padding-right:4px!important}
        nav [class*="px-12px"]{padding-left:4px!important;padding-right:4px!important}
        nav [class*="pl-14px"]{padding-left:6px!important}
        nav [class*="ml-26px"]{margin-left:10px!important}
        nav [class*="-ml-md"]{margin-left:-4px!important}
        nav [class*="border-t"]{margin-top:0!important;margin-bottom:0!important}

        /* CODE */
        pre,code{max-width:100%!important;word-break:break-all!important;white-space:pre-wrap!important}

        /* ============================================================
           v1.7.8 CODE COLLAPSER — 紅框修正
           toolbar 改為 position:absolute 嵌入 .pplx-pre-container 內部
           pre 加 padding-top:36px 推開首行,toolbar 不再蓋到任何文字
           ============================================================ */
        .pplx-pre-container{
            position:relative!important;
            display:block!important;
            margin-top:2px!important;
            margin-bottom:2px!important}
        .pplx-code-wrapper{
            position:absolute!important;
            top:0!important;
            right:0!important;
            left:0!important;
            height:36px!important;
            width:100%!important;
            display:flex!important;
            justify-content:flex-end!important;
            align-items:center!important;
            z-index:10!important;
            pointer-events:none!important;
            overflow:visible!important}
        .pplx-pre-container>pre{
            padding-top:36px!important;  /* 首行推開,toolbar 不覆蓋任何代碼 */
            margin-top:0!important}
        .pplx-code-toolbar{
            pointer-events:auto!important;
            margin-right:6px!important;
            display:flex!important;
            flex-direction:row!important;
            align-items:center!important;
            gap:5px!important;
            background:var(--background-base-color,#ffffff)!important;
            border:1px solid rgba(14,165,233,.22)!important;
            padding:3px 6px 3px 8px!important;
            border-radius:20px!important;
            box-shadow:0 2px 8px rgba(14,165,233,.12)!important;
            max-width:calc(100% - 40px)!important;
            min-width:100px!important}
        .pplx-tb-left{display:flex!important;align-items:center!important;gap:4px!important;overflow:hidden!important;flex:1!important;min-width:0!important}
        .pplx-code-name{font-size:11px!important;font-weight:700!important;white-space:nowrap!important;overflow:hidden!important;text-overflow:ellipsis!important;color:#0ea5e9!important;user-select:none!important;background:rgba(14,165,233,.10)!important;padding:1px 7px 1px 5px!important;border-radius:10px!important;line-height:1.6!important;cursor:default!important}
        .pplx-code-name::before{content:'●';margin-right:4px;font-size:7px;vertical-align:middle;opacity:.7}
        .pplx-code-ver{font-size:10px!important;font-weight:500!important;white-space:nowrap!important;flex-shrink:0!important;color:#64748b!important;user-select:none!important;background:rgba(100,116,139,.10)!important;padding:1px 6px!important;border-radius:8px!important;line-height:1.6!important;cursor:default!important}
        .pplx-code-arrow{flex-shrink:0!important;cursor:pointer!important;color:#fff!important;font-size:10px!important;padding:2px 8px!important;border-radius:10px!important;background:#0ea5e9!important;transition:background .15s!important;user-select:none!important;line-height:1.5!important;font-weight:bold!important}
        .pplx-code-arrow:hover{background:#0284c7!important}
        .pplx-code-arrow.pplx-expanded{background:#0284c7!important}
        .pplx-code-copy{flex-shrink:0!important;cursor:pointer!important;font-size:13px!important;padding:2px 6px!important;border-radius:8px!important;line-height:1.4!important;transition:background .15s,transform .1s!important;user-select:none!important;margin-left:2px!important}
        .pplx-code-copy:hover{background:rgba(14,165,233,.15)!important;transform:scale(1.12)!important}
        .pplx-code-collapsed{max-height:0!important;min-height:0!important;overflow:hidden!important;opacity:.75!important;cursor:pointer!important;border-bottom:3px dashed #0ea5e9!important;padding:0!important;margin:0!important;transition:max-height .3s ease,opacity .2s!important}
        .pplx-code-collapsed:hover{opacity:1!important}

        /* DRAG HANDLE */
        #pplx-resize-handle{width:8px;height:100vh;position:fixed;top:0;left:var(--pplx-sidebar-width,185px);z-index:9999999;cursor:col-resize;background:transparent}
        #pplx-resize-handle::after{content:'';position:absolute;left:50%;top:0;bottom:0;width:1px;background:#22d3ee;transform:translateX(-50%)}
        #pplx-resize-handle:hover::after,#pplx-resize-handle.active::after{background:#06b6d4;width:2px}
        #pplx-drag-curtain{position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:9999998;cursor:col-resize;display:none}
        body.pplx-resizing #pplx-drag-curtain{display:block}
        body.pplx-resizing *{user-select:none!important}

        /* GLOBAL COLLAPSE BTN */
        #pplx-global-collapse-btn{position:fixed!important;right:18px!important;bottom:60px!important;z-index:9999999!important;background:#0ea5e9!important;color:#fff!important;border:none!important;border-radius:20px!important;width:32px!important;height:32px!important;font-size:15px!important;cursor:pointer!important;box-shadow:0 3px 8px rgba(0,0,0,.25)!important;display:flex!important;align-items:center!important;justify-content:center!important;transition:transform .2s,background .2s!important;user-select:none!important}
        #pplx-global-collapse-btn:hover{transform:scale(1.08)!important;background:#0284c7!important}
    `;

    if (typeof GM_addStyle !== 'undefined') { GM_addStyle(css); }
    else { const s=document.createElement('style'); s.textContent=css; document.documentElement.appendChild(s); }

    // ============================================================
    // SIDEBAR
    // ============================================================
    function applySidebarWidth(px) {
        savedWidth = px;
        document.documentElement.style.setProperty('--pplx-sidebar-width', px + 'px');
        ['div.w-sideBarWidth','nav.groupsidebar','nav[class*="groupsidebar"]'].forEach(sel => {
            document.querySelectorAll(sel).forEach(el => {
                el.style.setProperty('width', px+'px','important');
                el.style.setProperty('min-width', px+'px','important');
                el.style.setProperty('max-width', px+'px','important');
            });
        });
        const h=document.getElementById('pplx-resize-handle');
        if(h)h.style.left=px+'px';
    }
    function watchSidebarElement(){
        const el=document.querySelector('div.w-sideBarWidth');
        if(!el||el._pplxWatched)return; el._pplxWatched=true;
        new MutationObserver(()=>{if(parseInt(el.style.width)!==savedWidth)applySidebarWidth(savedWidth);}).observe(el,{attributes:true,attributeFilter:['style']});
    }
    function fixThreadSectionWidth(){
        document.querySelectorAll('nav [style*="width: 200"]').forEach(el=>el.style.setProperty('width','9999px','important'));
        document.querySelectorAll('nav span[style*="mask-image"]').forEach(el=>{el.style.removeProperty('mask-image');el.style.removeProperty('-webkit-mask-image');});
    }
    function fixPageContentWidth(){
        document.querySelectorAll('[style*="--page-content-width"]').forEach(el=>{
            if(el.style.getPropertyValue('--page-content-width')!=='9999px')
                el.style.setProperty('--page-content-width','9999px');
        });
        document.querySelectorAll('[class*="bg-subtle"][class*="rounded-2xl"][style*="max-width"]').forEach(el=>{
            el.style.removeProperty('max-width');
        });
    }

    applySidebarWidth(savedWidth);
    setInterval(()=>{
        const el=document.querySelector('div.w-sideBarWidth');
        if(el&&parseInt(el.style.width)!==savedWidth)applySidebarWidth(savedWidth);
        fixThreadSectionWidth();
    },400);

    // ============================================================
    // 置底
    // ============================================================
    let scrollToBottomTimers=[];
    function scheduleScrollToBottom(){
        scrollToBottomTimers.forEach(t=>clearTimeout(t));
        scrollToBottomTimers=[];
        [300,700,1300,2500,4000].forEach(delay=>{
            scrollToBottomTimers.push(setTimeout(()=>{
                const sc=document.querySelector('.scrollable-container');
                if(sc)sc.scrollTop=sc.scrollHeight;
            },delay));
        });
    }

    let lastUrl=location.href, lastBubbleScan=0;
    function checkUrlChange(){
        if(location.href===lastUrl)return;
        lastUrl=location.href;
        lastBubbleScan=0;
        setTimeout(fixPageContentWidth,300);
        setTimeout(fixPageContentWidth,800);
        scheduleScrollToBottom();
    }

    function expandUserBubbles(){
        const now=Date.now();
        if(now-lastBubbleScan<600)return;
        lastBubbleScan=now;
        const sc=document.querySelector('.scrollable-container');
        if(!sc||sc.getBoundingClientRect().width<10)return;
        sc.querySelectorAll('[class*="justify-end"]').forEach(row=>{
            if(row._pplxRowFixed||row.children.length<2)return;
            const children=Array.from(row.children);
            const bubble=children[children.length-1];
            const ac=children.slice(0,-1).filter(c=>{
                const cls=typeof c.className==='string'?c.className:'';
                return cls.includes('invisible')||cls.includes('opacity-0')||c.querySelectorAll('button').length>0;
            });
            if(!ac.length)return;
            row._pplxRowFixed=true;row.style.position='relative';
            ac.forEach(el=>{el.style.position='absolute';el.style.right='4px';el.style.left='auto';el.style.top='4px';el.style.zIndex='20';});
            bubble.style.setProperty('width','100%','important');
            bubble.style.setProperty('max-width','100%','important');
            bubble.style.setProperty('text-align','left','important');
        });
    }

    function compressNavIcons(){
        ['32px','28px'].forEach(px=>{
            document.querySelectorAll(`nav [style*="width: ${px}"]`).forEach(el=>{
                if(el.style.width===px||el.style.minWidth===px){
                    el.style.setProperty('width','20px','important');
                    el.style.setProperty('min-width','20px','important');
                }
            });
        });
    }

    // ============================================================
    // CODE — 複製排除 language label
    // ============================================================
    const LANG_RE=/^(javascript|typescript|python|java|css|html|sql|bash|sh|shell|json|yaml|xml|go|rust|c\+\+|cpp|c#|ruby|php|swift|kotlin|r|matlab|scala|perl|lua|dart|vue|jsx|tsx|sass|scss|less|toml|ini|dockerfile|makefile|plaintext|text)$/i;
    function getCleanCode(pre){
        const codeEl=pre.querySelector('code');
        if(codeEl)return codeEl.innerText;
        const clone=pre.cloneNode(true);
        clone.querySelectorAll('[data-testid="code-language-indicator"]').forEach(el=>el.remove());
        clone.querySelectorAll('.pplx-code-toolbar,.pplx-code-wrapper').forEach(el=>el.remove());
        const raw=clone.innerText.trim();
        const lines=raw.split('\n');
        if(LANG_RE.test((lines[0]||'').trim()))return lines.slice(1).join('\n').trimStart();
        return raw;
    }

    let isGlobalCollapsed=true;
    function ensureGlobalBtn(){
        if(document.getElementById('pplx-global-collapse-btn')||!document.body)return;
        const btn=document.createElement('div');
        btn.id='pplx-global-collapse-btn';btn.textContent='⏬';btn.title='全域折疊/展開代碼';
        btn.onclick=()=>{
            isGlobalCollapsed=!isGlobalCollapsed;
            btn.textContent=isGlobalCollapsed?'⏬':'⏫';
            document.querySelectorAll('pre.pplx-processed').forEach(pre=>{
                const arrow=pre._pplxArrow;
                if(isGlobalCollapsed){pre.classList.add('pplx-code-collapsed');if(arrow){arrow.textContent='▼ 展開';arrow.classList.remove('pplx-expanded');}}
                else{pre.classList.remove('pplx-code-collapsed');if(arrow){arrow.textContent='▲ 折疊';arrow.classList.add('pplx-expanded');}}
            });
        };
        document.body.appendChild(btn);
    }

    // ============================================================
    // v1.7.8 processCodeBlocks — 使用 .pplx-pre-container 包裹 pre
    // toolbar 絕對定位於容器頂部,pre 加 padding-top:36px 推開首行
    // ============================================================
    function processCodeBlocks(){
        document.querySelectorAll('pre:not(.pplx-processed)').forEach(pre=>{
            pre.classList.add('pplx-processed');
            if(!pre.parentNode)return;

            const txt=pre.innerText||'';
            const nmMatch=txt.match(/@name\s+([^\n]+)/i);
            const vmMatch=txt.match(/@version\s+([^\n]+)/i);

            // 建立外層容器(包裹 toolbar + pre)
            const container=document.createElement('div');
            container.className='pplx-pre-container';

            // 建立 toolbar wrapper(absolute 定位,嵌入容器頂部)
            const wrap=document.createElement('div');
            wrap.className='pplx-code-wrapper';

            const tbar=document.createElement('div');
            tbar.className='pplx-code-toolbar';
            const left=document.createElement('div');
            left.className='pplx-tb-left';

            if(nmMatch){const n=document.createElement('span');n.className='pplx-code-name';n.textContent=nmMatch[1].trim();n.title=nmMatch[1].trim();left.appendChild(n);}
            if(vmMatch){const v=document.createElement('span');v.className='pplx-code-ver';v.textContent='v'+vmMatch[1].trim();left.appendChild(v);}

            const arrow=document.createElement('span');
            arrow.className='pplx-code-arrow';
            arrow.title='展開 / 折疊代碼';
            if(isGlobalCollapsed){arrow.textContent='▼ 展開';pre.classList.add('pplx-code-collapsed');}
            else{arrow.textContent='▲ 折疊';arrow.classList.add('pplx-expanded');}
            arrow.onclick=e=>{
                e.preventDefault();e.stopPropagation();
                const collapsed=pre.classList.toggle('pplx-code-collapsed');
                arrow.textContent=collapsed?'▼ 展開':'▲ 折疊';
                arrow.classList.toggle('pplx-expanded',!collapsed);
            };
            left.appendChild(arrow);

            const copyBtn=document.createElement('span');
            copyBtn.className='pplx-code-copy';copyBtn.textContent='📋';copyBtn.title='複製代碼';
            copyBtn.onclick=e=>{
                e.preventDefault();e.stopPropagation();
                const code=getCleanCode(pre);
                const fb=()=>{copyBtn.textContent='✅';setTimeout(()=>copyBtn.textContent='📋',2000);};
                if(navigator.clipboard)navigator.clipboard.writeText(code).then(fb).catch(()=>{const ta=document.createElement('textarea');ta.value=code;document.body.appendChild(ta);ta.select();document.execCommand('copy');document.body.removeChild(ta);fb();});
                else{const ta=document.createElement('textarea');ta.value=code;document.body.appendChild(ta);ta.select();document.execCommand('copy');document.body.removeChild(ta);fb();}
            };
            pre.onclick=()=>{if(pre.classList.contains('pplx-code-collapsed')){pre.classList.remove('pplx-code-collapsed');arrow.textContent='▲ 折疊';arrow.classList.add('pplx-expanded');}};

            tbar.appendChild(left);
            tbar.appendChild(copyBtn);
            wrap.appendChild(tbar);

            // 插入容器,將 wrap 與 pre 都放入容器中
            pre.parentNode.insertBefore(container, pre);
            container.appendChild(wrap);   // toolbar(absolute 定位在容器頂部)
            container.appendChild(pre);    // pre(有 padding-top:36px 推開首行)
            pre._pplxArrow=arrow;
        });
    }

    let isResizing=false,animId=null;
    function ensureResizeHandle(){
        if(document.getElementById('pplx-resize-handle')||!document.body)return;
        const h=document.createElement('div');h.id='pplx-resize-handle';h.title='拖曳側欄寬度 | 雙擊還原';
        const c=document.createElement('div');c.id='pplx-drag-curtain';
        document.body.appendChild(h);document.body.appendChild(c);
        h.addEventListener('mousedown',e=>{isResizing=true;h.classList.add('active');document.body.classList.add('pplx-resizing');e.preventDefault();});
        window.addEventListener('mousemove',e=>{if(!isResizing)return;if(animId)cancelAnimationFrame(animId);animId=requestAnimationFrame(()=>applySidebarWidth(Math.min(Math.max(e.clientX,MIN_W),MAX_W)));});
        window.addEventListener('mouseup',()=>{if(!isResizing)return;isResizing=false;h.classList.remove('active');document.body.classList.remove('pplx-resizing');try{GM_setValue('pplx_sidebar_width',savedWidth);}catch(_){}});
        h.addEventListener('dblclick',()=>{applySidebarWidth(185);try{GM_setValue('pplx_sidebar_width',185);}catch(_){}});
    }

    let originalTitle=document.title,tabState='IDLE',wasGenerating=false;
    function setTabState(s){let t=originalTitle;if(s==='GENERATING')t='【⏳】 '+originalTitle;else if(s==='DONE')t='【✅】 '+originalTitle;if(document.title!==t)document.title=t;}
    window.addEventListener('focus',()=>{if(tabState==='DONE'){tabState='IDLE';setTabState('IDLE');}});
    window.addEventListener('click',()=>{if(tabState==='DONE'){tabState='IDLE';setTabState('IDLE');}});
    function detectGenerating(){
        const stop=document.querySelector('button[aria-label*="Stop"],button[aria-label*="停止"]');
        const gen=!!(stop&&stop.offsetParent!==null);
        if(gen&&!wasGenerating){tabState='GENERATING';setTabState(tabState);wasGenerating=true;if(!originalTitle.includes('【'))originalTitle=document.title;}
        else if(!gen&&wasGenerating){tabState='DONE';setTabState(tabState);wasGenerating=false;}
        if(tabState==='IDLE'&&!document.title.includes('【'))originalTitle=document.title;
    }

    function maintainUI(){
        ensureResizeHandle();
        watchSidebarElement();
        ensureGlobalBtn();
        processCodeBlocks();
        detectGenerating();
        checkUrlChange();
        expandUserBubbles();
        compressNavIcons();
        fixPageContentWidth();
    }
    setInterval(maintainUI,300);
    maintainUI();
    scheduleScrollToBottom();
})();