:root{--ink:oklch(96% .025 270);--muted:oklch(76% .035 270);--bg:oklch(15% .04 275);--surface:oklch(21% .055 275);--surface-2:oklch(25% .07 275);--line:oklch(43% .08 275);--violet:oklch(70% .18 300);--blue:oklch(72% .16 235);--yellow:oklch(86% .16 90);--green:oklch(78% .16 155);--red:oklch(72% .17 25);--space-1:.5rem;--space-2:1rem;--space-3:1.5rem;--space-4:2.5rem;--space-5:clamp(3rem,9vw,8rem);--text:clamp(1rem,1.3vw,1.15rem);--title:clamp(2.7rem,8vw,7rem);--h2:clamp(1.6rem,3vw,2.5rem);--ease:cubic-bezier(.2,.8,.2,1);--fast:160ms;--slow:500ms}*{box-sizing:border-box}html{background:var(--bg);color:var(--ink);font:var(--text)/1.55 system-ui,sans-serif}body{margin:0;min-width:320px;background:radial-gradient(circle at 80% 5%,oklch(28% .12 285 / .55),transparent 32rem),var(--bg);min-height:100svh}a{color:inherit;text-decoration:none}button,input,textarea{font:inherit}button{cursor:pointer}.site-header{display:flex;justify-content:space-between;align-items:center;padding:var(--space-3) clamp(1rem,5vw,4rem);border-bottom:1px solid var(--line)}.brand{font-weight:800;letter-spacing:.04em}.signal,.eyebrow,.section-kicker{color:var(--blue);font-size:clamp(.68rem,1vw,.8rem);letter-spacing:.16em;font-weight:800}.home-shell{max-width:1180px;margin:auto;padding:var(--space-5) clamp(1rem,6vw,5rem) 5rem;display:grid;grid-template-columns:minmax(0,1.3fr) minmax(250px,.7fr);gap:clamp(3rem,10vw,10rem);align-items:end}.intro{position:relative}.avatar{display:grid;place-items:center;width:4.5rem;height:4.5rem;background:linear-gradient(135deg,var(--violet),var(--blue));color:var(--bg);font-size:2rem;clip-path:polygon(50% 0,100% 25%,86% 86%,15% 100%,0 35%);box-shadow:1rem 1rem 0 oklch(30% .1 280 / .45);margin-bottom:var(--space-4)}h1{font-size:var(--title);line-height:1.05;letter-spacing:normal;margin:var(--space-2) 0 var(--space-3);max-width:9ch}h2{font-size:var(--h2);line-height:1.05;margin:.35rem 0}.lead{max-width:32rem;color:var(--muted);font-size:clamp(1.2rem,2.4vw,1.8rem);margin:0 0 var(--space-4)}.actions{display:flex;gap:var(--space-2);flex-wrap:wrap}.button{display:inline-flex;align-items:center;justify-content:center;gap:.8rem;min-height:48px;padding:.65rem 1.2rem;border:1px solid var(--line);transition:transform var(--fast) var(--ease),opacity var(--fast) var(--ease),clip-path var(--fast) var(--ease)}.button.primary{background:var(--yellow);color:var(--bg);border-color:var(--yellow);font-weight:800;clip-path:polygon(0 8%,96% 0,100% 86%,4% 100%)}.button.quiet{background:var(--surface);color:var(--ink)}.button:hover{transform:translateY(-3px)}.button:active{transform:translateY(1px)}.button:focus-visible,.amounts button:focus-visible,input:focus-visible,textarea:focus-visible{outline:3px solid var(--blue);outline-offset:3px}.recent{background:linear-gradient(145deg,var(--surface-2),var(--surface));padding:var(--space-3);box-shadow:1.2rem 1.2rem 0 oklch(9% .04 275 / .65);transform:rotate(1deg)}.recent ul{list-style:none;padding:0;margin:var(--space-3) 0 0}.recent li{display:flex;gap:1rem;padding:1rem 0;border-top:1px solid var(--line)}.recent-amount{color:var(--yellow);font-weight:900;white-space:nowrap}.recent small{display:block;color:var(--muted);margin-top:.2rem}.doc-footer{display:flex;flex-wrap:wrap;gap:var(--space-3);}.doc-shell{max-width:46rem;margin:auto;padding:var(--space-5) clamp(1rem,5vw,3rem)}.doc-shell section{margin-bottom:var(--space-4)}.doc-shell h2{font-size:1.4rem;margin-top:var(--space-4)}.doc-shell ul{color:var(--muted)}.doc-shell p{color:var(--muted);max-width:40rem}.doc-shell strong,.doc-shell em{color:var(--ink)}.doc-nav{display:flex;flex-wrap:wrap;gap:var(--space-3);border-top:1px solid var(--line);padding-top:var(--space-3);margin-top:var(--space-5)}.doc-nav a:hover{color:var(--blue)}footer{display:flex;gap:var(--space-3);padding:var(--space-3) clamp(1rem,5vw,4rem);color:var(--muted);font-size:.85rem}footer a:hover{color:var(--ink)}.form-shell,.result-shell{max-width:720px;margin:auto;padding:var(--space-5) clamp(1rem,5vw,3rem)}.form-shell h1,.result-shell h1{font-size:clamp(2.5rem,7vw,5rem);max-width:11ch}.subtle,.fine-print{color:var(--muted)}form{margin-top:var(--space-4)}fieldset,.field{border:0;padding:0;margin:0 0 var(--space-4)}legend,label{display:block;font-weight:800;margin-bottom:.55rem}label span{font-weight:400;color:var(--muted);font-size:.85em}.amounts{display:grid;grid-auto-flow:column;grid-auto-columns:1fr;gap:.5rem;margin-bottom:1rem}.amounts button{min-height:52px;border:1px solid var(--line);background:var(--surface);color:var(--ink);transition:transform var(--fast) var(--ease),background var(--fast) var(--ease)}.amounts button:hover{background:var(--surface-2);transform:translateY(-2px)}.amounts button[aria-pressed=true]{background:var(--violet);color:var(--bg);border-color:var(--violet);font-weight:800}.amounts button[aria-pressed=true]::after{content:"✓";margin-left:.35em}input:not([type=checkbox]),textarea{display:block;width:100%;border:1px solid var(--line);background:var(--surface);color:var(--ink);padding:.75rem 1rem;border-radius:0}textarea{resize:vertical}small{color:var(--muted)}.check{display:flex;gap:.6rem;align-items:center;font-weight:400;margin-bottom:var(--space-3)}.check input{width:20px;height:20px;accent-color:var(--violet)}.submit{width:100%;font-size:1.1rem}.form-error{color:var(--red);border-left:3px solid var(--red);padding-left:1rem}.handoff{text-align:center;max-width:520px;margin:auto;padding:var(--space-5) 1rem}.handoff h1{margin-left:auto;margin-right:auto;font-size:clamp(2.6rem,7vw,5rem)}.handoff .avatar{margin-left:auto;margin-right:auto}.status-mark{font-size:3rem;font-weight:900;width:4.5rem;height:4.5rem;display:grid;place-items:center;margin-bottom:var(--space-3)}.waiting{color:var(--blue);background:oklch(30% .08 235)}.warning{color:var(--yellow);background:oklch(30% .09 90)}.success{color:var(--green);background:oklch(27% .08 155)}.neutral{color:var(--muted);background:var(--surface)}.payment-card{margin:var(--space-4) 0;padding:var(--space-3);background:var(--surface);border-left:4px solid var(--yellow);box-shadow:.8rem .8rem 0 oklch(9% .04 275 / .7)}.payment-row{display:grid;grid-template-columns:1fr auto auto;align-items:center;gap:.75rem;border-top:1px solid var(--line);padding:1rem 0;margin:0}.payment-row strong{font:900 clamp(1.25rem,4vw,2rem)/1 ui-monospace,monospace;letter-spacing:.1em}.copy{min-height:44px;background:transparent;border:1px solid var(--line);color:var(--ink);padding:.4rem .6rem}.copy:hover{border-color:var(--blue);color:var(--blue)}.deadline{color:var(--yellow);font-weight:800}.callout{border-left:3px solid var(--green);padding-left:1rem}@media(max-width:700px){.home-shell{display:block}.recent{margin-top:var(--space-5)}.site-header{padding:1rem}.form-shell,.result-shell{padding-top:var(--space-4)}.payment-row{grid-template-columns:1fr auto}.payment-row strong{grid-column:1/-1;grid-row:2}.copy{grid-column:2;grid-row:1}}
@media(prefers-reduced-motion:reduce){*,*::before,*::after{scroll-behavior:auto!important;transition-duration:0ms!important;animation-duration:0ms!important}}
.embed-shell{max-width:1100px;margin:auto;padding:var(--space-5) clamp(1rem,5vw,4rem)}.embed-shell h1{font-size:clamp(2.5rem,7vw,5.5rem);max-width:12ch}.source-picker{max-width:28rem;margin:var(--space-4) 0}.source-picker select{width:100%;padding:.75rem 1rem;background:var(--surface);color:var(--ink);border:1px solid var(--line)}.embed-grid{display:grid;grid-template-columns:minmax(220px,360px) 1fr;gap:clamp(2rem,7vw,6rem);align-items:center;margin:var(--space-5) 0}.qr-preview{background:var(--surface);padding:var(--space-3);box-shadow:.9rem .9rem 0 oklch(9% .04 275 / .7)}.qr-preview img{display:block;width:100%;height:auto;background:white}.encoded{font-size:.85rem;color:var(--muted);overflow-wrap:anywhere}.encoded a{color:var(--yellow)}.embed-controls .section-kicker{margin-top:var(--space-3)}.download-links{display:flex;flex-wrap:wrap;gap:.6rem}.download-links .button{font-size:.9rem}.snippets{display:grid;gap:var(--space-3);margin-top:var(--space-5)}.snippet{position:relative}.snippet textarea{font: .85rem/1.45 ui-monospace,monospace;padding-right:5rem;overflow:auto}.snippet .copy{position:absolute;right:.6rem;bottom:.6rem;background:var(--surface-2)}
@media(max-width:700px){.embed-grid{grid-template-columns:1fr}.qr-preview{max-width:360px;margin:auto}}
.admin-shell{max-width:1500px;margin:auto;padding:var(--space-4) clamp(1rem,4vw,3rem) 5rem}.admin-shell h1{font-size:clamp(2.5rem,6vw,5rem);max-width:none}.admin-filters{display:flex;align-items:end;gap:var(--space-2);flex-wrap:wrap;padding:var(--space-3);background:var(--surface);border:1px solid var(--line)}.admin-filters>div{min-width:10rem;flex:1}.admin-filters input,.admin-filters select{width:100%;padding:.65rem;background:var(--surface-2);color:var(--ink);border:1px solid var(--line)}.admin-summary{display:flex;align-items:center;gap:var(--space-2);flex-wrap:wrap;color:var(--muted)}.admin-summary .button{margin-left:auto}.admin-table-wrap{overflow-x:auto;background:var(--surface);border:1px solid var(--line)}.admin-table{width:100%;border-collapse:collapse;min-width:1050px}.admin-table th,.admin-table td{padding:.8rem;border-bottom:1px solid var(--line);text-align:left;vertical-align:top}.admin-table th{color:var(--muted);font-size:.8rem;letter-spacing:.05em}.admin-table td form{display:inline-block;margin:0 .4rem .4rem 0}.admin-table .simulated{background:oklch(30% .09 90 / .2)}.sim-label{color:var(--yellow);font-size:.8em}.pagination{display:flex;gap:var(--space-2);justify-content:center;margin:var(--space-3)}
@media(max-width:700px){.admin-table-wrap{overflow:visible;background:none;border:0}.admin-table{min-width:0}.admin-table thead{display:none}.admin-table,.admin-table tbody,.admin-table tr,.admin-table td{display:block;width:100%}.admin-table tr{margin-bottom:var(--space-2);padding:var(--space-2);background:var(--surface);border:1px solid var(--line)}.admin-table td{display:grid;grid-template-columns:8rem 1fr;gap:.7rem;padding:.5rem 0;border:0}.admin-table td::before{content:attr(data-label);color:var(--muted);font-size:.85em}.admin-table td[colspan]{display:block}.admin-table td[colspan]::before{content:none}.admin-summary .button{margin-left:0}}
.range-tabs{display:flex;flex-wrap:wrap;gap:var(--space-2);align-items:center;margin:var(--space-3) 0 var(--space-4)}
.range-tabs a{padding:.45rem .9rem;border:1px solid var(--line);color:var(--muted);transition:transform var(--fast) var(--ease),color var(--fast) var(--ease)}
.range-tabs a:hover{transform:translateY(-2px);color:var(--ink)}
.range-tabs a[aria-current]{background:var(--violet);border-color:var(--violet);color:var(--bg);font-weight:800}
.kpi-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));gap:var(--space-2);margin-bottom:var(--space-2)}
.kpi{background:var(--surface);border-left:3px solid var(--line);padding:var(--space-2) var(--space-3)}
.kpi-lead{border-left-color:var(--yellow)}
.kpi-label{display:block;color:var(--muted);font-size:.8rem;letter-spacing:.06em}
.kpi-value{display:block;font-size:clamp(1.5rem,3.5vw,2.4rem);line-height:1.15;margin-top:.3rem}
.kpi-lead .kpi-value{color:var(--yellow)}
.chart-block{margin-top:var(--space-4);background:var(--surface);padding:var(--space-3);overflow:hidden}
.chart-block h2{font-size:1.2rem;margin:0}
.chart-sub{color:var(--muted);font-size:.85rem;margin:.3rem 0 var(--space-3)}
.chart{width:100%;height:auto;display:block}
.chart .col,.chart .row{transition:opacity var(--fast) var(--ease)}
.chart:hover .col,.chart:hover .row{opacity:.45}
.chart .col:hover,.chart .row:hover{opacity:1}
.chart-empty{color:var(--muted);margin:0}

/* 來源頁的展開列。展開區是獨立的 <tr><td colspan> 整列，不是塞在「操作」欄裡 —— 欄寬會把 textarea 壓成一行、複製鈕擠出欄外、QR 與下載鈕堆成一長條。 */
.detail-row>td{padding-top:0;border-bottom:2px solid var(--line)}.detail-row summary{cursor:pointer;color:var(--blue);font-size:.85rem;letter-spacing:.06em;font-weight:800;padding:.5rem 0}.detail-row summary:hover{color:var(--yellow)}.source-detail{display:grid;grid-template-columns:minmax(200px,240px) minmax(0,1fr);gap:var(--space-3);align-items:start;padding:var(--space-2) 0 var(--space-3)}.source-detail .qr-preview{padding:var(--space-2);box-shadow:none}.source-detail .qr-preview img{margin-bottom:.6rem}.source-detail .download-links .button{min-height:38px;padding:.3rem .6rem;font-size:.8rem}.source-snippets{display:grid;gap:var(--space-2);min-width:0}.source-snippets label{margin-bottom:.3rem;font-size:.85rem}.source-edit{grid-column:1/-1;display:flex;gap:var(--space-2);align-items:end;flex-wrap:wrap;margin:0;padding-top:var(--space-2);border-top:1px solid var(--line)}.source-edit .field{flex:1;min-width:11rem;margin:0}@media(max-width:700px){.source-detail{grid-template-columns:1fr}.source-edit{display:block}.source-edit .field{margin-bottom:var(--space-2)}}

/* 中文標題不要用 ch 當寬度上限：ch 是數字 0 的寬（約 .55em），
   拿來限中文會在莫名其妙的字數斷行，留下孤字。改由容器寬決定，
   再用 text-wrap:balance 讓兩行平均分配，避免「去」這種單字落單。 */
.form-shell h1,.result-shell h1{max-width:none;text-wrap:balance}
/* 滿寬按鈕的斜切要用固定像素，不能用百分比。
   .button.primary 的 clip-path 是按窄按鈕調的百分比座標，
   拉到表單全寬後左右各被削掉三十幾 px，看起來像壞掉。 */
.button.primary.submit{clip-path:polygon(0 0,calc(100% - 14px) 0,100% 100%,14px 100%)}
/* 共用頁尾置中。頁面內容是置中的窄欄（form-shell / result-shell / doc-shell），
   頁尾卻是全幅靠左，會看起來像掉在角落的孤兒。
   置中對四個共用頁都成立；若改成對齊內容欄左緣，就得為三種不同欄寬做判斷。 */
.doc-footer{justify-content:center}

/* 付款方式選項橫排。.check 原本是為 /donate 那顆單獨的「同意公開」勾選框設計的
   （block 級 flex ＋ 1.5rem 下邊距），整組五個塞進後台表單就堆成一條直的，
   在 .admin-filters 那種橫向 flex 裡更慘 —— fieldset 沒有 flex 尺寸，
   被壓成 409px 寬、576px 高，標籤一個字一行，旁邊四個輸入框被 align-items:end
   推到底部，上面留一大片空白。改成自成一列、選項橫向 wrap 的 chip。 */
.pay-methods{flex:1 1 100%;margin:0}
.pay-methods legend{font-size:.85rem;letter-spacing:.05em;color:var(--muted);margin-bottom:.5rem}
.pay-methods .opts{display:flex;flex-wrap:wrap;gap:.5rem}
.pay-methods .check{margin:0;gap:.5rem;padding:.45rem .8rem;border:1px solid var(--line);background:var(--surface-2);transition:border-color var(--fast) var(--ease)}
.pay-methods .check:hover{border-color:var(--blue)}
.pay-methods .check input{width:18px;height:18px;flex:none}
.pay-methods .check:has(input:checked){border-color:var(--violet);background:oklch(32% .1 300 / .5)}
.pay-methods .check:has(input:disabled){opacity:.6;background:transparent}
.pay-methods .check:has(input:disabled):hover{border-color:var(--line)}
.pay-methods .check small{font-size:.8rem}
/* 展開列裡的編輯表單一直不是 flex：`.admin-table td form`（0,1,2）比 `.source-edit`
   （0,1,0）特異性高，display:inline-block 贏了 display:flex，又因為它是 grid item
   被 blockify 成 block，所以 .field 的 flex:1 從來沒生效過，三個欄位各佔一整列。
   加上付款方式那組之後才明顯。這裡把特異性拉高到蓋得過去。 */
.admin-table td form.source-edit{display:flex;margin:0}
.pay-methods .pay-note{color:var(--muted);font-size:.8rem;margin:.55rem 0 0}

/* 一個來源在 DOM 上是兩個 <tr>（資料列＋展開列），畫面上要讀成同一塊。
   同組共用底色與左側色條，組與組之間用外層底色的粗下邊框撐出間隙 ——
   <tr> 吃不到 margin，間隙只能由 border 做。左色條同時帶語意：
   啟用是紫色、停用轉成線條色並把文字轉灰，掃一眼就知道哪幾條連結是活的。 */
/* border-collapse 從 collapse 改成 separate：合併模式下，跨欄那格的下邊框會被
   拆成每欄一段畫，欄寬是小數時段與段之間留下 1px 的接縫，間隙帶上會出現一排
   淡淡的直線。separate ＋ border-spacing:0 讓它一次畫完，外觀其他部分不變。 */
.source-table{border-collapse:separate;border-spacing:0}
.admin-table tr.source-row,.admin-table tr.detail-row{background:var(--surface-2)}
.admin-table tr.source-row>td{border-bottom:0;padding-top:1.1rem}
.admin-table tr.detail-row>td{border-bottom:14px solid var(--bg);padding-bottom:.9rem}
.admin-table tr.source-row>td:first-child,.admin-table tr.detail-row>td:first-child{border-left:3px solid var(--violet)}
.admin-table tr.source-row.is-off>td:first-child,.admin-table tr.detail-row.is-off>td:first-child{border-left-color:var(--line)}
.admin-table tr.source-row.is-off>td{color:var(--muted)}
@media(max-width:700px){
.admin-table tr.source-row>td,.admin-table tr.detail-row>td{background:none;border-bottom:0;border-left:0;padding-top:.5rem}
.admin-table tr.source-row{margin-bottom:0;border-bottom:0;border-left:3px solid var(--violet)}
.admin-table tr.detail-row{border-top:0;border-left:3px solid var(--violet)}
.admin-table tr.source-row.is-off,.admin-table tr.detail-row.is-off{border-left-color:var(--line)}
}
