fix: consolidate InfoCard, dark bg overlay, visual polish
- Merge RatesSection and ContactLinks into InfoCard using proper CardHeader/CardTitle/CardDescription/CardContent/CardFooter/Separator - Dark translucent card (bg-black/50) with primary border glow - Full-opacity bg image with bg-black/70 overlay instead of opacity hack - Logo drop shadow uses --color-primary for thematic glow - Fix heading clipping: leading-tight instead of leading-none - Force dark mode from JS as safety net - Lucide Send/Mail icons with ghost Button links Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d899aff199
commit
767c4391cc
7 changed files with 88 additions and 82 deletions
11
src/App.vue
11
src/App.vue
|
|
@ -4,16 +4,17 @@ import InfoCard from '@/components/InfoCard.vue'
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="relative min-h-dvh flex flex-col items-center justify-center overflow-hidden">
|
<div class="relative min-h-dvh flex flex-col items-center justify-center overflow-hidden bg-black">
|
||||||
<!-- Full-bleed background -->
|
<!-- Background image + dark overlay -->
|
||||||
<img
|
<img
|
||||||
src="/atio_bg.webp"
|
src="/atio_bg.webp"
|
||||||
alt=""
|
alt=""
|
||||||
class="fixed inset-0 w-full h-full object-cover opacity-10 pointer-events-none select-none"
|
class="fixed inset-0 w-full h-full object-cover pointer-events-none select-none"
|
||||||
/>
|
/>
|
||||||
|
<div class="fixed inset-0 bg-black/70 pointer-events-none" />
|
||||||
|
|
||||||
<!-- Page content — vertically centered, generous whitespace -->
|
<!-- Page content -->
|
||||||
<main class="relative z-10 w-full max-w-xl px-6 py-16 max-md:px-4 max-md:py-10 space-y-12 max-md:space-y-8">
|
<main class="relative z-10 w-full max-w-lg px-6 py-16 max-md:px-4 max-md:py-10 space-y-10 max-md:space-y-6">
|
||||||
<HeroSection />
|
<HeroSection />
|
||||||
<InfoCard />
|
<InfoCard />
|
||||||
</main>
|
</main>
|
||||||
|
|
|
||||||
|
|
@ -14,17 +14,20 @@ const cashLabels: Record<string, string> = {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<section class="space-y-4">
|
<div class="space-y-4">
|
||||||
<h3 class="text-xs font-medium uppercase tracking-widest text-muted-foreground text-center">
|
<p class="text-xs font-medium uppercase tracking-widest text-muted-foreground text-center">
|
||||||
ATM Status
|
ATM Status
|
||||||
</h3>
|
</p>
|
||||||
|
|
||||||
<!-- Loading skeleton -->
|
<!-- Loading skeleton -->
|
||||||
<div v-if="loading" class="space-y-3">
|
<div v-if="loading" class="space-y-4">
|
||||||
<div v-for="i in atms.size" :key="i" class="flex items-center gap-3">
|
<div v-for="i in atms.size" :key="i" class="flex items-center gap-3">
|
||||||
<Skeleton class="size-2 rounded-full" />
|
<Skeleton class="size-2.5 rounded-full shrink-0" />
|
||||||
|
<div class="flex-1 space-y-1.5">
|
||||||
<Skeleton class="h-4 w-28" />
|
<Skeleton class="h-4 w-28" />
|
||||||
<Skeleton class="ml-auto h-5 w-20" />
|
<Skeleton class="h-3 w-20" />
|
||||||
|
</div>
|
||||||
|
<Skeleton class="h-5 w-20 rounded-full" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -37,7 +40,7 @@ const cashLabels: Record<string, string> = {
|
||||||
>
|
>
|
||||||
<!-- Status dot -->
|
<!-- Status dot -->
|
||||||
<span
|
<span
|
||||||
class="size-2 rounded-full shrink-0"
|
class="size-2.5 rounded-full shrink-0"
|
||||||
:class="{
|
:class="{
|
||||||
'bg-chart-3': atm.maintenance,
|
'bg-chart-3': atm.maintenance,
|
||||||
'bg-chart-4': !atm.maintenance && isOnline(atm),
|
'bg-chart-4': !atm.maintenance && isOnline(atm),
|
||||||
|
|
@ -46,27 +49,29 @@ const cashLabels: Record<string, string> = {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- Machine info -->
|
<!-- Machine info -->
|
||||||
<div class="min-w-0">
|
<div class="min-w-0 flex-1">
|
||||||
<span class="text-sm font-medium text-card-foreground">{{ atm.config.name }}</span>
|
<p class="text-sm font-medium text-card-foreground leading-tight">
|
||||||
<span class="text-muted-foreground text-xs ml-1.5">{{ atm.config.location }}</span>
|
{{ atm.config.name }}
|
||||||
|
</p>
|
||||||
|
<p class="text-xs text-muted-foreground">
|
||||||
|
{{ atm.config.location }}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Service badges -->
|
<!-- Service badges + last seen -->
|
||||||
<div class="ml-auto flex items-center gap-1.5">
|
<div class="flex items-center gap-2 shrink-0">
|
||||||
<Badge v-if="atm.maintenance" variant="secondary" class="text-chart-3 text-xs">
|
<Badge v-if="atm.maintenance" variant="secondary" class="text-chart-3">
|
||||||
Maintenance
|
Maintenance
|
||||||
</Badge>
|
</Badge>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<Badge
|
<Badge
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
class="text-xs"
|
|
||||||
:class="atm.cashIn ? 'text-chart-4' : 'text-muted-foreground'"
|
:class="atm.cashIn ? 'text-chart-4' : 'text-muted-foreground'"
|
||||||
>
|
>
|
||||||
Buy ₿
|
Buy ₿
|
||||||
</Badge>
|
</Badge>
|
||||||
<Badge
|
<Badge
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
class="text-xs"
|
|
||||||
:class="{
|
:class="{
|
||||||
'text-chart-4': isOnline(atm) && (atm.cashLevel === 'good' || atm.cashLevel === 'full'),
|
'text-chart-4': isOnline(atm) && (atm.cashLevel === 'good' || atm.cashLevel === 'full'),
|
||||||
'text-chart-3': isOnline(atm) && atm.cashLevel === 'low',
|
'text-chart-3': isOnline(atm) && atm.cashLevel === 'low',
|
||||||
|
|
@ -76,9 +81,11 @@ const cashLabels: Record<string, string> = {
|
||||||
{{ isOnline(atm) ? (cashLabels[atm.cashLevel] || 'Sell ₿') : 'Sell ₿' }}
|
{{ isOnline(atm) ? (cashLabels[atm.cashLevel] || 'Sell ₿') : 'Sell ₿' }}
|
||||||
</Badge>
|
</Badge>
|
||||||
</template>
|
</template>
|
||||||
<span class="text-xs text-muted-foreground ml-1">{{ statusText(atm) }}</span>
|
<span class="text-xs text-muted-foreground whitespace-nowrap">
|
||||||
|
{{ statusText(atm) }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
<script setup lang="ts">
|
|
||||||
import { Button } from '@/components/ui/button'
|
|
||||||
import { Send, Mail } from 'lucide-vue-next'
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<section class="space-y-3">
|
|
||||||
<h3 class="text-xs font-medium uppercase tracking-widest text-muted-foreground text-center">
|
|
||||||
Contact
|
|
||||||
</h3>
|
|
||||||
<div class="flex flex-col gap-2">
|
|
||||||
<Button variant="ghost" class="w-full justify-center gap-2 text-bitcoin hover:text-bitcoin hover:bg-secondary" as-child>
|
|
||||||
<a href="https://t.me/atitlanio" target="_blank" rel="noopener">
|
|
||||||
<Send class="size-4" />
|
|
||||||
<span>Telegram @atitlanio</span>
|
|
||||||
</a>
|
|
||||||
</Button>
|
|
||||||
<Button variant="ghost" class="w-full justify-center gap-2 text-bitcoin hover:text-bitcoin hover:bg-secondary" as-child>
|
|
||||||
<a href="mailto:atitlanio@protonmail.com">
|
|
||||||
<Mail class="size-4" />
|
|
||||||
<span>atitlanio@protonmail.com</span>
|
|
||||||
</a>
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</template>
|
|
||||||
|
|
@ -3,12 +3,12 @@
|
||||||
<img
|
<img
|
||||||
src="/logo.png"
|
src="/logo.png"
|
||||||
alt="Atitlan.io"
|
alt="Atitlan.io"
|
||||||
class="w-32 max-md:w-20 mx-auto drop-shadow-lg animate-float"
|
class="w-32 max-md:w-20 mx-auto drop-shadow-[0_4px_20px_var(--color-primary)] animate-float"
|
||||||
/>
|
/>
|
||||||
<h1 class="text-7xl max-md:text-4xl font-extralight tracking-tight leading-none pb-1 bg-gradient-to-r from-foreground to-bitcoin bg-clip-text text-transparent">
|
<h1 class="text-7xl max-md:text-4xl font-extralight tracking-tight leading-tight bg-gradient-to-r from-foreground to-bitcoin bg-clip-text text-transparent">
|
||||||
Coming Soon
|
Coming Soon
|
||||||
</h1>
|
</h1>
|
||||||
<p class="text-xl max-md:text-base font-light tracking-[0.2em] text-primary">
|
<p class="text-xl max-md:text-base font-light tracking-[0.2em] text-primary leading-relaxed">
|
||||||
Atitlan.io
|
Atitlan.io
|
||||||
</p>
|
</p>
|
||||||
</header>
|
</header>
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,59 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Card, CardContent } from '@/components/ui/card'
|
import {
|
||||||
import RatesSection from './RatesSection.vue'
|
Card,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
CardDescription,
|
||||||
|
CardContent,
|
||||||
|
CardFooter,
|
||||||
|
} from '@/components/ui/card'
|
||||||
|
import { Separator } from '@/components/ui/separator'
|
||||||
|
import { Button } from '@/components/ui/button'
|
||||||
|
import { Send, Mail } from 'lucide-vue-next'
|
||||||
import AtmStatusList from './AtmStatusList.vue'
|
import AtmStatusList from './AtmStatusList.vue'
|
||||||
import ContactLinks from './ContactLinks.vue'
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Card class="animate-fade-in [animation-delay:200ms] backdrop-blur-lg bg-card/40 border-border/40 shadow-xl">
|
<Card class="backdrop-blur-xl bg-black/50 border-primary/20 shadow-2xl shadow-primary/5">
|
||||||
<CardContent class="p-0 divide-y divide-border/40">
|
<!-- Bitcoinmat rates -->
|
||||||
<RatesSection class="px-8 py-7 max-md:px-5 max-md:py-5" />
|
<CardHeader class="text-center">
|
||||||
<AtmStatusList class="px-8 py-7 max-md:px-5 max-md:py-5" />
|
<CardTitle class="text-2xl max-md:text-xl font-medium text-bitcoin">
|
||||||
<ContactLinks class="px-8 py-7 max-md:px-5 max-md:py-5" />
|
Bitcoinmat
|
||||||
|
</CardTitle>
|
||||||
|
<CardDescription class="text-base max-md:text-sm">
|
||||||
|
Cash-in rate: <strong class="text-bitcoin font-semibold">3%</strong>
|
||||||
|
</CardDescription>
|
||||||
|
<CardDescription class="text-base max-md:text-sm">
|
||||||
|
Cash-out rate: <strong class="text-bitcoin font-semibold">8.75%</strong>
|
||||||
|
</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
|
||||||
|
<Separator />
|
||||||
|
|
||||||
|
<!-- ATM Status -->
|
||||||
|
<CardContent>
|
||||||
|
<AtmStatusList />
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
|
||||||
|
<Separator />
|
||||||
|
|
||||||
|
<!-- Contact -->
|
||||||
|
<CardFooter class="flex-col gap-2">
|
||||||
|
<p class="text-xs font-medium uppercase tracking-widest text-muted-foreground mb-1">
|
||||||
|
Contact
|
||||||
|
</p>
|
||||||
|
<Button variant="ghost" size="sm" class="w-full justify-center gap-2 text-bitcoin hover:text-bitcoin hover:bg-secondary" as-child>
|
||||||
|
<a href="https://t.me/atitlanio" target="_blank" rel="noopener">
|
||||||
|
<Send class="size-4" />
|
||||||
|
<span>Telegram @atitlanio</span>
|
||||||
|
</a>
|
||||||
|
</Button>
|
||||||
|
<Button variant="ghost" size="sm" class="w-full justify-center gap-2 text-bitcoin hover:text-bitcoin hover:bg-secondary" as-child>
|
||||||
|
<a href="mailto:atitlanio@protonmail.com">
|
||||||
|
<Mail class="size-4" />
|
||||||
|
<span>atitlanio@protonmail.com</span>
|
||||||
|
</a>
|
||||||
|
</Button>
|
||||||
|
</CardFooter>
|
||||||
</Card>
|
</Card>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
<template>
|
|
||||||
<section class="text-center space-y-4">
|
|
||||||
<h2 class="text-2xl max-md:text-lg font-medium text-bitcoin">
|
|
||||||
Bitcoinmat
|
|
||||||
</h2>
|
|
||||||
<div class="flex justify-center gap-8 max-md:gap-4 text-sm max-md:text-xs">
|
|
||||||
<div>
|
|
||||||
<p class="text-muted-foreground">Cash-in</p>
|
|
||||||
<p class="text-lg max-md:text-base font-semibold text-bitcoin">3%</p>
|
|
||||||
</div>
|
|
||||||
<Separator orientation="vertical" class="h-auto" />
|
|
||||||
<div>
|
|
||||||
<p class="text-muted-foreground">Cash-out</p>
|
|
||||||
<p class="text-lg max-md:text-base font-semibold text-bitcoin">8.75%</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { Separator } from '@/components/ui/separator'
|
|
||||||
</script>
|
|
||||||
|
|
@ -2,4 +2,7 @@ import { createApp } from 'vue'
|
||||||
import './style.css'
|
import './style.css'
|
||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
|
|
||||||
|
// Ensure dark mode is active
|
||||||
|
document.documentElement.classList.add('dark')
|
||||||
|
|
||||||
createApp(App).mount('#app')
|
createApp(App).mount('#app')
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue