← Public packages
@kentcdodds/package-app-kit
Design tokens, PWA install/update, About/version, cache helpers, and optional realtime notes sync for Kody package apps.
starter-remix/public/styles.css
301 lines · 10.8 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; }
.pak-hero {
display: grid;
justify-items: center;
gap: var(--space-3);
text-align: center;
padding: var(--space-5) var(--space-4);
background:
radial-gradient(ellipse at 50% 0%, color-mix(in srgb, var(--pak-stripe-cyan) 18%, transparent), transparent 55%);
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); }