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:
Patrick Mulligan 2026-04-01 17:34:02 -04:00
parent d899aff199
commit 767c4391cc
7 changed files with 88 additions and 82 deletions

View file

@ -4,16 +4,17 @@ import InfoCard from '@/components/InfoCard.vue'
</script>
<template>
<div class="relative min-h-dvh flex flex-col items-center justify-center overflow-hidden">
<!-- Full-bleed background -->
<div class="relative min-h-dvh flex flex-col items-center justify-center overflow-hidden bg-black">
<!-- Background image + dark overlay -->
<img
src="/atio_bg.webp"
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 -->
<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">
<!-- Page content -->
<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 />
<InfoCard />
</main>

View file

@ -14,17 +14,20 @@ const cashLabels: Record<string, string> = {
</script>
<template>
<section class="space-y-4">
<h3 class="text-xs font-medium uppercase tracking-widest text-muted-foreground text-center">
<div class="space-y-4">
<p class="text-xs font-medium uppercase tracking-widest text-muted-foreground text-center">
ATM Status
</h3>
</p>
<!-- 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">
<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="ml-auto h-5 w-20" />
<Skeleton class="h-3 w-20" />
</div>
<Skeleton class="h-5 w-20 rounded-full" />
</div>
</div>
@ -37,7 +40,7 @@ const cashLabels: Record<string, string> = {
>
<!-- Status dot -->
<span
class="size-2 rounded-full shrink-0"
class="size-2.5 rounded-full shrink-0"
:class="{
'bg-chart-3': atm.maintenance,
'bg-chart-4': !atm.maintenance && isOnline(atm),
@ -46,27 +49,29 @@ const cashLabels: Record<string, string> = {
/>
<!-- Machine info -->
<div class="min-w-0">
<span class="text-sm font-medium text-card-foreground">{{ atm.config.name }}</span>
<span class="text-muted-foreground text-xs ml-1.5">{{ atm.config.location }}</span>
<div class="min-w-0 flex-1">
<p class="text-sm font-medium text-card-foreground leading-tight">
{{ atm.config.name }}
</p>
<p class="text-xs text-muted-foreground">
{{ atm.config.location }}
</p>
</div>
<!-- Service badges -->
<div class="ml-auto flex items-center gap-1.5">
<Badge v-if="atm.maintenance" variant="secondary" class="text-chart-3 text-xs">
<!-- Service badges + last seen -->
<div class="flex items-center gap-2 shrink-0">
<Badge v-if="atm.maintenance" variant="secondary" class="text-chart-3">
Maintenance
</Badge>
<template v-else>
<Badge
variant="secondary"
class="text-xs"
:class="atm.cashIn ? 'text-chart-4' : 'text-muted-foreground'"
>
Buy
</Badge>
<Badge
variant="secondary"
class="text-xs"
:class="{
'text-chart-4': isOnline(atm) && (atm.cashLevel === 'good' || atm.cashLevel === 'full'),
'text-chart-3': isOnline(atm) && atm.cashLevel === 'low',
@ -76,9 +81,11 @@ const cashLabels: Record<string, string> = {
{{ isOnline(atm) ? (cashLabels[atm.cashLevel] || 'Sell ₿') : 'Sell ₿' }}
</Badge>
</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>
</section>
</template>

View file

@ -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>

View file

@ -3,12 +3,12 @@
<img
src="/logo.png"
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
</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
</p>
</header>

View file

@ -1,16 +1,59 @@
<script setup lang="ts">
import { Card, CardContent } from '@/components/ui/card'
import RatesSection from './RatesSection.vue'
import {
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 ContactLinks from './ContactLinks.vue'
</script>
<template>
<Card class="animate-fade-in [animation-delay:200ms] backdrop-blur-lg bg-card/40 border-border/40 shadow-xl">
<CardContent class="p-0 divide-y divide-border/40">
<RatesSection class="px-8 py-7 max-md:px-5 max-md:py-5" />
<AtmStatusList class="px-8 py-7 max-md:px-5 max-md:py-5" />
<ContactLinks class="px-8 py-7 max-md:px-5 max-md:py-5" />
<Card class="backdrop-blur-xl bg-black/50 border-primary/20 shadow-2xl shadow-primary/5">
<!-- Bitcoinmat rates -->
<CardHeader class="text-center">
<CardTitle class="text-2xl max-md:text-xl font-medium text-bitcoin">
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>
<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>
</template>

View file

@ -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>

View file

@ -2,4 +2,7 @@ import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
// Ensure dark mode is active
document.documentElement.classList.add('dark')
createApp(App).mount('#app')