style(ui): 全站 Memphis 换肤为玻璃拟态+极光渐变
设计 token 与中央类名保持不变,重写视觉:磨砂玻璃卡片、 紫→青渐变按钮、柔光阴影、发丝边框;emoji 图标换 SVG; 登录/支付/公告弹窗改为随主题的玻璃卡片。 Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
@@ -13,22 +13,24 @@ const html = computed(() => marked.parse(announcement.content.trim() || '暂无
|
|||||||
<div v-if="announcement.show"
|
<div v-if="announcement.show"
|
||||||
class="fixed inset-0 z-[80] bg-slate-950/70 backdrop-blur-sm flex items-center justify-center p-4"
|
class="fixed inset-0 z-[80] bg-slate-950/70 backdrop-blur-sm flex items-center justify-center p-4"
|
||||||
@click.self="dismissAnnouncement">
|
@click.self="dismissAnnouncement">
|
||||||
<div class="w-full max-w-lg rounded-xl bg-white text-slate-800 border-[3px] border-[#111] shadow-[8px_8px_0_#111] overflow-hidden flex flex-col max-h-[80vh]">
|
<div class="w-full max-w-lg rounded-2xl bg-[var(--menu-bg)] backdrop-blur-xl text-[color:var(--fg)] border border-[color:var(--glass-border)] shadow-[var(--glass-shadow-lg)] overflow-hidden flex flex-col max-h-[80vh]">
|
||||||
<div class="px-6 py-4 border-b-[2.5px] border-b-[#111] flex items-center justify-between gap-3 shrink-0">
|
<div class="px-6 py-4 border-b border-b-[color:var(--ink-soft)] flex items-center justify-between gap-3 shrink-0">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<span class="w-7 h-7 rounded-lg bg-[#fef08a] text-[#111] border-2 border-[#111] grid place-items-center">
|
<span class="w-7 h-7 rounded-lg text-white grid place-items-center"
|
||||||
|
style="background: linear-gradient(135deg, #7c5cfc, #22d3ee); box-shadow: 0 4px 12px var(--accent-glow)">
|
||||||
<Icon name="spark" class="w-4 h-4" />
|
<Icon name="spark" class="w-4 h-4" />
|
||||||
</span>
|
</span>
|
||||||
<h2 class="text-base font-extrabold">公告</h2>
|
<h2 class="text-base font-extrabold">公告</h2>
|
||||||
</div>
|
</div>
|
||||||
<button @click="dismissAnnouncement" class="text-slate-400 hover:text-slate-700 transition-colors">
|
<button @click="dismissAnnouncement" class="text-[color:var(--fg-3)] hover:text-[color:var(--fg)] transition-colors">
|
||||||
<Icon name="close" class="w-5 h-5" />
|
<Icon name="close" class="w-5 h-5" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="ann-body px-6 py-5 overflow-y-auto" v-html="html"></div>
|
<div class="ann-body px-6 py-5 overflow-y-auto" v-html="html"></div>
|
||||||
<div class="px-6 py-4 border-t-[2.5px] border-t-[#111] flex justify-end shrink-0">
|
<div class="px-6 py-4 border-t border-t-[color:var(--ink-soft)] flex justify-end shrink-0">
|
||||||
<button @click="dismissAnnouncement"
|
<button @click="dismissAnnouncement"
|
||||||
class="rounded-lg bg-[#ec5b13] text-white border-[2.5px] border-[#111] shadow-[3px_3px_0_#111] hover:-translate-x-0.5 hover:-translate-y-0.5 hover:shadow-[4px_4px_0_#111] active:translate-y-0.5 active:shadow-none px-5 py-2 text-sm font-extrabold transition-all">
|
class="rounded-lg text-white border border-white/20 px-5 py-2 text-sm font-extrabold hover:-translate-y-0.5 active:translate-y-0.5 transition-all"
|
||||||
|
style="background: linear-gradient(120deg, #7c5cfc, #22d3ee); box-shadow: 0 8px 20px var(--accent-glow)">
|
||||||
我知道了
|
我知道了
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -42,21 +44,21 @@ const html = computed(() => marked.parse(announcement.content.trim() || '暂无
|
|||||||
.ann-fade-enter-from, .ann-fade-leave-to { opacity: 0; }
|
.ann-fade-enter-from, .ann-fade-leave-to { opacity: 0; }
|
||||||
|
|
||||||
/* Minimal markdown typography for the announcement body. */
|
/* Minimal markdown typography for the announcement body. */
|
||||||
.ann-body { font-size: 0.9rem; line-height: 1.65; color: rgb(51 65 85); }
|
.ann-body { font-size: 0.9rem; line-height: 1.65; color: var(--fg-2); }
|
||||||
.ann-body :deep(h1) { font-size: 1.25rem; font-weight: 700; margin: 0.6em 0 0.4em; color: rgb(15 23 42); }
|
.ann-body :deep(h1) { font-size: 1.25rem; font-weight: 700; margin: 0.6em 0 0.4em; color: var(--fg); }
|
||||||
.ann-body :deep(h2) { font-size: 1.1rem; font-weight: 700; margin: 0.6em 0 0.4em; color: rgb(15 23 42); }
|
.ann-body :deep(h2) { font-size: 1.1rem; font-weight: 700; margin: 0.6em 0 0.4em; color: var(--fg); }
|
||||||
.ann-body :deep(h3) { font-size: 1rem; font-weight: 600; margin: 0.6em 0 0.3em; color: rgb(15 23 42); }
|
.ann-body :deep(h3) { font-size: 1rem; font-weight: 600; margin: 0.6em 0 0.3em; color: var(--fg); }
|
||||||
.ann-body :deep(p) { margin: 0.5em 0; }
|
.ann-body :deep(p) { margin: 0.5em 0; }
|
||||||
.ann-body :deep(ul), .ann-body :deep(ol) { margin: 0.5em 0; padding-left: 1.4em; }
|
.ann-body :deep(ul), .ann-body :deep(ol) { margin: 0.5em 0; padding-left: 1.4em; }
|
||||||
.ann-body :deep(ul) { list-style: disc; }
|
.ann-body :deep(ul) { list-style: disc; }
|
||||||
.ann-body :deep(ol) { list-style: decimal; }
|
.ann-body :deep(ol) { list-style: decimal; }
|
||||||
.ann-body :deep(li) { margin: 0.2em 0; }
|
.ann-body :deep(li) { margin: 0.2em 0; }
|
||||||
.ann-body :deep(a) { color: var(--m-orange); text-decoration: underline; }
|
.ann-body :deep(a) { color: var(--m-orange); text-decoration: underline; }
|
||||||
.ann-body :deep(strong) { font-weight: 700; color: rgb(15 23 42); }
|
.ann-body :deep(strong) { font-weight: 700; color: var(--fg); }
|
||||||
.ann-body :deep(code) { background: rgb(254 240 138 / 0.5); padding: 0.1em 0.35em; border-radius: 0.3rem; font-size: 0.85em; }
|
.ann-body :deep(code) { background: rgb(124 92 252 / 0.12); padding: 0.1em 0.35em; border-radius: 0.3rem; font-size: 0.85em; }
|
||||||
.ann-body :deep(pre) { background: #111; color: #f5f5f5; padding: 0.8em; border-radius: 0.5rem; overflow-x: auto; margin: 0.6em 0; }
|
.ann-body :deep(pre) { background: #111; color: #f5f5f5; padding: 0.8em; border-radius: 0.5rem; overflow-x: auto; margin: 0.6em 0; }
|
||||||
.ann-body :deep(pre code) { background: none; padding: 0; }
|
.ann-body :deep(pre code) { background: none; padding: 0; }
|
||||||
.ann-body :deep(blockquote) { border-left: 3px solid var(--m-orange); padding-left: 0.9em; color: rgb(100 116 139); margin: 0.6em 0; }
|
.ann-body :deep(blockquote) { border-left: 3px solid var(--m-orange); padding-left: 0.9em; color: var(--fg-3); margin: 0.6em 0; }
|
||||||
.ann-body :deep(hr) { border: none; border-top: 1px solid rgb(226 232 240); margin: 1em 0; }
|
.ann-body :deep(hr) { border: none; border-top: 1px solid var(--hairline); margin: 1em 0; }
|
||||||
.ann-body :deep(img) { max-width: 100%; border-radius: 0.5rem; margin: 0.5em 0; }
|
.ann-body :deep(img) { max-width: 100%; border-radius: 0.5rem; margin: 0.5em 0; }
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -164,9 +164,9 @@ async function submit() {
|
|||||||
<div class="absolute inset-0 bg-black/70 backdrop-blur-md" @click="closeLogin"></div>
|
<div class="absolute inset-0 bg-black/70 backdrop-blur-md" @click="closeLogin"></div>
|
||||||
|
|
||||||
<div class="card relative z-10 w-full max-w-[26rem]">
|
<div class="card relative z-10 w-full max-w-[26rem]">
|
||||||
<!-- ambient memphis crayon washes -->
|
<!-- ambient aurora washes -->
|
||||||
<div class="pointer-events-none absolute -top-24 -right-16 h-56 w-56 rounded-full bg-[#fef08a]/60 blur-3xl"></div>
|
<div class="pointer-events-none absolute -top-24 -right-16 h-56 w-56 rounded-full bg-[#8b5cf6]/30 blur-3xl"></div>
|
||||||
<div class="pointer-events-none absolute -bottom-24 -left-16 h-56 w-56 rounded-full bg-[#ffc1cc]/50 blur-3xl"></div>
|
<div class="pointer-events-none absolute -bottom-24 -left-16 h-56 w-56 rounded-full bg-[#22d3ee]/25 blur-3xl"></div>
|
||||||
|
|
||||||
<div class="relative p-7">
|
<div class="relative p-7">
|
||||||
<button class="absolute top-4 right-4 grid h-7 w-7 place-items-center rounded-lg text-[color:var(--fg-3)] hover:text-[color:var(--fg)] hover:bg-[var(--hover)] transition-colors"
|
<button class="absolute top-4 right-4 grid h-7 w-7 place-items-center rounded-lg text-[color:var(--fg-3)] hover:text-[color:var(--fg)] hover:bg-[var(--hover)] transition-colors"
|
||||||
@@ -262,21 +262,22 @@ async function submit() {
|
|||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.card {
|
.card {
|
||||||
border-radius: 1.1rem;
|
border-radius: 1.2rem;
|
||||||
background: var(--surface);
|
background: var(--menu-bg);
|
||||||
|
-webkit-backdrop-filter: blur(20px);
|
||||||
|
backdrop-filter: blur(20px);
|
||||||
color: var(--fg);
|
color: var(--fg);
|
||||||
border: 3px solid var(--ink);
|
border: 1px solid var(--glass-border);
|
||||||
box-shadow: 10px 10px 0 var(--shadow-ink);
|
box-shadow: var(--glass-shadow-lg);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
html.dark .card {
|
html.dark .card {
|
||||||
background: #1c1d24;
|
|
||||||
color: rgb(255 255 255 / 0.9);
|
color: rgb(255 255 255 / 0.9);
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo-halo {
|
.logo-halo {
|
||||||
position: relative;
|
position: relative;
|
||||||
filter: drop-shadow(0 6px 0 rgb(236 91 19 / 0.35));
|
filter: drop-shadow(0 6px 14px rgb(124 92 252 / 0.4));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* segmented tab control */
|
/* segmented tab control */
|
||||||
@@ -284,22 +285,21 @@ html.dark .card {
|
|||||||
display: flex; gap: 0.3rem; padding: 0.3rem;
|
display: flex; gap: 0.3rem; padding: 0.3rem;
|
||||||
border-radius: 0.7rem;
|
border-radius: 0.7rem;
|
||||||
background: var(--surface-2);
|
background: var(--surface-2);
|
||||||
border: 2px solid var(--ink);
|
border: 1px solid var(--ink-soft);
|
||||||
}
|
}
|
||||||
.tab {
|
.tab {
|
||||||
flex: 1; padding: 0.45rem 0; border-radius: 0.5rem;
|
flex: 1; padding: 0.45rem 0; border-radius: 0.5rem;
|
||||||
font-size: 0.8125rem; font-weight: 700; color: var(--fg-3);
|
font-size: 0.8125rem; font-weight: 700; color: var(--fg-3);
|
||||||
border: 2px solid transparent;
|
border: 1px solid transparent;
|
||||||
transition: background 0.18s, color 0.18s, box-shadow 0.18s, border-color 0.18s;
|
transition: background 0.18s, color 0.18s, box-shadow 0.18s, border-color 0.18s;
|
||||||
}
|
}
|
||||||
.tab:hover { color: var(--fg); }
|
.tab:hover { color: var(--fg); }
|
||||||
.tab-on {
|
.tab-on {
|
||||||
color: #111;
|
color: #fff;
|
||||||
background: var(--m-yellow);
|
background: linear-gradient(120deg, #7c5cfc, #5f6cf8);
|
||||||
border-color: var(--ink);
|
border-color: transparent;
|
||||||
box-shadow: 2px 2px 0 var(--shadow-ink);
|
box-shadow: 0 4px 14px var(--accent-glow);
|
||||||
}
|
}
|
||||||
html.dark .tab-on { color: #fff; background: var(--m-orange); }
|
|
||||||
|
|
||||||
/* icon-prefixed input */
|
/* icon-prefixed input */
|
||||||
.lm-field { position: relative; }
|
.lm-field { position: relative; }
|
||||||
@@ -311,14 +311,14 @@ html.dark .tab-on { color: #fff; background: var(--m-orange); }
|
|||||||
.lm-field:focus-within .ic { color: var(--m-orange); }
|
.lm-field:focus-within .ic { color: var(--m-orange); }
|
||||||
.fld {
|
.fld {
|
||||||
width: 100%; padding: 0.7rem 0.85rem 0.7rem 2.4rem; border-radius: 0.6rem;
|
width: 100%; padding: 0.7rem 0.85rem 0.7rem 2.4rem; border-radius: 0.6rem;
|
||||||
background: var(--surface); border: 2px solid var(--ink-soft);
|
background: var(--surface); border: 1px solid var(--ink-soft);
|
||||||
color: var(--fg); font-size: 0.875rem; outline: none;
|
color: var(--fg); font-size: 0.875rem; outline: none;
|
||||||
transition: border-color 0.15s, box-shadow 0.15s, background 0.15s;
|
transition: border-color 0.15s, box-shadow 0.15s, background 0.15s;
|
||||||
}
|
}
|
||||||
html.dark .fld { background: rgb(255 255 255 / 0.05); }
|
html.dark .fld { background: rgb(255 255 255 / 0.05); }
|
||||||
.fld:focus {
|
.fld:focus {
|
||||||
border-color: var(--ink);
|
border-color: rgb(124 92 252 / 0.65);
|
||||||
box-shadow: 3px 3px 0 var(--m-orange);
|
box-shadow: 0 0 0 3px rgb(124 92 252 / 0.18);
|
||||||
}
|
}
|
||||||
.fld::placeholder { color: var(--fg-faint); }
|
.fld::placeholder { color: var(--fg-faint); }
|
||||||
/* Keep autofill on-theme in dark (otherwise it paints white/yellow). */
|
/* Keep autofill on-theme in dark (otherwise it paints white/yellow). */
|
||||||
@@ -344,13 +344,12 @@ html.dark .fld:-webkit-autofill:focus {
|
|||||||
min-width: 5.5rem; /* keep width stable between text / spinner */
|
min-width: 5.5rem; /* keep width stable between text / spinner */
|
||||||
display: inline-flex; align-items: center; justify-content: center;
|
display: inline-flex; align-items: center; justify-content: center;
|
||||||
font-size: 0.75rem; font-weight: 800; white-space: nowrap;
|
font-size: 0.75rem; font-weight: 800; white-space: nowrap;
|
||||||
color: #111;
|
color: var(--fg);
|
||||||
background: var(--m-yellow); border: 2px solid var(--ink);
|
background: var(--hover); border: 1px solid rgb(124 92 252 / 0.4);
|
||||||
box-shadow: 2px 2px 0 var(--shadow-ink);
|
box-shadow: 0 2px 10px rgb(124 92 252 / 0.14);
|
||||||
transition: background 0.15s, box-shadow 0.15s, transform 0.15s, opacity 0.15s;
|
transition: background 0.15s, box-shadow 0.15s, transform 0.15s, opacity 0.15s;
|
||||||
}
|
}
|
||||||
html.dark .code-btn { color: #111; }
|
.code-btn:hover:not(:disabled) { transform: translateY(-1px); box-shadow: 0 4px 14px rgb(124 92 252 / 0.22); }
|
||||||
.code-btn:hover:not(:disabled) { transform: translate(-1px, -1px); box-shadow: 3px 3px 0 var(--shadow-ink); }
|
|
||||||
.code-btn:active:not(:disabled) { transform: scale(0.96) translateY(1px); box-shadow: none; }
|
.code-btn:active:not(:disabled) { transform: scale(0.96) translateY(1px); box-shadow: none; }
|
||||||
/* Disabled (sending / countdown): just dim — keep the theme text color so it
|
/* Disabled (sending / countdown): just dim — keep the theme text color so it
|
||||||
never washes out to invisible white on the light card. */
|
never washes out to invisible white on the light card. */
|
||||||
@@ -362,13 +361,13 @@ html.dark .code-btn { color: #111; }
|
|||||||
display: flex; align-items: center; justify-content: center; gap: 0.5rem;
|
display: flex; align-items: center; justify-content: center; gap: 0.5rem;
|
||||||
padding: 0.72rem 0; border-radius: 0.65rem; font-size: 0.9rem; font-weight: 800;
|
padding: 0.72rem 0; border-radius: 0.65rem; font-size: 0.9rem; font-weight: 800;
|
||||||
letter-spacing: 0.02em; color: white; margin-top: 0.35rem;
|
letter-spacing: 0.02em; color: white; margin-top: 0.35rem;
|
||||||
background: var(--m-orange);
|
background: linear-gradient(120deg, #7c5cfc, #5f6cf8 55%, #22d3ee 140%);
|
||||||
border: 2.5px solid var(--ink);
|
border: 1px solid rgb(255 255 255 / 0.16);
|
||||||
box-shadow: 4px 4px 0 var(--shadow-ink);
|
box-shadow: 0 8px 22px var(--accent-glow);
|
||||||
transition: transform 0.13s, box-shadow 0.13s, filter 0.15s;
|
transition: transform 0.13s, box-shadow 0.13s, filter 0.15s;
|
||||||
}
|
}
|
||||||
.btn-primary:hover:not(:disabled) { filter: brightness(1.06); transform: translate(-1px, -1px); box-shadow: 5px 5px 0 var(--shadow-ink); }
|
.btn-primary:hover:not(:disabled) { filter: brightness(1.07); transform: translateY(-1px); box-shadow: 0 12px 30px var(--accent-glow); }
|
||||||
.btn-primary:active:not(:disabled) { transform: scale(0.98) translateY(2px); box-shadow: 0 0 0 var(--shadow-ink); }
|
.btn-primary:active:not(:disabled) { transform: scale(0.98) translateY(1px); box-shadow: 0 4px 12px var(--accent-glow); }
|
||||||
.btn-primary:disabled { opacity: 0.6; cursor: not-allowed; }
|
.btn-primary:disabled { opacity: 0.6; cursor: not-allowed; }
|
||||||
|
|
||||||
.spinner {
|
.spinner {
|
||||||
@@ -382,7 +381,7 @@ html.dark .code-btn { color: #111; }
|
|||||||
display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.85rem;
|
display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.85rem;
|
||||||
padding: 0.6rem 0.75rem; border-radius: 0.6rem; font-size: 0.75rem; line-height: 1.4;
|
padding: 0.6rem 0.75rem; border-radius: 0.6rem; font-size: 0.75rem; line-height: 1.4;
|
||||||
color: #065f46; font-weight: 600;
|
color: #065f46; font-weight: 600;
|
||||||
background: var(--m-mint); border: 2px solid var(--ink);
|
background: rgb(52 211 153 / 0.14); border: 1px solid rgb(52 211 153 / 0.4);
|
||||||
}
|
}
|
||||||
html.dark .invite-banner { color: rgb(167 243 208); background: rgb(16 185 129 / 0.15); }
|
html.dark .invite-banner { color: rgb(167 243 208); background: rgb(16 185 129 / 0.15); }
|
||||||
.invite-banner svg { color: rgb(5 150 105); }
|
.invite-banner svg { color: rgb(5 150 105); }
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// Vivid mark: an open spectrum ring (lens/aperture) around a play triangle,
|
// Vivid mark: an open spectrum ring (lens/aperture) around a play triangle,
|
||||||
// with a shutter dot closing the gap — image + video in one glyph.
|
// with a shutter dot closing the gap — image + video in one glyph.
|
||||||
// Transparent background so it reads on both the dark and light shells.
|
// Transparent background so it reads on both the dark and light shells.
|
||||||
// Colors follow the memphis crayon palette (orange / pink / blue).
|
// Colors follow the aurora palette (violet / pink / cyan).
|
||||||
// Each instance gets unique gradient ids (useId) so multiple logos on one
|
// Each instance gets unique gradient ids (useId) so multiple logos on one
|
||||||
// page don't share/clobber defs.
|
// page don't share/clobber defs.
|
||||||
import { useId } from 'vue'
|
import { useId } from 'vue'
|
||||||
@@ -18,9 +18,9 @@ const gRing = `vring-${uid}`
|
|||||||
xmlns="http://www.w3.org/2000/svg" class="shrink-0">
|
xmlns="http://www.w3.org/2000/svg" class="shrink-0">
|
||||||
<defs>
|
<defs>
|
||||||
<linearGradient :id="gRing" x1="6" y1="6" x2="42" y2="42" gradientUnits="userSpaceOnUse">
|
<linearGradient :id="gRing" x1="6" y1="6" x2="42" y2="42" gradientUnits="userSpaceOnUse">
|
||||||
<stop stop-color="#ec5b13" />
|
<stop stop-color="#7c5cfc" />
|
||||||
<stop offset="0.5" stop-color="#f472b6" />
|
<stop offset="0.5" stop-color="#e879f9" />
|
||||||
<stop offset="1" stop-color="#38bdf8" />
|
<stop offset="1" stop-color="#22d3ee" />
|
||||||
</linearGradient>
|
</linearGradient>
|
||||||
</defs>
|
</defs>
|
||||||
|
|
||||||
@@ -29,10 +29,10 @@ const gRing = `vring-${uid}`
|
|||||||
<circle r="17.5" fill="none" :stroke="`url(#${gRing})`" stroke-width="4.4"
|
<circle r="17.5" fill="none" :stroke="`url(#${gRing})`" stroke-width="4.4"
|
||||||
stroke-linecap="round" stroke-dasharray="84 32" transform="rotate(-58)" />
|
stroke-linecap="round" stroke-dasharray="84 32" transform="rotate(-58)" />
|
||||||
<!-- play triangle = image + video -->
|
<!-- play triangle = image + video -->
|
||||||
<path d="M-3 -6.5 L8.5 0 L-3 6.5 Z" fill="#ec5b13" stroke="#111" stroke-width="1.4"
|
<path d="M-3 -6.5 L8.5 0 L-3 6.5 Z" fill="#7c5cfc" stroke="#111" stroke-width="1.4"
|
||||||
stroke-linejoin="round" />
|
stroke-linejoin="round" />
|
||||||
<!-- shutter dot -->
|
<!-- shutter dot -->
|
||||||
<circle cx="13" cy="-13" r="4.2" fill="#fef08a" stroke="#111" stroke-width="1.6" />
|
<circle cx="13" cy="-13" r="4.2" fill="#22d3ee" stroke="#111" stroke-width="1.6" />
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -103,31 +103,33 @@ onUnmounted(clearTimers)
|
|||||||
<transition name="pay-fade">
|
<transition name="pay-fade">
|
||||||
<div v-if="payment.show" class="fixed inset-0 z-[85] bg-slate-950/70 backdrop-blur-sm flex items-center justify-center p-4"
|
<div v-if="payment.show" class="fixed inset-0 z-[85] bg-slate-950/70 backdrop-blur-sm flex items-center justify-center p-4"
|
||||||
@click.self="!paid && finish()">
|
@click.self="!paid && finish()">
|
||||||
<div class="w-full max-w-sm rounded-xl bg-white text-slate-800 border-[3px] border-[#111] shadow-[8px_8px_0_#111] overflow-hidden">
|
<div class="w-full max-w-sm rounded-2xl bg-[var(--menu-bg)] backdrop-blur-xl text-[color:var(--fg)] border border-[color:var(--glass-border)] shadow-[var(--glass-shadow-lg)] overflow-hidden">
|
||||||
<div class="px-5 py-4 border-b-[2.5px] border-b-[#111] flex items-center justify-between">
|
<div class="px-5 py-4 border-b border-b-[color:var(--ink-soft)] flex items-center justify-between">
|
||||||
<h2 class="text-base font-semibold">{{ paid ? '支付成功' : dead ? '支付超时' : (isJump ? '支付监控中' : '扫码支付') }}</h2>
|
<h2 class="text-base font-semibold">{{ paid ? '支付成功' : dead ? '支付超时' : (isJump ? '支付监控中' : '扫码支付') }}</h2>
|
||||||
<button v-if="!paid" @click="finish" class="text-slate-400 hover:text-slate-700"><Icon name="close" class="w-5 h-5" /></button>
|
<button v-if="!paid" @click="finish" class="text-[color:var(--fg-3)] hover:text-[color:var(--fg)] transition-colors"><Icon name="close" class="w-5 h-5" /></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- paid -->
|
<!-- paid -->
|
||||||
<div v-if="paid" class="px-6 py-10 text-center">
|
<div v-if="paid" class="px-6 py-10 text-center">
|
||||||
<div class="w-16 h-16 mx-auto rounded-full bg-[#a7f3d0] text-emerald-700 border-[2.5px] border-[#111] shadow-[4px_4px_0_#111] grid place-items-center mb-4">
|
<div class="w-16 h-16 mx-auto rounded-full text-white grid place-items-center mb-4"
|
||||||
|
style="background: linear-gradient(135deg, #34d399, #2dd4bf); box-shadow: 0 10px 28px rgb(52 211 153 / 0.4)">
|
||||||
<Icon name="spark" class="w-8 h-8" />
|
<Icon name="spark" class="w-8 h-8" />
|
||||||
</div>
|
</div>
|
||||||
<p class="text-lg font-semibold text-slate-800">充值成功</p>
|
<p class="text-lg font-semibold text-[color:var(--fg)]">充值成功</p>
|
||||||
<p class="text-sm text-slate-500 mt-1">已到账 <strong class="text-emerald-600">{{ order.points }}</strong> 积分</p>
|
<p class="text-sm text-[color:var(--fg-3)] mt-1">已到账 <strong class="text-emerald-500">{{ order.points }}</strong> 积分</p>
|
||||||
<p class="text-xs text-slate-400 mt-4">{{ closeIn }} 秒后自动关闭</p>
|
<p class="text-xs text-[color:var(--fg-faint)] mt-4">{{ closeIn }} 秒后自动关闭</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- expired / cancelled -->
|
<!-- expired / cancelled -->
|
||||||
<div v-else-if="dead" class="px-6 py-10 text-center">
|
<div v-else-if="dead" class="px-6 py-10 text-center">
|
||||||
<div class="w-16 h-16 mx-auto rounded-full bg-slate-100 text-slate-400 grid place-items-center mb-4">
|
<div class="w-16 h-16 mx-auto rounded-full bg-[var(--surface-2)] text-[color:var(--fg-3)] grid place-items-center mb-4">
|
||||||
<Icon name="close" class="w-8 h-8" />
|
<Icon name="close" class="w-8 h-8" />
|
||||||
</div>
|
</div>
|
||||||
<p class="text-lg font-semibold text-slate-700">支付超时</p>
|
<p class="text-lg font-semibold text-[color:var(--fg)]">支付超时</p>
|
||||||
<p class="text-sm text-slate-500 mt-1">二维码已失效,订单已取消</p>
|
<p class="text-sm text-[color:var(--fg-3)] mt-1">二维码已失效,订单已取消</p>
|
||||||
<p class="text-xs text-slate-400 mt-1">如需充值请重新下单</p>
|
<p class="text-xs text-[color:var(--fg-faint)] mt-1">如需充值请重新下单</p>
|
||||||
<button @click="finish" class="mt-5 rounded-lg bg-[#ec5b13] text-white border-[2.5px] border-[#111] shadow-[3px_3px_0_#111] hover:-translate-y-0.5 active:translate-y-0.5 active:shadow-none px-5 py-2 text-sm font-extrabold transition-all">关闭</button>
|
<button @click="finish" class="mt-5 rounded-lg text-white border border-white/20 px-5 py-2 text-sm font-extrabold hover:-translate-y-0.5 active:translate-y-0.5 transition-all"
|
||||||
|
style="background: linear-gradient(120deg, #7c5cfc, #22d3ee); box-shadow: 0 8px 20px var(--accent-glow)">关闭</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- pending -->
|
<!-- pending -->
|
||||||
@@ -135,31 +137,31 @@ onUnmounted(clearTimers)
|
|||||||
<!-- qrcode: scan to pay -->
|
<!-- qrcode: scan to pay -->
|
||||||
<template v-if="!isJump">
|
<template v-if="!isJump">
|
||||||
<div class="flex justify-center mb-3">
|
<div class="flex justify-center mb-3">
|
||||||
<div class="w-[228px] h-[228px] rounded-xl border-[2.5px] border-[#111] shadow-[4px_4px_0_#111] grid place-items-center overflow-hidden bg-white p-3.5">
|
<div class="w-[228px] h-[228px] rounded-xl border border-[color:var(--glass-border)] shadow-[var(--glass-shadow)] grid place-items-center overflow-hidden bg-white p-3.5">
|
||||||
<img v-if="qrUrl" :src="qrUrl" alt="支付二维码" class="w-full h-full rounded-lg" />
|
<img v-if="qrUrl" :src="qrUrl" alt="支付二维码" class="w-full h-full rounded-lg" />
|
||||||
<span v-else class="text-xs text-slate-400">二维码生成中…</span>
|
<span v-else class="text-xs text-slate-400">二维码生成中…</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p class="text-center text-xs text-slate-500 mb-4">请使用<strong class="text-slate-700">{{ methodLabel }}</strong>扫码支付</p>
|
<p class="text-center text-xs text-[color:var(--fg-3)] mb-4">请使用<strong class="text-[color:var(--fg)]">{{ methodLabel }}</strong>扫码支付</p>
|
||||||
</template>
|
</template>
|
||||||
<!-- jump (no qrcode): the cashier opened in a new tab — just monitor -->
|
<!-- jump (no qrcode): the cashier opened in a new tab — just monitor -->
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<div class="flex flex-col items-center justify-center py-7 mb-2">
|
<div class="flex flex-col items-center justify-center py-7 mb-2">
|
||||||
<div class="w-12 h-12 rounded-full border-[3px] border-[#fecaca] border-t-[#ec5b13] animate-spin mb-3"></div>
|
<div class="w-12 h-12 rounded-full border-[3px] border-[rgb(124_92_252/0.2)] border-t-[#7c5cfc] animate-spin mb-3"></div>
|
||||||
<p class="text-sm font-medium text-slate-700">支付监控中…</p>
|
<p class="text-sm font-medium text-[color:var(--fg)]">支付监控中…</p>
|
||||||
<p class="text-xs text-slate-400 mt-1">已打开支付页面,完成后自动到账</p>
|
<p class="text-xs text-[color:var(--fg-faint)] mt-1">已打开支付页面,完成后自动到账</p>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<dl class="text-sm space-y-2">
|
<dl class="text-sm space-y-2">
|
||||||
<div class="flex justify-between"><dt class="text-slate-400">订单号</dt><dd class="font-mono text-xs text-slate-700">{{ order.id }}</dd></div>
|
<div class="flex justify-between"><dt class="text-[color:var(--fg-faint)]">订单号</dt><dd class="font-mono text-xs text-[color:var(--fg)]">{{ order.id }}</dd></div>
|
||||||
<div class="flex justify-between"><dt class="text-slate-400">状态</dt><dd class="text-amber-600 font-medium">{{ statusLabel }}</dd></div>
|
<div class="flex justify-between"><dt class="text-[color:var(--fg-faint)]">状态</dt><dd class="text-amber-500 font-medium">{{ statusLabel }}</dd></div>
|
||||||
<div class="flex justify-between"><dt class="text-slate-400">金额</dt><dd class="font-semibold text-slate-800">¥{{ order.amount }}</dd></div>
|
<div class="flex justify-between"><dt class="text-[color:var(--fg-faint)]">金额</dt><dd class="font-semibold text-[color:var(--fg)]">¥{{ order.amount }}</dd></div>
|
||||||
<div class="flex justify-between"><dt class="text-slate-400">充值积分</dt><dd class="text-[#ec5b13] font-semibold">{{ order.points }}</dd></div>
|
<div class="flex justify-between"><dt class="text-[color:var(--fg-faint)]">充值积分</dt><dd class="text-[color:var(--m-orange)] font-semibold">{{ order.points }}</dd></div>
|
||||||
<div class="flex justify-between"><dt class="text-slate-400">下单时间</dt><dd class="text-xs text-slate-600">{{ fmtTime(order.created_at) }}</dd></div>
|
<div class="flex justify-between"><dt class="text-[color:var(--fg-faint)]">下单时间</dt><dd class="text-xs text-[color:var(--fg-2)]">{{ fmtTime(order.created_at) }}</dd></div>
|
||||||
<div class="flex justify-between"><dt class="text-slate-400">支付倒计时</dt><dd class="tabular-nums font-medium" :class="remaining > 0 ? 'text-slate-700' : 'text-rose-500'">{{ remaining > 0 ? mmss : '已超时' }}</dd></div>
|
<div class="flex justify-between"><dt class="text-[color:var(--fg-faint)]">支付倒计时</dt><dd class="tabular-nums font-medium" :class="remaining > 0 ? 'text-[color:var(--fg)]' : 'text-rose-500'">{{ remaining > 0 ? mmss : '已超时' }}</dd></div>
|
||||||
</dl>
|
</dl>
|
||||||
<p class="text-[11px] text-slate-400 mt-4 text-center">支付完成后将自动到账,请勿关闭本窗口</p>
|
<p class="text-[11px] text-[color:var(--fg-faint)] mt-4 text-center">支付完成后将自动到账,请勿关闭本窗口</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -90,8 +90,8 @@ onUnmounted(() => document.removeEventListener('mousedown', onDocClick))
|
|||||||
leave-from-class="opacity-100 translate-y-0"
|
leave-from-class="opacity-100 translate-y-0"
|
||||||
leave-to-class="opacity-0 -translate-y-1">
|
leave-to-class="opacity-0 -translate-y-1">
|
||||||
<div v-if="open" ref="panel"
|
<div v-if="open" ref="panel"
|
||||||
class="absolute z-30 mt-2 w-full max-h-64 overflow-auto rounded-xl border-[2.5px] border-[color:var(--ink)]
|
class="absolute z-30 mt-2 w-full max-h-64 overflow-auto rounded-xl border border-[color:var(--glass-border)]
|
||||||
bg-[var(--menu-bg)] p-1.5 shadow-[5px_5px_0_var(--shadow-ink)]">
|
bg-[var(--menu-bg)] backdrop-blur-xl p-1.5 shadow-[var(--glass-shadow-lg)]">
|
||||||
<button v-for="(o, i) in options" :key="o.value" type="button"
|
<button v-for="(o, i) in options" :key="o.value" type="button"
|
||||||
:data-idx="i" @click="pick(o)" @mouseenter="active = i"
|
:data-idx="i" @click="pick(o)" @mouseenter="active = i"
|
||||||
class="w-full flex items-center justify-between gap-2 rounded-lg px-3 py-2 text-left text-sm font-medium transition-colors"
|
class="w-full flex items-center justify-between gap-2 rounded-lg px-3 py-2 text-left text-sm font-medium transition-colors"
|
||||||
|
|||||||
@@ -153,18 +153,19 @@ defineExpose({ startEdit, commitNote })
|
|||||||
.cv-node {
|
.cv-node {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
border-radius: 14px;
|
border-radius: 14px;
|
||||||
border: 2.5px solid var(--ink);
|
border: 1px solid var(--glass-border);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
contain: layout style paint;
|
contain: layout style paint;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
touch-action: none;
|
touch-action: none;
|
||||||
cursor: grab;
|
cursor: grab;
|
||||||
background: var(--surface);
|
background: var(--surface-solid);
|
||||||
box-shadow: 5px 5px 0 var(--shadow-ink);
|
box-shadow: var(--glass-shadow);
|
||||||
transition: box-shadow 0.15s ease;
|
transition: box-shadow 0.15s ease, border-color 0.15s ease;
|
||||||
}
|
}
|
||||||
.cv-node.is-selected {
|
.cv-node.is-selected {
|
||||||
box-shadow: 7px 7px 0 var(--m-orange);
|
border-color: rgb(124 92 252 / 0.7);
|
||||||
|
box-shadow: var(--glass-shadow-lg), 0 0 0 3px rgb(124 92 252 / 0.25), 0 10px 30px var(--accent-glow);
|
||||||
}
|
}
|
||||||
.cv-node:active {
|
.cv-node:active {
|
||||||
cursor: grabbing;
|
cursor: grabbing;
|
||||||
@@ -188,19 +189,24 @@ defineExpose({ startEdit, commitNote })
|
|||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
line-height: 1.35;
|
line-height: 1.35;
|
||||||
color: var(--fg);
|
color: var(--fg);
|
||||||
background: var(--surface);
|
background: var(--surface-solid);
|
||||||
border-top: 2.5px solid var(--ink);
|
border-top: 1px solid var(--ink-soft);
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 笔记 = 孟菲斯黄贴纸 */
|
/* 笔记 = 淡黄色贴纸 */
|
||||||
.cv-node--note {
|
.cv-node--note {
|
||||||
background: var(--m-yellow);
|
background: #fdf6c9;
|
||||||
|
border-color: rgb(180 140 20 / 0.35);
|
||||||
cursor: text;
|
cursor: text;
|
||||||
}
|
}
|
||||||
|
html.dark .cv-node--note {
|
||||||
|
background: rgb(250 204 21 / 0.14);
|
||||||
|
border-color: rgb(250 204 21 / 0.35);
|
||||||
|
}
|
||||||
.cv-node--note:not(.is-editing) {
|
.cv-node--note:not(.is-editing) {
|
||||||
cursor: grab;
|
cursor: grab;
|
||||||
}
|
}
|
||||||
@@ -217,6 +223,7 @@ defineExpose({ startEdit, commitNote })
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
html.dark .cv-node__note { color: rgb(255 255 255 / 0.88); }
|
||||||
.is-editing .cv-node__note {
|
.is-editing .cv-node__note {
|
||||||
user-select: text;
|
user-select: text;
|
||||||
cursor: text;
|
cursor: text;
|
||||||
@@ -229,6 +236,8 @@ defineExpose({ startEdit, commitNote })
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
background: var(--surface);
|
background: var(--surface);
|
||||||
|
-webkit-backdrop-filter: blur(10px);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
border-style: dashed;
|
border-style: dashed;
|
||||||
color: var(--fg-2);
|
color: var(--fg-2);
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
@@ -266,8 +275,9 @@ defineExpose({ startEdit, commitNote })
|
|||||||
width: 15px;
|
width: 15px;
|
||||||
height: 15px;
|
height: 15px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background: var(--m-orange);
|
background: linear-gradient(135deg, #7c5cfc, #22d3ee);
|
||||||
border: 2.5px solid var(--ink);
|
border: 1.5px solid rgb(255 255 255 / 0.7);
|
||||||
|
box-shadow: 0 2px 10px var(--accent-glow);
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: opacity 0.12s;
|
transition: opacity 0.12s;
|
||||||
cursor: crosshair;
|
cursor: crosshair;
|
||||||
@@ -286,8 +296,8 @@ defineExpose({ startEdit, commitNote })
|
|||||||
width: 15px;
|
width: 15px;
|
||||||
height: 15px;
|
height: 15px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
background: var(--m-blue);
|
background: var(--surface-solid);
|
||||||
border: 2.5px solid var(--ink);
|
border: 1px solid var(--ink);
|
||||||
cursor: nwse-resize;
|
cursor: nwse-resize;
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
}
|
}
|
||||||
@@ -305,22 +315,28 @@ defineExpose({ startEdit, commitNote })
|
|||||||
width: 24px;
|
width: 24px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
border-radius: 7px;
|
border-radius: 7px;
|
||||||
border: 2.5px solid var(--ink);
|
border: 1px solid var(--glass-border);
|
||||||
background: var(--m-yellow);
|
background: var(--menu-bg);
|
||||||
color: #1a1a1a;
|
-webkit-backdrop-filter: blur(10px);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
color: var(--fg);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
box-shadow: 2.5px 2.5px 0 var(--shadow-ink);
|
box-shadow: var(--glass-shadow);
|
||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
transition: transform 0.12s ease, background 0.12s ease, color 0.12s ease;
|
||||||
}
|
}
|
||||||
.cv-tools button:hover {
|
.cv-tools button:hover {
|
||||||
transform: translate(1px, 1px);
|
transform: translateY(-1px);
|
||||||
box-shadow: 1.5px 1.5px 0 var(--shadow-ink);
|
background: var(--hover);
|
||||||
}
|
}
|
||||||
.cv-tools__del {
|
.cv-tools__del {
|
||||||
background: #ffb4ab !important;
|
color: #e5484d;
|
||||||
|
}
|
||||||
|
.cv-tools__del:hover {
|
||||||
|
background: rgb(229 72 77 / 0.14) !important;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -617,8 +617,8 @@ defineExpose({
|
|||||||
}
|
}
|
||||||
.cv-marquee {
|
.cv-marquee {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
border: 2px dashed var(--ink);
|
border: 2px dashed rgb(124 92 252 / 0.5);
|
||||||
background: color-mix(in srgb, var(--m-yellow) 35%, transparent);
|
background: rgb(124 92 252 / 0.08);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
@@ -631,10 +631,12 @@ defineExpose({
|
|||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: var(--fg-2);
|
color: var(--fg-2);
|
||||||
background: var(--surface);
|
background: var(--surface);
|
||||||
border: 2px solid var(--ink);
|
-webkit-backdrop-filter: blur(10px);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
border: 1px solid var(--glass-border);
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
padding: 3px 14px;
|
padding: 3px 14px;
|
||||||
box-shadow: 3px 3px 0 var(--shadow-ink);
|
box-shadow: var(--glass-shadow);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
max-width: 92%;
|
max-width: 92%;
|
||||||
|
|||||||
@@ -49,9 +49,9 @@ watch(() => route.path, () => {
|
|||||||
<template>
|
<template>
|
||||||
<div class="theme-x h-screen flex bg-[var(--app-bg)] text-[color:var(--fg-2)] selection:bg-orange-400/30 overflow-hidden">
|
<div class="theme-x h-screen flex bg-[var(--app-bg)] text-[color:var(--fg-2)] selection:bg-orange-400/30 overflow-hidden">
|
||||||
<!-- ===== Sidebar ===== -->
|
<!-- ===== Sidebar ===== -->
|
||||||
<aside class="w-60 shrink-0 border-r-[3px] border-r-[color:var(--ink)] bg-[var(--surface)] backdrop-blur-md flex flex-col">
|
<aside class="w-60 shrink-0 border-r border-r-[color:var(--ink-soft)] bg-[var(--surface)] backdrop-blur-xl flex flex-col">
|
||||||
<router-link to="/" class="h-16 flex items-center gap-2.5 px-5 border-b-[3px] border-b-[color:var(--ink)] group">
|
<router-link to="/" class="h-16 flex items-center gap-2.5 px-5 border-b border-b-[color:var(--ink-soft)] group">
|
||||||
<img v-if="site.logo" :src="site.logo" :alt="site.title" class="w-8 h-8 rounded-[10px] object-contain ring-2 ring-[color:var(--ink)]" />
|
<img v-if="site.logo" :src="site.logo" :alt="site.title" class="w-8 h-8 rounded-[10px] object-contain ring-1 ring-[color:var(--ink)]" />
|
||||||
<Logo v-else :size="32" />
|
<Logo v-else :size="32" />
|
||||||
<div class="leading-tight min-w-0">
|
<div class="leading-tight min-w-0">
|
||||||
<div class="text-sm font-extrabold truncate tracking-tight text-[color:var(--fg)]">{{ site.title }}</div>
|
<div class="text-sm font-extrabold truncate tracking-tight text-[color:var(--fg)]">{{ site.title }}</div>
|
||||||
@@ -89,7 +89,7 @@ watch(() => route.path, () => {
|
|||||||
</template>
|
</template>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div class="p-3 border-t-[3px] border-t-[color:var(--ink)] space-y-1">
|
<div class="p-3 border-t border-t-[color:var(--ink-soft)] space-y-1">
|
||||||
<button type="button" @click="toggleTheme"
|
<button type="button" @click="toggleTheme"
|
||||||
class="w-full flex items-center gap-2.5 rounded-lg px-3 py-2 text-xs text-[color:var(--fg-2)] hover:bg-[var(--hover)] hover:text-[color:var(--fg)] transition-colors">
|
class="w-full flex items-center gap-2.5 rounded-lg px-3 py-2 text-xs text-[color:var(--fg-2)] hover:bg-[var(--hover)] hover:text-[color:var(--fg)] transition-colors">
|
||||||
<svg v-if="isDark" class="w-3.5 h-3.5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4"/></svg>
|
<svg v-if="isDark" class="w-3.5 h-3.5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4"/></svg>
|
||||||
@@ -106,18 +106,18 @@ watch(() => route.path, () => {
|
|||||||
|
|
||||||
<!-- ===== Main ===== -->
|
<!-- ===== Main ===== -->
|
||||||
<div class="flex-1 min-w-0 flex flex-col relative">
|
<div class="flex-1 min-w-0 flex flex-col relative">
|
||||||
<!-- memphis backdrop: polka dots + flat crayon washes -->
|
<!-- aurora backdrop: drifting gradient orbs + faint grain -->
|
||||||
<div aria-hidden="true" class="pointer-events-none absolute inset-0 overflow-hidden">
|
<div aria-hidden="true" class="pointer-events-none absolute inset-0 overflow-hidden">
|
||||||
<div class="memphis-dots absolute inset-0 opacity-50"></div>
|
<div class="memphis-dots absolute inset-0 opacity-40"></div>
|
||||||
<div class="absolute -top-32 left-1/3 w-[40rem] h-[40rem] rounded-full opacity-[0.16]"
|
<div class="absolute -top-40 left-1/4 w-[40rem] h-[40rem] rounded-full opacity-[0.45]"
|
||||||
style="background: radial-gradient(circle, #fef08a, transparent 60%); filter: blur(100px)"></div>
|
style="background: radial-gradient(circle, rgb(139 92 246 / 0.3), transparent 60%); filter: blur(110px)"></div>
|
||||||
<div class="absolute top-1/2 -right-40 w-[36rem] h-[36rem] rounded-full opacity-[0.14]"
|
<div class="absolute top-1/2 -right-48 w-[36rem] h-[36rem] rounded-full opacity-[0.4]"
|
||||||
style="background: radial-gradient(circle, #bae6fd, transparent 60%); filter: blur(100px)"></div>
|
style="background: radial-gradient(circle, rgb(34 211 238 / 0.24), transparent 60%); filter: blur(110px)"></div>
|
||||||
<div class="absolute bottom-0 left-0 w-[32rem] h-[32rem] rounded-full opacity-[0.12]"
|
<div class="absolute bottom-0 -left-24 w-[32rem] h-[32rem] rounded-full opacity-[0.35]"
|
||||||
style="background: radial-gradient(circle, #ffc1cc, transparent 60%); filter: blur(100px)"></div>
|
style="background: radial-gradient(circle, rgb(232 121 249 / 0.2), transparent 60%); filter: blur(110px)"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<header class="relative z-10 h-14 shrink-0 border-b-[3px] border-b-[color:var(--ink)] bg-[var(--app-bg)]/70 backdrop-blur-md flex items-center px-8">
|
<header class="relative z-10 h-14 shrink-0 border-b border-b-[color:var(--ink-soft)] bg-[var(--app-bg)]/60 backdrop-blur-xl flex items-center px-8">
|
||||||
<div class="text-[10px] uppercase tracking-[0.25em] text-[color:var(--m-orange)] font-extrabold mr-3">Admin</div>
|
<div class="text-[10px] uppercase tracking-[0.25em] text-[color:var(--m-orange)] font-extrabold mr-3">Admin</div>
|
||||||
<div class="text-[color:var(--fg-faint)] mr-3">/</div>
|
<div class="text-[color:var(--fg-faint)] mr-3">/</div>
|
||||||
<h1 class="text-sm font-semibold tracking-tight text-[color:var(--fg)]">{{ currentLabel }}</h1>
|
<h1 class="text-sm font-semibold tracking-tight text-[color:var(--fg)]">{{ currentLabel }}</h1>
|
||||||
@@ -144,36 +144,32 @@ watch(() => route.path, () => {
|
|||||||
gap: 0.75rem;
|
gap: 0.75rem;
|
||||||
padding: 0.55rem 0.875rem;
|
padding: 0.55rem 0.875rem;
|
||||||
border-radius: 0.625rem;
|
border-radius: 0.625rem;
|
||||||
border: 2px solid transparent;
|
border: 1px solid transparent;
|
||||||
color: var(--fg-2);
|
color: var(--fg-2);
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
|
transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
|
||||||
}
|
}
|
||||||
.admin-link:hover { background: rgb(254 240 138 / 0.5); color: var(--fg); border-color: var(--ink); }
|
.admin-link:hover { background: var(--hover); color: var(--fg); border-color: rgb(124 92 252 / 0.3); }
|
||||||
.admin-link.active {
|
.admin-link.active {
|
||||||
color: var(--fg);
|
color: #fff;
|
||||||
background: var(--m-yellow);
|
background: linear-gradient(120deg, #7c5cfc, #5f6cf8);
|
||||||
border-color: var(--ink);
|
border-color: transparent;
|
||||||
box-shadow: 3px 3px 0 var(--shadow-ink);
|
box-shadow: 0 4px 14px var(--accent-glow);
|
||||||
}
|
}
|
||||||
html.dark .admin-link:hover { background: rgb(236 91 19 / 0.18); }
|
.admin-link.active > span:first-child { opacity: 0; }
|
||||||
html.dark .admin-link.active { color: #fff; background: var(--m-orange); }
|
|
||||||
.admin-link.active > span:first-child { opacity: 1; }
|
|
||||||
|
|
||||||
.admin-sublink {
|
.admin-sublink {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 0.45rem 0.875rem 0.45rem 2.6rem;
|
padding: 0.45rem 0.875rem 0.45rem 2.6rem;
|
||||||
border-radius: 0.625rem;
|
border-radius: 0.625rem;
|
||||||
border: 2px solid transparent;
|
border: 1px solid transparent;
|
||||||
color: var(--fg-2);
|
color: var(--fg-2);
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
|
transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
|
||||||
}
|
}
|
||||||
.admin-sublink:hover { background: rgb(254 240 138 / 0.5); color: var(--fg); border-color: var(--ink); }
|
.admin-sublink:hover { background: var(--hover); color: var(--fg); border-color: rgb(124 92 252 / 0.3); }
|
||||||
.admin-sublink.active { color: var(--fg); background: var(--m-yellow); border-color: var(--ink); }
|
.admin-sublink.active { color: var(--m-orange); background: var(--hover); border-color: rgb(124 92 252 / 0.35); font-weight: 700; }
|
||||||
html.dark .admin-sublink:hover { background: rgb(236 91 19 / 0.18); }
|
|
||||||
html.dark .admin-sublink.active { color: #fff; background: var(--m-orange); }
|
|
||||||
|
|
||||||
.fade-enter-active, .fade-leave-active { transition: opacity 0.15s ease, transform 0.15s ease; }
|
.fade-enter-active, .fade-leave-active { transition: opacity 0.15s ease, transform 0.15s ease; }
|
||||||
.fade-enter-from { opacity: 0; transform: translateY(4px); }
|
.fade-enter-from { opacity: 0; transform: translateY(4px); }
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ async function onLogout() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- mobile panel -->
|
<!-- mobile panel -->
|
||||||
<div v-if="mobileOpen" class="md:hidden border-t-2 border-[color:var(--ink)] px-3 py-3 bg-[var(--menu-bg)]">
|
<div v-if="mobileOpen" class="md:hidden border-t border-[color:var(--ink-soft)] px-3 py-3 bg-[var(--menu-bg)]">
|
||||||
<router-link v-for="n in nav" :key="n.to" :to="n.to"
|
<router-link v-for="n in nav" :key="n.to" :to="n.to"
|
||||||
:exact-active-class="n.to === '/' ? 'm-on' : ''"
|
:exact-active-class="n.to === '/' ? 'm-on' : ''"
|
||||||
:active-class="n.to === '/' ? '' : 'm-on'"
|
:active-class="n.to === '/' ? '' : 'm-on'"
|
||||||
@@ -164,15 +164,15 @@ async function onLogout() {
|
|||||||
|
|
||||||
<!-- ===== Main column ===== -->
|
<!-- ===== Main column ===== -->
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<!-- memphis backdrop: polka dots + flat crayon washes -->
|
<!-- aurora backdrop: drifting gradient orbs + faint grain -->
|
||||||
<div aria-hidden="true" class="pointer-events-none absolute inset-0 overflow-hidden">
|
<div aria-hidden="true" class="pointer-events-none absolute inset-0 overflow-hidden">
|
||||||
<div class="memphis-dots absolute inset-0 opacity-60"></div>
|
<div class="memphis-dots absolute inset-0 opacity-50"></div>
|
||||||
<div class="absolute -top-32 left-1/3 w-[40rem] h-[40rem] rounded-full opacity-[0.22]"
|
<div class="absolute -top-40 left-1/4 w-[42rem] h-[42rem] rounded-full opacity-[0.5]"
|
||||||
style="background: radial-gradient(circle, #fef08a, transparent 60%); filter: blur(90px)"></div>
|
style="background: radial-gradient(circle, rgb(139 92 246 / 0.35), transparent 60%); filter: blur(100px)"></div>
|
||||||
<div class="absolute top-1/2 -right-40 w-[36rem] h-[36rem] rounded-full opacity-[0.18]"
|
<div class="absolute top-1/3 -right-48 w-[38rem] h-[38rem] rounded-full opacity-[0.45]"
|
||||||
style="background: radial-gradient(circle, #bae6fd, transparent 60%); filter: blur(90px)"></div>
|
style="background: radial-gradient(circle, rgb(34 211 238 / 0.3), transparent 60%); filter: blur(100px)"></div>
|
||||||
<div class="absolute bottom-0 left-0 w-[32rem] h-[32rem] rounded-full opacity-[0.16]"
|
<div class="absolute bottom-0 -left-24 w-[34rem] h-[34rem] rounded-full opacity-[0.4]"
|
||||||
style="background: radial-gradient(circle, #ffc1cc, transparent 60%); filter: blur(90px)"></div>
|
style="background: radial-gradient(circle, rgb(232 121 249 / 0.28), transparent 60%); filter: blur(100px)"></div>
|
||||||
<div class="anime-stars"></div>
|
<div class="anime-stars"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -196,8 +196,8 @@ async function onLogout() {
|
|||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.top-bar {
|
.top-bar {
|
||||||
background: color-mix(in srgb, var(--app-bg) 82%, transparent);
|
background: color-mix(in srgb, var(--app-bg) 62%, transparent);
|
||||||
border-bottom: 2.5px solid var(--ink);
|
border-bottom: 1px solid var(--ink-soft);
|
||||||
transition: border-color 0.2s ease;
|
transition: border-color 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,21 +208,17 @@ async function onLogout() {
|
|||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: var(--fg-2);
|
color: var(--fg-2);
|
||||||
background: transparent;
|
background: transparent;
|
||||||
border: 2px solid transparent;
|
border: 1px solid transparent;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: color 0.15s ease, background 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
|
transition: color 0.15s ease, background 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
|
||||||
}
|
}
|
||||||
.top-link:hover { color: var(--fg); background: var(--m-yellow); border-color: var(--ink); }
|
.top-link:hover { color: var(--fg); background: var(--hover); border-color: rgb(124 92 252 / 0.3); }
|
||||||
.top-link.on {
|
.top-link.on {
|
||||||
color: #111;
|
|
||||||
font-weight: 800;
|
|
||||||
background: var(--m-yellow);
|
|
||||||
border-color: var(--ink);
|
|
||||||
box-shadow: 3px 3px 0 var(--shadow-ink);
|
|
||||||
}
|
|
||||||
html.dark .top-link.on {
|
|
||||||
color: #fff;
|
color: #fff;
|
||||||
background: var(--m-orange);
|
font-weight: 700;
|
||||||
|
background: linear-gradient(120deg, #7c5cfc, #5f6cf8);
|
||||||
|
border-color: transparent;
|
||||||
|
box-shadow: 0 4px 14px var(--accent-glow);
|
||||||
}
|
}
|
||||||
|
|
||||||
.brand-spark {
|
.brand-spark {
|
||||||
@@ -245,19 +241,18 @@ html.dark .top-link.on {
|
|||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: var(--fg-2);
|
color: var(--fg-2);
|
||||||
background: transparent;
|
background: transparent;
|
||||||
border: 2px solid transparent;
|
border: 1px solid transparent;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: color 0.15s ease, background 0.15s ease, border-color 0.15s ease;
|
transition: color 0.15s ease, background 0.15s ease, border-color 0.15s ease;
|
||||||
}
|
}
|
||||||
.m-link:hover { color: var(--fg); background: var(--m-yellow); border-color: var(--ink); }
|
.m-link:hover { color: var(--fg); background: var(--hover); border-color: rgb(124 92 252 / 0.3); }
|
||||||
.m-link.m-on {
|
.m-link.m-on {
|
||||||
color: #111;
|
color: #fff;
|
||||||
font-weight: 800;
|
font-weight: 700;
|
||||||
background: var(--m-yellow);
|
background: linear-gradient(120deg, #7c5cfc, #5f6cf8);
|
||||||
border-color: var(--ink);
|
border-color: transparent;
|
||||||
box-shadow: 3px 3px 0 var(--shadow-ink);
|
box-shadow: 0 4px 14px var(--accent-glow);
|
||||||
}
|
}
|
||||||
html.dark .m-link.m-on { color: #fff; background: var(--m-orange); }
|
|
||||||
|
|
||||||
.round-btn {
|
.round-btn {
|
||||||
width: 2.125rem;
|
width: 2.125rem;
|
||||||
@@ -267,10 +262,12 @@ html.dark .m-link.m-on { color: #fff; background: var(--m-orange); }
|
|||||||
place-items: center;
|
place-items: center;
|
||||||
color: var(--fg-3);
|
color: var(--fg-3);
|
||||||
background: var(--surface);
|
background: var(--surface);
|
||||||
border: 2px solid var(--ink);
|
-webkit-backdrop-filter: blur(10px);
|
||||||
transition: color 0.15s ease, background 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease;
|
backdrop-filter: blur(10px);
|
||||||
|
border: 1px solid var(--ink-soft);
|
||||||
|
transition: color 0.15s ease, background 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease, border-color 0.15s ease;
|
||||||
}
|
}
|
||||||
.round-btn:hover { color: #111; background: var(--m-yellow); box-shadow: 3px 3px 0 var(--shadow-ink); transform: translate(-1px, -1px); }
|
.round-btn:hover { color: var(--fg); background: var(--hover); border-color: rgb(124 92 252 / 0.4); box-shadow: 0 4px 14px rgb(124 92 252 / 0.16); transform: translateY(-1px); }
|
||||||
.round-btn:active { transform: scale(0.95) translateY(1px); box-shadow: none; }
|
.round-btn:active { transform: scale(0.95) translateY(1px); box-shadow: none; }
|
||||||
|
|
||||||
/* mobile-only: .round-btn's display:grid outranks Tailwind's md:hidden, so
|
/* mobile-only: .round-btn's display:grid outranks Tailwind's md:hidden, so
|
||||||
@@ -286,14 +283,14 @@ html.dark .m-link.m-on { color: #fff; background: var(--m-orange); }
|
|||||||
font-size: 13.5px;
|
font-size: 13.5px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
background: var(--m-orange);
|
background: linear-gradient(120deg, #7c5cfc, #5f6cf8 55%, #22d3ee 140%);
|
||||||
border: 2.5px solid var(--ink);
|
border: 1px solid rgb(255 255 255 / 0.16);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
box-shadow: 3px 3px 0 var(--shadow-ink);
|
box-shadow: 0 6px 18px var(--accent-glow);
|
||||||
transition: transform 0.15s ease, filter 0.15s ease, box-shadow 0.15s ease;
|
transition: transform 0.15s ease, filter 0.15s ease, box-shadow 0.15s ease;
|
||||||
}
|
}
|
||||||
.solid-btn:hover { filter: brightness(1.06); transform: translate(-1px, -1px); box-shadow: 5px 5px 0 var(--shadow-ink); }
|
.solid-btn:hover { filter: brightness(1.07); transform: translateY(-1px); box-shadow: 0 10px 26px var(--accent-glow); }
|
||||||
.solid-btn:active { transform: scale(0.97) translateY(2px); box-shadow: 0 0 0 var(--shadow-ink); }
|
.solid-btn:active { transform: scale(0.97) translateY(1px); box-shadow: 0 3px 10px var(--accent-glow); }
|
||||||
|
|
||||||
.name-btn {
|
.name-btn {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
@@ -303,18 +300,21 @@ html.dark .m-link.m-on { color: #fff; background: var(--m-orange); }
|
|||||||
height: 2.125rem;
|
height: 2.125rem;
|
||||||
padding: 0 0.7rem 0 0.85rem;
|
padding: 0 0.7rem 0 0.85rem;
|
||||||
border-radius: 0.6rem;
|
border-radius: 0.6rem;
|
||||||
border: 2px solid var(--ink);
|
border: 1px solid var(--ink-soft);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: var(--fg);
|
color: var(--fg);
|
||||||
background: var(--surface);
|
background: var(--surface);
|
||||||
transition: background 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease;
|
-webkit-backdrop-filter: blur(10px);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
transition: background 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease, border-color 0.15s ease;
|
||||||
}
|
}
|
||||||
.name-btn:hover {
|
.name-btn:hover {
|
||||||
background: var(--m-yellow);
|
background: var(--hover);
|
||||||
box-shadow: 3px 3px 0 var(--shadow-ink);
|
border-color: rgb(124 92 252 / 0.4);
|
||||||
transform: translate(-1px, -1px);
|
box-shadow: 0 4px 14px rgb(124 92 252 / 0.16);
|
||||||
|
transform: translateY(-1px);
|
||||||
}
|
}
|
||||||
.name-txt {
|
.name-txt {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -328,10 +328,12 @@ html.dark .m-link.m-on { color: #fff; background: var(--m-orange); }
|
|||||||
top: 2.75rem;
|
top: 2.75rem;
|
||||||
width: 11.5rem;
|
width: 11.5rem;
|
||||||
padding: 0.4rem;
|
padding: 0.4rem;
|
||||||
border-radius: 0.75rem;
|
border-radius: 0.85rem;
|
||||||
background: var(--menu-bg);
|
background: var(--menu-bg);
|
||||||
border: 2.5px solid var(--ink);
|
-webkit-backdrop-filter: blur(18px);
|
||||||
box-shadow: 6px 6px 0 var(--shadow-ink);
|
backdrop-filter: blur(18px);
|
||||||
|
border: 1px solid var(--glass-border);
|
||||||
|
box-shadow: var(--glass-shadow-lg);
|
||||||
z-index: 50;
|
z-index: 50;
|
||||||
}
|
}
|
||||||
.menu-item {
|
.menu-item {
|
||||||
@@ -345,8 +347,8 @@ html.dark .m-link.m-on { color: #fff; background: var(--m-orange); }
|
|||||||
border: none;
|
border: none;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.menu-item:hover { background: var(--m-yellow); color: #111; }
|
.menu-item:hover { background: var(--hover); color: var(--fg); }
|
||||||
.menu-sep { height: 2px; background: var(--ink); opacity: 0.15; margin: 0.35rem 0.25rem; }
|
.menu-sep { height: 1px; background: var(--hairline); margin: 0.35rem 0.25rem; }
|
||||||
|
|
||||||
.fade-enter-active, .fade-leave-active { transition: opacity 0.2s ease, transform 0.2s ease; }
|
.fade-enter-active, .fade-leave-active { transition: opacity 0.2s ease, transform 0.2s ease; }
|
||||||
.fade-enter-from { opacity: 0; transform: translateY(8px); }
|
.fade-enter-from { opacity: 0; transform: translateY(8px); }
|
||||||
|
|||||||
+242
-191
@@ -9,72 +9,95 @@ video {
|
|||||||
|
|
||||||
:root {
|
:root {
|
||||||
font-family: "Inter", ui-sans-serif, system-ui, -apple-system, "PingFang SC", "Microsoft YaHei", sans-serif;
|
font-family: "Inter", ui-sans-serif, system-ui, -apple-system, "PingFang SC", "Microsoft YaHei", sans-serif;
|
||||||
--tw-ring-color: rgb(17 17 17 / 0.12);
|
--tw-ring-color: rgb(124 92 252 / 0.25);
|
||||||
|
|
||||||
/* ===== Theme palette — LIGHT (default): Memphis / neo-brutalism =====
|
/* ===== Theme palette — LIGHT (default): frosted glass / aurora =====
|
||||||
Drives the app chrome (rails/header) and the public marketing pages.
|
Drives the app chrome (rails/header) and the public marketing pages.
|
||||||
The `.dark` class on <html> flips these to the dark values below.
|
The `.dark` class on <html> flips these to the dark values below.
|
||||||
Text over generated images keeps a literal text-white (handled in markup). */
|
Text over generated images keeps a literal text-white (handled in markup). */
|
||||||
--app-bg: #f8f6f2; /* warm paper */
|
--app-bg: #eef0f8; /* cool porcelain */
|
||||||
--fg: #1a1a1a; /* primary heading/text */
|
--fg: #181524; /* primary heading/text */
|
||||||
--fg-2: rgb(26 26 26 / 0.64); /* body / secondary */
|
--fg-2: rgb(24 21 36 / 0.66); /* body / secondary */
|
||||||
--fg-3: rgb(26 26 26 / 0.48); /* muted */
|
--fg-3: rgb(24 21 36 / 0.48); /* muted */
|
||||||
--fg-faint: rgb(26 26 26 / 0.34); /* labels / hints */
|
--fg-faint: rgb(24 21 36 / 0.36); /* labels / hints */
|
||||||
--surface: #ffffff; /* raised card on page bg */
|
--surface: rgb(255 255 255 / 0.66); /* frosted card on page bg */
|
||||||
--surface-2: rgb(26 26 26 / 0.045); /* subtle inset panel (counter cells) */
|
--surface-solid: #ffffff; /* opaque version where blur is unwanted */
|
||||||
--hairline: rgb(26 26 26 / 0.12); /* faint borders / separators */
|
--surface-2: rgb(24 21 36 / 0.045); /* subtle inset panel (counter cells) */
|
||||||
--hover: rgb(254 240 138 / 0.55); /* hover wash — memphis yellow tint */
|
--hairline: rgb(24 21 36 / 0.1); /* faint borders / separators */
|
||||||
/* ink = the heavy outline color; shadow-ink = the offset "chunky" shadow */
|
--hover: rgb(124 92 252 / 0.1); /* hover wash — violet tint */
|
||||||
--ink: #111111;
|
/* ink = the hairline edge color; shadow-ink = the soft shadow tint.
|
||||||
--ink-soft: rgb(17 17 17 / 0.45);
|
Kept under their legacy names so existing markup keeps working — only the
|
||||||
--shadow-ink: #111111;
|
values changed from memphis-solid to glass-subtle. */
|
||||||
/* memphis accent crayons */
|
--ink: rgb(24 21 36 / 0.14);
|
||||||
--m-orange: #ec5b13;
|
--ink-soft: rgb(24 21 36 / 0.09);
|
||||||
--m-yellow: #fef08a;
|
--shadow-ink: rgb(88 80 200 / 0.14);
|
||||||
--m-pink: #ffc1cc;
|
/* aurora accent crayons — primary violet + soft pastel companions */
|
||||||
--m-blue: #bae6fd;
|
--m-orange: #7c5cfc;
|
||||||
--m-mint: #a7f3d0;
|
--m-orange-2: #22d3ee;
|
||||||
|
--m-yellow: #ece7fe;
|
||||||
|
--m-pink: #fad9f0;
|
||||||
|
--m-blue: #d8eefb;
|
||||||
|
--m-mint: #d9f4e8;
|
||||||
/* solid CTA button that sits on the page bg — inverts per theme */
|
/* solid CTA button that sits on the page bg — inverts per theme */
|
||||||
--btn-solid-bg: #1a1a1a;
|
--btn-solid-bg: #181524;
|
||||||
--btn-solid-bg-h: #000000;
|
--btn-solid-bg-h: #000000;
|
||||||
--btn-solid-fg: #fff;
|
--btn-solid-fg: #fff;
|
||||||
--menu-bg: #ffffff; /* dropdown / popover panel */
|
--menu-bg: rgb(255 255 255 / 0.82); /* dropdown / popover panel */
|
||||||
|
/* shared glass treatments */
|
||||||
|
--glass-border: rgb(255 255 255 / 0.55);
|
||||||
|
--glass-shadow: 0 8px 28px rgb(80 74 190 / 0.1), 0 2px 8px rgb(24 21 36 / 0.05);
|
||||||
|
--glass-shadow-lg: 0 16px 44px rgb(80 74 190 / 0.16), 0 4px 12px rgb(24 21 36 / 0.06);
|
||||||
|
--accent-glow: rgb(124 92 252 / 0.35);
|
||||||
}
|
}
|
||||||
|
|
||||||
html.dark {
|
html.dark {
|
||||||
--app-bg: #131318;
|
--app-bg: #08070f;
|
||||||
--fg: rgb(255 255 255 / 0.92);
|
--fg: rgb(255 255 255 / 0.93);
|
||||||
--fg-2: rgb(255 255 255 / 0.55);
|
--fg-2: rgb(255 255 255 / 0.6);
|
||||||
--fg-3: rgb(255 255 255 / 0.4);
|
--fg-3: rgb(255 255 255 / 0.42);
|
||||||
--fg-faint: rgb(255 255 255 / 0.3);
|
--fg-faint: rgb(255 255 255 / 0.3);
|
||||||
--surface: rgb(255 255 255 / 0.05);
|
--surface: rgb(255 255 255 / 0.05);
|
||||||
|
--surface-solid: #14131f;
|
||||||
--surface-2: rgb(255 255 255 / 0.05);
|
--surface-2: rgb(255 255 255 / 0.05);
|
||||||
--hairline: rgb(255 255 255 / 0.1);
|
--hairline: rgb(255 255 255 / 0.1);
|
||||||
--hover: rgb(236 91 19 / 0.2);
|
--hover: rgb(139 92 246 / 0.16);
|
||||||
--ink: rgb(244 244 245 / 0.85);
|
--ink: rgb(255 255 255 / 0.14);
|
||||||
--ink-soft: rgb(244 244 245 / 0.4);
|
--ink-soft: rgb(255 255 255 / 0.09);
|
||||||
--shadow-ink: rgb(244 244 245 / 0.22);
|
--shadow-ink: rgb(0 0 0 / 0.4);
|
||||||
--btn-solid-bg: #ec5b13;
|
--m-orange: #8b5cf6;
|
||||||
--btn-solid-bg-h: #f97316;
|
--m-orange-2: #22d3ee;
|
||||||
|
--m-yellow: #a78bfa;
|
||||||
|
--m-pink: #f0a6d8;
|
||||||
|
--m-blue: #6cd0f2;
|
||||||
|
--m-mint: #5fd9ac;
|
||||||
|
--btn-solid-bg: #8b5cf6;
|
||||||
|
--btn-solid-bg-h: #7c3aed;
|
||||||
--btn-solid-fg: #fff;
|
--btn-solid-fg: #fff;
|
||||||
--menu-bg: #1d1e26;
|
--menu-bg: rgb(24 23 36 / 0.86);
|
||||||
|
--glass-border: rgb(255 255 255 / 0.12);
|
||||||
|
--glass-shadow: 0 8px 28px rgb(0 0 0 / 0.35), 0 2px 8px rgb(0 0 0 / 0.2);
|
||||||
|
--glass-shadow-lg: 0 18px 50px rgb(0 0 0 / 0.5), 0 4px 14px rgb(0 0 0 / 0.3);
|
||||||
|
--accent-glow: rgb(139 92 246 / 0.45);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Smooth the flip so toggling doesn't hard-cut. */
|
/* Smooth the flip so toggling doesn't hard-cut. */
|
||||||
body, .theme-x { transition: background-color 0.25s ease, color 0.25s ease; }
|
body, .theme-x { transition: background-color 0.25s ease, color 0.25s ease; }
|
||||||
|
|
||||||
/* Footer CTA band — flat memphis-yellow panel with a heavy ink outline. */
|
/* Footer CTA band — aurora gradient panel with a glass edge. */
|
||||||
.cta-band {
|
.cta-band {
|
||||||
|
position: relative;
|
||||||
background:
|
background:
|
||||||
radial-gradient(circle, rgb(17 17 17 / 0.1) 1.3px, transparent 1.3px) 0 0 / 20px 20px,
|
radial-gradient(120% 160% at 0% 0%, rgb(124 92 252 / 0.2), transparent 55%),
|
||||||
var(--m-yellow);
|
radial-gradient(120% 160% at 100% 100%, rgb(34 211 238 / 0.16), transparent 55%),
|
||||||
border: 3px solid var(--ink);
|
var(--surface);
|
||||||
box-shadow: 10px 10px 0 var(--shadow-ink);
|
border: 1px solid var(--glass-border);
|
||||||
|
box-shadow: var(--glass-shadow-lg);
|
||||||
}
|
}
|
||||||
html.dark .cta-band {
|
html.dark .cta-band {
|
||||||
background:
|
background:
|
||||||
radial-gradient(circle, rgb(255 255 255 / 0.1) 1.3px, transparent 1.3px) 0 0 / 20px 20px,
|
radial-gradient(120% 160% at 0% 0%, rgb(139 92 246 / 0.22), transparent 55%),
|
||||||
rgb(236 91 19 / 0.16);
|
radial-gradient(120% 160% at 100% 100%, rgb(34 211 238 / 0.14), transparent 55%),
|
||||||
|
rgb(255 255 255 / 0.04);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ===== Light-mode rescue for hardcoded-dark pages =====
|
/* ===== Light-mode rescue for hardcoded-dark pages =====
|
||||||
@@ -83,10 +106,10 @@ html.dark .cta-band {
|
|||||||
LIGHT mode, remap those neutral whites to the dark-on-light palette. Scoped
|
LIGHT mode, remap those neutral whites to the dark-on-light palette. Scoped
|
||||||
to a `.theme-text` wrapper so the marketing homepage's over-image whites are
|
to a `.theme-text` wrapper so the marketing homepage's over-image whites are
|
||||||
never touched. Un-layered, so these win over Tailwind's @layer utilities. */
|
never touched. Un-layered, so these win over Tailwind's @layer utilities. */
|
||||||
html:not(.dark) .theme-text :is(.text-white, [class*="text-white/9"], [class*="text-white/8"]) { color: rgb(15 23 42 / 0.95); }
|
html:not(.dark) .theme-text :is(.text-white, [class*="text-white/9"], [class*="text-white/8"]) { color: rgb(24 21 36 / 0.95); }
|
||||||
html:not(.dark) .theme-text :is([class*="text-white/7"], [class*="text-white/6"]) { color: rgb(15 23 42 / 0.7); }
|
html:not(.dark) .theme-text :is([class*="text-white/7"], [class*="text-white/6"]) { color: rgb(24 21 36 / 0.7); }
|
||||||
html:not(.dark) .theme-text :is([class*="text-white/5"], [class*="text-white/4"]) { color: rgb(15 23 42 / 0.52); }
|
html:not(.dark) .theme-text :is([class*="text-white/5"], [class*="text-white/4"]) { color: rgb(24 21 36 / 0.52); }
|
||||||
html:not(.dark) .theme-text :is([class*="text-white/3"], [class*="text-white/2"], [class*="text-white/1"]) { color: rgb(15 23 42 / 0.4); }
|
html:not(.dark) .theme-text :is([class*="text-white/3"], [class*="text-white/2"], [class*="text-white/1"]) { color: rgb(24 21 36 / 0.4); }
|
||||||
html:not(.dark) .theme-text [class*="bg-white/"] { background-color: var(--surface-2); }
|
html:not(.dark) .theme-text [class*="bg-white/"] { background-color: var(--surface-2); }
|
||||||
html:not(.dark) .theme-text [class*="border-white/"] { border-color: var(--hairline); }
|
html:not(.dark) .theme-text [class*="border-white/"] { border-color: var(--hairline); }
|
||||||
html:not(.dark) .theme-text [class*="ring-white/"] { --tw-ring-color: var(--hairline); }
|
html:not(.dark) .theme-text [class*="ring-white/"] { --tw-ring-color: var(--hairline); }
|
||||||
@@ -102,7 +125,7 @@ html:not(.dark) .theme-text :is([class*="bg-slate-900"], [class*="bg-slate-800"]
|
|||||||
matcher also catches the /80 opacity variants. Badges keep their pale tinted
|
matcher also catches the /80 opacity variants. Badges keep their pale tinted
|
||||||
bg (bg-*-500/10) which reads fine on white. */
|
bg (bg-*-500/10) which reads fine on white. */
|
||||||
html:not(.dark) .theme-text :is([class*="text-sky-300"], [class*="text-sky-200"]) { color: rgb(79 70 229); }
|
html:not(.dark) .theme-text :is([class*="text-sky-300"], [class*="text-sky-200"]) { color: rgb(79 70 229); }
|
||||||
html:not(.dark) .theme-text :is([class*="text-orange-300"], [class*="text-orange-200"]) { color: rgb(234 88 12); }
|
html:not(.dark) .theme-text :is([class*="text-orange-300"], [class*="text-orange-200"]) { color: rgb(124 58 237); }
|
||||||
html:not(.dark) .theme-text :is([class*="text-rose-300"], [class*="text-rose-200"]) { color: rgb(225 29 72); }
|
html:not(.dark) .theme-text :is([class*="text-rose-300"], [class*="text-rose-200"]) { color: rgb(225 29 72); }
|
||||||
html:not(.dark) .theme-text :is([class*="text-emerald-300"], [class*="text-emerald-200"]) { color: rgb(5 150 105); }
|
html:not(.dark) .theme-text :is([class*="text-emerald-300"], [class*="text-emerald-200"]) { color: rgb(5 150 105); }
|
||||||
html:not(.dark) .theme-text :is([class*="text-sky-300"], [class*="text-sky-200"]) { color: rgb(2 132 199); }
|
html:not(.dark) .theme-text :is([class*="text-sky-300"], [class*="text-sky-200"]) { color: rgb(2 132 199); }
|
||||||
@@ -120,17 +143,23 @@ html:not(.dark) .theme-text :is(.fp, .pg, .act, .filter-pill, .kind-btn, .preset
|
|||||||
html:not(.dark) .theme-text :is(.fp, .pg, .act, .filter-pill, .kind-btn, .preset-btn, .opt, .chip-x):hover {
|
html:not(.dark) .theme-text :is(.fp, .pg, .act, .filter-pill, .kind-btn, .preset-btn, .opt, .chip-x):hover {
|
||||||
color: var(--fg); background: var(--hover);
|
color: var(--fg); background: var(--hover);
|
||||||
}
|
}
|
||||||
html:not(.dark) .theme-text :is(.fp-on, .pg-on, .seg-on, .opt-on) { background: var(--fg); color: #fff; box-shadow: 2px 2px 0 var(--m-orange); }
|
html:not(.dark) .theme-text :is(.fp-on, .pg-on, .seg-on, .opt-on) {
|
||||||
|
background: linear-gradient(120deg, #7c5cfc, #5f6cf8); color: #fff;
|
||||||
|
box-shadow: 0 4px 16px var(--accent-glow);
|
||||||
|
}
|
||||||
/* Tag chips (TagInput) — near-white orange text is unreadable on white; keep
|
/* Tag chips (TagInput) — near-white orange text is unreadable on white; keep
|
||||||
the orange tint but switch the label to dark ink. */
|
the tint but switch the label to dark ink. */
|
||||||
html:not(.dark) .theme-text .chip { color: rgb(15 23 42 / 0.9); }
|
html:not(.dark) .theme-text .chip { color: rgb(24 21 36 / 0.9); }
|
||||||
html:not(.dark) .theme-text .chip .chip-x { color: rgb(15 23 42 / 0.55); background: transparent; box-shadow: none; }
|
html:not(.dark) .theme-text .chip .chip-x { color: rgb(24 21 36 / 0.55); background: transparent; box-shadow: none; }
|
||||||
html:not(.dark) .theme-text .chip .chip-x:hover { color: #fff; background: rgb(244 63 94 / 0.6); }
|
html:not(.dark) .theme-text .chip .chip-x:hover { color: #fff; background: rgb(244 63 94 / 0.6); }
|
||||||
/* ShowcaseView marks the selected filter/kind tab with an `.on` modifier on
|
/* ShowcaseView marks the selected filter/kind tab with an `.on` modifier on
|
||||||
`.filter-pill`/`.kind-btn` (not the `-on` class above). Without this, the
|
`.filter-pill`/`.kind-btn` (not the `-on` class above). Without this, the
|
||||||
neutral `.filter-pill`/`.kind-btn` rescue paints selected == unselected and
|
neutral `.filter-pill`/`.kind-btn` rescue paints selected == unselected and
|
||||||
the highlight vanishes on a white page. Equal-or-higher specificity, later. */
|
the highlight vanishes on a white page. Equal-or-higher specificity, later. */
|
||||||
html:not(.dark) .theme-text :is(.filter-pill, .kind-btn).on { background: var(--fg); color: #fff; box-shadow: 2px 2px 0 var(--m-orange); }
|
html:not(.dark) .theme-text :is(.filter-pill, .kind-btn).on {
|
||||||
|
background: linear-gradient(120deg, #7c5cfc, #5f6cf8); color: #fff;
|
||||||
|
box-shadow: 0 4px 16px var(--accent-glow);
|
||||||
|
}
|
||||||
/* Selected COLORED filter pills — their scoped (dark) selected colors get
|
/* Selected COLORED filter pills — their scoped (dark) selected colors get
|
||||||
overridden by the neutral `.fp` rescue above, so re-state a light-mode
|
overridden by the neutral `.fp` rescue above, so re-state a light-mode
|
||||||
variant (tinted bg + dark-enough text + colored ring) with equal specificity
|
variant (tinted bg + dark-enough text + colored ring) with equal specificity
|
||||||
@@ -138,16 +167,14 @@ html:not(.dark) .theme-text :is(.filter-pill, .kind-btn).on { background: var(--
|
|||||||
html:not(.dark) .theme-text .fp-emerald { background: rgb(16 185 129 / 0.14); color: rgb(4 120 87); box-shadow: inset 0 0 0 1px rgb(16 185 129 / 0.45); }
|
html:not(.dark) .theme-text .fp-emerald { background: rgb(16 185 129 / 0.14); color: rgb(4 120 87); box-shadow: inset 0 0 0 1px rgb(16 185 129 / 0.45); }
|
||||||
html:not(.dark) .theme-text .fp-rose { background: rgb(244 63 94 / 0.12); color: rgb(190 18 60); box-shadow: inset 0 0 0 1px rgb(244 63 94 / 0.45); }
|
html:not(.dark) .theme-text .fp-rose { background: rgb(244 63 94 / 0.12); color: rgb(190 18 60); box-shadow: inset 0 0 0 1px rgb(244 63 94 / 0.45); }
|
||||||
html:not(.dark) .theme-text .fp-amber { background: rgb(245 158 11 / 0.16); color: rgb(180 83 9); box-shadow: inset 0 0 0 1px rgb(245 158 11 / 0.5); }
|
html:not(.dark) .theme-text .fp-amber { background: rgb(245 158 11 / 0.16); color: rgb(180 83 9); box-shadow: inset 0 0 0 1px rgb(245 158 11 / 0.5); }
|
||||||
html:not(.dark) .theme-text .fp-orange { background: rgb(249 115 22 / 0.14); color: rgb(194 65 12); box-shadow: inset 0 0 0 1px rgb(249 115 22 / 0.45); }
|
html:not(.dark) .theme-text .fp-orange { background: rgb(139 92 246 / 0.14); color: rgb(109 40 217); box-shadow: inset 0 0 0 1px rgb(139 92 246 / 0.45); }
|
||||||
html:not(.dark) .theme-text .fp-pink { background: rgb(244 114 182 / 0.14); color: rgb(190 24 93); box-shadow: inset 0 0 0 1px rgb(244 114 182 / 0.45); }
|
html:not(.dark) .theme-text .fp-pink { background: rgb(244 114 182 / 0.14); color: rgb(190 24 93); box-shadow: inset 0 0 0 1px rgb(244 114 182 / 0.45); }
|
||||||
html:not(.dark) .theme-text .fp-slate { background: rgb(100 116 139 / 0.14); color: rgb(51 65 85); box-shadow: inset 0 0 0 1px rgb(100 116 139 / 0.45); }
|
html:not(.dark) .theme-text .fp-slate { background: rgb(100 116 139 / 0.14); color: rgb(51 65 85); box-shadow: inset 0 0 0 1px rgb(100 116 139 / 0.45); }
|
||||||
html:not(.dark) .theme-text .fp-sky { background: rgb(14 165 233 / 0.14); color: rgb(3 105 161); box-shadow: inset 0 0 0 1px rgb(14 165 233 / 0.45); }
|
html:not(.dark) .theme-text .fp-sky { background: rgb(14 165 233 / 0.14); color: rgb(3 105 161); box-shadow: inset 0 0 0 1px rgb(14 165 233 / 0.45); }
|
||||||
html:not(.dark) .theme-text .fp-teal { background: rgb(20 184 166 / 0.14); color: rgb(15 118 110); box-shadow: inset 0 0 0 1px rgb(20 184 166 / 0.45); }
|
html:not(.dark) .theme-text .fp-teal { background: rgb(20 184 166 / 0.14); color: rgb(15 118 110); box-shadow: inset 0 0 0 1px rgb(20 184 166 / 0.45); }
|
||||||
|
|
||||||
/* Custom checkbox for admin tables (<input type="checkbox" class="chk">).
|
/* Custom checkbox for admin tables (<input type="checkbox" class="chk">).
|
||||||
Replaces the plain accent-color box with a rounded, branded one + white check.
|
Rounded glass box + white check; fills with the violet gradient when on. */
|
||||||
Neutral border + transparent bg so it reads on both the dark admin shell and
|
|
||||||
light mode; fills rose when checked. */
|
|
||||||
.chk {
|
.chk {
|
||||||
appearance: none;
|
appearance: none;
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
@@ -161,14 +188,14 @@ html:not(.dark) .theme-text .fp-teal { background: rgb(20 184 166 / 0.14); color
|
|||||||
display: inline-grid;
|
display: inline-grid;
|
||||||
place-content: center;
|
place-content: center;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
transition: background 0.15s, border-color 0.15s;
|
transition: background 0.15s, border-color 0.15s, box-shadow 0.15s;
|
||||||
}
|
}
|
||||||
.chk { border-color: var(--ink-soft); }
|
.chk { border-color: var(--ink); }
|
||||||
.chk:hover:not(:checked) { border-color: var(--m-orange); }
|
.chk:hover:not(:checked) { border-color: var(--m-orange); }
|
||||||
.chk:checked {
|
.chk:checked {
|
||||||
background: var(--m-orange);
|
background: linear-gradient(135deg, #7c5cfc, #22d3ee);
|
||||||
border-color: var(--ink);
|
border-color: transparent;
|
||||||
box-shadow: 2px 2px 0 var(--shadow-ink);
|
box-shadow: 0 2px 10px var(--accent-glow);
|
||||||
}
|
}
|
||||||
.chk:checked::after {
|
.chk:checked::after {
|
||||||
content: "";
|
content: "";
|
||||||
@@ -179,7 +206,7 @@ html:not(.dark) .theme-text .fp-teal { background: rgb(20 184 166 / 0.14); color
|
|||||||
transform: rotate(45deg);
|
transform: rotate(45deg);
|
||||||
margin-top: -0.12rem;
|
margin-top: -0.12rem;
|
||||||
}
|
}
|
||||||
.chk:focus-visible { outline: 2px solid rgb(236 91 19 / 0.5); outline-offset: 1px; }
|
.chk:focus-visible { outline: 2px solid rgb(124 92 252 / 0.5); outline-offset: 1px; }
|
||||||
/* Account identity tags (AccountsView: 子号 / 母号 / 普号 / 限额). The colors live
|
/* Account identity tags (AccountsView: 子号 / 母号 / 普号 / 限额). The colors live
|
||||||
here rather than as inline dark-palette utilities, which were invisible on the
|
here rather than as inline dark-palette utilities, which were invisible on the
|
||||||
light theme: light values first, html.dark override after. */
|
light theme: light values first, html.dark override after. */
|
||||||
@@ -195,11 +222,11 @@ html:not(.dark) .theme-text .fp-teal { background: rgb(20 184 166 / 0.14); color
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
.acct-tag-sub { background: rgb(14 165 233 / 0.14); color: rgb(3 105 161); box-shadow: inset 0 0 0 1px rgb(14 165 233 / 0.4); }
|
.acct-tag-sub { background: rgb(14 165 233 / 0.14); color: rgb(3 105 161); box-shadow: inset 0 0 0 1px rgb(14 165 233 / 0.4); }
|
||||||
.acct-tag-master { background: rgb(249 115 22 / 0.14); color: rgb(194 65 12); box-shadow: inset 0 0 0 1px rgb(249 115 22 / 0.4); }
|
.acct-tag-master { background: rgb(139 92 246 / 0.14); color: rgb(109 40 217); box-shadow: inset 0 0 0 1px rgb(139 92 246 / 0.4); }
|
||||||
.acct-tag-free { background: rgb(100 116 139 / 0.14); color: rgb(51 65 85); box-shadow: inset 0 0 0 1px rgb(100 116 139 / 0.4); }
|
.acct-tag-free { background: rgb(100 116 139 / 0.14); color: rgb(51 65 85); box-shadow: inset 0 0 0 1px rgb(100 116 139 / 0.4); }
|
||||||
.acct-tag-limit { background: rgb(245 158 11 / 0.16); color: rgb(180 83 9); box-shadow: inset 0 0 0 1px rgb(245 158 11 / 0.4); }
|
.acct-tag-limit { background: rgb(245 158 11 / 0.16); color: rgb(180 83 9); box-shadow: inset 0 0 0 1px rgb(245 158 11 / 0.4); }
|
||||||
html.dark .acct-tag-sub { background: rgb(14 165 233 / 0.18); color: rgb(125 211 252); box-shadow: inset 0 0 0 1px rgb(56 189 248 / 0.35); }
|
html.dark .acct-tag-sub { background: rgb(14 165 233 / 0.18); color: rgb(125 211 252); box-shadow: inset 0 0 0 1px rgb(56 189 248 / 0.35); }
|
||||||
html.dark .acct-tag-master { background: rgb(249 115 22 / 0.22); color: rgb(253 186 116); box-shadow: inset 0 0 0 1px rgb(253 186 116 / 0.35); }
|
html.dark .acct-tag-master { background: rgb(139 92 246 / 0.22); color: rgb(196 181 253); box-shadow: inset 0 0 0 1px rgb(167 139 250 / 0.35); }
|
||||||
html.dark .acct-tag-free { background: rgb(148 163 184 / 0.22); color: rgb(226 232 240); box-shadow: inset 0 0 0 1px rgb(148 163 184 / 0.35); }
|
html.dark .acct-tag-free { background: rgb(148 163 184 / 0.22); color: rgb(226 232 240); box-shadow: inset 0 0 0 1px rgb(148 163 184 / 0.35); }
|
||||||
html.dark .acct-tag-limit { background: rgb(245 158 11 / 0.18); color: rgb(252 211 77); box-shadow: inset 0 0 0 1px rgb(251 191 36 / 0.35); }
|
html.dark .acct-tag-limit { background: rgb(245 158 11 / 0.18); color: rgb(252 211 77); box-shadow: inset 0 0 0 1px rgb(251 191 36 / 0.35); }
|
||||||
/* Capability chips (ModelsView): all variants need bg + ring + color reset in light mode.
|
/* Capability chips (ModelsView): all variants need bg + ring + color reset in light mode.
|
||||||
@@ -224,7 +251,7 @@ html:not(.dark) .theme-text .price-chip {
|
|||||||
background: var(--surface-2);
|
background: var(--surface-2);
|
||||||
box-shadow: inset 0 0 0 1px var(--hairline);
|
box-shadow: inset 0 0 0 1px var(--hairline);
|
||||||
}
|
}
|
||||||
/* fp-white selected pill: on white bg the all-white fill vanishes — use a neutral dark variant. */
|
/* fp-white selected pill: on white bg the all-white fill vanishes — use a neutral variant. */
|
||||||
html:not(.dark) .theme-text .fp-white {
|
html:not(.dark) .theme-text .fp-white {
|
||||||
background: var(--surface-2);
|
background: var(--surface-2);
|
||||||
color: var(--fg-2);
|
color: var(--fg-2);
|
||||||
@@ -256,7 +283,7 @@ html:not(.dark) .media-card :is([class*="border-white/"], [class*="ring-white/"]
|
|||||||
html:not(.dark) .media-card :is([class*="text-emerald-3"], [class*="text-emerald-2"]) { color: rgb(110 231 183) !important; }
|
html:not(.dark) .media-card :is([class*="text-emerald-3"], [class*="text-emerald-2"]) { color: rgb(110 231 183) !important; }
|
||||||
html:not(.dark) .media-card :is([class*="text-rose-3"], [class*="text-rose-2"]) { color: rgb(251 207 232) !important; }
|
html:not(.dark) .media-card :is([class*="text-rose-3"], [class*="text-rose-2"]) { color: rgb(251 207 232) !important; }
|
||||||
html:not(.dark) .media-card :is([class*="text-sky-3"], [class*="text-sky-2"]) { color: rgb(147 197 253) !important; }
|
html:not(.dark) .media-card :is([class*="text-sky-3"], [class*="text-sky-2"]) { color: rgb(147 197 253) !important; }
|
||||||
html:not(.dark) .media-card :is([class*="text-orange-3"], [class*="text-orange-2"]) { color: rgb(253 186 116) !important; }
|
html:not(.dark) .media-card :is([class*="text-orange-3"], [class*="text-orange-2"]) { color: rgb(196 181 253) !important; }
|
||||||
html:not(.dark) .media-card :is([class*="text-sky-3"], [class*="text-sky-2"]) { color: rgb(125 211 252) !important; }
|
html:not(.dark) .media-card :is([class*="text-sky-3"], [class*="text-sky-2"]) { color: rgb(125 211 252) !important; }
|
||||||
html:not(.dark) .media-card :is([class*="text-amber-3"], [class*="text-amber-2"]) { color: rgb(252 211 77) !important; }
|
html:not(.dark) .media-card :is([class*="text-amber-3"], [class*="text-amber-2"]) { color: rgb(252 211 77) !important; }
|
||||||
|
|
||||||
@@ -271,8 +298,8 @@ html:not(.dark) .doc-code code { background: rgb(255 255 255 / 0.08); color: rgb
|
|||||||
html {
|
html {
|
||||||
scroll-behavior: smooth;
|
scroll-behavior: smooth;
|
||||||
/* Kill the bounce/glow when scrolling past the top or bottom of any
|
/* Kill the bounce/glow when scrolling past the top or bottom of any
|
||||||
scroll surface (the dark admin shell has fixed viewport height and we
|
scroll surface (the dark admin shell has fixed viewport height and we
|
||||||
don't want a rubber-band-y feel at the edges of inner scroll areas). */
|
don't want a rubber-band-y feel at the edges of inner scroll areas). */
|
||||||
overscroll-behavior: none;
|
overscroll-behavior: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,10 +308,11 @@ body {
|
|||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
text-rendering: optimizeLegibility;
|
text-rendering: optimizeLegibility;
|
||||||
overscroll-behavior: none;
|
overscroll-behavior: none;
|
||||||
/* Subtle ambient gradient + grain (used by PublicLayout via .ambient-bg) */
|
/* Aurora ambient gradient + grain (used by PublicLayout via .ambient-bg) */
|
||||||
}
|
}
|
||||||
|
|
||||||
::selection { background: var(--m-yellow); color: #111; }
|
::selection { background: rgb(139 92 246 / 0.32); color: inherit; }
|
||||||
|
html:not(.dark) ::selection { color: #181524; }
|
||||||
|
|
||||||
/* Tailwind v4 / preflight leaves <button> on the default arrow cursor, so
|
/* Tailwind v4 / preflight leaves <button> on the default arrow cursor, so
|
||||||
admins miss the affordance on icon-only actions (复制 / 删除 / 生成 等).
|
admins miss the affordance on icon-only actions (复制 / 删除 / 生成 等).
|
||||||
@@ -300,36 +328,45 @@ button:not(:disabled), [role="button"]:not([aria-disabled="true"]) { cursor: poi
|
|||||||
.card:has(> table) { overflow-x: auto; }
|
.card:has(> table) { overflow-x: auto; }
|
||||||
|
|
||||||
::-webkit-scrollbar { width: 9px; height: 9px; }
|
::-webkit-scrollbar { width: 9px; height: 9px; }
|
||||||
::-webkit-scrollbar-thumb { background: rgb(26 26 26 / 0.28); border-radius: 5px; border: 2px solid transparent; background-clip: content-box; }
|
::-webkit-scrollbar-thumb { background: rgb(24 21 36 / 0.2); border-radius: 5px; border: 2px solid transparent; background-clip: content-box; }
|
||||||
::-webkit-scrollbar-thumb:hover { background: rgb(26 26 26 / 0.45); background-clip: content-box; }
|
::-webkit-scrollbar-thumb:hover { background: rgb(24 21 36 / 0.38); background-clip: content-box; }
|
||||||
::-webkit-scrollbar-track { background: transparent; }
|
::-webkit-scrollbar-track { background: transparent; }
|
||||||
html.dark ::-webkit-scrollbar-thumb { background: rgb(255 255 255 / 0.22); background-clip: content-box; }
|
html.dark ::-webkit-scrollbar-thumb { background: rgb(255 255 255 / 0.18); background-clip: content-box; }
|
||||||
html.dark ::-webkit-scrollbar-thumb:hover { background: rgb(255 255 255 / 0.35); background-clip: content-box; }
|
html.dark ::-webkit-scrollbar-thumb:hover { background: rgb(255 255 255 / 0.32); background-clip: content-box; }
|
||||||
|
|
||||||
/* ===== Ambient background — used by the public shell ===== */
|
/* ===== Ambient background — aurora wash used by the public shell ===== */
|
||||||
.ambient-bg {
|
.ambient-bg {
|
||||||
background-color: var(--app-bg);
|
background-color: var(--app-bg);
|
||||||
background-image: radial-gradient(circle, rgb(17 17 17 / 0.07) 1.3px, transparent 1.3px);
|
background-image:
|
||||||
background-size: 22px 22px;
|
radial-gradient(60rem 40rem at 12% -10%, rgb(124 92 252 / 0.14), transparent 60%),
|
||||||
|
radial-gradient(52rem 36rem at 92% 8%, rgb(34 211 238 / 0.11), transparent 60%),
|
||||||
|
radial-gradient(46rem 32rem at 8% 96%, rgb(240 171 252 / 0.1), transparent 60%);
|
||||||
}
|
}
|
||||||
html.dark .ambient-bg {
|
html.dark .ambient-bg {
|
||||||
background-image: radial-gradient(circle, rgb(255 255 255 / 0.06) 1.3px, transparent 1.3px);
|
background-image:
|
||||||
|
radial-gradient(60rem 40rem at 12% -10%, rgb(139 92 246 / 0.2), transparent 60%),
|
||||||
|
radial-gradient(52rem 36rem at 92% 8%, rgb(34 211 238 / 0.13), transparent 60%),
|
||||||
|
radial-gradient(46rem 32rem at 8% 96%, rgb(232 121 249 / 0.1), transparent 60%);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ===== Memphis / neo-brutalist design kit =====
|
/* ===== Glass / aurora design kit =====
|
||||||
Heavy ink outlines, hard offset shadows, flat crayon accents (orange / yellow
|
Frosted surfaces, hairline edges, soft layered shadows and violet→cyan
|
||||||
/ pink / blue / mint), rotated stickers and squishy press feedback. Reusable
|
gradient accents. Same class names as the previous memphis kit so every
|
||||||
across the workbench + user subpages + public pages so the whole front-end
|
view picks the new look up without markup changes. */
|
||||||
shares one punchy, print-like look. */
|
|
||||||
|
|
||||||
/* Highlighter text — black words "marked" with a yellow swipe. */
|
/* Gradient headline text — violet → cyan swipe. */
|
||||||
.anime-grad-text {
|
.anime-grad-text {
|
||||||
background: linear-gradient(transparent 55%, var(--m-yellow) 55%);
|
background: linear-gradient(100deg, #7c5cfc 0%, #a855f7 45%, #22d3ee 100%);
|
||||||
padding: 0 0.1em;
|
-webkit-background-clip: text;
|
||||||
color: inherit;
|
background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
color: transparent;
|
||||||
|
padding: 0 0.05em;
|
||||||
}
|
}
|
||||||
html.dark .anime-grad-text {
|
html.dark .anime-grad-text {
|
||||||
background: linear-gradient(transparent 55%, rgb(236 91 19 / 0.55) 55%);
|
background: linear-gradient(100deg, #a78bfa 0%, #e879f9 45%, #67e8f9 100%);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
background-clip: text;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Section eyebrow — tiny uppercase kicker with a leading star. */
|
/* Section eyebrow — tiny uppercase kicker with a leading star. */
|
||||||
@@ -344,23 +381,24 @@ html.dark .anime-grad-text {
|
|||||||
}
|
}
|
||||||
.anime-eyebrow::before { content: '✦'; font-size: 0.85em; }
|
.anime-eyebrow::before { content: '✦'; font-size: 0.85em; }
|
||||||
|
|
||||||
/* Sticker label — rotated yellow chip with a hard shadow. */
|
/* Sticker label — glass chip with a soft glow. */
|
||||||
.sticker {
|
.sticker {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.3rem;
|
gap: 0.4rem;
|
||||||
padding: 0.3rem 0.75rem;
|
padding: 0.34rem 0.85rem;
|
||||||
border-radius: 0.55rem;
|
border-radius: 999px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 800;
|
font-weight: 700;
|
||||||
color: #111;
|
color: var(--fg);
|
||||||
background: var(--m-yellow);
|
background: var(--surface);
|
||||||
border: 2.5px solid var(--ink);
|
-webkit-backdrop-filter: blur(12px);
|
||||||
box-shadow: 4px 4px 0 var(--shadow-ink);
|
backdrop-filter: blur(12px);
|
||||||
transform: rotate(-1.5deg);
|
border: 1px solid var(--glass-border);
|
||||||
|
box-shadow: var(--glass-shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Chunky CTA — flat orange with an offset ink shadow and a press feel. */
|
/* Chunky CTA — violet→cyan gradient with a glow. */
|
||||||
.bubble-btn {
|
.bubble-btn {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -370,42 +408,37 @@ html.dark .anime-grad-text {
|
|||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
border: 2.5px solid var(--ink);
|
border: 1px solid rgb(255 255 255 / 0.18);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background: var(--m-orange);
|
background: linear-gradient(120deg, #7c5cfc, #5f6cf8 55%, #22d3ee);
|
||||||
box-shadow: 4px 4px 0 var(--shadow-ink);
|
box-shadow: 0 8px 24px var(--accent-glow);
|
||||||
transition: transform 0.15s ease, box-shadow 0.15s ease, filter 0.15s ease;
|
transition: transform 0.15s ease, box-shadow 0.15s ease, filter 0.15s ease;
|
||||||
}
|
}
|
||||||
.bubble-btn:hover { transform: translate(-2px, -2px); box-shadow: 6px 6px 0 var(--shadow-ink); filter: brightness(1.05); }
|
.bubble-btn:hover { transform: translateY(-2px); box-shadow: 0 12px 32px var(--accent-glow); filter: brightness(1.06); }
|
||||||
.bubble-btn:active { transform: scale(0.97) translateY(2px); box-shadow: 1px 1px 0 var(--shadow-ink); }
|
.bubble-btn:active { transform: scale(0.97) translateY(1px); box-shadow: 0 4px 12px var(--accent-glow); }
|
||||||
|
|
||||||
/* Memphis card — flat surface, heavy ink outline, hard offset shadow. */
|
/* Glass card — frosted surface, hairline edge, soft shadow. */
|
||||||
.anime-card {
|
.anime-card {
|
||||||
position: relative;
|
position: relative;
|
||||||
border-radius: 1rem;
|
border-radius: 1.1rem;
|
||||||
background: var(--surface);
|
background: var(--surface);
|
||||||
border: 2.5px solid var(--ink);
|
-webkit-backdrop-filter: blur(14px);
|
||||||
box-shadow: 5px 5px 0 var(--shadow-ink);
|
backdrop-filter: blur(14px);
|
||||||
|
border: 1px solid var(--glass-border);
|
||||||
|
box-shadow: var(--glass-shadow);
|
||||||
transition: transform 0.18s ease, box-shadow 0.18s ease;
|
transition: transform 0.18s ease, box-shadow 0.18s ease;
|
||||||
}
|
}
|
||||||
.anime-card:hover {
|
.anime-card:hover {
|
||||||
transform: translate(-2px, -2px);
|
transform: translateY(-3px);
|
||||||
box-shadow: 8px 8px 0 var(--shadow-ink);
|
box-shadow: var(--glass-shadow-lg);
|
||||||
}
|
|
||||||
html.dark .anime-card {
|
|
||||||
background: rgb(255 255 255 / 0.05);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Selected pill — solid ink with an orange offset shadow. */
|
/* Selected pill — gradient fill with a glow. */
|
||||||
.chip-on {
|
.chip-on {
|
||||||
color: #fff !important;
|
color: #fff !important;
|
||||||
background: #1a1a1a !important;
|
background: linear-gradient(120deg, #7c5cfc, #5f6cf8) !important;
|
||||||
border: 2px solid var(--ink) !important;
|
border: 1px solid transparent !important;
|
||||||
box-shadow: 3px 3px 0 var(--m-orange) !important;
|
box-shadow: 0 4px 16px var(--accent-glow) !important;
|
||||||
}
|
|
||||||
html.dark .chip-on {
|
|
||||||
background: var(--m-orange) !important;
|
|
||||||
box-shadow: 3px 3px 0 var(--shadow-ink) !important;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Twinkling star field — drop into any relatively-positioned decorative layer.
|
/* Twinkling star field — drop into any relatively-positioned decorative layer.
|
||||||
@@ -415,12 +448,12 @@ html.dark .chip-on {
|
|||||||
inset: 0;
|
inset: 0;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
background-image:
|
background-image:
|
||||||
radial-gradient(1.5px 1.5px at 12% 22%, rgb(236 91 19 / 0.7), transparent),
|
radial-gradient(1.5px 1.5px at 12% 22%, rgb(139 92 246 / 0.7), transparent),
|
||||||
radial-gradient(1.5px 1.5px at 78% 12%, rgb(56 189 248 / 0.7), transparent),
|
radial-gradient(1.5px 1.5px at 78% 12%, rgb(34 211 238 / 0.7), transparent),
|
||||||
radial-gradient(1px 1px at 42% 62%, rgb(236 91 19 / 0.6), transparent),
|
radial-gradient(1px 1px at 42% 62%, rgb(139 92 246 / 0.6), transparent),
|
||||||
radial-gradient(1.5px 1.5px at 88% 72%, rgb(244 114 182 / 0.6), transparent),
|
radial-gradient(1.5px 1.5px at 88% 72%, rgb(232 121 249 / 0.6), transparent),
|
||||||
radial-gradient(1px 1px at 24% 84%, rgb(56 189 248 / 0.55), transparent),
|
radial-gradient(1px 1px at 24% 84%, rgb(34 211 238 / 0.55), transparent),
|
||||||
radial-gradient(1px 1px at 62% 34%, rgb(250 204 21 / 0.55), transparent);
|
radial-gradient(1px 1px at 62% 34%, rgb(167 139 250 / 0.55), transparent);
|
||||||
animation: twinkle 4.5s ease-in-out infinite;
|
animation: twinkle 4.5s ease-in-out infinite;
|
||||||
}
|
}
|
||||||
@keyframes twinkle { 0%, 100% { opacity: 0.85; } 50% { opacity: 0.4; } }
|
@keyframes twinkle { 0%, 100% { opacity: 0.85; } 50% { opacity: 0.4; } }
|
||||||
@@ -445,35 +478,38 @@ html.dark .chip-on {
|
|||||||
z-index: 0;
|
z-index: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ===== Memphis utilities ===== */
|
/* ===== Glass utilities ===== */
|
||||||
/* Polka-dot texture layer (drop on a decorative absolutely-positioned div). */
|
/* Dot texture layer — kept faint so it reads as grain, not polka dots. */
|
||||||
.memphis-dots {
|
.memphis-dots {
|
||||||
background-image: radial-gradient(circle, rgb(17 17 17 / 0.14) 1.4px, transparent 1.4px);
|
background-image: radial-gradient(circle, rgb(24 21 36 / 0.07) 1.1px, transparent 1.1px);
|
||||||
background-size: 22px 22px;
|
background-size: 26px 26px;
|
||||||
}
|
}
|
||||||
html.dark .memphis-dots {
|
html.dark .memphis-dots {
|
||||||
background-image: radial-gradient(circle, rgb(255 255 255 / 0.1) 1.4px, transparent 1.4px);
|
background-image: radial-gradient(circle, rgb(255 255 255 / 0.05) 1.1px, transparent 1.1px);
|
||||||
}
|
}
|
||||||
/* Heavy outline + hard offset shadow helpers for one-off markup. */
|
/* Frosted surface helpers for one-off markup. */
|
||||||
.ink-card {
|
.ink-card {
|
||||||
background: var(--surface);
|
background: var(--surface);
|
||||||
border: 2.5px solid var(--ink);
|
-webkit-backdrop-filter: blur(14px);
|
||||||
box-shadow: 6px 6px 0 var(--shadow-ink);
|
backdrop-filter: blur(14px);
|
||||||
|
border: 1px solid var(--glass-border);
|
||||||
|
box-shadow: var(--glass-shadow-lg);
|
||||||
}
|
}
|
||||||
.ink-card-sm {
|
.ink-card-sm {
|
||||||
background: var(--surface);
|
background: var(--surface);
|
||||||
border: 2px solid var(--ink);
|
-webkit-backdrop-filter: blur(12px);
|
||||||
box-shadow: 4px 4px 0 var(--shadow-ink);
|
backdrop-filter: blur(12px);
|
||||||
|
border: 1px solid var(--glass-border);
|
||||||
|
box-shadow: var(--glass-shadow);
|
||||||
}
|
}
|
||||||
/* Lift on hover — the signature memphis card interaction. */
|
/* Lift on hover — the signature card interaction. */
|
||||||
.chunky-hover { transition: transform 0.18s ease, box-shadow 0.18s ease; }
|
.chunky-hover { transition: transform 0.18s ease, box-shadow 0.18s ease; }
|
||||||
.chunky-hover:hover { transform: translate(-2px, -2px); box-shadow: 8px 8px 0 var(--shadow-ink); }
|
.chunky-hover:hover { transform: translateY(-3px); box-shadow: var(--glass-shadow-lg); }
|
||||||
/* Squishy press for buttons (mirrors the reference site's .memphis-press). */
|
/* Squishy press for buttons. */
|
||||||
.memphis-press { transition: transform 0.15s ease; }
|
.memphis-press { transition: transform 0.15s ease; }
|
||||||
.memphis-press:active { transform: scale(0.97) translateY(2px); }
|
.memphis-press:active { transform: scale(0.97) translateY(1px); }
|
||||||
|
|
||||||
/* Empty-state badge — a rotated crayon tile with a star, replaces the old
|
/* Empty-state badge — frosted tile with a gradient star. */
|
||||||
mascot illustration in empty lists. */
|
|
||||||
.empty-badge {
|
.empty-badge {
|
||||||
width: 4.5rem;
|
width: 4.5rem;
|
||||||
height: 4.5rem;
|
height: 4.5rem;
|
||||||
@@ -481,12 +517,11 @@ html.dark .memphis-dots {
|
|||||||
place-items: center;
|
place-items: center;
|
||||||
font-size: 1.8rem;
|
font-size: 1.8rem;
|
||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
color: #111;
|
color: #fff;
|
||||||
background: var(--m-yellow);
|
background: linear-gradient(135deg, #7c5cfc, #22d3ee);
|
||||||
border: 3px solid var(--ink);
|
border: 1px solid rgb(255 255 255 / 0.2);
|
||||||
border-radius: 1rem;
|
border-radius: 1.2rem;
|
||||||
box-shadow: 5px 5px 0 var(--shadow-ink);
|
box-shadow: 0 12px 32px var(--accent-glow);
|
||||||
transform: rotate(-6deg);
|
|
||||||
animation: memphis-float 6s ease-in-out infinite;
|
animation: memphis-float 6s ease-in-out infinite;
|
||||||
}
|
}
|
||||||
@media (prefers-reduced-motion: reduce) { .empty-badge { animation: none; } }
|
@media (prefers-reduced-motion: reduce) { .empty-badge { animation: none; } }
|
||||||
@@ -507,40 +542,41 @@ html.dark .memphis-dots {
|
|||||||
remap them to the dark palette. */
|
remap them to the dark palette. */
|
||||||
.public-dark { color: rgb(255 255 255 / 0.9); }
|
.public-dark { color: rgb(255 255 255 / 0.9); }
|
||||||
.public-dark .card {
|
.public-dark .card {
|
||||||
background: rgb(255 255 255 / 0.035);
|
background: rgb(255 255 255 / 0.04);
|
||||||
border-color: var(--ink);
|
border-color: rgb(255 255 255 / 0.1);
|
||||||
color: rgb(255 255 255 / 0.92);
|
color: rgb(255 255 255 / 0.92);
|
||||||
box-shadow: 5px 5px 0 var(--shadow-ink);
|
box-shadow: var(--glass-shadow);
|
||||||
}
|
}
|
||||||
.public-dark .field {
|
.public-dark .field {
|
||||||
background: rgb(255 255 255 / 0.04);
|
background: rgb(255 255 255 / 0.04);
|
||||||
border-color: var(--ink-soft);
|
border-color: rgb(255 255 255 / 0.12);
|
||||||
color: rgb(255 255 255 / 0.95);
|
color: rgb(255 255 255 / 0.95);
|
||||||
transition: border-color 0.18s, background 0.18s, box-shadow 0.18s;
|
transition: border-color 0.18s, background 0.18s, box-shadow 0.18s;
|
||||||
}
|
}
|
||||||
.public-dark .field::placeholder { color: rgb(255 255 255 / 0.3); }
|
.public-dark .field::placeholder { color: rgb(255 255 255 / 0.3); }
|
||||||
/* Single focus treatment shared by every <.field> across the admin shell —
|
/* Single focus treatment shared by every <.field> across the admin shell —
|
||||||
an orange offset shadow, matching the light theme's focus affordance. */
|
a violet glow ring, matching the light theme's focus affordance. */
|
||||||
.public-dark .field:focus,
|
.public-dark .field:focus,
|
||||||
.public-dark .field:focus-visible {
|
.public-dark .field:focus-visible {
|
||||||
border-color: var(--ink);
|
border-color: rgb(139 92 246 / 0.7);
|
||||||
background: rgb(255 255 255 / 0.06);
|
background: rgb(255 255 255 / 0.06);
|
||||||
box-shadow: 3px 3px 0 rgb(236 91 19 / 0.6);
|
box-shadow: 0 0 0 3px rgb(139 92 246 / 0.25);
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
.public-dark .btn-soft {
|
.public-dark .btn-soft {
|
||||||
background: rgb(255 255 255 / 0.06);
|
background: rgb(255 255 255 / 0.05);
|
||||||
border-color: var(--ink-soft);
|
border-color: rgb(255 255 255 / 0.12);
|
||||||
color: rgb(255 255 255 / 0.85);
|
color: rgb(255 255 255 / 0.85);
|
||||||
}
|
}
|
||||||
.public-dark .btn-soft:hover { background: rgb(236 91 19 / 0.25); color: white; }
|
.public-dark .btn-soft:hover { background: rgb(139 92 246 / 0.25); color: white; }
|
||||||
.public-dark .btn-ghost { color: rgb(255 255 255 / 0.65); border-color: transparent; }
|
.public-dark .btn-ghost { color: rgb(255 255 255 / 0.65); border-color: transparent; }
|
||||||
.public-dark .btn-ghost:hover { background: rgb(236 91 19 / 0.18); color: white; }
|
.public-dark .btn-ghost:hover { background: rgb(139 92 246 / 0.18); color: white; }
|
||||||
.public-dark .btn-primary {
|
.public-dark .btn-primary {
|
||||||
background: var(--m-orange); color: #fff; box-shadow: 3px 3px 0 var(--shadow-ink);
|
background: linear-gradient(120deg, #7c5cfc, #5f6cf8); color: #fff;
|
||||||
|
box-shadow: 0 6px 18px var(--accent-glow);
|
||||||
}
|
}
|
||||||
.public-dark .btn-primary:hover { background: #f97316; }
|
.public-dark .btn-primary:hover { filter: brightness(1.08); }
|
||||||
.public-dark .pill { background: rgb(255 255 255 / 0.06); color: rgb(255 255 255 / 0.85); border-color: var(--ink-soft); }
|
.public-dark .pill { background: rgb(255 255 255 / 0.06); color: rgb(255 255 255 / 0.85); border-color: rgb(255 255 255 / 0.12); }
|
||||||
|
|
||||||
/* Remap slate text tokens */
|
/* Remap slate text tokens */
|
||||||
.public-dark .text-slate-900,
|
.public-dark .text-slate-900,
|
||||||
@@ -564,7 +600,7 @@ html.dark .memphis-dots {
|
|||||||
/* Tables in dark */
|
/* Tables in dark */
|
||||||
.public-dark .th { color: rgb(255 255 255 / 0.4); }
|
.public-dark .th { color: rgb(255 255 255 / 0.4); }
|
||||||
.public-dark .row { border-color: rgb(255 255 255 / 0.06); }
|
.public-dark .row { border-color: rgb(255 255 255 / 0.06); }
|
||||||
.public-dark .row:hover { background: rgb(255 255 255 / 0.03); }
|
.public-dark .row:hover { background: rgb(139 92 246 / 0.07); }
|
||||||
|
|
||||||
/* Inline code blocks (pill highlight) — only for inline <code>, NOT code inside
|
/* Inline code blocks (pill highlight) — only for inline <code>, NOT code inside
|
||||||
a <pre> block (docs examples), which would get an unwanted full-width tint. */
|
a <pre> block (docs examples), which would get an unwanted full-width tint. */
|
||||||
@@ -590,11 +626,14 @@ html.dark .memphis-dots {
|
|||||||
.public-dark .hover\:bg-slate-100:hover { background: rgb(255 255 255 / 0.06); }
|
.public-dark .hover\:bg-slate-100:hover { background: rgb(255 255 255 / 0.06); }
|
||||||
|
|
||||||
@layer components {
|
@layer components {
|
||||||
/* surfaces — flat white card with the memphis ink outline + offset shadow */
|
/* surfaces — frosted card with a hairline glass edge + soft shadow */
|
||||||
.card {
|
.card {
|
||||||
@apply bg-white rounded-xl;
|
@apply rounded-xl;
|
||||||
border: 2.5px solid var(--ink);
|
background: var(--surface);
|
||||||
box-shadow: 5px 5px 0 var(--shadow-ink);
|
-webkit-backdrop-filter: blur(14px);
|
||||||
|
backdrop-filter: blur(14px);
|
||||||
|
border: 1px solid var(--glass-border);
|
||||||
|
box-shadow: var(--glass-shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* buttons — each variant is self-contained (Tailwind v4 can't @apply a custom class) */
|
/* buttons — each variant is self-contained (Tailwind v4 can't @apply a custom class) */
|
||||||
@@ -602,56 +641,64 @@ html.dark .memphis-dots {
|
|||||||
@apply inline-flex items-center justify-center gap-1.5 rounded-lg text-sm font-bold
|
@apply inline-flex items-center justify-center gap-1.5 rounded-lg text-sm font-bold
|
||||||
disabled:opacity-50 disabled:cursor-not-allowed px-3.5 py-2;
|
disabled:opacity-50 disabled:cursor-not-allowed px-3.5 py-2;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
background: var(--m-orange);
|
background: linear-gradient(120deg, #7c5cfc, #5f6cf8 60%, #22d3ee 140%);
|
||||||
border: 2.5px solid var(--ink);
|
border: 1px solid rgb(255 255 255 / 0.16);
|
||||||
box-shadow: 3px 3px 0 var(--shadow-ink);
|
box-shadow: 0 6px 18px var(--accent-glow);
|
||||||
transition: transform 0.13s ease, box-shadow 0.13s ease, filter 0.13s ease;
|
transition: transform 0.13s ease, box-shadow 0.13s ease, filter 0.13s ease;
|
||||||
}
|
}
|
||||||
.btn-primary:hover:not(:disabled) { transform: translate(-1px, -1px); box-shadow: 4px 4px 0 var(--shadow-ink); filter: brightness(1.05); }
|
.btn-primary:hover:not(:disabled) { transform: translateY(-1px); box-shadow: 0 10px 26px var(--accent-glow); filter: brightness(1.07); }
|
||||||
.btn-primary:active:not(:disabled) { transform: scale(0.97) translateY(2px); box-shadow: 0 0 0 var(--shadow-ink); }
|
.btn-primary:active:not(:disabled) { transform: scale(0.97) translateY(1px); box-shadow: 0 3px 10px var(--accent-glow); }
|
||||||
.btn-soft {
|
.btn-soft {
|
||||||
@apply inline-flex items-center justify-center gap-1.5 rounded-lg text-xs font-semibold
|
@apply inline-flex items-center justify-center gap-1.5 rounded-lg text-xs font-semibold
|
||||||
disabled:opacity-50 disabled:cursor-not-allowed px-3 py-1.5;
|
disabled:opacity-50 disabled:cursor-not-allowed px-3 py-1.5;
|
||||||
color: var(--fg-2);
|
color: var(--fg-2);
|
||||||
background: var(--surface);
|
background: var(--surface);
|
||||||
border: 2px solid var(--ink-soft);
|
-webkit-backdrop-filter: blur(10px);
|
||||||
transition: transform 0.13s ease, box-shadow 0.13s ease, background 0.15s ease, color 0.15s ease;
|
backdrop-filter: blur(10px);
|
||||||
|
border: 1px solid var(--ink-soft);
|
||||||
|
transition: transform 0.13s ease, box-shadow 0.13s ease, background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
|
||||||
}
|
}
|
||||||
.btn-soft:hover:not(:disabled) {
|
.btn-soft:hover:not(:disabled) {
|
||||||
color: var(--fg);
|
color: var(--fg);
|
||||||
background: var(--m-yellow);
|
background: var(--hover);
|
||||||
border-color: var(--ink);
|
border-color: rgb(124 92 252 / 0.45);
|
||||||
box-shadow: 3px 3px 0 var(--shadow-ink);
|
box-shadow: 0 4px 14px rgb(124 92 252 / 0.16);
|
||||||
}
|
}
|
||||||
.btn-soft:active:not(:disabled) { transform: scale(0.97) translateY(2px); box-shadow: none; }
|
html.dark .btn-soft:hover:not(:disabled) { border-color: rgb(139 92 246 / 0.5); box-shadow: 0 4px 14px rgb(139 92 246 / 0.22); }
|
||||||
|
.btn-soft:active:not(:disabled) { transform: scale(0.97) translateY(1px); box-shadow: none; }
|
||||||
.btn-ghost {
|
.btn-ghost {
|
||||||
@apply inline-flex items-center justify-center gap-1.5 rounded-lg text-xs font-medium
|
@apply inline-flex items-center justify-center gap-1.5 rounded-lg text-xs font-medium
|
||||||
disabled:opacity-50 disabled:cursor-not-allowed px-3 py-1.5;
|
disabled:opacity-50 disabled:cursor-not-allowed px-3 py-1.5;
|
||||||
color: var(--fg-2);
|
color: var(--fg-2);
|
||||||
border: 2px solid transparent;
|
border: 1px solid transparent;
|
||||||
transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
|
transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
|
||||||
}
|
}
|
||||||
.btn-ghost:hover:not(:disabled) {
|
.btn-ghost:hover:not(:disabled) {
|
||||||
color: var(--fg);
|
color: var(--fg);
|
||||||
background: var(--m-yellow);
|
background: var(--hover);
|
||||||
border-color: var(--ink);
|
border-color: rgb(124 92 252 / 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* text link / quiet action */
|
/* text link / quiet action */
|
||||||
.link { @apply hover:text-slate-900 transition-colors cursor-pointer; color: var(--fg-3); }
|
.link { @apply transition-colors cursor-pointer; color: var(--fg-3); }
|
||||||
.link:hover { color: var(--m-orange); }
|
.link:hover { color: var(--m-orange); }
|
||||||
|
|
||||||
/* form controls — heavy outline, orange offset shadow on focus */
|
/* form controls — glass field, violet glow ring on focus */
|
||||||
.field {
|
.field {
|
||||||
@apply w-full rounded-lg bg-white px-3 py-2 text-sm
|
@apply w-full rounded-lg px-3 py-2 text-sm
|
||||||
outline-none placeholder:text-slate-400;
|
outline-none placeholder:text-slate-400;
|
||||||
color: var(--fg);
|
color: var(--fg);
|
||||||
border: 2px solid var(--ink-soft);
|
background: var(--surface);
|
||||||
transition: border-color 0.15s ease, box-shadow 0.15s ease;
|
border: 1px solid var(--ink-soft);
|
||||||
|
transition: border-color 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
|
||||||
}
|
}
|
||||||
.field:focus, .field:focus-visible {
|
.field:focus, .field:focus-visible {
|
||||||
border-color: var(--ink);
|
border-color: rgb(124 92 252 / 0.65);
|
||||||
box-shadow: 3px 3px 0 var(--m-orange);
|
box-shadow: 0 0 0 3px rgb(124 92 252 / 0.18);
|
||||||
|
}
|
||||||
|
html.dark .field:focus, html.dark .field:focus-visible {
|
||||||
|
border-color: rgb(139 92 246 / 0.7);
|
||||||
|
box-shadow: 0 0 0 3px rgb(139 92 246 / 0.25);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Native <select> using .field: drop the OS arrow for a custom chevron that
|
/* Native <select> using .field: drop the OS arrow for a custom chevron that
|
||||||
@@ -680,15 +727,19 @@ html.dark .memphis-dots {
|
|||||||
/* status pill */
|
/* status pill */
|
||||||
.pill {
|
.pill {
|
||||||
@apply inline-flex items-center rounded-md px-2 py-0.5 text-xs font-semibold;
|
@apply inline-flex items-center rounded-md px-2 py-0.5 text-xs font-semibold;
|
||||||
border: 1.5px solid var(--ink-soft);
|
border: 1px solid var(--ink-soft);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* table primitives */
|
/* table primitives */
|
||||||
.th { @apply text-left px-4 py-3 text-[11px] font-bold uppercase tracking-wider; color: var(--fg-faint); }
|
.th { @apply text-left px-4 py-3 text-[11px] font-bold uppercase tracking-wider; color: var(--fg-faint); }
|
||||||
.td { @apply px-4 py-3.5 align-middle; }
|
.td { @apply px-4 py-3.5 align-middle; }
|
||||||
.row { @apply border-t transition-colors; border-color: var(--hairline); }
|
.row { @apply border-t transition-colors; border-color: var(--hairline); }
|
||||||
.row:hover { background: rgb(254 240 138 / 0.35); }
|
.row:hover { background: rgb(124 92 252 / 0.06); }
|
||||||
|
|
||||||
/* avatar chip for identity columns */
|
/* avatar chip for identity columns */
|
||||||
.avatar { @apply w-8 h-8 rounded-full grid place-items-center text-xs font-bold shrink-0; border: 2px solid var(--ink); }
|
.avatar {
|
||||||
|
@apply w-8 h-8 rounded-full grid place-items-center text-xs font-bold shrink-0;
|
||||||
|
border: 1px solid var(--ink);
|
||||||
|
background: var(--surface-2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import { site } from '../site'
|
import { site } from '../site'
|
||||||
|
|
||||||
const contact = computed(() => site.contact || {})
|
const contact = computed(() => site.contact || {})
|
||||||
|
|
||||||
const powers = [
|
const powers = [
|
||||||
{ icon: '🎨', title: '文字生图', desc: '一句话出图,画幅与分辨率随模型可选。', bg: 'var(--m-mint)' },
|
{ icon: 't2i', title: '文字生图', desc: '一句话出图,画幅与分辨率随模型可选。', tint: 'linear-gradient(135deg,#34d399,#2dd4bf)' },
|
||||||
{ icon: '🖼️', title: '参考图生图', desc: '上传参考换风格、改构图、做变体。', bg: 'var(--m-pink)' },
|
{ icon: 'i2i', title: '参考图生图', desc: '上传参考换风格、改构图、做变体。', tint: 'linear-gradient(135deg,#e879f9,#f472b6)' },
|
||||||
{ icon: '🎬', title: '文字生视频', desc: '一段描述生成短片,时长分辨率可选。', bg: 'var(--m-blue)' },
|
{ icon: 't2v', title: '文字生视频', desc: '一段描述生成短片,时长分辨率可选。', tint: 'linear-gradient(135deg,#38bdf8,#22d3ee)' },
|
||||||
{ icon: '✨', title: '图生视频', desc: '给张参考图,让静态画面动起来。', bg: 'var(--m-yellow)' },
|
{ icon: 'i2v', title: '图生视频', desc: '给张参考图,让静态画面动起来。', tint: 'linear-gradient(135deg,#7c5cfc,#a855f7)' },
|
||||||
]
|
]
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -29,12 +29,12 @@ const powers = [
|
|||||||
</p>
|
</p>
|
||||||
<router-link to="/user" class="bubble-btn mt-7">开始创作 →</router-link>
|
<router-link to="/user" class="bubble-btn mt-7">开始创作 →</router-link>
|
||||||
</div>
|
</div>
|
||||||
<!-- memphis tile cluster standing in for the old mascot illustration -->
|
<!-- floating glass tile cluster standing in for a mascot illustration -->
|
||||||
<div class="ab-cluster" aria-hidden="true">
|
<div class="ab-cluster" aria-hidden="true">
|
||||||
<span class="ab-tile ab-1">🎨</span>
|
<span class="ab-tile ab-1"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3l1.9 5.8a2 2 0 0 0 1.3 1.3L21 12l-5.8 1.9a2 2 0 0 0-1.3 1.3L12 21l-1.9-5.8a2 2 0 0 0-1.3-1.3L3 12l5.8-1.9a2 2 0 0 0 1.3-1.3z"/></svg></span>
|
||||||
<span class="ab-tile ab-2">🖼️</span>
|
<span class="ab-tile ab-2"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="5" width="18" height="14" rx="2"/><path d="m3 16 5-5 3 3 4-4 6 6"/><circle cx="9" cy="9" r="1.4"/></svg></span>
|
||||||
<span class="ab-tile ab-3">🎬</span>
|
<span class="ab-tile ab-3"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 6h13v12H3z"/><path d="M16 10l5-3v10l-5-3"/></svg></span>
|
||||||
<span class="ab-tile ab-4">✨</span>
|
<span class="ab-tile ab-4"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M13 2 3 14h7l-1 8 10-12h-7z"/></svg></span>
|
||||||
<span class="ab-star">✦</span>
|
<span class="ab-star">✦</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -45,11 +45,15 @@ const powers = [
|
|||||||
<div class="anime-eyebrow text-[var(--m-orange)]">能做什么</div>
|
<div class="anime-eyebrow text-[var(--m-orange)]">能做什么</div>
|
||||||
<h2 class="mt-3 text-2xl md:text-3xl font-black tracking-tight text-[color:var(--fg)]">四种方式,把想象变成画面</h2>
|
<h2 class="mt-3 text-2xl md:text-3xl font-black tracking-tight text-[color:var(--fg)]">四种方式,把想象变成画面</h2>
|
||||||
<div class="mt-7 grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-3">
|
<div class="mt-7 grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-3">
|
||||||
<div v-for="p in powers" :key="p.title"
|
<div v-for="p in powers" :key="p.title" class="power-card p-5">
|
||||||
class="power-card p-5" :style="{ background: p.bg }">
|
<div class="power-ico" :style="{ background: p.tint }">
|
||||||
<div class="text-3xl">{{ p.icon }}</div>
|
<svg v-if="p.icon === 't2i'" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 5h16v14H4z"/><path d="M4 15l4.5-4.5 3 3L15 10l5 5"/><circle cx="9" cy="9" r="1.3"/></svg>
|
||||||
<div class="mt-3 text-base font-extrabold text-[#111]">{{ p.title }}</div>
|
<svg v-else-if="p.icon === 'i2i'" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 7h11v11H3z"/><path d="M10 4h11v11"/></svg>
|
||||||
<div class="mt-1.5 text-[13px] font-medium leading-relaxed text-[#111]/60">{{ p.desc }}</div>
|
<svg v-else-if="p.icon === 't2v'" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 6h13v12H3z"/><path d="M16 10l5-3v10l-5-3"/></svg>
|
||||||
|
<svg v-else viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 5h16v14H4z"/><path d="M9 9l6 3-6 3z"/></svg>
|
||||||
|
</div>
|
||||||
|
<div class="mt-3 text-base font-extrabold text-[color:var(--fg)]">{{ p.title }}</div>
|
||||||
|
<div class="mt-1.5 text-[13px] font-medium leading-relaxed text-[color:var(--fg-3)]">{{ p.desc }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -64,7 +68,7 @@ const powers = [
|
|||||||
<a v-if="contact.shop" :href="contact.shop" target="_blank" rel="noopener"
|
<a v-if="contact.shop" :href="contact.shop" target="_blank" rel="noopener"
|
||||||
class="group anime-card flex items-center justify-between gap-3 p-5">
|
class="group anime-card flex items-center justify-between gap-3 p-5">
|
||||||
<div>
|
<div>
|
||||||
<div class="sticker">🛍️ 商店</div>
|
<div class="sticker">商店</div>
|
||||||
<div class="text-base font-semibold text-[color:var(--fg)] mt-2 group-hover:text-[var(--m-orange)] transition-colors">前往商店</div>
|
<div class="text-base font-semibold text-[color:var(--fg)] mt-2 group-hover:text-[var(--m-orange)] transition-colors">前往商店</div>
|
||||||
</div>
|
</div>
|
||||||
<span class="text-[color:var(--fg-faint)] group-hover:translate-x-1 transition-transform">→</span>
|
<span class="text-[color:var(--fg-faint)] group-hover:translate-x-1 transition-transform">→</span>
|
||||||
@@ -72,33 +76,33 @@ const powers = [
|
|||||||
|
|
||||||
<a v-if="contact.email" :href="`mailto:${contact.email}`"
|
<a v-if="contact.email" :href="`mailto:${contact.email}`"
|
||||||
class="group anime-card p-5">
|
class="group anime-card p-5">
|
||||||
<div class="sticker">✉️ 邮箱</div>
|
<div class="sticker">邮箱</div>
|
||||||
<div class="text-base font-semibold text-[color:var(--fg)] mt-2 break-all group-hover:text-sky-600 transition-colors">{{ contact.email }}</div>
|
<div class="text-base font-semibold text-[color:var(--fg)] mt-2 break-all group-hover:text-sky-600 transition-colors">{{ contact.email }}</div>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a v-if="contact.qq && contact.qq_link" :href="contact.qq_link" target="_blank" rel="noopener"
|
<a v-if="contact.qq && contact.qq_link" :href="contact.qq_link" target="_blank" rel="noopener"
|
||||||
class="group anime-card flex items-center justify-between gap-3 p-5">
|
class="group anime-card flex items-center justify-between gap-3 p-5">
|
||||||
<div>
|
<div>
|
||||||
<div class="sticker">💬 QQ</div>
|
<div class="sticker">QQ</div>
|
||||||
<div class="text-base font-semibold text-[color:var(--fg)] mt-2 tabular-nums break-all group-hover:text-sky-600 transition-colors">{{ contact.qq }}</div>
|
<div class="text-base font-semibold text-[color:var(--fg)] mt-2 tabular-nums break-all group-hover:text-sky-600 transition-colors">{{ contact.qq }}</div>
|
||||||
</div>
|
</div>
|
||||||
<span class="text-[color:var(--fg-faint)] group-hover:translate-x-1 transition-transform">→</span>
|
<span class="text-[color:var(--fg-faint)] group-hover:translate-x-1 transition-transform">→</span>
|
||||||
</a>
|
</a>
|
||||||
<div v-else-if="contact.qq" class="anime-card p-5">
|
<div v-else-if="contact.qq" class="anime-card p-5">
|
||||||
<div class="sticker">💬 QQ</div>
|
<div class="sticker">QQ</div>
|
||||||
<div class="text-base font-semibold text-[color:var(--fg)] mt-2 tabular-nums break-all">{{ contact.qq }}</div>
|
<div class="text-base font-semibold text-[color:var(--fg)] mt-2 tabular-nums break-all">{{ contact.qq }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a v-if="contact.qq_group && contact.qq_group_link" :href="contact.qq_group_link" target="_blank" rel="noopener"
|
<a v-if="contact.qq_group && contact.qq_group_link" :href="contact.qq_group_link" target="_blank" rel="noopener"
|
||||||
class="group anime-card flex items-center justify-between gap-3 p-5">
|
class="group anime-card flex items-center justify-between gap-3 p-5">
|
||||||
<div>
|
<div>
|
||||||
<div class="sticker">🎀 QQ 群</div>
|
<div class="sticker">QQ 群</div>
|
||||||
<div class="text-base font-semibold text-[color:var(--fg)] mt-2 tabular-nums break-all group-hover:text-emerald-600 transition-colors">{{ contact.qq_group }}</div>
|
<div class="text-base font-semibold text-[color:var(--fg)] mt-2 tabular-nums break-all group-hover:text-emerald-600 transition-colors">{{ contact.qq_group }}</div>
|
||||||
</div>
|
</div>
|
||||||
<span class="text-[color:var(--fg-faint)] group-hover:translate-x-1 transition-transform">→</span>
|
<span class="text-[color:var(--fg-faint)] group-hover:translate-x-1 transition-transform">→</span>
|
||||||
</a>
|
</a>
|
||||||
<div v-else-if="contact.qq_group" class="anime-card p-5">
|
<div v-else-if="contact.qq_group" class="anime-card p-5">
|
||||||
<div class="sticker">🎀 QQ 群</div>
|
<div class="sticker">QQ 群</div>
|
||||||
<div class="text-base font-semibold text-[color:var(--fg)] mt-2 tabular-nums break-all">{{ contact.qq_group }}</div>
|
<div class="text-base font-semibold text-[color:var(--fg)] mt-2 tabular-nums break-all">{{ contact.qq_group }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -110,7 +114,7 @@ const powers = [
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
/* Crayon tile cluster — a loose collage of rotated ink-outlined squares. */
|
/* Floating glass tile cluster — a loose collage of rotated frosted squares. */
|
||||||
.ab-cluster {
|
.ab-cluster {
|
||||||
position: relative;
|
position: relative;
|
||||||
min-height: 240px;
|
min-height: 240px;
|
||||||
@@ -121,15 +125,19 @@ const powers = [
|
|||||||
place-items: center;
|
place-items: center;
|
||||||
width: 5.5rem;
|
width: 5.5rem;
|
||||||
height: 5.5rem;
|
height: 5.5rem;
|
||||||
font-size: 2.2rem;
|
border: 1px solid var(--glass-border);
|
||||||
border: 3px solid var(--ink);
|
border-radius: 1.2rem;
|
||||||
border-radius: 1rem;
|
background: var(--surface);
|
||||||
box-shadow: 6px 6px 0 var(--shadow-ink);
|
-webkit-backdrop-filter: blur(14px);
|
||||||
|
backdrop-filter: blur(14px);
|
||||||
|
box-shadow: var(--glass-shadow-lg);
|
||||||
|
color: var(--m-orange);
|
||||||
}
|
}
|
||||||
.ab-1 { left: 12%; top: 6%; background: var(--m-mint); transform: rotate(-9deg); animation: memphis-float 6s ease-in-out infinite; }
|
.ab-tile svg { width: 2.3rem; height: 2.3rem; }
|
||||||
.ab-2 { right: 14%; top: 0; background: var(--m-pink); transform: rotate(7deg); animation: memphis-float 7s ease-in-out infinite reverse; }
|
.ab-1 { left: 12%; top: 6%; transform: rotate(-9deg); animation: memphis-float 6s ease-in-out infinite; }
|
||||||
.ab-3 { left: 26%; bottom: 4%; background: var(--m-blue); transform: rotate(5deg); animation: memphis-bounce 4.5s ease-in-out infinite; }
|
.ab-2 { right: 14%; top: 0; color: var(--m-orange-2); transform: rotate(7deg); animation: memphis-float 7s ease-in-out infinite reverse; }
|
||||||
.ab-4 { right: 8%; bottom: 14%; background: var(--m-yellow); transform: rotate(-6deg); animation: memphis-float 5.5s ease-in-out infinite; }
|
.ab-3 { left: 26%; bottom: 4%; color: var(--m-pink); transform: rotate(5deg); animation: memphis-bounce 4.5s ease-in-out infinite; }
|
||||||
|
.ab-4 { right: 8%; bottom: 14%; color: var(--m-mint); transform: rotate(-6deg); animation: memphis-float 5.5s ease-in-out infinite; }
|
||||||
.ab-star {
|
.ab-star {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 50%; top: 44%;
|
left: 50%; top: 44%;
|
||||||
@@ -138,12 +146,25 @@ const powers = [
|
|||||||
animation: memphis-wiggle 3.5s ease-in-out infinite;
|
animation: memphis-wiggle 3.5s ease-in-out infinite;
|
||||||
}
|
}
|
||||||
.power-card {
|
.power-card {
|
||||||
border: 2.5px solid var(--ink);
|
border: 1px solid var(--glass-border);
|
||||||
border-radius: 1rem;
|
border-radius: 1.1rem;
|
||||||
box-shadow: 5px 5px 0 var(--shadow-ink);
|
background: var(--surface);
|
||||||
transition: transform 0.18s ease, box-shadow 0.18s ease;
|
-webkit-backdrop-filter: blur(14px);
|
||||||
|
backdrop-filter: blur(14px);
|
||||||
|
box-shadow: var(--glass-shadow);
|
||||||
|
transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease;
|
||||||
}
|
}
|
||||||
.power-card:hover { transform: translate(-2px, -2px); box-shadow: 8px 8px 0 var(--shadow-ink); }
|
.power-card:hover { transform: translateY(-3px); border-color: rgb(124 92 252 / 0.45); box-shadow: var(--glass-shadow-lg); }
|
||||||
|
.power-ico {
|
||||||
|
width: 2.6rem;
|
||||||
|
height: 2.6rem;
|
||||||
|
border-radius: 0.75rem;
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
color: #fff;
|
||||||
|
box-shadow: 0 6px 16px rgb(124 92 252 / 0.28);
|
||||||
|
}
|
||||||
|
.power-ico svg { width: 1.3rem; height: 1.3rem; }
|
||||||
@media (max-width: 768px) { .ab-cluster { display: none; } }
|
@media (max-width: 768px) { .ab-cluster { display: none; } }
|
||||||
@media (prefers-reduced-motion: reduce) { .ab-tile, .ab-star { animation: none; } }
|
@media (prefers-reduced-motion: reduce) { .ab-tile, .ab-star { animation: none; } }
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -883,26 +883,28 @@ const saveLabel = computed(() => ({
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
/* ===== 画布:Memphis/neo-brutalism 全屏工作台(随站点明暗主题走变量) ===== */
|
/* ===== 画布:玻璃拟态全屏工作台(随站点明暗主题走变量) ===== */
|
||||||
.cv-btn {
|
.cv-btn {
|
||||||
padding: 5px 11px;
|
padding: 5px 11px;
|
||||||
border-radius: 9px;
|
border-radius: 9px;
|
||||||
border: 2.5px solid var(--ink);
|
border: 1px solid var(--ink-soft);
|
||||||
background: var(--surface);
|
background: var(--surface);
|
||||||
|
-webkit-backdrop-filter: blur(10px);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
color: var(--fg);
|
color: var(--fg);
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
box-shadow: 3px 3px 0 var(--shadow-ink);
|
box-shadow: var(--glass-shadow);
|
||||||
transition: transform 0.12s ease, box-shadow 0.12s ease, background 0.12s ease;
|
transition: transform 0.12s ease, box-shadow 0.12s ease, background 0.12s ease, border-color 0.12s ease;
|
||||||
}
|
}
|
||||||
.cv-btn:hover:not(:disabled) {
|
.cv-btn:hover:not(:disabled) {
|
||||||
background: var(--m-yellow);
|
background: var(--hover);
|
||||||
|
border-color: rgb(124 92 252 / 0.4);
|
||||||
}
|
}
|
||||||
.cv-btn:active:not(:disabled) {
|
.cv-btn:active:not(:disabled) {
|
||||||
transform: translate(2px, 2px);
|
transform: translateY(1px);
|
||||||
box-shadow: 1px 1px 0 var(--shadow-ink);
|
|
||||||
}
|
}
|
||||||
.cv-btn:disabled {
|
.cv-btn:disabled {
|
||||||
opacity: 0.45;
|
opacity: 0.45;
|
||||||
@@ -912,16 +914,18 @@ const saveLabel = computed(() => ({
|
|||||||
background: #ffb4ab;
|
background: #ffb4ab;
|
||||||
}
|
}
|
||||||
.cv-btn--accent {
|
.cv-btn--accent {
|
||||||
background: var(--m-blue);
|
background: rgb(34 211 238 / 0.16);
|
||||||
|
border-color: rgb(34 211 238 / 0.4);
|
||||||
}
|
}
|
||||||
.cv-btn--accent:hover:not(:disabled) {
|
.cv-btn--accent:hover:not(:disabled) {
|
||||||
background: var(--m-mint);
|
background: rgb(52 211 153 / 0.16);
|
||||||
|
border-color: rgb(52 211 153 / 0.4);
|
||||||
}
|
}
|
||||||
.cv-select,
|
.cv-select,
|
||||||
.cv-input {
|
.cv-input {
|
||||||
padding: 6px 10px;
|
padding: 6px 10px;
|
||||||
border-radius: 9px;
|
border-radius: 9px;
|
||||||
border: 2.5px solid var(--ink);
|
border: 1px solid var(--ink-soft);
|
||||||
background: var(--surface);
|
background: var(--surface);
|
||||||
color: var(--fg);
|
color: var(--fg);
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
@@ -929,7 +933,8 @@ const saveLabel = computed(() => ({
|
|||||||
}
|
}
|
||||||
.cv-select:focus,
|
.cv-select:focus,
|
||||||
.cv-input:focus {
|
.cv-input:focus {
|
||||||
box-shadow: 3px 3px 0 var(--m-orange);
|
border-color: rgb(124 92 252 / 0.6);
|
||||||
|
box-shadow: 0 0 0 3px rgb(124 92 252 / 0.18);
|
||||||
}
|
}
|
||||||
|
|
||||||
.cv-page {
|
.cv-page {
|
||||||
@@ -947,8 +952,10 @@ const saveLabel = computed(() => ({
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
padding: 9px 14px;
|
padding: 9px 14px;
|
||||||
border-bottom: 3px solid var(--ink);
|
border-bottom: 1px solid var(--ink-soft);
|
||||||
background: var(--surface);
|
background: var(--surface);
|
||||||
|
-webkit-backdrop-filter: blur(14px);
|
||||||
|
backdrop-filter: blur(14px);
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
.cv-top__left,
|
.cv-top__left,
|
||||||
@@ -975,8 +982,8 @@ const saveLabel = computed(() => ({
|
|||||||
color: var(--fg);
|
color: var(--fg);
|
||||||
min-width: 46px;
|
min-width: 46px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
background: var(--m-yellow);
|
background: var(--hover);
|
||||||
border: 2px solid var(--ink);
|
border: 1px solid rgb(124 92 252 / 0.35);
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
padding: 1px 8px;
|
padding: 1px 8px;
|
||||||
}
|
}
|
||||||
@@ -1017,9 +1024,9 @@ const saveLabel = computed(() => ({
|
|||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
color: var(--fg);
|
color: var(--fg);
|
||||||
border: 3px dashed var(--ink);
|
border: 2px dashed rgb(34 211 238 / 0.6);
|
||||||
border-radius: 18px;
|
border-radius: 18px;
|
||||||
background: color-mix(in srgb, var(--m-blue) 55%, transparent);
|
background: rgb(34 211 238 / 0.1);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
.cv-loading,
|
.cv-loading,
|
||||||
@@ -1039,12 +1046,14 @@ const saveLabel = computed(() => ({
|
|||||||
color: #dc2626;
|
color: #dc2626;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 右侧生成面板 = 白纸卡片 */
|
/* 右侧生成面板 = 玻璃侧栏 */
|
||||||
.cv-panel {
|
.cv-panel {
|
||||||
width: 264px;
|
width: 264px;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
border-left: 3px solid var(--ink);
|
border-left: 1px solid var(--ink-soft);
|
||||||
background: var(--surface);
|
background: var(--surface);
|
||||||
|
-webkit-backdrop-filter: blur(14px);
|
||||||
|
backdrop-filter: blur(14px);
|
||||||
padding: 16px 14px;
|
padding: 16px 14px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -1081,19 +1090,23 @@ const saveLabel = computed(() => ({
|
|||||||
.cv-chip {
|
.cv-chip {
|
||||||
padding: 3px 11px;
|
padding: 3px 11px;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
border: 2.5px solid var(--ink);
|
border: 1px solid var(--ink-soft);
|
||||||
background: var(--surface);
|
background: var(--surface);
|
||||||
color: var(--fg);
|
color: var(--fg);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
transition: background 0.13s ease, border-color 0.13s ease, box-shadow 0.13s ease;
|
||||||
}
|
}
|
||||||
.cv-chip:hover {
|
.cv-chip:hover {
|
||||||
background: var(--m-blue);
|
background: var(--hover);
|
||||||
|
border-color: rgb(124 92 252 / 0.4);
|
||||||
}
|
}
|
||||||
.cv-chip.is-on {
|
.cv-chip.is-on {
|
||||||
background: var(--m-yellow);
|
color: #fff;
|
||||||
box-shadow: 2.5px 2.5px 0 var(--shadow-ink);
|
background: linear-gradient(120deg, #7c5cfc, #5f6cf8);
|
||||||
|
border-color: transparent;
|
||||||
|
box-shadow: 0 4px 14px var(--accent-glow);
|
||||||
}
|
}
|
||||||
.cv-refs {
|
.cv-refs {
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
@@ -1106,22 +1119,23 @@ const saveLabel = computed(() => ({
|
|||||||
.cv-gen {
|
.cv-gen {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
border-radius: 11px;
|
border-radius: 11px;
|
||||||
border: 2.5px solid var(--ink);
|
border: 1px solid rgb(255 255 255 / 0.18);
|
||||||
background: var(--m-orange);
|
background: linear-gradient(120deg, #7c5cfc, #5f6cf8 55%, #22d3ee 140%);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
box-shadow: 4px 4px 0 var(--shadow-ink);
|
box-shadow: 0 8px 22px var(--accent-glow);
|
||||||
transition: transform 0.12s ease, box-shadow 0.12s ease;
|
transition: transform 0.12s ease, box-shadow 0.12s ease, filter 0.12s ease;
|
||||||
}
|
}
|
||||||
.cv-gen:hover:not(:disabled) {
|
.cv-gen:hover:not(:disabled) {
|
||||||
transform: translate(-1px, -1px);
|
transform: translateY(-1px);
|
||||||
box-shadow: 5px 5px 0 var(--shadow-ink);
|
filter: brightness(1.07);
|
||||||
|
box-shadow: 0 12px 30px var(--accent-glow);
|
||||||
}
|
}
|
||||||
.cv-gen:active:not(:disabled) {
|
.cv-gen:active:not(:disabled) {
|
||||||
transform: translate(3px, 3px);
|
transform: translateY(1px) scale(0.99);
|
||||||
box-shadow: 1px 1px 0 var(--shadow-ink);
|
box-shadow: 0 4px 12px var(--accent-glow);
|
||||||
}
|
}
|
||||||
.cv-gen:disabled {
|
.cv-gen:disabled {
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
@@ -1137,9 +1151,9 @@ const saveLabel = computed(() => ({
|
|||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #92400e;
|
color: #92400e;
|
||||||
line-height: 1.6;
|
line-height: 1.6;
|
||||||
border: 2px dashed #f59e0b;
|
border: 1px dashed rgb(245 158 11 / 0.6);
|
||||||
border-radius: 9px;
|
border-radius: 9px;
|
||||||
background: var(--m-yellow);
|
background: rgb(245 158 11 / 0.12);
|
||||||
padding: 8px 10px;
|
padding: 8px 10px;
|
||||||
}
|
}
|
||||||
.cv-tips {
|
.cv-tips {
|
||||||
@@ -1163,8 +1177,8 @@ const saveLabel = computed(() => ({
|
|||||||
max-width: 92vw;
|
max-width: 92vw;
|
||||||
max-height: 92vh;
|
max-height: 92vh;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
border: 3px solid #fff;
|
border: 1px solid rgb(255 255 255 / 0.5);
|
||||||
box-shadow: 10px 10px 0 var(--m-orange);
|
box-shadow: 0 24px 60px rgb(0 0 0 / 0.5), 0 0 40px var(--accent-glow);
|
||||||
}
|
}
|
||||||
|
|
||||||
.cv-picker {
|
.cv-picker {
|
||||||
@@ -1179,10 +1193,12 @@ const saveLabel = computed(() => ({
|
|||||||
.cv-picker__box {
|
.cv-picker__box {
|
||||||
width: min(720px, 92vw);
|
width: min(720px, 92vw);
|
||||||
max-height: 80vh;
|
max-height: 80vh;
|
||||||
background: var(--surface);
|
background: var(--menu-bg);
|
||||||
border: 3px solid var(--ink);
|
-webkit-backdrop-filter: blur(20px);
|
||||||
|
backdrop-filter: blur(20px);
|
||||||
|
border: 1px solid var(--glass-border);
|
||||||
border-radius: 16px;
|
border-radius: 16px;
|
||||||
box-shadow: 8px 8px 0 var(--shadow-ink);
|
box-shadow: var(--glass-shadow-lg);
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -1212,13 +1228,14 @@ const saveLabel = computed(() => ({
|
|||||||
aspect-ratio: 1;
|
aspect-ratio: 1;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
border: 2.5px solid var(--ink);
|
border: 1px solid var(--ink-soft);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background: var(--surface-2);
|
background: var(--surface-2);
|
||||||
transition: transform 0.12s ease, box-shadow 0.12s ease;
|
transition: transform 0.12s ease, box-shadow 0.12s ease, border-color 0.12s ease;
|
||||||
}
|
}
|
||||||
.cv-picker__grid img:hover {
|
.cv-picker__grid img:hover {
|
||||||
transform: translate(-2px, -2px);
|
transform: translateY(-2px);
|
||||||
box-shadow: 4px 4px 0 var(--m-orange);
|
border-color: rgb(124 92 252 / 0.55);
|
||||||
|
box-shadow: 0 8px 20px var(--accent-glow);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -677,8 +677,8 @@ html.dark .num, html.dark .txt, html.dark .field {
|
|||||||
}
|
}
|
||||||
.num::placeholder, .txt::placeholder, .field::placeholder { color: var(--fg-faint); }
|
.num::placeholder, .txt::placeholder, .field::placeholder { color: var(--fg-faint); }
|
||||||
.num:focus, .txt:focus, .field:focus {
|
.num:focus, .txt:focus, .field:focus {
|
||||||
border-color: var(--ink);
|
border-color: rgb(124 92 252 / 0.65);
|
||||||
box-shadow: 3px 3px 0 var(--m-orange);
|
box-shadow: 0 0 0 3px rgb(124 92 252 / 0.18);
|
||||||
}
|
}
|
||||||
.num:disabled, .txt:disabled, .field:disabled { opacity: 0.45; cursor: not-allowed; }
|
.num:disabled, .txt:disabled, .field:disabled { opacity: 0.45; cursor: not-allowed; }
|
||||||
.num { width: 6rem; padding: 0.4rem 0.55rem; font-size: 0.8rem; text-align: right; -moz-appearance: textfield; appearance: textfield; }
|
.num { width: 6rem; padding: 0.4rem 0.55rem; font-size: 0.8rem; text-align: right; -moz-appearance: textfield; appearance: textfield; }
|
||||||
@@ -686,24 +686,23 @@ html.dark .num, html.dark .txt, html.dark .field {
|
|||||||
.txt { width: 16rem; max-width: 60%; padding: 0.4rem 0.65rem; font-size: 0.8rem; }
|
.txt { width: 16rem; max-width: 60%; padding: 0.4rem 0.65rem; font-size: 0.8rem; }
|
||||||
.field { width: 100%; padding: 0.55rem 0.75rem; font-size: 0.85rem; }
|
.field { width: 100%; padding: 0.55rem 0.75rem; font-size: 0.85rem; }
|
||||||
|
|
||||||
/* Section save buttons — solid memphis orange with a hard offset shadow.
|
/* Section save buttons — violet→cyan gradient with a glow. The global
|
||||||
The global .btn-primary under .public-dark already uses this palette; we
|
.btn-primary under .public-dark already uses this palette; we re-assert it
|
||||||
re-assert it here so the save action stays visually distinct. */
|
here so the save action stays visually distinct. */
|
||||||
.btn-primary {
|
.btn-primary {
|
||||||
padding: 0.55rem 1.15rem; border-radius: 0.6rem;
|
padding: 0.55rem 1.15rem; border-radius: 0.6rem;
|
||||||
font-size: 0.8rem; font-weight: 800; color: white;
|
font-size: 0.8rem; font-weight: 800; color: white;
|
||||||
background: var(--m-orange);
|
background: linear-gradient(120deg, #7c5cfc, #5f6cf8);
|
||||||
border: 2px solid var(--ink);
|
border: 1px solid rgb(255 255 255 / 0.16);
|
||||||
box-shadow: 3px 3px 0 var(--shadow-ink);
|
box-shadow: 0 6px 18px var(--accent-glow);
|
||||||
transition: filter 0.15s, transform 0.12s, box-shadow 0.15s, opacity 0.15s;
|
transition: filter 0.15s, transform 0.12s, box-shadow 0.15s, opacity 0.15s;
|
||||||
}
|
}
|
||||||
/* Re-assert the flat orange on hover for ALL states — the global
|
/* Keep the gradient on hover for ALL states — the global
|
||||||
`.public-dark .btn-primary:hover` in style.css repaints the background,
|
`.public-dark .btn-primary:hover` in style.css repaints the background,
|
||||||
so even disabled save buttons (注册与登录 / 邮件服务 default to disabled)
|
so even disabled save buttons would flash on hover. Keep this rule
|
||||||
would flash on hover. Keep this rule unconditional; only the
|
unconditional; only the brightness/lift below is gated on :not(:disabled). */
|
||||||
brightness/lift below is gated on :not(:disabled). */
|
.btn-primary:hover { filter: brightness(1.08); }
|
||||||
.btn-primary:hover { background: #f97316; }
|
.btn-primary:hover:not(:disabled) { transform: translateY(-1px); box-shadow: 0 10px 26px var(--accent-glow); }
|
||||||
.btn-primary:hover:not(:disabled) { transform: translate(-1px, -1px); box-shadow: 4px 4px 0 var(--shadow-ink); }
|
.btn-primary:active:not(:disabled) { transform: translateY(1px); box-shadow: none; }
|
||||||
.btn-primary:active:not(:disabled) { transform: translate(2px, 2px); box-shadow: none; }
|
|
||||||
.btn-primary:disabled { opacity: 0.45; cursor: not-allowed; box-shadow: none; }
|
.btn-primary:disabled { opacity: 0.45; cursor: not-allowed; box-shadow: none; }
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
+172
-107
@@ -121,32 +121,32 @@ const caps = computed(() => {
|
|||||||
{
|
{
|
||||||
key: 't2i', title: '文字生图', model: imageModels.value[0]?.id,
|
key: 't2i', title: '文字生图', model: imageModels.value[0]?.id,
|
||||||
desc: '一句话出图,画幅与分辨率按所选模型的可用范围给出。',
|
desc: '一句话出图,画幅与分辨率按所选模型的可用范围给出。',
|
||||||
tint: '#a7f3d0', color: '#065f46',
|
tint: 'linear-gradient(135deg,#34d399,#2dd4bf)', color: '#fff',
|
||||||
metas: [resRange.value, `${imageModels.value.length} 个模型`].filter(Boolean),
|
metas: [resRange.value, `${imageModels.value.length} 个模型`].filter(Boolean),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'i2i', title: '参考图生图', model: i2iModels[0]?.id,
|
key: 'i2i', title: '参考图生图', model: i2iModels[0]?.id,
|
||||||
desc: '上传参考图换风格、改构图、做变体,支持多张参考。',
|
desc: '上传参考图换风格、改构图、做变体,支持多张参考。',
|
||||||
tint: '#ffc1cc', color: '#9f1239',
|
tint: 'linear-gradient(135deg,#e879f9,#f472b6)', color: '#fff',
|
||||||
metas: ['多图参考', `${i2iModels.length} 个模型`],
|
metas: ['多图参考', `${i2iModels.length} 个模型`],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 't2v', title: '文字生视频', model: videoModels.value[0]?.id,
|
key: 't2v', title: '文字生视频', model: videoModels.value[0]?.id,
|
||||||
desc: '一段描述生成短片,时长与分辨率按模型能力可选。',
|
desc: '一段描述生成短片,时长与分辨率按模型能力可选。',
|
||||||
tint: '#bae6fd', color: '#075985',
|
tint: 'linear-gradient(135deg,#38bdf8,#22d3ee)', color: '#fff',
|
||||||
metas: [durationRange.value, videoRes.value, `${videoModels.value.length} 个模型`].filter(Boolean),
|
metas: [durationRange.value, videoRes.value, `${videoModels.value.length} 个模型`].filter(Boolean),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'i2v', title: '图生视频', model: i2vModels[0]?.id,
|
key: 'i2v', title: '图生视频', model: i2vModels[0]?.id,
|
||||||
desc: '给参考图或首帧,让静态画面动起来。',
|
desc: '给参考图或首帧,让静态画面动起来。',
|
||||||
tint: '#fef08a', color: '#92400e',
|
tint: 'linear-gradient(135deg,#7c5cfc,#a855f7)', color: '#fff',
|
||||||
metas: ['参考图', `${i2vModels.length} 个模型`],
|
metas: ['参考图', `${i2vModels.length} 个模型`],
|
||||||
},
|
},
|
||||||
].filter((c) => c.model)
|
].filter((c) => c.model)
|
||||||
})
|
})
|
||||||
|
|
||||||
// ---- model cards: the admin-set alias wins, so no upstream naming leaks ----
|
// ---- model cards: the admin-set alias wins, so no upstream naming leaks ----
|
||||||
const MODEL_TINT = ['#ec5b13', '#ffc1cc', '#bae6fd', '#a7f3d0', '#fef08a', '#f472b6', '#94a3b8']
|
const MODEL_TINT = ['#7c5cfc', '#22d3ee', '#e879f9', '#34d399', '#a78bfa', '#38bdf8', '#94a3b8']
|
||||||
const modelCards = computed(() => managed.value.map((m, i) => {
|
const modelCards = computed(() => managed.value.map((m, i) => {
|
||||||
const bits = []
|
const bits = []
|
||||||
if (m.resolutions?.length) bits.push(m.resolutions.join(' / '))
|
if (m.resolutions?.length) bits.push(m.resolutions.join(' / '))
|
||||||
@@ -201,12 +201,18 @@ function useExample(ex) {
|
|||||||
<section class="hero-band relative overflow-hidden pt-14 md:pt-20 pb-12">
|
<section class="hero-band relative overflow-hidden pt-14 md:pt-20 pb-12">
|
||||||
<div class="anime-stars"></div>
|
<div class="anime-stars"></div>
|
||||||
|
|
||||||
<!-- floating memphis shapes (desktop only) -->
|
<!-- floating aurora shapes (desktop only) -->
|
||||||
<div aria-hidden="true" class="pointer-events-none absolute inset-0 hidden lg:block">
|
<div aria-hidden="true" class="pointer-events-none absolute inset-0 hidden lg:block">
|
||||||
<span class="deco deco-a">🎨</span>
|
<span class="deco deco-a">
|
||||||
<span class="deco deco-b">⚡</span>
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3l1.9 5.8a2 2 0 0 0 1.3 1.3L21 12l-5.8 1.9a2 2 0 0 0-1.3 1.3L12 21l-1.9-5.8a2 2 0 0 0-1.3-1.3L3 12l5.8-1.9a2 2 0 0 0 1.3-1.3z"/></svg>
|
||||||
|
</span>
|
||||||
|
<span class="deco deco-b">
|
||||||
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M13 2 3 14h7l-1 8 10-12h-7z"/></svg>
|
||||||
|
</span>
|
||||||
<span class="deco deco-c">4K</span>
|
<span class="deco deco-c">4K</span>
|
||||||
<span class="deco deco-d">🎬</span>
|
<span class="deco deco-d">
|
||||||
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 6h13v12H3z"/><path d="M16 10l5-3v10l-5-3"/></svg>
|
||||||
|
</span>
|
||||||
<span class="deco deco-star">✦</span>
|
<span class="deco deco-star">✦</span>
|
||||||
<span class="deco deco-star deco-star-2">✦</span>
|
<span class="deco deco-star deco-star-2">✦</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -241,7 +247,7 @@ function useExample(ex) {
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- ============ GALLERY MARQUEE (hero + bento imagery) ============ -->
|
<!-- ============ GALLERY MARQUEE (hero + bento imagery) ============ -->
|
||||||
<section v-if="gallery.length" class="mt-6 -mx-4 md:-mx-8 overflow-hidden marquee-mask border-y-[3px] border-y-[color:var(--ink)] bg-[var(--surface)] py-4">
|
<section v-if="gallery.length" class="mt-6 -mx-4 md:-mx-8 overflow-hidden marquee-mask border-y border-y-[color:var(--ink-soft)] bg-[var(--surface)] py-4">
|
||||||
<div class="marquee flex gap-4 px-4 md:px-8 w-max">
|
<div class="marquee flex gap-4 px-4 md:px-8 w-max">
|
||||||
<button v-for="(card, i) in [...gallery, ...gallery]" :key="card.id + '-' + i" type="button"
|
<button v-for="(card, i) in [...gallery, ...gallery]" :key="card.id + '-' + i" type="button"
|
||||||
class="gcard" :style="cardBg(card)" :aria-label="card.title" @click="useExample(card)">
|
class="gcard" :style="cardBg(card)" :aria-label="card.title" @click="useExample(card)">
|
||||||
@@ -257,17 +263,22 @@ function useExample(ex) {
|
|||||||
<!-- ============ KPI STRIP ============ -->
|
<!-- ============ KPI STRIP ============ -->
|
||||||
<section class="mt-12 grid grid-cols-2 md:grid-cols-4 gap-3">
|
<section class="mt-12 grid grid-cols-2 md:grid-cols-4 gap-3">
|
||||||
<div v-for="k in [
|
<div v-for="k in [
|
||||||
{ v: modelCount, l: '在线模型', e: '🧩', bg: 'var(--m-yellow)' },
|
{ v: modelCount, l: '在线模型', i: 'models', tint: 'linear-gradient(135deg,#7c5cfc,#a855f7)' },
|
||||||
{ v: caps.length, l: '创作方式', e: '🎨', bg: 'var(--m-pink)' },
|
{ v: caps.length, l: '创作方式', i: 'wand', tint: 'linear-gradient(135deg,#e879f9,#f472b6)' },
|
||||||
{ v: resRange, l: '输出分辨率', e: '🖼️', bg: 'var(--m-blue)' },
|
{ v: resRange, l: '输出分辨率', i: 'image', tint: 'linear-gradient(135deg,#38bdf8,#22d3ee)' },
|
||||||
{ v: avgLabel, l: '平均出片 · 近 24h', e: '⚡', bg: 'var(--m-mint)' },
|
{ v: avgLabel, l: '平均出片 · 近 24h', i: 'bolt', tint: 'linear-gradient(135deg,#34d399,#2dd4bf)' },
|
||||||
]" :key="k.l"
|
]" :key="k.l"
|
||||||
class="kpi-card px-5 py-4" :style="{ background: k.bg }">
|
class="kpi-card px-5 py-4">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2.5">
|
||||||
<span class="text-lg">{{ k.e }}</span>
|
<span class="kpi-ico" :style="{ background: k.tint }">
|
||||||
<span class="text-[26px] font-black tabular-nums text-[#111]">{{ k.v }}</span>
|
<svg v-if="k.i === 'models'" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="7" height="7" rx="1.5"/><rect x="14" y="3" width="7" height="7" rx="1.5"/><rect x="3" y="14" width="7" height="7" rx="1.5"/><rect x="14" y="14" width="7" height="7" rx="1.5"/></svg>
|
||||||
|
<svg v-else-if="k.i === 'wand'" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m15 4 5 5L7 22l-5-5z"/><path d="m14 7 3 3"/><path d="M9 6V4M7 8H5M9 10v2M11 8h2"/></svg>
|
||||||
|
<svg v-else-if="k.i === 'image'" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="5" width="18" height="14" rx="2"/><path d="m3 16 5-5 3 3 4-4 6 6"/><circle cx="9" cy="9" r="1.4"/></svg>
|
||||||
|
<svg v-else viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M13 2 3 14h7l-1 8 10-12h-7z"/></svg>
|
||||||
|
</span>
|
||||||
|
<span class="text-[26px] font-black tabular-nums text-[color:var(--fg)]">{{ k.v }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-1.5 text-[10px] font-bold uppercase tracking-[0.18em] text-[#111]/60">{{ k.l }}</div>
|
<div class="mt-1.5 text-[10px] font-bold uppercase tracking-[0.18em] text-[color:var(--fg-3)]">{{ k.l }}</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@@ -371,15 +382,15 @@ function useExample(ex) {
|
|||||||
注册即可开始,图像与视频都能试;不满意就换个模型,额度按次计费。
|
注册即可开始,图像与视频都能试;不满意就换个模型,额度按次计费。
|
||||||
</p>
|
</p>
|
||||||
<button type="button" @click="go('/user')"
|
<button type="button" @click="go('/user')"
|
||||||
class="mt-7 group inline-flex items-center gap-3 rounded-xl bg-[var(--m-orange)] text-white border-[3px] border-[color:var(--ink)] shadow-[5px_5px_0_var(--shadow-ink)] hover:shadow-[7px_7px_0_var(--shadow-ink)] hover:-translate-x-0.5 hover:-translate-y-0.5 active:translate-y-0.5 active:shadow-none pl-6 pr-3 py-3 text-sm font-extrabold transition-all">
|
class="mt-7 group inline-flex items-center gap-3 rounded-xl text-white pl-6 pr-3 py-3 text-sm font-extrabold transition-all cta-go">
|
||||||
免费开始
|
免费开始
|
||||||
<span class="w-8 h-8 rounded-lg bg-white text-[#111] border-2 border-[#111] grid place-items-center font-black group-hover:translate-x-1 transition-transform">→</span>
|
<span class="w-8 h-8 rounded-lg bg-white/20 border border-white/30 grid place-items-center font-black group-hover:translate-x-1 transition-transform">→</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- thin footer line -->
|
<!-- thin footer line -->
|
||||||
<footer class="mt-16 pt-10 border-t-[3px] border-t-[color:var(--ink)] flex flex-wrap items-center justify-between gap-4 text-xs font-semibold text-[color:var(--fg-3)]">
|
<footer class="mt-16 pt-10 border-t border-t-[color:var(--ink-soft)] flex flex-wrap items-center justify-between gap-4 text-xs font-semibold text-[color:var(--fg-3)]">
|
||||||
<div class="flex items-center gap-3">
|
<div class="flex items-center gap-3">
|
||||||
<span class="font-semibold text-[color:var(--fg-2)]">{{ site.title }}</span>
|
<span class="font-semibold text-[color:var(--fg-2)]">{{ site.title }}</span>
|
||||||
<span>·</span>
|
<span>·</span>
|
||||||
@@ -401,15 +412,18 @@ function useExample(ex) {
|
|||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
max-width: 36rem;
|
max-width: 36rem;
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
border-radius: 1rem;
|
border-radius: 1.1rem;
|
||||||
background: var(--surface);
|
background: var(--surface);
|
||||||
border: 3px solid var(--ink);
|
-webkit-backdrop-filter: blur(16px);
|
||||||
box-shadow: 7px 7px 0 var(--shadow-ink);
|
backdrop-filter: blur(16px);
|
||||||
transition: box-shadow 0.2s ease, transform 0.2s ease;
|
border: 1px solid var(--glass-border);
|
||||||
|
box-shadow: var(--glass-shadow-lg);
|
||||||
|
transition: box-shadow 0.2s ease, transform 0.2s ease, border-color 0.2s ease;
|
||||||
}
|
}
|
||||||
.composer:focus-within {
|
.composer:focus-within {
|
||||||
transform: translate(-2px, -2px);
|
transform: translateY(-2px);
|
||||||
box-shadow: 10px 10px 0 var(--m-orange);
|
border-color: rgb(124 92 252 / 0.5);
|
||||||
|
box-shadow: 0 18px 50px var(--accent-glow), var(--glass-shadow);
|
||||||
}
|
}
|
||||||
.composer-input {
|
.composer-input {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
@@ -425,48 +439,50 @@ function useExample(ex) {
|
|||||||
.composer-input::placeholder { color: var(--fg-faint); }
|
.composer-input::placeholder { color: var(--fg-faint); }
|
||||||
.composer-go {
|
.composer-go {
|
||||||
flex: none;
|
flex: none;
|
||||||
border: 2.5px solid var(--ink);
|
border: 1px solid rgb(255 255 255 / 0.16);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
padding: 0.65rem 1.2rem;
|
padding: 0.65rem 1.2rem;
|
||||||
border-radius: 0.7rem;
|
border-radius: 0.75rem;
|
||||||
background: var(--m-orange);
|
background: linear-gradient(120deg, #7c5cfc, #5f6cf8 55%, #22d3ee 140%);
|
||||||
box-shadow: 3px 3px 0 var(--shadow-ink);
|
box-shadow: 0 6px 18px var(--accent-glow);
|
||||||
transition: transform 0.15s ease, box-shadow 0.15s ease, filter 0.15s ease;
|
transition: transform 0.15s ease, box-shadow 0.15s ease, filter 0.15s ease;
|
||||||
}
|
}
|
||||||
.composer-go:hover { transform: translate(-1px, -1px); box-shadow: 4px 4px 0 var(--shadow-ink); filter: brightness(1.06); }
|
.composer-go:hover { transform: translateY(-1px); box-shadow: 0 10px 26px var(--accent-glow); filter: brightness(1.07); }
|
||||||
.composer-go:active { transform: scale(0.96) translateY(2px); box-shadow: 0 0 0 var(--shadow-ink); }
|
.composer-go:active { transform: scale(0.96) translateY(1px); box-shadow: 0 3px 10px var(--accent-glow); }
|
||||||
|
|
||||||
.chip {
|
.chip {
|
||||||
font-size: 12.5px;
|
font-size: 12.5px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: var(--fg-2);
|
color: var(--fg-2);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border: 2px solid var(--ink);
|
border: 1px solid var(--ink-soft);
|
||||||
padding: 0.4rem 0.8rem;
|
padding: 0.4rem 0.8rem;
|
||||||
border-radius: 0.6rem;
|
border-radius: 999px;
|
||||||
background: var(--surface);
|
background: var(--surface);
|
||||||
transition: color 0.15s ease, background 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease;
|
-webkit-backdrop-filter: blur(10px);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
transition: color 0.15s ease, background 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease, border-color 0.15s ease;
|
||||||
}
|
}
|
||||||
.chip:hover {
|
.chip:hover {
|
||||||
color: #111;
|
color: var(--fg);
|
||||||
background: var(--m-yellow);
|
background: var(--hover);
|
||||||
box-shadow: 3px 3px 0 var(--shadow-ink);
|
border-color: rgb(124 92 252 / 0.45);
|
||||||
transform: translate(-1px, -1px);
|
box-shadow: 0 4px 14px rgb(124 92 252 / 0.18);
|
||||||
|
transform: translateY(-1px);
|
||||||
}
|
}
|
||||||
html.dark .chip:hover { color: #111; }
|
|
||||||
|
|
||||||
/* ---------- hero cards (kind=hero) ---------- */
|
/* ---------- hero cards (kind=hero) ---------- */
|
||||||
.fcard {
|
.fcard {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
border: 3px solid var(--ink);
|
border: 1px solid var(--glass-border);
|
||||||
padding: 0;
|
padding: 0;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border-radius: 1rem;
|
border-radius: 1.1rem;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
box-shadow: 7px 7px 0 var(--shadow-ink);
|
box-shadow: var(--glass-shadow-lg);
|
||||||
transition: transform 0.45s cubic-bezier(0.2, 0.7, 0.2, 1);
|
transition: transform 0.45s cubic-bezier(0.2, 0.7, 0.2, 1);
|
||||||
animation: fcardIn 0.7s cubic-bezier(0.2, 0.7, 0.2, 1) backwards;
|
animation: fcardIn 0.7s cubic-bezier(0.2, 0.7, 0.2, 1) backwards;
|
||||||
}
|
}
|
||||||
@@ -511,28 +527,46 @@ html.dark .chip:hover { color: #111; }
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border: 2.5px solid var(--ink);
|
border: 1px solid var(--glass-border);
|
||||||
padding: 1.35rem;
|
padding: 1.35rem;
|
||||||
border-radius: 1rem;
|
border-radius: 1.1rem;
|
||||||
background: var(--surface);
|
background: var(--surface);
|
||||||
box-shadow: 5px 5px 0 var(--shadow-ink);
|
-webkit-backdrop-filter: blur(14px);
|
||||||
transition: transform 0.18s ease, box-shadow 0.18s ease;
|
backdrop-filter: blur(14px);
|
||||||
|
box-shadow: var(--glass-shadow);
|
||||||
|
transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease;
|
||||||
|
}
|
||||||
|
.cap-card::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: -3rem;
|
||||||
|
right: -3rem;
|
||||||
|
width: 9rem;
|
||||||
|
height: 9rem;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: radial-gradient(circle, rgb(124 92 252 / 0.22), transparent 65%);
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.25s ease;
|
||||||
}
|
}
|
||||||
.cap-card:hover {
|
.cap-card:hover {
|
||||||
transform: translate(-3px, -3px);
|
transform: translateY(-4px);
|
||||||
box-shadow: 9px 9px 0 var(--m-orange);
|
border-color: rgb(124 92 252 / 0.45);
|
||||||
|
box-shadow: var(--glass-shadow-lg), 0 10px 30px rgb(124 92 252 / 0.14);
|
||||||
}
|
}
|
||||||
html.dark .cap-card { background: rgb(255 255 255 / 0.05); }
|
.cap-card:hover::before { opacity: 1; }
|
||||||
.cap-arrow { position: absolute; top: 1.1rem; right: 1.1rem; color: var(--fg-3); transition: color 0.15s ease; }
|
.cap-arrow { position: absolute; top: 1.1rem; right: 1.1rem; color: var(--fg-3); transition: color 0.15s ease, transform 0.15s ease; }
|
||||||
.cap-card:hover .cap-arrow { color: var(--m-orange); }
|
.cap-card:hover .cap-arrow { color: var(--m-orange); transform: translate(2px, -2px); }
|
||||||
.cap-icon {
|
.cap-icon {
|
||||||
|
position: relative;
|
||||||
width: 2.6rem;
|
width: 2.6rem;
|
||||||
height: 2.6rem;
|
height: 2.6rem;
|
||||||
border-radius: 0.7rem;
|
border-radius: 0.8rem;
|
||||||
border: 2px solid var(--ink);
|
border: 1px solid var(--ink-soft);
|
||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
margin-bottom: 0.9rem;
|
margin-bottom: 0.9rem;
|
||||||
|
-webkit-backdrop-filter: blur(8px);
|
||||||
|
backdrop-filter: blur(8px);
|
||||||
}
|
}
|
||||||
.cap-icon svg { width: 1.25rem; height: 1.25rem; }
|
.cap-icon svg { width: 1.25rem; height: 1.25rem; }
|
||||||
.cap-meta {
|
.cap-meta {
|
||||||
@@ -542,7 +576,7 @@ html.dark .cap-card { background: rgb(255 255 255 / 0.05); }
|
|||||||
color: var(--fg-2);
|
color: var(--fg-2);
|
||||||
padding: 0.18rem 0.5rem;
|
padding: 0.18rem 0.5rem;
|
||||||
border-radius: 0.4rem;
|
border-radius: 0.4rem;
|
||||||
border: 1.5px solid var(--ink-soft);
|
border: 1px solid var(--ink-soft);
|
||||||
background: var(--surface-2);
|
background: var(--surface-2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -550,14 +584,14 @@ html.dark .cap-card { background: rgb(255 255 255 / 0.05); }
|
|||||||
.tile {
|
.tile {
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
border: 2.5px solid var(--ink);
|
border: 1px solid var(--glass-border);
|
||||||
padding: 0;
|
padding: 0;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border-radius: 1rem;
|
border-radius: 1.1rem;
|
||||||
box-shadow: 5px 5px 0 var(--shadow-ink);
|
box-shadow: var(--glass-shadow);
|
||||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
|
||||||
}
|
}
|
||||||
.tile:hover { transform: translate(-2px, -2px); box-shadow: 8px 8px 0 var(--m-blue); }
|
.tile:hover { transform: translateY(-3px); border-color: rgb(34 211 238 / 0.5); box-shadow: var(--glass-shadow-lg), 0 10px 30px rgb(34 211 238 / 0.14); }
|
||||||
.tile-veil {
|
.tile-veil {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
@@ -584,14 +618,14 @@ html.dark .cap-card { background: rgb(255 255 255 / 0.05); }
|
|||||||
display: block;
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
border: 2.5px solid var(--ink);
|
border: 1px solid var(--glass-border);
|
||||||
padding: 0;
|
padding: 0;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border-radius: 1rem;
|
border-radius: 1.1rem;
|
||||||
box-shadow: 5px 5px 0 var(--shadow-ink);
|
box-shadow: var(--glass-shadow);
|
||||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
|
||||||
}
|
}
|
||||||
.work:hover { transform: translate(-2px, -2px); box-shadow: 8px 8px 0 var(--m-pink); }
|
.work:hover { transform: translateY(-3px); border-color: rgb(232 121 249 / 0.5); box-shadow: var(--glass-shadow-lg), 0 10px 30px rgb(232 121 249 / 0.14); }
|
||||||
.work-img { display: block; width: 100%; aspect-ratio: 4 / 5; transition: transform 0.5s ease; }
|
.work-img { display: block; width: 100%; aspect-ratio: 4 / 5; transition: transform 0.5s ease; }
|
||||||
.work:hover .work-img { transform: scale(1.04); }
|
.work:hover .work-img { transform: scale(1.04); }
|
||||||
.work-overlay {
|
.work-overlay {
|
||||||
@@ -627,11 +661,12 @@ html.dark .cap-card { background: rgb(255 255 255 / 0.05); }
|
|||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
color: rgb(11 13 19);
|
color: #fff;
|
||||||
background: var(--m-yellow);
|
background: linear-gradient(120deg, #7c5cfc, #22d3ee);
|
||||||
border: 2px solid #111;
|
border: 1px solid rgb(255 255 255 / 0.25);
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
padding: 0.4rem 0.8rem;
|
padding: 0.4rem 0.8rem;
|
||||||
|
box-shadow: 0 4px 14px rgb(124 92 252 / 0.4);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------- model row ---------- */
|
/* ---------- model row ---------- */
|
||||||
@@ -643,14 +678,15 @@ html.dark .cap-card { background: rgb(255 255 255 / 0.05); }
|
|||||||
width: 14.5rem;
|
width: 14.5rem;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
padding: 1.25rem;
|
padding: 1.25rem;
|
||||||
border-radius: 1rem;
|
border-radius: 1.1rem;
|
||||||
border: 2.5px solid var(--ink);
|
border: 1px solid var(--glass-border);
|
||||||
background: var(--surface);
|
background: var(--surface);
|
||||||
box-shadow: 5px 5px 0 var(--shadow-ink);
|
-webkit-backdrop-filter: blur(14px);
|
||||||
transition: box-shadow 0.18s ease, transform 0.18s ease;
|
backdrop-filter: blur(14px);
|
||||||
|
box-shadow: var(--glass-shadow);
|
||||||
|
transition: box-shadow 0.18s ease, transform 0.18s ease, border-color 0.18s ease;
|
||||||
}
|
}
|
||||||
.model-card:hover { transform: translate(-2px, -2px); box-shadow: 8px 8px 0 var(--m-mint); }
|
.model-card:hover { transform: translateY(-3px); border-color: rgb(124 92 252 / 0.45); box-shadow: var(--glass-shadow-lg); }
|
||||||
html.dark .model-card { background: rgb(255 255 255 / 0.05); }
|
|
||||||
.model-glow {
|
.model-glow {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -2.5rem;
|
top: -2.5rem;
|
||||||
@@ -659,39 +695,43 @@ html.dark .model-card { background: rgb(255 255 255 / 0.05); }
|
|||||||
height: 8rem;
|
height: 8rem;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
filter: blur(40px);
|
filter: blur(40px);
|
||||||
opacity: 0.3;
|
opacity: 0.35;
|
||||||
}
|
}
|
||||||
.model-tag {
|
.model-tag {
|
||||||
font-size: 10.5px;
|
font-size: 10.5px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
padding: 0.18rem 0.55rem;
|
padding: 0.18rem 0.55rem;
|
||||||
border-radius: 0.4rem;
|
border-radius: 0.4rem;
|
||||||
border: 1.5px solid var(--ink);
|
border: 1px solid var(--ink-soft);
|
||||||
}
|
}
|
||||||
.model-tag.is-image { background: var(--m-mint); color: #065f46; }
|
.model-tag.is-image { background: rgb(52 211 153 / 0.16); color: rgb(5 150 105); border-color: rgb(52 211 153 / 0.4); }
|
||||||
.model-tag.is-video { background: var(--m-blue); color: #075985; }
|
.model-tag.is-video { background: rgb(34 211 238 / 0.16); color: rgb(8 145 178); border-color: rgb(34 211 238 / 0.4); }
|
||||||
|
html.dark .model-tag.is-image { color: rgb(110 231 183); }
|
||||||
|
html.dark .model-tag.is-video { color: rgb(103 232 249); }
|
||||||
|
|
||||||
/* ---------- hero band + memphis deco ---------- */
|
/* ---------- hero band + aurora deco ---------- */
|
||||||
.hero-band {
|
.hero-band {
|
||||||
border-radius: 2rem;
|
border-radius: 2rem;
|
||||||
}
|
}
|
||||||
/* Floating crayon chips scattered around the headline — each is a small
|
/* Floating glass chips scattered around the headline — each is a small
|
||||||
ink-outlined tile with a hard shadow and its own idle animation. */
|
frosted tile with a soft shadow and its own idle animation. */
|
||||||
.deco {
|
.deco {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
border: 3px solid var(--ink);
|
border: 1px solid var(--glass-border);
|
||||||
box-shadow: 5px 5px 0 var(--shadow-ink);
|
box-shadow: var(--glass-shadow);
|
||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
color: #111;
|
color: var(--fg);
|
||||||
|
background: var(--surface);
|
||||||
|
-webkit-backdrop-filter: blur(12px);
|
||||||
|
backdrop-filter: blur(12px);
|
||||||
}
|
}
|
||||||
|
.deco svg { width: 45%; height: 45%; color: var(--m-orange); }
|
||||||
.deco-a {
|
.deco-a {
|
||||||
left: 7%; top: 22%;
|
left: 7%; top: 22%;
|
||||||
width: 3.6rem; height: 3.6rem;
|
width: 3.6rem; height: 3.6rem;
|
||||||
border-radius: 0.9rem;
|
border-radius: 1rem;
|
||||||
background: var(--m-yellow);
|
|
||||||
font-size: 1.5rem;
|
|
||||||
transform: rotate(-8deg);
|
transform: rotate(-8deg);
|
||||||
animation: memphis-float 6s ease-in-out infinite;
|
animation: memphis-float 6s ease-in-out infinite;
|
||||||
}
|
}
|
||||||
@@ -699,34 +739,35 @@ html.dark .model-card { background: rgb(255 255 255 / 0.05); }
|
|||||||
right: 8%; top: 16%;
|
right: 8%; top: 16%;
|
||||||
width: 3rem; height: 3rem;
|
width: 3rem; height: 3rem;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
background: var(--m-pink);
|
|
||||||
font-size: 1.2rem;
|
|
||||||
transform: rotate(6deg);
|
transform: rotate(6deg);
|
||||||
animation: memphis-wiggle 3.5s ease-in-out infinite;
|
animation: memphis-wiggle 3.5s ease-in-out infinite;
|
||||||
}
|
}
|
||||||
|
.deco-b svg { color: var(--m-orange-2); }
|
||||||
.deco-c {
|
.deco-c {
|
||||||
left: 13%; bottom: 16%;
|
left: 13%; bottom: 16%;
|
||||||
width: 3.2rem; height: 2.4rem;
|
width: 3.2rem; height: 2.4rem;
|
||||||
border-radius: 0.6rem;
|
border-radius: 0.7rem;
|
||||||
background: var(--m-blue);
|
|
||||||
font-size: 0.95rem;
|
font-size: 0.95rem;
|
||||||
letter-spacing: 0.05em;
|
letter-spacing: 0.05em;
|
||||||
|
color: var(--m-orange);
|
||||||
transform: rotate(9deg);
|
transform: rotate(9deg);
|
||||||
animation: memphis-float 7s ease-in-out infinite reverse;
|
animation: memphis-float 7s ease-in-out infinite reverse;
|
||||||
}
|
}
|
||||||
.deco-d {
|
.deco-d {
|
||||||
right: 13%; bottom: 20%;
|
right: 13%; bottom: 20%;
|
||||||
width: 3.4rem; height: 2.6rem;
|
width: 3.4rem; height: 2.6rem;
|
||||||
border-radius: 0.7rem;
|
border-radius: 0.8rem;
|
||||||
background: var(--m-mint);
|
|
||||||
font-size: 1.15rem;
|
|
||||||
transform: rotate(-7deg);
|
transform: rotate(-7deg);
|
||||||
animation: memphis-bounce 4s ease-in-out infinite;
|
animation: memphis-bounce 4s ease-in-out infinite;
|
||||||
}
|
}
|
||||||
|
.deco-d svg { color: #34d399; }
|
||||||
.deco-star {
|
.deco-star {
|
||||||
left: 22%; top: 10%;
|
left: 22%; top: 10%;
|
||||||
border: none;
|
border: none;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
|
background: transparent;
|
||||||
|
-webkit-backdrop-filter: none;
|
||||||
|
backdrop-filter: none;
|
||||||
font-size: 1.7rem;
|
font-size: 1.7rem;
|
||||||
color: var(--m-orange);
|
color: var(--m-orange);
|
||||||
animation: memphis-wiggle 4s ease-in-out infinite;
|
animation: memphis-wiggle 4s ease-in-out infinite;
|
||||||
@@ -739,14 +780,37 @@ html.dark .model-card { background: rgb(255 255 255 / 0.05); }
|
|||||||
}
|
}
|
||||||
@media (prefers-reduced-motion: reduce) { .deco { animation: none; } }
|
@media (prefers-reduced-motion: reduce) { .deco { animation: none; } }
|
||||||
|
|
||||||
/* KPI tiles — flat crayon fills, dark ink type (readable in both themes). */
|
/* KPI tiles — frosted cards with a gradient icon chip. */
|
||||||
.kpi-card {
|
.kpi-card {
|
||||||
border: 2.5px solid var(--ink);
|
border: 1px solid var(--glass-border);
|
||||||
border-radius: 1rem;
|
border-radius: 1.1rem;
|
||||||
box-shadow: 5px 5px 0 var(--shadow-ink);
|
background: var(--surface);
|
||||||
transition: transform 0.18s ease, box-shadow 0.18s ease;
|
-webkit-backdrop-filter: blur(14px);
|
||||||
|
backdrop-filter: blur(14px);
|
||||||
|
box-shadow: var(--glass-shadow);
|
||||||
|
transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease;
|
||||||
}
|
}
|
||||||
.kpi-card:hover { transform: translate(-2px, -2px); box-shadow: 8px 8px 0 var(--shadow-ink); }
|
.kpi-card:hover { transform: translateY(-3px); border-color: rgb(124 92 252 / 0.4); box-shadow: var(--glass-shadow-lg); }
|
||||||
|
.kpi-ico {
|
||||||
|
width: 2rem;
|
||||||
|
height: 2rem;
|
||||||
|
border-radius: 0.6rem;
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
color: #fff;
|
||||||
|
flex: none;
|
||||||
|
box-shadow: 0 4px 12px rgb(124 92 252 / 0.3);
|
||||||
|
}
|
||||||
|
.kpi-ico svg { width: 1.05rem; height: 1.05rem; }
|
||||||
|
|
||||||
|
/* ---------- CTA button ---------- */
|
||||||
|
.cta-go {
|
||||||
|
background: linear-gradient(120deg, #7c5cfc, #5f6cf8 55%, #22d3ee 140%);
|
||||||
|
border: 1px solid rgb(255 255 255 / 0.2);
|
||||||
|
box-shadow: 0 10px 30px var(--accent-glow);
|
||||||
|
}
|
||||||
|
.cta-go:hover { transform: translateY(-2px); box-shadow: 0 14px 38px var(--accent-glow); filter: brightness(1.07); }
|
||||||
|
.cta-go:active { transform: translateY(1px) scale(0.98); box-shadow: 0 4px 14px var(--accent-glow); }
|
||||||
|
|
||||||
/* ---------- gallery marquee ---------- */
|
/* ---------- gallery marquee ---------- */
|
||||||
.marquee-mask {
|
.marquee-mask {
|
||||||
@@ -767,18 +831,19 @@ html.dark .model-card { background: rgb(255 255 255 / 0.05); }
|
|||||||
width: 15rem;
|
width: 15rem;
|
||||||
height: 10rem;
|
height: 10rem;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
border: 2.5px solid var(--ink);
|
border: 1px solid var(--glass-border);
|
||||||
padding: 0;
|
padding: 0;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border-radius: 1rem;
|
border-radius: 1rem;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
box-shadow: 4px 4px 0 var(--shadow-ink);
|
box-shadow: var(--glass-shadow);
|
||||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
|
||||||
}
|
}
|
||||||
.gcard:hover {
|
.gcard:hover {
|
||||||
transform: translate(-2px, -2px);
|
transform: translateY(-3px);
|
||||||
box-shadow: 7px 7px 0 var(--m-orange);
|
border-color: rgb(124 92 252 / 0.5);
|
||||||
|
box-shadow: var(--glass-shadow-lg), 0 10px 30px rgb(124 92 252 / 0.16);
|
||||||
}
|
}
|
||||||
@media (prefers-reduced-motion: reduce) {
|
@media (prefers-reduced-motion: reduce) {
|
||||||
.marquee { animation: none; }
|
.marquee { animation: none; }
|
||||||
|
|||||||
@@ -328,7 +328,7 @@ onUnmounted(() => window.removeEventListener('keydown', onKey))
|
|||||||
<span v-if="f.resolution" class="text-emerald-300/90">{{ f.resolution }}</span>
|
<span v-if="f.resolution" class="text-emerald-300/90">{{ f.resolution }}</span>
|
||||||
<span v-if="f.ratio" class="text-white/40">{{ f.ratio }}</span>
|
<span v-if="f.ratio" class="text-white/40">{{ f.ratio }}</span>
|
||||||
<span v-if="f.kind === 'video' && f.duration" class="text-rose-300/80">{{ f.duration }}</span>
|
<span v-if="f.kind === 'video' && f.duration" class="text-rose-300/80">{{ f.duration }}</span>
|
||||||
<span v-if="f.deai" class="text-[#ec5b13]">去AI</span>
|
<span v-if="f.deai" class="text-[#a78bfa]">去AI</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-[10px] text-white/35 mt-0.5 tabular-nums">{{ fmtSize(f.size) }} · {{ fmtTs(f.mtime) }}</div>
|
<div class="text-[10px] text-white/35 mt-0.5 tabular-nums">{{ fmtSize(f.size) }} · {{ fmtTs(f.mtime) }}</div>
|
||||||
|
|||||||
@@ -80,26 +80,27 @@ function toast(m) {
|
|||||||
<div class="theme-text space-y-10">
|
<div class="theme-text space-y-10">
|
||||||
<!-- header -->
|
<!-- header -->
|
||||||
<header>
|
<header>
|
||||||
<span class="sticker">🎀 奖励</span>
|
<span class="sticker">✦ 奖励</span>
|
||||||
<h1 class="mt-3 text-4xl md:text-5xl font-bold tracking-tight">邀请好友</h1>
|
<h1 class="mt-3 text-4xl md:text-5xl font-bold tracking-tight">邀请好友</h1>
|
||||||
<p class="text-white/45 mt-2">好友用你的链接注册,并完成首次生图后,你得 {{ INVITE_REWARD }} 积分。</p>
|
<p class="text-white/45 mt-2">好友用你的链接注册,并完成首次生图后,你得 {{ INVITE_REWARD }} 积分。</p>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<section class="relative rounded-2xl p-7 md:p-8 overflow-hidden ink-card">
|
<section class="relative rounded-2xl p-7 md:p-8 overflow-hidden ink-card">
|
||||||
<div class="memphis-dots absolute inset-0 opacity-30 pointer-events-none"></div>
|
<div class="memphis-dots absolute inset-0 opacity-30 pointer-events-none"></div>
|
||||||
<div class="relative inline-grid w-11 h-11 rounded-xl bg-[var(--m-yellow)] border-2 border-[color:var(--ink)] shadow-[3px_3px_0_var(--shadow-ink)] grid place-items-center text-[#111]">
|
<div class="relative inline-grid w-11 h-11 rounded-xl text-white place-items-center"
|
||||||
|
style="background: linear-gradient(135deg, #7c5cfc, #22d3ee); box-shadow: 0 8px 20px var(--accent-glow)">
|
||||||
<Icon name="accounts" class="w-5 h-5" />
|
<Icon name="accounts" class="w-5 h-5" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- summary -->
|
<!-- summary -->
|
||||||
<div class="relative mt-6 grid grid-cols-2 gap-3">
|
<div class="relative mt-6 grid grid-cols-2 gap-3">
|
||||||
<div class="rounded-xl px-4 py-3 border-2 border-[color:var(--ink)] bg-[var(--m-mint)] shadow-[3px_3px_0_var(--shadow-ink)]">
|
<div class="rounded-xl px-4 py-3 border border-[color:var(--glass-border)] bg-[var(--surface)] shadow-[var(--glass-shadow)]">
|
||||||
<div class="text-2xl font-black tabular-nums text-[#111]">{{ inviteCount }}</div>
|
<div class="text-2xl font-black tabular-nums text-[color:var(--fg)]">{{ inviteCount }}</div>
|
||||||
<div class="text-[10px] text-[#111]/55 mt-1 uppercase tracking-widest font-bold">已邀请</div>
|
<div class="text-[10px] text-[color:var(--fg-3)] mt-1 uppercase tracking-widest font-bold">已邀请</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="rounded-xl px-4 py-3 border-2 border-[color:var(--ink)] bg-[var(--m-blue)] shadow-[3px_3px_0_var(--shadow-ink)]">
|
<div class="rounded-xl px-4 py-3 border border-[color:var(--glass-border)] bg-[var(--surface)] shadow-[var(--glass-shadow)]">
|
||||||
<div class="text-2xl font-black tabular-nums text-[#111]">{{ inviteEarned.toLocaleString('en-US') }}</div>
|
<div class="text-2xl font-black tabular-nums text-[color:var(--fg)]">{{ inviteEarned.toLocaleString('en-US') }}</div>
|
||||||
<div class="text-[10px] text-[#111]/55 mt-1 uppercase tracking-widest font-bold">累计积分</div>
|
<div class="text-[10px] text-[color:var(--fg-3)] mt-1 uppercase tracking-widest font-bold">累计积分</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -108,11 +109,12 @@ function toast(m) {
|
|||||||
<label class="block text-xs font-bold text-white/50 mb-2">邀请码</label>
|
<label class="block text-xs font-bold text-white/50 mb-2">邀请码</label>
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<button @click="copyCode"
|
<button @click="copyCode"
|
||||||
class="flex-1 rounded-xl border-2 border-[color:var(--ink)] bg-[var(--surface)] px-4 py-3 text-sm font-mono text-left shadow-[3px_3px_0_var(--shadow-ink)] hover:-translate-y-0.5 hover:shadow-[4px_4px_0_var(--shadow-ink)] transition-all">
|
class="flex-1 rounded-xl border border-[color:var(--ink-soft)] bg-[var(--surface)] px-4 py-3 text-sm font-mono text-left shadow-[var(--glass-shadow)] hover:-translate-y-0.5 hover:border-[rgb(124_92_252/0.45)] transition-all">
|
||||||
{{ inviteCode || '—' }}
|
{{ inviteCode || '—' }}
|
||||||
</button>
|
</button>
|
||||||
<button @click="copyInvite"
|
<button @click="copyInvite"
|
||||||
class="rounded-xl border-[2.5px] border-[color:var(--ink)] bg-[var(--m-orange)] text-white px-5 py-3 text-sm font-extrabold shadow-[3px_3px_0_var(--shadow-ink)] hover:-translate-y-0.5 hover:shadow-[4px_4px_0_var(--shadow-ink)] active:translate-y-0.5 active:shadow-none transition-all">
|
class="rounded-xl border border-white/20 text-white px-5 py-3 text-sm font-extrabold hover:-translate-y-0.5 active:translate-y-0.5 transition-all"
|
||||||
|
style="background: linear-gradient(120deg, #7c5cfc, #22d3ee); box-shadow: 0 8px 20px var(--accent-glow)">
|
||||||
复制链接
|
复制链接
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -327,7 +327,7 @@ const sourcePill = (s) => ({
|
|||||||
</template>
|
</template>
|
||||||
<template v-if="e.deai">
|
<template v-if="e.deai">
|
||||||
<span class="text-white/25 mx-1.5">·</span>
|
<span class="text-white/25 mx-1.5">·</span>
|
||||||
<span class="text-[#ec5b13]">去AI特征</span>
|
<span class="text-[#a78bfa]">去AI特征</span>
|
||||||
</template>
|
</template>
|
||||||
</td>
|
</td>
|
||||||
<td class="px-3 py-3.5 text-right text-xs tabular-nums align-middle whitespace-nowrap">
|
<td class="px-3 py-3.5 text-right text-xs tabular-nums align-middle whitespace-nowrap">
|
||||||
|
|||||||
@@ -1058,7 +1058,7 @@ onUnmounted(() => {
|
|||||||
<div class="pg-cap text-[11px] leading-tight font-medium line-clamp-2 transition-colors"
|
<div class="pg-cap text-[11px] leading-tight font-medium line-clamp-2 transition-colors"
|
||||||
:class="item.prompt ? 'pointer-events-auto cursor-pointer' : ''"
|
:class="item.prompt ? 'pointer-events-auto cursor-pointer' : ''"
|
||||||
:title="item.prompt ? '点击复制提示词' : ''" @click.stop="copyPrompt(item)">{{ item.prompt }}</div>
|
:title="item.prompt ? '点击复制提示词' : ''" @click.stop="copyPrompt(item)">{{ item.prompt }}</div>
|
||||||
<div class="pg-cap-sub text-[9px] mt-0.5 font-mono truncate">{{ item.model }}<span v-if="item.deai"> · <span class="text-[#ec5b13]">去AI</span></span><span v-if="item.elapsed_ms"> · {{ (item.elapsed_ms / 1000).toFixed(1) }}s</span></div>
|
<div class="pg-cap-sub text-[9px] mt-0.5 font-mono truncate">{{ item.model }}<span v-if="item.deai"> · <span class="text-[#a78bfa]">去AI</span></span><span v-if="item.elapsed_ms"> · {{ (item.elapsed_ms / 1000).toFixed(1) }}s</span></div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<!-- pending / running -->
|
<!-- pending / running -->
|
||||||
|
|||||||
@@ -273,7 +273,7 @@ async function recharge() {
|
|||||||
<section class="lg:col-span-2 card overflow-hidden">
|
<section class="lg:col-span-2 card overflow-hidden">
|
||||||
<div class="p-7 md:p-8 relative">
|
<div class="p-7 md:p-8 relative">
|
||||||
<div class="absolute -top-16 -right-16 w-48 h-48 rounded-full opacity-30 blur-3xl"
|
<div class="absolute -top-16 -right-16 w-48 h-48 rounded-full opacity-30 blur-3xl"
|
||||||
style="background: radial-gradient(circle,#f97316,transparent 60%)"></div>
|
style="background: radial-gradient(circle,#8b5cf6,transparent 60%)"></div>
|
||||||
<div class="relative grid md:grid-cols-[260px_1fr] gap-8 items-start">
|
<div class="relative grid md:grid-cols-[260px_1fr] gap-8 items-start">
|
||||||
<div>
|
<div>
|
||||||
<div class="inline-grid w-10 h-10 rounded-xl bg-orange-500/15 ring-1 ring-orange-400/30 grid place-items-center text-orange-300">
|
<div class="inline-grid w-10 h-10 rounded-xl bg-orange-500/15 ring-1 ring-orange-400/30 grid place-items-center text-orange-300">
|
||||||
|
|||||||
@@ -257,7 +257,7 @@ const params = (e) => {
|
|||||||
:title="e.error + ' — 点击复制'"
|
:title="e.error + ' — 点击复制'"
|
||||||
@click.stop="copyError(e)">⚠ {{ e.error }}</div>
|
@click.stop="copyError(e)">⚠ {{ e.error }}</div>
|
||||||
</td>
|
</td>
|
||||||
<td class="px-3 py-3 align-middle text-xs text-slate-500 tabular-nums">{{ params(e) || '—' }}<span v-if="e.deai"> · <span class="text-[#ec5b13]">去AI特征</span></span></td>
|
<td class="px-3 py-3 align-middle text-xs text-slate-500 tabular-nums">{{ params(e) || '—' }}<span v-if="e.deai"> · <span class="text-[#a78bfa]">去AI特征</span></span></td>
|
||||||
<td class="px-3 py-3 align-middle text-right text-xs text-slate-700 tabular-nums">{{ e.cost ? points(e.cost) : '—' }}</td>
|
<td class="px-3 py-3 align-middle text-right text-xs text-slate-700 tabular-nums">{{ e.cost ? points(e.cost) : '—' }}</td>
|
||||||
<td class="px-3 py-3 align-middle text-right text-xs text-slate-500 tabular-nums">{{ e.elapsed_ms ? (e.elapsed_ms / 1000).toFixed(1) + 's' : '—' }}</td>
|
<td class="px-3 py-3 align-middle text-right text-xs text-slate-500 tabular-nums">{{ e.elapsed_ms ? (e.elapsed_ms / 1000).toFixed(1) + 's' : '—' }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -361,7 +361,7 @@ onUnmounted(() => {
|
|||||||
<span v-if="e.resolution" class="text-emerald-300/90">{{ e.resolution }}</span>
|
<span v-if="e.resolution" class="text-emerald-300/90">{{ e.resolution }}</span>
|
||||||
<span v-if="e.ratio" class="text-white/40">{{ e.ratio }}</span>
|
<span v-if="e.ratio" class="text-white/40">{{ e.ratio }}</span>
|
||||||
<span v-if="e.kind === 'video' && e.duration" class="text-rose-300/80">{{ e.duration }}</span>
|
<span v-if="e.kind === 'video' && e.duration" class="text-rose-300/80">{{ e.duration }}</span>
|
||||||
<span v-if="e.deai" class="text-[#ec5b13]">去AI</span>
|
<span v-if="e.deai" class="text-[#a78bfa]">去AI</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-[10px] text-white/35 mt-0.5 tabular-nums">{{ fmtTs(e.ts) }}<span v-if="e.elapsed_ms"> · {{ fmtMs(e.elapsed_ms) }}</span></div>
|
<div class="text-[10px] text-white/35 mt-0.5 tabular-nums">{{ fmtTs(e.ts) }}<span v-if="e.elapsed_ms"> · {{ fmtMs(e.elapsed_ms) }}</span></div>
|
||||||
|
|||||||
Reference in New Issue
Block a user