polish: fix padding and spacing across all sections to match Pencil design
- FeatureCard: px-7 pt-8 pb-8 (design: padding [32,28]), h-full for equal heights - HeroSection: py-20 on mobile, gap-20 between columns, screenshot 380px - PrivacyBanner: py-14, gap-20, stat items min-w-[100px] - SeeItLiveSection: py-24, max-w-[640px] header, block img - FeaturesSection: gap-[72px] section, flex wrapper for equal-height cards - ScreenshotsSection: lg:h-[340px] images, px-6 py-5 info, gap-2 - HowItWorksSection: gap-20 columns, gap-10 steps, divide-y billing items, p-10 card - SupportSection: py-24, gap-16, flex wrappers for equal-height cards - ContactSection: py-20, gap-20, p-9 form card, gap-5 fields - AppFooter: pt-14 pb-7, border-b [#1E293B], pt-5 bottom bar
This commit is contained in:
@@ -1,16 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
// Design: padding [56, 100, 28, 100], footerTop gap 64, fBrand width 260, fDiv #1E293B
|
||||
const productLinks = [
|
||||
{ label: 'Features', href: '#features' },
|
||||
{ label: 'How It Works', href: '#how-it-works' },
|
||||
{ label: 'Services', href: '#support' },
|
||||
]
|
||||
|
||||
const companyLinks = [
|
||||
{ label: 'About Us', href: '#' },
|
||||
{ label: 'Contact', href: '#contact' },
|
||||
{ label: 'Blog', href: '#' },
|
||||
]
|
||||
|
||||
const legalLinks = [
|
||||
{ label: 'Privacy Policy', href: '#' },
|
||||
{ label: 'Terms of Service', href: '#' },
|
||||
@@ -18,20 +17,22 @@ const legalLinks = [
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<footer class="bg-[#020617] text-white">
|
||||
<div class="page-container py-14 pb-7">
|
||||
<footer class="bg-[#020617]">
|
||||
<div class="page-container pt-14 pb-7">
|
||||
|
||||
<!-- Top row: brand + nav columns -->
|
||||
<div class="flex flex-col md:flex-row gap-12 md:gap-16 pb-10 border-b border-[#1E293B]">
|
||||
<!-- Top row: fBrand 260 + spacer + 3 nav columns, gap 64 -->
|
||||
<div class="flex flex-col md:flex-row gap-16 pb-10 border-b border-[#1E293B]">
|
||||
|
||||
<!-- Brand column -->
|
||||
<!-- Brand column: gap 14, width 260 -->
|
||||
<div class="flex flex-col gap-3.5 w-full md:w-[260px] shrink-0">
|
||||
<!-- Logo row: gap 8 -->
|
||||
<div class="flex items-center gap-2">
|
||||
<div class="w-7 h-7 rounded-[6px] bg-[#1D4ED8] flex items-center justify-center shrink-0">
|
||||
<span class="text-white font-bold text-sm leading-none">T</span>
|
||||
</div>
|
||||
<span class="text-white font-bold text-base">TapTrack</span>
|
||||
</div>
|
||||
<!-- Tagline: 13px, lineHeight 1.65, max-w 220 -->
|
||||
<p class="text-[#475569] text-[13px] leading-[1.65] max-w-[220px]">
|
||||
On-premises NFC attendance for Philippine schools. Student data stays where it belongs — with you.
|
||||
</p>
|
||||
@@ -40,10 +41,9 @@ const legalLinks = [
|
||||
<!-- Spacer -->
|
||||
<div class="hidden md:block flex-1" />
|
||||
|
||||
<!-- Nav columns -->
|
||||
<!-- Nav columns: gap 64 between columns, gap 12 inside each -->
|
||||
<div class="grid grid-cols-2 sm:grid-cols-3 gap-8 md:gap-16">
|
||||
|
||||
<!-- Product -->
|
||||
<div class="flex flex-col gap-3">
|
||||
<span class="text-[#D1D5DB] font-semibold text-[13px]">Product</span>
|
||||
<a
|
||||
@@ -56,7 +56,6 @@ const legalLinks = [
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Company -->
|
||||
<div class="flex flex-col gap-3">
|
||||
<span class="text-[#D1D5DB] font-semibold text-[13px]">Company</span>
|
||||
<a
|
||||
@@ -69,7 +68,6 @@ const legalLinks = [
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Legal -->
|
||||
<div class="flex flex-col gap-3">
|
||||
<span class="text-[#D1D5DB] font-semibold text-[13px]">Legal</span>
|
||||
<a
|
||||
@@ -81,10 +79,11 @@ const legalLinks = [
|
||||
{{ link.label }}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Bottom bar -->
|
||||
<!-- Bottom bar: padding [20, 0, 0, 0] -->
|
||||
<div class="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-2 pt-5">
|
||||
<p class="text-[#374151] text-xs">
|
||||
© 2025 TapTrack. All rights reserved. Built in the Philippines.
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
|
||||
const form = ref({
|
||||
school: '',
|
||||
contact: '',
|
||||
phone: '',
|
||||
})
|
||||
|
||||
// Design: padding [80, 100], gap 80, alignItems center
|
||||
const form = ref({ school: '', contact: '', phone: '' })
|
||||
const submitted = ref(false)
|
||||
const submitting = ref(false)
|
||||
const error = ref('')
|
||||
@@ -17,7 +13,6 @@ const bulletPoints = [
|
||||
'✓ Demo of the live system before you commit',
|
||||
]
|
||||
|
||||
// Replace with your actual Formspree form ID: https://formspree.io
|
||||
const FORMSPREE_URL = 'https://formspree.io/f/YOUR_FORM_ID'
|
||||
|
||||
async function handleSubmit() {
|
||||
@@ -31,11 +26,7 @@ async function handleSubmit() {
|
||||
const res = await fetch(FORMSPREE_URL, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
|
||||
body: JSON.stringify({
|
||||
school: form.value.school,
|
||||
contact: form.value.contact,
|
||||
phone: form.value.phone,
|
||||
}),
|
||||
body: JSON.stringify({ school: form.value.school, contact: form.value.contact, phone: form.value.phone }),
|
||||
})
|
||||
if (res.ok) {
|
||||
submitted.value = true
|
||||
@@ -52,9 +43,9 @@ async function handleSubmit() {
|
||||
|
||||
<template>
|
||||
<section id="contact" class="bg-[#0F172A]">
|
||||
<div class="page-container flex flex-col lg:flex-row items-start lg:items-center gap-16 xl:gap-20 py-20">
|
||||
<div class="page-container flex flex-col lg:flex-row items-start lg:items-center gap-20 py-20">
|
||||
|
||||
<!-- Left: Copy -->
|
||||
<!-- Left: gap 20 -->
|
||||
<div v-reveal class="flex-1 flex flex-col gap-5 min-w-0">
|
||||
<span class="text-[#60A5FA] font-semibold text-[11px] tracking-[2px] uppercase">
|
||||
Get in Touch
|
||||
@@ -65,6 +56,7 @@ async function handleSubmit() {
|
||||
<p class="text-[#94A3B8] text-[16px] leading-[1.65] max-w-[520px]">
|
||||
Tell us about your school and we'll get back to you with a tailored proposal — including implementation scope, NFC hardware, and SMS credit packages that fit your needs.
|
||||
</p>
|
||||
<!-- Bullet points: gap 10 -->
|
||||
<div class="flex flex-col gap-2.5 mt-1">
|
||||
<span
|
||||
v-for="point in bulletPoints"
|
||||
@@ -76,17 +68,17 @@ async function handleSubmit() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Right: Form card -->
|
||||
<!-- Right: Form card, width 480, padding 36, gap 20, cornerRadius 16, fill #1E293B -->
|
||||
<div v-reveal="{ delay: 150 }" class="w-full lg:w-[480px] shrink-0">
|
||||
<div class="bg-[#1E293B] rounded-2xl p-8 lg:p-9 flex flex-col gap-5">
|
||||
<div class="bg-[#1E293B] rounded-2xl p-9 flex flex-col gap-5">
|
||||
|
||||
<div>
|
||||
<div class="flex flex-col gap-1">
|
||||
<h3 class="text-white font-bold text-xl">Request a Demo</h3>
|
||||
<p class="text-[#64748B] text-[13px] mt-1">Fill this out and we'll reach you within 24 hours.</p>
|
||||
<p class="text-[#64748B] text-[13px]">Fill this out and we'll reach you within 24 hours.</p>
|
||||
</div>
|
||||
|
||||
<!-- Success state -->
|
||||
<div v-if="submitted" class="flex flex-col items-center gap-3 py-6 text-center">
|
||||
<div v-if="submitted" class="flex flex-col items-center gap-3 py-8 text-center">
|
||||
<div class="w-12 h-12 rounded-full bg-[#059669] flex items-center justify-center">
|
||||
<span class="text-white font-bold text-xl">✓</span>
|
||||
</div>
|
||||
@@ -94,7 +86,7 @@ async function handleSubmit() {
|
||||
<p class="text-[#94A3B8] text-sm">We'll get back to you within 24 hours.</p>
|
||||
</div>
|
||||
|
||||
<!-- Form -->
|
||||
<!-- Form: gap 16 between fields -->
|
||||
<form v-else class="flex flex-col gap-4" @submit.prevent="handleSubmit">
|
||||
|
||||
<div class="flex flex-col gap-1.5">
|
||||
@@ -127,8 +119,9 @@ async function handleSubmit() {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<p v-if="error" class="text-red-400 text-[13px]">{{ error }}</p>
|
||||
<p v-if="error" class="text-red-400 text-[13px] -mt-1">{{ error }}</p>
|
||||
|
||||
<!-- Submit button: padding [13, 0], width fill -->
|
||||
<button
|
||||
type="submit"
|
||||
:disabled="submitting"
|
||||
|
||||
@@ -11,19 +11,18 @@ defineProps<{
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-col gap-3.5 bg-[#F8FAFC] border border-[#E2E8F0] rounded-[14px] p-7 pt-8">
|
||||
<!-- Icon box -->
|
||||
<!-- Design: cornerRadius 14, padding [32, 28], gap 14 -->
|
||||
<div class="flex flex-col gap-3.5 bg-[#F8FAFC] border border-[#E2E8F0] rounded-2xl px-7 pt-8 pb-8 h-full">
|
||||
<!-- Icon box: 44×44, cornerRadius 10 -->
|
||||
<div
|
||||
class="w-11 h-11 rounded-[10px] flex items-center justify-center shrink-0"
|
||||
:style="{ backgroundColor: iconBg }"
|
||||
>
|
||||
<component :is="icon" :size="22" :stroke-width="1.75" :style="{ color: iconColor }" />
|
||||
</div>
|
||||
|
||||
<!-- Title -->
|
||||
<!-- Title: 16px semibold -->
|
||||
<h3 class="text-[#0F172A] font-semibold text-base leading-snug">{{ title }}</h3>
|
||||
|
||||
<!-- Description -->
|
||||
<!-- Description: 13px, lineHeight 1.65 -->
|
||||
<p class="text-[#64748B] text-[13px] leading-[1.65]">{{ description }}</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -15,87 +15,86 @@ const features = [
|
||||
iconColor: '#1D4ED8',
|
||||
iconBg: '#EFF6FF',
|
||||
title: 'NFC Tap-In Attendance',
|
||||
description:
|
||||
'Students tap their NFC ID card on the reader. Attendance is recorded instantly — no queuing, no manual entry, no errors.',
|
||||
description: 'Students tap their NFC ID card on the reader. Attendance is recorded instantly — no queuing, no manual entry, no errors.',
|
||||
},
|
||||
{
|
||||
icon: MessageSquare,
|
||||
iconColor: '#059669',
|
||||
iconBg: '#ECFDF5',
|
||||
title: 'Instant Parent SMS Alerts',
|
||||
description:
|
||||
'Parents receive an automatic SMS the moment their child arrives or is marked absent. No app required on their end.',
|
||||
description: 'Parents receive an automatic SMS the moment their child arrives or is marked absent. No app required on their end.',
|
||||
},
|
||||
{
|
||||
icon: LayoutDashboard,
|
||||
iconColor: '#CA8A04',
|
||||
iconBg: '#FEF9C3',
|
||||
title: 'Live Attendance Dashboard',
|
||||
description:
|
||||
'Principals and advisers see real-time attendance, late counts, and absent students — all from a single screen.',
|
||||
description: 'Principals and advisers see real-time attendance, late counts, and absent students — all from a single screen.',
|
||||
},
|
||||
{
|
||||
icon: BookOpen,
|
||||
iconColor: '#7C3AED',
|
||||
iconBg: '#F3E8FF',
|
||||
title: 'Automated Attendance Reports',
|
||||
description:
|
||||
'Monthly attendance summaries are generated and sent automatically to administrators — with per-student and per-class breakdowns.',
|
||||
description: 'Monthly attendance summaries are generated and sent automatically to administrators — with per-student and per-class breakdowns.',
|
||||
},
|
||||
{
|
||||
icon: Users,
|
||||
iconColor: '#E11D48',
|
||||
iconBg: '#FFF1F2',
|
||||
title: 'Student & Section Management',
|
||||
description:
|
||||
"Manage your full student roster, assign sections and advisers, and link each student to their parent's contact number.",
|
||||
description: "Manage your full student roster, assign sections and advisers, and link each student to their parent's contact number.",
|
||||
},
|
||||
{
|
||||
icon: Activity,
|
||||
iconColor: '#0284C7',
|
||||
iconBg: '#E0F2FE',
|
||||
title: 'SMS Credit Monitoring',
|
||||
description:
|
||||
'Track your prepaid SMS credit balance in real time. Low-credit alerts let you top up before you run out — no interruptions to parent notifications.',
|
||||
description: 'Track your prepaid SMS credit balance in real time. Low-credit alerts let you top up before you run out — no interruptions to parent notifications.',
|
||||
},
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- Design: padding [96, 100], gap 72 between header and grid -->
|
||||
<section id="features" class="bg-white">
|
||||
<div class="page-container flex flex-col gap-[72px] py-24">
|
||||
|
||||
<!-- Section header -->
|
||||
<div v-reveal class="flex flex-col items-center gap-2.5">
|
||||
<!-- Header: gap 10, alignItems center -->
|
||||
<div v-reveal class="flex flex-col items-center gap-2.5 text-center">
|
||||
<span class="text-[#1D4ED8] font-semibold text-[11px] tracking-[2px] uppercase">
|
||||
What TapTrack Does
|
||||
</span>
|
||||
<h2 class="text-[#0F172A] font-bold text-[clamp(28px,3vw,40px)] leading-[1.15] text-center max-w-[560px]">
|
||||
<h2 class="text-[#0F172A] font-bold text-[clamp(28px,3vw,40px)] leading-[1.15] max-w-[560px]">
|
||||
Every feature your school<br class="hidden sm:block" /> actually needs.
|
||||
</h2>
|
||||
<p class="text-[#64748B] text-[17px] leading-[1.6] text-center max-w-[560px]">
|
||||
<p class="text-[#64748B] text-[17px] leading-[1.6] max-w-[560px]">
|
||||
Designed around the real workflow of Filipino schools — from homeroom attendance to parent communication.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Cards grid: 2 rows × 3 cols -->
|
||||
<!-- 2 rows × 3 cols, gap 24 between cards, gap 24 between rows -->
|
||||
<div class="flex flex-col gap-6">
|
||||
<!-- Row 1 -->
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
<div
|
||||
v-for="(feature, i) in features.slice(0, 3)"
|
||||
:key="feature.title"
|
||||
v-for="(f, i) in features.slice(0, 3)"
|
||||
:key="f.title"
|
||||
v-reveal="{ delay: i * 80 }"
|
||||
class="flex"
|
||||
>
|
||||
<FeatureCard v-bind="feature" />
|
||||
<FeatureCard v-bind="f" />
|
||||
</div>
|
||||
</div>
|
||||
<!-- Row 2 -->
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
<div
|
||||
v-for="(feature, i) in features.slice(3)"
|
||||
:key="feature.title"
|
||||
v-for="(f, i) in features.slice(3)"
|
||||
:key="f.title"
|
||||
v-reveal="{ delay: i * 80 }"
|
||||
class="flex"
|
||||
>
|
||||
<FeatureCard v-bind="feature" />
|
||||
<FeatureCard v-bind="f" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -3,29 +3,30 @@
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section class="bg-[#F8FAFF] min-h-[640px] flex items-center">
|
||||
<div class="page-container w-full flex flex-col lg:flex-row items-center gap-16 xl:gap-20 py-16 lg:py-0">
|
||||
<!-- Design: height 640, padding [0, 100], gap 80 between columns -->
|
||||
<section class="bg-[#F8FAFF]">
|
||||
<div class="page-container w-full flex flex-col lg:flex-row items-center gap-20 min-h-[640px] py-20 lg:py-16">
|
||||
|
||||
<!-- ── Left Column ─────────────────────────────────── -->
|
||||
<div v-reveal class="flex-1 flex flex-col gap-7 min-w-0">
|
||||
|
||||
<!-- Pill badge -->
|
||||
<!-- Pill badge: fill #EFF6FF, cornerRadius 20, padding [5,12], gap 6 -->
|
||||
<div class="inline-flex items-center gap-1.5 bg-[#EFF6FF] rounded-full px-3 py-[5px] w-fit">
|
||||
<span class="w-1.5 h-1.5 rounded-full bg-[#1D4ED8] shrink-0"></span>
|
||||
<span class="text-[#1D4ED8] font-semibold text-xs">Built for Philippine Schools</span>
|
||||
<span class="text-[#1D4ED8] font-semibold text-xs leading-none">Built for Philippine Schools</span>
|
||||
</div>
|
||||
|
||||
<!-- H1 -->
|
||||
<!-- H1: 58px bold, lineHeight 1.1 -->
|
||||
<h1 class="text-[#0F172A] font-bold text-[clamp(38px,4.5vw,58px)] leading-[1.1] max-w-[560px]">
|
||||
Attendance That<br>Runs Itself.
|
||||
</h1>
|
||||
|
||||
<!-- Subtitle -->
|
||||
<!-- Subtitle: 17px, lineHeight 1.7 -->
|
||||
<p class="text-[#475569] text-[17px] leading-[1.7] max-w-[520px]">
|
||||
TapTrack is an on-premises NFC attendance system — students tap their ID card, parents get an SMS, and your records are updated automatically. No manual registers. No paper trails.
|
||||
</p>
|
||||
|
||||
<!-- CTA Buttons -->
|
||||
<!-- CTA Buttons: gap 12, padding [13, 26] -->
|
||||
<div class="flex flex-wrap items-center gap-3">
|
||||
<a
|
||||
href="#contact"
|
||||
@@ -41,18 +42,18 @@
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Trust row -->
|
||||
<!-- Trust row: gap 20 -->
|
||||
<div class="flex flex-wrap items-center gap-5">
|
||||
<span class="text-[#64748B] text-[13px]">✓ Student data stays on your servers</span>
|
||||
<span class="text-[#64748B] text-[13px]">✓ No cloud lock-in</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ── Right Column ────────────────────────────────── -->
|
||||
<!-- ── Right Column: width 580, gap 16 ───────────────── -->
|
||||
<div v-reveal="{ delay: 150 }" class="w-full lg:w-[580px] shrink-0 flex flex-col gap-4 items-center">
|
||||
|
||||
<!-- Screenshot frame -->
|
||||
<div class="w-full max-w-[580px] h-[300px] sm:h-[380px] rounded-2xl overflow-hidden border-2 border-[#E2E8F0] shadow-xl">
|
||||
<!-- Screenshot: 580×380, cornerRadius 16, border 2px -->
|
||||
<div class="w-full max-w-[580px] h-[320px] sm:h-[380px] rounded-2xl overflow-hidden border-2 border-[#E2E8F0] shadow-xl">
|
||||
<img
|
||||
src="/screenshots/58IBI.png"
|
||||
alt="TapTrack live attendance dashboard"
|
||||
@@ -60,7 +61,7 @@
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Caption -->
|
||||
<!-- Caption: 12px, textAlign center -->
|
||||
<p class="text-[#94A3B8] text-xs text-center max-w-[520px] leading-relaxed">
|
||||
Live dashboard running on your school's own server — data never leaves your premises.
|
||||
</p>
|
||||
|
||||
@@ -1,24 +1,22 @@
|
||||
<script setup lang="ts">
|
||||
import { Wrench, Zap, CircleCheck } from 'lucide-vue-next'
|
||||
|
||||
// Design: padding [96, 100], gap 80, layout horizontal
|
||||
const steps = [
|
||||
{
|
||||
num: '1',
|
||||
title: "We install TapTrack on your school's hardware",
|
||||
description:
|
||||
'Our team sets up the on-premises software and NFC reader. You pay a one-time implementation fee and you own the setup.',
|
||||
description: 'Our team sets up the on-premises software and NFC reader. You pay a one-time implementation fee and you own the setup.',
|
||||
},
|
||||
{
|
||||
num: '2',
|
||||
title: 'We enrol your students and train your staff',
|
||||
description:
|
||||
'We import your student list, assign NFC ID cards, add parent numbers, and run a full walkthrough with your administrators.',
|
||||
description: 'We import your student list, assign NFC ID cards, add parent numbers, and run a full walkthrough with your administrators.',
|
||||
},
|
||||
{
|
||||
num: '3',
|
||||
title: 'Top up SMS credits monthly as needed',
|
||||
description:
|
||||
'No recurring subscription. You purchase prepaid SMS credits when you need them. The system keeps sending alerts as long as your credits last.',
|
||||
description: 'No recurring subscription. You purchase prepaid SMS credits when you need them. The system keeps sending alerts as long as your credits last.',
|
||||
},
|
||||
]
|
||||
|
||||
@@ -42,10 +40,12 @@ const billingItems = [
|
||||
|
||||
<template>
|
||||
<section id="how-it-works" class="bg-[#F8FAFF]">
|
||||
<div class="page-container flex flex-col lg:flex-row gap-16 xl:gap-20 py-24">
|
||||
<div class="page-container flex flex-col lg:flex-row gap-20 py-24">
|
||||
|
||||
<!-- Left: Steps -->
|
||||
<!-- Left column: gap 40 -->
|
||||
<div v-reveal class="flex-1 flex flex-col gap-10 min-w-0">
|
||||
|
||||
<!-- Header: gap 10 -->
|
||||
<div class="flex flex-col gap-2.5">
|
||||
<span class="text-[#1D4ED8] font-semibold text-[11px] tracking-[2px] uppercase">
|
||||
How It Works
|
||||
@@ -58,16 +58,19 @@ const billingItems = [
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col gap-8">
|
||||
<!-- Steps: gap 40, each step gap 20 -->
|
||||
<div class="flex flex-col gap-10">
|
||||
<div
|
||||
v-for="(step, i) in steps"
|
||||
:key="step.num"
|
||||
v-reveal="{ delay: i * 100 }"
|
||||
class="flex items-start gap-5"
|
||||
>
|
||||
<!-- Number bubble: 36×36, cornerRadius 18 -->
|
||||
<div class="w-9 h-9 rounded-full bg-[#1D4ED8] flex items-center justify-center shrink-0 mt-0.5">
|
||||
<span class="text-white font-bold text-[15px] leading-none">{{ step.num }}</span>
|
||||
</div>
|
||||
<!-- Step content: gap 6 -->
|
||||
<div class="flex flex-col gap-1.5 min-w-0">
|
||||
<h3 class="text-[#0F172A] font-semibold text-[15px] leading-snug">{{ step.title }}</h3>
|
||||
<p class="text-[#64748B] text-[13px] leading-[1.6]">{{ step.description }}</p>
|
||||
@@ -76,20 +79,22 @@ const billingItems = [
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Right: Billing card -->
|
||||
<!-- Right: Billing card, width 460, padding 40, gap 24, cornerRadius 20 -->
|
||||
<div v-reveal="{ delay: 150 }" class="w-full lg:w-[460px] shrink-0">
|
||||
<div class="bg-white border border-[#E2E8F0] rounded-[20px] p-8 lg:p-10 flex flex-col gap-6">
|
||||
<h3 class="text-[#0F172A] font-bold text-xl">How billing works</h3>
|
||||
<p class="text-[#64748B] text-[14px] leading-[1.6]">
|
||||
Transparent, no surprises. You only pay for what you actually use.
|
||||
</p>
|
||||
<div class="bg-white border border-[#E2E8F0] rounded-[20px] p-10 flex flex-col gap-6 h-full">
|
||||
<div class="flex flex-col gap-2">
|
||||
<h3 class="text-[#0F172A] font-bold text-xl">How billing works</h3>
|
||||
<p class="text-[#64748B] text-[14px] leading-[1.6]">
|
||||
Transparent, no surprises. You only pay for what you actually use.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col">
|
||||
<!-- Billing items -->
|
||||
<div class="flex flex-col divide-y divide-[#F1F5F9]">
|
||||
<div
|
||||
v-for="(item, i) in billingItems"
|
||||
v-for="item in billingItems"
|
||||
:key="item.title"
|
||||
class="flex items-start gap-3.5 py-4"
|
||||
:class="i === 0 ? 'border-b border-[#F1F5F9]' : ''"
|
||||
class="flex items-start gap-3.5 py-4 first:pt-0 last:pb-0"
|
||||
>
|
||||
<div
|
||||
class="w-9 h-9 rounded-lg flex items-center justify-center shrink-0"
|
||||
@@ -97,13 +102,14 @@ const billingItems = [
|
||||
>
|
||||
<component :is="item.icon" :size="18" :stroke-width="1.75" :style="{ color: item.iconColor }" />
|
||||
</div>
|
||||
<div class="flex flex-col gap-0.5 min-w-0">
|
||||
<div class="flex flex-col gap-1 min-w-0">
|
||||
<span class="text-[#0F172A] font-semibold text-[14px]">{{ item.title }}</span>
|
||||
<span class="text-[#64748B] text-[13px] leading-[1.5]">{{ item.description }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Note: fill #F0FDF4, cornerRadius 8, padding [12,14], gap 10 -->
|
||||
<div class="flex items-start gap-2.5 bg-[#F0FDF4] rounded-lg px-3.5 py-3">
|
||||
<CircleCheck :size="16" :stroke-width="2" class="text-[#16A34A] shrink-0 mt-0.5" />
|
||||
<p class="text-[#15803D] text-[13px] leading-[1.5]">
|
||||
|
||||
@@ -9,31 +9,35 @@ const stats = [
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- Design: padding [56, 100], gap 80, alignItems center -->
|
||||
<section class="bg-[#0F172A]">
|
||||
<div class="page-container flex flex-col lg:flex-row items-start lg:items-center gap-12 lg:gap-20 py-14">
|
||||
<div class="page-container flex flex-col lg:flex-row items-start lg:items-center gap-20 py-14">
|
||||
|
||||
<!-- Left: Text content -->
|
||||
<!-- Left: gap 12 -->
|
||||
<div v-reveal class="flex-1 flex flex-col gap-3 min-w-0">
|
||||
<!-- Label: fill #1E3A5F, cornerRadius 4, padding [4,10] -->
|
||||
<div class="w-fit bg-[#1E3A5F] rounded px-[10px] py-1">
|
||||
<span class="text-[#60A5FA] font-semibold text-[11px] tracking-[1px] uppercase">
|
||||
Data Privacy
|
||||
</span>
|
||||
</div>
|
||||
<!-- Title: 28px bold, lineHeight 1.2, max-w 500 -->
|
||||
<h2 class="text-white font-bold text-[28px] leading-[1.2] max-w-[500px]">
|
||||
Student data never leaves your school.
|
||||
</h2>
|
||||
<!-- Sub: 15px, lineHeight 1.6, max-w 500 -->
|
||||
<p class="text-[#94A3B8] text-[15px] leading-[1.6] max-w-[500px]">
|
||||
TapTrack runs entirely on your own server. No student records, attendance logs, or personal data are ever uploaded to a third-party cloud.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Right: Stat items -->
|
||||
<!-- Right: gap 40, stat items centered -->
|
||||
<div class="flex flex-row flex-wrap gap-10 shrink-0">
|
||||
<div
|
||||
v-for="(stat, i) in stats"
|
||||
:key="stat.label"
|
||||
v-reveal="{ delay: i * 100 }"
|
||||
class="flex flex-col items-center gap-1.5 min-w-[90px]"
|
||||
class="flex flex-col items-center gap-1.5 min-w-[100px]"
|
||||
>
|
||||
<component :is="stat.icon" class="text-[#60A5FA]" :size="28" :stroke-width="1.75" />
|
||||
<span class="text-white font-semibold text-[13px]">{{ stat.label }}</span>
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
<script setup lang="ts">
|
||||
// Design: padding [96, 100], gap 56, screenshot cards cornerRadius 14, border #E2E8F0
|
||||
const cards = [
|
||||
{
|
||||
img: '/screenshots/4frZA.png',
|
||||
alt: 'TapTrack Student Directory screen',
|
||||
title: 'Student Directory',
|
||||
description:
|
||||
'Manage your full roster — NFC ID assignments, parent numbers, section placement, and enrolment status all in one place.',
|
||||
description: 'Manage your full roster — NFC ID assignments, parent numbers, section placement, and enrolment status all in one place.',
|
||||
},
|
||||
{
|
||||
img: '/screenshots/Reports.jpg',
|
||||
alt: 'TapTrack Reports & Analytics screen',
|
||||
title: 'Reports & Analytics',
|
||||
description:
|
||||
'Generate attendance summaries by class, date range, and section. Export to PDF or Excel for DepEd compliance and parent meetings.',
|
||||
description: 'Generate attendance summaries by class, date range, and section. Export to PDF or Excel for DepEd compliance and parent meetings.',
|
||||
},
|
||||
]
|
||||
</script>
|
||||
@@ -22,19 +21,19 @@ const cards = [
|
||||
<div class="page-container flex flex-col gap-14 py-24">
|
||||
|
||||
<!-- Header -->
|
||||
<div v-reveal class="flex flex-col items-center gap-2.5">
|
||||
<div v-reveal class="flex flex-col items-center gap-2.5 text-center">
|
||||
<span class="text-[#1D4ED8] font-semibold text-[11px] tracking-[2px] uppercase">
|
||||
Inside TapTrack
|
||||
</span>
|
||||
<h2 class="text-[#0F172A] font-bold text-[clamp(26px,3vw,38px)] leading-[1.15] text-center max-w-[600px]">
|
||||
<h2 class="text-[#0F172A] font-bold text-[clamp(26px,3vw,38px)] leading-[1.15] max-w-[600px]">
|
||||
A system built for how your school actually works.
|
||||
</h2>
|
||||
<p class="text-[#64748B] text-[16px] leading-[1.6] text-center max-w-[580px]">
|
||||
<p class="text-[#64748B] text-[16px] leading-[1.6] max-w-[580px]">
|
||||
Every screen is purpose-built for school administrators, advisers, and principals — not generic enterprise software.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Screenshot cards grid -->
|
||||
<!-- 2-col card grid, gap 28 -->
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-7">
|
||||
<div
|
||||
v-for="(card, i) in cards"
|
||||
@@ -42,14 +41,16 @@ const cards = [
|
||||
v-reveal="{ delay: i * 120 }"
|
||||
class="flex flex-col rounded-[14px] border border-[#E2E8F0] overflow-hidden"
|
||||
>
|
||||
<div class="h-[240px] sm:h-[300px] lg:h-[340px] overflow-hidden">
|
||||
<!-- Image: height 340, object-top -->
|
||||
<div class="h-[260px] sm:h-[320px] lg:h-[340px] overflow-hidden">
|
||||
<img
|
||||
:src="card.img"
|
||||
:alt="card.alt"
|
||||
class="w-full h-full object-cover object-top"
|
||||
class="w-full h-full object-cover object-top block"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-col gap-1.5 px-6 py-5">
|
||||
<!-- Info: padding [20, 24], gap 6 -->
|
||||
<div class="flex flex-col gap-2 px-6 py-5">
|
||||
<h3 class="text-[#0F172A] font-semibold text-base">{{ card.title }}</h3>
|
||||
<p class="text-[#64748B] text-[13px] leading-[1.6]">{{ card.description }}</p>
|
||||
</div>
|
||||
|
||||
@@ -1,34 +1,37 @@
|
||||
<script setup lang="ts">
|
||||
// Gate View kiosk screenshot section
|
||||
// Design: padding [96, 100], gap 40, layout vertical, alignItems center
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section class="bg-[#F8FAFF]">
|
||||
<div class="page-container flex flex-col items-center gap-10 py-24">
|
||||
|
||||
<!-- Header -->
|
||||
<div v-reveal class="flex flex-col items-center gap-2.5 w-full">
|
||||
<!-- Header: gap 10, alignItems center, width fill -->
|
||||
<div v-reveal class="flex flex-col items-center gap-2.5 w-full max-w-[640px]">
|
||||
<!-- Label: 11px semibold, tracking 2px -->
|
||||
<span class="text-[#1D4ED8] font-semibold text-[11px] tracking-[2px] uppercase">
|
||||
The System in Action
|
||||
</span>
|
||||
<h2 class="text-[#0F172A] font-bold text-[clamp(28px,3vw,38px)] leading-[1.15] text-center max-w-[600px]">
|
||||
<!-- Title: 38px bold, lineHeight 1.15, textAlign center, width 600 -->
|
||||
<h2 class="text-[#0F172A] font-bold text-[clamp(28px,3vw,38px)] leading-[1.15] text-center">
|
||||
The gate display students see every morning.
|
||||
</h2>
|
||||
<p class="text-[#64748B] text-[16px] leading-[1.6] text-center max-w-[600px]">
|
||||
<!-- Sub: 16px, lineHeight 1.6, textAlign center, width 600 -->
|
||||
<p class="text-[#64748B] text-[16px] leading-[1.6] text-center">
|
||||
A full-screen kiosk view runs at your school gate — students tap their NFC ID card and instantly see their name, section, and status confirmed.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Gate View Screenshot -->
|
||||
<!-- Gate screenshot: width 960, height 540, cornerRadius 16, border #E2E8F0 -->
|
||||
<div v-reveal="{ delay: 100 }" class="w-full max-w-[960px] rounded-2xl overflow-hidden border border-[#E2E8F0] shadow-lg">
|
||||
<img
|
||||
src="/screenshots/gE861.png"
|
||||
alt="TapTrack gate kiosk display"
|
||||
class="w-full h-auto object-cover"
|
||||
class="w-full h-auto block"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Caption -->
|
||||
<!-- Caption: 13px, textAlign center, width 700 -->
|
||||
<p v-reveal="{ delay: 150 }" class="text-[#94A3B8] text-[13px] text-center max-w-[700px] leading-relaxed">
|
||||
Full-screen gate display running on a monitor at your school entrance. No login required for students — just tap and go.
|
||||
</p>
|
||||
|
||||
@@ -8,46 +8,42 @@ import {
|
||||
} from 'lucide-vue-next'
|
||||
import FeatureCard from './FeatureCard.vue'
|
||||
|
||||
// Design: padding [96, 100], gap 64, card padding [36, 28]
|
||||
const supportCards = [
|
||||
{
|
||||
icon: Headphones,
|
||||
iconColor: '#1D4ED8',
|
||||
iconBg: '#EFF6FF',
|
||||
title: 'Dedicated Support Channel',
|
||||
description:
|
||||
'Get direct access to our technical team via chat or phone. No ticket queues, no bots — real people who know your setup.',
|
||||
description: 'Get direct access to our technical team via chat or phone. No ticket queues, no bots — real people who know your setup.',
|
||||
},
|
||||
{
|
||||
icon: Settings,
|
||||
iconColor: '#CA8A04',
|
||||
iconBg: '#FEF9C3',
|
||||
title: 'System Updates & Maintenance',
|
||||
description:
|
||||
'We push updates to fix bugs and add improvements. Your system stays current without you having to do anything.',
|
||||
description: 'We push updates to fix bugs and add improvements. Your system stays current without you having to do anything.',
|
||||
},
|
||||
{
|
||||
icon: GraduationCap,
|
||||
iconColor: '#059669',
|
||||
iconBg: '#ECFDF5',
|
||||
title: 'Staff Re-training Assistance',
|
||||
description:
|
||||
"New school year, new staff? We'll get your team up to speed. Re-training sessions available on request.",
|
||||
description: "New school year, new staff? We'll get your team up to speed. Re-training sessions available on request.",
|
||||
},
|
||||
{
|
||||
icon: Monitor,
|
||||
iconColor: '#7C3AED',
|
||||
iconBg: '#F3E8FF',
|
||||
title: 'Remote Troubleshooting',
|
||||
description:
|
||||
'Most issues can be resolved remotely. Our team can connect to your system and fix problems without an on-site visit.',
|
||||
description: 'Most issues can be resolved remotely. Our team can connect to your system and fix problems without an on-site visit.',
|
||||
},
|
||||
{
|
||||
icon: DatabaseBackup,
|
||||
iconColor: '#E11D48',
|
||||
iconBg: '#FFF1F2',
|
||||
title: 'Data Backup Assistance',
|
||||
description:
|
||||
'We help you set up regular attendance data backups so your records are always safe, even if hardware fails.',
|
||||
description: 'We help you set up regular attendance data backups so your records are always safe, even if hardware fails.',
|
||||
},
|
||||
]
|
||||
</script>
|
||||
@@ -57,42 +53,44 @@ const supportCards = [
|
||||
<div class="page-container flex flex-col gap-16 py-24">
|
||||
|
||||
<!-- Header -->
|
||||
<div v-reveal class="flex flex-col items-center gap-2.5">
|
||||
<div v-reveal class="flex flex-col items-center gap-2.5 text-center">
|
||||
<span class="text-[#1D4ED8] font-semibold text-[11px] tracking-[2px] uppercase">
|
||||
After-Sales Support
|
||||
</span>
|
||||
<h2 class="text-[#0F172A] font-bold text-[clamp(28px,3vw,38px)] leading-[1.15] text-center max-w-[560px]">
|
||||
<h2 class="text-[#0F172A] font-bold text-[clamp(28px,3vw,38px)] leading-[1.15] max-w-[560px]">
|
||||
We don't just install and leave.
|
||||
</h2>
|
||||
<p class="text-[#64748B] text-[17px] leading-[1.6] text-center max-w-[560px]">
|
||||
<p class="text-[#64748B] text-[17px] leading-[1.6] max-w-[560px]">
|
||||
Our team stays with you long after go-live. If something breaks or your staff needs help, we're one message away.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Row 1: 3 cards -->
|
||||
<!-- Row 1: 3 cards, gap 24 -->
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
<div
|
||||
v-for="(card, i) in supportCards.slice(0, 3)"
|
||||
:key="card.title"
|
||||
v-reveal="{ delay: i * 80 }"
|
||||
class="flex"
|
||||
>
|
||||
<FeatureCard v-bind="card" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Row 2: 2 cards + quote card -->
|
||||
<!-- Row 2: 2 support cards + quote card -->
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
<div
|
||||
v-for="(card, i) in supportCards.slice(3)"
|
||||
:key="card.title"
|
||||
v-reveal="{ delay: i * 80 }"
|
||||
class="flex"
|
||||
>
|
||||
<FeatureCard v-bind="card" />
|
||||
</div>
|
||||
|
||||
<!-- Quote card -->
|
||||
<div v-reveal="{ delay: 160 }" class="flex flex-col gap-4 bg-[#EFF6FF] border border-[#BFDBFE] rounded-[14px] p-7 pt-9">
|
||||
<p class="text-[#1E3A5F] font-medium text-base leading-[1.65]">
|
||||
<!-- Quote card: fill #EFF6FF, border #BFDBFE, padding [36, 28], gap 16 -->
|
||||
<div v-reveal="{ delay: 160 }" class="flex flex-col gap-4 bg-[#EFF6FF] border border-[#BFDBFE] rounded-2xl px-7 pt-9 pb-8">
|
||||
<p class="text-[#1E3A5F] font-medium text-base leading-[1.65] flex-1">
|
||||
"Think of us as your school's IT partner for attendance — not just a vendor who sold you something."
|
||||
</p>
|
||||
<div class="flex items-center gap-2.5">
|
||||
|
||||
Reference in New Issue
Block a user