Source
This app’s code and revision history are public. Download a copy or explore the files below.
Public
The app’s code and revision history are public.
Run it yourself
Take the whole tree and run it on your own machine. The download needs no account. Cloning needs a sign-in.
Download .zip
bounded clone a8c677472ab5691741798a3d
A copy you download is not bounded. The guarantees this app runs under - declared egress, proven invariants, writes that fail closed - live in the runtime serving this page, not in the files. What you get is auditable source you can read and run, with no runtime guarantees attached.
public/kit.css
/* OpenApps free apps: one look across the store and every app.
Same tokens as openapps.xyz: warm paper, Newsreader headlines, Archivo for everything else,
one solid ink button, cobalt for links and focus. */
@font-face {
font-family: "Archivo Variable";
font-style: normal;
font-weight: 100 900;
font-display: swap;
src: url(/fonts/ArchivoVariable-var.woff2) format("woff2-variations");
}
@font-face {
font-family: "Newsreader Variable";
font-style: normal;
font-weight: 200 800;
font-display: swap;
src: url(/fonts/NewsreaderVariable-var.woff2) format("woff2-variations");
}
:root {
--ink: #15171b;
--ink-solid: #0b0b0c;
--muted: #5d6169;
--faint: #8a8e96;
--line: #e3e6ea;
--line-strong: #cfd5dd;
--paper: #fdfdfc;
--paper-warm: #f8f3ea;
--paper-deep: #f1e9da;
--panel: #f0f3f8;
--panel-line: #dfe5ee;
--cobalt: #2e5ec4;
--cobalt-ink: #1f4597;
--cobalt-wash: #e9effa;
--sage: #4f7a5c;
--sage-wash: #e8f1ea;
--brick: #a8442c;
--brick-wash: #f8e9e4;
--gold: #b8892c;
--serif: "Newsreader Variable", Georgia, "Times New Roman", serif;
--sans: "Archivo Variable", system-ui, -apple-system, "Segoe UI", sans-serif;
--mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
--radius: 10px;
--radius-lg: 18px;
--shadow: 0 1px 2px #1a1d2410, 0 8px 24px -12px #1a1d2426;
--page: min(1180px, calc(100% - 48px));
color-scheme: light;
}
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
body {
margin: 0;
background: var(--paper);
color: var(--ink);
font: 400 16px/1.6 var(--sans);
-webkit-font-smoothing: antialiased;
}
img, svg, video, canvas { display: block; max-width: 100%; }
a { color: var(--cobalt); text-decoration: none; }
a:hover { color: var(--cobalt-ink); }
:is(a, button, input, select, textarea, summary):focus-visible { outline: 2px solid var(--cobalt); outline-offset: 3px; }
h1, h2, h3, h4, p, ul, ol, figure, blockquote { margin: 0; }
button, input, select, textarea { font: inherit; color: inherit; }
::selection { background: #cddcf6; }
.wrap { width: var(--page); margin-inline: auto; }
.serif { font-family: var(--serif); }
.muted { color: var(--muted); }
.eyebrow { font: 650 11.5px/1 var(--sans); letter-spacing: .14em; text-transform: uppercase; color: var(--muted); }
.display { font: 330 clamp(40px, 5.6vw, 72px)/1.04 var(--serif); letter-spacing: -.035em; text-wrap: balance; }
.h1 { font: 350 clamp(34px, 4.2vw, 54px)/1.06 var(--serif); letter-spacing: -.03em; text-wrap: balance; }
.h2 { font: 360 clamp(28px, 3vw, 40px)/1.1 var(--serif); letter-spacing: -.028em; text-wrap: balance; }
.h3 { font: 600 19px/1.3 var(--sans); letter-spacing: -.012em; }
.lede { font-size: clamp(17px, 1.5vw, 19.5px); line-height: 1.6; color: #4a4e56; max-width: 60ch; }
/* Header */
.site-head { position: sticky; top: 0; z-index: 20; background: #fdfdfcee; -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px); border-bottom: 1px solid #0000; transition: border-color .2s; }
.site-head.scrolled { border-bottom-color: var(--line); }
.site-head .wrap { display: flex; align-items: center; gap: 22px; min-height: 64px; }
.brand { display: inline-flex; align-items: center; gap: 10px; color: var(--ink-solid); font: 650 16px/1 var(--sans); letter-spacing: -.02em; }
.brand:hover { color: var(--ink-solid); }
.brand img { width: 26px; height: 26px; }
.brand .brand-app { color: var(--muted); font-weight: 500; }
.brand .brand-sep { color: var(--line-strong); font-weight: 300; }
.site-nav { display: flex; align-items: center; gap: 4px; margin-left: auto; }
.site-nav a { display: inline-flex; align-items: center; min-height: 40px; padding: 0 12px; border-radius: 8px; color: #33363c; font: 600 14.5px/1 var(--sans); }
.site-nav a:hover { color: var(--ink-solid); background: #0000000a; }
.site-nav a[aria-current="page"] { color: var(--ink-solid); }
@media (max-width: 720px) {
.site-nav .nav-optional { display: none; }
.site-head .wrap { gap: 10px; }
}
/* Buttons */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; min-height: 46px; padding: 0 20px; border: 1px solid var(--ink-solid); border-radius: var(--radius); background: var(--ink-solid); color: #fff; font: 600 14.5px/1 var(--sans); cursor: pointer; transition: background .15s, transform .15s, box-shadow .15s; white-space: nowrap; text-decoration: none; }
.btn:hover { background: #2a2c31; color: #fff; }
.btn:active { transform: translateY(1px); }
.btn:disabled, .btn[aria-disabled="true"] { opacity: .45; cursor: not-allowed; }
.btn-line { background: transparent; color: var(--ink-solid); border-color: var(--line-strong); }
.btn-line:hover { background: #00000008; color: var(--ink-solid); border-color: #b5bdc8; }
.btn-quiet { background: transparent; color: var(--ink); border-color: transparent; }
.btn-quiet:hover { background: #0000000a; color: var(--ink-solid); }
.btn-sm { min-height: 36px; padding: 0 14px; font-size: 14px; border-radius: 8px; }
.btn-lg { min-height: 54px; padding: 0 26px; font-size: 15.5px; }
.btn-danger { color: var(--brick); }
.btn-block { width: 100%; }
/* Fields */
.field { display: grid; gap: 7px; }
.field > span, .label { font: 600 13.5px/1.2 var(--sans); color: #33363c; }
.field small, .hint { font-size: 13px; color: var(--muted); }
.input, .select, .textarea { width: 100%; min-height: 46px; padding: 11px 13px; border: 1px solid var(--line-strong); border-radius: var(--radius); background: #fff; color: var(--ink); font: 400 15.5px/1.35 var(--sans); transition: border-color .15s, box-shadow .15s; }
.textarea { min-height: 96px; resize: vertical; line-height: 1.5; }
.input:hover, .select:hover, .textarea:hover { border-color: #b5bdc8; }
.input:focus, .select:focus, .textarea:focus { outline: none; border-color: var(--cobalt); box-shadow: 0 0 0 3px #2e5ec41f; }
.input::placeholder, .textarea::placeholder { color: #9a9ea6; }
.check { display: inline-flex; align-items: center; gap: 9px; font-size: 15px; cursor: pointer; }
.check input { width: 18px; height: 18px; accent-color: var(--ink-solid); }
/* Surfaces */
.card { background: #fff; border: 1px solid var(--line); border-radius: var(--radius-lg); box-shadow: var(--shadow); }
.panel { background: var(--panel); border: 1px solid var(--panel-line); border-radius: var(--radius-lg); }
.paper { background: var(--paper-warm); border: 1px solid #ece2cf; border-radius: var(--radius-lg); }
.chip { display: inline-flex; align-items: center; gap: 6px; min-height: 26px; padding: 0 10px; border-radius: 999px; background: var(--panel); border: 1px solid var(--panel-line); color: #3c4048; font: 600 12.5px/1 var(--sans); white-space: nowrap; }
.chip-free { background: var(--sage-wash); border-color: #cfe2d4; color: #2f5a3c; }
.chip-cobalt { background: var(--cobalt-wash); border-color: #d1ddf5; color: var(--cobalt-ink); }
.rule { height: 1px; background: var(--line); border: 0; margin: 0; }
.notice { padding: 12px 14px; border-radius: var(--radius); background: var(--panel); border: 1px solid var(--panel-line); font-size: 14.5px; color: #3a3e46; }
.notice-error { background: var(--brick-wash); border-color: #efcfc5; color: #7c2f1d; }
.notice-ok { background: var(--sage-wash); border-color: #cfe2d4; color: #2f5a3c; }
/* Tables */
.table { width: 100%; border-collapse: collapse; font-size: 15px; }
.table th, .table td { padding: 13px 14px; border-bottom: 1px solid var(--line); text-align: left; vertical-align: top; }
.table th { font: 650 12px/1.2 var(--sans); letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.table td.yes { color: #2f5a3c; font-weight: 600; }
.table td.no { color: #8b4a3a; }
.table-wrap { overflow-x: auto; border: 1px solid var(--line); border-radius: var(--radius-lg); background: #fff; }
.table-wrap .table tr:last-child td { border-bottom: 0; }
/* Prose (blog, docs) */
.prose { font-size: 18px; line-height: 1.72; color: #24272d; max-width: 68ch; }
.prose > * + * { margin-top: 1.1em; }
.prose h2 { margin-top: 2em; font: 380 30px/1.18 var(--serif); letter-spacing: -.022em; color: var(--ink-solid); }
.prose h3 { margin-top: 1.7em; font: 650 19px/1.35 var(--sans); letter-spacing: -.01em; }
.prose a { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; text-decoration-color: #2e5ec466; }
.prose ul, .prose ol { padding-left: 1.3em; }
.prose li + li { margin-top: .4em; }
.prose code { font: 500 .86em/1 var(--mono); padding: .15em .38em; border-radius: 5px; background: var(--panel); border: 1px solid var(--panel-line); }
.prose pre { overflow-x: auto; padding: 16px 18px; border-radius: 12px; background: #16181d; color: #e8eaee; font: 13.5px/1.6 var(--mono); }
.prose pre code { padding: 0; background: none; border: 0; color: inherit; font-size: inherit; }
.prose blockquote { padding-left: 18px; border-left: 3px solid var(--cobalt); color: #3e424a; font-style: italic; }
.prose table { width: 100%; border-collapse: collapse; font-size: 15.5px; }
.prose th, .prose td { padding: 10px 12px; border-bottom: 1px solid var(--line); text-align: left; }
.prose th { font-weight: 650; }
.prose strong { font-weight: 650; color: var(--ink-solid); }
/* Code block outside prose */
.code { position: relative; overflow-x: auto; padding: 16px 18px; border-radius: 12px; background: #16181d; color: #e8eaee; font: 13px/1.65 var(--mono); white-space: pre; }
.code .c { color: #8b93a3; }
/* FAQ */
.faq { display: grid; gap: 10px; }
.faq details { background: #fff; border: 1px solid var(--line); border-radius: 14px; padding: 4px 20px; }
.faq summary { cursor: pointer; list-style: none; display: flex; align-items: center; justify-content: space-between; gap: 16px; min-height: 58px; font: 600 16.5px/1.35 var(--sans); }
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: "+"; font: 300 24px/1 var(--sans); color: var(--muted); transition: transform .2s; }
.faq details[open] summary::after { transform: rotate(45deg); }
.faq details > div { padding: 0 0 18px; color: #3d4148; line-height: 1.65; }
/* Footer */
.site-foot { margin-top: 96px; padding: 56px 0 40px; border-top: 1px solid var(--line); background: var(--paper); font-size: 14.5px; color: var(--muted); }
.site-foot .foot-grid { display: grid; grid-template-columns: 1.4fr repeat(3, 1fr); gap: 32px; }
.site-foot h4 { margin-bottom: 12px; font: 650 12px/1 var(--sans); letter-spacing: .12em; text-transform: uppercase; color: var(--ink); }
.site-foot ul { list-style: none; padding: 0; display: grid; gap: 9px; }
.site-foot a { color: #4a4e56; }
.site-foot a:hover { color: var(--ink-solid); }
.site-foot .foot-note { margin-top: 40px; padding-top: 22px; border-top: 1px solid var(--line); display: flex; flex-wrap: wrap; justify-content: space-between; gap: 12px; font-size: 13.5px; }
@media (max-width: 760px) { .site-foot .foot-grid { grid-template-columns: 1fr 1fr; } }
/* Utilities */
.stack { display: grid; gap: var(--gap, 16px); }
.row { display: flex; align-items: center; gap: var(--gap, 12px); flex-wrap: wrap; }
.spread { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.center { text-align: center; }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.mono { font-family: var(--mono); }
.nowrap { white-space: nowrap; }
.section { padding-block: clamp(56px, 8vw, 96px); }
.section-tight { padding-block: clamp(36px, 5vw, 56px); }
.art { mix-blend-mode: multiply; }
.toast { position: fixed; left: 50%; bottom: 24px; z-index: 50; transform: translateX(-50%); padding: 12px 18px; border-radius: 10px; background: var(--ink-solid); color: #fff; font: 600 14px/1.3 var(--sans); box-shadow: 0 10px 30px #0004; }
.spinner { width: 18px; height: 18px; border: 2px solid #0000001f; border-top-color: currentColor; border-radius: 50%; animation: spin .7s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; } }
/* The OpenApps free apps network, in every app's footer. */
.oa-network { display: grid; gap: 16px; padding-bottom: 28px; margin-bottom: 4px; border-bottom: 1px solid var(--line); }
.oa-network-title { display: grid; gap: 4px; }
.oa-network-title a { color: var(--ink-solid); font: 400 22px/1.2 var(--serif); letter-spacing: -.015em; }
.oa-network-title span { font-size: 14px; color: var(--muted); }
.oa-network ul { list-style: none; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 8px 18px; }
.oa-network li { display: grid; gap: 1px; }
.oa-network li a { color: var(--ink); font: 600 14.5px/1.3 var(--sans); }
.oa-network li a:hover { color: var(--cobalt); }
.oa-network li a[aria-current="page"] { color: var(--muted); }
.oa-network li span { font-size: 13px; color: var(--faint); }
.oa-network-more { font-size: 13.5px; color: var(--faint); }
.oa-network-more a { color: #4a4e56; }
Change history
Link to OpenApps pages and add a contribution strip
Bind the agent address in the policy
Add favicon.ico so browsers that ask for it stop getting a 404
Bounded source sync
Bounded source sync
Bounded source sync
Bounded source sync