---
description: Use this skill when generating any standalone HTML page — dashboards, reports, landing pages, status pages, data displays, forms, or any web content. Provides a default CSS design system with light theme, responsive layout, badges, and mobile-first card fallback.
---

# Web Page Style Guide

When creating any standalone HTML page (dashboards, reports, landing pages, status pages, data displays, forms, portfolios, etc.), follow this design system for a clean, professional look with built-in mobile responsiveness.

## Design Principles

- **Light background** (`#faf9f7` warm off-white), white containers
- **Table-based layout** for data on desktop, card-based on mobile
- **Monospace numbers** using `'SF Mono', Menlo, monospace`
- **Warm accent color** (`#e8654a` coral/orange) for active states
- **Colored badges** for categorical data (green/red/yellow/blue/gray)
- **Skeleton loading** animations while data fetches
- **No external CSS dependencies** — pure inline `<style>` block

## HTML Structure

```html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Dashboard Title</title>
  <style>
    /* Paste the CSS from the "Base CSS" section below */
  </style>
</head>
<body>
  <!-- 1. Top Bar: title, tabs, actions -->
  <div class="topbar">
    <div class="topbar-title">Dashboard Title</div>
    <button class="tab active" onclick="switchTab('tab1')">Tab 1</button>
    <button class="tab" onclick="switchTab('tab2')">Tab 2</button>
    <div class="topbar-right">
      <button class="refresh-btn" onclick="refresh()">Refresh</button>
    </div>
  </div>

  <!-- 2. Summary Strip: key metrics -->
  <div class="summary-strip" id="summary">
    <div class="summary-item">
      <div class="summary-label">Metric</div>
      <div class="summary-value">123</div>
      <div class="summary-sub">detail</div>
    </div>
    <!-- more items... -->
  </div>

  <!-- 3. Filter Bar -->
  <div class="filter-bar">
    <button class="filter-btn active" onclick="filter('all', this)">All</button>
    <button class="filter-btn" onclick="filter('catA', this)">Category A</button>
    <span class="count-label" id="count">-- items</span>
  </div>

  <!-- 4. Desktop Table -->
  <div class="table-wrap">
    <table>
      <thead><tr><th>Column</th><!-- ... --></tr></thead>
      <tbody id="table-body"></tbody>
    </table>
  </div>

  <!-- 5. Mobile Cards (hidden on desktop, shown on mobile) -->
  <div class="mobile-cards" id="cards"></div>

  <!-- 6. Footer -->
  <div class="footer" id="last-updated"></div>
</body>
</html>
```

## Base CSS

```css
* { margin:0; padding:0; box-sizing:border-box; }
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background:#faf9f7; color:#1a1a1a; }
a { color:inherit; text-decoration:none; }
a:hover { color:#e8654a; }

/* Top bar */
.topbar { display:flex; align-items:center; gap:24px; padding:16px 32px; background:#fff; border-bottom:1px solid #e8e5e1; }
.topbar-title { font-size:18px; font-weight:700; color:#1a1a1a; white-space:nowrap; }
.tab { padding:6px 16px; border-radius:6px; font-size:13px; font-weight:600; cursor:pointer; border:none; background:transparent; color:#888; transition:all .2s; }
.tab.active { background:#e8654a; color:#fff; }
.tab:hover:not(.active) { color:#1a1a1a; background:#f0eeeb; }
.topbar-right { margin-left:auto; display:flex; align-items:center; gap:16px; font-size:13px; color:#888; }
.refresh-btn { padding:6px 14px; border-radius:6px; font-size:12px; font-weight:600; cursor:pointer; border:1px solid #ddd; background:#fff; color:#666; transition:all .2s; }
.refresh-btn:hover { background:#f0eeeb; border-color:#ccc; }

/* Summary strip */
.summary-strip { display:flex; gap:0; padding:0 32px; background:#fff; border-bottom:1px solid #e8e5e1; }
.summary-item { padding:14px 24px; border-right:1px solid #e8e5e1; }
.summary-item:last-child { border-right:none; }
.summary-label { font-size:10px; font-weight:700; text-transform:uppercase; letter-spacing:1.2px; color:#999; margin-bottom:4px; }
.summary-value { font-size:20px; font-weight:700; font-family:'SF Mono',Menlo,monospace; }
.summary-sub { font-size:11px; margin-top:2px; }

/* Filter bar */
.filter-bar { display:flex; align-items:center; gap:12px; padding:12px 32px; background:#fff; border-bottom:1px solid #e8e5e1; }
.filter-btn { padding:4px 14px; border-radius:4px; font-size:12px; font-weight:600; cursor:pointer; border:1px solid #ddd; background:#fff; color:#666; }
.filter-btn.active { background:#1a1a1a; color:#fff; border-color:#1a1a1a; }
.count-label { margin-left:auto; font-size:13px; color:#888; font-family:'SF Mono',Menlo,monospace; }

/* Table */
.table-wrap { padding:0 32px; }
table { width:100%; border-collapse:collapse; font-size:13px; }
thead th { text-align:left; padding:10px 12px; font-size:10px; font-weight:700; text-transform:uppercase; letter-spacing:1px; color:#999; border-bottom:2px solid #e8e5e1; white-space:nowrap; }
tbody tr { border-bottom:1px solid #f0eeeb; transition:background .15s; }
tbody tr:hover { background:#f7f5f2; }
tbody td { padding:12px; vertical-align:middle; }
.td-right { text-align:right; }
.td-center { text-align:center; }
.mono { font-family:'SF Mono',Menlo,monospace; }

/* Badges */
.badge { display:inline-block; padding:2px 10px; border-radius:4px; font-size:11px; font-weight:700; }
.badge-green  { background:#dcfce7; color:#15803d; }
.badge-red    { background:#fde8e8; color:#b91c1c; }
.badge-yellow { background:#fef3c7; color:#a16207; }
.badge-blue   { background:#dbeafe; color:#1d4ed8; }
.badge-gray   { background:#f0eeeb; color:#888; }

/* Semantic color helpers */
.text-pos { color:#15803d; }
.text-neg { color:#dc2626; }

/* Icon + title in table cell */
.cell-with-icon { display:flex; align-items:center; gap:10px; }
.cell-icon { width:28px; height:28px; border-radius:6px; object-fit:cover; flex-shrink:0; }
.cell-icon-placeholder { width:28px; height:28px; border-radius:6px; background:#f0eeeb; flex-shrink:0; display:flex; align-items:center; justify-content:center; font-size:12px; color:#999; }
.cell-title { font-weight:600; font-size:13px; max-width:320px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.cell-title:hover { color:#e8654a; }

/* Small colored pill (e.g. days remaining, status) */
.pill { font-size:10px; padding:2px 6px; border-radius:3px; font-weight:600; white-space:nowrap; }
.pill-red    { background:#fde8e8; color:#dc2626; }
.pill-yellow { background:#fef3c7; color:#a16207; }
.pill-gray   { background:#f0eeeb; color:#888; }

/* Footer */
.footer { text-align:center; padding:20px; font-size:11px; color:#ccc; }

/* Loading skeleton */
.skeleton { background:linear-gradient(90deg, #f0eeeb 25%, #e8e5e1 50%, #f0eeeb 75%); background-size:200% 100%; animation:shimmer 1.5s infinite; border-radius:4px; }
@keyframes shimmer { 0%{background-position:200% 0} 100%{background-position:-200% 0} }

/* ─── Mobile Cards ─── */
.mobile-cards { display:none; padding:8px 16px; }
.m-card { background:#fff; border:1px solid #e8e5e1; border-radius:10px; padding:14px; margin-bottom:10px; }
.m-card-head { display:flex; align-items:flex-start; gap:10px; margin-bottom:10px; }
.m-card-title { font-weight:600; font-size:13px; color:#1a1a1a; flex:1; line-height:1.4; }
.m-card-title:hover { color:#e8654a; }
.m-card-badges { display:flex; gap:6px; flex-shrink:0; }
.m-card-grid { display:grid; grid-template-columns:1fr 1fr 1fr; gap:8px; }
.m-card-label { font-size:10px; font-weight:600; text-transform:uppercase; letter-spacing:0.8px; color:#999; margin-bottom:2px; }
.m-card-val { font-size:13px; font-weight:700; font-family:'SF Mono',Menlo,monospace; }
.m-card-footer { display:flex; align-items:center; justify-content:space-between; margin-top:10px; padding-top:8px; border-top:1px solid #f0eeeb; }

/* ─── Responsive Breakpoint ─── */
@media (max-width: 768px) {
  .topbar { padding:12px 16px; gap:12px; flex-wrap:wrap; }
  .topbar-title { font-size:15px; }
  .summary-strip { padding:0 16px; flex-wrap:wrap; }
  .summary-item { padding:10px 14px; flex:1; min-width:45%; }
  .summary-value { font-size:16px; }
  .filter-bar { padding:10px 16px; }
  .table-wrap { display:none; }
  .mobile-cards { display:block; }
}
```

## JavaScript Patterns

### Tab Switching

```javascript
function switchTab(tab) {
  document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
  document.getElementById('tab-' + tab).classList.add('active');
  // Show/hide sections
  document.querySelectorAll('[data-tab]').forEach(s => {
    s.style.display = s.dataset.tab === tab ? '' : 'none';
  });
}
```

### Filter Buttons

```javascript
let currentFilter = 'all';
function filter(value, btn) {
  currentFilter = value;
  document.querySelectorAll('.filter-btn').forEach(b => b.classList.remove('active'));
  btn.classList.add('active');
  renderData(allData);
}
```

### Render Table + Mobile Cards Together

Always render both desktop table rows and mobile cards in the same function:

```javascript
function renderData(items) {
  const filtered = currentFilter === 'all' ? items
    : items.filter(i => i.category === currentFilter);

  document.getElementById('count').textContent = filtered.length + ' items';

  // Desktop table
  document.getElementById('table-body').innerHTML = filtered.map(item => {
    return '<tr>' +
      '<td>' + item.name + '</td>' +
      '<td class="td-right mono">' + item.value + '</td>' +
      '</tr>';
  }).join('');

  // Mobile cards
  document.getElementById('cards').innerHTML = filtered.map(item => {
    return '<div class="m-card">' +
      '<div class="m-card-head"><div class="m-card-title">' + item.name + '</div></div>' +
      '<div class="m-card-grid">' +
        '<div><div class="m-card-label">Value</div><div class="m-card-val">' + item.value + '</div></div>' +
      '</div>' +
    '</div>';
  }).join('');
}
```

### Skeleton Loading Placeholders

Use skeleton elements in the initial HTML that get replaced when data loads:

```html
<div class="summary-item">
  <div class="skeleton" style="width:60px;height:12px;margin-bottom:6px"></div>
  <div class="skeleton" style="width:80px;height:24px"></div>
</div>
```

### Auto-Refresh

```javascript
loadData();
setInterval(loadData, 60000); // refresh every 60s
```

## Color Reference

| Token | Value | Use |
|-------|-------|-----|
| Background | `#faf9f7` | Page background |
| Surface | `#fff` | Cards, topbar, strips |
| Border | `#e8e5e1` | Dividers, card borders |
| Border light | `#f0eeeb` | Table row borders, subtle dividers |
| Hover | `#f7f5f2` | Table row hover |
| Text primary | `#1a1a1a` | Headings, body |
| Text secondary | `#888` | Labels, muted text |
| Text tertiary | `#999` | Uppercase labels |
| Text muted | `#ccc` | Footer |
| Accent | `#e8654a` | Active tabs, link hover |
| Positive | `#15803d` | Profit, success, green badge text |
| Positive bg | `#dcfce7` | Green badge background |
| Negative | `#dc2626` | Loss, error, red badge text |
| Negative bg | `#fde8e8` | Red badge background |
| Warning | `#a16207` | Caution, yellow badge text |
| Warning bg | `#fef3c7` | Yellow badge background |
| Info | `#1d4ed8` | Blue badge text |
| Info bg | `#dbeafe` | Blue badge background |
| Filter active | `#1a1a1a` bg, `#fff` text | Active filter button |
