fc / src /theme.py
Chuiguohuang's picture
feat(ui): 各榜单加折叠——Hero+前3常驻,第4名起展开可见完整榜单
e0345d0 verified
Raw History Blame Contribute Delete
39.2 kB
"""品牌主题:藏青 / 红 / 金(取自肆带贰队徽)。
提供注入用的 CSS 字符串与若干小型 HTML 构件(队徽、徽章、统计卡)。
CSS 用普通字符串(非 f-string),避免大括号转义。
"""
from __future__ import annotations
from shiny import ui
from .config import CREST_URL
CSS = """
:root{
--navy-deep:#0A1730; --navy:#11254A; --navy-2:#16305C; --navy-line:#24417a;
--red:#C8102E; --red-2:#E2384B;
--gold:#D4AF37; --gold-2:#EBCB6B; --gold-dim:rgba(212,175,55,.30);
--blue:#3DA5D9; --green:#1FA971;
--cream:#F2ECDD; --muted:#9DB0D0; --ink:#0A1325;
}
*{box-sizing:border-box}
html{background:var(--navy-deep)}
body{
margin:0; color:var(--cream); min-height:100vh;
font-family:"Segoe UI","Microsoft YaHei","PingFang SC",system-ui,sans-serif;
background:
radial-gradient(1100px 680px at 88% 0%, rgba(200,16,46,.22), transparent 60%),
radial-gradient(900px 600px at 4% 6%, rgba(61,165,217,.16), transparent 58%),
linear-gradient(180deg,#0d1b38 0%, var(--navy-deep) 60%, var(--navy-deep) 100%);
background-repeat:no-repeat;
-webkit-font-smoothing:antialiased;
}
.sde-shell{max-width:1080px;margin:0 auto;padding:18px 18px 64px}
/* ---------- 顶栏 ---------- */
.sde-topbar{display:flex;align-items:center;gap:14px;padding:10px 4px 18px;flex-wrap:wrap}
.sde-brand{display:flex;align-items:center;gap:14px}
.sde-brand .zh{font-size:26px;font-weight:800;letter-spacing:.14em;line-height:1;
background:linear-gradient(180deg,var(--gold-2),var(--gold));-webkit-background-clip:text;
background-clip:text;color:transparent}
.sde-brand .en{font-size:11px;letter-spacing:.30em;color:var(--muted);margin-top:6px;text-transform:uppercase}
.sde-spacer{flex:1}
.sde-welcome{color:var(--muted);font-size:14px;margin-right:6px}
.sde-welcome b{color:var(--cream)}
/* ---------- 队徽 ---------- */
.sde-crest{border-radius:50%;background:radial-gradient(circle at 50% 38%,#ffffff,#eef2f7);
border:2px solid var(--gold);box-shadow:0 8px 26px -8px rgba(0,0,0,.7),0 0 0 4px rgba(212,175,55,.12);
display:grid;place-items:center;overflow:hidden;flex:0 0 auto}
.sde-crest img{width:86%;height:86%;object-fit:contain;display:block}
/* ---------- 卡片 ---------- */
.sde-card{background:linear-gradient(180deg,rgba(255,255,255,.045),rgba(255,255,255,.015));
border:1px solid var(--gold-dim);border-radius:18px;padding:18px 20px;margin-bottom:18px;
box-shadow:0 24px 50px -34px rgba(0,0,0,.85), inset 0 1px 0 rgba(255,255,255,.04)}
.sde-card-h{display:flex;align-items:center;gap:10px;margin:0 0 14px}
.sde-card-h .t{font-size:15px;font-weight:800;letter-spacing:.10em;color:var(--cream)}
.sde-card-h .ic{font-size:18px}
.sde-card-h::after{content:"";flex:1;height:1px;
background:linear-gradient(90deg,var(--gold-dim),transparent)}
.sde-sub{color:var(--muted);font-size:12.5px;margin:-6px 0 14px}
/* ---------- 统计卡 ---------- */
.sde-stats{display:grid;grid-template-columns:repeat(5,1fr);gap:12px}
.sde-stats.cols-4{grid-template-columns:repeat(4,1fr)}
.sde-stats.cols-3{grid-template-columns:repeat(3,1fr)}
@media(max-width:760px){.sde-stats,.sde-stats.cols-4,.sde-stats.cols-3{grid-template-columns:repeat(2,1fr)}}
.sde-stat{background:linear-gradient(180deg,rgba(255,255,255,.05),rgba(255,255,255,.01));
border:1px solid rgba(255,255,255,.08);border-radius:14px;padding:14px 12px;text-align:center}
.sde-stat .v{font-size:30px;font-weight:800;line-height:1;color:var(--gold-2)}
.sde-stat .l{font-size:12px;color:var(--muted);margin-top:7px;letter-spacing:.05em}
.sde-stat .s{font-size:11px;color:var(--muted);margin-top:3px;opacity:.85}
.sde-stat.accent-red .v{color:var(--red-2)}
.sde-stat.accent-blue .v{color:var(--blue)}
.sde-stat.accent-green .v{color:var(--green)}
.sde-stat.accent-cream .v{color:var(--cream)}
/* ---------- 表格 ---------- */
.sde-table-wrap{overflow-x:auto}
.sde-table{width:100%;border-collapse:collapse;font-size:14px}
.sde-table th{text-align:left;font-size:11px;letter-spacing:.10em;text-transform:uppercase;
color:var(--gold);font-weight:700;padding:8px 10px;border-bottom:1px solid var(--gold-dim);white-space:nowrap}
.sde-table td{padding:9px 10px;border-bottom:1px solid rgba(255,255,255,.06);color:var(--cream);vertical-align:middle}
.sde-table tbody tr:hover{background:rgba(212,175,55,.06)}
.sde-table tr.is-me{background:rgba(212,175,55,.12)}
.sde-table tr.is-me td:first-child{box-shadow:inset 3px 0 0 var(--gold)}
.sde-num{text-align:right;font-variant-numeric:tabular-nums;font-weight:700}
.sde-rank{width:42px;text-align:center;font-weight:800;color:var(--muted)}
.sde-jersey{display:inline-block;min-width:30px;padding:1px 7px;margin-right:8px;border-radius:6px;
background:rgba(61,165,217,.16);border:1px solid rgba(61,165,217,.35);color:#bfe2f6;
font-size:12px;font-weight:700;text-align:center}
.sde-me-tag{margin-left:8px;font-size:11px;color:var(--ink);background:var(--gold);
padding:0 7px;border-radius:20px;font-weight:800}
.sde-empty{color:var(--muted);text-align:center;padding:24px;font-size:13px}
/* 结果徽章 */
.badge-res{display:inline-block;width:22px;height:22px;line-height:22px;text-align:center;
border-radius:6px;font-size:12px;font-weight:800;color:#fff}
.badge-W{background:var(--green)} .badge-D{background:#6b7a99} .badge-L{background:var(--red)}
.ha-pill{font-size:11px;padding:1px 8px;border-radius:20px;border:1px solid rgba(255,255,255,.18);color:var(--muted)}
.ha-home{color:var(--gold-2);border-color:var(--gold-dim)}
/* ---------- 表单 / 控件 ---------- */
.form-label{color:var(--cream);font-size:13px;font-weight:600;margin-bottom:5px}
.form-control,.form-select{background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.16);
color:var(--cream);border-radius:10px}
.form-control:focus,.form-select:focus{background:rgba(255,255,255,.09);border-color:var(--gold);
box-shadow:0 0 0 .18rem rgba(212,175,55,.22);color:var(--cream)}
.form-control::placeholder{color:#7e90b3}
.form-select option{color:#10203f;background:#eaf0fb}
.form-check-input{background-color:rgba(255,255,255,.12);border-color:rgba(255,255,255,.3)}
.form-check-input:checked{background-color:var(--gold);border-color:var(--gold)}
.shiny-input-container{margin-bottom:12px}
/* 按钮 */
.btn{border-radius:10px;font-weight:700;letter-spacing:.02em}
.btn-primary,.btn-default.btn-primary{background:linear-gradient(180deg,var(--gold-2),var(--gold));
border:none;color:#1a1305}
.btn-primary:hover{filter:brightness(1.07);color:#1a1305}
.btn-danger{background:var(--red);border:none}
.btn-outline-light{border-color:rgba(255,255,255,.35);color:var(--cream)}
.btn-outline-light:hover{background:rgba(255,255,255,.1);color:#fff}
/* 导航 */
.nav-tabs,.nav-pills{border-bottom:1px solid var(--gold-dim);gap:6px;margin-bottom:18px}
.nav-tabs .nav-link,.nav-pills .nav-link{color:var(--muted);border:none;font-weight:700;
letter-spacing:.04em;padding:9px 16px;border-radius:10px 10px 0 0}
.nav-tabs .nav-link:hover{color:var(--cream);background:rgba(255,255,255,.04)}
.nav-tabs .nav-link.active,.nav-pills .nav-link.active{color:var(--ink);
background:linear-gradient(180deg,var(--gold-2),var(--gold));border:none}
/* ---------- 登录页 ---------- */
.sde-login-wrap{display:flex;justify-content:center;padding:6vh 16px 40px}
.sde-login{width:100%;max-width:380px;text-align:center}
.sde-login .sde-crest{margin:0 auto 18px}
.sde-login .zh{font-size:34px;font-weight:800;letter-spacing:.18em;
background:linear-gradient(180deg,var(--gold-2),var(--gold));-webkit-background-clip:text;
background-clip:text;color:transparent}
.sde-login .en{font-size:11px;letter-spacing:.34em;color:var(--muted);margin:10px 0 4px;text-transform:uppercase}
.sde-login .city{font-size:12px;color:var(--blue);letter-spacing:.2em;margin-bottom:22px}
.sde-login .sde-card{text-align:left}
.sde-login .btn-primary{width:100%;padding:9px;margin-top:6px}
.sde-login-hint{color:var(--muted);font-size:12px;margin-top:14px;line-height:1.7}
.sde-login-hint code{background:rgba(255,255,255,.08);padding:1px 6px;border-radius:5px;color:var(--gold-2)}
/* 通知深色化 */
.shiny-notification{background:var(--navy-2);color:var(--cream);border:1px solid var(--gold-dim)}
/* 我的数据:紧凑表单 */
.sde-form-table .shiny-input-container{margin:0}
.sde-form-table label:empty{display:none}
.sde-form-table .form-control{padding:4px 8px;text-align:center}
/* ---------- 个人趋势图 ---------- */
.sde-trend-wrap{overflow-x:auto}
.sde-legend{display:flex;gap:18px;font-size:12px;color:var(--muted);margin-bottom:10px}
.sde-legend > span{display:inline-flex;align-items:center;gap:6px}
.sde-dot-g,.sde-dot-a{width:11px;height:11px;border-radius:3px;display:inline-block}
.sde-dot-g{background:#EBCB6B}
.sde-dot-a{background:#3DA5D9}
/* ================= 冲击力榜单(Hero 聚光台 + 奖牌行 + 能量条) ================= */
@keyframes sde-row-in{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
@keyframes sde-sheen{0%,55%{transform:translateX(-130%) skewX(-18deg)}100%{transform:translateX(230%) skewX(-18deg)}}
@keyframes sde-bar-grow{from{transform:scaleX(0)}to{transform:scaleX(1)}}
@keyframes sde-crown-bob{0%,100%{transform:rotate(-8deg)}50%{transform:rotate(6deg) translateY(-2px)}}
.sde-board{display:flex;flex-direction:column;gap:8px}
/* --- 榜首 Hero --- */
.sde-hero{position:relative;overflow:hidden;border-radius:14px;padding:16px 16px 14px;
background:
radial-gradient(120% 150% at 100% 0%, rgba(212,175,55,.28), transparent 55%),
linear-gradient(135deg, rgba(212,175,55,.16), rgba(17,37,74,.9) 58%);
border:1px solid rgba(212,175,55,.55);
box-shadow:0 14px 34px -18px rgba(212,175,55,.45), inset 0 1px 0 rgba(255,255,255,.08);
animation:sde-row-in .45s ease both}
.sde-hero::after{content:"";position:absolute;top:0;bottom:0;width:46%;
background:linear-gradient(105deg,transparent,rgba(255,236,180,.16) 45%,transparent 60%);
animation:sde-sheen 3.4s ease-in-out infinite;pointer-events:none}
.sde-hero .crown{position:absolute;top:8px;right:12px;font-size:26px;opacity:.9;
filter:drop-shadow(0 3px 8px rgba(212,175,55,.6));animation:sde-crown-bob 2.6s ease-in-out infinite;transform-origin:60% 90%}
.sde-hero .title{font-size:10.5px;font-weight:800;letter-spacing:.34em;color:var(--gold);
text-transform:uppercase;margin-bottom:8px;display:flex;align-items:center;gap:8px}
.sde-hero .title::after{content:"";flex:0 0 42px;height:1px;background:linear-gradient(90deg,var(--gold),transparent)}
.sde-hero .who{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap}
.sde-hero .nm{font-size:21px;font-weight:900;letter-spacing:.02em;color:var(--cream);
text-shadow:0 2px 14px rgba(212,175,55,.35)}
.sde-hero .big{margin-left:auto;display:flex;align-items:baseline;gap:5px}
.sde-hero .big .n{font-size:42px;font-weight:900;line-height:.9;
background:linear-gradient(180deg,#fff2c4,var(--gold));-webkit-background-clip:text;background-clip:text;color:transparent;
font-variant-numeric:tabular-nums;filter:drop-shadow(0 4px 14px rgba(212,175,55,.45))}
.sde-hero .big .u{font-size:12px;color:var(--gold-2);font-weight:700}
.sde-hero .sub2{margin-top:4px;font-size:12px;color:var(--muted)}
.sde-hero .sde-jersey{transform:translateY(-2px)}
/* --- 2/3 名奖牌行 + 普通行 --- */
.sde-brow{position:relative;display:flex;align-items:center;gap:10px;padding:9px 12px;
border-radius:11px;background:rgba(255,255,255,.028);border:1px solid rgba(255,255,255,.06);
animation:sde-row-in .45s ease both;overflow:hidden}
.sde-brow:nth-child(2){animation-delay:.06s}.sde-brow:nth-child(3){animation-delay:.12s}
.sde-brow:nth-child(4){animation-delay:.18s}.sde-brow:nth-child(5){animation-delay:.24s}
.sde-brow:nth-child(6){animation-delay:.30s}.sde-brow:nth-child(7){animation-delay:.36s}
.sde-brow:nth-child(8){animation-delay:.42s}
.sde-brow.r2{background:linear-gradient(90deg,rgba(203,213,235,.10),rgba(255,255,255,.02) 62%);
border-color:rgba(203,213,235,.30)}
.sde-brow.r3{background:linear-gradient(90deg,rgba(205,127,50,.12),rgba(255,255,255,.02) 62%);
border-color:rgba(205,127,50,.32)}
.sde-brow.is-me{border-color:var(--gold);box-shadow:inset 3px 0 0 var(--gold)}
.sde-brow .rk{flex:0 0 26px;text-align:center;font-weight:900;font-size:15px;color:var(--muted)}
.sde-brow.r2 .rk,.sde-brow.r3 .rk{font-size:17px}
.sde-brow .nm{font-weight:700;color:var(--cream);font-size:14px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.sde-brow .val{margin-left:auto;font-weight:900;font-size:16px;color:var(--gold-2);
font-variant-numeric:tabular-nums;white-space:nowrap}
.sde-brow .val .u{font-size:11px;color:var(--muted);font-weight:600;margin-left:3px}
/* 能量条 */
.sde-brow .bar{position:absolute;left:0;bottom:0;height:2.5px;width:var(--w,0%);border-radius:2px;
background:linear-gradient(90deg,var(--gold),rgba(212,175,55,.15));transform-origin:left;
animation:sde-bar-grow .8s .25s cubic-bezier(.2,.8,.2,1) both}
.sde-brow.c-blue .bar{background:linear-gradient(90deg,var(--blue),rgba(61,165,217,.15))}
.sde-brow.c-blue .val{color:#8fd4f5}
.sde-brow.c-green .bar{background:linear-gradient(90deg,var(--green),rgba(31,169,113,.15))}
.sde-brow.c-green .val{color:#5fd7a7}
.sde-hero.c-blue{border-color:rgba(61,165,217,.55);
background:radial-gradient(120% 150% at 100% 0%, rgba(61,165,217,.28), transparent 55%),
linear-gradient(135deg, rgba(61,165,217,.16), rgba(17,37,74,.9) 58%);
box-shadow:0 14px 34px -18px rgba(61,165,217,.45), inset 0 1px 0 rgba(255,255,255,.08)}
.sde-hero.c-blue .big .n{background:linear-gradient(180deg,#d9f1ff,var(--blue));-webkit-background-clip:text;background-clip:text}
.sde-hero.c-blue .title{color:var(--blue)}
.sde-hero.c-green{border-color:rgba(31,169,113,.55);
background:radial-gradient(120% 150% at 100% 0%, rgba(31,169,113,.26), transparent 55%),
linear-gradient(135deg, rgba(31,169,113,.15), rgba(17,37,74,.9) 58%);
box-shadow:0 14px 34px -18px rgba(31,169,113,.45), inset 0 1px 0 rgba(255,255,255,.08)}
.sde-hero.c-green .big .n{background:linear-gradient(180deg,#c9f5e2,var(--green));-webkit-background-clip:text;background-clip:text}
.sde-hero.c-green .title{color:var(--green)}
.sde-hero.c-red{border-color:rgba(226,56,75,.55);
background:radial-gradient(120% 150% at 100% 0%, rgba(200,16,46,.30), transparent 55%),
linear-gradient(135deg, rgba(200,16,46,.17), rgba(17,37,74,.9) 58%);
box-shadow:0 14px 34px -18px rgba(200,16,46,.5), inset 0 1px 0 rgba(255,255,255,.08)}
.sde-hero.c-red .big .n{background:linear-gradient(180deg,#ffd2d8,var(--red-2));-webkit-background-clip:text;background-clip:text;
filter:drop-shadow(0 4px 14px rgba(200,16,46,.5))}
.sde-hero.c-red .title{color:var(--red-2)}
.sde-hero.c-red .crown{filter:drop-shadow(0 3px 8px rgba(200,16,46,.6))}
.sde-brow.c-red .bar{background:linear-gradient(90deg,var(--red-2),rgba(200,16,46,.15))}
.sde-brow.c-red .val{color:#ff9fab}
.sde-brow.c-red.r2,.sde-brow.c-red.r3{border-color:rgba(226,56,75,.30)}
.sde-board .sde-empty{padding:18px}
/* ================= 每场比分 · 战报记分牌 ================= */
.sde-mc-list{display:flex;flex-direction:column;gap:12px}
.sde-scorecard{position:relative;overflow:hidden;border-radius:14px;padding:14px 16px 12px;
background:linear-gradient(180deg,rgba(255,255,255,.045),rgba(255,255,255,.012));
border:1px solid rgba(255,255,255,.09);animation:sde-row-in .45s ease both;
transition:transform .18s ease, box-shadow .18s ease}
.sde-scorecard:hover{transform:translateY(-2px);box-shadow:0 18px 40px -22px rgba(0,0,0,.9)}
.sde-scorecard::before{content:"";position:absolute;left:0;top:0;bottom:0;width:4px}
.sde-scorecard.res-W::before{background:linear-gradient(180deg,var(--green),rgba(31,169,113,.25))}
.sde-scorecard.res-D::before{background:linear-gradient(180deg,#6b7a99,rgba(107,122,153,.25))}
.sde-scorecard.res-L::before{background:linear-gradient(180deg,var(--red),rgba(200,16,46,.25))}
.sde-scorecard.res-W{background:
radial-gradient(90% 130% at 0% 0%, rgba(31,169,113,.13), transparent 52%),
linear-gradient(180deg,rgba(255,255,255,.045),rgba(255,255,255,.012))}
.sde-scorecard.res-L{background:
radial-gradient(90% 130% at 0% 0%, rgba(200,16,46,.13), transparent 52%),
linear-gradient(180deg,rgba(255,255,255,.045),rgba(255,255,255,.012))}
.sde-sc-meta{display:flex;align-items:center;gap:9px;flex-wrap:wrap;font-size:12px;color:var(--muted)}
.sde-sc-meta .d{font-variant-numeric:tabular-nums;letter-spacing:.04em}
.sde-sc-meta .note{opacity:.8}
.sde-sc-main{display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:12px;margin:10px 0 4px}
.sde-sc-side{min-width:0}
.sde-sc-side .tn{font-weight:800;font-size:15.5px;color:var(--cream);
white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.sde-sc-side.us .tn{color:var(--gold-2)}
.sde-sc-side.them{text-align:right}
.sde-sc-score{display:flex;align-items:center;gap:10px}
.sde-sc-score .n{font-size:37px;font-weight:900;line-height:1;color:var(--cream);
font-variant-numeric:tabular-nums;text-shadow:0 3px 16px rgba(0,0,0,.5)}
.sde-sc-score .sep{font-size:20px;color:var(--muted);font-weight:300;transform:translateY(-2px)}
.sde-scorecard.res-W .sde-sc-score .n.us{color:#6fe3b1;text-shadow:0 0 22px rgba(31,169,113,.55)}
.sde-scorecard.res-L .sde-sc-score .n.them{color:var(--red-2);text-shadow:0 0 22px rgba(200,16,46,.5)}
.sde-sc-badge{position:absolute;top:12px;right:12px;width:34px;height:34px;border-radius:10px;
display:grid;place-items:center;font-weight:900;font-size:16px;color:#fff}
.sde-sc-badge.W{background:linear-gradient(160deg,#27c584,#128757);box-shadow:0 6px 18px -6px rgba(31,169,113,.8)}
.sde-sc-badge.D{background:linear-gradient(160deg,#8494b5,#5b6b8d);box-shadow:0 6px 18px -6px rgba(107,122,153,.8)}
.sde-sc-badge.L{background:linear-gradient(160deg,#e2384b,#a30d26);box-shadow:0 6px 18px -6px rgba(200,16,46,.8)}
.sde-sc-detail{display:flex;flex-direction:column;gap:7px;margin-top:10px;padding-top:10px;
border-top:1px dashed rgba(255,255,255,.10)}
/* 分行明细:标签列(固定宽,右对齐) + 该类芯片 */
.sde-detail-row{display:flex;align-items:flex-start;gap:10px}
.sde-dl{flex:0 0 92px;display:inline-flex;align-items:center;justify-content:flex-end;gap:5px;
font-size:12.5px;font-weight:800;padding-top:3px;letter-spacing:.02em;white-space:nowrap}
.sde-dl .ic{font-size:13px}
.sde-dl.mvp{color:#ffe9a8}
.sde-dl.dmvp{color:#ffc3cb}
.sde-dl.goal{color:var(--gold-2)}
.sde-dl.assist{color:#8fd4f5}
.sde-dr{display:flex;flex-wrap:wrap;gap:6px 7px;min-width:0}
@media(max-width:480px){.sde-dl{flex-basis:84px;font-size:12px}}
.sde-chip{display:inline-flex;align-items:center;gap:6px;font-size:12.5px;padding:3px 11px;
border-radius:20px;border:1px solid rgba(255,255,255,.12);background:rgba(255,255,255,.04);color:var(--cream)}
.sde-chip .ic{font-size:12px}
.sde-chip.goal{border-color:rgba(212,175,55,.4);background:rgba(212,175,55,.10)}
.sde-chip.assist{border-color:rgba(61,165,217,.4);background:rgba(61,165,217,.10)}
.sde-chip.mvp{border-color:rgba(212,175,55,.65);background:linear-gradient(90deg,rgba(212,175,55,.22),rgba(212,175,55,.08));
color:#ffe9a8;font-weight:800;box-shadow:0 0 14px -4px rgba(212,175,55,.7)}
.sde-chip.dmvp{border-color:rgba(226,56,75,.6);background:linear-gradient(90deg,rgba(200,16,46,.24),rgba(200,16,46,.08));
color:#ffc3cb;font-weight:800;box-shadow:0 0 14px -4px rgba(200,16,46,.7)}
/* 比分折叠:默认展示最近 N 场,其余收进 <details> */
.sde-mc-more{display:block}
.sde-mc-more > summary.sde-more-btn{list-style:none;cursor:pointer;user-select:none;
display:flex;align-items:center;justify-content:center;gap:8px;
padding:9px 14px;border-radius:12px;font-size:13px;font-weight:700;color:var(--muted);
background:rgba(255,255,255,.03);border:1px dashed rgba(212,175,55,.35);
transition:color .15s ease,border-color .15s ease,background .15s ease}
.sde-mc-more > summary.sde-more-btn::-webkit-details-marker{display:none}
.sde-mc-more > summary.sde-more-btn:hover{color:var(--gold-2);border-color:var(--gold);
background:rgba(212,175,55,.07)}
.sde-more-btn .arr{transition:transform .2s ease;font-size:12px}
.sde-mc-more[open] > summary .arr{transform:rotate(180deg)}
.sde-more-btn .txt-close{display:none}
.sde-mc-more[open] > summary .txt-open{display:none}
.sde-mc-more[open] > summary .txt-close{display:inline}
.sde-mc-more > .sde-mc-list{margin-top:12px}
/* 榜单折叠:Hero+2/3名常驻,第4名起收进 <details>(复用 sde-more-btn 样式) */
.sde-board-more{display:block}
.sde-board-more > summary.sde-more-btn{margin-top:2px}
.sde-board-more-list{display:flex;flex-direction:column;gap:8px;margin-top:8px}
/* ============ 我的主场 · 球员卡 Hero ============ */
.sde-pcard{position:relative;overflow:hidden;border-radius:18px;padding:22px 22px 18px;margin-bottom:18px;
background:
radial-gradient(130% 170% at 100% 0%, rgba(212,175,55,.22), transparent 55%),
radial-gradient(90% 120% at 0% 100%, rgba(61,165,217,.10), transparent 50%),
linear-gradient(135deg, rgba(212,175,55,.10), rgba(17,37,74,.94) 60%);
border:1px solid rgba(212,175,55,.5);
box-shadow:0 20px 48px -24px rgba(212,175,55,.45), inset 0 1px 0 rgba(255,255,255,.07);
animation:sde-row-in .5s ease both}
.sde-pcard::after{content:"";position:absolute;top:0;bottom:0;width:44%;
background:linear-gradient(105deg,transparent,rgba(255,236,180,.10) 45%,transparent 60%);
animation:sde-sheen 4.2s ease-in-out infinite;pointer-events:none}
.sde-pcard .wm{position:absolute;right:-8px;top:-38px;font-size:170px;font-weight:900;line-height:1;
color:transparent;-webkit-text-stroke:2px rgba(212,175,55,.22);pointer-events:none;
font-variant-numeric:tabular-nums;letter-spacing:-.05em;user-select:none}
.sde-pcard .kicker{font-size:10.5px;font-weight:800;letter-spacing:.34em;color:var(--gold);
text-transform:uppercase;margin-bottom:6px;display:flex;align-items:center;gap:8px}
.sde-pcard .kicker::after{content:"";flex:0 0 46px;height:1px;background:linear-gradient(90deg,var(--gold),transparent)}
.sde-pcard .nm{font-size:31px;font-weight:900;color:var(--cream);line-height:1.15;
text-shadow:0 2px 18px rgba(212,175,55,.35)}
.sde-pcard .rl{font-size:12px;color:var(--muted);letter-spacing:.20em;margin-top:3px;text-transform:uppercase}
.sde-badges{display:flex;flex-wrap:wrap;gap:7px;margin-top:13px;position:relative;z-index:1}
.sde-badge{display:inline-flex;align-items:center;gap:5px;font-size:12px;font-weight:800;
padding:3px 11px;border-radius:20px;border:1px solid rgba(212,175,55,.5);
background:linear-gradient(90deg,rgba(212,175,55,.20),rgba(212,175,55,.06));color:#ffe9a8}
.sde-badge.b-blue{border-color:rgba(61,165,217,.5);background:linear-gradient(90deg,rgba(61,165,217,.20),rgba(61,165,217,.06));color:#bfe6fb}
.sde-badge.b-red{border-color:rgba(226,56,75,.5);background:linear-gradient(90deg,rgba(200,16,46,.22),rgba(200,16,46,.06));color:#ffc3cb}
.sde-badge.b-green{border-color:rgba(31,169,113,.5);background:linear-gradient(90deg,rgba(31,169,113,.20),rgba(31,169,113,.06));color:#a9ecd0}
.sde-quote{margin-top:15px;padding:11px 15px;border-left:3px solid var(--gold);
background:rgba(212,175,55,.07);border-radius:0 11px 11px 0;position:relative;z-index:1}
.sde-quote .h{font-weight:900;color:var(--gold-2);font-size:14.5px;letter-spacing:.08em}
.sde-quote .b{color:var(--cream);font-size:13px;margin-top:4px;line-height:1.75;opacity:.92}
.sde-ptiles{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-top:16px;position:relative;z-index:1}
@media(max-width:560px){.sde-ptiles{grid-template-columns:repeat(2,1fr)}.sde-pcard .wm{font-size:120px;top:-24px}}
.sde-ptile{background:rgba(10,19,37,.45);border:1px solid rgba(255,255,255,.09);
border-radius:12px;padding:12px 10px;text-align:center;backdrop-filter:blur(2px)}
.sde-ptile .v{font-size:25px;font-weight:900;color:var(--gold-2);font-variant-numeric:tabular-nums;line-height:1}
.sde-ptile .l{font-size:11.5px;color:var(--muted);margin-top:6px;letter-spacing:.04em}
.sde-ptile .r{font-size:11px;color:var(--gold);margin-top:3px;font-weight:700}
.sde-ptile.t-blue .v{color:#8fd4f5}.sde-ptile.t-blue .r{color:var(--blue)}
.sde-ptile.t-green .v{color:#5fd7a7}.sde-ptile.t-green .r{color:var(--green)}
.sde-ptile.t-red .v{color:#ff9fab}.sde-ptile.t-red .r{color:var(--red-2)}
.sde-ptile.t-cream .v{color:var(--cream)}
/* ============ FIFA UT 式球员卡(华丽版) ============ */
@keyframes sde-fifa-in{from{opacity:0;transform:translateY(16px) scale(.96)}to{opacity:1;transform:none}}
@keyframes sde-halo{0%,100%{opacity:.55;transform:translateX(-50%) scale(1)}50%{opacity:.95;transform:translateX(-50%) scale(1.12)}}
.sde-fifa-wrap{display:flex;justify-content:center;margin-bottom:18px;perspective:900px}
.sde-fifa{position:relative;width:300px;padding:28px 26px 24px;text-align:center;
clip-path:polygon(12% 0,88% 0,100% 7%,100% 86%,50% 100%,0 86%,0 7%);
animation:sde-fifa-in .55s cubic-bezier(.2,.9,.3,1.2) both;overflow:hidden;
transition:transform .25s ease}
.sde-fifa:hover{transform:rotateX(4deg) rotateY(-5deg) translateY(-5px) scale(1.02)}
/* 卡底渐变 + 织物噪点 + 中轴几何雕纹 */
.sde-fifa.gold{background:
repeating-conic-gradient(from 30deg at 50% 42%, rgba(255,255,255,.07) 0 8deg, transparent 8deg 16deg),
radial-gradient(120% 90% at 50% 0%, #fff6d0 0%, #ffe08a 26%, #f2c247 50%, #d69a2a 78%, #b07d1c 100%);
box-shadow:0 26px 60px -20px rgba(245,196,71,.85), 0 0 34px -8px rgba(255,224,138,.55),
inset 0 0 0 1px rgba(255,255,255,.55), inset 0 2px 14px rgba(255,255,255,.4)}
.sde-fifa.silver{background:
repeating-conic-gradient(from 30deg at 50% 42%, rgba(255,255,255,.09) 0 8deg, transparent 8deg 16deg),
radial-gradient(120% 90% at 50% 0%, #ffffff 0%, #e6edf6 28%, #bcc9dc 56%, #93a2ba 86%, #7688a1 100%);
box-shadow:0 26px 60px -20px rgba(147,162,186,.8), 0 0 30px -8px rgba(220,232,248,.6),
inset 0 0 0 1px rgba(255,255,255,.7), inset 0 2px 14px rgba(255,255,255,.5)}
.sde-fifa.bronze{background:
repeating-conic-gradient(from 30deg at 50% 42%, rgba(255,255,255,.07) 0 8deg, transparent 8deg 16deg),
radial-gradient(120% 90% at 50% 0%, #ffe0b8 0%, #f5b578 26%, #e29452 50%, #c1712f 80%, #9c561f 100%);
box-shadow:0 26px 60px -20px rgba(226,148,82,.8), 0 0 30px -8px rgba(245,181,120,.55),
inset 0 0 0 1px rgba(255,255,255,.5), inset 0 2px 14px rgba(255,236,220,.45)}
.sde-fifa.legend{background:
repeating-conic-gradient(from 30deg at 50% 42%, rgba(255,255,255,.09) 0 8deg, transparent 8deg 16deg),
radial-gradient(120% 90% at 50% 0%, #f6ecff 0%, #d9b8ff 26%, #b483f5 54%, #8a54e0 82%, #6234ac 100%);
box-shadow:0 26px 66px -18px rgba(154,108,216,.95), 0 0 40px -6px rgba(200,166,242,.7),
inset 0 0 0 1px rgba(255,255,255,.7), inset 0 2px 16px rgba(255,255,255,.55)}
/* 双层内描边 */
.sde-fifa::before{content:"";position:absolute;inset:7px;pointer-events:none;
clip-path:polygon(12% 0,88% 0,100% 7%,100% 86%,50% 100%,0 86%,0 7%);
border:1px solid rgba(70,48,8,.4);box-shadow:inset 0 0 0 3px rgba(255,255,255,.14)}
/* 扫光 */
.sde-fifa::after{content:"";position:absolute;top:0;bottom:0;width:55%;
background:linear-gradient(105deg,transparent,rgba(255,255,255,.32) 48%,transparent 62%);
animation:sde-sheen 3.8s ease-in-out infinite;pointer-events:none}
/* 顶部 tier 光冠 */
.sde-fifa .halo{position:absolute;top:-34px;left:50%;transform:translateX(-50%);width:190px;height:70px;
background:radial-gradient(50% 100% at 50% 100%, rgba(255,255,255,.55), transparent 70%);
filter:blur(6px);animation:sde-halo 3.2s ease-in-out infinite;pointer-events:none}
.sde-fifa,.sde-fifa *{color:#3d2b06}
.sde-fifa.silver,.sde-fifa.silver *{color:#28303e}
.sde-fifa.bronze,.sde-fifa.bronze *{color:#3c2510}
.sde-fifa.legend,.sde-fifa.legend *{color:#2c1650}
.sde-fifa .top{display:flex;align-items:flex-start;gap:10px;text-align:left}
.sde-fifa .ovr{font-size:56px;font-weight:900;line-height:.88;letter-spacing:-.03em;
text-shadow:0 1px 0 rgba(255,255,255,.55), 0 3px 10px rgba(60,40,5,.35)}
.sde-fifa .meta{display:flex;flex-direction:column;gap:2px;padding-top:6px}
.sde-fifa .pos{font-size:17px;font-weight:900;letter-spacing:.1em}
.sde-fifa .jer{font-size:12px;font-weight:800;opacity:.75;letter-spacing:.06em}
.sde-fifa .crest-s{margin-left:auto;width:46px;height:46px;border-radius:50%;overflow:hidden;
border:2px solid rgba(70,48,8,.45);background:#fff;box-shadow:0 3px 10px rgba(60,40,5,.35)}
.sde-fifa .crest-s img{width:100%;height:100%;object-fit:contain}
.sde-fifa .fname{font-size:23px;font-weight:900;letter-spacing:.06em;margin-top:11px;
padding-bottom:10px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
border-bottom:2px solid rgba(70,48,8,.4);
text-shadow:0 1px 0 rgba(255,255,255,.4)}
.sde-fifa .grid{display:grid;grid-template-columns:1fr 1fr;gap:4px 22px;margin-top:12px;padding:0 8px}
.sde-fifa .st{display:flex;align-items:baseline;justify-content:space-between;gap:8px}
.sde-fifa .st .n{font-size:19px;font-weight:900;font-variant-numeric:tabular-nums;
text-shadow:0 1px 0 rgba(255,255,255,.4)}
.sde-fifa .st .k{font-size:12px;font-weight:800;letter-spacing:.08em;opacity:.8}
.sde-fifa .club{margin-top:13px;font-size:10px;font-weight:800;letter-spacing:.3em;opacity:.7;text-transform:uppercase}
@media(max-width:400px){.sde-fifa{width:270px}}
/* ---- 主页 · 全队球员卡墙 ---- */
.sde-fifa-wall{display:grid;grid-template-columns:repeat(auto-fill,minmax(228px,1fr));
gap:16px;justify-items:center}
.sde-fifa-wall .sde-fifa{width:228px;padding:20px 18px 16px}
.sde-fifa-wall > :nth-child(2) .sde-fifa{animation-delay:.05s}
.sde-fifa-wall > :nth-child(3) .sde-fifa{animation-delay:.1s}
.sde-fifa-wall > :nth-child(4) .sde-fifa{animation-delay:.15s}
.sde-fifa-wall > :nth-child(n+5) .sde-fifa{animation-delay:.2s}
.sde-fifa-wall .ovr{font-size:42px}
.sde-fifa-wall .fname{font-size:18px;margin-top:8px;padding-bottom:8px}
.sde-fifa-wall .pos{font-size:14px}
.sde-fifa-wall .crest-s{width:36px;height:36px}
.sde-fifa-wall .grid{gap:2px 14px;margin-top:9px;padding:0 4px}
.sde-fifa-wall .st .n{font-size:15px}
.sde-fifa-wall .st .k{font-size:10.5px}
.sde-fifa-wall .club{margin-top:10px;font-size:8.5px}
.sde-fifa-wall .halo{width:140px;height:52px;top:-26px}
.sde-fifa.is-me-card{outline:0}
.sde-fifa.is-me-card .fname::after{content:" ★";font-size:15px}
/* ---- 💎 钻石球星卡(专属皮肤·仅个人页本人可见·纯外观不碰评分) ---- */
@keyframes sde-dia-hue{to{filter:hue-rotate(360deg)}}
@keyframes sde-dia-holo{0%{background-position:0% 50%}50%{background-position:100% 50%}100%{background-position:0% 50%}}
@keyframes sde-dia-glow{
0%,100%{box-shadow:0 26px 66px -18px rgba(0,180,220,.7),0 0 40px -6px rgba(60,220,255,.55),
inset 0 0 0 1px rgba(180,240,255,.35),inset 0 2px 22px rgba(80,200,255,.18)}
50%{box-shadow:0 26px 74px -14px rgba(0,220,255,.92),0 0 62px -2px rgba(120,240,255,.82),
inset 0 0 0 1px rgba(200,250,255,.6),inset 0 2px 26px rgba(120,230,255,.32)}}
/* 深黑曜石底 + 冰蓝/四色全息流光 + 几何雕纹 */
.sde-fifa.diamond{
background:
repeating-linear-gradient(115deg, rgba(0,245,212,.12) 0px, rgba(51,224,255,.10) 12px,
rgba(123,97,255,.10) 24px, rgba(255,46,151,.08) 36px, transparent 36px, transparent 72px),
repeating-conic-gradient(from 30deg at 50% 42%, rgba(180,240,255,.06) 0 8deg, transparent 8deg 16deg),
radial-gradient(120% 95% at 50% 0%, #16324e 0%, #0e2036 34%, #0a1526 64%, #060b16 100%);
background-size:220% 220%, auto, auto;
animation:sde-fifa-in .55s cubic-bezier(.2,.9,.3,1.2) both,
sde-dia-holo 7s ease-in-out infinite, sde-dia-glow 3.6s ease-in-out infinite}
.sde-fifa.diamond,.sde-fifa.diamond *{color:#eafaff}
/* 流动的四色钻石切面镶边(沿用卡片六边形轮廓) */
.sde-fifa.diamond::before{
inset:0;padding:2px;border:none;box-shadow:none;
background:conic-gradient(from 0deg,#00f5d4,#33e0ff,#7b61ff,#ff2e97,#ffd166,#00f5d4);
-webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
-webkit-mask-composite:xor;mask-composite:exclude;
animation:sde-dia-hue 6s linear infinite;opacity:.95}
/* 更亮更宽的棱镜白光扫过 */
.sde-fifa.diamond::after{
background:linear-gradient(105deg,transparent 30%,rgba(255,255,255,.55) 47%,
rgba(180,240,255,.35) 52%,transparent 66%)}
/* 冰蓝光冠 */
.sde-fifa.diamond .halo{
background:radial-gradient(50% 100% at 50% 100%, rgba(120,240,255,.7), transparent 72%)}
/* 深底下的描边/分割线/高光改冰蓝 */
.sde-fifa.diamond .fname{border-bottom-color:rgba(130,225,255,.5);
text-shadow:0 0 10px rgba(0,230,255,.45)}
.sde-fifa.diamond .ovr{text-shadow:0 0 14px rgba(90,230,255,.62)}
.sde-fifa.diamond .st .n{text-shadow:0 0 8px rgba(0,245,212,.45)}
.sde-fifa.diamond .crest-s{border-color:rgba(150,235,255,.65);background:rgba(255,255,255,.92);
box-shadow:0 0 12px rgba(80,220,255,.5)}
/* 位置角标点亮钻石标识 */
.sde-fifa.diamond .pos::after{content:" 💎";font-size:13px}
/* 背面同款冰蓝配色 */
.sde-fifa.diamond .bname{border-bottom-color:rgba(130,225,255,.5)}
.sde-fifa.diamond .bst{background:rgba(120,220,255,.12);border-color:rgba(150,235,255,.3)}
.sde-fifa.diamond .bquote{background:rgba(120,220,255,.10);border-left-color:rgba(150,235,255,.6)}
/* ---- 球星卡 3D 翻面(checkbox+label,零 JS) ---- */
.sde-flip-box{position:relative;width:100%;display:flex;justify-content:center}
.sde-flip-cb{position:absolute;opacity:0;pointer-events:none}
.sde-flip{display:block;cursor:pointer;perspective:1100px;-webkit-tap-highlight-color:transparent}
.sde-flipper{position:relative;transition:transform .62s cubic-bezier(.35,.9,.3,1.05);
transform-style:preserve-3d}
.sde-flip-cb:checked + .sde-flip .sde-flipper{transform:rotateY(180deg)}
.sde-flipper .face{backface-visibility:hidden;-webkit-backface-visibility:hidden}
.sde-flipper .face.back{position:absolute;inset:0;transform:rotateY(180deg);
display:flex;justify-content:center}
.sde-flipper .face.back .sde-fifa{height:100%;display:flex;flex-direction:column}
/* 翻面时停掉正面 hover 倾斜,避免和翻转打架 */
.sde-flip .sde-fifa:hover{transform:none}
.sde-flip:hover .sde-flipper{transform:rotateY(-6deg)}
.sde-flip-cb:checked + .sde-flip:hover .sde-flipper{transform:rotateY(186deg)}
/* 正/背面的翻面提示 */
.sde-fifa .fflip,.sde-fifa .bflip{margin-top:9px;font-size:10px;font-weight:800;
letter-spacing:.14em;opacity:.55;text-transform:uppercase}
/* ---- 背面内容 ---- */
.sde-fifa-back{text-align:center;justify-content:flex-start}
.sde-fifa-back .bname{font-size:20px;font-weight:900;letter-spacing:.05em;margin-top:2px;
padding-bottom:8px;border-bottom:2px solid rgba(70,48,8,.4);
white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
text-shadow:0 1px 0 rgba(255,255,255,.4)}
.sde-fifa-back .bapps{font-size:11.5px;font-weight:800;opacity:.75;margin-top:7px;letter-spacing:.08em}
.sde-fifa-back .bgrid{display:grid;grid-template-columns:1fr 1fr;gap:6px 12px;margin-top:10px;padding:0 4px}
.sde-fifa-back .bst{display:flex;align-items:center;justify-content:space-between;gap:6px;
background:rgba(255,255,255,.22);border:1px solid rgba(70,48,8,.25);
border-radius:9px;padding:6px 9px}
.sde-fifa-back .bk{font-size:11px;font-weight:800;opacity:.85;white-space:nowrap}
.sde-fifa-back .bn{font-size:17px;font-weight:900;font-variant-numeric:tabular-nums;
text-shadow:0 1px 0 rgba(255,255,255,.4)}
.sde-fifa-back .bquote{margin-top:10px;padding:8px 11px;text-align:left;
background:rgba(255,255,255,.20);border-left:3px solid rgba(70,48,8,.45);border-radius:0 9px 9px 0}
.sde-fifa-back .qt{font-size:12.5px;font-weight:900;letter-spacing:.04em}
.sde-fifa-back .qb{font-size:11px;line-height:1.65;margin-top:3px;opacity:.88}
.sde-fifa-back .bflip{margin-top:auto;padding-top:8px}
/* 卡墙内背面字号微调 */
.sde-fifa-wall .sde-fifa-back .bname{font-size:16.5px}
.sde-fifa-wall .sde-fifa-back .bn{font-size:15px}
.sde-fifa-wall .sde-fifa-back .qb{font-size:10.5px}
@media(max-width:560px){
.sde-sc-score .n{font-size:30px}
.sde-hero .big .n{font-size:34px}
.sde-hero .nm{font-size:18px}
}
/* ---------- 赛季筛选条 ---------- */
.sde-season-bar{display:flex;justify-content:flex-end;align-items:flex-end;gap:12px;margin:-2px 0 4px}
.sde-season-bar .shiny-input-container{width:auto;min-width:150px;margin-bottom:8px}
.sde-season-bar label{color:var(--muted);font-size:12px;margin-bottom:3px}
.sde-season-bar .btn{margin-bottom:8px;white-space:nowrap}
/* ---------- 比赛卡片:主页比分明细 + 我的逐场登记(天生响应式,手机不溢出) ---------- */
.sde-mc-list{display:flex;flex-direction:column;gap:10px}
.sde-mc{background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.07);
border-radius:12px;padding:11px 14px}
.sde-mc-top{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.sde-mc-date{font-variant-numeric:tabular-nums;color:var(--muted);font-size:13px;min-width:74px}
.sde-mc-opp{font-weight:700;color:var(--cream)}
.sde-mc-note{color:var(--muted);font-size:12px;opacity:.8}
.sde-mc-score{font-weight:800;font-size:16px;color:var(--gold-2);
font-variant-numeric:tabular-nums;letter-spacing:.04em}
.sde-mc-detail{display:flex;gap:8px 20px;flex-wrap:wrap;margin-top:9px;padding-top:9px;
border-top:1px dashed rgba(255,255,255,.10);font-size:13px}
.sde-mc-detail .lbl-goal{color:var(--gold-2);font-weight:700}
.sde-mc-detail .lbl-assist{color:var(--blue);font-weight:700}
.sde-mc-detail .nm{color:var(--cream)}
/* 逐场登记控件:出勤 / 进球 / 助攻,超窄屏自动换行 */
.sde-ctl-row{display:flex;gap:14px 22px;flex-wrap:wrap;align-items:center;margin-top:11px}
.sde-ctl{display:flex;align-items:center;gap:9px}
.sde-ctl-l{font-size:13px;color:var(--muted);font-weight:600}
.sde-mc-form .shiny-input-container{margin-bottom:0}
.sde-mc-form .form-control{padding:5px 8px;text-align:center}
.sde-foot{color:var(--muted);text-align:center;font-size:12px;margin-top:30px;padding-top:18px;
border-top:1px solid rgba(255,255,255,.08)}
"""
def crest(size: int = 52) -> ui.Tag:
"""队徽圆形徽章。"""
return ui.div(
ui.img(src=CREST_URL, alt="肆带贰队徽"),
class_="sde-crest",
style=f"width:{size}px;height:{size}px",
)
def result_badge(r: str) -> ui.Tag:
return ui.span(r, class_=f"badge-res badge-{r}")
def ha_pill(home_away: str) -> ui.Tag:
is_home = home_away == "home"
return ui.span("主" if is_home else "客", class_="ha-pill " + ("ha-home" if is_home else ""))
def card(title: str, *body, icon: str = "", sub: str = "") -> ui.Tag:
head = ui.div(
(ui.span(icon, class_="ic") if icon else None),
ui.span(title, class_="t"),
class_="sde-card-h",
)
sub_el = ui.div(sub, class_="sde-sub") if sub else None
return ui.div(head, sub_el, *body, class_="sde-card")
def stat(value, label: str, sub: str = "", accent: str = "gold") -> ui.Tag:
return ui.div(
ui.div(str(value), class_="v"),
ui.div(label, class_="l"),
(ui.div(sub, class_="s") if sub else None),
class_=f"sde-stat accent-{accent}",
)