diff --git a/appstore/screenshots/README.md b/appstore/screenshots/README.md new file mode 100644 index 0000000..6f47d4e --- /dev/null +++ b/appstore/screenshots/README.md @@ -0,0 +1,51 @@ +# Mac App Store screenshots + +Five 2560x1600 frames for the Margin listing: `frame-1.png` through `frame-5.png`. + +Each frame is an HTML page in `src/`, rendered at a 2560x1600 viewport with a device pixel ratio of +1. The app window inside the frame is not a bitmap capture. It is a CSS rebuild of the real app in +`src/app.css`, with rules and values lifted from `shared/css/tokens.css` and `src/styles/app.css`, +laid out at the app's own 1440x900 and scaled once into the 1600x1000 window well. That is why the +type is sharp: it is real text at render time, not a resampled screenshot. + +| File | Frame | Shows | +| --- | --- | --- | +| `frame-1.png` | Write | The writing surface, preview dock closed | +| `frame-2.png` | Preview | The editor beside the live page preview | +| `frame-3.png` | Proof | Three proofing marks and an open spelling popover | +| `frame-4.png` | Publish | The PDF export preview panel over the editor | +| `frame-5.png` | Yours | The library, no sign-in anywhere | + +## Re-rendering + +Serve this directory and screenshot each page at a 2560x1600 viewport, dpr 1: + +``` +python3 -m http.server 8731 +``` + +Load `http://127.0.0.1:8731/src/frame-1.html` and capture the viewport to `frame-1.png` here. Check +every output with `sips -g pixelWidth -g pixelHeight frame-*.png`; App Store Connect rejects +anything that is not exactly 2560x1600. + +Type comes from Google Fonts (Literata for headlines and prose, Hanken Grotesk for the interface), +so the render needs a network connection. + +## Editing + +`src/frame.css` is the frame surface: the eyebrow, headline, supporting line and the window well. +Every length in it is a real output pixel. + +`src/app.css` is the app window. Every length in it is an app pixel, so a value copied out of the +product's own stylesheet can go in unchanged. Keep it that way; the whole point is that the +screenshots stay honest about what the app looks like. + +Copy lives in each `src/frame-N.html`, along with that frame's window markup, since every frame +shows a different state of the app. + +## Sample content + +The frames use "The Quiet Hours" by Elena Marsh, an invented author. The prose is original and +written for this listing, so it is safe to publish. If you change it, keep it general non-fiction +rather than novel writing: the listing positions Margin as a writing app, not as software for one +genre. diff --git a/appstore/screenshots/frame-1.png b/appstore/screenshots/frame-1.png new file mode 100644 index 0000000..c164ad1 Binary files /dev/null and b/appstore/screenshots/frame-1.png differ diff --git a/appstore/screenshots/frame-2.png b/appstore/screenshots/frame-2.png new file mode 100644 index 0000000..3758f68 Binary files /dev/null and b/appstore/screenshots/frame-2.png differ diff --git a/appstore/screenshots/frame-3.png b/appstore/screenshots/frame-3.png new file mode 100644 index 0000000..194d93d Binary files /dev/null and b/appstore/screenshots/frame-3.png differ diff --git a/appstore/screenshots/frame-4.png b/appstore/screenshots/frame-4.png new file mode 100644 index 0000000..2a6ee14 Binary files /dev/null and b/appstore/screenshots/frame-4.png differ diff --git a/appstore/screenshots/frame-5.png b/appstore/screenshots/frame-5.png new file mode 100644 index 0000000..1a1fc0d Binary files /dev/null and b/appstore/screenshots/frame-5.png differ diff --git a/appstore/screenshots/src/app.css b/appstore/screenshots/src/app.css new file mode 100644 index 0000000..b367a0b --- /dev/null +++ b/appstore/screenshots/src/app.css @@ -0,0 +1,807 @@ +/* The Margin window, rebuilt in CSS so it renders crisply at any scale. + Rules and values are lifted from the app itself: shared/css/tokens.css and + src/styles/app.css. Authored at the app's own pixel sizes in a 1440x900 + window, then scaled once by frame.css to fill the 1600x1000 window well. */ + +:root { + --font-ui: "Hanken Grotesk", ui-sans-serif, system-ui, -apple-system, sans-serif; + --font-book: "Literata", Georgia, "Times New Roman", serif; + --font-heading: "Literata", Georgia, "Times New Roman", serif; + + --r-sm: 5px; + --r-md: 8px; + --r-lg: 12px; + + --pane-sidebar: 248px; + --pane-dock: 384px; + --measure: 46em; + --titlebar-h: 46px; + + --t-1: 11px; + --t-2: 12px; + --t-3: 13px; + --t-4: 15px; + + --paper: #fcfbf7; + --shell: #f1ece2; + --sidebar: #ece6da; + --raised: #fbfaf6; + + --ink: #23201b; + --ink-soft: #6b6458; + --ink-faint: #9b9484; + + --line: #e3ddce; + --line-strong: #d6cfbd; + + --accent: #2a2622; + --accent-ink: #100e0b; + --accent-wash: rgba(35, 32, 27, 0.08); + --accent-contrast: #faf7f0; + + --danger: #b4453a; + --danger-ink: #963327; + + --shadow-page: 0 1px 2px rgba(35, 32, 27, 0.06), 0 14px 30px rgba(35, 32, 27, 0.09); + --shadow-pop: 0 8px 24px rgba(35, 32, 27, 0.14); +} + +.app { + position: relative; + width: 1440px; + height: 900px; + display: flex; + flex-direction: column; + overflow: hidden; + background: var(--shell); + color: var(--ink); + font-family: var(--font-ui); + font-size: var(--t-3); + line-height: normal; + text-align: left; +} + +.app svg { + flex: none; + fill: none; + stroke: currentColor; + stroke-width: 1.6; + stroke-linecap: round; + stroke-linejoin: round; +} + +/* Title bar ---------------------------------------------------------------- */ + +.titlebar { + flex: none; + position: relative; + z-index: 45; + height: var(--titlebar-h); + display: grid; + grid-template-columns: 1fr auto 1fr; + align-items: center; + padding: 0 14px 0 84px; + background: var(--shell); + border-bottom: 1px solid var(--line); +} + +.lights { + position: absolute; + left: 20px; + top: 50%; + transform: translateY(-50%); + display: flex; + gap: 8px; +} +.lights i { + width: 12px; + height: 12px; + border-radius: 50%; +} +.lights i:nth-child(1) { + background: #ff5f57; +} +.lights i:nth-child(2) { + background: #febc2e; +} +.lights i:nth-child(3) { + background: #28c840; +} + +.titlebar .lead { + grid-column: 1; + justify-self: start; + display: flex; + gap: 4px; +} +.titlebar .doc-title { + grid-column: 2; + font-size: var(--t-2); + letter-spacing: 0.02em; + color: var(--ink-soft); +} +.titlebar .actions { + grid-column: 3; + justify-self: end; + display: flex; + gap: 4px; +} + +.icon-btn { + width: 30px; + height: 30px; + display: grid; + place-items: center; + border-radius: var(--r-sm); + color: var(--ink-soft); +} +.icon-btn[data-on="true"] { + color: var(--accent); + background: var(--accent-wash); + box-shadow: inset 0 0 0 1px var(--line-strong); +} + +.body { + flex: 1; + display: flex; + min-height: 0; +} + +/* Sidebar ------------------------------------------------------------------ */ + +.sidebar { + width: var(--pane-sidebar); + flex: none; + background: var(--sidebar); + border-right: 1px solid var(--line); + display: flex; + flex-direction: column; + padding: 6px 0 10px; + overflow: hidden; +} + +.brand { + display: flex; + align-items: center; + gap: 6px; + padding: 12px 18px 16px; + color: var(--ink-faint); +} +.brand .back-label { + font-size: var(--t-3); + font-weight: 600; + color: var(--ink-soft); +} + +.cover-item { + position: relative; + display: flex; + align-items: center; + gap: 11px; + margin: 2px 10px 4px; + padding: 8px 12px; + border-radius: var(--r-sm); + color: var(--ink-soft); + font-size: var(--t-3); +} +.cover-item .title { + font-weight: 500; +} +.cover-item svg { + color: var(--ink-faint); +} + +.add-page { + margin: 2px 12px; + padding: 8px 10px; + display: flex; + align-items: center; + gap: 8px; + border-radius: var(--r-sm); + font-size: var(--t-3); + color: var(--ink-faint); +} + +.chapters { + list-style: none; + margin: 6px 0 0; + padding: 0 10px; + flex: 1; + overflow: hidden; +} + +.nav-label { + padding: 4px 22px; + margin: 0; + font-size: var(--t-1); + font-weight: 600; + letter-spacing: 0.14em; + text-transform: uppercase; + color: var(--ink-faint); +} +.nav-section + .nav-section { + margin-top: 12px; +} + +.chapter { + position: relative; + display: flex; + align-items: baseline; + gap: 11px; + padding: 8px 12px; + border-radius: var(--r-sm); + color: var(--ink-soft); +} +.chapter[data-active="true"] { + background: var(--paper); + color: var(--ink); + box-shadow: 0 1px 2px rgba(35, 32, 27, 0.05); +} +.chapter[data-active="true"]::before { + content: ""; + position: absolute; + left: -10px; + top: 8px; + bottom: 8px; + width: 3px; + background: var(--accent); + border-radius: 0 2px 2px 0; +} +.chapter .num { + font-size: var(--t-1); + color: var(--ink-faint); + width: 13px; + font-variant-numeric: tabular-nums; +} +.chapter[data-active="true"] .num { + color: var(--accent); +} +.chapter .text { + flex: 1; + min-width: 0; + display: flex; + flex-direction: column; + gap: 2px; +} +.chapter .title { + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.chapter .meta { + font-size: var(--t-1); + letter-spacing: 0.01em; + color: var(--ink-faint); +} +.chapter .grip { + display: grid; + place-items: center; + align-self: center; + margin: 0 -5px 0 -6px; + color: var(--ink-faint); + opacity: 0; +} +.chapter[data-active="true"] .grip { + opacity: 0.55; +} + +.add-chapter { + margin: 8px 10px 4px; + width: calc(100% - 20px); + padding: 9px 12px; + display: flex; + align-items: center; + justify-content: center; + gap: 8px; + border-radius: var(--r-sm); + color: var(--ink-faint); + border: 1px dashed var(--line-strong); +} + +/* Writing surface ---------------------------------------------------------- */ + +.editor-pane { + flex: 1; + min-width: 0; + background: var(--paper); + overflow: hidden; + display: flex; + flex-direction: column; + align-items: center; +} + +.sheet { + width: 100%; + max-width: var(--measure); + padding: 104px 24px 200px; +} +.sheet[data-width="wide"] { + max-width: 62em; +} + +.chapter-opener { + text-align: center; + margin: 0 0 3.4rem; +} +.chapter-num { + font-family: var(--font-ui); + font-size: var(--t-1); + font-weight: 600; + letter-spacing: 0.28em; + text-transform: uppercase; + color: var(--ink-faint); + margin: 0; +} +.chapter-title { + font-family: var(--font-heading); + font-weight: 500; + font-size: 31px; + line-height: 1.16; + letter-spacing: -0.01em; + margin: 15px 0 0; +} + +.prose { + font-family: var(--font-book); + color: var(--ink); + font-optical-sizing: auto; +} +.prose p { + font-size: 19px; + line-height: 1.68; + margin: 0; + text-align: justify; + hyphens: auto; + -webkit-hyphens: auto; +} +.prose p[data-indent="true"] { + text-indent: 1.3em; +} +.prose .first::first-letter { + float: left; + font-size: 3.1em; + line-height: 0.82; + padding: 0.05em 0.09em 0 0; + font-weight: 500; +} + +.caret { + display: inline-block; + width: 1.5px; + height: 1.05em; + background: var(--ink); + vertical-align: -0.18em; + margin-left: 1px; +} + +/* Proofing ----------------------------------------------------------------- */ + +.proof-mark { + border-radius: 2px; + text-decoration: underline; + text-decoration-thickness: 2px; + text-underline-offset: 3px; + -webkit-box-decoration-break: clone; + box-decoration-break: clone; +} +.proof-mark.sev-error { + background: rgba(180, 69, 58, 0.13); + text-decoration-color: #b4453a; +} +.proof-mark.sev-warn { + background: rgba(168, 119, 24, 0.16); + text-decoration-color: #9c6e16; +} +.proof-mark.sev-suggest { + background: rgba(47, 110, 79, 0.13); + text-decoration-color: #2f6e4f; +} + +.proof-anchor { + position: relative; +} +.proof-pop { + position: absolute; + top: calc(100% + 6px); + left: 50%; + transform: translateX(-50%); + z-index: 50; + width: 264px; + padding: 8px; + background: var(--paper); + border: 1px solid var(--line); + border-radius: var(--r-md); + box-shadow: var(--shadow-pop); + font-family: var(--font-ui); + text-align: left; + text-indent: 0; +} +.proof-pop-kind { + display: inline-block; + margin: 0 0 6px 2px; + padding: 2px 8px; + border-radius: 999px; + font-size: var(--t-1); + font-weight: 600; + letter-spacing: 0.04em; + text-transform: uppercase; +} +.proof-pop-kind.sev-error { + background: rgba(180, 69, 58, 0.14); + color: var(--danger-ink); +} +.proof-pop-msg { + display: block; + padding: 2px 4px 8px; + font-size: var(--t-2); + color: var(--ink-soft); + line-height: 1.4; +} +.proof-pop-suggestions { + display: flex; + flex-wrap: wrap; + gap: 4px; +} +.proof-suggestion { + padding: 5px 10px; + border-radius: var(--r-sm); + background: var(--accent-wash); + color: var(--ink); + font-size: var(--t-2); + font-weight: 600; +} +.proof-suggestion.is-hover { + background: var(--accent); + color: var(--accent-contrast); +} +.proof-pop-actions { + display: flex; + gap: 4px; + margin-top: 8px; + padding-top: 8px; + border-top: 1px solid var(--line); +} +.proof-action { + flex: 1; + padding: 6px 8px; + border-radius: var(--r-sm); + font-size: var(--t-1); + color: var(--ink-soft); + text-align: center; +} + +/* Preview dock ------------------------------------------------------------- */ + +.dock { + width: var(--pane-dock); + flex: none; + background: var(--shell); + border-left: 1px solid var(--line); + overflow: hidden; + padding: 26px 28px 80px; +} +.dock-head { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 18px; +} +.dock-head .label { + font-size: var(--t-1); + font-weight: 600; + letter-spacing: 0.14em; + text-transform: uppercase; + color: var(--ink-faint); +} +.dock-head .meta { + font-size: var(--t-1); + color: var(--ink-faint); + font-variant-numeric: tabular-nums; +} +.dock-tools { + display: flex; + align-items: center; + gap: 10px; +} +.trim-select { + display: inline-flex; + align-items: center; + gap: 7px; + font-family: var(--font-ui); + font-size: var(--t-2); + color: var(--ink-soft); + background: var(--raised); + border: 1px solid var(--line); + border-radius: var(--r-sm); + padding: 4px 8px; +} +.trim-select svg { + width: 11px; + height: 11px; + color: var(--ink-faint); +} + +.dock-col { + display: flex; + flex-direction: column; + gap: 16px; +} +.page { + position: relative; + background: #fffefb; + border: 1px solid var(--line); + border-radius: 2px; + box-shadow: var(--shadow-page); + aspect-ratio: 6 / 9; + padding: 11% 12% 13%; + overflow: hidden; + flex: none; +} +.page .p-opener { + text-align: center; + margin-bottom: 15px; +} +.page .p-num { + font-family: var(--font-ui); + font-size: 6px; + font-weight: 600; + letter-spacing: 0.24em; + text-transform: uppercase; + color: var(--ink-faint); + margin: 0; +} +.page .p-title { + font-family: var(--font-heading); + font-size: 12px; + margin: 5px 0 0; +} +.page p { + font-family: var(--font-book); + font-size: 6.6px; + line-height: 1.5; + text-align: justify; + hyphens: auto; + -webkit-hyphens: auto; + margin: 0; + color: #2b2720; +} +.page p[data-indent="true"] { + text-indent: 1.2em; +} +.page .folio { + position: absolute; + left: 12%; + right: 12%; + bottom: 5.5%; + text-align: center; + font-family: var(--font-book); + font-size: 6px; + color: var(--ink-faint); +} + +/* Export preview panel ----------------------------------------------------- */ + +.overlay { + position: absolute; + inset: 0; + z-index: 55; + background: rgba(35, 32, 27, 0.28); + -webkit-backdrop-filter: blur(2px); + backdrop-filter: blur(2px); +} + +.preview-panel { + position: absolute; + z-index: 56; + display: flex; + flex-direction: column; + background: var(--paper); + border: 1px solid var(--line); + border-radius: var(--r-lg); + box-shadow: var(--shadow-pop); + overflow: hidden; +} +.preview-bar { + flex: none; + height: 52px; + display: flex; + align-items: center; + gap: 10px; + padding: 0 12px; + background: var(--paper); + border-bottom: 1px solid var(--line); +} +.preview-title { + flex: 1; + min-width: 0; + font-family: var(--font-book); + font-size: 15px; + color: var(--ink); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.preview-count { + font-size: var(--t-2); + color: var(--ink-faint); + font-variant-numeric: tabular-nums; +} +.preview-zoom { + display: flex; + align-items: center; + gap: 2px; +} +.preview-zoom span { + width: 44px; + text-align: center; + font-size: var(--t-2); + color: var(--ink-soft); + font-variant-numeric: tabular-nums; +} +.btn-primary { + font-family: var(--font-ui); + font-size: var(--t-3); + font-weight: 500; + padding: 9px 20px; + border-radius: var(--r-sm); + background: var(--accent); + color: var(--accent-contrast); +} +.preview-stage { + flex: 1; + overflow: hidden; + padding: 28px; + background: var(--shell); +} +.preview-col { + display: flex; + flex-direction: column; + align-items: center; + gap: 16px; +} +.preview-page { + position: relative; + flex: none; + width: 460px; + aspect-ratio: 6 / 9; + background: #fff; + border-radius: 2px; + box-shadow: var(--shadow-page); + overflow: hidden; + padding: 11% 12% 13%; + color: #23201b; +} +.preview-page .p-opener { + text-align: center; + margin-bottom: 22px; +} +.preview-page .p-num { + font-family: var(--font-ui); + font-size: 8.4px; + font-weight: 600; + letter-spacing: 0.24em; + text-transform: uppercase; + color: #9b9484; + margin: 0; +} +.preview-page .p-title { + font-family: var(--font-heading); + font-size: 16.8px; + font-weight: 500; + margin: 7px 0 0; +} +.preview-page p { + font-family: var(--font-book); + font-size: 9.2px; + line-height: 1.62; + text-align: justify; + hyphens: auto; + -webkit-hyphens: auto; + margin: 0; + color: #2b2720; +} +.preview-page p[data-indent="true"] { + text-indent: 1.2em; +} +.preview-page .first::first-letter { + float: left; + font-size: 3.1em; + line-height: 0.82; + padding: 0.05em 0.09em 0 0; + font-weight: 500; +} +.preview-page .folio { + position: absolute; + left: 12%; + right: 12%; + bottom: 5.5%; + text-align: center; + font-family: var(--font-book); + font-size: 8.4px; + color: #b3ab9c; +} + +/* Library ------------------------------------------------------------------ */ + +.library { + position: relative; + width: 1440px; + height: 900px; + overflow: hidden; + background: var(--shell); + color: var(--ink); + font-family: var(--font-ui); + font-size: var(--t-3); + line-height: normal; + text-align: left; +} +.library svg { + flex: none; + fill: none; + stroke: currentColor; + stroke-width: 1.6; + stroke-linecap: round; + stroke-linejoin: round; +} +.library-head { + position: relative; + height: 44px; + display: flex; + align-items: center; + justify-content: flex-end; + padding: 0 14px; +} +.shelf { + max-width: 1040px; + margin: 0 auto; + padding: 26px 44px 80px; + display: grid; + grid-template-columns: repeat(auto-fill, minmax(168px, 1fr)); + gap: 28px; +} +.card { + position: relative; + aspect-ratio: 5 / 7; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 9px; + padding: 22px 18px; + text-align: center; + border-radius: 4px; +} +.card-book { + background: var(--paper); + border: 1px solid var(--line); + box-shadow: var(--shadow-page); +} +.card-title { + font-family: var(--font-book); + font-size: 20px; + font-weight: 500; + line-height: 1.18; + color: var(--ink); +} +.card-author { + font-size: var(--t-2); + color: var(--ink-soft); +} +.card-meta { + position: absolute; + left: 14px; + right: 14px; + bottom: 14px; + font-size: var(--t-1); + color: var(--ink-faint); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +.card-action { + background: transparent; + border: 1px dashed var(--line-strong); + color: var(--ink-faint); + font-size: var(--t-3); +} diff --git a/appstore/screenshots/src/frame-1.html b/appstore/screenshots/src/frame-1.html new file mode 100644 index 0000000..03a83f4 --- /dev/null +++ b/appstore/screenshots/src/frame-1.html @@ -0,0 +1,155 @@ + + + + +Margin App Store frame 1 + + + + + + + +
+

Write

+

A calm writing studio.

+

Your words, set in real typography, with nothing else asking for attention.

+ +
+
+
+ + + + + The Quiet Hours + + + + + + + + + + +
+ +
+ + +
+
+
+

Chapter 1

+

The Long Morning

+
+
+

+ The best hours are the ones nobody asks for. They arrive before the day has decided + what it wants from you, and they leave without ceremony, and what happens in them is + almost never what you planned. +

+

+ I have kept the same desk for eleven years. It is not a good desk. One leg is + shorter than the others and I have never fixed it, because the small tilt reminds + me, every time I sit down, that the work is not going to be perfect either, and that + this has never once stopped anybody. +

+

+ What I have learned about working slowly is that it is not slow. It only looks that + way from the outside. From inside it feels like the only speed at which anything + holds together. +

+

+ There is a particular hour, somewhere between the first coffee and the second, when + the work stops feeling like a performance. Nothing on the page has changed. What has + changed is that you have stopped listening for applause. +

+

+ The trick, if there is one, is to start before you are ready. Readiness is a story + you tell yourself about a future morning that will be calmer than this one, and it + will not be. The calm is something you make, badly at first, out of whatever the day + has left lying around. +

+

+ I write the first sentence standing up. I do not know why this works and I have + stopped asking. Somewhere in the business of not sitting down the sentence loses its + self-consciousness, and by the time I take the chair there is something on the page + to argue with. +

+
+
+
+
+
+
+
+ + diff --git a/appstore/screenshots/src/frame-2.html b/appstore/screenshots/src/frame-2.html new file mode 100644 index 0000000..4a1d31f --- /dev/null +++ b/appstore/screenshots/src/frame-2.html @@ -0,0 +1,268 @@ + + + + +Margin App Store frame 2 + + + + + + + +
+

Preview

+

Typeset as you write.

+

A live page preview shows every sentence exactly as it will come out in print.

+ +
+
+
+ + + + + The Quiet Hours + + + + + + + + + + +
+ +
+ + +
+
+
+

Chapter 1

+

The Long Morning

+
+
+

+ The best hours are the ones nobody asks for. They arrive before the day has decided + what it wants from you, and they leave without ceremony, and what happens in them is + almost never what you planned. +

+

+ I have kept the same desk for eleven years. It is not a good desk. One leg is + shorter than the others and I have never fixed it, because the small tilt reminds + me, every time I sit down, that the work is not going to be perfect either, and that + this has never once stopped anybody. +

+

+ What I have learned about working slowly is that it is not slow. It only looks that + way from the outside. From inside it feels like the only speed at which anything + holds together. +

+

+ There is a particular hour, somewhere between the first coffee and the second, when + the work stops feeling like a performance. Nothing on the page has changed. What has + changed is that you have stopped listening for applause. +

+

+ The trick, if there is one, is to start before you are ready. Readiness is a story + you tell yourself about a future morning that will be calmer than this one, and it + will not be. The calm is something you make, badly at first, out of whatever the day + has left lying around. +

+

+ I write the first sentence standing up. I do not know why this works and I have + stopped asking. Somewhere in the business of not sitting down the sentence loses its + self-consciousness, and by the time I take the chair there is something on the page + to argue with. +

+
+
+
+ +
+
+ Preview + + 1 of 4 + + 6 × 9 in + + + +
+ +
+
+
+

Chapter 1

+

The Long Morning

+
+

+ The best hours are the ones nobody asks for. They arrive before the day has decided + what it wants from you, and they leave without ceremony, and what happens in them is + almost never what you planned. +

+

+ I have kept the same desk for eleven years. It is not a good desk. One leg is + shorter than the others and I have never fixed it, because the small tilt reminds + me, every time I sit down, that the work is not going to be perfect either, and that + this has never once stopped anybody. +

+

+ What I have learned about working slowly is that it is not slow. It only looks that + way from the outside. From inside it feels like the only speed at which anything + holds together. +

+

+ There is a particular hour, somewhere between the first coffee and the second, when + the work stops feeling like a performance. Nothing on the page has changed. What has + changed is that you have stopped listening for applause. +

+

+ The trick, if there is one, is to start before you are ready. Readiness is a story + you tell yourself about a future morning that will be calmer than this one, and it + will not be. The calm is something you make, badly at first, out of whatever the day + has left lying around. +

+

+ I write the first sentence standing up. I do not know why this works and I have + stopped asking. Somewhere in the business of not sitting down the sentence loses its + self-consciousness, and by the time I take the chair there is something on the page + to argue with. +

+

+ Everything after that is argument. You put a thing down, you read it back, you tell + it that it is not quite true, and you try again. Nine times out of ten the second + attempt is worse. The tenth is why anybody does this. +

+

+ By eleven the light has moved across the desk and the day has started making its + claims. I stop where I am, mid-sentence if I can manage it, because a sentence left + open is a door left open, and tomorrow I will walk straight back through it. +

+

+ None of this is a method. A method is something you can hand to somebody else, and I + have tried, and what they get is a description of a room they do not live in. +

+

+ What I can hand over is smaller. Sit down before the day has an opinion. Write badly + on purpose for ten minutes. Stop while it is still going well. That is the whole of + it, and it has taken me eleven years to be able to say it in three sentences. +

+

7

+
+ +
+

+ What the desk knows, and I keep forgetting, is that the work is not a mood. It does + not care whether I arrived at it happily. It only registers whether I arrived, and + how long I stayed, and whether I was honest about the sentence in front of me while + I was there. +

+

+ The second hour is quieter than the first, which nobody warns you about. You expect + momentum. What you get is a kind of patience, and it turns out that patience is + faster. +

+

+ I have never once regretted a morning spent this way. I have regretted almost every + morning spent otherwise, which is not the same as saying that I stopped having them. +

+

+ There is a version of this essay that argues for discipline, and I have read it many + times, and it has never once got me out of bed. +

+

+ The version that works is duller. Make the room boring. Put the phone in another + room, not face down on the desk, because face down on the desk is still a decision + you have to keep making. Decide once, in advance, while you are calm, and then let + the morning be simple. +

+

+ I am not a fast writer. I have watched fast writers with the particular envy of + someone who has done the arithmetic and knows it does not matter. Over a year the + slow ones and the quick ones arrive at roughly the same place, and the slow ones + seem to enjoy the journey more, which is not nothing. +

+

+ What I want from a morning is not very much. Two hours. One paragraph I did not have + when I sat down. The sense, at the end, that I told the truth about something small. +

+
+
+
+
+
+
+
+ + diff --git a/appstore/screenshots/src/frame-3.html b/appstore/screenshots/src/frame-3.html new file mode 100644 index 0000000..83019fc --- /dev/null +++ b/appstore/screenshots/src/frame-3.html @@ -0,0 +1,161 @@ + + + + +Margin App Store frame 3 + + + + + + + +
+

Proof

+

Proofed on your machine.

+

Spelling and grammar as you type, checked on the Mac in front of you. Nothing is sent away to be read.

+ +
+
+
+ + + + + The Quiet Hours + + + + + + + + + + +
+ +
+ + +
+
+
+

Chapter 2

+

On Interruption

+
+
+

+ An interruption costs more than the minutes it takes. It costs the shape of the + thought you were holding, which does not come back in the same form, and + occassionally + Spelling + “occassionally” may be misspelled + + occasionally + occasional + + + Ignore + Remember + + + does not come back at all. +

+

+ So I have made the room boring. There is nothing on these walls. The window faces a + brick wall two metres away, which sounds like a punishment and is in fact a gift, + because there is nothing out there to look at and so I look at the page. +

+

+ People assume the point is discipline. It is not. The point is to make the right + thing the easiest thing, so that discipline is never called upon, because discipline + is a small and unreliable fuel and it runs out + at around eleven in the morning. +

+

+ There is a thing that happens when you + let the morning break in half. The second half is never the first half continued. It + is a new morning, shorter, with the good hour already spent, and you will spend it + trying to remember what you were about to say. +

+

+ I keep a card by the door with one line on it, in my own handwriting, so that I + cannot pretend somebody else set the rule: nothing before the work. Not the post, + not the news, not the small useful errand that would only take a minute. +

+
+
+
+
+
+
+
+ + diff --git a/appstore/screenshots/src/frame-4.html b/appstore/screenshots/src/frame-4.html new file mode 100644 index 0000000..903997b --- /dev/null +++ b/appstore/screenshots/src/frame-4.html @@ -0,0 +1,241 @@ + + + + +Margin App Store frame 4 + + + + + + + +
+

Publish

+

Export PDF and EPUB.

+

Read every page before you save it. Send the PDF to a printer, or the EPUB to any store.

+ +
+
+
+ + + + + The Quiet Hours + + + + + + + + + + +
+ +
+ + +
+
+
+

Chapter 1

+

The Long Morning

+
+
+

+ The best hours are the ones nobody asks for. They arrive before the day has decided + what it wants from you, and they leave without ceremony, and what happens in them is + almost never what you planned. +

+
+
+
+ +
+
+ Preview + + 1 of 4 + + 6 × 9 in + + + +
+
+
+
+

Chapter 1

+

The Long Morning

+
+

+ The best hours are the ones nobody asks for. They arrive before the day has decided + what it wants from you, and they leave without ceremony, and what happens in them is + almost never what you planned. +

+

+ I have kept the same desk for eleven years. It is not a good desk. One leg is + shorter than the others and I have never fixed it, because the small tilt reminds + me, every time I sit down, that the work is not going to be perfect either, and that + this has never once stopped anybody. +

+
+
+
+
+ +
+ +
+
+ + The Quiet Hours + 96 pages + + + Fit + + + Save PDF… +
+ +
+
+
+
+

Chapter 1

+

The Long Morning

+
+

+ The best hours are the ones nobody asks for. They arrive before the day has decided + what it wants from you, and they leave without ceremony, and what happens in them is + almost never what you planned. +

+

+ I have kept the same desk for eleven years. It is not a good desk. One leg is + shorter than the others and I have never fixed it, because the small tilt reminds + me, every time I sit down, that the work is not going to be perfect either, and that + this has never once stopped anybody. +

+

+ What I have learned about working slowly is that it is not slow. It only looks that + way from the outside. From inside it feels like the only speed at which anything + holds together. +

+

+ There is a particular hour, somewhere between the first coffee and the second, when + the work stops feeling like a performance. Nothing on the page has changed. What has + changed is that you have stopped listening for applause. +

+

+ The trick, if there is one, is to start before you are ready. Readiness is a story + you tell yourself about a future morning that will be calmer than this one, and it + will not be. The calm is something you make, badly at first, out of whatever the day + has left lying around. +

+

+ I write the first sentence standing up. I do not know why this works and I have + stopped asking. Somewhere in the business of not sitting down the sentence loses its + self-consciousness, and by the time I take the chair there is something on the page + to argue with. +

+

+ Everything after that is argument. You put a thing down, you read it back, you tell + it that it is not quite true, and you try again. Nine times out of ten the second + attempt is worse. The tenth is why anybody does this. +

+

7

+
+ +
+

+ By eleven the light has moved across the desk and the day has started making its + claims. I stop where I am, mid-sentence if I can manage it, because a sentence left + open is a door left open, and tomorrow I will walk straight back through it. +

+

+ None of this is a method. A method is something you can hand to somebody else, and I + have tried, and what they get is a description of a room they do not live in. +

+

+ What I can hand over is smaller. Sit down before the day has an opinion. Write badly + on purpose for ten minutes. Stop while it is still going well. +

+
+
+
+
+
+
+
+ + diff --git a/appstore/screenshots/src/frame-5.html b/appstore/screenshots/src/frame-5.html new file mode 100644 index 0000000..8bcef46 --- /dev/null +++ b/appstore/screenshots/src/frame-5.html @@ -0,0 +1,105 @@ + + + + +Margin App Store frame 5 + + + + + + + +
+

Yours

+

No account, no subscription.

+

Nothing to sign in to. Every piece is a plain file on your own Mac, yours to move, copy and back up.

+ +
+
+
+ + +
+ +
+ + + New project + + + + Import EPUB + + + + The Quiet Hours + Elena Marsh + Edited just now + + + Field Notes + Elena Marsh + Edited yesterday + + + The Tuesday Letter + Elena Marsh + Edited 3 days ago + + + Small Repairs + Elena Marsh + Edited 6 days ago + + + A Year of Mondays + Elena Marsh + Edited Aug 12, 2026 + + + Nothing on These Walls + Elena Marsh + Edited Aug 4, 2026 + + + Twelve Openings + Elena Marsh + Edited Jul 28, 2026 + + + Rooms I Have Worked In + Elena Marsh + Edited Jul 9, 2026 + + + The Long Way Round + Elena Marsh + Edited Jun 30, 2026 + + + Working Slowly + Elena Marsh + Edited Jun 2, 2026 + + + Every Second Sentence + Elena Marsh + Edited May 19, 2026 + + + Letters I Did Not Send + Elena Marsh + Edited Apr 27, 2026 + + + The Brick Wall + Elena Marsh + Edited Mar 14, 2026 + +
+
+
+
+ + diff --git a/appstore/screenshots/src/frame.css b/appstore/screenshots/src/frame.css new file mode 100644 index 0000000..2a9bdfd --- /dev/null +++ b/appstore/screenshots/src/frame.css @@ -0,0 +1,111 @@ +/* Shared surface for every Mac App Store frame. Rendered at exactly 2560x1600, + so every length here is a real output pixel. */ + +:root { + --paper: #fcfbf7; + --shell: #f1ece2; + --ink: #23201b; + --ink-soft: #6b6458; + --ink-faint: #9b9484; + --line-strong: #d6cfbd; + + --font-ui: "Hanken Grotesk", ui-sans-serif, system-ui, -apple-system, sans-serif; + --font-book: "Literata", Georgia, "Times New Roman", serif; +} + +* { + box-sizing: border-box; +} + +html, +body { + margin: 0; + padding: 0; +} + +body { + width: 2560px; + height: 1600px; + overflow: hidden; + background: + radial-gradient(128% 92% at 50% -14%, var(--paper) 0%, rgba(252, 251, 247, 0) 62%), + var(--shell); + color: var(--ink); + font-family: var(--font-ui); + -webkit-font-smoothing: antialiased; + text-rendering: optimizeLegibility; +} + +.frame { + width: 2560px; + height: 1600px; + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + overflow: hidden; + padding: 120px 100px 116px; +} + +.eyebrow { + margin: 0 0 24px; + font-size: 22px; + font-weight: 650; + letter-spacing: 0.2em; + text-transform: uppercase; + color: var(--ink-faint); +} + +.headline { + margin: 0; + font-family: var(--font-book); + font-size: 92px; + font-weight: 560; + line-height: 1.06; + letter-spacing: -0.022em; + color: var(--ink); + font-optical-sizing: auto; +} + +.support { + margin: 30px 0 0; + max-width: 1700px; + font-size: 32px; + line-height: 1.5; + color: var(--ink-soft); + text-wrap: balance; +} + +/* The app window sitting on the surface, never full bleed. The window itself is + live markup authored at the app's own 1440x900 (see app.css) and scaled up to + fill this well, so the type stays vector-sharp instead of being resampled. */ +.shot { + position: relative; + width: 1600px; + height: 1000px; + flex: none; + margin-top: 100px; + border-radius: 22px; + background: var(--paper); + overflow: hidden; + box-shadow: + 0 2px 4px rgba(35, 32, 27, 0.06), + 0 10px 26px -8px rgba(35, 32, 27, 0.14), + 0 46px 96px -26px rgba(35, 32, 27, 0.36); +} + +.shot__scale { + width: 1440px; + height: 900px; + transform: scale(1.1111111111); + transform-origin: 0 0; +} + +.shot::after { + content: ""; + position: absolute; + inset: 0; + border-radius: 22px; + box-shadow: inset 0 0 0 1px var(--line-strong); + pointer-events: none; +}