feat(player): refresh dark gold betting theme
- add generated dark-gold WebP assets for PC/mobile backgrounds, cards, dialogs, tabs, mailbox, VS and bet buttons - apply the new assets across player home, match detail, outright cards, modals, wallet/profile/detail screens and bet slip controls - simplify confirm dialogs and reuse bet button resources for normal/pressed states - hide mobile announcement center, tighten mobile bet list layout, and remove extra dark page backgrounds/scrollbar styling - cache and deduplicate outright market loading to speed up repeated tab/detail navigation - document player image-generation constraints in AGENTS.md
@@ -90,6 +90,14 @@
|
|||||||
- 管理端切页慢的分析与优化任务见 `docs/admin-page-switch-performance.md`。
|
- 管理端切页慢的分析与优化任务见 `docs/admin-page-switch-performance.md`。
|
||||||
- **不要**把 `apps/player/dist/` 提交进 Git;生产由 Docker 构建生成静态资源。
|
- **不要**把 `apps/player/dist/` 提交进 Git;生产由 Docker 构建生成静态资源。
|
||||||
|
|
||||||
|
### 玩家端主题生图约束
|
||||||
|
|
||||||
|
- 生成 `apps/player` 主题图片资源时,必须先查看并参考现有同场景资源,优先保持当前暗金足球主题一致,不要另起一套风格。
|
||||||
|
- PC 首页/赛事详情/弹窗类赛事面板应优先对齐 `apps/player/src/assets/images/generated/pc-featured-match-bg-v1.webp`:暗金球场、中央 V 型光线、薄金色边框、低亮度背景、内容区域干净。
|
||||||
|
- 弹窗资源必须是“带完整边框的面板图”,不能只是普通背景图;四边边框要在图片内完整可见,中心区域要足够暗且简洁,保证文字可读。
|
||||||
|
- 避免生成过度写实、照片质感过重、厚重金属、强眩光、烟雾、人物、旗帜、logo、文字、数字;也不要生成与主题不一致的纯矢量科幻线框风。
|
||||||
|
- 生成资源默认输出 WebP,控制体积,文件放在 `apps/player/src/assets/images/generated/`,命名带清晰场景和版本号(如 `modal-gold-frame-v4.webp`)。
|
||||||
|
|
||||||
## i18n 改文案流程
|
## i18n 改文案流程
|
||||||
|
|
||||||
支持语言均为 **zh-CN / en-US / ms-MY**(马来语)。改文案须**三语同步**,不要只改中文。
|
支持语言均为 **zh-CN / en-US / ms-MY**(马来语)。改文案须**三语同步**,不要只改中文。
|
||||||
@@ -209,4 +217,3 @@
|
|||||||
- 不要提交 `.env`、`.env.docker`、镜像 tar、`apps/*/dist/`。
|
- 不要提交 `.env`、`.env.docker`、镜像 tar、`apps/*/dist/`。
|
||||||
- 改 player 主题相关文件时,先确认当前分支是 `main` 还是 `theme-`*,避免用错 CSS 变量(如 theme-2 无 `--gold`)。
|
- 改 player 主题相关文件时,先确认当前分支是 `main` 还是 `theme-`*,避免用错 CSS 变量(如 theme-2 无 `--gold`)。
|
||||||
- 管理端改列表页性能时,参考 `docs/admin-page-switch-performance.md` 任务清单,优先 KeepAlive + 缓存而非盲目减 API 字段。
|
- 管理端改列表页性能时,参考 `docs/admin-page-switch-performance.md` 任务清单,优先 KeepAlive + 缓存而非盲目减 API 字段。
|
||||||
|
|
||||||
|
|||||||
|
After Width: | Height: | Size: 60 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 8.1 KiB |
|
After Width: | Height: | Size: 66 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 65 KiB |
|
After Width: | Height: | Size: 86 KiB |
BIN
apps/player/src/assets/images/generated/modal-gold-frame-v1.webp
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
apps/player/src/assets/images/generated/modal-gold-frame-v2.webp
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
apps/player/src/assets/images/generated/modal-gold-frame-v3.webp
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
apps/player/src/assets/images/generated/modal-gold-frame-v4.webp
Normal file
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 5.8 KiB |
|
After Width: | Height: | Size: 4.6 KiB |
|
After Width: | Height: | Size: 4.8 KiB |
|
After Width: | Height: | Size: 4.9 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 83 KiB |
BIN
apps/player/src/assets/images/generated/pc-global-bg-v1.webp
Normal file
|
After Width: | Height: | Size: 127 KiB |
|
After Width: | Height: | Size: 86 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 62 KiB |
|
After Width: | Height: | Size: 30 KiB |
BIN
apps/player/src/assets/images/generated/pc-sidebar-bg-v1.webp
Normal file
|
After Width: | Height: | Size: 61 KiB |
BIN
apps/player/src/assets/images/generated/pc-top-nav-bg-v1.webp
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
apps/player/src/assets/images/generated/pc-wallet-banner-v1.webp
Normal file
|
After Width: | Height: | Size: 49 KiB |
|
After Width: | Height: | Size: 114 KiB |
BIN
apps/player/src/assets/images/generated/vs-gold-alpha-v1.webp
Normal file
|
After Width: | Height: | Size: 25 KiB |
@@ -101,18 +101,33 @@ function onConfirm() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.confirm-modal {
|
.confirm-modal {
|
||||||
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 340px;
|
max-width: 374px;
|
||||||
background: linear-gradient(165deg, #1a1810 0%, #121212 45%, #0a0a0a 100%);
|
overflow: hidden;
|
||||||
border: 1px solid var(--border-gold-soft, rgba(200, 168, 78, 0.25));
|
background:
|
||||||
border-radius: 12px;
|
linear-gradient(180deg, rgba(212, 175, 55, 0.08), transparent 38%),
|
||||||
padding: 22px 18px 16px;
|
rgba(14, 14, 12, 0.96);
|
||||||
box-shadow: 0 0 24px rgba(212, 175, 55, 0.08);
|
border: 1px solid rgba(212, 175, 55, 0.34);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 31px 28px 25px;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-modal::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 24px;
|
||||||
|
right: 24px;
|
||||||
|
height: 1px;
|
||||||
|
background: linear-gradient(90deg, transparent, rgba(232, 200, 74, 0.65), transparent);
|
||||||
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.confirm-title {
|
.confirm-title {
|
||||||
margin: 0 0 10px;
|
margin: 0 0 12px;
|
||||||
font-size: 17px;
|
font-size: 18px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
color: var(--gold, #c8a84e);
|
color: var(--gold, #c8a84e);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@@ -120,7 +135,7 @@ function onConfirm() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.confirm-message {
|
.confirm-message {
|
||||||
margin: 0 0 20px;
|
margin: 0 0 26px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 1.6;
|
line-height: 1.6;
|
||||||
color: #c8c8c8;
|
color: #c8c8c8;
|
||||||
@@ -130,17 +145,17 @@ function onConfirm() {
|
|||||||
|
|
||||||
.confirm-actions {
|
.confirm-actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 10px;
|
gap: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.confirm-btn {
|
.confirm-btn {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-height: 44px;
|
min-height: 49px;
|
||||||
border-radius: 8px;
|
border-radius: 0;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: opacity 0.15s;
|
transition: opacity 0.15s, filter 0.15s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.confirm-btn:disabled {
|
.confirm-btn:disabled {
|
||||||
@@ -149,20 +164,30 @@ function onConfirm() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.confirm-btn.cancel {
|
.confirm-btn.cancel {
|
||||||
border: 1px solid #333;
|
border: 0;
|
||||||
background: transparent;
|
background: url('../assets/images/generated/pc-betslip-btn-secondary-v1.webp') center / 100% 100% no-repeat;
|
||||||
color: #888;
|
color: #9f9273;
|
||||||
}
|
}
|
||||||
|
|
||||||
.confirm-btn.confirm {
|
.confirm-btn.confirm {
|
||||||
border: none;
|
border: none;
|
||||||
background: linear-gradient(135deg, #d4a017, #e8c84a);
|
background: url('../assets/images/generated/pc-betslip-btn-primary-v1.webp') center / 100% 100% no-repeat;
|
||||||
color: #1a1a1a;
|
color: #1b1200;
|
||||||
}
|
}
|
||||||
|
|
||||||
.confirm-btn.confirm.danger {
|
.confirm-btn.cancel:not(:disabled):hover,
|
||||||
background: linear-gradient(135deg, #c0392b, #e74c3c);
|
.confirm-btn.confirm:not(:disabled):hover {
|
||||||
color: #fff;
|
filter: brightness(1.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-btn.cancel:not(:disabled):active {
|
||||||
|
background-image: url('../assets/images/generated/pc-betslip-btn-secondary-pressed-v1.webp');
|
||||||
|
filter: brightness(0.96);
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-btn.confirm:not(:disabled):active {
|
||||||
|
background-image: url('../assets/images/generated/pc-betslip-btn-primary-pressed-v1.webp');
|
||||||
|
filter: brightness(0.98);
|
||||||
}
|
}
|
||||||
|
|
||||||
.confirm-fade-enter-active,
|
.confirm-fade-enter-active,
|
||||||
|
|||||||
@@ -317,47 +317,61 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.fab-btn {
|
.fab-btn {
|
||||||
width: 56px;
|
width: 48px;
|
||||||
height: 56px;
|
height: 48px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background: var(--primary);
|
background: url('../assets/images/generated/floating-mailbox-fab-v1.webp') center / cover no-repeat;
|
||||||
color: #fff;
|
color: var(--primary-light);
|
||||||
border: none;
|
border: 0;
|
||||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
box-shadow:
|
||||||
|
0 8px 22px rgba(0, 0, 0, 0.42),
|
||||||
|
0 0 16px rgba(212, 175, 55, 0.12);
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: transform 0.2s, background 0.2s;
|
transition: transform 0.2s, box-shadow 0.2s, color 0.2s, filter 0.2s;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fab-btn:hover {
|
.fab-btn:hover {
|
||||||
transform: scale(1.05);
|
transform: translateY(-1px);
|
||||||
background: var(--primary-light);
|
color: #fff1a8;
|
||||||
|
filter: brightness(1.08);
|
||||||
|
box-shadow:
|
||||||
|
0 10px 26px rgba(0, 0, 0, 0.5),
|
||||||
|
0 0 20px rgba(212, 175, 55, 0.18);
|
||||||
}
|
}
|
||||||
|
|
||||||
.fab-active {
|
.fab-active {
|
||||||
transform: scale(0.95);
|
transform: scale(0.96);
|
||||||
|
color: #fff1a8;
|
||||||
|
filter: brightness(0.94);
|
||||||
}
|
}
|
||||||
|
|
||||||
.fab-icon {
|
.fab-icon {
|
||||||
width: 28px;
|
width: 24px;
|
||||||
height: 28px;
|
height: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.badge {
|
.badge {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: -3px;
|
||||||
right: 0;
|
right: -3px;
|
||||||
background: var(--danger, #ff4d4f);
|
background: var(--danger, #ff4d4f);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-size: 11px;
|
font-size: 10px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
padding: 2px 6px;
|
min-width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
padding: 0 5px;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
border: 2px solid var(--bg-card);
|
border: 1px solid rgba(255, 255, 255, 0.9);
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
box-shadow: 0 2px 8px rgba(255, 69, 58, 0.42);
|
||||||
}
|
}
|
||||||
|
|
||||||
.popup-panel {
|
.popup-panel {
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import MatchBetCard from './MatchBetCard.vue';
|
import MatchBetCard from './MatchBetCard.vue';
|
||||||
import saishiImg from '../assets/images/saishi.webp';
|
import saishiImg from '../assets/images/generated/saishi-gold-trophy-v1.webp';
|
||||||
import cardBg from '../assets/images/card-bg.webp';
|
import cardBg from '../assets/images/generated/pc-match-list-card-bg-v1.webp';
|
||||||
|
|
||||||
const matchCardBg = `url(${cardBg})`;
|
const matchCardBg = `url(${cardBg})`;
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ function continueBrowsing() {
|
|||||||
<div v-if="auth.loginPromptVisible" class="login-overlay" @click.self="continueBrowsing">
|
<div v-if="auth.loginPromptVisible" class="login-overlay" @click.self="continueBrowsing">
|
||||||
<div class="login-modal">
|
<div class="login-modal">
|
||||||
<button type="button" class="close-btn" :aria-label="t('auth.continue_browsing')" @click="continueBrowsing">
|
<button type="button" class="close-btn" :aria-label="t('auth.continue_browsing')" @click="continueBrowsing">
|
||||||
✕
|
�
|
||||||
</button>
|
</button>
|
||||||
<h2 class="login-title">{{ t('auth.login_required') }}</h2>
|
<h2 class="login-title">{{ t('auth.login_required') }}</h2>
|
||||||
<p class="login-hint">{{ t('auth.login_hint') }}</p>
|
<p class="login-hint">{{ t('auth.login_hint') }}</p>
|
||||||
@@ -64,10 +64,13 @@ function continueBrowsing() {
|
|||||||
position: relative;
|
position: relative;
|
||||||
width: 90%;
|
width: 90%;
|
||||||
max-width: 360px;
|
max-width: 360px;
|
||||||
background: #1a1a1a;
|
background:
|
||||||
border: 1px solid var(--border-gold-soft, rgba(200, 168, 78, 0.25));
|
linear-gradient(rgba(16, 14, 10, 0.12), rgba(16, 14, 10, 0.16)),
|
||||||
border-radius: 12px;
|
url('../assets/images/generated/modal-gold-frame-v4.webp') center / 102% 102% no-repeat;
|
||||||
padding: 28px 24px 24px;
|
border: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
padding: 36px 30px 30px;
|
||||||
|
box-shadow: 0 18px 44px rgba(0, 0, 0, 0.55), 0 0 24px rgba(212, 175, 55, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.close-btn {
|
.close-btn {
|
||||||
|
|||||||
@@ -9,6 +9,10 @@ import { useBetSlipStore } from '../stores/betSlip';
|
|||||||
import { useDesktopBetPopover } from '../composables/useDesktopBetPopover';
|
import { useDesktopBetPopover } from '../composables/useDesktopBetPopover';
|
||||||
import { resolveSelectionLabel } from '../utils/selectionLabel';
|
import { resolveSelectionLabel } from '../utils/selectionLabel';
|
||||||
import MarketSelectionsPanel from './match-detail/MarketSelectionsPanel.vue';
|
import MarketSelectionsPanel from './match-detail/MarketSelectionsPanel.vue';
|
||||||
|
import vsImg from '../assets/images/generated/vs-gold-alpha-v1.webp';
|
||||||
|
import matchListCardBg from '../assets/images/generated/pc-match-list-card-bg-v1.webp';
|
||||||
|
|
||||||
|
const matchCardBg = `url(${matchListCardBg})`;
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
match: {
|
match: {
|
||||||
@@ -229,7 +233,9 @@ function goMatchDetail() {
|
|||||||
<div class="center-col">
|
<div class="center-col">
|
||||||
<span class="kickoff">{{ kickoffText }}</span>
|
<span class="kickoff">{{ kickoffText }}</span>
|
||||||
<span v-if="phase !== 'open' && liveScoreText" class="live-score">{{ liveScoreText }}</span>
|
<span v-if="phase !== 'open' && liveScoreText" class="live-score">{{ liveScoreText }}</span>
|
||||||
<span v-else class="vs">VS</span>
|
<span v-else class="vs">
|
||||||
|
<img :src="vsImg" alt="VS" class="vs-img" />
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="team">
|
<div class="team">
|
||||||
@@ -294,9 +300,9 @@ function goMatchDetail() {
|
|||||||
<style scoped>
|
<style scoped>
|
||||||
.match-card {
|
.match-card {
|
||||||
position: relative;
|
position: relative;
|
||||||
background: linear-gradient(180deg, #1a1a1a 0%, #0d0d0d 100%);
|
background: v-bind(matchCardBg) center / 100% 100% no-repeat;
|
||||||
border: 1px solid rgba(140, 140, 140, 0.35);
|
border: 0;
|
||||||
border-radius: 6px;
|
border-radius: 0;
|
||||||
padding: 10px 8px 10px;
|
padding: 10px 8px 10px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -312,7 +318,7 @@ function goMatchDetail() {
|
|||||||
content: '';
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
background: linear-gradient(135deg, rgba(100, 100, 100, 0.08) 0%, transparent 50%, rgba(80, 80, 80, 0.05) 100%);
|
background: linear-gradient(180deg, rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.2));
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
}
|
}
|
||||||
@@ -412,13 +418,21 @@ function goMatchDetail() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.vs {
|
.vs {
|
||||||
font-size: 22px;
|
width: 48px;
|
||||||
font-weight: 900;
|
height: 28px;
|
||||||
color: #fff;
|
display: inline-flex;
|
||||||
letter-spacing: 0.08em;
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
text-shadow: 0 1px 4px rgba(0, 0, 0, 0.9);
|
transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1), filter 0.3s ease;
|
||||||
transition: font-size 0.25s ease, transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1), text-shadow 0.3s ease;
|
}
|
||||||
|
|
||||||
|
.vs-img {
|
||||||
|
width: 46px;
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
object-fit: contain;
|
||||||
|
filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.9));
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-tag {
|
.status-tag {
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ function confirm() {
|
|||||||
<Teleport to="body">
|
<Teleport to="body">
|
||||||
<div v-if="open" class="overlay" @click.self="close">
|
<div v-if="open" class="overlay" @click.self="close">
|
||||||
<div class="modal" role="dialog" aria-modal="true" :aria-label="t('profile.avatar')">
|
<div class="modal" role="dialog" aria-modal="true" :aria-label="t('profile.avatar')">
|
||||||
<button type="button" class="close-x" :aria-label="t('bet.cancel')" @click="close">✕</button>
|
<button type="button" class="close-x" :aria-label="t('bet.cancel')" @click="close">✕</button>
|
||||||
<h3 class="title">{{ t('profile.avatar') }}</h3>
|
<h3 class="title">{{ t('profile.avatar') }}</h3>
|
||||||
<PlayerAvatarPicker v-model="draft" />
|
<PlayerAvatarPicker v-model="draft" />
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
@@ -69,11 +69,13 @@ function confirm() {
|
|||||||
max-width: 360px;
|
max-width: 360px;
|
||||||
max-height: 85vh;
|
max-height: 85vh;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
background: linear-gradient(165deg, #1a1810 0%, #121212 45%, #0a0a0a 100%);
|
background:
|
||||||
border: 1px solid var(--border-gold-soft);
|
linear-gradient(rgba(16, 14, 10, 0.12), rgba(16, 14, 10, 0.16)),
|
||||||
border-radius: var(--radius);
|
url('../assets/images/generated/modal-gold-frame-v4.webp') center / 102% 102% no-repeat;
|
||||||
padding: 16px 14px 14px;
|
border: 0;
|
||||||
box-shadow: var(--shadow), 0 0 24px rgba(212, 175, 55, 0.08);
|
border-radius: 0;
|
||||||
|
padding: 28px 24px 22px;
|
||||||
|
box-shadow: var(--shadow), 0 0 24px rgba(212, 175, 55, 0.12);
|
||||||
}
|
}
|
||||||
|
|
||||||
.close-x {
|
.close-x {
|
||||||
|
|||||||
@@ -1181,7 +1181,9 @@ onUnmounted(() => {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background: var(--desktop-sidebar-panel-bg);
|
background:
|
||||||
|
linear-gradient(rgba(14, 12, 9, 0.58), rgba(14, 12, 9, 0.68)),
|
||||||
|
url('../../assets/images/generated/pc-betslip-sidebar-bg-v1.webp') no-repeat center / cover;
|
||||||
}
|
}
|
||||||
|
|
||||||
.panel-head {
|
.panel-head {
|
||||||
@@ -1233,14 +1235,22 @@ onUnmounted(() => {
|
|||||||
flex: 0 0 20%;
|
flex: 0 0 20%;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
padding: 10px 4px;
|
padding: 10px 4px;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
background: url('../../assets/images/generated/pc-betslip-btn-secondary-v1.webp') center / 100% 100% no-repeat;
|
||||||
|
color: var(--primary-light);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.clear-slip-btn:hover {
|
.clear-slip-btn:hover {
|
||||||
color: var(--primary-light);
|
color: #fff0a8;
|
||||||
border-color: var(--border-gold-soft);
|
filter: brightness(1.08);
|
||||||
background: rgba(212, 175, 55, 0.06);
|
}
|
||||||
|
|
||||||
|
.clear-slip-btn.foot-clear:active {
|
||||||
|
background-image: url('../../assets/images/generated/pc-betslip-btn-secondary-pressed-v1.webp');
|
||||||
|
filter: brightness(0.96);
|
||||||
}
|
}
|
||||||
|
|
||||||
.balance-info {
|
.balance-info {
|
||||||
@@ -1806,17 +1816,26 @@ onUnmounted(() => {
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
border-radius: 4px;
|
border-radius: 0;
|
||||||
background: linear-gradient(180deg, #F0D875 0%, #D4AF37 100%);
|
background: url('../../assets/images/generated/pc-betslip-btn-primary-v1.webp') center / 100% 100% no-repeat;
|
||||||
color: #3D2800;
|
color: #1b1200;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
transition: opacity 0.2s;
|
transition: opacity 0.2s, filter 0.15s;
|
||||||
border: none;
|
border: none;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.submit-btn:not(:disabled):hover {
|
||||||
|
filter: brightness(1.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-btn:not(:disabled):active {
|
||||||
|
background-image: url('../../assets/images/generated/pc-betslip-btn-primary-pressed-v1.webp');
|
||||||
|
filter: brightness(0.98);
|
||||||
|
}
|
||||||
|
|
||||||
.submit-btn:disabled {
|
.submit-btn:disabled {
|
||||||
opacity: 0.4;
|
opacity: 0.4;
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
|
|||||||
@@ -83,16 +83,16 @@ function statusLabel(status: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const SEL_TRANS: Record<string, Record<string, string>> = {
|
const SEL_TRANS: Record<string, Record<string, string>> = {
|
||||||
'主胜': { 'en-US': 'Home Win', 'ms-MY': 'Rumah Menang' },
|
'\u4e3b\u80dc': { 'en-US': 'Home Win', 'ms-MY': 'Rumah Menang' },
|
||||||
'客胜': { 'en-US': 'Away Win', 'ms-MY': 'Tandang Menang' },
|
'\u5ba2\u80dc': { 'en-US': 'Away Win', 'ms-MY': 'Tandang Menang' },
|
||||||
'和局': { 'en-US': 'Draw', 'ms-MY': 'Seri' },
|
'\u548c\u5c40': { 'en-US': 'Draw', 'ms-MY': 'Seri' },
|
||||||
'主': { 'en-US': 'Home', 'ms-MY': 'Rumah' },
|
'\u4e3b': { 'en-US': 'Home', 'ms-MY': 'Rumah' },
|
||||||
'客': { 'en-US': 'Away', 'ms-MY': 'Tandang' },
|
'\u5ba2': { 'en-US': 'Away', 'ms-MY': 'Tandang' },
|
||||||
'大': { 'en-US': 'Over', 'ms-MY': 'Atas' },
|
'\u5927': { 'en-US': 'Over', 'ms-MY': 'Atas' },
|
||||||
'小': { 'en-US': 'Under', 'ms-MY': 'Bawah' },
|
'\u5c0f': { 'en-US': 'Under', 'ms-MY': 'Bawah' },
|
||||||
'单': { 'en-US': 'Odd', 'ms-MY': 'Ganjil' },
|
'\u5355': { 'en-US': 'Odd', 'ms-MY': 'Ganjil' },
|
||||||
'双': { 'en-US': 'Even', 'ms-MY': 'Genap' },
|
'\u53cc': { 'en-US': 'Even', 'ms-MY': 'Genap' },
|
||||||
'冠军': { 'en-US': 'Winner', 'ms-MY': 'Juara' },
|
'\u51a0\u519b': { 'en-US': 'Winner', 'ms-MY': 'Juara' },
|
||||||
};
|
};
|
||||||
|
|
||||||
function translateSel(name: string): string {
|
function translateSel(name: string): string {
|
||||||
@@ -115,8 +115,8 @@ function translateSel(name: string): string {
|
|||||||
<div v-if="visible" class="modal-overlay" @click.self="close">
|
<div v-if="visible" class="modal-overlay" @click.self="close">
|
||||||
<div class="modal-container" role="dialog" aria-modal="true">
|
<div class="modal-container" role="dialog" aria-modal="true">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<span class="modal-title">{{ t('bet.detail_title') || '注单详情' }}</span>
|
<span class="modal-title">{{ t('bet.detail_title') }}</span>
|
||||||
<button type="button" class="modal-close" @click="close">✕</button>
|
<button type="button" class="modal-close" @click="close">✕</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
@@ -132,36 +132,36 @@ function translateSel(name: string): string {
|
|||||||
<template v-else-if="detail">
|
<template v-else-if="detail">
|
||||||
<div class="info-rows">
|
<div class="info-rows">
|
||||||
<div class="info-row">
|
<div class="info-row">
|
||||||
<span class="row-label">{{ t('bet.bet_no') || '注单号' }}</span>
|
<span class="row-label">{{ t('bet.bet_no') }}</span>
|
||||||
<span class="row-val mono">{{ detail.betNo }}</span>
|
<span class="row-val mono">{{ detail.betNo }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="info-row">
|
<div class="info-row">
|
||||||
<span class="row-label">{{ t('common.status') || '状态' }}</span>
|
<span class="row-label">{{ t('common.status') }}</span>
|
||||||
<span class="row-val">
|
<span class="row-val">
|
||||||
<span class="st-badge" :class="statusClass(detail.status)">{{ statusLabel(detail.status) }}</span>
|
<span class="st-badge" :class="statusClass(detail.status)">{{ statusLabel(detail.status) }}</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="info-row">
|
<div class="info-row">
|
||||||
<span class="row-label">{{ t('bet.stake') || '投注额' }}</span>
|
<span class="row-label">{{ t('bet.stake') }}</span>
|
||||||
<span class="row-val">{{ detail.stake }}</span>
|
<span class="row-val">{{ detail.stake }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="info-row">
|
<div class="info-row">
|
||||||
<span class="row-label">{{ t('bet.potential_payout') || '预计派彩' }}</span>
|
<span class="row-label">{{ t('bet.potential_payout') }}</span>
|
||||||
<span class="row-val gold">{{ detail.potentialReturn || '-' }}</span>
|
<span class="row-val gold">{{ detail.potentialReturn || '-' }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="info-row">
|
<div class="info-row">
|
||||||
<span class="row-label">{{ t('bet.placed_at') || '下注时间' }}</span>
|
<span class="row-label">{{ t('bet.placed_at') }}</span>
|
||||||
<span class="row-val muted">{{ detail.placedAt ? new Date(detail.placedAt).toLocaleString() : '-' }}</span>
|
<span class="row-val muted">{{ detail.placedAt ? new Date(detail.placedAt).toLocaleString() : '-' }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="sel-section">
|
<div class="sel-section">
|
||||||
<div class="sel-section-title">{{ t('bet.selections') || '投注选项' }}</div>
|
<div class="sel-section-title">{{ t('bet.selections') }}</div>
|
||||||
<div v-for="(leg, idx) in detail.legs" :key="idx" class="sel-item">
|
<div v-for="(leg, idx) in detail.legs" :key="idx" class="sel-item">
|
||||||
<div class="sel-item-main">
|
<div class="sel-item-main">
|
||||||
<span class="sel-item-match">{{ leg.matchTitle || t('bet.match') }}</span>
|
<span class="sel-item-match">{{ leg.matchTitle || t('bet.match') }}</span>
|
||||||
<span class="sel-item-pick">
|
<span class="sel-item-pick">
|
||||||
{{ leg.marketLabel || '' }} · {{ translateSel(leg.selectionName || '') }}
|
{{ leg.marketLabel || '' }} - {{ translateSel(leg.selectionName || '') }}
|
||||||
</span>
|
</span>
|
||||||
<span v-if="leg.score?.ft" class="sel-item-score">{{ t('history.ft') }}: {{ leg.score.ft }}</span>
|
<span v-if="leg.score?.ft" class="sel-item-score">{{ t('history.ft') }}: {{ leg.score.ft }}</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -170,7 +170,7 @@ function translateSel(name: string): string {
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<div v-else class="modal-empty">{{ t('common.not_found') || '未找到记录' }}</div>
|
<div v-else class="modal-empty">{{ t('common.not_found') }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -191,15 +191,19 @@ function translateSel(name: string): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.modal-container {
|
.modal-container {
|
||||||
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 520px;
|
max-width: 520px;
|
||||||
max-height: 80vh;
|
max-height: 80vh;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
background: var(--desktop-sidebar-bg, rgba(20, 20, 20, 0.95));
|
padding: 20px 22px 22px;
|
||||||
border: 1px solid var(--desktop-border, #262626);
|
background:
|
||||||
border-radius: 4px;
|
linear-gradient(rgba(15, 14, 11, 0.18), rgba(15, 14, 11, 0.2)),
|
||||||
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.5);
|
url('../../assets/images/generated/modal-gold-frame-v4.webp') center / 102% 102% no-repeat;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
box-shadow: 0 18px 48px rgba(0, 0, 0, 0.58), 0 0 28px rgba(212, 175, 55, 0.12);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -207,8 +211,8 @@ function translateSel(name: string): string {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: 12px 16px;
|
padding: 2px 0 12px;
|
||||||
border-bottom: 1px solid var(--desktop-border, #262626);
|
border-bottom: 1px solid rgba(212, 175, 55, 0.16);
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -275,9 +279,7 @@ function translateSel(name: string): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Info rows */
|
/* Info rows */
|
||||||
.info-rows {
|
.info-rows { border-bottom: 1px solid rgba(212, 175, 55, 0.12); }
|
||||||
border-bottom: 1px solid var(--desktop-border, #262626);
|
|
||||||
}
|
|
||||||
|
|
||||||
.info-row {
|
.info-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -324,7 +326,7 @@ function translateSel(name: string): string {
|
|||||||
.st-default { background: rgba(100,100,100,0.1); color: #888; }
|
.st-default { background: rgba(100,100,100,0.1); color: #888; }
|
||||||
|
|
||||||
/* Selections */
|
/* Selections */
|
||||||
.sel-section { padding: 12px 16px 16px; }
|
.sel-section { padding: 12px 0 2px; }
|
||||||
|
|
||||||
.sel-section-title {
|
.sel-section-title {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
|||||||
@@ -47,7 +47,9 @@ watch(
|
|||||||
width: var(--desktop-right-betslip-w);
|
width: var(--desktop-right-betslip-w);
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
border-left: 1px solid var(--border);
|
border-left: 1px solid var(--border);
|
||||||
background: var(--desktop-sidebar-panel-bg);
|
background:
|
||||||
|
linear-gradient(rgba(14, 12, 9, 0.58), rgba(14, 12, 9, 0.68)),
|
||||||
|
url('../../assets/images/generated/pc-betslip-sidebar-bg-v1.webp') no-repeat center / cover;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
|
|||||||
@@ -2,7 +2,10 @@
|
|||||||
import { ref, computed, onMounted, onUnmounted } from 'vue';
|
import { ref, computed, onMounted, onUnmounted } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import type { OutrightEvent, OutrightSelection } from '../outright/OutrightEventSection.vue';
|
import type { OutrightEvent, OutrightSelection } from '../outright/OutrightEventSection.vue';
|
||||||
import saishiImg from '../../assets/images/saishi.webp';
|
import saishiImg from '../../assets/images/generated/saishi-gold-trophy-v1.webp';
|
||||||
|
import outrightListCardBg from '../../assets/images/generated/pc-match-list-card-bg-v1.webp';
|
||||||
|
|
||||||
|
const outrightCardBg = `url(${outrightListCardBg})`;
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
event: OutrightEvent;
|
event: OutrightEvent;
|
||||||
@@ -107,9 +110,9 @@ const topSelections = computed(() => {
|
|||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-height: 140px;
|
min-height: 140px;
|
||||||
border: 1px solid rgba(140, 140, 140, 0.35);
|
border: 0;
|
||||||
border-radius: 6px;
|
border-radius: 0;
|
||||||
background: linear-gradient(180deg, #1a1a1a 0%, #0d0d0d 100%);
|
background: v-bind(outrightCardBg) center / 100% 100% no-repeat;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|||||||
@@ -82,8 +82,8 @@ function txLabel(tx: TxDetail): string {
|
|||||||
<div v-if="visible" class="modal-overlay" @click.self="close">
|
<div v-if="visible" class="modal-overlay" @click.self="close">
|
||||||
<div class="modal-container" role="dialog" aria-modal="true">
|
<div class="modal-container" role="dialog" aria-modal="true">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<span class="modal-title">{{ t('wallet.transaction_detail') || '交易详情' }}</span>
|
<span class="modal-title">{{ t('wallet.transaction_detail') }}</span>
|
||||||
<button type="button" class="modal-close" @click="close">✕</button>
|
<button type="button" class="modal-close" @click="close">✕</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
@@ -99,45 +99,45 @@ function txLabel(tx: TxDetail): string {
|
|||||||
<template v-else-if="detail">
|
<template v-else-if="detail">
|
||||||
<div class="info-rows">
|
<div class="info-rows">
|
||||||
<div class="info-row">
|
<div class="info-row">
|
||||||
<span class="row-label">{{ t('wallet.type') || '类型' }}</span>
|
<span class="row-label">{{ t('wallet.type') }}</span>
|
||||||
<span class="row-val">{{ txLabel(detail) }}</span>
|
<span class="row-val">{{ txLabel(detail) }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="info-row">
|
<div class="info-row">
|
||||||
<span class="row-label">{{ t('wallet.amount') || '金额' }}</span>
|
<span class="row-label">{{ t('wallet.amount') }}</span>
|
||||||
<span class="row-val mono" :class="parseFloat(detail.amount) >= 0 ? 'pos' : 'neg'">{{ formatMoney(detail.amount, locale) }}</span>
|
<span class="row-val mono" :class="parseFloat(detail.amount) >= 0 ? 'pos' : 'neg'">{{ formatMoney(detail.amount, locale) }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="info-row">
|
<div class="info-row">
|
||||||
<span class="row-label">{{ t('wallet.note') || '备注' }}</span>
|
<span class="row-label">{{ t('wallet.note') }}</span>
|
||||||
<span class="row-val">{{ txSummaryLabel(detail, t) || '-' }}</span>
|
<span class="row-val">{{ txSummaryLabel(detail, t) || '-' }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="info-row">
|
<div class="info-row">
|
||||||
<span class="row-label">{{ t('wallet.balance_before') || '变动前余额' }}</span>
|
<span class="row-label">{{ t('wallet.balance_before') }}</span>
|
||||||
<span class="row-val mono">{{ formatMoney(detail.balanceBefore, locale) }}</span>
|
<span class="row-val mono">{{ formatMoney(detail.balanceBefore, locale) }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="info-row">
|
<div class="info-row">
|
||||||
<span class="row-label">{{ t('wallet.balance_after') || '变动后余额' }}</span>
|
<span class="row-label">{{ t('wallet.balance_after') }}</span>
|
||||||
<span class="row-val mono">{{ formatMoney(detail.balanceAfter, locale) }}</span>
|
<span class="row-val mono">{{ formatMoney(detail.balanceAfter, locale) }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="parseFloat(detail.frozenBefore || '0') > 0 || parseFloat(detail.frozenAfter || '0') > 0" class="info-row">
|
<div v-if="parseFloat(detail.frozenBefore || '0') > 0 || parseFloat(detail.frozenAfter || '0') > 0" class="info-row">
|
||||||
<span class="row-label">{{ t('wallet.frozen_before') || '冻结前' }}</span>
|
<span class="row-label">{{ t('wallet.frozen_before') }}</span>
|
||||||
<span class="row-val mono">{{ formatMoney(detail.frozenBefore, locale) }}</span>
|
<span class="row-val mono">{{ formatMoney(detail.frozenBefore, locale) }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="parseFloat(detail.frozenBefore || '0') > 0 || parseFloat(detail.frozenAfter || '0') > 0" class="info-row">
|
<div v-if="parseFloat(detail.frozenBefore || '0') > 0 || parseFloat(detail.frozenAfter || '0') > 0" class="info-row">
|
||||||
<span class="row-label">{{ t('wallet.frozen_after') || '冻结后' }}</span>
|
<span class="row-label">{{ t('wallet.frozen_after') }}</span>
|
||||||
<span class="row-val mono">{{ formatMoney(detail.frozenAfter, locale) }}</span>
|
<span class="row-val mono">{{ formatMoney(detail.frozenAfter, locale) }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="info-row">
|
<div class="info-row">
|
||||||
<span class="row-label">{{ t('wallet.time') || '时间' }}</span>
|
<span class="row-label">{{ t('wallet.time') }}</span>
|
||||||
<span class="row-val muted">{{ new Date(detail.createdAt).toLocaleString() }}</span>
|
<span class="row-val muted">{{ new Date(detail.createdAt).toLocaleString() }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="info-row">
|
<div class="info-row">
|
||||||
<span class="row-label">{{ t('wallet.transaction_id') || '流水号' }}</span>
|
<span class="row-label">{{ t('wallet.transaction_id') }}</span>
|
||||||
<span class="row-val mono muted">{{ detail.transactionId }}</span>
|
<span class="row-val mono muted">{{ detail.transactionId }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<div v-else class="modal-empty">{{ t('common.not_found') || '未找到记录' }}</div>
|
<div v-else class="modal-empty">{{ t('common.not_found') }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -158,15 +158,19 @@ function txLabel(tx: TxDetail): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.modal-container {
|
.modal-container {
|
||||||
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 460px;
|
max-width: 460px;
|
||||||
max-height: 80vh;
|
max-height: 80vh;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
background: var(--desktop-sidebar-bg, rgba(20, 20, 20, 0.95));
|
padding: 20px 22px 22px;
|
||||||
border: 1px solid var(--desktop-border, #262626);
|
background:
|
||||||
border-radius: 4px;
|
linear-gradient(rgba(15, 14, 11, 0.18), rgba(15, 14, 11, 0.2)),
|
||||||
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.5);
|
url('../../assets/images/generated/modal-gold-frame-v4.webp') center / 102% 102% no-repeat;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
box-shadow: 0 18px 48px rgba(0, 0, 0, 0.58), 0 0 28px rgba(212, 175, 55, 0.12);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,8 +178,8 @@ function txLabel(tx: TxDetail): string {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: 12px 16px;
|
padding: 2px 0 12px;
|
||||||
border-bottom: 1px solid var(--desktop-border, #262626);
|
border-bottom: 1px solid rgba(212, 175, 55, 0.16);
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -242,7 +242,7 @@ function onSubmitClick() {
|
|||||||
matchName: props.pick.eventTitle,
|
matchName: props.pick.eventTitle,
|
||||||
marketId: '',
|
marketId: '',
|
||||||
marketName: props.pick.eventTitle,
|
marketName: props.pick.eventTitle,
|
||||||
selectionName: `${props.pick.teamName} · ${props.pick.eventTitle}`,
|
selectionName: `${props.pick.teamName} - ${props.pick.eventTitle}`,
|
||||||
odds: oddsNum.value,
|
odds: oddsNum.value,
|
||||||
marketType: 'OUTRIGHT',
|
marketType: 'OUTRIGHT',
|
||||||
lineValue: null,
|
lineValue: null,
|
||||||
@@ -304,7 +304,7 @@ function formatOdds(odds: string) {
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="open && pick" class="overlay" @click.self="close">
|
<div v-if="open && pick" class="overlay" @click.self="close">
|
||||||
<div class="modal" role="dialog" aria-modal="true">
|
<div class="modal" role="dialog" aria-modal="true">
|
||||||
<button type="button" class="close-x" :aria-label="t('bet.cancel')" @click="close">✕</button>
|
<button type="button" class="close-x" :aria-label="t('bet.cancel')" @click="close">✕</button>
|
||||||
|
|
||||||
<template v-if="step === 'form'">
|
<template v-if="step === 'form'">
|
||||||
<p class="hint">{{ t('bet.outright_enter_stake') }}</p>
|
<p class="hint">{{ t('bet.outright_enter_stake') }}</p>
|
||||||
@@ -321,7 +321,7 @@ function formatOdds(odds: string) {
|
|||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<template v-if="oddsDelta && !oddsDelta.suspended">
|
<template v-if="oddsDelta && !oddsDelta.suspended">
|
||||||
@ {{ oddsDelta.oldOdds.toFixed(2) }} → {{ oddsDelta.newOdds.toFixed(2) }}
|
@ {{ oddsDelta.oldOdds.toFixed(2) }} -> {{ oddsDelta.newOdds.toFixed(2) }}
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
@ {{ formatOdds(currentOdds || pick.odds) }}
|
@ {{ formatOdds(currentOdds || pick.odds) }}
|
||||||
@@ -357,7 +357,7 @@ function formatOdds(odds: string) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p class="est-return">
|
<p class="est-return">
|
||||||
{{ t('history.est_return') }}:<span class="est-value">{{ estReturnText }}</span>
|
{{ t('history.est_return') }}: <span class="est-value">{{ estReturnText }}</span>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p v-if="error" class="error">{{ error }}</p>
|
<p v-if="error" class="error">{{ error }}</p>
|
||||||
@@ -368,7 +368,7 @@ function formatOdds(odds: string) {
|
|||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="btn-confirm btn-gold-outline"
|
class="btn-confirm"
|
||||||
:disabled="loading || stake <= 0 || hasSuspendedSelection"
|
:disabled="loading || stake <= 0 || hasSuspendedSelection"
|
||||||
@click="onSubmitClick"
|
@click="onSubmitClick"
|
||||||
>
|
>
|
||||||
@@ -378,7 +378,7 @@ function formatOdds(odds: string) {
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<div class="success-icon">✓</div>
|
<div class="success-icon">✓</div>
|
||||||
<h3 class="success-title">{{ t('bet.outright_success') }}</h3>
|
<h3 class="success-title">{{ t('bet.outright_success') }}</h3>
|
||||||
|
|
||||||
<div class="hero hero--compact">
|
<div class="hero hero--compact">
|
||||||
@@ -400,7 +400,7 @@ function formatOdds(odds: string) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button type="button" class="btn-done btn-gold-outline" @click="close">
|
<button type="button" class="btn-done" @click="close">
|
||||||
{{ t('bet.outright_done') }}
|
{{ t('bet.outright_done') }}
|
||||||
</button>
|
</button>
|
||||||
</template>
|
</template>
|
||||||
@@ -437,12 +437,12 @@ function formatOdds(odds: string) {
|
|||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 300px;
|
max-width: 300px;
|
||||||
background: linear-gradient(165deg, #1a1810 0%, #121212 45%, #0a0a0a 100%);
|
background: url('../../assets/images/generated/outright-bet-modal-frame-v2.webp') center / 100% 100% no-repeat;
|
||||||
border: 1px solid var(--border-gold-soft);
|
border: 0;
|
||||||
border-radius: var(--radius);
|
border-radius: 0;
|
||||||
padding: 18px 16px 16px;
|
padding: 30px 24px 24px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
box-shadow: var(--shadow), 0 0 24px rgba(212, 175, 55, 0.08);
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.close-x {
|
.close-x {
|
||||||
@@ -644,22 +644,36 @@ function formatOdds(odds: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.btn-cancel {
|
.btn-cancel {
|
||||||
padding: 10px;
|
height: 46px;
|
||||||
border-radius: 6px;
|
padding: 10px 12px;
|
||||||
background: #1a1a1a;
|
border: 0;
|
||||||
border: 1px solid var(--border);
|
border-radius: 0;
|
||||||
|
background: url('../../assets/images/generated/pc-betslip-btn-secondary-v1.webp') center / 100% 100% no-repeat;
|
||||||
color: var(--text-muted);
|
color: var(--text-muted);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn-cancel:active {
|
||||||
|
background-image: url('../../assets/images/generated/pc-betslip-btn-secondary-pressed-v1.webp');
|
||||||
|
}
|
||||||
|
|
||||||
.btn-confirm {
|
.btn-confirm {
|
||||||
padding: 10px;
|
height: 46px;
|
||||||
border-radius: 6px;
|
padding: 10px 12px;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
background: url('../../assets/images/generated/pc-betslip-btn-primary-v1.webp') center / 100% 100% no-repeat;
|
||||||
|
color: #100d04;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn-confirm:active {
|
||||||
|
background-image: url('../../assets/images/generated/pc-betslip-btn-primary-pressed-v1.webp');
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-cancel:disabled,
|
||||||
.btn-confirm:disabled {
|
.btn-confirm:disabled {
|
||||||
opacity: 0.45;
|
opacity: 0.45;
|
||||||
}
|
}
|
||||||
@@ -708,9 +722,17 @@ function formatOdds(odds: string) {
|
|||||||
|
|
||||||
.btn-done {
|
.btn-done {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 11px;
|
height: 46px;
|
||||||
border-radius: 6px;
|
padding: 11px 12px;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
background: url('../../assets/images/generated/pc-betslip-btn-primary-v1.webp') center / 100% 100% no-repeat;
|
||||||
|
color: #100d04;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn-done:active {
|
||||||
|
background-image: url('../../assets/images/generated/pc-betslip-btn-primary-pressed-v1.webp');
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import OutrightOptionCard from './OutrightOptionCard.vue';
|
import OutrightOptionCard from './OutrightOptionCard.vue';
|
||||||
import saishiImg from '../../assets/images/saishi.webp';
|
import saishiImg from '../../assets/images/generated/saishi-gold-trophy-v1.webp';
|
||||||
import cardBg from '../../assets/images/card-bg.webp';
|
import cardBg from '../../assets/images/generated/pc-match-list-card-bg-v1.webp';
|
||||||
|
|
||||||
const matchCardBg = `url(${cardBg})`;
|
const matchCardBg = `url(${cardBg})`;
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import OutrightEventSection, {
|
|||||||
} from './OutrightEventSection.vue';
|
} from './OutrightEventSection.vue';
|
||||||
import OutrightBetModal, { type OutrightPick } from './OutrightBetModal.vue';
|
import OutrightBetModal, { type OutrightPick } from './OutrightBetModal.vue';
|
||||||
import { useAuthStore } from '../../stores/auth';
|
import { useAuthStore } from '../../stores/auth';
|
||||||
import emptyMatchesImg from '../../assets/images/empty-matches.svg';
|
import emptyMatchesImg from '../../assets/images/generated/empty-matches-stadium-v1.webp';
|
||||||
import GoldSpinner from '../../components/GoldSpinner.vue';
|
import GoldSpinner from '../../components/GoldSpinner.vue';
|
||||||
import { useOutrightEvents } from '../../composables/useOutrightEvents';
|
import { useOutrightEvents } from '../../composables/useOutrightEvents';
|
||||||
|
|
||||||
@@ -159,16 +159,25 @@ function closeModal() {
|
|||||||
|
|
||||||
.state,
|
.state,
|
||||||
.empty {
|
.empty {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: var(--text-muted);
|
color: var(--text-muted);
|
||||||
padding: 48px 20px;
|
padding: 34px 20px 44px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.empty-icon {
|
.empty-icon {
|
||||||
width: 96px;
|
width: min(270px, 82vw);
|
||||||
height: 96px;
|
aspect-ratio: 16 / 9;
|
||||||
margin-bottom: 14px;
|
height: auto;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
border-radius: 8px;
|
||||||
|
object-fit: cover;
|
||||||
|
opacity: 0.86;
|
||||||
|
mask-image: linear-gradient(90deg, transparent 0, #000 10%, #000 90%, transparent 100%);
|
||||||
|
-webkit-mask-image: linear-gradient(90deg, transparent 0, #000 10%, #000 90%, transparent 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.empty-hint {
|
.empty-hint {
|
||||||
|
|||||||
@@ -1,15 +1,23 @@
|
|||||||
import { ref } from 'vue';
|
import { onMounted, ref, watch } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import api from '../api';
|
import api from '../api';
|
||||||
import type { OutrightEvent } from '../components/outright/OutrightEventSection.vue';
|
import type { OutrightEvent } from '../components/outright/OutrightEventSection.vue';
|
||||||
import type { OutrightSelection } from '../components/outright/OutrightEventSection.vue';
|
import type { OutrightSelection } from '../components/outright/OutrightEventSection.vue';
|
||||||
import { useOnLocaleChange } from './useOnLocaleChange';
|
|
||||||
|
const CACHE_TTL_MS = 8000;
|
||||||
|
const loading = ref(false);
|
||||||
|
const loadError = ref('');
|
||||||
|
const events = ref<OutrightEvent[]>([]);
|
||||||
|
let lastLoadedAt = 0;
|
||||||
|
let inFlight: Promise<OutrightEvent[]> | null = null;
|
||||||
|
|
||||||
|
type LoadOptions = {
|
||||||
|
silent?: boolean;
|
||||||
|
force?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
export function useOutrightEvents() {
|
export function useOutrightEvents() {
|
||||||
const { t } = useI18n();
|
const { t, locale } = useI18n();
|
||||||
const loading = ref(true);
|
|
||||||
const loadError = ref('');
|
|
||||||
const events = ref<OutrightEvent[]>([]);
|
|
||||||
|
|
||||||
function mergeOddsOnly(fresh: OutrightEvent[]) {
|
function mergeOddsOnly(fresh: OutrightEvent[]) {
|
||||||
const freshMap = new Map<string, OutrightEvent>();
|
const freshMap = new Map<string, OutrightEvent>();
|
||||||
@@ -30,15 +38,34 @@ export function useOutrightEvents() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function load(options?: { silent?: boolean }) {
|
async function load(options?: LoadOptions) {
|
||||||
const hadData = events.value.length > 0;
|
const hadData = events.value.length > 0;
|
||||||
|
if (!options?.force && hadData && Date.now() - lastLoadedAt < CACHE_TTL_MS) {
|
||||||
|
loading.value = false;
|
||||||
|
loadError.value = '';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inFlight) {
|
||||||
|
if (!hadData && !options?.silent) loading.value = true;
|
||||||
|
try {
|
||||||
|
await inFlight;
|
||||||
|
} finally {
|
||||||
|
if (!hadData && !options?.silent) loading.value = false;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!hadData && !options?.silent) loading.value = true;
|
if (!hadData && !options?.silent) loading.value = true;
|
||||||
loadError.value = '';
|
loadError.value = '';
|
||||||
try {
|
try {
|
||||||
const { data } = await api.get('/player/outrights');
|
inFlight = api.get('/player/outrights').then(({ data }) => {
|
||||||
const list = (data?.data ?? []) as OutrightEvent[];
|
const list = (data?.data ?? []) as OutrightEvent[];
|
||||||
const fresh = list.filter((e) => e.selections?.length > 0);
|
return list.filter((e) => e.selections?.length > 0);
|
||||||
if (!hadData) {
|
});
|
||||||
|
const fresh = await inFlight;
|
||||||
|
lastLoadedAt = Date.now();
|
||||||
|
if (!hadData || options?.force) {
|
||||||
events.value = fresh;
|
events.value = fresh;
|
||||||
} else {
|
} else {
|
||||||
mergeOddsOnly(fresh);
|
mergeOddsOnly(fresh);
|
||||||
@@ -53,10 +80,19 @@ export function useOutrightEvents() {
|
|||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
if (!hadData && !options?.silent) loading.value = false;
|
if (!hadData && !options?.silent) loading.value = false;
|
||||||
|
inFlight = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
useOnLocaleChange(load);
|
onMounted(() => {
|
||||||
|
void load({ silent: events.value.length > 0 });
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(locale, (next, prev) => {
|
||||||
|
if (prev && next !== prev) {
|
||||||
|
void load({ silent: events.value.length > 0, force: true });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
loading,
|
loading,
|
||||||
|
|||||||
@@ -261,7 +261,7 @@ watch(
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 8px 12px;
|
padding: 8px 12px;
|
||||||
min-height: var(--player-header-h);
|
min-height: var(--player-header-h);
|
||||||
background: rgba(17, 17, 17, 0.94);
|
background: rgba(29, 27, 22, 0.88);
|
||||||
border-bottom: 1px solid var(--border);
|
border-bottom: 1px solid var(--border);
|
||||||
z-index: 120;
|
z-index: 120;
|
||||||
}
|
}
|
||||||
@@ -371,7 +371,7 @@ watch(
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
min-height: calc(var(--player-bottom-nav-h) + var(--safe-bottom));
|
min-height: calc(var(--player-bottom-nav-h) + var(--safe-bottom));
|
||||||
padding-bottom: var(--safe-bottom);
|
padding-bottom: var(--safe-bottom);
|
||||||
background: rgba(17, 17, 17, 0.96);
|
background: rgba(29, 27, 22, 0.9);
|
||||||
border-top: 1px solid var(--border);
|
border-top: 1px solid var(--border);
|
||||||
box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.35);
|
box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.35);
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
|
|||||||
@@ -7,13 +7,13 @@
|
|||||||
--secondary: #1A1A1A;
|
--secondary: #1A1A1A;
|
||||||
--tertiary: #000000;
|
--tertiary: #000000;
|
||||||
--neutral: #8E8E93;
|
--neutral: #8E8E93;
|
||||||
--bg-body: #000000;
|
--bg-body: #080806;
|
||||||
--bg-card: rgba(20, 20, 20, 0.65);
|
--bg-card: rgba(33, 31, 25, 0.76);
|
||||||
--bg-hover: rgba(34, 34, 34, 0.65);
|
--bg-hover: rgba(47, 44, 35, 0.82);
|
||||||
--bg-elevated: rgba(42, 42, 42, 0.65);
|
--bg-elevated: rgba(58, 54, 43, 0.86);
|
||||||
--text: #FFFFFF;
|
--text: #FFFFFF;
|
||||||
--text-muted: #8E8E93;
|
--text-muted: #B7B0A0;
|
||||||
--border: #333333;
|
--border: rgba(255, 226, 156, 0.18);
|
||||||
--border-gold: #D4AF37;
|
--border-gold: #D4AF37;
|
||||||
--border-gold-soft: rgba(212, 175, 55, 0.28);
|
--border-gold-soft: rgba(212, 175, 55, 0.28);
|
||||||
--border-w: 1px;
|
--border-w: 1px;
|
||||||
@@ -209,9 +209,9 @@ body {
|
|||||||
/* 保留 bg 位图;用 scroll 替代 fixed,减轻移动端滚动重绘(后续可换 WebP/AVIF) */
|
/* 保留 bg 位图;用 scroll 替代 fixed,减轻移动端滚动重绘(后续可换 WebP/AVIF) */
|
||||||
background-color: var(--tertiary);
|
background-color: var(--tertiary);
|
||||||
background-image:
|
background-image:
|
||||||
radial-gradient(ellipse 120% 60% at 50% -10%, rgba(212, 175, 55, 0.14), transparent 55%),
|
radial-gradient(ellipse 120% 60% at 50% -10%, rgba(246, 210, 108, 0.2), transparent 56%),
|
||||||
linear-gradient(rgba(0, 0, 0, 0.88), rgba(0, 0, 0, 0.88)),
|
linear-gradient(rgba(0, 0, 0, 0.62), rgba(0, 0, 0, 0.7)),
|
||||||
url('./assets/images/bg.webp');
|
url('./assets/images/generated/saishi-gold-trophy-v1.webp');
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: center center;
|
background-position: center center;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
@@ -223,7 +223,10 @@ body {
|
|||||||
|
|
||||||
@media (min-width: 1024px) {
|
@media (min-width: 1024px) {
|
||||||
body {
|
body {
|
||||||
background-image: url('./assets/images/pcbg.png');
|
background-image:
|
||||||
|
radial-gradient(ellipse 90% 70% at 50% 0%, rgba(246, 210, 108, 0.14), transparent 58%),
|
||||||
|
linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.58)),
|
||||||
|
url('./assets/images/generated/pc-global-bg-v1.webp');
|
||||||
background-attachment: fixed;
|
background-attachment: fixed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,8 +8,11 @@
|
|||||||
inset: 0;
|
inset: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
background-color: #000;
|
background-color: #0d0b08;
|
||||||
background-image: url('../../assets/images/pcbg.png');
|
background-image:
|
||||||
|
radial-gradient(ellipse 90% 68% at 50% 0%, rgba(246, 210, 108, 0.14), transparent 58%),
|
||||||
|
linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.58)),
|
||||||
|
url('../../assets/images/generated/pc-global-bg-v1.webp');
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
background-attachment: fixed;
|
background-attachment: fixed;
|
||||||
@@ -21,7 +24,7 @@
|
|||||||
content: '';
|
content: '';
|
||||||
position: fixed;
|
position: fixed;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
background: radial-gradient(ellipse 80% 60% at 50% 0%, rgba(212, 175, 55, 0.03) 0%, transparent 60%);
|
background: radial-gradient(ellipse 80% 60% at 50% 0%, rgba(255, 221, 128, 0.08) 0%, transparent 60%);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
}
|
}
|
||||||
@@ -29,10 +32,8 @@
|
|||||||
.desktop-header-wrap {
|
.desktop-header-wrap {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
height: var(--desktop-header-h);
|
height: var(--desktop-header-h);
|
||||||
background: rgba(14, 14, 14, 0.88);
|
background: #12100c url('../../assets/images/generated/pc-top-nav-bg-v1.webp') center / 100% 100% no-repeat;
|
||||||
backdrop-filter: var(--blur-md);
|
border-bottom: 0;
|
||||||
-webkit-backdrop-filter: var(--blur-md);
|
|
||||||
border-bottom: 1px solid var(--border);
|
|
||||||
z-index: var(--z-header);
|
z-index: var(--z-header);
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -45,7 +46,7 @@
|
|||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
z-index: var(--z-sticky);
|
z-index: var(--z-sticky);
|
||||||
border-bottom: 1px solid var(--border);
|
border-bottom: 1px solid var(--border);
|
||||||
background: rgba(14, 14, 14, 0.85);
|
background: rgba(26, 24, 19, 0.78);
|
||||||
backdrop-filter: var(--blur-sm);
|
backdrop-filter: var(--blur-sm);
|
||||||
-webkit-backdrop-filter: var(--blur-sm);
|
-webkit-backdrop-filter: var(--blur-sm);
|
||||||
}
|
}
|
||||||
@@ -90,7 +91,7 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 0 16px;
|
padding: 0 16px;
|
||||||
border-bottom: 1px solid var(--border);
|
border-bottom: 1px solid var(--border);
|
||||||
background: rgba(14, 14, 14, 0.85);
|
background: rgba(26, 24, 19, 0.76);
|
||||||
backdrop-filter: var(--blur-sm);
|
backdrop-filter: var(--blur-sm);
|
||||||
-webkit-backdrop-filter: var(--blur-sm);
|
-webkit-backdrop-filter: var(--blur-sm);
|
||||||
}
|
}
|
||||||
@@ -105,7 +106,7 @@
|
|||||||
|
|
||||||
.desktop-betting-left {
|
.desktop-betting-left {
|
||||||
border-right: 1px solid var(--border);
|
border-right: 1px solid var(--border);
|
||||||
background: rgba(14, 14, 14, 0.6);
|
background: rgba(26, 24, 19, 0.56);
|
||||||
backdrop-filter: var(--blur-sm);
|
backdrop-filter: var(--blur-sm);
|
||||||
-webkit-backdrop-filter: var(--blur-sm);
|
-webkit-backdrop-filter: var(--blur-sm);
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
@@ -209,7 +210,7 @@
|
|||||||
.desktop-hub-right {
|
.desktop-hub-right {
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
padding: var(--space-5);
|
padding: var(--space-5);
|
||||||
background: rgba(10, 10, 10, 0.3);
|
background: rgba(18, 16, 12, 0.18);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Auth Layout: Centered container ── */
|
/* ── Auth Layout: Centered container ── */
|
||||||
|
|||||||
@@ -12,20 +12,20 @@
|
|||||||
--primary: #D4AF37;
|
--primary: #D4AF37;
|
||||||
--primary-dark: #A8841F;
|
--primary-dark: #A8841F;
|
||||||
--primary-light: #F0D875;
|
--primary-light: #F0D875;
|
||||||
--secondary: #141414;
|
--secondary: #1c1a15;
|
||||||
--tertiary: #0A0A0A;
|
--tertiary: #0f0d09;
|
||||||
--neutral: #8E8E93;
|
--neutral: #8E8E93;
|
||||||
--bg-body: #050505;
|
--bg-body: #0d0b08;
|
||||||
--bg-card: rgba(20, 20, 20, 0.92);
|
--bg-card: rgba(32, 30, 24, 0.82);
|
||||||
--bg-card-hover: rgba(28, 28, 28, 0.95);
|
--bg-card-hover: rgba(44, 40, 31, 0.9);
|
||||||
--bg-hover: rgba(38, 38, 38, 0.95);
|
--bg-hover: rgba(52, 48, 38, 0.9);
|
||||||
--bg-elevated: rgba(45, 45, 45, 0.95);
|
--bg-elevated: rgba(62, 57, 45, 0.92);
|
||||||
--bg-surface: rgba(16, 16, 16, 0.88);
|
--bg-surface: rgba(28, 26, 21, 0.8);
|
||||||
--text: #FFFFFF;
|
--text: #FFFFFF;
|
||||||
--text-secondary: #B8B8BD;
|
--text-secondary: #D3CBB8;
|
||||||
--text-muted: #8E8E93;
|
--text-muted: #B5AD9B;
|
||||||
--border: #262626;
|
--border: rgba(255, 226, 156, 0.16);
|
||||||
--border-subtle: rgba(255, 255, 255, 0.06);
|
--border-subtle: rgba(255, 235, 185, 0.1);
|
||||||
--border-gold: #D4AF37;
|
--border-gold: #D4AF37;
|
||||||
--border-gold-soft: rgba(212, 175, 55, 0.25);
|
--border-gold-soft: rgba(212, 175, 55, 0.25);
|
||||||
--border-w: 1px;
|
--border-w: 1px;
|
||||||
@@ -62,10 +62,10 @@
|
|||||||
--desktop-right-betslip-collapsed-w: 40px;
|
--desktop-right-betslip-collapsed-w: 40px;
|
||||||
|
|
||||||
/* ── Desktop specific vars ── */
|
/* ── Desktop specific vars ── */
|
||||||
--desktop-bg: #050505;
|
--desktop-bg: #0d0b08;
|
||||||
--desktop-border: #262626;
|
--desktop-border: rgba(255, 226, 156, 0.16);
|
||||||
--desktop-sidebar-bg: rgba(20, 20, 20, 0.95);
|
--desktop-sidebar-bg: rgba(30, 28, 23, 0.82);
|
||||||
--desktop-sidebar-panel-bg: linear-gradient(rgba(16, 16, 16, 0.88), rgba(16, 16, 16, 0.88)), url('../../assets/images/cebian.webp') no-repeat center / cover;
|
--desktop-sidebar-panel-bg: linear-gradient(rgba(18, 16, 12, 0.52), rgba(18, 16, 12, 0.64)), url('../../assets/images/generated/pc-sidebar-bg-v1.webp') no-repeat center / cover;
|
||||||
|
|
||||||
/* ── Spacing Scale (8dp rhythm) ── */
|
/* ── Spacing Scale (8dp rhythm) ── */
|
||||||
--space-1: 4px;
|
--space-1: 4px;
|
||||||
|
|||||||
@@ -364,12 +364,19 @@ const showPhaseWatermark = computed(
|
|||||||
.receipt {
|
.receipt {
|
||||||
position: relative;
|
position: relative;
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
background: rgba(18, 18, 18, 0.96);
|
background:
|
||||||
|
linear-gradient(rgba(18, 16, 12, 0.78), rgba(16, 14, 10, 0.86)),
|
||||||
|
url('../assets/images/generated/detail-ledger-ticket-bg-v1.webp') center / cover no-repeat;
|
||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
box-shadow: var(--shadow);
|
box-shadow: var(--shadow);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.receipt > * {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* result strip */
|
/* result strip */
|
||||||
.receipt-result {
|
.receipt-result {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -533,7 +540,7 @@ const showPhaseWatermark = computed(
|
|||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
padding: 14px;
|
padding: 14px;
|
||||||
background: rgba(255, 255, 255, 0.02);
|
background: rgba(255, 242, 198, 0.045);
|
||||||
border: 1px solid rgba(255, 255, 255, 0.06);
|
border: 1px solid rgba(255, 255, 255, 0.06);
|
||||||
border-radius: var(--radius-sm);
|
border-radius: var(--radius-sm);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { usePlayerMatches } from '../composables/usePlayerMatches';
|
|||||||
import LeagueAccordionItem from '../components/LeagueAccordionItem.vue';
|
import LeagueAccordionItem from '../components/LeagueAccordionItem.vue';
|
||||||
import MatchBetCard from '../components/MatchBetCard.vue';
|
import MatchBetCard from '../components/MatchBetCard.vue';
|
||||||
import OutrightPanel from '../components/outright/OutrightPanel.vue';
|
import OutrightPanel from '../components/outright/OutrightPanel.vue';
|
||||||
import emptyMatchesImg from '../assets/images/empty-matches.svg';
|
import emptyMatchesImg from '../assets/images/generated/empty-matches-stadium-v1.webp';
|
||||||
import { useOnLocaleChange } from '../composables/useOnLocaleChange';
|
import { useOnLocaleChange } from '../composables/useOnLocaleChange';
|
||||||
import GoldSpinner from '../components/GoldSpinner.vue';
|
import GoldSpinner from '../components/GoldSpinner.vue';
|
||||||
import { usePullToRefresh } from '../composables/usePullToRefresh';
|
import { usePullToRefresh } from '../composables/usePullToRefresh';
|
||||||
@@ -452,7 +452,6 @@ function goMatch(id: string) {
|
|||||||
.bet-page {
|
.bet-page {
|
||||||
margin: 0 -16px;
|
margin: 0 -16px;
|
||||||
padding-bottom: 8px;
|
padding-bottom: 8px;
|
||||||
background: var(--bg-body);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Tab panel toggle: avoid display:none to prevent browser releasing image resources */
|
/* Tab panel toggle: avoid display:none to prevent browser releasing image resources */
|
||||||
@@ -772,16 +771,25 @@ function goMatch(id: string) {
|
|||||||
.state,
|
.state,
|
||||||
.placeholder,
|
.placeholder,
|
||||||
.empty {
|
.empty {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: var(--text-muted);
|
color: var(--text-muted);
|
||||||
padding: 48px 20px;
|
padding: 34px 20px 44px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.empty-icon {
|
.empty-icon {
|
||||||
width: 96px;
|
width: min(270px, 82vw);
|
||||||
height: 96px;
|
aspect-ratio: 16 / 9;
|
||||||
margin-bottom: 14px;
|
height: auto;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
border-radius: 8px;
|
||||||
|
object-fit: cover;
|
||||||
|
opacity: 0.86;
|
||||||
|
mask-image: linear-gradient(90deg, transparent 0, #000 10%, #000 90%, transparent 100%);
|
||||||
|
-webkit-mask-image: linear-gradient(90deg, transparent 0, #000 10%, #000 90%, transparent 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.placeholder {
|
.placeholder {
|
||||||
|
|||||||
@@ -2,11 +2,11 @@
|
|||||||
import { onActivated, computed, ref } from 'vue';
|
import { onActivated, computed, ref } from 'vue';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import emptyMatchesImg from '../assets/images/empty-matches.svg';
|
import emptyMatchesImg from '../assets/images/generated/empty-matches-stadium-v1.webp';
|
||||||
import vsImg from '../assets/images/vs.png';
|
import vsImg from '../assets/images/generated/vs-gold-alpha-v1.webp';
|
||||||
import cardBg from '../assets/images/card-bg.webp';
|
import hotCardBg from '../assets/images/generated/match-card-bg-gold-stadium-v1.webp';
|
||||||
|
import upcomingCardBg from '../assets/images/generated/match-card-bg-gold-tunnel-v1.webp';
|
||||||
import BannerCarousel from '../components/BannerCarousel.vue';
|
import BannerCarousel from '../components/BannerCarousel.vue';
|
||||||
import HomeAnnouncementCard from '../components/HomeAnnouncementCard.vue';
|
|
||||||
import { usePlayerHome } from '../composables/usePlayerHome';
|
import { usePlayerHome } from '../composables/usePlayerHome';
|
||||||
import TeamEmblem from '../components/TeamEmblem.vue';
|
import TeamEmblem from '../components/TeamEmblem.vue';
|
||||||
import GoldSpinner from '../components/GoldSpinner.vue';
|
import GoldSpinner from '../components/GoldSpinner.vue';
|
||||||
@@ -16,7 +16,8 @@ import type { PlayerHomeMatch } from '../composables/usePlayerHome';
|
|||||||
|
|
||||||
type HotTab = 'hot' | 'upcoming';
|
type HotTab = 'hot' | 'upcoming';
|
||||||
|
|
||||||
const matchCardBg = `url(${cardBg})`;
|
const hotMatchCardBg = `url(${hotCardBg})`;
|
||||||
|
const upcomingMatchCardBg = `url(${upcomingCardBg})`;
|
||||||
const { t, locale } = useI18n();
|
const { t, locale } = useI18n();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { banners, hotMatches, upcomingMatches, loading, load, announcementItems } = usePlayerHome();
|
const { banners, hotMatches, upcomingMatches, loading, load, announcementItems } = usePlayerHome();
|
||||||
@@ -54,10 +55,16 @@ function formatKickoff(startTime: string) {
|
|||||||
return formatLocalMatchDateTime(startTime, locale.value, { variant: 'full' });
|
return formatLocalMatchDateTime(startTime, locale.value, { variant: 'full' });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function matchCardStyle(tab: HotTab) {
|
||||||
|
return {
|
||||||
|
'--match-card-bg': tab === 'hot' ? hotMatchCardBg : upcomingMatchCardBg,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div class="mobile-home">
|
||||||
<div
|
<div
|
||||||
class="pull-indicator"
|
class="pull-indicator"
|
||||||
:style="pullIndicatorStyle()"
|
:style="pullIndicatorStyle()"
|
||||||
@@ -67,10 +74,6 @@ function formatKickoff(startTime: string) {
|
|||||||
|
|
||||||
<BannerCarousel :banners="banners" :fallback-to="bannerFallbackTo" />
|
<BannerCarousel :banners="banners" :fallback-to="bannerFallbackTo" />
|
||||||
|
|
||||||
<div class="home-card-wrapper">
|
|
||||||
<HomeAnnouncementCard />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="hot-tabs" role="tablist" :aria-label="t('home.hot_matches')">
|
<div class="hot-tabs" role="tablist" :aria-label="t('home.hot_matches')">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@@ -98,6 +101,7 @@ function formatKickoff(startTime: string) {
|
|||||||
:key="match.id"
|
:key="match.id"
|
||||||
class="match-card"
|
class="match-card"
|
||||||
:class="{ 'match-card--live-anim': activeTab === 'hot' && index < 3 }"
|
:class="{ 'match-card--live-anim': activeTab === 'hot' && index < 3 }"
|
||||||
|
:style="matchCardStyle(activeTab)"
|
||||||
@click="goMatch(match.id)"
|
@click="goMatch(match.id)"
|
||||||
>
|
>
|
||||||
<div class="match-info">
|
<div class="match-info">
|
||||||
@@ -153,8 +157,9 @@ function formatKickoff(startTime: string) {
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.home-card-wrapper {
|
.mobile-home {
|
||||||
margin: 12px 16px;
|
width: 100%;
|
||||||
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pull-indicator {
|
.pull-indicator {
|
||||||
@@ -166,33 +171,79 @@ function formatKickoff(startTime: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.hot-tabs {
|
.hot-tabs {
|
||||||
display: flex;
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
margin: 14px 0;
|
margin: 14px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hot-tab {
|
.hot-tab {
|
||||||
flex: 1;
|
position: relative;
|
||||||
min-height: 36px;
|
isolation: isolate;
|
||||||
|
width: 100%;
|
||||||
|
min-height: 44px;
|
||||||
|
aspect-ratio: 1024 / 275;
|
||||||
padding: 0 12px;
|
padding: 0 12px;
|
||||||
border-radius: var(--radius-sm);
|
border: 0;
|
||||||
border: 1px solid var(--border);
|
background: transparent;
|
||||||
background: var(--bg-card);
|
color: rgba(255, 255, 255, 0.62);
|
||||||
color: var(--text-muted);
|
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
font-weight: 600;
|
font-weight: 700;
|
||||||
transition: background 0.2s, border-color 0.2s, color 0.2s;
|
letter-spacing: 0;
|
||||||
|
transition: color 0.2s ease, transform 0.2s ease;
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
user-select: none;
|
||||||
|
appearance: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hot-tab::before,
|
||||||
|
.hot-tab::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
transition: opacity 0.2s ease, background 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hot-tab::before {
|
||||||
|
z-index: -2;
|
||||||
|
background: url('../assets/images/generated/home-tab-frame-gold-v1.webp') center / 100% 100% no-repeat;
|
||||||
|
opacity: 0.58;
|
||||||
|
filter: saturate(0.86) brightness(0.76);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hot-tab::after {
|
||||||
|
z-index: -1;
|
||||||
|
inset: 8px 16px;
|
||||||
|
background: rgba(0, 0, 0, 0.16);
|
||||||
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hot-tab.active {
|
.hot-tab.active {
|
||||||
font-weight: 700;
|
|
||||||
background: rgba(244, 162, 97, 0.1);
|
|
||||||
border-color: var(--primary);
|
|
||||||
color: var(--primary-light);
|
color: var(--primary-light);
|
||||||
|
text-shadow: 0 0 10px rgba(247, 211, 101, 0.32);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hot-tab.active::before,
|
||||||
|
.hot-tab:active::before {
|
||||||
|
opacity: 1;
|
||||||
|
filter: saturate(1.08) brightness(1.02);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hot-tab.active::after {
|
||||||
|
background: rgba(0, 0, 0, 0.04);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hot-tab:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hot-tab:focus-visible::before {
|
||||||
|
filter: drop-shadow(0 0 6px rgba(247, 211, 101, 0.45));
|
||||||
}
|
}
|
||||||
|
|
||||||
.hot-tab:active {
|
.hot-tab:active {
|
||||||
opacity: 0.92;
|
transform: scale(0.985);
|
||||||
}
|
}
|
||||||
|
|
||||||
.match-card {
|
.match-card {
|
||||||
@@ -218,8 +269,8 @@ function formatKickoff(startTime: string) {
|
|||||||
content: '';
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
background: v-bind(matchCardBg) center / 100% 100% no-repeat;
|
background: var(--match-card-bg) center / 100% 100% no-repeat;
|
||||||
opacity: 0.25;
|
opacity: 0.28;
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
@@ -232,7 +283,7 @@ function formatKickoff(startTime: string) {
|
|||||||
.match-info,
|
.match-info,
|
||||||
.match-flags {
|
.match-flags {
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 1;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.match-info {
|
.match-info {
|
||||||
@@ -445,15 +496,24 @@ function formatKickoff(startTime: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.empty {
|
.empty {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: var(--text-muted);
|
color: var(--text-muted);
|
||||||
padding: 40px 20px;
|
padding: 30px 20px 36px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.empty-icon {
|
.empty-icon {
|
||||||
width: 96px;
|
width: min(260px, 82vw);
|
||||||
height: 96px;
|
aspect-ratio: 16 / 9;
|
||||||
margin-bottom: 14px;
|
height: auto;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
border-radius: 8px;
|
||||||
|
object-fit: cover;
|
||||||
|
opacity: 0.86;
|
||||||
|
mask-image: linear-gradient(90deg, transparent 0, #000 10%, #000 90%, transparent 100%);
|
||||||
|
-webkit-mask-image: linear-gradient(90deg, transparent 0, #000 10%, #000 90%, transparent 100%);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import CorrectScorePanel from '../components/match-detail/CorrectScorePanel.vue'
|
|||||||
import { isCorrectScoreMarket, parseScoreCode } from '../utils/correctScoreLayout';
|
import { isCorrectScoreMarket, parseScoreCode } from '../utils/correctScoreLayout';
|
||||||
import { useOnLocaleChange } from '../composables/useOnLocaleChange';
|
import { useOnLocaleChange } from '../composables/useOnLocaleChange';
|
||||||
import { usePullToRefresh } from '../composables/usePullToRefresh';
|
import { usePullToRefresh } from '../composables/usePullToRefresh';
|
||||||
import vsImg from '../assets/images/vs.png';
|
import vsImg from '../assets/images/generated/vs-gold-alpha-v1.webp';
|
||||||
import GoldSpinner from '../components/GoldSpinner.vue';
|
import GoldSpinner from '../components/GoldSpinner.vue';
|
||||||
import { matchPhaseLabel, type MatchPhase } from '../utils/matchPhase';
|
import { matchPhaseLabel, type MatchPhase } from '../utils/matchPhase';
|
||||||
import { formatLocalMatchDateTime } from '@thebet365/shared';
|
import { formatLocalMatchDateTime } from '@thebet365/shared';
|
||||||
@@ -911,18 +911,36 @@ function onPickSelection(selId: string, marketId: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.my-bets-list {
|
.my-bets-list {
|
||||||
display: flex;
|
display: grid;
|
||||||
flex-direction: column;
|
grid-auto-flow: column;
|
||||||
gap: 8px;
|
grid-template-rows: repeat(2, minmax(72px, auto));
|
||||||
|
grid-auto-columns: minmax(158px, calc((100% - 6px) / 2));
|
||||||
|
gap: 6px;
|
||||||
|
overflow-x: auto;
|
||||||
|
overflow-y: hidden;
|
||||||
|
padding-bottom: 2px;
|
||||||
|
scroll-snap-type: x proximity;
|
||||||
|
scrollbar-width: none;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-bets-list::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.my-bet-card {
|
.my-bet-card {
|
||||||
background: #1c1c1c;
|
background: #1c1c1c;
|
||||||
border: 1px solid #2e2e2e;
|
border: 1px solid #2e2e2e;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
padding: 10px 12px;
|
padding: 8px 9px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: background 0.15s;
|
transition: background 0.15s;
|
||||||
|
min-width: 0;
|
||||||
|
min-height: 72px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
scroll-snap-align: start;
|
||||||
}
|
}
|
||||||
|
|
||||||
.my-bet-card:active {
|
.my-bet-card:active {
|
||||||
@@ -931,27 +949,29 @@ function onPickSelection(selId: string, marketId: string) {
|
|||||||
|
|
||||||
.bet-header {
|
.bet-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
gap: 6px;
|
||||||
margin-bottom: 6px;
|
margin-bottom: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bet-type {
|
.bet-type {
|
||||||
font-size: 12px;
|
font-size: 11px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
margin-right: 8px;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bet-status {
|
.bet-status {
|
||||||
font-size: 11px;
|
font-size: 10px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
padding: 2px 8px;
|
padding: 1px 6px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
line-height: 1.5;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -972,18 +992,30 @@ function onPickSelection(selId: string, marketId: string) {
|
|||||||
|
|
||||||
.bet-footer {
|
.bet-footer {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
align-items: flex-end;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
gap: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bet-stake {
|
.bet-stake {
|
||||||
font-size: 11px;
|
font-size: 10px;
|
||||||
color: #888;
|
color: #888;
|
||||||
|
min-width: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bet-return {
|
.bet-return {
|
||||||
font-size: 13px;
|
font-size: 12px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 340px) {
|
||||||
|
.my-bets-list {
|
||||||
|
grid-auto-columns: minmax(148px, calc((100% - 6px) / 2));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -281,13 +281,23 @@ function auditNoteDisplayText(remark: { kind: 'note'; text: string }) {
|
|||||||
|
|
||||||
.summary-card,
|
.summary-card,
|
||||||
.audit-card {
|
.audit-card {
|
||||||
background: linear-gradient(135deg, #1a1810 0%, #1f1b0e 40%, #16140c 100%);
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
background:
|
||||||
|
linear-gradient(rgba(22, 20, 15, 0.74), rgba(18, 16, 12, 0.84)),
|
||||||
|
url('../assets/images/generated/detail-ledger-ticket-bg-v1.webp') center / cover no-repeat;
|
||||||
border: 1px solid rgba(212, 175, 55, 0.2);
|
border: 1px solid rgba(212, 175, 55, 0.2);
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.summary-card > *,
|
||||||
|
.audit-card > * {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
.summary-head { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
|
.summary-head { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
|
||||||
.method-badge { font-size: 10px; font-weight: 700; padding: 2px 8px; border-radius: 4px; }
|
.method-badge { font-size: 10px; font-weight: 700; padding: 2px 8px; border-radius: 4px; }
|
||||||
.method-badge.bank { background: rgba(212,175,55,0.15); color: var(--primary-light); }
|
.method-badge.bank { background: rgba(212,175,55,0.15); color: var(--primary-light); }
|
||||||
|
|||||||
@@ -262,23 +262,31 @@ function goCashbackDetail() {
|
|||||||
gap: 6px;
|
gap: 6px;
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
background: #141414;
|
background:
|
||||||
|
linear-gradient(rgba(22, 20, 15, 0.74), rgba(18, 16, 12, 0.84)),
|
||||||
|
url('../assets/images/generated/detail-ledger-ticket-bg-v1.webp') center / cover no-repeat;
|
||||||
border: 1px solid #222;
|
border: 1px solid #222;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero.pos {
|
.hero.pos {
|
||||||
border-color: rgba(212, 175, 55, 0.25);
|
border-color: rgba(212, 175, 55, 0.25);
|
||||||
background: linear-gradient(135deg, rgba(212, 175, 55, 0.1), rgba(212, 175, 55, 0.03));
|
background:
|
||||||
|
linear-gradient(135deg, rgba(212, 175, 55, 0.14), rgba(20, 16, 8, 0.76)),
|
||||||
|
url('../assets/images/generated/detail-ledger-ticket-bg-v1.webp') center / cover no-repeat;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero.neg {
|
.hero.neg {
|
||||||
border-color: rgba(224, 80, 80, 0.2);
|
border-color: rgba(224, 80, 80, 0.2);
|
||||||
background: linear-gradient(135deg, rgba(224, 80, 80, 0.1), rgba(224, 80, 80, 0.03));
|
background:
|
||||||
|
linear-gradient(135deg, rgba(224, 80, 80, 0.1), rgba(20, 12, 10, 0.78)),
|
||||||
|
url('../assets/images/generated/detail-ledger-ticket-bg-v1.webp') center / cover no-repeat;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero.zero {
|
.hero.zero {
|
||||||
border-color: rgba(255, 255, 255, 0.08);
|
border-color: rgba(255, 255, 255, 0.08);
|
||||||
background: #141414;
|
background:
|
||||||
|
linear-gradient(rgba(22, 20, 15, 0.76), rgba(18, 16, 12, 0.84)),
|
||||||
|
url('../assets/images/generated/detail-ledger-ticket-bg-v1.webp') center / cover no-repeat;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-type {
|
.hero-type {
|
||||||
@@ -314,13 +322,22 @@ function goCashbackDetail() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.section {
|
.section {
|
||||||
background: #141414;
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
background:
|
||||||
|
linear-gradient(rgba(22, 20, 15, 0.78), rgba(18, 16, 12, 0.86)),
|
||||||
|
url('../assets/images/generated/detail-ledger-ticket-bg-v1.webp') center / cover no-repeat;
|
||||||
border: 1px solid #222;
|
border: 1px solid #222;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
padding: 14px 16px;
|
padding: 14px 16px;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.section > * {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
.section-title {
|
.section-title {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
|
|||||||
@@ -228,12 +228,21 @@ function legResultClass(status?: string) {
|
|||||||
.detail-right { display: flex; flex-direction: column; gap: 16px; }
|
.detail-right { display: flex; flex-direction: column; gap: 16px; }
|
||||||
|
|
||||||
.detail-card {
|
.detail-card {
|
||||||
background: var(--desktop-sidebar-bg);
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
background:
|
||||||
|
linear-gradient(rgba(22, 20, 15, 0.76), rgba(18, 16, 12, 0.82)),
|
||||||
|
url('../../assets/images/generated/detail-ledger-ticket-bg-v1.webp') center / cover no-repeat;
|
||||||
border: 1px solid var(--desktop-border);
|
border: 1px solid var(--desktop-border);
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.detail-card > * {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
.card-title { font-size: 11px; font-weight: 700; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.06em; margin-bottom: 14px; padding-bottom: 10px; border-bottom: 1px solid var(--desktop-border); }
|
.card-title { font-size: 11px; font-weight: 700; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.06em; margin-bottom: 14px; padding-bottom: 10px; border-bottom: 1px solid var(--desktop-border); }
|
||||||
|
|
||||||
/* Selection rows */
|
/* Selection rows */
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { useDesktopParlayMatches, type DesktopParlayMatch } from '../../composab
|
|||||||
import { useOutrightEvents } from '../../composables/useOutrightEvents';
|
import { useOutrightEvents } from '../../composables/useOutrightEvents';
|
||||||
import MatchBetCard from '../../components/MatchBetCard.vue';
|
import MatchBetCard from '../../components/MatchBetCard.vue';
|
||||||
import DesktopOutrightEventCard from '../../components/desktop/DesktopOutrightEventCard.vue';
|
import DesktopOutrightEventCard from '../../components/desktop/DesktopOutrightEventCard.vue';
|
||||||
|
import emptyMatchesImg from '../../assets/images/generated/empty-matches-stadium-v1.webp';
|
||||||
import {
|
import {
|
||||||
isAfterLocalTodayMatchWindow as isAfterTodayMatchWindow,
|
isAfterLocalTodayMatchWindow as isAfterTodayMatchWindow,
|
||||||
isInLocalTodayMatchWindow as isInTodayMatchWindow,
|
isInLocalTodayMatchWindow as isInTodayMatchWindow,
|
||||||
@@ -159,7 +160,7 @@ function closeModal() {
|
|||||||
|
|
||||||
async function refresh() {
|
async function refresh() {
|
||||||
if (mainTab.value === 'outright') {
|
if (mainTab.value === 'outright') {
|
||||||
await loadOutrights({ silent: false });
|
await loadOutrights({ silent: false, force: true });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await loadParlayMatches(true);
|
await loadParlayMatches(true);
|
||||||
@@ -224,6 +225,7 @@ void loadParlayMatches(true);
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<div v-else class="empty-state">
|
<div v-else class="empty-state">
|
||||||
|
<img :src="emptyMatchesImg" alt="" class="empty-state-art" />
|
||||||
<p>{{ t('bet.no_matches') }}</p>
|
<p>{{ t('bet.no_matches') }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -254,6 +256,7 @@ void loadParlayMatches(true);
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<div v-else class="empty-state">
|
<div v-else class="empty-state">
|
||||||
|
<img :src="emptyMatchesImg" alt="" class="empty-state-art" />
|
||||||
<p>{{ outrightError || t('bet.no_outright') }}</p>
|
<p>{{ outrightError || t('bet.no_outright') }}</p>
|
||||||
<p v-if="!outrightError" class="empty-hint">{{ t('bet.no_outright_hint') }}</p>
|
<p v-if="!outrightError" class="empty-hint">{{ t('bet.no_outright_hint') }}</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -438,12 +441,31 @@ void loadParlayMatches(true);
|
|||||||
}
|
}
|
||||||
|
|
||||||
.empty-state {
|
.empty-state {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 40px 16px;
|
padding: 40px 16px;
|
||||||
color: var(--text-muted);
|
color: var(--text-muted);
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.empty-state-art {
|
||||||
|
width: min(460px, 70%);
|
||||||
|
aspect-ratio: 16 / 9;
|
||||||
|
height: auto;
|
||||||
|
border-radius: 8px;
|
||||||
|
object-fit: cover;
|
||||||
|
opacity: 0.72;
|
||||||
|
mask-image: linear-gradient(90deg, transparent 0, #000 10%, #000 90%, transparent 100%);
|
||||||
|
-webkit-mask-image: linear-gradient(90deg, transparent 0, #000 10%, #000 90%, transparent 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-state p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.empty-hint {
|
.empty-hint {
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
@@ -459,7 +481,8 @@ void loadParlayMatches(true);
|
|||||||
|
|
||||||
.outright-event-grid {
|
.outright-event-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
|
grid-template-columns: repeat(auto-fill, minmax(340px, 420px));
|
||||||
|
justify-content: start;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ import AnnouncementMarquee from '../../components/AnnouncementMarquee.vue';
|
|||||||
import { usePlayerHome } from '../../composables/usePlayerHome';
|
import { usePlayerHome } from '../../composables/usePlayerHome';
|
||||||
import TeamEmblem from '../../components/TeamEmblem.vue';
|
import TeamEmblem from '../../components/TeamEmblem.vue';
|
||||||
import GoldSpinner from '../../components/GoldSpinner.vue';
|
import GoldSpinner from '../../components/GoldSpinner.vue';
|
||||||
|
import emptyMatchesImg from '../../assets/images/generated/empty-matches-stadium-v1.webp';
|
||||||
|
import vsImg from '../../assets/images/generated/vs-gold-alpha-v1.webp';
|
||||||
import { formatLocalMatchDateTime } from '@thebet365/shared';
|
import { formatLocalMatchDateTime } from '@thebet365/shared';
|
||||||
import type { PlayerHomeMatch } from '../../composables/usePlayerHome';
|
import type { PlayerHomeMatch } from '../../composables/usePlayerHome';
|
||||||
import { useDesktopBetPopover } from '../../composables/useDesktopBetPopover';
|
import { useDesktopBetPopover } from '../../composables/useDesktopBetPopover';
|
||||||
@@ -226,7 +228,9 @@ function getHoveredSideForMatch(match: PlayerHomeMatch | null, cardRootId: strin
|
|||||||
/>
|
/>
|
||||||
<span class="featured-team-name">{{ featuredMatch.homeTeamName }}</span>
|
<span class="featured-team-name">{{ featuredMatch.homeTeamName }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="featured-vs vs-heartbeat">VS</div>
|
<div class="featured-vs vs-heartbeat">
|
||||||
|
<img :src="vsImg" alt="VS" class="featured-vs-img" />
|
||||||
|
</div>
|
||||||
<div class="featured-team">
|
<div class="featured-team">
|
||||||
<TeamEmblem
|
<TeamEmblem
|
||||||
size="lg"
|
size="lg"
|
||||||
@@ -293,7 +297,9 @@ function getHoveredSideForMatch(match: PlayerHomeMatch | null, cardRootId: strin
|
|||||||
/>
|
/>
|
||||||
<span class="team-name">{{ match.homeTeamName }}</span>
|
<span class="team-name">{{ match.homeTeamName }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="vs-text">VS</div>
|
<div class="vs-text">
|
||||||
|
<img :src="vsImg" alt="VS" class="vs-mini-img" />
|
||||||
|
</div>
|
||||||
<div class="team-row">
|
<div class="team-row">
|
||||||
<TeamEmblem
|
<TeamEmblem
|
||||||
size="sm"
|
size="sm"
|
||||||
@@ -317,7 +323,9 @@ function getHoveredSideForMatch(match: PlayerHomeMatch | null, cardRootId: strin
|
|||||||
/>
|
/>
|
||||||
<span class="hover-team-name">{{ match.homeTeamName }}</span>
|
<span class="hover-team-name">{{ match.homeTeamName }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="hover-vs-glow">VS</div>
|
<div class="hover-vs-glow">
|
||||||
|
<img :src="vsImg" alt="VS" class="hover-vs-img" />
|
||||||
|
</div>
|
||||||
<div class="hover-team away-slide">
|
<div class="hover-team away-slide">
|
||||||
<TeamEmblem
|
<TeamEmblem
|
||||||
size="md"
|
size="md"
|
||||||
@@ -364,6 +372,7 @@ function getHoveredSideForMatch(match: PlayerHomeMatch | null, cardRootId: strin
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<div v-else class="empty-state">
|
<div v-else class="empty-state">
|
||||||
|
<img :src="emptyMatchesImg" alt="" class="empty-state-art" />
|
||||||
<p>{{ t('home.no_matches') }}</p>
|
<p>{{ t('home.no_matches') }}</p>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -405,7 +414,9 @@ function getHoveredSideForMatch(match: PlayerHomeMatch | null, cardRootId: strin
|
|||||||
/>
|
/>
|
||||||
<span class="team-name">{{ match.homeTeamName }}</span>
|
<span class="team-name">{{ match.homeTeamName }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="vs-text">VS</div>
|
<div class="vs-text">
|
||||||
|
<img :src="vsImg" alt="VS" class="vs-mini-img" />
|
||||||
|
</div>
|
||||||
<div class="team-row">
|
<div class="team-row">
|
||||||
<TeamEmblem
|
<TeamEmblem
|
||||||
size="sm"
|
size="sm"
|
||||||
@@ -429,7 +440,9 @@ function getHoveredSideForMatch(match: PlayerHomeMatch | null, cardRootId: strin
|
|||||||
/>
|
/>
|
||||||
<span class="hover-team-name">{{ match.homeTeamName }}</span>
|
<span class="hover-team-name">{{ match.homeTeamName }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="hover-vs-glow">VS</div>
|
<div class="hover-vs-glow">
|
||||||
|
<img :src="vsImg" alt="VS" class="hover-vs-img" />
|
||||||
|
</div>
|
||||||
<div class="hover-team away-slide">
|
<div class="hover-team away-slide">
|
||||||
<TeamEmblem
|
<TeamEmblem
|
||||||
size="md"
|
size="md"
|
||||||
@@ -474,6 +487,7 @@ function getHoveredSideForMatch(match: PlayerHomeMatch | null, cardRootId: strin
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="!loading" class="empty-state">
|
<div v-else-if="!loading" class="empty-state">
|
||||||
|
<img :src="emptyMatchesImg" alt="" class="empty-state-art" />
|
||||||
<p>{{ t('home.upcoming_empty') }}</p>
|
<p>{{ t('home.upcoming_empty') }}</p>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -505,7 +519,9 @@ function getHoveredSideForMatch(match: PlayerHomeMatch | null, cardRootId: strin
|
|||||||
</div>
|
</div>
|
||||||
<div class="sri-teams">
|
<div class="sri-teams">
|
||||||
<span>{{ m.homeTeamName }}</span>
|
<span>{{ m.homeTeamName }}</span>
|
||||||
<span class="sri-vs">vs</span>
|
<span class="sri-vs">
|
||||||
|
<img :src="vsImg" alt="VS" class="sri-vs-img" />
|
||||||
|
</span>
|
||||||
<span>{{ m.awayTeamName }}</span>
|
<span>{{ m.awayTeamName }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -520,7 +536,9 @@ function getHoveredSideForMatch(match: PlayerHomeMatch | null, cardRootId: strin
|
|||||||
<TeamEmblem size="md" :team-code="m.homeTeamCode" :team-name="m.homeTeamName" :logo-url="m.homeTeamLogoUrl" />
|
<TeamEmblem size="md" :team-code="m.homeTeamCode" :team-name="m.homeTeamName" :logo-url="m.homeTeamLogoUrl" />
|
||||||
<span>{{ m.homeTeamName }}</span>
|
<span>{{ m.homeTeamName }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="sri-preview-vs-text">VS</div>
|
<div class="sri-preview-vs-text">
|
||||||
|
<img :src="vsImg" alt="VS" class="sri-preview-vs-img" />
|
||||||
|
</div>
|
||||||
<div class="sri-preview-team away-team">
|
<div class="sri-preview-team away-team">
|
||||||
<TeamEmblem size="md" :team-code="m.awayTeamCode" :team-name="m.awayTeamName" :logo-url="m.awayTeamLogoUrl" />
|
<TeamEmblem size="md" :team-code="m.awayTeamCode" :team-name="m.awayTeamName" :logo-url="m.awayTeamLogoUrl" />
|
||||||
<span>{{ m.awayTeamName }}</span>
|
<span>{{ m.awayTeamName }}</span>
|
||||||
@@ -623,7 +641,7 @@ function getHoveredSideForMatch(match: PlayerHomeMatch | null, cardRootId: strin
|
|||||||
}
|
}
|
||||||
|
|
||||||
.content-section {
|
.content-section {
|
||||||
background: rgba(20, 20, 20, 0.88);
|
background: rgba(32, 30, 24, 0.78);
|
||||||
backdrop-filter: var(--blur-md);
|
backdrop-filter: var(--blur-md);
|
||||||
-webkit-backdrop-filter: var(--blur-md);
|
-webkit-backdrop-filter: var(--blur-md);
|
||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
@@ -685,22 +703,39 @@ function getHoveredSideForMatch(match: PlayerHomeMatch | null, cardRootId: strin
|
|||||||
.loading-state,
|
.loading-state,
|
||||||
.empty-state {
|
.empty-state {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
min-height: 160px;
|
min-height: 160px;
|
||||||
color: var(--text-muted);
|
color: var(--text-muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.empty-state-art {
|
||||||
|
width: min(420px, 72%);
|
||||||
|
aspect-ratio: 16 / 9;
|
||||||
|
height: auto;
|
||||||
|
border-radius: 8px;
|
||||||
|
object-fit: cover;
|
||||||
|
opacity: 0.72;
|
||||||
|
mask-image: linear-gradient(90deg, transparent 0, #000 10%, #000 90%, transparent 100%);
|
||||||
|
-webkit-mask-image: linear-gradient(90deg, transparent 0, #000 10%, #000 90%, transparent 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-state p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Featured 焦点大卡 */
|
/* Featured 焦点大卡 */
|
||||||
.featured-match {
|
.featured-match {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: var(--space-4);
|
gap: var(--space-4);
|
||||||
padding: 18px 20px;
|
padding: 18px 20px 20px;
|
||||||
border-radius: var(--radius-lg);
|
border-radius: var(--radius-lg);
|
||||||
background:
|
background:
|
||||||
linear-gradient(135deg, rgba(0, 0, 0, 0.08), rgba(0, 0, 0, 0.04) 50%, rgba(15, 10, 0, 0.1)),
|
linear-gradient(90deg, rgba(0, 0, 0, 0.34), rgba(0, 0, 0, 0.12) 50%, rgba(10, 6, 0, 0.36)),
|
||||||
url('../../assets/images/card-bg.webp') center/cover no-repeat;
|
url('../../assets/images/generated/pc-featured-match-bg-v1.webp') center / 100% 100% no-repeat;
|
||||||
border: 1px solid var(--border-gold);
|
border: 1px solid var(--border-gold);
|
||||||
box-shadow: var(--shadow-gold-lg), inset 0 0 20px rgba(212, 175, 55, 0.06);
|
box-shadow: var(--shadow-gold-lg), inset 0 0 20px rgba(212, 175, 55, 0.06);
|
||||||
margin-bottom: var(--space-4);
|
margin-bottom: var(--space-4);
|
||||||
@@ -711,6 +746,11 @@ function getHoveredSideForMatch(match: PlayerHomeMatch | null, cardRootId: strin
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.featured-match > * {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
.featured-match::before {
|
.featured-match::before {
|
||||||
content: '';
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@@ -718,10 +758,30 @@ function getHoveredSideForMatch(match: PlayerHomeMatch | null, cardRootId: strin
|
|||||||
width: 180px; height: 180px;
|
width: 180px; height: 180px;
|
||||||
background: radial-gradient(circle at top right, rgba(212, 175, 55, 0.2), transparent 60%);
|
background: radial-gradient(circle at top right, rgba(212, 175, 55, 0.2), transparent 60%);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
z-index: 0;
|
||||||
animation: goldGlowPulse 3.5s ease-in-out infinite;
|
animation: goldGlowPulse 3.5s ease-in-out infinite;
|
||||||
transform-origin: top right;
|
transform-origin: top right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.featured-match::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
z-index: 2;
|
||||||
|
pointer-events: none;
|
||||||
|
background: url('../../assets/images/generated/pc-featured-match-bg-v1.webp') center / 100% 100% no-repeat;
|
||||||
|
mask:
|
||||||
|
linear-gradient(#000 0 0) top / 100% 22px no-repeat,
|
||||||
|
linear-gradient(#000 0 0) bottom / 100% 22px no-repeat,
|
||||||
|
linear-gradient(#000 0 0) left / 22px 100% no-repeat,
|
||||||
|
linear-gradient(#000 0 0) right / 22px 100% no-repeat;
|
||||||
|
-webkit-mask:
|
||||||
|
linear-gradient(#000 0 0) top / 100% 22px no-repeat,
|
||||||
|
linear-gradient(#000 0 0) bottom / 100% 22px no-repeat,
|
||||||
|
linear-gradient(#000 0 0) left / 22px 100% no-repeat,
|
||||||
|
linear-gradient(#000 0 0) right / 22px 100% no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
.featured-match:hover {
|
.featured-match:hover {
|
||||||
transform: translateY(-2px);
|
transform: translateY(-2px);
|
||||||
box-shadow: var(--glow-gold-lg), inset 0 0 24px rgba(212, 175, 55, 0.08);
|
box-shadow: var(--glow-gold-lg), inset 0 0 24px rgba(212, 175, 55, 0.08);
|
||||||
@@ -786,22 +846,35 @@ function getHoveredSideForMatch(match: PlayerHomeMatch | null, cardRootId: strin
|
|||||||
}
|
}
|
||||||
|
|
||||||
.featured-vs {
|
.featured-vs {
|
||||||
font-family: var(--font-display);
|
width: 72px;
|
||||||
font-size: var(--text-2xl);
|
height: 48px;
|
||||||
font-weight: 400;
|
display: flex;
|
||||||
font-style: italic;
|
align-items: center;
|
||||||
color: var(--primary-light);
|
justify-content: center;
|
||||||
text-shadow: 0 0 12px rgba(212, 175, 55, 0.5);
|
}
|
||||||
|
|
||||||
|
.featured-vs-img {
|
||||||
|
width: 68px;
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
object-fit: contain;
|
||||||
|
filter:
|
||||||
|
drop-shadow(0 0 4px rgba(255, 231, 150, 0.42))
|
||||||
|
drop-shadow(0 0 8px rgba(212, 175, 55, 0.26));
|
||||||
}
|
}
|
||||||
|
|
||||||
.featured-markets {
|
.featured-markets {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(3, 1fr);
|
grid-template-columns: repeat(3, 1fr);
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
margin: 14px -20px -18px;
|
margin: 14px -12px 0;
|
||||||
padding: 14px 20px 18px;
|
padding: 14px 12px 8px;
|
||||||
background: #000000;
|
background: rgba(10, 8, 4, 0.46);
|
||||||
border-top: 1px solid rgba(212, 175, 55, 0.2);
|
border-top: 1px solid rgba(246, 210, 108, 0.22);
|
||||||
|
border-radius: 0 0 8px 8px;
|
||||||
|
box-shadow: inset 0 1px 0 rgba(255, 236, 174, 0.08);
|
||||||
|
backdrop-filter: blur(4px);
|
||||||
|
-webkit-backdrop-filter: blur(4px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.featured-market-block {
|
.featured-market-block {
|
||||||
@@ -947,15 +1020,20 @@ function getHoveredSideForMatch(match: PlayerHomeMatch | null, cardRootId: strin
|
|||||||
}
|
}
|
||||||
|
|
||||||
.vs-text {
|
.vs-text {
|
||||||
font-size: 10px;
|
display: flex;
|
||||||
font-weight: 800;
|
align-items: center;
|
||||||
color: var(--text-muted);
|
|
||||||
font-style: italic;
|
|
||||||
padding-left: 36px;
|
padding-left: 36px;
|
||||||
line-height: 1;
|
|
||||||
margin: -2px 0;
|
margin: -2px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.vs-mini-img {
|
||||||
|
width: 30px;
|
||||||
|
height: auto;
|
||||||
|
object-fit: contain;
|
||||||
|
opacity: 0.78;
|
||||||
|
filter: drop-shadow(0 1px 3px rgba(0, 0, 0, 0.75));
|
||||||
|
}
|
||||||
|
|
||||||
.team-row {
|
.team-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -1124,10 +1202,17 @@ function getHoveredSideForMatch(match: PlayerHomeMatch | null, cardRootId: strin
|
|||||||
}
|
}
|
||||||
|
|
||||||
.sri-vs {
|
.sri-vs {
|
||||||
color: var(--text-muted);
|
display: inline-flex;
|
||||||
font-size: 9px;
|
align-items: center;
|
||||||
font-weight: 600;
|
flex-shrink: 0;
|
||||||
font-style: italic;
|
}
|
||||||
|
|
||||||
|
.sri-vs-img {
|
||||||
|
width: 22px;
|
||||||
|
height: auto;
|
||||||
|
object-fit: contain;
|
||||||
|
opacity: 0.7;
|
||||||
|
filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.7));
|
||||||
}
|
}
|
||||||
|
|
||||||
.sri-time {
|
.sri-time {
|
||||||
@@ -1309,19 +1394,26 @@ function getHoveredSideForMatch(match: PlayerHomeMatch | null, cardRootId: strin
|
|||||||
}
|
}
|
||||||
|
|
||||||
.hover-vs-glow {
|
.hover-vs-glow {
|
||||||
font-size: 18px;
|
width: 58px;
|
||||||
font-weight: 900;
|
height: 38px;
|
||||||
font-style: italic;
|
display: flex;
|
||||||
color: var(--primary-light);
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
transform: scale(2.8);
|
transform: scale(2.8);
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
text-shadow:
|
|
||||||
0 0 10px rgba(212, 175, 55, 0.8),
|
|
||||||
0 0 20px rgba(212, 175, 55, 0.4);
|
|
||||||
transition: transform 0.35s cubic-bezier(0.175, 0.885, 0.32, 1.275) 0.1s, opacity 0.3s ease 0.1s;
|
transition: transform 0.35s cubic-bezier(0.175, 0.885, 0.32, 1.275) 0.1s, opacity 0.3s ease 0.1s;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.hover-vs-img {
|
||||||
|
width: 56px;
|
||||||
|
height: auto;
|
||||||
|
object-fit: contain;
|
||||||
|
filter:
|
||||||
|
drop-shadow(0 0 5px rgba(255, 231, 150, 0.52))
|
||||||
|
drop-shadow(0 0 9px rgba(212, 175, 55, 0.34));
|
||||||
|
}
|
||||||
|
|
||||||
.match-card:is(:hover, .match-card--engaged) .hover-vs-glow {
|
.match-card:is(:hover, .match-card--engaged) .hover-vs-glow {
|
||||||
transform: scale(1);
|
transform: scale(1);
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
@@ -1330,11 +1422,9 @@ function getHoveredSideForMatch(match: PlayerHomeMatch | null, cardRootId: strin
|
|||||||
|
|
||||||
@keyframes vs-clash-impact {
|
@keyframes vs-clash-impact {
|
||||||
0% {
|
0% {
|
||||||
text-shadow: 0 0 25px rgba(212, 175, 55, 1);
|
|
||||||
transform: scale(1.25);
|
transform: scale(1.25);
|
||||||
}
|
}
|
||||||
100% {
|
100% {
|
||||||
text-shadow: 0 0 8px rgba(212, 175, 55, 0.7);
|
|
||||||
transform: scale(1);
|
transform: scale(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1471,17 +1561,26 @@ function getHoveredSideForMatch(match: PlayerHomeMatch | null, cardRootId: strin
|
|||||||
}
|
}
|
||||||
|
|
||||||
.sri-preview-vs-text {
|
.sri-preview-vs-text {
|
||||||
font-size: 16px;
|
width: 48px;
|
||||||
font-weight: 900;
|
height: 32px;
|
||||||
font-style: italic;
|
display: flex;
|
||||||
color: var(--primary-light);
|
align-items: center;
|
||||||
text-shadow: 0 0 8px rgba(212, 175, 55, 0.6);
|
justify-content: center;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: scale(2.2);
|
transform: scale(2.2);
|
||||||
transition: opacity 0.3s ease 0.1s, transform 0.35s cubic-bezier(0.175, 0.885, 0.32, 1.275) 0.1s;
|
transition: opacity 0.3s ease 0.1s, transform 0.35s cubic-bezier(0.175, 0.885, 0.32, 1.275) 0.1s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sri-preview-vs-img {
|
||||||
|
width: 46px;
|
||||||
|
height: auto;
|
||||||
|
object-fit: contain;
|
||||||
|
filter:
|
||||||
|
drop-shadow(0 0 4px rgba(255, 231, 150, 0.42))
|
||||||
|
drop-shadow(0 0 8px rgba(212, 175, 55, 0.26));
|
||||||
|
}
|
||||||
|
|
||||||
.side-recommend-item:hover .sri-preview-vs-text {
|
.side-recommend-item:hover .sri-preview-vs-text {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: scale(1);
|
transform: scale(1);
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import { formatLocalMatchDateTime, defaultMarketName, DETAIL_MARKET_TYPES } from
|
|||||||
import { resolveSelectionLabel } from '../../utils/selectionLabel';
|
import { resolveSelectionLabel } from '../../utils/selectionLabel';
|
||||||
import { useDesktopBetPopover } from '../../composables/useDesktopBetPopover';
|
import { useDesktopBetPopover } from '../../composables/useDesktopBetPopover';
|
||||||
import { useDesktopBetLocate, scrollToBetSelection } from '../../composables/useDesktopBetLocate';
|
import { useDesktopBetLocate, scrollToBetSelection } from '../../composables/useDesktopBetLocate';
|
||||||
|
import vsImg from '../../assets/images/generated/vs-gold-alpha-v1.webp';
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -360,7 +361,9 @@ function getHoveredSide() {
|
|||||||
<span class="divider">-</span>
|
<span class="divider">-</span>
|
||||||
<span class="score">{{ match.score?.ftAway }}</span>
|
<span class="score">{{ match.score?.ftAway }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="versus-row vs" v-else>VS</div>
|
<div class="versus-row vs" v-else>
|
||||||
|
<img :src="vsImg" alt="VS" class="score-vs-img" />
|
||||||
|
</div>
|
||||||
<span class="kickoff-time">{{ kickoff }}</span>
|
<span class="kickoff-time">{{ kickoff }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -537,13 +540,15 @@ function getHoveredSide() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.match-score-band {
|
.match-score-band {
|
||||||
background:
|
aspect-ratio: 1600 / 320;
|
||||||
linear-gradient(135deg, rgba(0, 0, 0, 0.08), rgba(0, 0, 0, 0.04) 50%, rgba(15, 10, 0, 0.1)),
|
background-image: url('../../assets/images/generated/pc-featured-match-bg-v1.webp');
|
||||||
url('../../assets/images/card-bg.webp') center/cover no-repeat;
|
background-position: center;
|
||||||
border: 1px solid var(--border-gold);
|
background-repeat: no-repeat;
|
||||||
box-shadow: var(--shadow-gold), inset 0 0 20px rgba(212, 175, 55, 0.06);
|
background-size: 100% 100%;
|
||||||
border-radius: 12px;
|
border: 0;
|
||||||
padding: 18px 24px;
|
box-shadow: var(--shadow-gold);
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 12px 24px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -595,9 +600,17 @@ function getHoveredSide() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.versus-row.vs {
|
.versus-row.vs {
|
||||||
font-size: 22px;
|
min-height: 42px;
|
||||||
font-weight: 800;
|
justify-content: center;
|
||||||
color: var(--text-muted);
|
}
|
||||||
|
|
||||||
|
.score-vs-img {
|
||||||
|
width: 72px;
|
||||||
|
height: auto;
|
||||||
|
object-fit: contain;
|
||||||
|
filter:
|
||||||
|
drop-shadow(0 0 4px rgba(255, 231, 150, 0.42))
|
||||||
|
drop-shadow(0 0 8px rgba(212, 175, 55, 0.26));
|
||||||
}
|
}
|
||||||
|
|
||||||
.kickoff-time {
|
.kickoff-time {
|
||||||
|
|||||||
@@ -8,11 +8,11 @@ import OutrightOptionCard from '../../components/outright/OutrightOptionCard.vue
|
|||||||
import OutrightBetModal, { type OutrightPick } from '../../components/outright/OutrightBetModal.vue';
|
import OutrightBetModal, { type OutrightPick } from '../../components/outright/OutrightBetModal.vue';
|
||||||
import { useAuthStore } from '../../stores/auth';
|
import { useAuthStore } from '../../stores/auth';
|
||||||
import GoldSpinner from '../../components/GoldSpinner.vue';
|
import GoldSpinner from '../../components/GoldSpinner.vue';
|
||||||
import saishiImg from '../../assets/images/saishi.webp';
|
import saishiImg from '../../assets/images/generated/saishi-gold-trophy-v1.webp';
|
||||||
import cardBg from '../../assets/images/card-bg.webp';
|
import outrightDetailBg from '../../assets/images/generated/pc-outright-detail-bg-v1.webp';
|
||||||
import { useDesktopBetLocate, scrollToBetSelection } from '../../composables/useDesktopBetLocate';
|
import { useDesktopBetLocate, scrollToBetSelection } from '../../composables/useDesktopBetLocate';
|
||||||
|
|
||||||
const matchCardBg = `url(${cardBg})`;
|
const matchCardBg = `url(${outrightDetailBg})`;
|
||||||
const ODDS_POLL_MS = 15000;
|
const ODDS_POLL_MS = 15000;
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
@@ -246,7 +246,7 @@ onUnmounted(stopPolling);
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
background: v-bind(matchCardBg) center / cover no-repeat;
|
background: v-bind(matchCardBg) center / cover no-repeat;
|
||||||
opacity: 0.22;
|
opacity: 0.36;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { useAppLocale } from '../../composables/useAppLocale';
|
|||||||
import { usePlayerProfile } from '../../composables/usePlayerProfile';
|
import { usePlayerProfile } from '../../composables/usePlayerProfile';
|
||||||
import { formatMoney } from '../../utils/localeDisplay';
|
import { formatMoney } from '../../utils/localeDisplay';
|
||||||
import { parseCashbackApiData, sumCashbackAmount } from '../../utils/cashback';
|
import { parseCashbackApiData, sumCashbackAmount } from '../../utils/cashback';
|
||||||
import walletBg from '../../assets/images/wallet-bg.webp';
|
import walletBg from '../../assets/images/generated/pc-wallet-banner-v1.webp';
|
||||||
|
|
||||||
const { t, locale } = useI18n();
|
const { t, locale } = useI18n();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -223,6 +223,12 @@ const quickLinks = computed(() => [
|
|||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
height: auto;
|
height: auto;
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
scrollbar-width: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-page::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-title {
|
.page-title {
|
||||||
@@ -306,8 +312,8 @@ const quickLinks = computed(() => [
|
|||||||
display: block;
|
display: block;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
object-position: center center;
|
object-position: center center;
|
||||||
transform: scale(1.05);
|
transform: scale(1.01);
|
||||||
filter: brightness(0.86);
|
filter: brightness(0.94);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -292,12 +292,21 @@ function auditNoteDisplayText(remark: { kind: 'note'; text: string }) {
|
|||||||
.detail-layout { display: flex; flex-direction: column; gap: 16px; max-width: 680px; }
|
.detail-layout { display: flex; flex-direction: column; gap: 16px; max-width: 680px; }
|
||||||
|
|
||||||
.detail-card {
|
.detail-card {
|
||||||
background: var(--desktop-sidebar-bg);
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
background:
|
||||||
|
linear-gradient(rgba(22, 20, 15, 0.76), rgba(18, 16, 12, 0.82)),
|
||||||
|
url('../../assets/images/generated/detail-ledger-ticket-bg-v1.webp') center / cover no-repeat;
|
||||||
border: 1px solid var(--desktop-border);
|
border: 1px solid var(--desktop-border);
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.detail-card > * {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
.header-card { display: flex; flex-direction: column; gap: 12px; }
|
.header-card { display: flex; flex-direction: column; gap: 12px; }
|
||||||
|
|
||||||
.order-no {
|
.order-no {
|
||||||
|
|||||||
@@ -166,12 +166,21 @@ function txLabel(tx: TxDetail): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.detail-card {
|
.detail-card {
|
||||||
background: var(--desktop-sidebar-bg);
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
background:
|
||||||
|
linear-gradient(rgba(22, 20, 15, 0.76), rgba(18, 16, 12, 0.82)),
|
||||||
|
url('../../assets/images/generated/detail-ledger-ticket-bg-v1.webp') center / cover no-repeat;
|
||||||
border: 1px solid var(--desktop-border);
|
border: 1px solid var(--desktop-border);
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
padding: 28px;
|
padding: 28px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.detail-card > * {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Hero card (left) */
|
/* Hero card (left) */
|
||||||
.hero-card {
|
.hero-card {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||