用户气泡黑金(短消息也亮);发送/语音/停止按钮黑金;输入框与AI消息的选中文本=黑底金字;Alt+G 开关
目前為
// ==UserScript==
// @name ChatGPT Black-Gold (v3.4, black bg + gold text selection)
// @namespace lukas.tools
// @version 3.4
// @description 用户气泡黑金(短消息也亮);发送/语音/停止按钮黑金;输入框与AI消息的选中文本=黑底金字;Alt+G 开关
// @license MIT
// @match https://chat.openai.com/*
// @match https://chatgpt.com/*
// @run-at document-start
// @grant none
// ==/UserScript==
(function () {
'use strict';
const CSS = `
:root{
--deep:#07080a;
--deep2:#0f1013;
--gold-hi:#ffd95a; /* 高光金(更黄) */
--gold:#ffc93a; /* 正金 */
--gold-mid:#e9b030;
--gold-edge:#956a0a;
--ivory:#fff7e6; /* 用户气泡内文字更亮 */
--ivory-2:#f0e6c5;
--edge:#2a2c31;
}
.chat-bgb-on *{
transition: background-color .15s, color .15s, border-color .15s, box-shadow .15s, opacity .15s;
}
/* ===== 按钮:发送 / 语音 / 停止 ===== */
.chat-bgb-on .bgb-action{
color:var(--gold-hi) !important;
background:
linear-gradient(18deg, rgba(255,232,140,.36) 0%, rgba(255,232,140,0) 14%),
radial-gradient(120% 160% at 30% -20%, rgba(255,217,90,.42), transparent 58%),
linear-gradient(180deg, var(--deep2), var(--deep)) !important;
border:1px solid var(--gold) !important;
border-radius:9999px !important;
box-shadow:0 0 0 1px rgba(149,106,10,.35) inset, 0 10px 24px rgba(255,217,90,.18);
}
.chat-bgb-on .bgb-action:hover{
background:linear-gradient(180deg, var(--gold-hi), var(--gold)) !important;
color:#151515 !important;
}
.chat-bgb-on .bgb-action svg{ color:inherit !important; fill:currentColor !important; }
/* ===== 仅用户气泡(AI 不改外观) ===== */
.chat-bgb-on .bgb-user{
position:relative;
color:var(--ivory);
background:
linear-gradient(16deg, rgba(255,232,140,.22) 0%, rgba(255,232,140,0) 12%),
radial-gradient(200px 120px at 22% 6%, rgba(255,217,90,.28), rgba(255,217,90,0) 60%),
radial-gradient(85% 120% at 16% -18%, rgba(255,201,58,.16), rgba(255,201,58,0) 62%),
linear-gradient(180deg, #14161b, #0a0b0e) !important;
border-radius:22px;
box-shadow:0 12px 28px rgba(255,217,90,.08);
overflow:hidden;
}
.chat-bgb-on .bgb-user::before{
content:""; position:absolute; inset:0; border-radius:inherit; padding:1.25px;
background:linear-gradient(135deg, var(--gold-hi) 0%, var(--gold) 42%, var(--gold-edge) 72%, var(--gold-hi) 100%);
-webkit-mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
-webkit-mask-composite:xor; mask-composite:exclude; pointer-events:none;
}
.chat-bgb-on .bgb-user::after{
content:""; position:absolute; inset:2px; border-radius:inherit;
background:
linear-gradient(180deg, rgba(255,255,255,.12), rgba(255,255,255,0) 14%),
linear-gradient(180deg, rgba(0,0,0,0) 68%, rgba(0,0,0,.26) 100%);
box-shadow: inset 0 0 0 1px rgba(255,255,255,.02);
pointer-events:none;
}
.chat-bgb-on .bgb-user :is(p,span,li,div){ text-shadow:0 1px 0 rgba(0,0,0,.22); }
.chat-bgb-on .bgb-user a{ color:var(--gold-hi) !important; }
.chat-bgb-on .bgb-user code, .chat-bgb-on .bgb-user pre{
background:#0f1114 !important; color:var(--ivory) !important; border:1px solid var(--edge) !important;
}
.chat-bgb-on .bgb-user svg{ color:var(--ivory-2); fill:currentColor; }
/* ===== 选中(Selection):黑底金字 ===== */
/* 输入框(composer) */
.chat-bgb-on .bgb-composer::selection,
.chat-bgb-on .bgb-composer *::selection{
background: var(--deep) !important;
color: var(--gold-hi) !important;
}
/* AI 消息文本 */
.chat-bgb-on .bgb-assistSel::selection,
.chat-bgb-on .bgb-assistSel *::selection{
background: var(--deep) !important;
color: var(--gold-hi) !important;
}
`;
const STYLE_ID = 'bgb-style-v34';
function injectCSS(){
if (!document.getElementById(STYLE_ID)){
const s = document.createElement('style');
s.id = STYLE_ID;
s.textContent = CSS;
document.documentElement.appendChild(s);
}
document.documentElement.classList.add('chat-bgb-on');
}
/* ===== 仅给“用户消息”的真实气泡打类 ===== */
function findBubble(turn){
const divs = turn.querySelectorAll('div');
let best=null, score=-1;
for (const el of divs){
if (el.closest('form')) continue;
const cs = getComputedStyle(el);
if (cs.display==='inline') continue;
const r = ['borderTopLeftRadius','borderTopRightRadius','borderBottomLeftRadius','borderBottomRightRadius']
.map(k=>parseFloat(cs[k])||0).reduce((a,b)=>a+b,0);
if (r < 20) continue;
const bg = cs.backgroundColor;
if (!bg || /rgba?\(0,\s*0,\s*0,\s*0\)/.test(bg)) continue;
const pad = ['paddingTop','paddingRight','paddingBottom','paddingLeft']
.map(k=>parseFloat(cs[k])||0).reduce((a,b)=>a+b,0);
const rect = el.getBoundingClientRect();
const sc = pad + r + Math.min(rect.width, 900) + Math.min(rect.height, 600);
if (sc > score){ best = el; score = sc; }
}
return best;
}
function styleUserTurn(turn){
if (turn.dataset.messageStyled==='1') return;
if (turn.getAttribute('data-message-author-role')!=='user') return;
const bubble = findBubble(turn);
if (!bubble) return;
bubble.classList.add('bgb-user');
turn.dataset.messageStyled='1';
}
function styleAllUserTurns(){ document.querySelectorAll('[data-message-author-role]').forEach(styleUserTurn); }
/* ===== 标记输入框容器(用于 selection 覆盖) ===== */
function markComposer(){
const el = document.querySelector('form textarea, form [contenteditable="true"][role="textbox"]');
const box = el ? (el.closest('form') || el) : null;
if (box && !box.classList.contains('bgb-composer')) box.classList.add('bgb-composer');
}
/* ===== 标记 AI 消息容器(用于 selection 覆盖) ===== */
function markAssistantSelection(){
document.querySelectorAll('[data-message-author-role="assistant"]').forEach(el=>{
if (!el.classList.contains('bgb-assistSel')) el.classList.add('bgb-assistSel');
});
}
/* ===== 按钮上色:发送/语音/停止 ===== */
function isVoice(btn){
const t=(btn.getAttribute('aria-label')||btn.title||'').toLowerCase();
const id=(btn.getAttribute('data-testid')||'').toLowerCase();
return /voice|microphone|mic|语音|麦克/.test(t) || /voice|microphone|mic/.test(id);
}
function isSend(btn){
const t=(btn.getAttribute('aria-label')||'').toLowerCase();
const id=(btn.getAttribute('data-testid')||'').toLowerCase();
return /send|发送/.test(t) || /send/.test(id);
}
function isStop(btn){
const t=(btn.getAttribute('aria-label')||'').toLowerCase();
const id=(btn.getAttribute('data-testid')||'').toLowerCase();
return /stop|停止|cancel|中止/.test(t) || /stop/.test(id);
}
function markActions(){
document.querySelectorAll('form button').forEach(b=>{
if (b.classList.contains('bgb-action')) return;
if (isSend(b) || isVoice(b) || isStop(b)) b.classList.add('bgb-action');
});
}
// Init & observers
injectCSS();
styleAllUserTurns();
markComposer();
markAssistantSelection();
markActions();
const mo = new MutationObserver(()=>{
styleAllUserTurns();
markComposer();
markAssistantSelection();
markActions();
});
mo.observe(document.documentElement, {subtree:true, childList:true});
// Alt+G 开关
window.addEventListener('keydown', e=>{
if (e.altKey && (e.key==='g'||e.key==='G')){
e.preventDefault();
const on=document.documentElement.classList.toggle('chat-bgb-on');
localStorage.setItem('bgb_on', on?'on':'off');
}
}, true);
if (localStorage.getItem('bgb_on')==='off'){
document.documentElement.classList.remove('chat-bgb-on');
}
})();