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 b3b80918bc912dda8c53a48d
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
/* Invoice. Shared look comes from /kit.css; this is the app's own layout. */
body.app-mode .landing-only { display: none !important; }
body:not(.app-mode) #app:empty, #mine:empty { display: none; }
.page-pad { padding-block: 56px 80px; }
.page-pad-sm { padding-block: 28px 80px; }
.narrow { max-width: 640px; }
.small { font-size: 14px; }
.faint { color: var(--faint); }
.pre { white-space: pre-line; }
.site-nav a { white-space: nowrap; }
@media (max-width: 420px) { .site-nav a { padding: 0 9px; } }
/* Landing hero: the copy, then the editor */
.app-hero { padding: 36px 0 64px; background: var(--paper-warm); border-bottom: 1px solid #ece2cf; }
.hero-copy { display: flex; align-items: center; justify-content: space-between; gap: 32px; margin-bottom: 28px; }
.app-hero h1 { margin-top: 12px; font-size: clamp(38px, 4.6vw, 60px); }
.app-hero .lede { margin-top: 14px; }
.hero-points { list-style: none; padding: 0; margin-top: 18px; display: flex; flex-wrap: wrap; gap: 8px 22px; font-size: 15px; color: #3c4048; }
.hero-points li { display: flex; gap: 9px; align-items: baseline; }
.hero-points li::before { content: ""; flex: 0 0 7px; height: 7px; border-radius: 50%; background: var(--cobalt); transform: translateY(-2px); }
.hero-art { width: 220px; height: auto; flex: none; }
.mine-jump { display: inline-flex; align-items: center; min-height: 36px; margin-top: 16px; padding: 0 14px; border: 1px solid #d1ddf5; border-radius: 999px; background: var(--cobalt-wash); color: var(--cobalt-ink); font: var(--type-control); font-size: 14px; }
@media (hover: hover) { .mine-jump:hover { border-color: var(--cobalt); color: var(--cobalt-ink); } }
@media (max-width: 760px) {
.hero-art { display: none; }
.app-hero { padding: 20px 0 40px; }
.hero-copy { margin-bottom: 18px; }
.app-hero h1 { margin-top: 10px; font-size: 36px; }
.app-hero .lede { margin-top: 10px; font-size: 16.5px; }
.hero-points { margin-top: 12px; gap: 6px 18px; font-size: 14.5px; }
}
/* Editor */
/* Until the editor mounts, its slot holds a screen of space, so the sections below do not jump down when it arrives. */
#editor:not(:has(.editor)) { min-height: 100vh; }
.editor { scroll-margin-top: 76px; }
.editor-grid { display: grid; grid-template-columns: minmax(0, 470px) minmax(0, 1fr); gap: 28px; }
.editor-form { align-self: start; padding: 6px 22px; }
/* The paper keeps the actions in view: it scrolls inside its column when it is taller than the window. */
.preview-sticky { position: sticky; top: 80px; display: grid; grid-template-columns: minmax(0, 1fr); grid-template-rows: auto minmax(0, 1fr); gap: 14px; max-height: calc(100vh - 96px); }
.preview-scroll { overflow-y: auto; margin: 0 -16px; padding: 0 16px; overscroll-behavior: contain; }
.editor-actions { display: grid; gap: 10px; }
.editor-actions .row { gap: 8px; }
.form-end { display: grid; gap: 10px; padding: 18px 0 16px; border-top: 1px solid var(--line); }
.form-end .row { gap: 8px; }
.editor .editor-switch, .editor-bar { display: none; }
.editor-switch { align-items: center; gap: 8px; }
.editor-switch .segmented { flex: 1; }
.form-section { padding: 18px 0; border-top: 1px solid var(--line); }
.form-section:first-child { border-top: 0; }
.form-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 12px; }
.form-title { margin-bottom: 12px; font: 650 12px/1.2 var(--sans); letter-spacing: .1em; text-transform: uppercase; color: var(--muted); }
.form-head .form-title { margin-bottom: 0; }
.form-head .btn { margin: -8px -10px -8px 0; }
.field .form-title { margin-bottom: 0; }
.field > span em { font-style: normal; font-weight: 500; color: var(--faint); }
.two, .grid-4 { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 12px; }
.form .input, .form .select { min-width: 0; }
.form .field { align-content: start; }
.textarea-sm { min-height: 0; }
.input-sm { min-height: 42px; padding: 8px 10px; }
.logo-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.logo-thumb { max-width: 120px; max-height: 44px; object-fit: contain; padding: 4px; border: 1px solid var(--line); border-radius: 8px; background: #fff; }
.biz-summary { display: flex; align-items: center; gap: 12px; width: 100%; margin-top: 10px; padding: 12px 14px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--paper); text-align: left; cursor: pointer; font-size: 15px; }
@media (hover: hover) { .biz-summary:hover { border-color: var(--line-strong); } }
.biz-summary img { max-width: 72px; max-height: 32px; object-fit: contain; }
.items { list-style: none; padding: 0; display: grid; gap: 10px; }
.item { display: grid; gap: 8px; padding: 10px; border: 1px solid var(--line); border-radius: 12px; background: var(--paper); }
.item-top { display: flex; gap: 6px; align-items: center; }
.item-top .input { min-height: 42px; padding: 9px 11px; }
/* Quantity, price and tax keep their widths; the amount sits at the right, or on its own row when it does not fit. */
.item-nums { display: flex; flex-wrap: wrap; gap: 8px; align-items: flex-end; padding-right: 44px; }
.item-nums > .mini { flex: 0 1 80px; }
.item-nums > .mini + .mini { flex-basis: 120px; }
.item-nums.with-tax > .mini { flex-basis: 72px; }
.item-nums.with-tax > .mini + .mini { flex-basis: 110px; }
.item-nums.with-tax > .mini + .mini + .mini { flex-basis: 72px; }
.mini { display: grid; gap: 4px; min-width: 0; }
.mini span { font: 600 12px/1 var(--sans); color: var(--muted); }
.item-amount { margin-left: auto; padding-bottom: 10px; font: 600 15px var(--sans); white-space: nowrap; }
.add-line { margin-top: 12px; }
.suffix-input { display: flex; align-items: center; border: 1px solid var(--line-strong); border-radius: var(--radius); background: #fff; }
.suffix-input:focus-within { border-color: var(--cobalt); box-shadow: 0 0 0 3px #2e5ec41f; }
.suffix-input .input { border: 0; box-shadow: none !important; }
.suffix-input span { padding-right: 13px; color: var(--muted); font: 600 14px var(--sans); }
.tax-note { min-height: 46px; display: flex; align-items: center; }
.check.small { font-size: 14px; margin-top: 2px; }
.check.small input { width: 16px; height: 16px; }
.discount-row { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 8px; }
.segmented { display: grid; gap: 4px; padding: 4px; border-radius: 12px; background: var(--panel); border: 1px solid var(--panel-line); }
.segmented-2 { grid-template-columns: 1fr 1fr; }
.segmented button { min-height: 36px; padding: 0 12px; border: 0; border-radius: 9px; background: transparent; cursor: pointer; font: var(--type-control); color: var(--muted); transition: background-color var(--motion-fast) var(--ease-out), color var(--motion-fast) var(--ease-out), box-shadow var(--motion-fast) var(--ease-out); }
.segmented button[aria-pressed="true"] { background: #fff; color: var(--ink-solid); box-shadow: 0 1px 3px #0000001a; }
.kind-switch { max-width: 260px; margin-bottom: 14px; }
@media (pointer: coarse) { .segmented { padding: 3px; } .segmented button { min-height: 40px; } }
.editor:focus { outline: none; }
@media (max-width: 1080px) { .editor-grid { grid-template-columns: minmax(0, 420px) minmax(0, 1fr); gap: 20px; } }
@media (max-width: 900px) {
.editor .editor-switch { display: flex; margin-bottom: 12px; }
.editor-form, .editor-preview { animation: oa-fade-in var(--motion) var(--ease-out); }
.editor-grid { grid-template-columns: minmax(0, 1fr); }
.editor[data-view="edit"] .editor-preview, .editor[data-view="preview"] .editor-form { display: none; }
.editor-actions, .form-end { display: none; }
.preview-sticky { position: static; max-height: none; }
.preview-scroll { overflow: visible; }
.editor-bar { display: grid; gap: 8px; position: sticky; bottom: 0; z-index: 10; margin: 14px -24px 0; padding: 12px max(24px, var(--safe-right)) calc(12px + var(--safe-bottom)) max(24px, var(--safe-left)); background: #fdfdfcf2; -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px); border-top: 1px solid var(--line); }
.editor-bar-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.editor-bar-total { display: grid; line-height: 1.2; font-size: 13px; }
.editor-bar-total strong { font-size: 17px; }
.editor-bar .row { gap: 6px; flex-wrap: nowrap; }
.editor-bar .btn { min-height: 44px; padding: 0 14px; }
.editor-bar .new-btn { display: none; }
.editor-form { padding: 4px 16px; }
}
/* The discount needs room for its type switch and an amount, so tax and discount stack on phones. */
@media (max-width: 560px) { .tax-discount { grid-template-columns: minmax(0, 1fr); } }
@media (max-width: 420px) {
.two { grid-template-columns: minmax(0, 1fr); }
.item-nums { padding-right: 0; }
.item-nums > .mini { flex-basis: 72px; }
.item-nums > .mini + .mini { flex-basis: 110px; }
.editor-bar svg { display: none; }
}
/* The paper */
.paper-fit { width: 100%; min-width: 0; padding-bottom: 24px; }
.sheet { box-sizing: border-box; margin-inline: auto; padding: 67px; background: #fff; color: #15171b; border-radius: 4px; box-shadow: 0 1px 2px #1a1d2414, 0 18px 50px -20px #1a1d2440; font: 400 12.7px/1.45 "Helvetica Neue", Helvetica, Arial, sans-serif; }
.sheet p, .sheet dl, .sheet dd { margin: 0; }
.sheet .ph { color: #b3b7be; }
.sheet-head { display: flex; justify-content: space-between; gap: 32px; }
.sheet-from { max-width: 55%; }
.sheet-logo { max-width: 213px; max-height: 75px; object-fit: contain; object-position: left; margin-bottom: 20px; }
.sheet-name { font-weight: 700; font-size: 17.3px; line-height: 1.3; }
.sheet-muted { color: #5e6369; margin-top: 4px; }
.sheet-meta { text-align: right; }
.sheet-title { font-weight: 700; font-size: 32px; line-height: 1; letter-spacing: .01em; }
.sheet-meta dl { display: grid; grid-template-columns: auto auto; gap: 3px 28px; margin-top: 22px; text-align: left; }
.sheet-meta dt { color: #5e6369; }
.sheet-meta dd { font-weight: 700; text-align: right; }
.sheet-paid { color: #2e6b45 !important; }
.sheet-bill { display: flex; justify-content: space-between; gap: 32px; margin-top: 36px; }
.sheet-label { font-weight: 700; font-size: 10.7px; letter-spacing: .06em; text-transform: uppercase; color: #5e6369; margin-bottom: 8px !important; }
.sheet-client { font-weight: 700; font-size: 15.3px; }
.sheet-due { text-align: right; }
.sheet-amount { font-weight: 700; font-size: 29px; line-height: 1.1; }
.sheet-table { width: 100%; margin-top: 34px; border-collapse: collapse; }
.sheet-table th { padding: 8px 11px; background: #f3f4f6; font-weight: 700; font-size: 10px; letter-spacing: .06em; text-transform: uppercase; color: #5e6369; text-align: left; }
.sheet-table td { padding: 9px 11px 10px; border-bottom: 1px solid #dcdee3; vertical-align: top; }
.sheet-table .num { text-align: right; white-space: nowrap; width: 1%; }
.sheet-table td:first-child { word-break: break-word; }
.sheet-totals { display: grid; justify-content: end; margin-top: 18px; }
.sheet-totals dl { display: grid; grid-template-columns: 200px auto; row-gap: 5px; padding-right: 11px; }
.sheet-totals dd { padding-left: 24px; }
.sheet-totals dt { color: #5e6369; }
.sheet-totals dd { text-align: right; white-space: nowrap; }
.sheet-totals .sheet-total { margin-top: 6px; padding-top: 8px; border-top: 1px solid #15171b; color: #15171b; font-weight: 700; font-size: 16px; }
.sheet-block { margin-top: 30px; }
.sheet a { color: var(--cobalt); text-decoration: underline; text-underline-offset: 2px; overflow-wrap: anywhere; }
.sheet-line-meta { display: none; }
/* Narrow screens: the sheet reflows at full text size instead of shrinking the page. */
.sheet-fluid { width: 100%; padding: 22px 18px 26px; font-size: 14.5px; line-height: 1.5; }
.sheet-fluid .sheet-head { flex-direction: column; gap: 18px; }
.sheet-fluid .sheet-from { max-width: none; }
.sheet-fluid .sheet-logo { max-width: 160px; max-height: 56px; margin-bottom: 12px; }
.sheet-fluid .sheet-name { font-size: 17px; }
.sheet-fluid .sheet-meta { text-align: left; }
.sheet-fluid .sheet-title { font-size: 22px; }
.sheet-fluid .sheet-meta dl { grid-template-columns: auto minmax(0, 1fr); gap: 4px 16px; margin-top: 10px; }
.sheet-fluid .sheet-meta dd { text-align: right; }
.sheet-fluid .sheet-bill { flex-direction: column; gap: 16px; margin-top: 22px; padding-top: 18px; border-top: 1px solid #e6e8ec; }
.sheet-fluid .sheet-due { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; text-align: left; }
.sheet-fluid .sheet-due .sheet-label { margin-bottom: 0 !important; }
.sheet-fluid .sheet-amount { font-size: 24px; }
.sheet-fluid .sheet-table { margin-top: 20px; }
.sheet-fluid .qp { display: none; }
.sheet-fluid .sheet-table th { padding: 7px 10px; }
.sheet-fluid .sheet-table td { padding: 10px; }
.sheet-fluid .sheet-line-meta { display: block; margin-top: 2px; color: #5e6369; font-size: 13px; white-space: nowrap; }
.sheet-fluid .sheet-totals { justify-content: stretch; margin-top: 14px; }
.sheet-fluid .sheet-totals dl { grid-template-columns: minmax(0, 1fr) auto; padding-right: 10px; }
.sheet-fluid .sheet-block { margin-top: 22px; }
/* Shared invoice page */
.inv-head { border-bottom: 1px solid #ece2cf; background: var(--paper-warm); }
.inv-head-inner { display: flex; align-items: flex-end; justify-content: space-between; gap: 20px; flex-wrap: wrap; padding: 26px 0 24px; }
.inv-head-text { min-width: 0; }
.inv-back { display: inline-flex; align-items: center; gap: 4px; min-height: 44px; margin: -10px 0 -6px -6px; padding: 0 6px; border-radius: 8px; color: var(--muted); font: var(--type-control); }
@media (hover: hover) { .inv-back:hover { color: var(--ink-solid); background: #0000000a; } }
.inv-title { display: flex; align-items: center; flex-wrap: wrap; gap: 14px; margin-top: 8px; font: 360 clamp(34px, 4vw, 46px)/1.05 var(--serif); letter-spacing: -.03em; color: var(--ink-solid); }
.inv-title .chip { font-size: 13px; min-height: 28px; letter-spacing: 0; }
.inv-sub { margin-top: 8px; }
.inv-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.inv-skeleton-head { display: grid; gap: 12px; padding-block: 6px 4px; }
.skeleton-eyebrow { width: 140px; height: 12px; }
.skeleton-amount { width: 220px; height: 44px; }
.skeleton-sub { width: min(300px, 70vw); height: 14px; }
.skeleton-sheet { width: 100%; height: min(1056px, 120vw); border-radius: 4px; }
.problem { max-width: 560px; margin-inline: auto; padding-block: 36px 40px; }
.problem > h1 { font: var(--type-title); letter-spacing: -.02em; color: var(--ink-solid); text-wrap: balance; }
.problem > img { width: 150px; }
.inv-body { display: grid; grid-template-columns: minmax(0, 1fr); gap: 18px; padding-top: 24px; padding-bottom: 40px; }
.inv-paper { max-width: 816px; width: 100%; margin-inline: auto; }
.inv-edit-head { margin-bottom: 18px; }
.owner-card { display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px; padding: 18px 20px; max-width: 816px; width: 100%; margin-inline: auto; }
.owner-note { max-width: 816px; width: 100%; margin-inline: auto; }
.chip-overdue { background: var(--brick-wash); border-color: #efcfc5; color: #7c2f1d; }
.made-with { margin-top: 8px; }
.linklike { padding: 0; border: 0; background: none; color: var(--cobalt); cursor: pointer; font: inherit; }
@media (hover: hover) { .linklike:hover { color: var(--cobalt-ink); } }
.link-row { display: flex; align-items: center; gap: 8px; }
.send-row { gap: 8px; }
.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; }
@media (max-width: 600px) {
.inv-actions { width: 100%; }
.inv-actions > .btn { flex: 1 1 40%; }
.inv-actions > .btn:first-child { flex-basis: 100%; }
.inv-actions > .btn:only-child { flex-basis: 100%; }
.inv-head-inner { padding: 18px 0 18px; gap: 16px; }
}
/* Your invoices */
.mine { border-bottom: 1px solid var(--line); scroll-margin-top: 64px; }
.mine-head { align-items: flex-end; }
.mine-summary { margin-top: 6px; font-size: 15px; }
.mine-list { list-style: none; padding: 0; margin-top: 18px; border: 1px solid var(--line); border-radius: 14px; background: #fff; overflow: hidden; }
.mine-list li + li { border-top: 1px solid var(--line); }
.mine-list a { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 14px 18px; color: var(--ink); }
@media (hover: hover) { .mine-list a:hover { background: #fafbfc; color: var(--ink); } }
.mine-list a { min-height: 64px; transition: background-color var(--motion-fast) var(--ease-out); }
.chip-skeleton { width: 64px; height: 26px; border-radius: 999px; }
.mine-main { display: grid; gap: 2px; min-width: 0; }
.mine-main strong { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mine-main .muted { font-size: 13.5px; }
.mine-side { display: flex; align-items: center; gap: 12px; white-space: nowrap; }
.mine-total { font-weight: 600; }
/* Landing sections */
.steps { display: grid; grid-template-columns: repeat(3, 1fr); gap: 28px; margin-top: 28px; padding: 0; counter-reset: step; }
.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 { font: 600 18px/1.3 var(--sans); }
.steps p { margin-top: 8px; color: #4a4e56; }
@media (max-width: 760px) { .steps { grid-template-columns: 1fr; } }
.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; }
@media (max-width: 900px) { .api-grid { grid-template-columns: 1fr; } }
.more-apps { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 12px; list-style: none; padding: 0; margin-top: 22px; }
.more-apps a { display: grid; gap: 4px; padding: 16px 18px; border: 1px solid var(--line); border-radius: 14px; background: #fff; color: var(--ink); }
@media (hover: hover) { .more-apps a:hover { border-color: var(--line-strong); box-shadow: var(--shadow); color: var(--ink); } }
.more-apps strong { font: 400 22px/1.1 var(--serif); }
.more-apps span { color: var(--muted); font-size: 14px; }
.compare td:first-child { font-weight: 600; }
.compare th, .compare td { min-width: 130px; }
Change history
Quality pass: phone-readable invoice, estimates, email client, saved clients, CSV export, openapi.json
Bounded source sync
Bounded source sync
Bounded source sync
Bounded source sync
Bounded source sync
Bounded source sync