grubflip-design/page-template.html
Ava 9fb5bd83a6 Add Payfrit design system, page templates, and component prototypes
Core brand design system, page layout templates, avatar styles,
sponsor token purchase flow, and status dashboard — all as living
HTML/CSS design references for the team.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 05:56:18 +00:00

1327 lines
47 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Payfrit — Page Template</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
/* ========================================
PAYFRIT PAGE TEMPLATE v1.0
Created by Ava — 2026-03-19
Design tokens mirror design-system.html
======================================== */
/* --- Design Tokens --- */
:root {
--color-primary: #0D6E6E;
--color-primary-light: #14A3A3;
--color-primary-dark: #094F4F;
--color-primary-bg: #E6F5F5;
--color-accent: #F5A623;
--color-accent-light: #FFCF70;
--color-accent-dark: #C4841A;
--color-success: #2ECC71;
--color-success-bg: #EAFAF1;
--color-warning: #F39C12;
--color-warning-bg: #FEF5E7;
--color-error: #E74C3C;
--color-error-bg: #FDEDEC;
--color-gray-50: #F9FAFB;
--color-gray-100: #F3F4F6;
--color-gray-200: #E5E7EB;
--color-gray-300: #D1D5DB;
--color-gray-400: #9CA3AF;
--color-gray-500: #6B7280;
--color-gray-600: #4B5563;
--color-gray-700: #374151;
--color-gray-800: #1F2937;
--color-gray-900: #111827;
--color-bg: #FFFFFF;
--color-bg-subtle: #F9FAFB;
--color-bg-muted: #F3F4F6;
--font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
--text-xs: 0.75rem;
--text-sm: 0.875rem;
--text-base: 1rem;
--text-lg: 1.125rem;
--text-xl: 1.25rem;
--text-2xl: 1.5rem;
--text-3xl: 1.875rem;
--font-normal: 400;
--font-medium: 500;
--font-semibold:600;
--font-bold: 700;
--leading-normal: 1.5;
--space-1: 0.25rem;
--space-2: 0.5rem;
--space-3: 0.75rem;
--space-4: 1rem;
--space-5: 1.25rem;
--space-6: 1.5rem;
--space-8: 2rem;
--space-10: 2.5rem;
--space-12: 3rem;
--radius-sm: 0.25rem;
--radius-md: 0.5rem;
--radius-lg: 0.75rem;
--radius-xl: 1rem;
--radius-full: 9999px;
--shadow-sm: 0 1px 2px rgba(0,0,0,0.05);
--shadow-md: 0 4px 6px -1px rgba(0,0,0,0.1), 0 2px 4px -2px rgba(0,0,0,0.1);
--shadow-lg: 0 10px 15px -3px rgba(0,0,0,0.1), 0 4px 6px -4px rgba(0,0,0,0.1);
--transition-fast: 150ms ease;
--transition-base: 200ms ease;
/* Layout */
--sidebar-width: 240px;
--header-height: 60px;
--sidebar-collapsed: 0px;
}
/* --- Reset --- */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { font-size: 16px; -webkit-font-smoothing: antialiased; scroll-behavior: smooth; }
body {
font-family: var(--font-family);
color: var(--color-gray-800);
background: var(--color-bg-subtle);
line-height: var(--leading-normal);
min-height: 100vh;
}
a { color: var(--color-primary); text-decoration: none; }
a:hover { color: var(--color-primary-dark); }
img { max-width: 100%; display: block; }
button { cursor: pointer; font-family: inherit; }
/* ========================================
LAYOUT SKELETON
======================================== */
/* Outer shell: header is fixed, body scrolls */
.pf-shell {
display: flex;
flex-direction: column;
min-height: 100vh;
}
/* ----------------------------------------
HEADER
---------------------------------------- */
.pf-header {
position: fixed;
top: 0;
left: 0;
right: 0;
height: var(--header-height);
background: var(--color-primary-dark);
display: flex;
align-items: center;
padding: 0 var(--space-6);
z-index: 200;
box-shadow: var(--shadow-md);
}
/* Logo */
.pf-logo {
display: flex;
align-items: center;
gap: var(--space-2);
text-decoration: none;
flex-shrink: 0;
}
.pf-logo__mark {
width: 32px;
height: 32px;
background: var(--color-accent);
border-radius: var(--radius-md);
display: flex;
align-items: center;
justify-content: center;
font-weight: var(--font-bold);
font-size: var(--text-sm);
color: var(--color-primary-dark);
letter-spacing: -0.5px;
}
.pf-logo__name {
font-size: var(--text-lg);
font-weight: var(--font-bold);
color: #FFFFFF;
letter-spacing: -0.3px;
}
.pf-logo__name span {
color: var(--color-accent-light);
}
/* Mobile hamburger */
.pf-hamburger {
display: none;
margin-left: var(--space-4);
background: transparent;
border: none;
padding: var(--space-2);
border-radius: var(--radius-sm);
color: rgba(255,255,255,0.85);
transition: background var(--transition-fast);
}
.pf-hamburger:hover { background: rgba(255,255,255,0.1); }
.pf-hamburger svg { display: block; }
/* Header center — global search */
.pf-header__search {
flex: 1;
max-width: 420px;
margin: 0 var(--space-8);
}
.pf-search-wrap {
position: relative;
}
.pf-search-wrap svg {
position: absolute;
left: var(--space-3);
top: 50%;
transform: translateY(-50%);
color: var(--color-gray-400);
pointer-events: none;
}
.pf-search {
width: 100%;
height: 36px;
background: rgba(255,255,255,0.1);
border: 1px solid rgba(255,255,255,0.15);
border-radius: var(--radius-full);
padding: 0 var(--space-4) 0 2.25rem;
color: #fff;
font-size: var(--text-sm);
outline: none;
transition: background var(--transition-fast), border-color var(--transition-fast);
}
.pf-search::placeholder { color: rgba(255,255,255,0.5); }
.pf-search:focus {
background: rgba(255,255,255,0.18);
border-color: rgba(255,255,255,0.35);
}
/* Header right — actions */
.pf-header__actions {
display: flex;
align-items: center;
gap: var(--space-2);
margin-left: auto;
}
.pf-icon-btn {
width: 36px;
height: 36px;
background: transparent;
border: none;
border-radius: var(--radius-md);
color: rgba(255,255,255,0.8);
display: flex;
align-items: center;
justify-content: center;
position: relative;
transition: background var(--transition-fast), color var(--transition-fast);
}
.pf-icon-btn:hover { background: rgba(255,255,255,0.1); color: #fff; }
.pf-badge {
position: absolute;
top: 4px;
right: 4px;
width: 8px;
height: 8px;
background: var(--color-accent);
border-radius: var(--radius-full);
border: 2px solid var(--color-primary-dark);
}
.pf-avatar {
width: 32px;
height: 32px;
border-radius: var(--radius-full);
background: linear-gradient(135deg, var(--color-primary-light), var(--color-accent));
border: 2px solid rgba(255,255,255,0.25);
display: flex;
align-items: center;
justify-content: center;
font-size: var(--text-xs);
font-weight: var(--font-semibold);
color: white;
cursor: pointer;
transition: border-color var(--transition-fast);
margin-left: var(--space-2);
}
.pf-avatar:hover { border-color: rgba(255,255,255,0.6); }
/* ----------------------------------------
BODY (below fixed header)
---------------------------------------- */
.pf-body {
display: flex;
margin-top: var(--header-height);
flex: 1;
min-height: calc(100vh - var(--header-height));
}
/* ----------------------------------------
SIDEBAR
---------------------------------------- */
.pf-sidebar {
width: var(--sidebar-width);
flex-shrink: 0;
background: var(--color-bg);
border-right: 1px solid var(--color-gray-200);
display: flex;
flex-direction: column;
position: sticky;
top: var(--header-height);
height: calc(100vh - var(--header-height));
overflow-y: auto;
overflow-x: hidden;
transition: width var(--transition-base), transform var(--transition-base);
z-index: 100;
}
/* Scrollbar styling */
.pf-sidebar::-webkit-scrollbar { width: 4px; }
.pf-sidebar::-webkit-scrollbar-track { background: transparent; }
.pf-sidebar::-webkit-scrollbar-thumb { background: var(--color-gray-300); border-radius: 4px; }
.pf-sidebar__inner {
padding: var(--space-4) 0 var(--space-8);
display: flex;
flex-direction: column;
gap: var(--space-1);
flex: 1;
}
/* Nav section label */
.pf-nav-label {
font-size: var(--text-xs);
font-weight: var(--font-semibold);
color: var(--color-gray-400);
text-transform: uppercase;
letter-spacing: 0.08em;
padding: var(--space-4) var(--space-5) var(--space-1);
margin-top: var(--space-2);
}
/* Nav item */
.pf-nav-item {
display: flex;
align-items: center;
gap: var(--space-3);
padding: var(--space-2) var(--space-5);
font-size: var(--text-sm);
font-weight: var(--font-medium);
color: var(--color-gray-600);
border-radius: 0;
border: none;
background: transparent;
width: 100%;
text-align: left;
cursor: pointer;
border-left: 3px solid transparent;
transition: color var(--transition-fast), background var(--transition-fast), border-color var(--transition-fast);
text-decoration: none;
}
.pf-nav-item svg { flex-shrink: 0; color: var(--color-gray-400); transition: color var(--transition-fast); }
.pf-nav-item:hover {
color: var(--color-primary);
background: var(--color-primary-bg);
text-decoration: none;
}
.pf-nav-item:hover svg { color: var(--color-primary); }
.pf-nav-item.is-active {
color: var(--color-primary);
background: var(--color-primary-bg);
border-left-color: var(--color-primary);
font-weight: var(--font-semibold);
}
.pf-nav-item.is-active svg { color: var(--color-primary); }
/* Nav badge (e.g., count) */
.pf-nav-chip {
margin-left: auto;
background: var(--color-primary-bg);
color: var(--color-primary);
font-size: var(--text-xs);
font-weight: var(--font-semibold);
padding: 1px 7px;
border-radius: var(--radius-full);
}
.pf-nav-item.is-active .pf-nav-chip {
background: var(--color-primary);
color: white;
}
/* Sidebar footer */
.pf-sidebar__footer {
border-top: 1px solid var(--color-gray-200);
padding: var(--space-4) var(--space-5);
margin-top: auto;
}
.pf-sidebar-user {
display: flex;
align-items: center;
gap: var(--space-3);
}
.pf-sidebar-user__avatar {
width: 34px;
height: 34px;
border-radius: var(--radius-full);
background: linear-gradient(135deg, var(--color-primary-light), var(--color-accent));
display: flex;
align-items: center;
justify-content: center;
font-size: var(--text-xs);
font-weight: var(--font-bold);
color: white;
flex-shrink: 0;
}
.pf-sidebar-user__info { min-width: 0; }
.pf-sidebar-user__name {
font-size: var(--text-sm);
font-weight: var(--font-semibold);
color: var(--color-gray-800);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.pf-sidebar-user__role {
font-size: var(--text-xs);
color: var(--color-gray-500);
}
/* ----------------------------------------
MAIN CONTENT
---------------------------------------- */
.pf-main {
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
}
/* Page header / breadcrumb bar */
.pf-page-header {
background: var(--color-bg);
border-bottom: 1px solid var(--color-gray-200);
padding: var(--space-5) var(--space-8);
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--space-4);
flex-wrap: wrap;
}
.pf-breadcrumb {
display: flex;
align-items: center;
gap: var(--space-2);
font-size: var(--text-sm);
color: var(--color-gray-500);
}
.pf-breadcrumb a { color: var(--color-gray-500); }
.pf-breadcrumb a:hover { color: var(--color-primary); text-decoration: none; }
.pf-breadcrumb__sep { color: var(--color-gray-300); }
.pf-breadcrumb__current { color: var(--color-gray-800); font-weight: var(--font-medium); }
.pf-page-title-block { }
.pf-page-title {
font-size: var(--text-2xl);
font-weight: var(--font-bold);
color: var(--color-gray-900);
line-height: 1.2;
margin-top: var(--space-1);
}
.pf-page-actions {
display: flex;
align-items: center;
gap: var(--space-3);
flex-shrink: 0;
}
/* Buttons */
.pf-btn {
display: inline-flex;
align-items: center;
gap: var(--space-2);
padding: 0 var(--space-5);
height: 38px;
border-radius: var(--radius-md);
font-size: var(--text-sm);
font-weight: var(--font-semibold);
border: 1.5px solid transparent;
cursor: pointer;
transition: all var(--transition-fast);
white-space: nowrap;
font-family: inherit;
text-decoration: none;
}
.pf-btn--primary {
background: var(--color-primary);
color: white;
border-color: var(--color-primary);
}
.pf-btn--primary:hover {
background: var(--color-primary-dark);
border-color: var(--color-primary-dark);
color: white;
text-decoration: none;
}
.pf-btn--secondary {
background: var(--color-bg);
color: var(--color-gray-700);
border-color: var(--color-gray-300);
}
.pf-btn--secondary:hover {
background: var(--color-gray-100);
border-color: var(--color-gray-400);
color: var(--color-gray-900);
text-decoration: none;
}
.pf-btn--ghost {
background: transparent;
color: var(--color-gray-600);
border-color: transparent;
}
.pf-btn--ghost:hover {
background: var(--color-gray-100);
color: var(--color-gray-800);
text-decoration: none;
}
.pf-btn--accent {
background: var(--color-accent);
color: var(--color-primary-dark);
border-color: var(--color-accent);
font-weight: var(--font-bold);
}
.pf-btn--accent:hover {
background: var(--color-accent-dark);
border-color: var(--color-accent-dark);
color: white;
text-decoration: none;
}
/* Content area */
.pf-content {
flex: 1;
padding: var(--space-8);
display: flex;
flex-direction: column;
gap: var(--space-6);
}
/* ----------------------------------------
REUSABLE CONTENT COMPONENTS
---------------------------------------- */
/* Stat cards row */
.pf-stats-row {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: var(--space-5);
}
.pf-stat-card {
background: var(--color-bg);
border: 1px solid var(--color-gray-200);
border-radius: var(--radius-lg);
padding: var(--space-5) var(--space-6);
box-shadow: var(--shadow-sm);
display: flex;
flex-direction: column;
gap: var(--space-2);
transition: box-shadow var(--transition-fast);
}
.pf-stat-card:hover { box-shadow: var(--shadow-md); }
.pf-stat-card__label {
font-size: var(--text-xs);
font-weight: var(--font-semibold);
color: var(--color-gray-500);
text-transform: uppercase;
letter-spacing: 0.06em;
}
.pf-stat-card__value {
font-size: var(--text-3xl);
font-weight: var(--font-bold);
color: var(--color-gray-900);
line-height: 1;
}
.pf-stat-card__delta {
font-size: var(--text-xs);
font-weight: var(--font-medium);
display: flex;
align-items: center;
gap: 3px;
}
.pf-stat-card__delta--up { color: #16a34a; }
.pf-stat-card__delta--down { color: var(--color-error); }
.pf-stat-card__icon {
width: 36px;
height: 36px;
border-radius: var(--radius-md);
display: flex;
align-items: center;
justify-content: center;
align-self: flex-end;
margin-top: calc(-1 * var(--space-8));
}
.pf-stat-card__icon--primary { background: var(--color-primary-bg); color: var(--color-primary); }
.pf-stat-card__icon--accent { background: #FFF3DC; color: var(--color-accent-dark); }
.pf-stat-card__icon--success { background: var(--color-success-bg); color: #16a34a; }
.pf-stat-card__icon--info { background: #EBF5FB; color: #2563eb; }
/* Two-column layout for panels */
.pf-grid-2 {
display: grid;
grid-template-columns: 1fr 1fr;
gap: var(--space-6);
}
.pf-grid-3-1 {
display: grid;
grid-template-columns: 3fr 1fr;
gap: var(--space-6);
}
/* Card / Panel */
.pf-card {
background: var(--color-bg);
border: 1px solid var(--color-gray-200);
border-radius: var(--radius-lg);
box-shadow: var(--shadow-sm);
overflow: hidden;
}
.pf-card__header {
display: flex;
align-items: center;
justify-content: space-between;
padding: var(--space-4) var(--space-6);
border-bottom: 1px solid var(--color-gray-200);
}
.pf-card__title {
font-size: var(--text-base);
font-weight: var(--font-semibold);
color: var(--color-gray-900);
}
.pf-card__subtitle {
font-size: var(--text-xs);
color: var(--color-gray-500);
margin-top: 2px;
}
.pf-card__body {
padding: var(--space-6);
}
.pf-card__footer {
padding: var(--space-4) var(--space-6);
border-top: 1px solid var(--color-gray-200);
background: var(--color-bg-subtle);
}
/* Table */
.pf-table-wrap { overflow-x: auto; }
.pf-table {
width: 100%;
border-collapse: collapse;
font-size: var(--text-sm);
}
.pf-table th {
text-align: left;
padding: var(--space-3) var(--space-4);
font-size: var(--text-xs);
font-weight: var(--font-semibold);
color: var(--color-gray-500);
text-transform: uppercase;
letter-spacing: 0.06em;
border-bottom: 1px solid var(--color-gray-200);
white-space: nowrap;
background: var(--color-bg-subtle);
}
.pf-table td {
padding: var(--space-4);
border-bottom: 1px solid var(--color-gray-100);
color: var(--color-gray-700);
vertical-align: middle;
}
.pf-table tr:last-child td { border-bottom: none; }
.pf-table tr:hover td { background: var(--color-gray-50); }
/* Status pill */
.pf-pill {
display: inline-flex;
align-items: center;
gap: 4px;
padding: 2px 10px;
border-radius: var(--radius-full);
font-size: var(--text-xs);
font-weight: var(--font-semibold);
}
.pf-pill::before {
content: '';
width: 6px;
height: 6px;
border-radius: 50%;
background: currentColor;
}
.pf-pill--success { background: var(--color-success-bg); color: #15803d; }
.pf-pill--warning { background: var(--color-warning-bg); color: #b45309; }
.pf-pill--error { background: var(--color-error-bg); color: #b91c1c; }
.pf-pill--info { background: #EBF5FB; color: #1d4ed8; }
.pf-pill--neutral { background: var(--color-gray-100); color: var(--color-gray-600); }
/* Sidebar overlay (mobile) */
.pf-sidebar-overlay {
display: none;
position: fixed;
inset: 0;
background: rgba(0,0,0,0.45);
z-index: 99;
backdrop-filter: blur(2px);
}
.pf-sidebar-overlay.is-visible { display: block; }
/* Alert / Banner */
.pf-alert {
display: flex;
align-items: flex-start;
gap: var(--space-3);
padding: var(--space-4) var(--space-5);
border-radius: var(--radius-md);
font-size: var(--text-sm);
border: 1px solid transparent;
}
.pf-alert svg { flex-shrink: 0; margin-top: 1px; }
.pf-alert__body { flex: 1; }
.pf-alert__title { font-weight: var(--font-semibold); margin-bottom: var(--space-1); }
.pf-alert--info { background: #EBF5FB; border-color: #BFDBFE; color: #1e40af; }
.pf-alert--success { background: var(--color-success-bg); border-color: #A7F3D0; color: #065f46; }
.pf-alert--warning { background: var(--color-warning-bg); border-color: #FDE68A; color: #92400e; }
/* Empty state */
.pf-empty {
padding: var(--space-12) var(--space-6);
text-align: center;
color: var(--color-gray-400);
}
.pf-empty__icon { font-size: 2.5rem; margin-bottom: var(--space-3); }
.pf-empty__title { font-size: var(--text-base); font-weight: var(--font-semibold); color: var(--color-gray-600); margin-bottom: var(--space-1); }
.pf-empty__desc { font-size: var(--text-sm); }
/* ----------------------------------------
FOOTER
---------------------------------------- */
.pf-footer {
background: var(--color-bg);
border-top: 1px solid var(--color-gray-200);
padding: var(--space-5) var(--space-8);
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
gap: var(--space-4);
}
.pf-footer__copy {
font-size: var(--text-xs);
color: var(--color-gray-400);
}
.pf-footer__links {
display: flex;
gap: var(--space-5);
}
.pf-footer__links a {
font-size: var(--text-xs);
color: var(--color-gray-400);
transition: color var(--transition-fast);
}
.pf-footer__links a:hover { color: var(--color-primary); text-decoration: none; }
/* ========================================
RESPONSIVE — MOBILE
breakpoint: 768px
======================================== */
@media (max-width: 768px) {
/* Show hamburger */
.pf-hamburger { display: flex; }
/* Hide search on very small */
.pf-header__search { display: none; }
/* Sidebar slides off-screen */
.pf-sidebar {
position: fixed;
top: var(--header-height);
left: 0;
bottom: 0;
height: calc(100vh - var(--header-height));
transform: translateX(-100%);
z-index: 150;
box-shadow: var(--shadow-lg);
}
.pf-sidebar.is-open {
transform: translateX(0);
}
/* Main takes full width */
.pf-body { margin-left: 0; }
/* Content padding tighter */
.pf-content { padding: var(--space-5) var(--space-4); }
.pf-page-header { padding: var(--space-4) var(--space-4); }
/* Stats — 2 columns on mobile */
.pf-stats-row { grid-template-columns: repeat(2, 1fr); gap: var(--space-3); }
/* Two-col panels stack */
.pf-grid-2, .pf-grid-3-1 { grid-template-columns: 1fr; }
/* Page title */
.pf-page-title { font-size: var(--text-xl); }
/* Footer */
.pf-footer { flex-direction: column; align-items: flex-start; padding: var(--space-4); }
}
@media (max-width: 480px) {
.pf-stats-row { grid-template-columns: 1fr; }
.pf-page-actions .pf-btn--secondary { display: none; }
}
/* ========================================
TEMPLATE ANNOTATION STYLES
(remove in production)
======================================== */
.template-note {
font-size: var(--text-xs);
font-weight: var(--font-semibold);
color: var(--color-gray-400);
text-transform: uppercase;
letter-spacing: 0.06em;
background: repeating-linear-gradient(
45deg,
rgba(245, 166, 35, 0.05),
rgba(245, 166, 35, 0.05) 5px,
transparent 5px,
transparent 15px
);
border: 1px dashed rgba(245, 166, 35, 0.4);
border-radius: var(--radius-sm);
padding: var(--space-2) var(--space-3);
margin-bottom: var(--space-3);
}
/* Chart placeholder */
.pf-chart-placeholder {
height: 200px;
background: linear-gradient(180deg, var(--color-primary-bg) 0%, transparent 100%);
border-radius: var(--radius-md);
display: flex;
align-items: flex-end;
justify-content: center;
padding-bottom: var(--space-4);
overflow: hidden;
position: relative;
}
.pf-chart-bars {
display: flex;
align-items: flex-end;
gap: 6px;
height: 160px;
padding: 0 var(--space-4);
width: 100%;
}
.pf-chart-bar {
flex: 1;
background: var(--color-primary);
border-radius: 3px 3px 0 0;
opacity: 0.7;
min-height: 8px;
transition: opacity var(--transition-fast);
}
.pf-chart-bar:hover { opacity: 1; }
.pf-chart-bar.is-accent { background: var(--color-accent); opacity: 0.85; }
</style>
</head>
<body>
<!-- ============================================
SIDEBAR OVERLAY (mobile backdrop)
============================================ -->
<div class="pf-sidebar-overlay" id="sidebarOverlay" onclick="closeSidebar()"></div>
<!-- ============================================
SHELL
============================================ -->
<div class="pf-shell">
<!-- ==========================================
HEADER
========================================== -->
<header class="pf-header">
<!-- Logo -->
<a href="#" class="pf-logo">
<div class="pf-logo__mark">PF</div>
<span class="pf-logo__name">Pay<span>frit</span></span>
</a>
<!-- Mobile hamburger (opens sidebar) -->
<button class="pf-hamburger" onclick="toggleSidebar()" aria-label="Toggle navigation">
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
<line x1="3" y1="5" x2="17" y2="5"/><line x1="3" y1="10" x2="17" y2="10"/><line x1="3" y1="15" x2="17" y2="15"/>
</svg>
</button>
<!-- Global search -->
<div class="pf-header__search">
<div class="pf-search-wrap">
<svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="9" cy="9" r="6"/><line x1="15" y1="15" x2="19" y2="19"/>
</svg>
<input class="pf-search" type="search" placeholder="Search Payfrit…" aria-label="Global search">
</div>
</div>
<!-- Actions -->
<div class="pf-header__actions">
<!-- Notifications -->
<button class="pf-icon-btn" aria-label="Notifications">
<div class="pf-badge"></div>
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M18 8a6 6 0 0 0-12 0c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 0 1-3.46 0"/>
</svg>
</button>
<!-- Help -->
<button class="pf-icon-btn" aria-label="Help">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><line x1="12" y1="17" x2="12.01" y2="17"/>
</svg>
</button>
<!-- Avatar -->
<div class="pf-avatar" role="button" aria-label="User menu">JD</div>
</div>
</header><!-- /pf-header -->
<!-- ==========================================
BODY: SIDEBAR + MAIN
========================================== -->
<div class="pf-body">
<!-- ========================================
SIDEBAR
======================================== -->
<aside class="pf-sidebar" id="sidebar" aria-label="Main navigation">
<div class="pf-sidebar__inner">
<span class="pf-nav-label">Overview</span>
<a href="#" class="pf-nav-item is-active">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/></svg>
Dashboard
</a>
<a href="#" class="pf-nav-item">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="1" x2="12" y2="23"/><path d="M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"/></svg>
Transactions
<span class="pf-nav-chip">12</span>
</a>
<a href="#" class="pf-nav-item">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 12V22H4V12"/><path d="M22 7H2v5h20V7z"/><path d="M12 22V7"/><path d="M12 7H7.5a2.5 2.5 0 0 1 0-5C11 2 12 7 12 7z"/><path d="M12 7h4.5a2.5 2.5 0 0 0 0-5C13 2 12 7 12 7z"/></svg>
Benefits
</a>
<span class="pf-nav-label">Health</span>
<a href="#" class="pf-nav-item">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"/></svg>
Wellness
</a>
<a href="#" class="pf-nav-item">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 3h18v18H3z"/><path d="M12 8v8"/><path d="M8 12h8"/></svg>
Claims
<span class="pf-nav-chip">3</span>
</a>
<a href="#" class="pf-nav-item">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/><polyline points="10 9 9 9 8 9"/></svg>
Documents
</a>
<span class="pf-nav-label">Account</span>
<a href="#" class="pf-nav-item">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
Profile
</a>
<a href="#" class="pf-nav-item">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.07 4.93a10 10 0 0 1 0 14.14"/><path d="M4.93 4.93a10 10 0 0 0 0 14.14"/></svg>
Settings
</a>
</div><!-- /pf-sidebar__inner -->
<!-- Sidebar user footer -->
<div class="pf-sidebar__footer">
<div class="pf-sidebar-user">
<div class="pf-sidebar-user__avatar">JD</div>
<div class="pf-sidebar-user__info">
<div class="pf-sidebar-user__name">Jane Doe</div>
<div class="pf-sidebar-user__role">Member · Acme Corp</div>
</div>
</div>
</div>
</aside><!-- /pf-sidebar -->
<!-- ========================================
MAIN
======================================== -->
<div class="pf-main">
<!-- Page header / breadcrumb + title -->
<div class="pf-page-header">
<div class="pf-page-title-block">
<nav class="pf-breadcrumb" aria-label="Breadcrumb">
<a href="#">Home</a>
<span class="pf-breadcrumb__sep"></span>
<span class="pf-breadcrumb__current">Dashboard</span>
</nav>
<h1 class="pf-page-title">Dashboard</h1>
</div>
<div class="pf-page-actions">
<button class="pf-btn pf-btn--secondary">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
Export
</button>
<button class="pf-btn pf-btn--primary">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
New Claim
</button>
</div>
</div><!-- /pf-page-header -->
<!-- Page content -->
<div class="pf-content">
<!-- Alert banner (dismissible) -->
<div class="pf-alert pf-alert--info" role="alert">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>
<div class="pf-alert__body">
<div class="pf-alert__title">Benefits renewal coming up</div>
Your plan renews on April 1, 2026. Review your elections before March 25 to avoid lapses.
</div>
</div>
<!-- Stat cards -->
<div class="pf-stats-row">
<div class="pf-stat-card">
<div class="pf-stat-card__label">Balance</div>
<div class="pf-stat-card__value">$1,240</div>
<div class="pf-stat-card__delta pf-stat-card__delta--up">
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="18 15 12 9 6 15"/></svg>
+$320 this month
</div>
<div class="pf-stat-card__icon pf-stat-card__icon--primary">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="1" x2="12" y2="23"/><path d="M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"/></svg>
</div>
</div>
<div class="pf-stat-card">
<div class="pf-stat-card__label">Claims This Year</div>
<div class="pf-stat-card__value">7</div>
<div class="pf-stat-card__delta pf-stat-card__delta--up">
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="18 15 12 9 6 15"/></svg>
3 approved
</div>
<div class="pf-stat-card__icon pf-stat-card__icon--accent">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>
</div>
</div>
<div class="pf-stat-card">
<div class="pf-stat-card__label">Wellness Score</div>
<div class="pf-stat-card__value">84</div>
<div class="pf-stat-card__delta pf-stat-card__delta--up">
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="18 15 12 9 6 15"/></svg>
+6 pts vs. last month
</div>
<div class="pf-stat-card__icon pf-stat-card__icon--success">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"/></svg>
</div>
</div>
<div class="pf-stat-card">
<div class="pf-stat-card__label">Plan Utilization</div>
<div class="pf-stat-card__value">62%</div>
<div class="pf-stat-card__delta pf-stat-card__delta--down">
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg>
-4% vs. avg
</div>
<div class="pf-stat-card__icon pf-stat-card__icon--info">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="20" x2="18" y2="10"/><line x1="12" y1="20" x2="12" y2="4"/><line x1="6" y1="20" x2="6" y2="14"/></svg>
</div>
</div>
</div><!-- /pf-stats-row -->
<!-- Two-column: chart + quick actions -->
<div class="pf-grid-3-1">
<!-- Chart card -->
<div class="pf-card">
<div class="pf-card__header">
<div>
<div class="pf-card__title">Spending Overview</div>
<div class="pf-card__subtitle">Last 12 months</div>
</div>
<button class="pf-btn pf-btn--ghost" style="height:32px;padding:0 12px;font-size:0.75rem;">Month ▾</button>
</div>
<div class="pf-card__body">
<div class="pf-chart-placeholder">
<div class="pf-chart-bars">
<div class="pf-chart-bar" style="height:45%"></div>
<div class="pf-chart-bar" style="height:60%"></div>
<div class="pf-chart-bar" style="height:35%"></div>
<div class="pf-chart-bar" style="height:75%"></div>
<div class="pf-chart-bar" style="height:50%"></div>
<div class="pf-chart-bar" style="height:90%"></div>
<div class="pf-chart-bar" style="height:65%"></div>
<div class="pf-chart-bar" style="height:55%"></div>
<div class="pf-chart-bar" style="height:80%"></div>
<div class="pf-chart-bar" style="height:40%"></div>
<div class="pf-chart-bar" style="height:70%"></div>
<div class="pf-chart-bar is-accent" style="height:85%"></div>
</div>
</div>
</div>
<div class="pf-card__footer" style="display:flex;gap:24px;">
<div style="font-size:0.75rem;color:var(--color-gray-500);">
<span style="display:inline-block;width:10px;height:10px;background:var(--color-primary);border-radius:2px;margin-right:5px;vertical-align:middle;"></span>
Health Spend
</div>
<div style="font-size:0.75rem;color:var(--color-gray-500);">
<span style="display:inline-block;width:10px;height:10px;background:var(--color-accent);border-radius:2px;margin-right:5px;vertical-align:middle;"></span>
Wellness Spend
</div>
</div>
</div>
<!-- Quick actions card -->
<div class="pf-card">
<div class="pf-card__header">
<div class="pf-card__title">Quick Actions</div>
</div>
<div class="pf-card__body" style="display:flex;flex-direction:column;gap:10px;">
<a href="#" class="pf-btn pf-btn--primary" style="width:100%;justify-content:center;">File a Claim</a>
<a href="#" class="pf-btn pf-btn--secondary" style="width:100%;justify-content:center;">View Benefits</a>
<a href="#" class="pf-btn pf-btn--secondary" style="width:100%;justify-content:center;">Upload Receipt</a>
<a href="#" class="pf-btn pf-btn--ghost" style="width:100%;justify-content:center;">Contact Support</a>
</div>
</div>
</div><!-- /pf-grid-3-1 -->
<!-- Two-column: recent transactions + plan summary -->
<div class="pf-grid-2">
<!-- Recent transactions table -->
<div class="pf-card">
<div class="pf-card__header">
<div>
<div class="pf-card__title">Recent Transactions</div>
<div class="pf-card__subtitle">Last 30 days</div>
</div>
<a href="#" style="font-size:0.8rem;font-weight:600;color:var(--color-primary);">View all →</a>
</div>
<div class="pf-table-wrap">
<table class="pf-table">
<thead>
<tr>
<th>Merchant</th>
<th>Date</th>
<th>Amount</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<div style="font-weight:500;color:var(--color-gray-800);">CVS Pharmacy</div>
<div style="font-size:0.75rem;color:var(--color-gray-400);">Prescription</div>
</td>
<td style="color:var(--color-gray-500);">Mar 17</td>
<td style="font-weight:600;">$42.00</td>
<td><span class="pf-pill pf-pill--success">Approved</span></td>
</tr>
<tr>
<td>
<div style="font-weight:500;color:var(--color-gray-800);">City Fitness</div>
<div style="font-size:0.75rem;color:var(--color-gray-400);">Gym membership</div>
</td>
<td style="color:var(--color-gray-500);">Mar 15</td>
<td style="font-weight:600;">$55.00</td>
<td><span class="pf-pill pf-pill--success">Approved</span></td>
</tr>
<tr>
<td>
<div style="font-weight:500;color:var(--color-gray-800);">Dr. Park, MD</div>
<div style="font-size:0.75rem;color:var(--color-gray-400);">Office visit</div>
</td>
<td style="color:var(--color-gray-500);">Mar 10</td>
<td style="font-weight:600;">$200.00</td>
<td><span class="pf-pill pf-pill--warning">Pending</span></td>
</tr>
<tr>
<td>
<div style="font-weight:500;color:var(--color-gray-800);">Whole Foods</div>
<div style="font-size:0.75rem;color:var(--color-gray-400);">Nutrition</div>
</td>
<td style="color:var(--color-gray-500);">Mar 8</td>
<td style="font-weight:600;">$78.50</td>
<td><span class="pf-pill pf-pill--error">Denied</span></td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- Plan summary card -->
<div class="pf-card">
<div class="pf-card__header">
<div>
<div class="pf-card__title">Plan Summary</div>
<div class="pf-card__subtitle">Acme Corp · 2026</div>
</div>
<span class="pf-pill pf-pill--success">Active</span>
</div>
<div class="pf-card__body" style="display:flex;flex-direction:column;gap:var(--space-5);">
<!-- FSA progress -->
<div>
<div style="display:flex;justify-content:space-between;align-items:baseline;margin-bottom:6px;">
<span style="font-size:0.8rem;font-weight:600;color:var(--color-gray-700);">FSA Balance</span>
<span style="font-size:0.8rem;color:var(--color-gray-500);">$1,240 / $2,000</span>
</div>
<div style="height:8px;background:var(--color-gray-200);border-radius:var(--radius-full);overflow:hidden;">
<div style="height:100%;width:62%;background:var(--color-primary);border-radius:var(--radius-full);"></div>
</div>
</div>
<!-- Deductible progress -->
<div>
<div style="display:flex;justify-content:space-between;align-items:baseline;margin-bottom:6px;">
<span style="font-size:0.8rem;font-weight:600;color:var(--color-gray-700);">Deductible Met</span>
<span style="font-size:0.8rem;color:var(--color-gray-500);">$850 / $1,500</span>
</div>
<div style="height:8px;background:var(--color-gray-200);border-radius:var(--radius-full);overflow:hidden;">
<div style="height:100%;width:57%;background:var(--color-accent);border-radius:var(--radius-full);"></div>
</div>
</div>
<!-- Out of pocket -->
<div>
<div style="display:flex;justify-content:space-between;align-items:baseline;margin-bottom:6px;">
<span style="font-size:0.8rem;font-weight:600;color:var(--color-gray-700);">Out-of-Pocket Max</span>
<span style="font-size:0.8rem;color:var(--color-gray-500);">$1,240 / $5,000</span>
</div>
<div style="height:8px;background:var(--color-gray-200);border-radius:var(--radius-full);overflow:hidden;">
<div style="height:100%;width:25%;background:var(--color-primary-light);border-radius:var(--radius-full);"></div>
</div>
</div>
<hr style="border:none;border-top:1px solid var(--color-gray-200);">
<div style="display:grid;grid-template-columns:1fr 1fr;gap:var(--space-4);">
<div>
<div style="font-size:0.7rem;font-weight:600;color:var(--color-gray-400);text-transform:uppercase;letter-spacing:.06em;margin-bottom:2px;">Plan Type</div>
<div style="font-size:0.875rem;font-weight:600;color:var(--color-gray-800);">HDHP + FSA</div>
</div>
<div>
<div style="font-size:0.7rem;font-weight:600;color:var(--color-gray-400);text-transform:uppercase;letter-spacing:.06em;margin-bottom:2px;">Renews</div>
<div style="font-size:0.875rem;font-weight:600;color:var(--color-gray-800);">Apr 1, 2026</div>
</div>
<div>
<div style="font-size:0.7rem;font-weight:600;color:var(--color-gray-400);text-transform:uppercase;letter-spacing:.06em;margin-bottom:2px;">Network</div>
<div style="font-size:0.875rem;font-weight:600;color:var(--color-gray-800);">Blue Shield PPO</div>
</div>
<div>
<div style="font-size:0.7rem;font-weight:600;color:var(--color-gray-400);text-transform:uppercase;letter-spacing:.06em;margin-bottom:2px;">Members</div>
<div style="font-size:0.875rem;font-weight:600;color:var(--color-gray-800);">You + Spouse</div>
</div>
</div>
</div>
<div class="pf-card__footer">
<a href="#" class="pf-btn pf-btn--ghost" style="font-size:0.8rem;height:30px;padding:0 10px;">View Full Plan Details →</a>
</div>
</div>
</div><!-- /pf-grid-2 -->
</div><!-- /pf-content -->
<!-- ========================================
FOOTER
======================================== -->
<footer class="pf-footer">
<div class="pf-footer__copy">© 2026 Payfrit, Inc. All rights reserved.</div>
<nav class="pf-footer__links" aria-label="Footer links">
<a href="#">Privacy Policy</a>
<a href="#">Terms of Use</a>
<a href="#">HIPAA Notice</a>
<a href="#">Help Center</a>
</nav>
</footer>
</div><!-- /pf-main -->
</div><!-- /pf-body -->
</div><!-- /pf-shell -->
<script>
/* Sidebar toggle for mobile */
function toggleSidebar() {
const sidebar = document.getElementById('sidebar');
const overlay = document.getElementById('sidebarOverlay');
sidebar.classList.toggle('is-open');
overlay.classList.toggle('is-visible');
document.body.style.overflow = sidebar.classList.contains('is-open') ? 'hidden' : '';
}
function closeSidebar() {
const sidebar = document.getElementById('sidebar');
const overlay = document.getElementById('sidebarOverlay');
sidebar.classList.remove('is-open');
overlay.classList.remove('is-visible');
document.body.style.overflow = '';
}
/* Close sidebar on nav item click (mobile) */
document.querySelectorAll('.pf-nav-item').forEach(function(item) {
item.addEventListener('click', function() {
if (window.innerWidth <= 768) closeSidebar();
});
});
/* Close on escape key */
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape') closeSidebar();
});
</script>
</body>
</html>