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 7716a56ff3432bc0c1e4837c
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
/* PDF. Shared look comes from /kit.css; this is the app's own layout. */
body { padding-left: var(--safe-left); padding-right: var(--safe-right); }
button { -webkit-tap-highlight-color: transparent; } /* buttons have their own pressed look */
body.app-mode .landing-only { display: none !important; }
.grow { flex: 1; min-width: 0; }
/* Landing hero with the workspace */
.app-hero { padding: 48px 0 72px; background: linear-gradient(180deg, var(--paper-warm) 0%, var(--paper) 100%); border-bottom: 1px solid #f0ebe1; }
.app-hero-grid { display: grid; grid-template-columns: minmax(0, 1fr) 460px; grid-template-areas: "head work" "body work"; column-gap: 56px; }
.hero-head { grid-area: head; align-self: end; }
.hero-work { grid-area: work; align-self: center; }
.hero-body { grid-area: body; align-self: start; }
.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); }
@media (max-width: 900px) {
.app-hero { padding: 24px 0 48px; }
.app-hero-grid { grid-template-columns: minmax(0, 1fr); grid-template-areas: "head" "work" "body"; row-gap: 22px; }
.app-hero .lede { margin-top: 0; }
}
body.app-mode .app-hero { padding: 16px 0 32px; background: var(--paper); border-bottom: 0; }
body.app-mode .app-hero-grid { display: block; }
.drop { display: grid; justify-items: center; gap: 14px; padding: 28px 24px 30px; text-align: center; border: 1.5px dashed var(--line-strong); transition: border-color var(--motion-fast) var(--ease-out), background-color var(--motion-fast) var(--ease-out); }
.drop.is-over { border-color: var(--cobalt); background: var(--cobalt-wash); }
.drop-art { width: 210px; height: auto; margin-bottom: -6px; -webkit-mask-image: radial-gradient(closest-side, #000 72%, #0000); mask-image: radial-gradient(closest-side, #000 72%, #0000); }
.drop-title { font: 380 28px/1.15 var(--serif); letter-spacing: -.02em; text-wrap: balance; }
.drop .btn { min-width: 220px; }
.drop .problems { width: 100%; text-align: left; }
@media (max-width: 900px) { .drop-art { width: 120px; } .drop { gap: 12px; padding: 18px 18px 22px; } .drop-title { font-size: 25px; } }
/* Workspace */
.editor { display: flex; flex-direction: column; }
.editor-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 12px 16px; flex-wrap: wrap; padding: 8px 0 18px; }
.editor-title-wrap { min-width: 0; max-width: 100%; }
.editor-title { font: 360 clamp(28px, 3.4vw, 40px)/1.1 var(--serif); letter-spacing: -.025em; overflow-wrap: anywhere; color: var(--ink-solid); }
.editor-meta { display: flex; align-items: center; gap: 6px; margin-top: 6px; color: var(--muted); font-size: 14.5px; }
.editor-meta svg { width: 15px; height: 15px; flex: none; color: var(--sage); }
.editor-actions { gap: 6px; }
.problems { display: grid; grid-template-columns: minmax(0, 1fr); gap: 8px; scroll-margin: calc(80px + var(--safe-top)) 0 24px; }
.editor .problems { margin-bottom: 14px; }
.problems .notice { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; padding-right: 6px; }
.problems .icon-btn { width: 32px; height: 32px; margin-top: -5px; color: inherit; }
.icon-btn { display: grid; place-items: center; width: 38px; height: 38px; flex: none; border: 0; border-radius: 10px; background: none; cursor: pointer; color: var(--muted); }
@media (hover: hover) { .icon-btn:hover { background: #0000000a; color: var(--ink); } }
.files-wrap { margin-bottom: 16px; }
.files { list-style: none; padding: 0; display: grid; grid-template-columns: minmax(0, 1fr); gap: 6px; }
.file { position: relative; display: flex; align-items: center; gap: 12px; min-height: 50px; padding: 4px 4px 4px 12px; border: 1px solid var(--line); border-radius: 12px; background: #fff; cursor: grab; -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
.file.is-dragging { opacity: .35; }
.file.drop-before::before, .file.drop-after::after { content: ""; position: absolute; left: 8px; right: 8px; height: 3px; border-radius: 2px; background: var(--cobalt); }
.file.drop-before::before { top: -5px; }
.file.drop-after::after { bottom: -5px; }
.file-badge { display: grid; place-items: center; flex: none; min-width: 26px; height: 26px; padding: 0 6px; border-radius: 999px; background: var(--cobalt-wash); color: var(--cobalt-ink); font: 650 12.5px/1 var(--sans); }
.file-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font: 600 15px/1.3 var(--sans); }
.file-meta { flex: none; color: var(--muted); font-size: 13.5px; }
.file-tools { display: flex; flex: none; }
.editor-grid { display: grid; grid-template-columns: minmax(0, 1fr) 330px; gap: 28px; align-items: start; }
.editor-side { position: sticky; top: calc(76px + var(--safe-top)); max-height: calc(100vh - 80px - var(--safe-top)); overflow-y: auto; padding: 4px 6px 16px; margin: -4px -6px 0; }
.side-card { padding: 18px 20px 20px; }
.panel-body { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; }
.side-title { margin-top: 2px; font: var(--type-title); letter-spacing: -.02em; color: var(--ink-solid); }
.segmented { display: grid; gap: 4px; padding: 4px; border-radius: 12px; background: var(--panel); border: 1px solid var(--panel-line); }
.segmented button { min-height: 38px; padding: 0 6px; 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); }
@media (hover: hover) { .segmented button:hover { color: var(--ink-solid); } }
.segmented button[aria-checked="true"] { background: #fff; color: var(--ink-solid); box-shadow: 0 1px 3px #0000001a; }
.segmented button:focus-visible { outline-offset: -2px; }
@media (pointer: coarse) { .segmented button { min-height: 44px; } }
/* The panel's switch between PDF, Split and Images reads as tabs, so it does not look like one more option. */
.tabs { display: grid; margin: -6px 0 0; border-bottom: 1px solid var(--line); }
.tabs button { position: relative; min-height: 44px; padding: 0 4px; border: 0; background: none; cursor: pointer; font: var(--type-control); color: var(--muted); transition: color var(--motion-fast) var(--ease-out); }
.tabs button::after { content: ""; position: absolute; left: 10%; right: 10%; bottom: -1px; height: 2px; border-radius: 2px; background: var(--ink-solid); opacity: 0; transform: scaleX(.4); transition: transform var(--motion) var(--ease-out), opacity var(--motion-fast) var(--ease-out); }
@media (hover: hover) { .tabs button:hover { color: var(--ink-solid); } }
.tabs button[aria-checked="true"] { color: var(--ink-solid); }
.tabs button[aria-checked="true"]::after { opacity: 1; transform: none; }
.tabs button:focus-visible { outline-offset: -3px; }
.pagebar { position: sticky; top: calc(64px + var(--safe-top)); z-index: 10; display: flex; align-items: center; justify-content: space-between; gap: 10px; min-height: 56px; padding: 8px 0; margin-bottom: 14px; background: var(--paper); border-bottom: 1px solid var(--line); }
.pagebar-hint { color: var(--muted); font-size: 14px; }
.pagebar-count { font: 600 15px var(--sans); color: var(--ink-solid); }
.pagebar-actions { display: flex; flex: none; justify-content: flex-end; gap: 6px; }
.pagebar-sel { display: flex; align-items: center; gap: 6px; }
.pages { list-style: none; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(156px, 1fr)); gap: 16px; }
.page { position: relative; padding: 8px 8px 4px; border: 1px solid var(--line); border-radius: 14px; background: #fff; cursor: grab; -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; transition: border-color var(--motion-fast) var(--ease-out), box-shadow var(--motion-fast) var(--ease-out); }
@media (hover: hover) { .page:hover { border-color: var(--line-strong); } }
.page.is-selected { border-color: var(--cobalt); box-shadow: 0 0 0 1.5px var(--cobalt); }
.page.is-selected .thumb { background: var(--cobalt-wash); }
.page.is-dragging { opacity: .35; }
.page.drop-before::before, .page.drop-after::after { content: ""; position: absolute; top: 10px; bottom: 10px; width: 3px; border-radius: 2px; background: var(--cobalt); }
.page.drop-before::before { left: -10px; }
.page.drop-after::after { right: -10px; }
.page-select { position: relative; display: block; width: 100%; padding: 0; border: 0; border-radius: 9px; background: none; cursor: inherit; }
.thumb { position: relative; display: block; aspect-ratio: 1; border-radius: 9px; background: var(--paper-warm); overflow: hidden; transition: background-color var(--motion-fast) var(--ease-out); }
.thumb img { position: absolute; inset: 0; margin: auto; max-width: calc(100% - 20px); max-height: calc(100% - 20px); background: #fff; box-shadow: 0 1px 2px #1a1d2420, 0 4px 12px -6px #1a1d2440; opacity: 0; transition: transform var(--motion) var(--ease-out), opacity var(--motion) var(--ease-out); pointer-events: none; }
.thumb img.is-shown { opacity: 1; }
.thumb-wait { position: absolute; inset: 9% 21%; border-radius: 2px; }
.thumb-none { position: absolute; inset: 0; display: grid; place-items: center; color: var(--muted); font-size: 13px; }
.page-no { position: absolute; top: 6px; left: 6px; display: grid; place-items: center; min-width: 26px; height: 26px; padding: 0 7px; border-radius: 999px; background: var(--ink-solid); color: #fff; font: 650 12.5px/1 var(--sans); }
.page-from { position: absolute; bottom: 6px; left: 6px; max-width: calc(100% - 12px); padding: 3px 7px; border-radius: 6px; background: #fffffff0; border: 1px solid var(--line); color: #3c4048; font: 600 11.5px/1.2 var(--sans); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.page-tick { position: absolute; top: 6px; right: 6px; display: grid; place-items: center; width: 26px; height: 26px; border-radius: 50%; border: 1.5px solid var(--line-strong); background: #fffffff0; color: transparent; opacity: 0; transition: opacity var(--motion-fast) var(--ease-out), background-color var(--motion-fast) var(--ease-out), border-color var(--motion-fast) var(--ease-out); }
@media (hover: hover) { .page:hover .page-tick { opacity: 1; } }
.page-select:focus-visible .page-tick, .page.is-selected .page-tick { opacity: 1; }
.page.is-selected .page-tick { border-color: var(--cobalt); background: var(--cobalt); color: #fff; }
.page-tick svg { width: 16px; height: 16px; stroke-width: 2.2; }
.page-tools { display: flex; justify-content: space-between; margin-top: 4px; }
.tool { display: grid; place-items: center; width: 34px; height: 34px; border: 0; border-radius: 8px; background: none; color: var(--muted); cursor: pointer; transition: background-color var(--motion-fast) var(--ease-out), color var(--motion-fast) var(--ease-out); }
@media (hover: hover) { .tool:hover:not(:disabled) { background: #0000000a; color: var(--ink-solid); } }
.tool:active:not(:disabled) { background: #00000010; }
.tool:disabled { opacity: .3; cursor: default; }
@media (pointer: coarse) { .tool { width: 40px; height: 44px; } }
.drag-ghost { position: fixed; z-index: 80; margin: 0; list-style: none; pointer-events: none; rotate: 2deg; box-shadow: var(--shadow-pop); opacity: .96; }
body.is-sorting, body.is-sorting * { cursor: grabbing !important; }
.parts { display: grid; grid-template-columns: minmax(0, 1fr); gap: 10px; }
.parts-actions { display: grid; gap: 8px; }
.part-list { list-style: none; padding: 0; display: grid; max-height: 300px; overflow-y: auto; overscroll-behavior: contain; border-top: 1px solid var(--line); }
.part-list li { display: flex; align-items: center; gap: 8px; padding: 8px 0; border-bottom: 1px solid var(--line); }
.part-list li:last-child { border-bottom: 0; }
.part-name { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font: 600 14px/1.3 var(--sans); }
.part-meta { display: block; color: var(--muted); font-size: 13px; }
.work { position: fixed; left: 50%; bottom: calc(24px + var(--safe-bottom)); z-index: 70; display: grid; gap: 8px; width: min(340px, calc(100% - 32px)); padding: 12px 16px; border-radius: 12px; background: var(--ink-solid); color: #fff; font: 600 14px/1.3 var(--sans); box-shadow: 0 10px 30px #0004; transform: translateX(-50%); animation: oa-toast-in var(--motion) var(--ease-out); }
.bar { display: block; height: 4px; border-radius: 2px; background: #ffffff33; overflow: hidden; }
.bar span { display: block; height: 100%; border-radius: 2px; background: #fff; transition: width var(--motion) var(--ease-out); }
.bar .bar-wait { width: 30%; animation: bar-wait 1.1s ease-in-out infinite; }
@keyframes bar-wait { from { transform: translateX(-100%); } to { transform: translateX(340%); } }
.toast { z-index: 70; display: flex; align-items: center; gap: 14px; }
/* With a sheet or dialog open, a message shows at the top so it does not cover the sheet's buttons. */
body:has(.dialog-backdrop) :is(.toast, .work) { top: calc(16px + var(--safe-top)); bottom: auto; }
.toast-action { flex: none; min-height: 32px; padding: 0 12px; border: 1px solid #ffffff4d; border-radius: 8px; background: none; color: #fff; font: var(--type-control); cursor: pointer; }
@media (hover: hover) { .toast-action:hover { background: #ffffff1a; } }
@media (pointer: coarse) { .toast-action { position: relative; } .toast-action::before { content: ""; position: absolute; inset: -6px; } }
.drop-overlay { position: fixed; inset: 0; z-index: 90; display: grid; place-items: center; background: #2e5ec414; border: 3px dashed var(--cobalt); pointer-events: none; animation: oa-fade-in var(--motion-fast) var(--ease-out); }
.drop-overlay span { padding: 14px 22px; border-radius: 12px; background: #fff; box-shadow: var(--shadow); font: 600 17px var(--sans); }
.empty-state .row { justify-content: center; }
/* Phones: one column, the panel opens as a sheet, the main buttons sit in a bar at the bottom. */
@media (max-width: 720px) {
.editor { min-height: calc(100vh - 80px - var(--safe-top)); min-height: calc(100dvh - 80px - var(--safe-top)); }
.editor-grid { grid-template-columns: minmax(0, 1fr); flex: 1; align-content: start; }
body.app-mode .app-hero { padding-bottom: 0; }
.editor-head { align-items: center; padding: 4px 0 14px; }
.editor-title { font-size: 30px; }
.action-bar { margin-top: 20px; }
.action-bar .btn-options { flex: 0 0 auto; }
.action-bar .btn { padding: 0 14px; }
.work { bottom: calc(88px + var(--safe-bottom)); }
.pages { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.page.drop-before::before { left: -8px; }
.page.drop-after::after { right: -8px; }
.file { min-height: 48px; gap: 10px; padding-left: 10px; }
.pagebar { min-height: 52px; }
}
/* Landing sections */
.steps { display: grid; grid-template-columns: repeat(3, minmax(0, 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: minmax(0, 1fr); gap: 22px; } }
.tools { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 12px; margin-top: 28px; list-style: none; padding: 0; }
.tools a { display: grid; align-content: start; gap: 6px; height: 100%; padding: 18px 18px 20px; border: 1px solid var(--line); border-radius: 14px; background: #fff; color: var(--ink); transition: border-color var(--motion-fast) var(--ease-out), box-shadow var(--motion-fast) var(--ease-out); }
@media (hover: hover) { .tools a:hover { border-color: var(--line-strong); box-shadow: var(--shadow); color: var(--ink); } }
.tools h3 { font: 600 17px/1.3 var(--sans); color: var(--ink-solid); }
.tools p { color: #4a4e56; font-size: 15px; line-height: 1.5; }
@media (max-width: 1100px) { .tools { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 760px) { .tools { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
/* On phones the jobs are a compact grid of names; the descriptions stay in the page for readers and search. */
@media (max-width: 520px) {
.tools { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.tools a { align-content: center; min-height: 56px; padding: 12px 14px; }
.tools h3 { font-size: 15.5px; }
.tools p { display: none; }
}
.private-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 40px; align-items: start; }
.private-grid .lede { margin-top: 14px; }
.private-list { list-style: none; padding: 0; display: grid; gap: 14px; }
.private-list li { padding: 16px 18px; border-radius: 14px; background: var(--paper-warm); border: 1px solid #ece2cf; }
.private-list strong { display: block; font: 600 16px/1.35 var(--sans); }
.private-list span { display: block; margin-top: 4px; color: #4a4e56; font-size: 15px; }
@media (max-width: 900px) { .private-grid { grid-template-columns: minmax(0, 1fr); gap: 24px; } }
.compare td:first-child { font-weight: 600; }
.compare { min-width: 640px; }
.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); transition: border-color var(--motion-fast) var(--ease-out), box-shadow var(--motion-fast) var(--ease-out); }
@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; }
.ai-note { display: grid; grid-template-columns: minmax(0, .9fr) minmax(0, 1.1fr); gap: 40px; align-items: start; }
.ai-note .lede { margin-top: 14px; }
.ai-note .code { margin-top: 16px; }
@media (max-width: 900px) { .ai-note { grid-template-columns: minmax(0, 1fr); gap: 20px; } }
Change history
Quality pass: compress, PDF to JPG, phone layout, job links, llms.txt and index.md
Bounded source sync
Bounded source sync
Bounded source sync
Bounded source sync