<section class="demo-section">
<h2>Cards</h2>
<div class="demo-row" style="align-items: stretch;">
<article class="card" style="max-width: 320px;">
<header class="card-title">Default card</header>
<div class="card-content">
A simple card with title, content, and footer.
</div>
<footer class="card-footer">
<button class="btn btn-primary btn-sm">Action</button>
</footer>
</article>
<article class="card card-filled" style="max-width: 320px;">
<header class="card-title">Filled card</header>
<div class="card-content">
Uses a subtle background fill instead of white.
</div>
<footer class="card-footer">
<button class="btn btn-secondary btn-sm">Action</button>
</footer>
</article>
<article class="card card-outlined" style="max-width: 320px;">
<header class="card-title">Outlined card</header>
<div class="card-content">
Transparent background with a stronger border.
</div>
<footer class="card-footer">
<button class="btn btn-tertiary btn-sm">Action</button>
</footer>
</article>
</div>
<div class="demo-row" style="align-items: stretch;">
<article class="card card-primary" style="max-width: 320px;">
<div class="card-content">
Primary accent card with yellow tint.
</div>
</article>
<article class="card card-secondary" style="max-width: 320px;">
<div class="card-content">
Secondary accent card with mint tint.
</div>
</article>
<article class="card card-elevated" style="max-width: 320px;">
<div class="card-content">
Elevated card with a soft shadow.
</div>
</article>
</div>
<h3>Sizes</h3>
<div class="demo-row" style="align-items: stretch;">
<article class="card card-sm" style="max-width: 240px;">
<header class="card-title">Small card</header>
<div class="card-content">Compact padding and radius.</div>
</article>
<article class="card card-lg" style="max-width: 360px;">
<header class="card-title">Large card</header>
<div class="card-content">Generous padding and larger radius.</div>
</article>
</div>
<h3>Status cards</h3>
<div class="demo-row" style="align-items: stretch;">
<article class="card status-card card-success" style="max-width: 220px;">
<span class="card-title">Healthy</span>
<div class="card-content">
<div class="status-icon-container">
<div class="status-icon"><i class="ph ph-check-circle"></i></div>
</div>
<p class="status-name">All systems operational.</p>
</div>
</article>
<article class="card status-card card-warning" style="max-width: 220px;">
<span class="card-title">Pending</span>
<div class="card-content">
<div class="status-icon-container">
<div class="status-icon"><i class="ph ph-warning"></i></div>
</div>
<p class="status-name">Waiting for approval.</p>
</div>
</article>
<article class="card status-card card-error" style="max-width: 220px;">
<span class="card-title">Failed</span>
<div class="card-content">
<div class="status-icon-container">
<div class="status-icon"><i class="ph ph-warning-octagon"></i></div>
</div>
<p class="status-name">Build failed at step 4.</p>
</div>
</article>
</div>
<h3>Metric card</h3>
<div class="demo-row" style="align-items: stretch;">
<article class="card metric-card" style="max-width: 320px;">
<div class="card-content">
<div class="metric-card-header">
<p class="metric-card-label">Monthly usage</p>
<span class="metric-card-icon"><i class="ph ph-chart-line-up"></i></span>
</div>
<p class="metric-card-value">84.2%</p>
<div class="metric-card-meta">
<span class="metric-card-delta">+12.8%</span>
<span>vs previous period</span>
</div>
</div>
</article>
</div>
<h3>Horizontal card</h3>
<div class="demo-row" style="align-items: stretch;">
<article class="card card-horizontal" style="max-width: 640px;">
<div class="card-media">
<img src="/assets/avatar-placeholder.jpg" alt="">
</div>
<div class="card-body">
<h3 class="card-title"><a href="#">Project Alpha</a></h3>
<div class="card-content">
<p>Compact horizontal layout for content listings, search results, and entity rows.</p>
</div>
<div class="card-footer">
<span>Updated 2h ago</span>
<span class="badge badge-success">Active</span>
</div>
</div>
</article>
</div>
<h3>Login card</h3>
<div class="demo-row" style="align-items: stretch;">
<article class="card login-card">
<header class="card-title login-card-header">
<span class="login-card-title">Sign in</span>
</header>
<div class="card-content">
<form class="login-card-form" onsubmit="event.preventDefault();">
<div class="form-group">
<label class="label">
Username
<input type="text" class="input" placeholder="Enter username" autocomplete="username">
</label>
</div>
<div class="form-group">
<label class="label">
Password
<input type="password" class="input" placeholder="••••••" autocomplete="current-password">
</label>
</div>
<button class="btn btn-secondary with-icon login-card-submit" type="submit"><i class="ph ph-sign-in"></i> Sign in</button>
<div class="login-card-links">
<a href="#" class="login-card-link">Forgot password?</a>
<a href="#" class="login-card-link">Create account</a>
</div>
</form>
</div>
</article>
</div>
<h3>User card — compact</h3>
<div class="demo-row" style="align-items: stretch;">
<article class="card user-card user-card-compact" style="max-width: 360px;">
<div class="user-card-body">
<a class="profile-identity" href="#" target="_blank" rel="noopener noreferrer">
<span class="identity">
<span class="avatar avatar-mint avatar-sm is-online">
<img src="/assets/avatar-placeholder.jpg" alt="">
</span>
<span class="identity-content">
<span class="identity-title">Eugene Sukhodolskiy</span>
<span class="identity-meta">goldmikki@gmail.com</span>
</span>
</span>
</a>
<div class="user-card-actions">
<button class="btn-icon" type="button" aria-label="Edit profile"><i class="ph ph-pencil-simple" aria-hidden="true"></i></button>
<button class="btn-icon" type="button" aria-label="Logout"><i class="ph ph-sign-out" aria-hidden="true"></i></button>
</div>
</div>
</article>
</div>
<h3>User card — full</h3>
<div class="demo-row" style="align-items: stretch;">
<article class="card user-card" style="max-width: 320px;">
<div class="user-card-body">
<span class="identity">
<span class="avatar avatar-mint avatar-md is-online">
<img src="/assets/avatar-placeholder.jpg" alt="">
</span>
<span class="identity-content">
<span class="identity-title">Eugene Sukhodolskiy</span>
<span class="identity-meta">goldmikki@gmail.com</span>
</span>
</span>
<span class="user-card-role">Lead Frontend Engineer</span>
<div class="user-card-actions">
<button class="btn btn-primary btn-sm" type="button">View profile</button>
<button class="btn btn-secondary btn-sm" type="button">Message</button>
</div>
</div>
</article>
</div>
<h3>Vue cards</h3>
<div id="vue-cards-app" class="vue-mount"></div>
<script type="module">
import { createApp } from "vue";
import { GnCard, GnButton } from "/vue/index.js";
createApp({
components: { GnCard, GnButton },
template: `
<div class="demo-row" style="align-items: stretch;">
<gn-card title="Vue card" style="max-width: 320px;">
Content rendered through the Vue adapter.
<template #footer>
<gn-button variant="primary" size="sm">Action</gn-button>
</template>
</gn-card>
</div>
`
}).mount("#vue-cards-app");
</script>
<h3>Vue action card</h3>
<div id="vue-action-card-app" class="vue-mount"></div>
<script type="module">
import { createApp } from "vue";
import { GnActionCard, GnButton } from "/vue/index.js";
createApp({
components: { GnActionCard, GnButton },
template: `
<div class="demo-row" style="align-items: stretch;">
<gn-action-card kicker="Pro tip" title="Ready to publish?" text="Review your changes before making them public." style="max-width: 360px;">
<template #actions>
<gn-button variant="primary" size="sm">Publish</gn-button>
<gn-button variant="secondary" size="sm">Cancel</gn-button>
</template>
</gn-action-card>
</div>
`
}).mount("#vue-action-card-app");
</script>
<h3>Vue card gallery</h3>
<div id="vue-card-gallery-app" class="vue-mount"></div>
<script type="module">
import { createApp, ref } from "vue";
import { GnHorizontalCard, GnUserCard, GnMetricCard, GnStatusCard, GnLoginCard, GnButton, GnBadge } from "/vue/index.js";
createApp({
components: { GnHorizontalCard, GnUserCard, GnMetricCard, GnStatusCard, GnLoginCard, GnButton, GnBadge },
setup() {
const submitted = ref(false);
const onLogin = (payload) => { submitted.value = JSON.stringify(payload); };
return { submitted, onLogin };
},
template: `
<div class="demo-row" style="align-items: stretch; flex-wrap: wrap;">
<gn-horizontal-card image="/assets/avatar-placeholder.jpg" title="Project Alpha" title-href="#project" icon="ph-arrow-right" style="max-width: 640px;">
<p>Compact horizontal layout for content listings.</p>
<template #footer>
<span>Updated 2h ago</span>
<gn-badge variant="success">Active</gn-badge>
</template>
</gn-horizontal-card>
<gn-metric-card label="Monthly usage" value="84.2%" delta="+12.8%" meta="vs previous period" icon="ph-chart-line-up" style="max-width: 320px;" />
<gn-status-card title="Healthy" text="All systems operational." icon="ph-check-circle" variant="success" style="max-width: 220px;" />
<gn-user-card
name="Eugene Sukhodolskiy"
email="goldmikki@gmail.com"
role="Lead Frontend Engineer"
:avatar="{ src: '/assets/avatar-placeholder.jpg', status: 'online', size: 'md', variant: 'mint' }"
href="#profile"
:actions="[
{ icon: 'ph-user', label: 'View profile', variant: 'primary' },
{ icon: 'ph-chat-circle', label: 'Message', variant: 'secondary' }
]"
style="max-width: 320px;"
/>
<gn-login-card
title="Sign in"
username-label="Username"
password-label="Password"
submit-text="Sign in"
remember-me
forgot-href="#forgot"
signup-href="#signup"
@submit="onLogin"
/>
</div>
<p v-if="submitted" class="text-muted" style="margin-top: 12px;">Submitted: {{ submitted }}</p>
`
}).mount("#vue-card-gallery-app");
</script>
</section>