Greasy Fork is available in English.

Perplexity Widescreen & Compact & Code Collapser

v1.9.14: 穩定修正版號同步;箭頭僅保留icon與tooltip

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

You will need to install an extension such as Tampermonkey to install this script.

Tendrás que instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Tendrás que instalar una extensión como Tampermonkey antes de poder instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

// ==UserScript==
// @name         Perplexity Widescreen & Compact & Code Collapser
// @namespace    http://tampermonkey.net/
// @version      1.9.14
// @description  v1.9.14: 穩定修正版號同步;箭頭僅保留icon與tooltip
// @author       ford933
// @license      All Rights Reserved
// @match        https://www.perplexity.ai/*
// @grant        GM_addStyle
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_info
// @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{max-width:100%!important}
        body{max-width:100%!important;overflow-x:clip!important}
        .scrollable-container{max-width:100%!important;width:100%!important;padding-left:16px!important;padding-right:12px!important}
        .scrollable-container>div:not([data-radix-popper-content-wrapper]):not([data-radix-dropdown-menu-content]):not([style*="position: fixed"]):not([style*="position:fixed"]){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:not([data-radix-popper-content-wrapper] .prose),.prose>*:not([data-radix-popper-content-wrapper] *){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 */
        div[data-ask-input-container="true"]{max-width:520px!important;margin-left:auto!important;margin-right:auto!important}
        div:has(>div[data-ask-input-container="true"]){max-width:520px!important;margin-left:auto!important;margin-right:auto!important;contain:layout style!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}

        /* CHAT SPACING */
        .scrollable-container .gap-y-lg{row-gap:4px!important}
        .scrollable-container .gap-y-md{row-gap:2px!important}
        .scrollable-container .gap-y-sm{row-gap:1px!important}
        .scrollable-container .gap-5{gap:4px!important}
        .scrollable-container .gap-4{gap:2px!important}
        .scrollable-container .gap-md{gap:2px!important}
        .scrollable-container .gap-sm{gap:1px!important}
        .scrollable-container .mt-md:not(nav .mt-md):not(.prose .mt-md){margin-top:2px!important}
        .scrollable-container .mt-xs:not(nav .mt-xs):not(.prose .mt-xs){margin-top:0!important}
        .scrollable-container [class*="pt-md"]:not(nav [class*="pt-md"]):not(.prose [class*="pt-md"]){padding-top:2px!important}
        .scrollable-container [class*="pt-lg"]:not(nav [class*="pt-lg"]):not(.prose [class*="pt-lg"]){padding-top:2px!important}
        .scrollable-container .flex.items-center.justify-between{padding-top:0!important;margin-top:0!important}
        .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}

        /* TABLE */
        .scrollable-container table{border-collapse:separate!important;border-spacing:0!important}
        .scrollable-container table th{padding:3px 6px!important;min-width:40px!important;vertical-align:bottom!important;white-space:normal!important;word-break:break-word!important}
        .scrollable-container table td{padding:2px 6px!important;min-width:40px!important;vertical-align:top!important;white-space:normal!important;word-break:break-word!important}
        .scrollable-container .overflow-auto[class*="rounded"]{overflow-x:auto!important;max-width:100%!important;display:block!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}
        .scrollable-container [class*="grouptitle"]{display:flex!important;width:100%!important;max-width:100%!important;flex-direction:column!important}
        .scrollable-container [class*="groupquery"]{width:100%!important;max-width:100%!important}
        .scrollable-container [class*="rounded-tl-2xl"][class*="bg-subtle"]{max-width:100%!important;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 .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]:not([role="option"]):not([role="menuitem"]):not([data-radix-collection-item]):not([cmdk-item]),nav button:not([role="option"]):not([role="menuitem"]):not([data-radix-collection-item]):not([cmdk-item]){height:auto!important;max-height:22px!important;line-height:1.2!important}
        nav a:not([role="option"]):not([data-radix-collection-item]) svg,nav button:not([role="option"]):not([role="menuitem"]):not([data-radix-collection-item]) svg{width:14px!important;height:14px!important}

        nav [class*="gap-"]:not([role="listbox"]):not([role="menu"]):not([data-radix-popper-content-wrapper]):not([data-radix-select-content]){gap:0!important}
        nav [class*="py-"]:not([role="option"]):not([role="menuitem"]):not([data-radix-collection-item]):not([cmdk-item]){padding-top:0!important;padding-bottom:0!important}
        nav [class*="my-"]:not([role="option"]):not([role="menuitem"]):not([data-radix-collection-item]){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:2px!important;margin-bottom:2px!important}

        nav [class*="group"][class*="sidebar-sub-menu"] > div[class*="h-10"],
        nav [class*="group\/sidebar-sub-menu"] > div[class*="h-10"]{height:24px!important;min-height:24px!important;max-height:24px!important;padding-top:0!important;padding-bottom:0!important}
        nav [class*="group"][class*="sidebar-sub-menu"] > div[class*="h-7"],
        nav [class*="group\/sidebar-sub-menu"] > div[class*="h-7"]{height:20px!important;min-height:20px!important;max-height:20px!important;padding-top:0!important;padding-bottom:0!important}
        nav [class*="group"][class*="sidebar-sub-menu"] [class*="size-6"],
        nav [class*="group\/sidebar-sub-menu"] [class*="size-6"]{width:16px!important;height:16px!important;min-width:16px!important;min-height:16px!important}
        nav [class*="group"][class*="sidebar-sub-menu"] svg[width="18"],
        nav [class*="group\/sidebar-sub-menu"] svg[width="18"]{width:14px!important;height:14px!important}
        nav [class*="group"][class*="sidebar-sub-menu"] [class*="text-sm"],
        nav [class*="group\/sidebar-sub-menu"] [class*="text-sm"]{line-height:24px!important;font-size:11.5px!important}
        nav [class*="group"][class*="sidebar-sub-menu"] [class*="text-xs"],
        nav [class*="group\/sidebar-sub-menu"] [class*="text-xs"]{line-height:20px!important;font-size:11px!important}
        nav [class*="group"][class*="sidebar-sub-menu"] > div[class*="rounded-xl"],
        nav [class*="group\/sidebar-sub-menu"] > div[class*="rounded-xl"]{border-radius:6px!important}
        nav [class*="group"][class*="sidebar-sub-menu"] [class*="pl-sm"],
        nav [class*="group\/sidebar-sub-menu"] [class*="pl-sm"]{padding-left:4px!important}
        nav [class*="group"][class*="sidebar-sub-menu"] [class*="px-sm"],
        nav [class*="group\/sidebar-sub-menu"] [class*="px-sm"]{padding-left:4px!important;padding-right:4px!important}
        nav [class*="group"][class*="sidebar-sub-menu"] [class*="pr-3"]{padding-right:4px!important}
        nav [class*="group"][class*="sidebar-sub-menu"] button[class*="h-6"],
        nav [class*="group\/sidebar-sub-menu"] button[class*="h-6"]{height:18px!important;min-height:18px!important;padding:0!important}
        nav > div{gap:0!important}
        nav [class*="flex-col"]{gap:0!important}

        /* 隱藏被快捷鈕取代的 nav 列 */
        .pplx-hidden-nav-row{display:none!important}

        /* ── 新建行 position:relative,讓快捷鈕可 absolute 定位 ── */
        /* v1.9.3:+新建 icon 鈕,在 logo 正右方,獨立不融合 */
        #pplx-new-btn-header{
            display:inline-flex!important;align-items:center!important;justify-content:center!important;
            width:26px!important;height:26px!important;
            min-width:26px!important;min-height:26px!important;
            border-radius:6px!important;border:none!important;cursor:pointer!important;
            background:transparent!important;
            color:var(--text-quiet,currentColor)!important;
            opacity:.7!important;flex-shrink:0!important;
            text-decoration:none!important;
            margin-left:3px!important;margin-right:0!important;
            padding:0!important;
            transition:background 130ms,opacity 130ms!important;
            vertical-align:middle!important;
        }
        #pplx-new-btn-header:hover{background:rgba(128,128,128,.15)!important;opacity:1!important}
        #pplx-new-btn-header svg{width:15px!important;height:15px!important;display:block!important;stroke:currentColor!important;fill:none!important;pointer-events:none!important;}
        .pplx-newbtn-anchor{position:relative!important;overflow:visible!important}

        /* ── 快捷鈕群組:absolute 釘在行右端 ── */
        .pplx-hdr-shortcuts{
            position:absolute!important;
            right:2px!important;top:50%!important;
            transform:translateY(-50%)!important;
            display:flex!important;align-items:center!important;
            justify-content:flex-end!important;
            gap:0px!important;
            width:auto!important;
            max-width:calc(100% - 60px)!important;
            z-index:100!important;
            pointer-events:none!important;
            visibility:visible!important;opacity:1!important;
        }

        /* ── 快捷鈕本體 ── */
        a.pplx-hdr-btn{
            display:inline-flex!important;align-items:center!important;justify-content:center!important;
            flex:0 0 auto!important;
            height:22px!important;
            max-height:22px!important;min-height:22px!important;
            width:24px!important;min-width:24px!important;
            border-radius:5px!important;
            background:transparent!important;border:none!important;cursor:pointer!important;
            color:var(--text-quiet,currentColor)!important;
            opacity:.7!important;flex-shrink:0!important;
            text-decoration:none!important;
            padding:0!important;margin:0!important;
            line-height:1!important;
            transition:background 130ms,opacity 130ms!important;
            visibility:visible!important;pointer-events:auto!important;
            overflow:visible!important;box-sizing:border-box!important;
        }
        a.pplx-hdr-btn:hover{background:rgba(128,128,128,.15)!important;opacity:1!important}

        /* SVG 固定 14px — 覆蓋所有 nav svg 規則 */
        a.pplx-hdr-btn svg{
            width:14px!important;height:14px!important;
            min-width:14px!important;min-height:14px!important;
            max-width:14px!important;max-height:14px!important;
            display:block!important;pointer-events:none!important;
            stroke:currentColor!important;fill:none!important;
            overflow:visible!important;
        }

        /* Tooltip */
        a.pplx-hdr-btn::after{
            content:attr(data-tip);display:none;
            position:absolute;top:calc(100% + 4px);left:50%;
            transform:translateX(-50%);
            background:rgba(0,0,0,.82);color:#fff;
            font-size:11px;padding:2px 7px;border-radius:4px;
            white-space:nowrap;pointer-events:none;z-index:99999;
            font-family:sans-serif;font-weight:normal;
        }
        a.pplx-hdr-btn:hover::after{display:block}

        /* DROPDOWN RESET — 保護 Perplexity 原生彈層不被 nav rules 影響 */
        .bg-raised.shadow-overlay{max-width:none!important;width:auto!important;contain:none!important}
        .bg-raised.shadow-overlay *{max-width:none!important}
        [data-radix-popper-content-wrapper]{overflow:visible!important;max-height:none!important;height:auto!important;width:auto!important;max-width:none!important;transform-origin:unset!important}
        [role="listbox"],[role="menu"],[role="dialog"],[data-radix-select-content],[data-radix-dropdown-menu-content],[cmdk-root]{max-height:80vh!important;height:auto!important;overflow-y:auto!important;overflow-x:visible!important;width:auto!important;min-width:160px!important}
        [role="listbox"] *,[role="menu"] *,[data-radix-popper-content-wrapper] *,[data-radix-select-content] *,[data-radix-dropdown-menu-content] *{max-height:none!important;height:auto!important;line-height:normal!important;padding-top:revert!important;padding-bottom:revert!important;margin-top:revert!important;margin-bottom:revert!important;gap:revert!important;max-width:none!important;width:auto!important}
        [role="option"],[role="menuitem"],[data-radix-collection-item],[cmdk-item]{max-height:none!important;height:auto!important;min-height:28px!important;line-height:1.4!important;padding-top:4px!important;padding-bottom:4px!important;white-space:nowrap!important}

        /* CODE */
        pre,code{max-width:100%!important;word-break:break-all!important;white-space:pre-wrap!important}
        .pplx-pre-container{position:relative!important;display:block!important;overflow:visible!important;margin-top:2px!important;margin-bottom:2px!important}
        .pplx-code-wrapper{position:sticky!important;top:0!important;height:0!important;width:100%!important;display:flex!important;justify-content:flex-end!important;align-items:flex-start!important;z-index:200!important;pointer-events:none!important;overflow:visible!important}
        .pplx-pre-container>pre{padding-top:38px!important;margin-top:0!important}
        .pplx-code-toolbar{pointer-events:auto!important;margin-right:6px!important;margin-top:3px!important;display:flex!important;flex-direction:row!important;align-items:center!important;gap:0!important;background:var(--background-base-color,#ffffff)!important;border:1px solid rgba(14,165,233,.22)!important;padding:3px 4px 3px 8px!important;border-radius:20px!important;box-shadow:0 2px 10px rgba(14,165,233,.18)!important;max-width:calc(100% - 40px)!important;min-width:100px!important}
        .pplx-tb-left{display:flex!important;align-items:center!important;gap:2px!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,.pplx-code-copy,.pplx-code-download{flex-shrink:0!important;cursor:pointer!important;display:inline-flex!important;align-items:center!important;justify-content:center!important;width:24px!important;min-width:24px!important;height:24px!important;padding:0!important;margin-left:0!important;border-radius:8px!important;line-height:1!important;transition:background .15s,transform .1s!important;user-select:none!important}.pplx-code-arrow{color:#fff!important;background:#0ea5e9!important;font-weight:bold!important;font-size:12px!important}
        .pplx-code-arrow:hover{background:#0284c7!important;transform:scale(1.08)!important}
        .pplx-code-arrow.pplx-expanded{background:#0284c7!important}
        .pplx-code-copy,.pplx-code-download{font-size:13px!important;background:transparent!important}
        .pplx-code-copy:hover,.pplx-code-download: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 Width ──
    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');
                // 不強制 min-width,讓 Perplexity 原生折疊鈕可自由縮小
                el.style.removeProperty('min-width');
                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(() => { const _wm = parseInt(el.style.width); if (!isNaN(_wm) && _wm > 60 && _wm !== 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'); });
        document.querySelectorAll('[class*="bg-subtle"][class*="rounded-tl-2xl"][style*="max-width"]').forEach(el => { el.style.removeProperty('max-width'); });
        document.querySelectorAll('[class*="grouptitle"]').forEach(el => {
            if (getComputedStyle(el).display === 'inline-flex') {
                el.style.setProperty('display', 'flex', 'important');
                el.style.setProperty('width', '100%', 'important');
            }
        });
    }

    // ── 快捷鈕定義 ──
    const SHORTCUT_DEFS = [
        {
            label: '空間', href: '/spaces',
            svg: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 7c0-1.1.9-2 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><line x1="9" y1="13" x2="15" y2="13"/><line x1="12" y1="10" x2="12" y2="16"/></svg>`
        },
        {
            label: '成品', href: '/computer/artifacts',
            svg: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="8" height="8" rx="1.5"/><rect x="13" y="3" width="8" height="8" rx="1.5"/><rect x="3" y="13" width="8" height="8" rx="1.5"/><rect x="13" y="13" width="8" height="8" rx="1.5"/></svg>`
        },
        {
            label: '自訂', href: '/computer/connectors',
            svg: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06-.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>`
        },
    ];

    const HIDDEN_LABELS = new Set(['空間', '成品', '自訂']);
    let shortcutsInjected = false;

    // ── v1.8.6 核心:找「新建」所在的 collapsible-sidebar-section
    //   對它加 position:relative,然後 append 一個 absolute 定位的快捷列
    //   完全不改變父層 flex 方向,不影響 nav 結構
    // ── v1.9.2:把 +新建 注入到 sidebar 頂部 header 列(logo 右方)──
    function injectNewBtnToHeader() {
        if (document.getElementById('pplx-new-btn-header')) return true;
        // 找 sidebar header:nav 第一個直接子 div
        const nav = document.querySelector('nav[class*="groupsidebar"]')
                 || document.querySelector('nav[class*="sidebar"]')
                 || document.querySelector('div.w-sideBarWidth nav');
        if (!nav) return false;
        const headerDiv = nav.firstElementChild;
        if (!headerDiv) return false;

        // 找 logo(第一個 a 元素)
        const logoA = headerDiv.querySelector('a');
        if (!logoA) return false;

        const newBtn = document.createElement('a');
        newBtn.id = 'pplx-new-btn-header';
        newBtn.href = '/';
        newBtn.setAttribute('aria-label', '新建');
        newBtn.title = '新建對話';
        // 只有 + 圖示,不加文字,保持 icon 風格一致
        newBtn.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>`;
        // 插在 logo 的正後方(logo nextSibling 前)
        if (logoA.nextSibling) {
            headerDiv.insertBefore(newBtn, logoA.nextSibling);
        } else {
            headerDiv.appendChild(newBtn);
        }
        return true;
    }

    // ── v1.9.1:多選擇器找 section,完全不動 nav flex 結構 ──
    function findAnchorSection() {
        // 嘗試各種可能的「新建」aria-label(中英文,有無 draggable)
        const selectors = [
            'a[draggable="false"][aria-label="新建"]',
            'a[aria-label="新建"]',
            'a[aria-label="New"]',
            'a[aria-label="新增"]',
            'a[draggable="false"][href="/"]',
        ];
        for (const sel of selectors) {
            const link = document.querySelector(sel);
            if (!link) continue;
            let el = link;
            for (let i = 0; i < 10; i++) {
                el = el.parentElement;
                if (!el) break;
                if ((el.className || '').includes('collapsible-sidebar-section')) return el;
            }
        }
        // 最後備援:取第一個 collapsible-sidebar-section
        return document.querySelector('div[class*="collapsible-sidebar-section"]') || null;
    }
    function injectSidebarShortcuts() {
        if (document.querySelector('.pplx-newbtn-anchor')) return true;  // 已注入
        const sectionEl = findAnchorSection();
        if (!sectionEl) return false;
        if (sectionEl.dataset.pplxDone) return true;
        sectionEl.dataset.pplxDone = '1';

        // 加 position:relative,讓快捷鈕 absolute 相對此 section 定位(不動 flex)
        sectionEl.classList.add('pplx-newbtn-anchor');

        // 建立快捷鈕群組
        const wrap = document.createElement('div');
        wrap.className = 'pplx-hdr-shortcuts';

        SHORTCUT_DEFS.forEach(({ label, href, svg }) => {
            const a = document.createElement('a');
            a.href = href;
            a.className = 'pplx-hdr-btn';
            a.setAttribute('data-tip', label);
            a.setAttribute('aria-label', label);
            a.innerHTML = svg;
            wrap.appendChild(a);
        });

        sectionEl.appendChild(wrap);
        hideOriginalNavRows();
        return true;
    }

    function hideOriginalNavRows() {
        document.querySelectorAll('div[class*="collapsible-sidebar-section"]').forEach(section => {
            if (section.classList.contains('pplx-hidden-nav-row')) return;
            const link = section.querySelector('a[aria-label]');
            if (link && HIDDEN_LABELS.has(link.getAttribute('aria-label'))) {
                section.classList.add('pplx-hidden-nav-row');
            }
        });
    }

    applySidebarWidth(savedWidth);
    setInterval(() => {
        const el = document.querySelector('div.w-sideBarWidth');
        const _w191 = parseInt(el ? el.style.width : '0');
        if (el && !isNaN(_w191) && _w191 > 60 && _w191 !== savedWidth) applySidebarWidth(savedWidth);
        // 折疊時隱藏青色 resize handle
        const rh = document.getElementById('pplx-resize-handle');
        if (rh) rh.style.display = (!isNaN(_w191) && _w191 < 60) ? 'none' : '';
        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;
        shortcutsInjected = false;
        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');
                }
            });
        });
    }

    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;
    }
    function sanitizeFilename(name) {
        return String(name || 'code')
            .replace(/[\/:*?"<>|]+/g, '-')
            .replace(/\s+/g, ' ')
            .trim()
            .replace(/[. ]+$/g, '')
            .slice(0, 160) || 'code';
    }
    function getDownloadInfo(pre) {
        const txt = pre.innerText || '';
        const nmMatch = txt.match(/@name\s+([^\n]+)/i);
        const name = sanitizeFilename(nmMatch ? nmMatch[1].trim() : 'code');
        const currentVersion = getCurrentScriptVersion();
        const version = currentVersion.toLowerCase().startsWith('v') ? currentVersion : ('v' + currentVersion);
        return { name, version, filename: `${name} ${version}.txt` };
    }
    function getCurrentScriptVersion() {
        try {
            if (typeof GM_info !== 'undefined' && GM_info && GM_info.script && GM_info.script.version) {
                return String(GM_info.script.version).trim();
            }
        } catch (_) {}
        return '1.9.14';
    }
    function syncVersionInCode(code) {
        const currentVersion = getCurrentScriptVersion();
        let out = String(code || '');
        out = out.replace(/^([ 	]*\/\/\s*@version\s+).+$/gmi, `$1${currentVersion}`);
        return out;
    }
    function downloadTextFile(filename, content) {
        const blob = new Blob([content], { type: 'text/plain;charset=utf-8' });
        const a = document.createElement('a');
        a.href = URL.createObjectURL(blob);
        a.download = filename;
        document.body.appendChild(a);
        a.click();
        setTimeout(() => {
            URL.revokeObjectURL(a.href);
            a.remove();
        }, 1000);
    }

    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);
    }

    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);
            const container = document.createElement('div'); container.className = 'pplx-pre-container';
            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 = '展開代碼或收縮代碼'; arrow.setAttribute('aria-label', '展開代碼或收縮代碼');
            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(); }
            };
            const downloadBtn = document.createElement('span');
            downloadBtn.className = 'pplx-code-download'; downloadBtn.textContent = '💾'; downloadBtn.title = '下載代碼';
            downloadBtn.onclick = e => {
                e.preventDefault(); e.stopPropagation();
                const code = getCleanCode(pre);
                const info = getDownloadInfo(pre);
                downloadTextFile(info.filename, code);
                downloadBtn.textContent = '✅';
                setTimeout(() => downloadBtn.textContent = '💾', 2000);
            };
            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); tbar.appendChild(downloadBtn); wrap.appendChild(tbar);
            pre.parentNode.insertBefore(container, pre);
            container.appendChild(wrap); container.appendChild(pre);
            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();
        if (!shortcutsInjected) shortcutsInjected = injectSidebarShortcuts();
        injectNewBtnToHeader();
        hideOriginalNavRows();
    }
    setInterval(maintainUI, 300);
    maintainUI();
    scheduleScrollToBottom();
})();