/* 裝飾品（ui/deco.js 畫的）：頭像框、名字特效、徽章、訊息泡泡、個人頁背景。App 和管理後台共用 */

/* 像素字體：Pixelify Sans（SIL Open Font License，見 fonts/OFL.txt），只有英文字母，中文用一般字體 */
@font-face { font-family: 'Pixelify Sans'; font-style: normal; font-weight: 500; font-display: swap; src: url('fonts/PixelifySans.woff2') format('woff2'); }

/* ---------- 頭像框：框畫在頭像外面，不改變頭像佔的大小 ---------- */
.deco-av { position: relative; display: inline-block; flex: none; vertical-align: middle; line-height: 0; }
.deco-av > .avatar { position: relative; z-index: 1; display: inline-flex; }
/* 有框時左右留出框超出的寬度（deco.js 設定 --deco-ext）：不會壓到旁邊的名字，也不會在邊緣被切掉。
   清單裡（好友、名單、對話、留言…）改成每個頭像不管有沒有框都留一樣的空間，頭像和名字才會對齊（ui/style.css） */
.deco-av.deco-framed { margin-inline: var(--deco-ext, 0px); }
/* 會轉的框（圓環、軌道、像素）轉到斜角時外框會變大：layout 包起來，框的特效不算進捲動範圍，
   不然清單最下面那個人的框會讓捲軸一下出現一下消失（不會裁掉特效，paint 才會） */
.deco-av.deco-framed { contain: layout; }
.deco-fx { position: absolute; pointer-events: none; z-index: 2; }
.deco-ring { border-radius: 50%; }
/* --deco-g：光暈大小（deco.js 依頭像大小設定，大頭像 10px） */
.deco-neon { border-radius: 50%; border-style: solid; box-shadow: 0 0 var(--deco-g, 10px) var(--deco-c), 0 0 calc(var(--deco-g, 10px) * 2) color-mix(in srgb, var(--deco-c) 45%, transparent), inset 0 0 calc(var(--deco-g, 10px) * .8) color-mix(in srgb, var(--deco-c) 60%, transparent); animation: deco-neon 1.8s ease-in-out infinite; }
.deco-svgfill { width: 100%; height: 100%; display: block; }
.deco-sq > .avatar { border-radius: 10%; }
.deco-hex > .avatar { border-radius: 0; clip-path: polygon(50% 0, 93% 25%, 93% 75%, 50% 100%, 7% 75%, 7% 25%); }
.deco-orbit { animation: deco-spin 3.2s linear infinite; }
.deco-orbit::before { content: ""; position: absolute; inset: 6%; border-radius: 50%; border: 1px dashed color-mix(in srgb, var(--deco-c) 55%, transparent); }
.deco-arm { position: absolute; inset: 0; }
.deco-arm::after { content: ""; position: absolute; left: 50%; top: 0; width: 13%; height: 13%; margin-left: -6.5%; border-radius: 50%; background: var(--deco-c); box-shadow: 0 0 6px var(--deco-c); }
.deco-crystal { z-index: 0; clip-path: polygon(50% 0, 93% 25%, 93% 75%, 50% 100%, 7% 75%, 7% 25%); overflow: hidden; }
.deco-crystal::after { content: ""; position: absolute; top: -40%; bottom: -40%; left: -60%; width: 40%; background: linear-gradient(90deg, transparent, rgba(255,255,255,.85), transparent); transform: rotate(20deg); animation: deco-shine var(--deco-t, 2.8s) ease-in-out infinite; }
.deco-crystal.deco-still::after { display: none; }
.deco-flame { z-index: 0; }
/* 畫在頭像後面的（翅膀、耳朵、往上飄的東西） */
.deco-back { z-index: 0; }
.deco-glow { border-radius: 50%; border: 1.5px solid; }

/* ---------- 名字 ---------- */
.deco-name-row { display: inline-flex; align-items: center; gap: 4px; min-width: 0; max-width: 100%; }
/* 太長用「…」；clip 加上外距，霓虹光暈、外光不會被裁成方塊 */
.deco-name-row > .deco-name { min-width: 0; overflow: clip; overflow-clip-margin: 16px; text-overflow: ellipsis; white-space: nowrap; }
.deco-badge { flex: none; display: inline-block; vertical-align: -0.15em; }
.deco-clip { -webkit-background-clip: text; background-clip: text; color: transparent !important; background-size: 200% 100%; }
.deco-pixel { font-family: 'Pixelify Sans', "Microsoft JhengHei UI", "Segoe UI", system-ui, sans-serif; letter-spacing: .02em; }
.deco-flicker { animation: deco-flicker 4s linear infinite; }
.deco-glitch { animation: deco-glitch 2.6s steps(1) infinite; }
/* 燃燒的字：火光往上竄（光暈不超過 16px，名字的 clip 外距才不會把它切掉） */
/* 奧術：漸層字流動、兩層光暈一亮一暗，左上、右下兩顆星芒輪流閃（星芒自己有顏色，不跟著漸層字變透明） */
.deco-arcane { position: relative; animation: deco-flow var(--deco-t, 4s) linear infinite, deco-aura 2.6s ease-in-out infinite alternate; }
.deco-arcane.deco-still { animation: deco-aura 2.6s ease-in-out infinite alternate; background-size: 100% 100%; }
.deco-arcane::before, .deco-arcane::after { content: "✦"; position: absolute; font-size: .55em; line-height: 1; color: var(--deco-s); -webkit-text-fill-color: var(--deco-s); text-shadow: 0 0 4px var(--deco-s); pointer-events: none; animation: deco-sparkle 2.4s ease-in-out infinite; }
.deco-arcane::before { left: -.5em; top: -.25em; }
.deco-arcane::after { right: -.45em; bottom: -.05em; animation-delay: -1.2s; }
@keyframes deco-aura { from { filter: drop-shadow(0 0 2px var(--deco-g)) drop-shadow(0 0 5px var(--deco-g)); } to { filter: drop-shadow(0 0 3px var(--deco-g)) drop-shadow(0 0 10px var(--deco-g)); } }
@keyframes deco-sparkle { 0%, 100% { opacity: 0; transform: scale(.3) rotate(0); } 50% { opacity: 1; transform: scale(1) rotate(90deg); } }
/* 打字機：名字後面閃的游標 */
.deco-cursor::after { content: "▌"; color: var(--deco-a); margin-left: 1px; animation: deco-blink 1s steps(1) infinite; }
.deco-fire { text-shadow: 0 0 3px var(--deco-a), 0 -1px 5px var(--deco-a), 0 -3px 8px var(--deco-b), 0 -6px 10px color-mix(in srgb, var(--deco-b) 70%, transparent); animation: deco-fire 1.3s ease-in-out infinite alternate; }

/* ---------- 訊息泡泡 ---------- */
.deco-bubble a, .deco-bubble .mention { color: inherit; }
.deco-pixel-box { border-radius: 0 !important; }
.deco-crt { font-family: ui-monospace, "Cascadia Mono", Consolas, "Microsoft JhengHei UI", monospace; animation: deco-crt 5s steps(1) infinite; }
.deco-edge { border: 2px solid transparent !important; }
.deco-comic { font-weight: 700; border-radius: 14px !important; margin: 0 6px 6px 0; }
.deco-note { border-radius: 2px !important; background-position: 0 0, 0 .45em; }
/* 一呼百應：聲波那一層從左掃到右（前 60%），後面停著等下一次 */
@keyframes deco-herald { 0% { background-position: 100% 0, 0 0; } 60%, 100% { background-position: 0% 0, 0 0; } }
@keyframes deco-starfield { to { background-position: 14px 28px, -19px 19px, 17px -17px, 12px 24px, 0 0; } }
@keyframes deco-sigil { 0%, 100% { box-shadow: 0 0 4px color-mix(in srgb, var(--deco-c) 40%, transparent), 0 0 0 1px color-mix(in srgb, var(--deco-c) 45%, transparent) inset; } 50% { box-shadow: 0 0 14px color-mix(in srgb, var(--deco-c) 80%, transparent), 0 0 0 1px var(--deco-c) inset; } }
@keyframes deco-drift { 0%, 100% { background-position: 0% 0%, 100% 100%, 0 0, 0 0; } 50% { background-position: 100% 60%, 0% 40%, 0 0, 0 0; } }

/* ---------- 個人頁背景 ---------- */
.deco-banner { display: block; width: 100%; height: 100%; }

/* 流光邊框轉的角度：要註冊成角度才能做動畫 */
@property --deco-angle { syntax: '<angle>'; inherits: false; initial-value: 0deg; }

@keyframes deco-spin { to { transform: rotate(360deg); } }
@keyframes deco-angle { to { --deco-angle: 360deg; } }
@keyframes deco-flap { 50% { transform: rotate(13deg); } }
@keyframes deco-twitch { 0%, 82%, 100% { transform: none; } 86% { transform: rotate(-9deg); } 90% { transform: rotate(4deg); } 94% { transform: rotate(-3deg); } }
@keyframes deco-twinkle { 0%, 100% { transform: scale(0) rotate(0); opacity: 0; } 50% { transform: scale(1) rotate(90deg); opacity: 1; } }
@keyframes deco-glint { 0% { background-position: 100% 0, 0 0; } 55%, 100% { background-position: 0% 0, 0 0; } }
@keyframes deco-fire {
  0% { text-shadow: 0 0 3px var(--deco-a), 1px -1px 5px var(--deco-a), -1px -3px 8px var(--deco-b), 1px -6px 10px color-mix(in srgb, var(--deco-b) 70%, transparent); }
  50% { text-shadow: 0 0 4px var(--deco-a), -1px -2px 6px var(--deco-a), 1px -4px 9px var(--deco-b), -1px -7px 9px color-mix(in srgb, var(--deco-b) 55%, transparent); }
  100% { text-shadow: 0 0 3px var(--deco-a), 0 -1px 4px var(--deco-a), 0 -2px 7px var(--deco-b), 1px -5px 10px color-mix(in srgb, var(--deco-b) 80%, transparent); }
}
@keyframes deco-blink { 50% { opacity: 0; } }
@keyframes deco-bob { 50% { transform: translateY(-3px); } }
/* 訊號崩壞：紅藍兩層平常疊在一起，偶爾錯開；整圈偶爾跳一下、雜訊方塊閃一下 */
@keyframes deco-rgb-a { 0%, 70%, 78%, 90%, 100% { transform: none; opacity: 0; } 72% { transform: translate(-3px, 1px); opacity: .9; } 74% { transform: translate(2px, -1px); opacity: .9; } 92% { transform: translate(-2px, 0); opacity: .9; } }
@keyframes deco-rgb-b { 0%, 70%, 78%, 90%, 100% { transform: none; opacity: 0; } 72% { transform: translate(3px, -1px); opacity: .9; } 74% { transform: translate(-2px, 1px); opacity: .9; } 92% { transform: translate(2px, 0); opacity: .9; } }
@keyframes deco-jump { 0%, 71%, 75%, 91%, 100% { transform: none; } 72% { transform: translateX(2px) skewX(-6deg); } 92% { transform: translateX(-1px); } }
.deco-noise { animation: deco-noise 2.4s steps(1) infinite; }
@keyframes deco-noise { 0%, 70%, 76%, 90%, 94%, 100% { opacity: 0; } 72%, 92% { opacity: 1; } }
@keyframes deco-crt { 0%, 96%, 100% { opacity: 1; } 97% { opacity: .82; } 98% { opacity: 1; } 99% { opacity: .9; } }
@keyframes deco-hue { to { filter: hue-rotate(360deg); } }
@keyframes deco-neon { 50% { opacity: .7; box-shadow: 0 0 calc(var(--deco-g, 10px) * .4) var(--deco-c), inset 0 0 calc(var(--deco-g, 10px) * .4) color-mix(in srgb, var(--deco-c) 40%, transparent); } }
@keyframes deco-shine { 0%, 40% { left: -60%; } 100% { left: 130%; } }
@keyframes deco-flow { to { background-position: 200% 0; } }
@keyframes deco-stripes { to { background-position: 28.28px 0; } }
@keyframes deco-flicker { 0%, 18%, 22%, 62%, 64%, 100% { opacity: 1; } 20%, 63% { opacity: .55; } }
@keyframes deco-glitch { 0%, 90%, 100% { text-shadow: none; transform: none; } 92% { text-shadow: -2px 0 var(--deco-a), 2px 0 var(--deco-b); transform: translateX(1px); } 95% { text-shadow: 2px 0 var(--deco-a), -2px 0 var(--deco-b); transform: translateX(-1px); } }

/* 排行獎勵的名字特效（商店不賣）：--ra 主色、--rb 副色、--rc 亮點。deco-lv1 是第 4～10 名，lv4 是第 1 名（名次的差別見下面） */
.deco-rk { position: relative; }
.deco-rk-host { --rk-bg: linear-gradient(0deg, var(--ra), var(--rc), var(--ra), var(--rb), var(--ra)); --rk-size: 100% 300%; background-image: var(--rk-bg); background-size: var(--rk-size); }
.deco-rk-visitors { --rk-bg: linear-gradient(110deg, var(--ra), var(--rb), var(--rc), var(--rb), var(--ra)); --rk-size: 300% 100%; background-image: var(--rk-bg); background-size: var(--rk-size); }
.deco-rk-join { --rk-bg: repeating-linear-gradient(90deg, var(--ra) 0, var(--rb) .5em, var(--ra) 1em); --rk-size: 2em 100%; background-image: var(--rk-bg); background-size: var(--rk-size); }
.deco-rk-followers { background-image: linear-gradient(105deg, transparent 40%, var(--rc) 50%, transparent 60%), linear-gradient(180deg, var(--rc), var(--ra) 55%, var(--rb)); background-size: 250% 100%, 100% 100%; background-repeat: no-repeat; background-position: 100% 0, 0 0; }
.deco-rk-likes { --rk-bg: linear-gradient(90deg, var(--ra), var(--rb), var(--rc), var(--rb), var(--ra)); --rk-size: 200% 100%; background-image: var(--rk-bg); background-size: var(--rk-size); }
.deco-rk-downloads { --rk-bg: repeating-linear-gradient(180deg, var(--ra) 0, var(--rb) .3em, var(--ra) .6em); --rk-size: 100% 1.2em; background-image: var(--rk-bg); background-size: var(--rk-size); }
.deco-rk.deco-lv2, .deco-rk.deco-lv3, .deco-rk.deco-lv4 { animation: var(--rk-move); }
.deco-rk-host { --rk-t: 1.1s; --rk-move: deco-rk-up var(--rk-t) linear infinite; }
.deco-rk-visitors { --rk-t: 1.8s; --rk-move: deco-rk-swirl var(--rk-t) ease-in-out infinite alternate; }
.deco-rk-join { --rk-t: 1s; --rk-move: deco-rk-walk var(--rk-t) linear infinite; }
.deco-rk-followers { --rk-t: 1.8s; --rk-move: deco-glint var(--rk-t) ease-in-out infinite; }
/* 收到的讚：漸層一直往右流（不像之前的心跳閃光一跳一跳） */
.deco-rk-likes { --rk-t: 1.6s; --rk-move: deco-flow var(--rk-t) linear infinite; }
.deco-rk-downloads { --rk-t: .8s; --rk-move: deco-rk-fall var(--rk-t) linear infinite; }
/* lv3 以上：光暈跟著動畫一起跳（用 drop-shadow，背景剪成文字也照得到） */
.deco-rk.deco-lv3, .deco-rk.deco-lv4 { animation: var(--rk-move), deco-rk-glow 1.1s ease-in-out infinite alternate; }
.deco-rk-likes.deco-lv3 { animation: var(--rk-move), deco-rk-beatglow 1.6s ease-in-out infinite; }
/* 條紋字（加入時數、下載數）的光暈太大會糊成一片：只留一圈細的 */
:is(.deco-rk-join, .deco-rk-downloads):is(.deco-lv3, .deco-lv4) { animation: var(--rk-move), deco-rk-glow-thin 1.1s ease-in-out infinite alternate; }
@keyframes deco-rk-glow-thin { from { filter: drop-shadow(0 0 1px var(--ra)); } to { filter: drop-shadow(0 0 3px var(--ra)); } }
/* 名次的差別：第 4～10 名不動、顏色淡一點；第 3 名花紋會動；第 2 名再加光暈和一道掃過的白色反光；
   第 1 名像「奧術」：花紋動得快、兩層會呼吸又變色的光暈、左上和右下兩顆輪流閃的星芒（星芒在名字外距 16px 內，不會被切到） */
.deco-rk.deco-lv1 { filter: saturate(.75) brightness(.92); }
:is(.deco-lv3, .deco-lv4).deco-rk:not(.deco-rk-followers) { background-image: linear-gradient(150deg, transparent 40%, rgba(255, 255, 255, .85) 50%, transparent 60%), var(--rk-bg); background-size: 300% 300%, var(--rk-size); }
/* 讚的花紋往右流一圈是 200%：反光那層橫向也用 200%，一圈結束剛好接回原位（300% 會每圈跳一下） */
.deco-rk-likes:is(.deco-lv3, .deco-lv4) { background-size: 200% 300%, var(--rk-size); }
.deco-rk.deco-lv4 { animation: var(--rk-move), deco-rk-arcane 2.2s ease-in-out infinite; animation-duration: calc(var(--rk-t, 1s) * .7), 2.2s; }
.deco-rk.deco-lv4::before, .deco-rk.deco-lv4::after { content: "✦"; position: absolute; font-size: .6em; line-height: 1; color: #ffffff; -webkit-text-fill-color: #ffffff; text-shadow: 0 0 3px var(--rc), 0 0 6px var(--ra); pointer-events: none; animation: deco-sparkle 1.8s ease-in-out infinite; }
.deco-rk.deco-lv4::before { left: -.55em; top: -.3em; }
.deco-rk.deco-lv4::after { right: -.5em; bottom: -.1em; animation-delay: -.9s; }
@keyframes deco-rk-arcane {
  0%, 100% { filter: drop-shadow(0 0 2px var(--rc)) drop-shadow(0 0 7px var(--ra)); }
  50% { filter: drop-shadow(0 0 3px #ffffff) drop-shadow(0 0 11px var(--rb)); }
}
@keyframes deco-rk-up { to { background-position: 0 -300%; } }
@keyframes deco-rk-swirl { from { background-position: 0 0; } to { background-position: 100% 0; } }
@keyframes deco-rk-walk { to { background-position: 2em 0; } }
@keyframes deco-rk-fall { to { background-position: 0 1.2em; } }
@keyframes deco-rk-glow { from { filter: drop-shadow(0 0 2px var(--ra)); } to { filter: drop-shadow(0 0 3px var(--ra)) drop-shadow(0 0 8px var(--rb)); } }
/* 心跳光暈：一下慢慢亮起、慢慢暗下（每格的濾鏡都是同樣三個，瀏覽器才會平滑地補間，不會一格一格跳） */
@keyframes deco-rk-beatglow { 0%, 100% { filter: brightness(1) drop-shadow(0 0 2px var(--ra)) drop-shadow(0 0 1px var(--rb)); } 50% { filter: brightness(1.12) drop-shadow(0 0 4px var(--ra)) drop-shadow(0 0 8px var(--rb)); } }
@keyframes deco-rk-ember { 0% { opacity: 0; transform: translateY(.3em); } 30% { opacity: 1; } 100% { opacity: 0; transform: translateY(-.6em); } }

@media (prefers-reduced-motion: reduce) {
  .deco-fx, .deco-fx::before, .deco-fx::after, .deco-fx *, .deco-name, .deco-bubble { animation: none !important; }
}
/* 頭像框畫在頭像外面：不管放在哪裡（個人連結、Addon 卡片的作者等會把 span 裁切的地方）都不能被裁掉，不然會變成方形 */
.deco-av { overflow: visible !important; text-overflow: clip !important; }
/* 名字特效的光暈同理：太長還是用「…」，但留外距給光暈 */
.deco-name, .deco-name-row { overflow: clip !important; overflow-clip-margin: 16px; }
/* 外面那一層也會裁（對話列表的名字、個人連結、作品卡片的作者、聊天室頂部、右上角的名字…都是 overflow: hidden 加「…」）：
   光暈被裁成一個方框。有特效名字的那一層改成 clip 加外距，「…」照樣有 */
:is(.conv-name, a.person > span, .addon-by > span, .thread-head > .person > *, .me-name, .mention-name):has(.deco-name) { overflow: clip !important; overflow-clip-margin: 16px; }
/* Safari（iPhone）不支援 overflow-clip-margin，上面留的外距沒有用，光暈照樣被裁成方框：
   改用內距把裁切範圍撐大、再用負外距抵銷（排版位置不變；content-box 讓 max-width 不把內距算進去）。漸層字的漸層照舊對齊文字，不跟著內距變寬。
   撐大的範圍會蓋到旁邊的按鈕（例如上一則留言的「回覆」）：不接收點擊，點名字時交給外面的連結、按鈕 */
@supports not (overflow-clip-margin: 16px) {
  .deco-name, .deco-name-row, :is(.conv-name, a.person > span, .addon-by > span, .thread-head > .person > *, .me-name, .mention-name):has(.deco-name) { box-sizing: content-box; padding: 16px; margin: -16px; pointer-events: none; }
  .deco-clip { background-origin: content-box; }
  /* 奧術名字的兩顆小星星：位置是從內距外緣算的，撐大的 16px 要扣回來，不然會跑到名字右下方 16px 外、被切到只剩一個小點 */
  .deco-arcane::before { left: calc(16px - .5em); top: calc(16px - .25em); }
  .deco-arcane::after { right: calc(16px - .45em); bottom: calc(16px - .05em); }
  .deco-rk.deco-lv4::before { left: calc(16px - .55em); top: calc(16px - .3em); }
  .deco-rk.deco-lv4::after { right: calc(16px - .5em); bottom: calc(16px - .1em); }
}
