Skip to content

Kody is live

Watch the launch video — what Kody is, and why it exists.

← Public packages

@kentcdodds/package-app-kit

Design tokens, PWA install/update, About/version, cache helpers, and optional realtime notes sync for Kody package apps.

public/styles.css

374 lines · 12.4 KB · CSS
/* package-app-kit Remix starter tokens + layout (static copy; no Vite) */
:root {
  color-scheme: light dark;
  --pak-bg0: #fafafa;
  --pak-bg1: #f4f4f5;
  --pak-surface: #ffffff;
  --pak-surface-2: #f4f4f5;
  --pak-ink: #18181b;
  --pak-muted: #71717a;
  --pak-line: rgba(24, 24, 27, 0.12);
  --pak-accent: #0891b2;
  --pak-accent-2: #06b6d4;
  --pak-accent-ink: #ffffff;
  --pak-stripe-cyan: #06b6d4;
  --pak-stripe-green: #16a34a;
  --pak-stripe-yellow: #ca8a04;
  --pak-stripe-magenta: #db2777;
  --pak-stripe-red: #dc2626;
  --pak-good: #16a34a;
  --pak-warn: #ca8a04;
  --pak-bad: #dc2626;
  --pak-radius: 12px;
  --pak-radius-sm: 10px;
  --pak-tap: 48px;
  --pak-gap: 12px;
  --pak-space-1: 4px;
  --pak-space-2: 8px;
  --pak-space-3: 12px;
  --pak-space-4: 16px;
  --pak-space-5: 24px;
  --pak-space-6: 32px;
  --pak-space-7: 48px;
  --pak-space-8: 64px;
  --bg0: var(--pak-bg0);
  --bg1: var(--pak-bg1);
  --surface: var(--pak-surface);
  --surface-2: var(--pak-surface-2);
  --ink: var(--pak-ink);
  --muted: var(--pak-muted);
  --line: var(--pak-line);
  --accent: var(--pak-accent);
  --accent-2: var(--pak-accent-2);
  --accent-ink: var(--pak-accent-ink);
  --good: var(--pak-good);
  --warn: var(--pak-warn);
  --bad: var(--pak-bad);
  --radius: var(--pak-radius);
  --radius-sm: var(--pak-radius-sm);
  --tap: var(--pak-tap);
  --gap: var(--pak-gap);
  --space-1: var(--pak-space-1);
  --space-2: var(--pak-space-2);
  --space-3: var(--pak-space-3);
  --space-4: var(--pak-space-4);
  --space-5: var(--pak-space-5);
  --space-6: var(--pak-space-6);
  --space-7: var(--pak-space-7);
  --space-8: var(--pak-space-8);
}
@media (prefers-color-scheme: dark) {
  :root {
    --pak-bg0: #0a0a0a;
    --pak-bg1: #121212;
    --pak-surface: #161616;
    --pak-surface-2: #1c1c1c;
    --pak-ink: #f5f5f5;
    --pak-muted: #a3a3a3;
    --pak-line: rgba(245, 245, 245, 0.12);
    --pak-accent: #3bffff;
    --pak-accent-2: #22d3ee;
    --pak-accent-ink: #0a0a0a;
    --pak-stripe-cyan: #3bffff;
    --pak-stripe-green: #00e887;
    --pak-stripe-yellow: #ffe600;
    --pak-stripe-magenta: #ff2bd6;
    --pak-stripe-red: #ff2a2a;
    --pak-good: #00e887;
    --pak-warn: #ffe600;
    --pak-bad: #ff2a2a;
  }
}
* { box-sizing: border-box; }
html, body { margin: 0; min-height: 100%; }
body {
  font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
  background: linear-gradient(160deg, var(--bg0), var(--bg1));
  color: var(--ink);
  line-height: 1.45;
}
a { color: var(--accent-2); }
code { font-size: 0.9em; }
.pak-wrap { max-width: 42rem; margin: 0 auto; padding: var(--space-5) var(--space-5) var(--space-8); }
.pak-stack { display: flex; flex-direction: column; gap: var(--space-5); }
.pak-stack-sm { display: flex; flex-direction: column; gap: var(--space-2); }
.pak-cluster { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; }
.pak-row { display: flex; flex-wrap: wrap; gap: var(--space-3); align-items: end; }
.pak-inset { padding: var(--space-4); }
.pak-mt-1 { margin-top: var(--space-1); }
.pak-mt-2 { margin-top: var(--space-2); }
.pak-gap-2 { gap: var(--space-2); }
.pak-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: var(--space-5);
}
.pak-eyebrow { margin: 0; font-size: 0.75rem; letter-spacing: 0.04em; text-transform: uppercase; color: var(--muted); }
.pak-muted { color: var(--muted); margin: 0; }
.pak-nav { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: 0; }
.pak-btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: var(--tap); padding: 0 var(--space-4);
  border-radius: var(--radius-sm); border: 1px solid var(--line);
  background: var(--surface-2); color: var(--ink); font: inherit; text-decoration: none; cursor: pointer;
}
.pak-btn[aria-current="page"] { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.pak-btn-accent { background: var(--accent); border-color: transparent; color: var(--accent-ink); }
.pak-btn-danger { background: transparent; border-color: var(--bad); color: var(--bad); }
.pak-btn-danger[data-armed="true"] { background: var(--bad); color: #fff; }
.pak-btn:disabled { opacity: 0.55; cursor: not-allowed; }
.pak-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-2); }
.pak-list-item {
  display: flex; justify-content: space-between; gap: var(--space-3); align-items: center;
  padding: var(--space-3); border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--surface-2);
}

.pak-list-item[data-pending="true"] {
  opacity: 0.62;
  border-style: dashed;
}
.pak-list-item[data-pending="true"] .pak-pending-label {
  display: inline;
  color: var(--muted);
  font-size: 0.8rem;
  font-weight: 650;
}
.pak-pending-label { display: none; }
.pak-input {
  display: block; width: 100%; min-height: var(--tap); margin-top: var(--space-1);
  padding: 0 var(--space-3); border: 1px solid var(--line); border-radius: var(--radius-sm);
  font: inherit; background: var(--surface); color: var(--ink);
}
.pak-swatches { display: flex; flex-wrap: wrap; gap: var(--space-3); }
.pak-swatch { display: inline-block; width: 1.25rem; height: 1.25rem; border-radius: 999px; border: 1px solid var(--line); vertical-align: middle; margin-right: var(--space-1); }
.pak-swatch-label { display: inline-flex; align-items: center; font-size: 0.85rem; color: var(--muted); }
.pak-toast-host {
  position: fixed; right: var(--space-4); bottom: var(--space-4); z-index: 40;
  display: flex; flex-direction: column; gap: var(--space-2); max-width: min(22rem, calc(100vw - 2rem));
}
.pak-toast {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  padding: var(--space-3); box-shadow: 0 8px 24px rgba(0,0,0,0.12);
}
.pak-toast[data-tone="success"] { border-color: var(--good); }
.pak-toast[data-tone="error"] { border-color: var(--bad); }
.pak-toast-actions { display: flex; gap: var(--space-2); margin-top: var(--space-2); }
[hidden] { display: none !important; }

/* Hide install / first-run chrome when already installed (CSS before JS hydrates). */
@media (display-mode: standalone), (display-mode: fullscreen), (display-mode: minimal-ui) {
  [data-install-wrap], [data-install-hint], [data-first-run-splash],
  .pak-splash-overlay, .pak-install-hint-overlay { display: none !important; }
}

.visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}
.pak-header { display: flex; flex-direction: column; gap: var(--space-4); }
.pak-brand { display: flex; align-items: center; gap: var(--space-3); min-height: var(--tap); }
.pak-logo {
  width: 28px; height: 28px; border-radius: 8px; flex: 0 0 auto;
  border: 1px solid var(--line); background: transparent; object-fit: cover;
}
.pak-title { margin: 0; font-size: clamp(1.2rem, 2.5vw, 1.55rem); line-height: 1.2; flex: 1 1 auto; min-width: 0; }
.pak-lede { margin: 0; }
.pak-grow { display: block; }
/* Mobile-friendly tips: hover + keyboard/tap focus (no hover-only). */
[data-tip] { position: relative; }
[data-tip]::after {
  content: attr(data-tip);
  position: absolute; left: 50%; bottom: calc(100% + 8px); transform: translateX(-50%);
  z-index: 30; max-width: min(16rem, 70vw); padding: 0.4rem 0.55rem;
  border-radius: 8px; border: 1px solid var(--line); background: var(--ink); color: var(--surface);
  font-size: 0.75rem; line-height: 1.3; white-space: normal; text-align: center;
  opacity: 0; pointer-events: none; transition: opacity 0.12s ease;
}
[data-tip]:hover::after,
[data-tip]:focus::after,
[data-tip]:focus-within::after,
[data-tip]:focus-visible::after { opacity: 1; }


.pak-pill {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 1.5rem; padding: 0 0.45rem; margin-left: var(--space-2);
  border-radius: 999px; font-size: 0.8rem; font-weight: 650;
  background: color-mix(in srgb, var(--accent-ink) 18%, transparent);
  color: inherit;
}
.pak-btn-icon {
  width: var(--tap); min-width: var(--tap); padding: 0;
  flex: 0 0 auto;
}
.pak-install-root { display: contents; }
.pak-install-slot {
  width: var(--tap); height: var(--tap);
  flex: 0 0 auto;
  margin-left: auto;
  display: inline-flex; align-items: center; justify-content: center;
}
/* Reserve space always; hide control without collapsing the slot (no CLS). */
.pak-install-slot[data-available="false"] .pak-btn-icon {
  visibility: hidden;
  pointer-events: none;
}
.pak-splash-overlay,
.pak-install-hint-overlay {
  position: fixed;
  z-index: 70;
  left: 50%;
  top: calc(12px + env(safe-area-inset-top, 0px));
  transform: translateX(-50%);
  width: min(420px, calc(100% - 24px));
  pointer-events: none;
}
.pak-splash-card,
.pak-install-hint-card {
  pointer-events: auto;
  box-shadow: 0 10px 28px rgba(0,0,0,0.18);
}
.pak-install-hint-overlay {
  top: auto;
  bottom: calc(16px + env(safe-area-inset-bottom, 0px));
}
/* Author CSS must not defeat the HTML hidden attribute (display:grid/flex overlays). */
.pak-splash-overlay[hidden],
.pak-install-hint-overlay[hidden],
[data-install-hint][hidden],
[data-first-run-splash][hidden] {
  display: none !important;
}

/* Update toast: fixed overlay — never participates in document flow (no CLS). */
.pak-update-toast {
  position: fixed;
  z-index: 80;
  left: 50%;
  bottom: calc(16px + env(safe-area-inset-bottom, 0px));
  transform: translateX(-50%);
  width: min(420px, calc(100% - 24px));
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--space-2) var(--space-3);
  align-items: center;
  margin: 0;
  pointer-events: auto;
  box-shadow: 0 10px 28px rgba(0,0,0,0.18);
}
.pak-update-toast .pak-toast-actions { margin-top: 0; flex-wrap: wrap; justify-content: flex-end; }
.pak-update-toast p { margin: 2px 0 0; }

/* Immediate press feedback without CLS — opacity/cursor only, no size change. */
.pak-btn[data-pending="true"],
.pak-btn[aria-busy="true"] {
  opacity: 0.72;
  cursor: progress;
}

/* Error alert — reserved in-flow slot; size stays stable (no late expansion tricks). */
.pak-error {
  border: 1px solid color-mix(in srgb, var(--bad) 45%, var(--line));
  background: color-mix(in srgb, var(--bad) 8%, var(--surface));
  border-radius: var(--radius);
  padding: var(--space-3) var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}
.pak-error-title { font-size: 0.95rem; color: var(--bad); }
.pak-error-message { margin: 0; }
.pak-error-hint { margin: 0; font-size: 0.85rem; }

/* Home: soft cyan glow behind header+nav+hero (no hard cut under nav pills). */
.pak-wrap:has(.pak-hero) {
  position: relative;
  isolation: isolate;
}
.pak-wrap:has(.pak-hero)::before {
  content: "";
  position: absolute;
  pointer-events: none;
  z-index: 0;
  left: 50%;
  top: 0;
  transform: translateX(-50%);
  width: min(40rem, 150%);
  height: min(30rem, 75vh);
  background: radial-gradient(
    ellipse 85% 70% at 50% 42%,
    color-mix(in srgb, var(--pak-stripe-cyan) 18%, transparent),
    color-mix(in srgb, var(--pak-stripe-cyan) 8%, transparent) 42%,
    transparent 68%
  );
}
.pak-wrap:has(.pak-hero) > * {
  position: relative;
  z-index: 1;
}

.pak-hero {
  display: grid;
  justify-items: center;
  gap: var(--space-3);
  text-align: center;
  padding: var(--space-5) var(--space-4);
  background: transparent;
  border: none;
  border-radius: var(--radius);
}
.pak-hero-logo {
  width: min(220px, 55vw);
  height: auto;
  display: block;
  background: transparent;
}
.pak-swatches-stripes { margin-top: var(--space-2); }

/* Home kit showcase — spacing rulers + labeled demo boxes */
.pak-space-rulers {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.pak-space-ruler {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: var(--space-4);
}
.pak-space-ruler-label {
  flex: 0 0 4.5rem;
  font-size: 0.75rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.pak-space-ruler-bar {
  display: block;
  height: var(--space-3);
  border-radius: 4px;
  background: color-mix(in srgb, var(--accent) 55%, var(--surface-2));
  border: 1px solid var(--line);
  min-width: 2px;
}
.pak-demo-box {
  flex: 1 1 8rem;
  min-width: 7rem;
  border: 1px dashed var(--line);
  border-radius: var(--radius-sm);
  padding: var(--space-3);
  background: var(--surface);
}
.pak-demo-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.75rem;
  min-height: 1.75rem;
  padding: 0 var(--space-2);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  border: 1px solid var(--line);
  font-size: 0.85rem;
}