generated from alphane/template
First draft of HomePageUpgrade from claude
This commit is contained in:
+598
-11
@@ -1,28 +1,615 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div class="home-page">
|
||||||
<v-row>
|
<v-row>
|
||||||
<v-col
|
<v-col
|
||||||
cols="12"
|
cols="12"
|
||||||
sm="6"
|
md="3"
|
||||||
md="4"
|
class="sidebar-col"
|
||||||
lg="2"
|
|
||||||
>
|
>
|
||||||
<AppCard
|
<aside class="sidebar">
|
||||||
v-if="isAuthenticated"
|
<nav
|
||||||
:to="{ name: 'DashboardPage' }"
|
class="sidebar-nav mb-6 mt-8"
|
||||||
elevation="6"
|
aria-label="Primary"
|
||||||
>
|
>
|
||||||
You are signed in. Go to Dashboard
|
<RouterLink
|
||||||
</AppCard>
|
:to="{ name: 'BlogPage' }"
|
||||||
|
class="sidebar-nav-link"
|
||||||
|
>
|
||||||
|
<span>Blog</span><span class="sidebar-nav-path">~/blog</span>
|
||||||
|
</RouterLink>
|
||||||
|
</nav>
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
<v-divider class="my-4" />
|
||||||
|
|
||||||
|
<div class="social-links">
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
class="social-link"
|
||||||
|
title="GitHub"
|
||||||
|
>
|
||||||
|
<v-icon>mdi-github</v-icon>
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
class="social-link"
|
||||||
|
title="Gitea"
|
||||||
|
>
|
||||||
|
<v-icon>mdi-git</v-icon>
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
class="social-link"
|
||||||
|
title="LinkedIn"
|
||||||
|
>
|
||||||
|
<v-icon>mdi-linkedin</v-icon>
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
class="social-link"
|
||||||
|
title="Instagram"
|
||||||
|
>
|
||||||
|
<v-icon>mdi-instagram</v-icon>
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
class="social-link"
|
||||||
|
title="Gmail"
|
||||||
|
>
|
||||||
|
<v-icon>mdi-gmail</v-icon>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</v-col>
|
||||||
|
|
||||||
|
<v-col
|
||||||
|
cols="12"
|
||||||
|
md="6"
|
||||||
|
>
|
||||||
|
<main>
|
||||||
|
<div class="terminal mb-10">
|
||||||
|
<div class="terminal-bar">
|
||||||
|
<span class="terminal-dot terminal-dot-red"></span>
|
||||||
|
<span class="terminal-dot terminal-dot-yellow"></span>
|
||||||
|
<span class="terminal-dot terminal-dot-green"></span>
|
||||||
|
<span class="terminal-title">calebburke.dev</span>
|
||||||
|
</div>
|
||||||
|
<div class="terminal-prompt">
|
||||||
|
<span class="term-green">caleb</span>
|
||||||
|
<span class="term-cyan">@</span><span class="term-green">burke</span>
|
||||||
|
<span class="term-white"> ~</span>
|
||||||
|
<span class="term-cyan">$</span>
|
||||||
|
<span class="terminal-cmd"> cat about.txt</span>
|
||||||
|
<span class="terminal-out"> Full Stack Developer </span>
|
||||||
|
|
||||||
|
<span class="term-green">caleb</span>
|
||||||
|
<span class="term-cyan">@</span>
|
||||||
|
<span class="term-green">burke</span>
|
||||||
|
<span class="term-white"> ~</span>
|
||||||
|
<span class="term-cyan">$ </span>
|
||||||
|
<span class="terminal-cmd">{{ typedText }}</span>
|
||||||
|
<span class="term-cursor">█</span>
|
||||||
|
<!-- <span class="term-green">caleb</span><span class="term-cyan">@</span
|
||||||
|
><span class="term-green">burke</span><span class="term-white">:~$</span>
|
||||||
|
<span class="terminal-cmd"> ls ~/posts | head -3</span>
|
||||||
|
<span
|
||||||
|
v-if="isLoading"
|
||||||
|
class="terminal-out terminal-out-dim"
|
||||||
|
>loading…</span
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
v-else-if="recentBlogPosts.length === 0"
|
||||||
|
class="terminal-out terminal-out-dim"
|
||||||
|
>(no posts published yet)</span
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
v-else
|
||||||
|
class="terminal-out terminal-out-dim"
|
||||||
|
>{{ recentBlogPosts.map((blogPost) => blogPost.slug).join(" ") }}</span
|
||||||
|
> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<section class="posts-section">
|
||||||
|
<div class="section-head">
|
||||||
|
<div>
|
||||||
|
<span class="section-eyebrow">~/posts</span>
|
||||||
|
<h2 class="text-h6 font-weight-bold">Recent posts</h2>
|
||||||
|
</div>
|
||||||
|
<RouterLink
|
||||||
|
:to="{ name: 'BlogPage' }"
|
||||||
|
class="section-view-all"
|
||||||
|
>view all →</RouterLink
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="isLoading">
|
||||||
|
<v-skeleton-loader
|
||||||
|
v-for="index in 3"
|
||||||
|
:key="index"
|
||||||
|
type="list-item-two-line"
|
||||||
|
class="mb-2"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p
|
||||||
|
v-else-if="recentBlogPosts.length === 0"
|
||||||
|
class="text-medium-emphasis"
|
||||||
|
>
|
||||||
|
Nothing published yet — check back soon.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-else
|
||||||
|
class="posts"
|
||||||
|
>
|
||||||
|
<article
|
||||||
|
v-for="blogPost in recentBlogPosts"
|
||||||
|
:key="blogPost.id"
|
||||||
|
class="post"
|
||||||
|
>
|
||||||
|
<div class="post-date">
|
||||||
|
<span class="post-date-day">{{ formatPostDay(blogPost.publishedAt) }}</span>
|
||||||
|
{{ formatPostMonth(blogPost.publishedAt) }}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3 class="text-subtitle-1 font-weight-bold mb-1">{{ blogPost.title }}</h3>
|
||||||
|
<div
|
||||||
|
v-if="blogPost.tags.length"
|
||||||
|
class="post-tags"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
v-for="tag in blogPost.tags"
|
||||||
|
:key="tag"
|
||||||
|
class="tag-chip"
|
||||||
|
>{{ tag }}</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
</v-col>
|
||||||
|
|
||||||
|
<v-col
|
||||||
|
cols="12"
|
||||||
|
md="3"
|
||||||
|
class="rail-col"
|
||||||
|
>
|
||||||
|
<aside class="rail">
|
||||||
|
<div
|
||||||
|
v-if="allTags.length"
|
||||||
|
class="rail-block"
|
||||||
|
>
|
||||||
|
<span class="rail-eyebrow">Tags</span>
|
||||||
|
<div class="tag-cloud">
|
||||||
|
<span
|
||||||
|
v-for="tag in allTags"
|
||||||
|
:key="tag"
|
||||||
|
class="tag-chip"
|
||||||
|
>{{ tag }}</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="rail-block">
|
||||||
|
<div class="now-box">
|
||||||
|
<div class="now-row">
|
||||||
|
<span class="now-key">release</span
|
||||||
|
><span class="now-value">{{ status.releaseTag || "dev" }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="now-row">
|
||||||
|
<span class="now-key">commit</span
|
||||||
|
><span class="now-value">{{ shortCommitHash }}</span>
|
||||||
|
</div>
|
||||||
|
<RouterLink
|
||||||
|
:to="{ name: 'StatusPage' }"
|
||||||
|
class="now-link"
|
||||||
|
>
|
||||||
|
view status
|
||||||
|
</RouterLink>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="rail-block">
|
||||||
|
<div class="cta-card">
|
||||||
|
<p v-if="isAuthenticated">Welcome back — jump into your dashboard.</p>
|
||||||
|
<p v-else>Sign in to manage posts and track flashcard progress.</p>
|
||||||
|
<v-btn
|
||||||
|
:to="isAuthenticated ? { name: 'DashboardPage' } : { name: 'SignInPage' }"
|
||||||
|
color="primary"
|
||||||
|
variant="tonal"
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
|
{{ isAuthenticated ? "Go to dashboard" : "Log in" }}
|
||||||
|
</v-btn>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { computed, onMounted, onUnmounted, reactive, ref } from "vue"
|
||||||
|
import { DateTime } from "luxon"
|
||||||
import { useAuth0 } from "@auth0/auth0-vue"
|
import { useAuth0 } from "@auth0/auth0-vue"
|
||||||
|
|
||||||
import AppCard from "@/components/common/AppCard.vue"
|
import http from "@/api/http-client"
|
||||||
|
import usePublicBlogPosts from "@/use/use-public-blog-posts"
|
||||||
|
|
||||||
const { isAuthenticated } = useAuth0()
|
const { isAuthenticated } = useAuth0()
|
||||||
|
|
||||||
|
const { blogPosts, isLoading, fetch: fetchBlogPosts } = usePublicBlogPosts()
|
||||||
|
|
||||||
|
const recentBlogPosts = computed(() => blogPosts.value.slice(0, 4))
|
||||||
|
const allTags = computed(() => [...new Set(blogPosts.value.flatMap((blogPost) => blogPost.tags))])
|
||||||
|
|
||||||
|
function formatPostDay(publishedAt: string | null): string {
|
||||||
|
if (!publishedAt) return ""
|
||||||
|
return DateTime.fromISO(publishedAt).toLocal().toFormat("dd")
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatPostMonth(publishedAt: string | null): string {
|
||||||
|
if (!publishedAt) return ""
|
||||||
|
return DateTime.fromISO(publishedAt).toLocal().toFormat("MMM yyyy")
|
||||||
|
}
|
||||||
|
|
||||||
|
const status = reactive({
|
||||||
|
releaseTag: "",
|
||||||
|
gitCommitHash: "",
|
||||||
|
})
|
||||||
|
|
||||||
|
const shortCommitHash = computed(() => status.gitCommitHash.slice(0, 7) || "local")
|
||||||
|
|
||||||
|
const TYPED_PHRASES = [
|
||||||
|
" Hello!",
|
||||||
|
" sudo rm -rf --no-preserve-root /",
|
||||||
|
" :(){ :|:& };:",
|
||||||
|
" Cheers!",
|
||||||
|
" привет",
|
||||||
|
" クリア",
|
||||||
|
" Εβίβα!",
|
||||||
|
" 干杯",
|
||||||
|
" Будьмо!",
|
||||||
|
" Na zdraví!",
|
||||||
|
" 乾杯!",
|
||||||
|
]
|
||||||
|
const TYPE_DELAY_MS = 150
|
||||||
|
const DELETE_DELAY_MS = 100
|
||||||
|
const PAUSE_AFTER_TYPED_MS = 1500
|
||||||
|
const PAUSE_AFTER_DELETED_MS = 5000
|
||||||
|
const INITIAL_DELAY_MS = 800
|
||||||
|
|
||||||
|
const typedText = ref("")
|
||||||
|
let currentPhrase = ""
|
||||||
|
let typingTimeoutId: ReturnType<typeof setTimeout>
|
||||||
|
|
||||||
|
function pickRandomPhrase() {
|
||||||
|
return TYPED_PHRASES[Math.floor(Math.random() * TYPED_PHRASES.length)]
|
||||||
|
}
|
||||||
|
|
||||||
|
function typeCharacter(index: number) {
|
||||||
|
typedText.value = currentPhrase.slice(0, index)
|
||||||
|
|
||||||
|
if (index < currentPhrase.length) {
|
||||||
|
typingTimeoutId = setTimeout(() => typeCharacter(index + 1), TYPE_DELAY_MS)
|
||||||
|
} else {
|
||||||
|
typingTimeoutId = setTimeout(() => deleteCharacter(index), PAUSE_AFTER_TYPED_MS)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteCharacter(index: number) {
|
||||||
|
typedText.value = currentPhrase.slice(0, index)
|
||||||
|
|
||||||
|
if (index > 0) {
|
||||||
|
typingTimeoutId = setTimeout(() => deleteCharacter(index - 1), DELETE_DELAY_MS)
|
||||||
|
} else {
|
||||||
|
typingTimeoutId = setTimeout(() => {
|
||||||
|
currentPhrase = pickRandomPhrase()
|
||||||
|
typeCharacter(0)
|
||||||
|
}, PAUSE_AFTER_DELETED_MS)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await fetchBlogPosts()
|
||||||
|
|
||||||
|
currentPhrase = pickRandomPhrase()
|
||||||
|
typingTimeoutId = setTimeout(() => typeCharacter(0), INITIAL_DELAY_MS)
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { data } = await http.get("/_status")
|
||||||
|
status.releaseTag = data.RELEASE_TAG
|
||||||
|
status.gitCommitHash = data.GIT_COMMIT_HASH
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to fetch status:", error)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
clearTimeout(typingTimeoutId)
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.home-page {
|
||||||
|
max-width: 1300px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar,
|
||||||
|
.rail {
|
||||||
|
position: sticky;
|
||||||
|
top: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-nav {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-nav-link {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 7px 10px;
|
||||||
|
margin: 0 -10px;
|
||||||
|
border-radius: 6px;
|
||||||
|
font-family: ui-monospace, Menlo, Monaco, Consolas, "Ubuntu Mono", monospace;
|
||||||
|
font-size: 14px;
|
||||||
|
color: rgb(var(--v-theme-textSecondary));
|
||||||
|
text-decoration: none;
|
||||||
|
transition:
|
||||||
|
background-color 0.15s ease,
|
||||||
|
color 0.15s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-nav-link:hover,
|
||||||
|
.sidebar-nav-link.router-link-active {
|
||||||
|
background-color: rgb(var(--v-theme-hoverColor));
|
||||||
|
color: rgb(var(--v-theme-textPrimary));
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-nav-path {
|
||||||
|
color: rgb(var(--v-theme-textSecondary) / 70%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.social-links {
|
||||||
|
display: flex;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.social-link {
|
||||||
|
color: rgb(var(--v-theme-textSecondary));
|
||||||
|
transition: color 0.15s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.social-link:hover {
|
||||||
|
color: rgb(var(--v-theme-primary));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Terminal hero */
|
||||||
|
.terminal {
|
||||||
|
background-color: rgb(var(--v-theme-surface));
|
||||||
|
border: 1px solid rgb(var(--v-theme-borderColor));
|
||||||
|
border-radius: 8px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-bar {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 10px 14px;
|
||||||
|
background-color: rgb(var(--v-theme-containerBg));
|
||||||
|
border-bottom: 1px solid rgb(var(--v-theme-borderColor));
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-dot {
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-dot-red {
|
||||||
|
background-color: rgb(var(--v-theme-error));
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-dot-yellow {
|
||||||
|
background-color: rgb(var(--v-theme-warning));
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-dot-green {
|
||||||
|
background-color: rgb(var(--v-theme-success));
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-title {
|
||||||
|
margin: 0 auto;
|
||||||
|
transform: translateX(-16px);
|
||||||
|
font-family: ui-monospace, Menlo, Monaco, Consolas, "Ubuntu Mono", monospace;
|
||||||
|
font-size: 12px;
|
||||||
|
color: rgb(var(--v-theme-textSecondary));
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-prompt {
|
||||||
|
display: block;
|
||||||
|
padding: 20px 22px 24px;
|
||||||
|
font-family: ui-monospace, Menlo, Monaco, Consolas, "Ubuntu Mono", monospace;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-cmd {
|
||||||
|
color: rgb(var(--v-theme-textPrimary));
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-out {
|
||||||
|
display: block;
|
||||||
|
margin: 0 0 10px;
|
||||||
|
color: rgb(var(--v-theme-textSecondary));
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-out-dim {
|
||||||
|
color: rgb(var(--v-theme-textSecondary) / 60%);
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes terminal-blink {
|
||||||
|
50% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Section headers */
|
||||||
|
.section-head {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-eyebrow {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
font-family: ui-monospace, Menlo, Monaco, Consolas, "Ubuntu Mono", monospace;
|
||||||
|
font-size: 12px;
|
||||||
|
color: rgb(var(--v-theme-primary));
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-view-all {
|
||||||
|
font-family: ui-monospace, Menlo, Monaco, Consolas, "Ubuntu Mono", monospace;
|
||||||
|
font-size: 12px;
|
||||||
|
color: rgb(var(--v-theme-textSecondary));
|
||||||
|
text-decoration: none;
|
||||||
|
border-bottom: 1px solid rgb(var(--v-theme-borderColor));
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-view-all:hover {
|
||||||
|
color: rgb(var(--v-theme-primary));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Posts */
|
||||||
|
.post {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 76px 1fr;
|
||||||
|
gap: 18px;
|
||||||
|
padding: 18px 0;
|
||||||
|
border-bottom: 1px solid rgb(var(--v-theme-borderColor));
|
||||||
|
}
|
||||||
|
|
||||||
|
.post:first-child {
|
||||||
|
padding-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.post:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-date {
|
||||||
|
font-family: ui-monospace, Menlo, Monaco, Consolas, "Ubuntu Mono", monospace;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.5;
|
||||||
|
color: rgb(var(--v-theme-textSecondary) / 70%);
|
||||||
|
padding-top: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-date-day {
|
||||||
|
display: block;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: rgb(var(--v-theme-textSecondary));
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-tags {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-chip {
|
||||||
|
font-family: ui-monospace, Menlo, Monaco, Consolas, "Ubuntu Mono", monospace;
|
||||||
|
font-size: 11px;
|
||||||
|
padding: 2px 8px;
|
||||||
|
border-radius: 20px;
|
||||||
|
background-color: rgb(var(--v-theme-surface));
|
||||||
|
border: 1px solid rgb(var(--v-theme-borderColor));
|
||||||
|
color: rgb(var(--v-theme-textSecondary));
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-cloud {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Right rail */
|
||||||
|
.rail {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rail-eyebrow {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
font-family: ui-monospace, Menlo, Monaco, Consolas, "Ubuntu Mono", monospace;
|
||||||
|
font-size: 11px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.06em;
|
||||||
|
color: rgb(var(--v-theme-textSecondary) / 70%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.now-box {
|
||||||
|
padding: 14px 16px;
|
||||||
|
background-color: rgb(var(--v-theme-surface));
|
||||||
|
border: 1px solid rgb(var(--v-theme-borderColor));
|
||||||
|
border-radius: 6px;
|
||||||
|
font-family: ui-monospace, Menlo, Monaco, Consolas, "Ubuntu Mono", monospace;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.now-row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 8px;
|
||||||
|
line-height: 1.9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.now-key {
|
||||||
|
color: rgb(var(--v-theme-textSecondary) / 70%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.now-value {
|
||||||
|
color: rgb(var(--v-theme-textPrimary));
|
||||||
|
}
|
||||||
|
|
||||||
|
.now-link {
|
||||||
|
display: inline-block;
|
||||||
|
margin-top: 10px;
|
||||||
|
color: rgb(var(--v-theme-primary));
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cta-card {
|
||||||
|
padding: 16px;
|
||||||
|
background-color: rgb(var(--v-theme-lightprimary));
|
||||||
|
border: 1px solid rgb(var(--v-theme-primary) / 25%);
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cta-card p {
|
||||||
|
margin: 0 0 12px;
|
||||||
|
font-size: 13px;
|
||||||
|
color: rgb(var(--v-theme-textSecondary));
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 960px) {
|
||||||
|
.sidebar,
|
||||||
|
.rail {
|
||||||
|
position: static;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user