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 788ba0fa01083b300ad50913
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.
src/styles.css
/* Canvas. Shared look comes from /kit.css; this is the app's own layout. */
body.app-mode .landing-only, body.app-mode .site-head, body.app-mode .site-foot { display: none !important; }
body:not(.app-mode) #app:empty { display: none; }
.page-pad { padding-block: 56px 80px; }
.narrow { max-width: 640px; }
.grow { flex: 1; min-width: 0; }
.label { font: 600 14.5px/1.3 var(--sans); color: var(--ink); }
.link-btn { padding: 0; border: 0; background: none; color: var(--cobalt); font: inherit; cursor: pointer; }
.link-btn:hover { color: var(--cobalt-ink); text-decoration: underline; }
.icon-btn { display: inline-grid; place-items: center; width: 38px; height: 38px; border: 0; border-radius: 10px; background: none; cursor: pointer; color: var(--muted); flex: none; }
.icon-btn:hover { background: #0000000a; color: var(--ink); }
.icon-btn-sm { width: 30px; height: 30px; border-radius: 8px; }
.spinner-light { border-color: #ffffff55; border-top-color: #fff; }
/* Landing hero with the board starter */
.app-hero { padding: 40px 0 72px; background: linear-gradient(180deg, #faf6ee 0%, #fdfdfc 100%); border-bottom: 1px solid #f0ebe1; }
.app-hero-grid { display: grid; grid-template-columns: minmax(0, 1fr) 460px; grid-template-areas: "intro start" "points start" "yours start"; grid-template-rows: auto auto 1fr; column-gap: 56px; align-items: start; }
.hero-intro { grid-area: intro; }
.hero-start { grid-area: start; }
.hero-points { grid-area: points; }
.hero-yours { grid-area: yours; }
.app-hero h1 { margin-top: 14px; }
.app-hero .lede { margin-top: 18px; }
.hero-points { list-style: none; padding: 0; margin-top: 26px; display: grid; gap: 10px; font-size: 15.5px; color: #3c4048; }
.hero-points li { display: flex; gap: 10px; align-items: baseline; }
.hero-points li::before { content: ""; flex: 0 0 8px; height: 8px; border-radius: 50%; background: var(--cobalt); transform: translateY(-2px); }
.hero-art { width: 200px; height: auto; margin-bottom: -6px; }
@media (max-width: 960px) { .app-hero-grid { grid-template-columns: minmax(0, 1fr); grid-template-areas: "intro" "start" "yours" "points"; grid-template-rows: none; row-gap: 26px; } .hero-points { margin-top: 0; } }
@media (max-width: 600px) { .app-hero { padding-top: 16px; } .hero-art { width: 112px; margin-bottom: 4px; } }
.start { display: grid; gap: 14px; padding: 24px; }
.start-hint { text-align: center; margin-top: -4px; }
.start-templates { display: grid; gap: 10px; margin-top: 4px; }
.tpl-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.tpl { display: grid; gap: 3px; align-content: start; padding: 12px 13px; border: 1px solid var(--line-strong); border-radius: var(--radius); background: #fff; cursor: pointer; text-align: left; transition: border-color .15s, box-shadow .15s; }
.tpl:hover:not(:disabled) { border-color: #b5bdc8; box-shadow: var(--shadow); }
.tpl:disabled { cursor: progress; opacity: .7; }
.tpl-name { font: 600 14.5px/1.3 var(--sans); color: var(--ink); }
.tpl-sum { font-size: 13px; color: var(--muted); line-height: 1.4; }
@media (max-width: 380px) { .tpl-grid { grid-template-columns: minmax(0, 1fr); } }
@media (max-width: 600px) { .start { padding: 18px; } }
.your-boards { margin-top: 30px; display: grid; gap: 8px; }
@media (max-width: 960px) { .your-boards { margin-top: 0; } }
.your-boards ul { list-style: none; padding: 0; display: grid; gap: 6px; max-width: 460px; }
.your-boards li { display: flex; align-items: center; gap: 10px; padding: 6px 6px 6px 14px; border: 1px solid var(--line); border-radius: 12px; background: #fff; }
.your-boards li a { flex: 1; min-width: 0; font-weight: 600; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.your-boards li a:hover { color: var(--cobalt); }
.your-boards .link-btn { justify-self: start; font-size: 14px; font-weight: 600; }
/* Landing sections */
.steps { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 28px; margin-top: 28px; counter-reset: step; padding: 0; }
.steps li { list-style: none; counter-increment: step; }
.steps li::before { content: counter(step); display: grid; place-items: center; width: 34px; height: 34px; margin-bottom: 14px; border-radius: 50%; background: var(--ink-solid); color: #fff; font: 650 15px var(--sans); }
.steps h3, .features h3 { font: 600 18px/1.3 var(--sans); }
.steps p, .features p { margin-top: 8px; color: #4a4e56; }
@media (max-width: 760px) { .steps { grid-template-columns: minmax(0, 1fr); } }
.features { list-style: none; padding: 0; margin-top: 26px; display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 14px; }
.features li { padding: 20px; border: 1px solid var(--line); border-radius: 16px; background: #fff; }
.tpl-links, .more-apps { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 12px; list-style: none; padding: 0; margin-top: 22px; }
.tpl-links a, .more-apps a { display: grid; gap: 4px; height: 100%; padding: 16px 18px; border: 1px solid var(--line); border-radius: 14px; background: #fff; color: var(--ink); }
.tpl-links a:hover, .more-apps a:hover { border-color: var(--line-strong); box-shadow: var(--shadow); color: var(--ink); }
.tpl-links strong, .more-apps strong { font: 400 22px/1.15 var(--serif); }
.tpl-links span, .more-apps span { color: var(--muted); font-size: 14px; }
.compare td { min-width: 150px; }
.compare td:first-child { font-weight: 600; min-width: 130px; }
.api-grid { display: grid; grid-template-columns: minmax(0, .9fr) minmax(0, 1.1fr); gap: 40px; align-items: start; }
.api-grid .code { font-size: 12.5px; }
.api-grid code, .faq code { font: 500 .88em var(--mono); padding: .1em .35em; border-radius: 5px; background: var(--panel); border: 1px solid var(--panel-line); }
@media (max-width: 900px) { .api-grid { grid-template-columns: minmax(0, 1fr); gap: 24px; } }
.limits { margin-top: 18px; padding-left: 20px; display: grid; gap: 6px; color: #3c4048; }
/* Template pages */
.crumbs { font-size: 14px; color: var(--muted); margin-bottom: 18px; }
.tpl-hero { max-width: 820px; }
.tpl-cta { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-top: 26px; }
.tpl-preview { display: flex; gap: 16px; overflow-x: auto; padding: 4px 4px 14px; margin-top: 20px; }
.tpl-col { flex: 0 0 220px; padding: 12px; border: 1.5px solid #c9ced6; border-radius: 10px; background: #fff; }
.tpl-col h3 { font: 600 14px/1.3 var(--sans); color: #4a4e56; margin-bottom: 10px; }
.tpl-note { min-height: 72px; padding: 10px 12px; border-radius: 8px; font-size: 14.5px; line-height: 1.35; color: #1e1e1e; }
.tpl-note + .tpl-note { margin-top: 8px; }
.tpl-flow { margin-top: 20px; padding: 16px; border: 1px solid var(--line); border-radius: 14px; background: #fff; overflow-x: auto; }
.tpl-flow svg { max-width: 100%; height: auto; margin-inline: auto; }
.tpl-cols { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 32px; }
.tpl-list { margin-top: 14px; padding-left: 20px; display: grid; gap: 8px; color: #3c4048; }
@media (max-width: 760px) { .tpl-cols { grid-template-columns: minmax(0, 1fr); } }
/* Board page: the editor fills the screen */
.board { position: fixed; inset: 0; height: 100dvh; }
.board-loading { display: flex; align-items: center; justify-content: center; gap: 12px; min-height: 100dvh; color: var(--muted); }
.board .excalidraw svg, .board .excalidraw img { max-width: none; }
.board .excalidraw svg { display: initial; }
.board-actions { display: flex; align-items: center; gap: 8px; }
.board-btn { display: inline-flex; align-items: center; gap: 6px; height: 36px; padding: 0 12px; border: 1px solid var(--color-surface-lowest, #e3e6ea); border-radius: 8px; background: var(--island-bg-color, #fff); color: var(--text-primary-color, #1b1b1f); font: 600 14px var(--sans); cursor: pointer; box-shadow: var(--shadow-island, 0 1px 3px #0000001a); }
.board-btn:hover { background: var(--button-hover-bg, #f1f0ff); }
.board-btn-ink { background: var(--ink-solid); border-color: var(--ink-solid); color: #fff; }
.board-btn-ink:hover { background: #2a2c31; }
.save-state { display: inline-flex; align-items: center; gap: 8px; font: 500 13px var(--sans); color: var(--muted); white-space: nowrap; }
.save-offline { color: var(--brick); }
/* On phones Excalidraw's tools fill the top row, so these sit in the middle of its bottom bar. */
.board-actions-mobile { position: fixed; z-index: 4; left: 50%; transform: translateX(-50%); bottom: calc(env(safe-area-inset-bottom, 0px) + 22px); }
.board-actions-mobile .board-btn-text, .board-actions-mobile .save-saved, .board-actions-mobile .save-saving, .board-actions-mobile .save-readonly { display: none; }
.board-actions-mobile .board-btn { height: 38px; padding: 0 12px; box-shadow: none; }
/* Share sheet */
.share { display: grid; grid-template-columns: minmax(0, 1fr); gap: 18px; }
.link-row { display: grid; grid-template-columns: minmax(0, 1fr); gap: 8px; }
.link-row-head { display: grid; gap: 2px; }
.link-row-copy { gap: 8px; flex-wrap: nowrap; }
.link-code { flex: 1; min-width: 0; padding: 9px 11px; border-radius: 8px; background: var(--panel); border: 1px solid var(--panel-line); font: 13px var(--mono); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.owner-box { display: grid; grid-template-columns: minmax(0, 1fr); gap: 14px; padding-top: 16px; border-top: 1px solid var(--line); }
.wrap-row { flex-wrap: wrap; gap: 8px; }
.danger-zone { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; padding-top: 14px; border-top: 1px solid var(--line); }
/* Sheets */
.modal-backdrop { position: fixed; inset: 0; z-index: 60; display: grid; place-items: center; padding: 20px; background: #15171b66; animation: fade .15s ease; }
.modal { display: flex; flex-direction: column; width: min(560px, 100%); max-height: min(88vh, 900px); border-radius: 18px; background: #fff; color: var(--ink); font: 400 16px/1.6 var(--sans); box-shadow: 0 30px 80px -20px #0006; animation: rise .18s ease; }
.modal-head { display: flex; align-items: center; justify-content: space-between; padding: 18px 20px 6px; }
.modal-title { font: 400 26px/1.2 var(--serif); letter-spacing: -.015em; }
.modal-body { padding: 12px 20px 20px; overflow-y: auto; }
.modal-foot { display: flex; align-items: center; gap: 10px; padding: 14px 20px; border-top: 1px solid var(--line); }
@keyframes fade { from { opacity: 0; } }
@keyframes rise { from { opacity: 0; transform: translateY(10px); } }
@media (max-width: 600px) {
.modal-backdrop { place-items: end stretch; padding: 0; }
.modal { width: 100%; max-height: 92dvh; border-radius: 18px 18px 0 0; }
}
.toast { z-index: 90; }
.site-nav a { white-space: nowrap; }
Change history
Point OpenApps links to openapps.free
Bind AGENT_ADDRESS in policy constants
Use functions.openapps.xyz alias, add OpenApp contribution strip
Bounded source sync
Bounded source sync
Bounded source sync
Bounded source sync