/* mark · web draft surface
 *
 * Every value here comes from ../../DESIGN.md, which is itself a mirror of
 * Theme.swift. If you are tempted to invent a colour, it belongs in DESIGN.md
 * first or it does not belong.
 *
 * The palette is `hearth`: near-black ground, one ember accent. Chosen because
 * this is a page you write on for an hour, not a screen you check.
 */

:root {
  /* hearth */
  --bg:        #08090A;
  --bg-elev:   #0F1311;
  --card:      #0F1011;
  --card2:     #0B0C0D;
  --ink:       #F6F4F0;
  --ink2:      #9AA39C;
  --ink3:      #79837C;
  --ink4:      #5E6762;
  --line:      rgba(255, 255, 255, 0.05);
  --line-strong: rgba(255, 255, 255, 0.07);
  --ember:     #E2724C;

  --r-sm: 12px;
  --r-md: 14px;
  --r-lg: 20px;

  --s-xs: 5px;
  --s-sm: 8px;
  --s-md: 14px;
  --s-lg: 22px;
  --s-xl: 36px;

  --display: "Playfair Display", Georgia, "Times New Roman", serif;
  --body: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  --rail: 288px;
  --measure: 42rem;

}

* { box-sizing: border-box; }

/* The `hidden` attribute is a UA rule (`display: none`), so ANY author rule
 * that sets `display` silently defeats it — and three of the blocks this app
 * toggles (`.pair`, `.blank`, `.rail`) set one. Caught in the browser with the
 * empty state rendering underneath a draft that was open. Declare the override
 * once, at the top, rather than remembering it per component. */
[hidden] { display: none !important; }

html, body {
  height: 100%;
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--body);
  font-size: 17px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
input, textarea { font: inherit; color: inherit; background: none; border: 0; }
input:focus, textarea:focus, button:focus-visible { outline: none; }
button:focus-visible { box-shadow: 0 0 0 2px var(--ember); border-radius: var(--r-sm); }

/* An eyebrow is mono, uppercase, wide. It never carries prose. */
.eyebrow {
  font-family: var(--mono);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink4);
}

/* ── shell ─────────────────────────────────────────────────────────────── */

.app { display: grid; grid-template-columns: var(--rail) 1fr; height: 100%; }

/* ── the rail ──────────────────────────────────────────────────────────── */

.rail {
  border-right: 1px solid var(--line);
  background: var(--card2);
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.rail__head {
  padding: var(--s-xl) var(--s-lg) var(--s-md);
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-sm);
}

/* 2026-09-24 · the logo is the app icon itself — black tile, cream script m,
 * the ember page-turn corner (Mark: "make sure our new logo is used"). It
 * replaces the alpha-mask glyph that painted only the letter. */
.logo {
  width: 30px;
  height: 30px;
  flex: none;
  border-radius: 22.37%;
  display: block;
}

.rail__new {
  font-family: var(--mono);
  font-size: 0.75rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ember);
  padding: var(--s-xs) var(--s-sm);
  border-radius: 9999px;
  transition: background 140ms ease;
}
.rail__new:hover { background: rgba(226, 114, 76, 0.12); }

.rail__list { overflow-y: auto; padding: var(--s-sm) var(--s-sm) var(--s-xl); flex: 1; min-height: 0; }

.draft {
  display: block;
  width: 100%;
  text-align: left;
  padding: var(--s-md);
  border-radius: var(--r-md);
  border: 1px solid transparent;
  transition: background 120ms ease, border-color 120ms ease;
}
.draft + .draft { margin-top: 2px; }
.draft:hover { background: var(--card); }
.draft[aria-current="true"] { background: var(--card); border-color: var(--line-strong); }

/* v2 · 2026-08-25 · sans. Mark: *"less serif — even the column on the
 * left-hand side uses serif. We don't need that. If you wanna use serif, use
 * it for a date, but that's it."* A serif on every list row makes the list
 * compete with the page you are writing, and the page should win. */
.draft__title {
  font-family: var(--body);
  font-weight: 500;
  font-size: 0.9375rem;
  line-height: 1.3;
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.draft__meta {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.04em;
  color: var(--ink4);
  margin-top: var(--s-xs);
}
.draft[aria-current="true"] .draft__meta { color: var(--ink3); }

.rail__empty {
  padding: var(--s-lg) var(--s-md);
  color: var(--ink4);
  font-size: 0.9375rem;
  line-height: 1.5;
}

/* ── the page ──────────────────────────────────────────────────────────── */

.page { display: flex; flex-direction: column; min-width: 0; min-height: 0; }

.page__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-md);
  padding: var(--s-lg) var(--s-xl);
  border-bottom: 1px solid var(--line);
}

/* One accent per screen, on the live thing: here it is the save state. */
.sync { white-space: nowrap; font-family: var(--mono); font-size: 0.6875rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink4); }
.sync[data-state="saving"] { color: var(--ember); }
.sync[data-state="error"]  { color: var(--ember); }

.page__actions { display: flex; align-items: center; gap: var(--s-md); }

.ghost {
  white-space: nowrap;
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink4);
  padding: var(--s-xs) var(--s-sm);
  border-radius: 9999px;
  transition: color 120ms ease, background 120ms ease;
}
.ghost:hover { color: var(--ink2); background: rgba(255,255,255,0.04); }
.ghost--danger:hover { color: var(--ember); background: rgba(226,114,76,0.1); }

.sheet { flex: 1; overflow-y: auto; min-height: 0; }

.sheet__inner {
  max-width: var(--measure);
  margin: 0 auto;
  padding: var(--s-xl) var(--s-lg) calc(var(--s-xl) * 2);
}

/* ── the leaf ──────────────────────────────────────────────────────────────
 *
 * Mark: *"the website doesn't look premium at all. In fact, it looks like it
 * was just rushed."*
 *
 * He is right and the reason is structural, not decorative: there was no
 * page. Words sat directly on the near-black ground with nothing around them,
 * so the writing had no edges, the wide margins read as neglect rather than
 * matting, and the whole screen was a text field pretending to be a document.
 *
 * The app's own vocabulary already has the answer — an elevated panel on the
 * canvas, one hairline, generous padding. Same object, same rules. The height
 * is the point too: it holds most of the viewport whether you have written
 * three words or three hundred, so the surface stops shrinking to fit its
 * contents and starts behaving like paper. */
.leaf {
  background: var(--bg-elev);
  border: 1px solid var(--line);
  border-radius: 24px;
  padding: calc(var(--s-xl) * 1.15) calc(var(--s-xl) * 1.15) var(--s-xl);
  min-height: min(72vh, 46rem);
  display: flex;
  flex-direction: column;
  min-width: 0;
}

/* ── the date hero ─────────────────────────────────────────────────────────
 *
 * Mark: *"can you give the web app the same hero that we have in the app,
 * kind of the date? It's kind of like our theme, right? It's our thing, our
 * shtick."*
 *
 * It is, and it is law 2 of the build plan: the big serif date is the app's
 * signature. It says which app you are in before you have read a word, and
 * this page had nothing doing that job.
 *
 * It sits ABOVE the leaf rather than on it, so the paper stays clean and the
 * date reads as the day the page belongs to — which it is: the draft's own
 * date, not today's.
 *
 * This is also the ONE serif left on the page, per Mark's rule — *"if you
 * wanna use serif, use it for a date, but that's it."* And it is deliberately
 * the opposite call from the title, which shrank for privacy: a title is
 * yours, and a date is not a secret from anyone who can see a calendar. */
.hero { padding: 0 var(--s-xs) var(--s-lg); }

.hero__weekday {
  font-family: var(--mono);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--ember);
  margin-bottom: 6px;
}

.hero__date {
  font-family: var(--display);
  font-style: italic;
  font-weight: 500;
  /* 58px on the phone; here it scales with the window rather than towering
   * over a laptop or getting lost on a 32-inch. */
  font-size: clamp(2.5rem, 3.4vw, 3.5rem);
  line-height: 0.86;
  letter-spacing: -0.015em;
  color: var(--ink);
}

/* v2 · 2026-08-25 · **a title nobody across the room can read.**
 *
 * This was 3.25rem — 52px of italic serif, legible from the far side of a
 * café. Mark: *"the title is way too big. If you're writing a moment, do you
 * want everyone around you to see it? I don't think so."*
 *
 * That is a privacy argument, not a taste one, and it wins: a journal is the
 * one kind of writing where the type must NOT broadcast. It is now sans at
 * 1.5rem — a heading, not a poster — and the date above it carries the serif
 * for the whole page. */
.title {
  display: block;
  width: 100%;
  font-family: var(--body);
  font-weight: 600;
  font-size: 1.5rem;
  line-height: 1.14;
  letter-spacing: -0.015em;
  margin-bottom: var(--s-lg);
  resize: none;
  overflow: hidden;
}
.title::placeholder { color: var(--ink4); opacity: 1; }

.body {
  display: block;
  width: 100%;
  font-family: var(--body);
  font-size: 1.0625rem;
  line-height: 1.75;
  /* Grows with the leaf rather than setting its own floor — the paper is the
   * thing with a size now, and the field simply fills it. */
  flex: 1;
  min-height: 12rem;
  resize: none;
  overflow: hidden;
}
.body::placeholder { color: var(--ink4); opacity: 1; }

/* v2 · 2026-09-19 · names the lead the moment the rule catches it — the
 * phone shows this by styling the line itself, which a textarea cannot do. */
.leadhint {
  margin-top: var(--s-sm);
  font-family: var(--mono, ui-monospace, monospace);
  font-size: 0.6875rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink4);
}

.count {
  margin-top: var(--s-xl);
  padding-top: var(--s-md);
  border-top: 1px solid var(--line);
}

/* ── empty state ───────────────────────────────────────────────────────── */

.blank {
  flex: 1;
  display: grid;
  place-items: center;
  text-align: center;
  padding: var(--s-xl);
}
.blank__inner { max-width: 26rem; }
.blank h2 {
  font-family: var(--body);
  font-weight: 600;
  font-size: 1.5rem;
  letter-spacing: -0.01em;
  line-height: 1.2;
  margin: var(--s-md) 0 var(--s-sm);
}
.blank p { color: var(--ink3); margin: 0 0 var(--s-lg); }

.btn {
  display: inline-block;
  background: var(--ember);
  color: #fff;
  font-weight: 600;
  padding: var(--s-md) var(--s-xl);
  border-radius: 9999px;
  transition: filter 120ms ease;
}
.btn:hover { filter: brightness(1.06); }

/* ── pairing ───────────────────────────────────────────────────────────── */

.pair {
  min-height: 100%;
  display: grid;
  grid-template-rows: auto 1fr auto;
  padding: var(--s-lg) var(--s-xl);
  gap: var(--s-lg);
}
.pair__brand { display: flex; align-items: center; gap: var(--s-md); }
.pair__logo { width: 44px; height: 44px; border-radius: 22.37%; display: block; }
.pair__tag {
  font-family: var(--display);
  font-style: italic;
  font-weight: 500;
  font-size: 1.375rem;
  color: var(--ink);
}
.pair__main {
  align-self: center;
  justify-self: center;
  display: grid;
  grid-template-columns: minmax(0, 30rem) 17rem;
  gap: calc(var(--s-xl) * 1.5);
  align-items: center;
  width: min(64rem, 100%);
  justify-content: center;
}
.pair__card {
  width: 100%;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: calc(var(--s-xl) * 1.1);
}
.pair__fine { font-size: 0.8125rem !important; color: var(--ink4) !important; margin: var(--s-md) 0 0 !important; }
.pair__qr { display: flex; flex-direction: column; align-items: center; text-align: center; gap: var(--s-sm); }
.pair__qrtitle { font-weight: 600; font-size: 1.0625rem; margin-top: var(--s-sm); }
.pair__qrnote { color: var(--ink3); font-size: 0.875rem; max-width: 16rem; }
.pair__foot { display: flex; justify-content: center; }

/* A QR is only a QR on white with a quiet margin; the logo sits in the middle
 * (error correction H leaves room for it), like Day One's. */
.qr {
  position: relative;
  width: 15rem;
  height: 15rem;
  padding: 0.9rem;
  background: #fff;
  border-radius: var(--r-md);
}
.qr svg { width: 100%; height: 100%; display: block; }
.qr__logo {
  position: absolute;
  left: 50%; top: 50%;
  width: 22%; height: 22%;
  transform: translate(-50%, -50%);
  border-radius: 22.37%;
  box-shadow: 0 0 0 4px #fff;
}
.qr[data-state="done"] svg, .qr[data-state="done"] .qr__logo { opacity: 0.12; }
.qr--small { width: 4.5rem; height: 4.5rem; padding: 0.3rem; border-radius: 8px; }
.getapp {
  display: flex; align-items: center; gap: var(--s-md);
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: var(--s-md) var(--s-lg);
}
.getapp__title { font-weight: 600; font-size: 0.9375rem; }
.getapp__link { color: var(--ember); font-size: 0.875rem; text-decoration: none; }
.getapp__link:hover { text-decoration: underline; }

@media (max-width: 860px) {
  .pair { padding: var(--s-lg) var(--s-md); }
  .pair__main { grid-template-columns: 1fr; gap: var(--s-xl); }
  .pair__qr { order: -1; }
  .pair__qr .qr { width: 12rem; height: 12rem; }
}
.pair h1 {
  font-family: var(--body);
  font-weight: 600;
  font-size: 1.75rem;
  letter-spacing: -0.015em;
  line-height: 1.15;
  margin: var(--s-md) 0 var(--s-sm);
}
.pair p { color: var(--ink3); margin: 0 0 var(--s-lg); font-size: 0.9375rem; }

.pair__input {
  width: 100%;
  font-family: var(--mono);
  font-size: 1.0625rem;
  letter-spacing: 0.08em;
  padding: var(--s-md);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  background: var(--card2);
  margin-bottom: var(--s-md);
}
.pair__input:focus { border-color: var(--ember); }
.pair__err { color: var(--ember); font-size: 0.875rem; min-height: 1.25rem; margin-top: var(--s-sm); }

/* ── narrow ────────────────────────────────────────────────────────────── */

@media (max-width: 860px) {
  .app { grid-template-columns: 1fr; }
  .rail { display: none; }
  .app[data-rail="open"] { grid-template-columns: 1fr; }
  .app[data-rail="open"] .rail { display: flex; }
  .app[data-rail="open"] .page { display: none; }
  .title { font-size: 2.25rem; }
  .sheet__inner { padding: var(--s-xl) var(--s-lg) calc(var(--s-xl) * 2); }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; }
}

/* v2 · the six-digit field. Big, centred and widely tracked because it is
 * being read off a phone and typed here — the two are a pair, and the phone
 * shows it at the same weight. */
.pair__input--code {
  text-align: center;
  font-size: 2rem;
  letter-spacing: 0.32em;
  text-indent: 0.32em;   /* re-centre: tracking adds a trailing gap */
  padding: var(--s-lg) var(--s-md);
}

/* ── photos in a draft ─────────────────────────────────────────────────── */

.shots {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: var(--s-sm);
  margin-top: var(--s-lg);
}

.shot { position: relative; aspect-ratio: 4 / 3; }
.shot img {
  width: 100%; height: 100%;
  object-fit: cover;
  border-radius: var(--r-md);   /* photos are clipped, never boxed */
  display: block;
}
.shot__x {
  position: absolute; top: 6px; right: 6px;
  width: 26px; height: 26px;
  display: grid; place-items: center;
  border-radius: 9999px;
  background: rgba(8, 9, 10, 0.72);
  color: var(--ink);
  font-size: 15px; line-height: 1;
  backdrop-filter: blur(6px);
  opacity: 0;
  transition: opacity 120ms ease;
}
.shot:hover .shot__x, .shot__x:focus-visible { opacity: 1; }

.tools {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-md);
  margin-top: var(--s-xl);
  padding-top: var(--s-md);
  border-top: 1px solid var(--line);
}
.tools .count { margin: 0; padding: 0; border: 0; }

/* Drop target · the whole sheet, so you can let go anywhere. */
.sheet.dropping { outline: 2px dashed var(--ember); outline-offset: -12px; }


/* ── the wide desk ─────────────────────────────────────────────────────────
 *
 * Mark, writing on a 27" and a 32": *"the space we have to write on there is
 * extremely large. Just a lot of dead, empty space."*
 *
 * The tempting fix — let the text fill the width — is the wrong one: a 1600px
 * line is unreadable, and this is a page you write on for an hour. The measure
 * stays. What changes is that the margin stops being empty: past 1400px the
 * photos and the tools move OUT of the writing column and into the space
 * beside it, so the width carries something instead of nothing, and the
 * pictures are visible while you write rather than below the fold.
 *
 * Under 1400px nothing moves — the aside is simply the next thing down the
 * page, which is what it always was. */
@media (min-width: 1400px) {
  .sheet__inner {
    display: grid;
    max-width: calc(var(--measure) + 21rem);
    grid-template-columns: minmax(0, var(--measure)) 16rem;
    /* Named, not implicit. Adding the hero to a bare two-column grid dropped
       it into cell 1 and pushed the leaf into the margin column — the kind of
       break that only shows up on the width you were not looking at. */
    grid-template-areas:
      "hero ."
      "leaf side";
    column-gap: var(--s-xl);
    align-items: start;
  }
  .hero { grid-area: hero; }
  .leaf { grid-area: leaf; }
  /* The aside sits on the desk BESIDE the paper, not on it — pinned there,
   * the way you would put the photographs next to what you are writing. */
  .side { grid-area: side; position: sticky; top: var(--s-xl); }
  .side .shots { margin-top: 0; }
}

/* The aside's own stacking, at every width. */
.side { display: flex; flex-direction: column; gap: var(--s-md); min-width: 0; }

/* ── the date, as a control ────────────────────────────────────────────────
 *
 * The hero was a `div`; it is a `button` now, and it has to keep looking like
 * the page's signature rather than turning into a form field. So the only
 * resting difference is the cursor and a hairline that appears on hover —
 * enough to say "this does something", not enough to make the date look like
 * a control that is waiting for you. */
button.hero__date {
  display: block;
  padding: 0;
  border: 0;
  background: none;
  text-align: left;
  cursor: pointer;
  border-bottom: 2px solid transparent;
  transition: border-color 140ms ease, color 140ms ease;
}
button.hero__date:hover,
button.hero__date:focus-visible { border-bottom-color: rgba(226, 114, 76, 0.55); }
/* Once you have chosen a day, the date is carrying a decision rather than
 * just reporting one, and it says so quietly and permanently. */
button.hero__date[data-edited="true"] { border-bottom-color: rgba(226, 114, 76, 0.55); }

/* v2 · 2026-08-25 · **always there.**
 *
 * This was hidden until you hovered the hero, which was my mistake and a
 * plain one: Mark went looking for a way to set when something happened and
 * reported it missing — while it was sitting under his cursor, invisible.
 *
 * An affordance nobody can see does not exist. It is quiet enough at 10px in
 * ink4 that it costs nothing to leave up, and it is the line he described
 * unprompted: "TODAY · 3:42 PM, not prominent". */
.hero__hint {
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink4);
  margin-top: 10px;
  transition: color 140ms ease;
}
.hero:hover .hero__hint { color: var(--ink3); }

/* The real input never shows — the hero opens it via showPicker(). It cannot
 * be `display: none`, or Safari refuses to open a picker for it. */
.hero__input {
  position: absolute;
  width: 1px; height: 1px;
  opacity: 0;
  pointer-events: none;
}
.hero { position: relative; }

/* `unpair` is the one destructive-adjacent action that is NOT about the page
 * you are looking at, so it steps back behind close and delete. */
.ghost--quiet { color: var(--ink4); opacity: 0.65; }
.ghost--quiet:hover { opacity: 1; }

/* ── Quick Mark ────────────────────────────────────────────────────────────
 *
 * A field, a rule under it, and nothing else. It is not a card and it has no
 * button, because both would make it look like a place you go to do something
 * — and the whole argument for it is that it is a place you do NOT go. One
 * sentence, Enter, back to work. */
.quick {
  padding: 0 var(--s-lg) var(--s-md);
  border-bottom: 1px solid var(--line);
  margin-bottom: var(--s-sm);
}

.quick__input {
  display: block;
  width: 100%;
  font-family: var(--body);
  font-size: 0.9375rem;
  line-height: 1.5;
  color: var(--ink);
  padding: var(--s-sm) 0;
  border: 0;
  background: none;
  /* Grows with the thought, then stops. Past about five lines the honest
   * answer is the real editor, not a taller box — which is what ⇧enter is
   * for. `resize: none` because a drag handle in a capture field is an
   * invitation to treat it as a document. */
  resize: none;
  overflow-y: auto;
  max-height: 7.5rem;
}
.quick__input::placeholder { color: var(--ink4); opacity: 1; }

.quick__hint {
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink4);
  min-height: 1em;
  opacity: 0;
  transition: opacity 140ms ease, color 140ms ease;
}
/* The hint is invisible until you are in the field — an instruction nobody is
 * following is just furniture. It stays up for the moment after a capture,
 * because "kept" is the only receipt this feature gives you. */
.quick:focus-within .quick__hint,
.quick__hint[data-state] { opacity: 1; }
.quick__hint[data-state="kept"]  { color: var(--ember); }
.quick__hint[data-state="error"] { color: var(--ember); }

/* The open page was kept into Mark on the phone. A quiet notice, not an
   alarm — nothing has gone wrong, the draft simply has a home now. */
.gone {
  margin: 0 0 18px;
  padding: 10px 14px;
  border-radius: 12px;
  font-size: 0.82rem;
  letter-spacing: 0.02em;
  color: var(--ink-2, #6b6b73);
  background: rgba(226, 114, 76, 0.10);
  border: 1px solid rgba(226, 114, 76, 0.28);
}

/* The countdown turns warm only in the last week — before that it is a fact,
   not a warning, and a permanent alarm is one you stop seeing. */
[data-urgent="true"] { color: #C0603C; }

/* Threads are chosen on the phone. This says the capability exists without
   pretending the choosing can happen here — quiet, the weight of a caption,
   sitting under the tools where you finish rather than where you start. */

/* ───────────────────────────────────────────────────────────────────────────
   53a · the writing desk
   "It's a phone screen stretched across a monitor." The card, the top-bar
   weighting and the wrapped meta rail were the three things making it read
   that way.
   ─────────────────────────────────────────────────────────────────────── */

/* The card is gone: one measure, no box, no fixed height. A tall empty box
   promises more than eight words can fill. */
.leaf--open {
  background: none;
  border: 0;
  box-shadow: none;
  padding: 0;
  max-width: 620px;
}
.leaf--open .title,
.leaf--open .body { background: none; }

/* Shortcuts, printed. The vocabulary is the reason to be at a keyboard. */
.kbd {
  display: inline-block;
  margin-left: 7px;
  padding: 1px 5px;
  border: 1px solid rgba(255,255,255,0.16);
  border-radius: 5px;
  font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: 0.66rem;
  line-height: 1.5;
  color: var(--ink-3, #8a8a92);
  vertical-align: 1px;
}

/* The rail's ··· — where the two irreversible things now live. */
.railmenu { position: relative; margin-left: auto; }
.railmenu__btn {
  background: none; border: 0; cursor: pointer;
  padding: 2px 8px; border-radius: 8px;
  color: var(--ink-3, #8a8a92);
  font-size: 1rem; line-height: 1;
}
.railmenu__btn:hover { color: var(--ink, #EDEFEC); background: rgba(255,255,255,0.06); }
.railmenu__pop {
  position: absolute; top: 26px; right: 0; z-index: 40;
  min-width: 214px; padding: 6px;
  background: #14151A;
  border: 1px solid rgba(255,255,255,0.10);
  border-radius: 12px;
  box-shadow: 0 18px 44px rgba(0,0,0,0.55);
}
.railmenu__item {
  display: block; width: 100%; text-align: left;
  background: none; border: 0; cursor: pointer;
  padding: 9px 10px; border-radius: 8px;
  font-size: 0.82rem; color: var(--ink-2, #b9b9c0);
}
.railmenu__item:hover { background: rgba(255,255,255,0.07); color: var(--ink, #EDEFEC); }
/* Destructive, and it looks it — but at the BOTTOM of a menu, not the top of
   a page. "Never three peer-weight words in a top bar." */
.railmenu__item--danger { color: #C0603C; }
.railmenu__item--danger:hover { background: rgba(192,96,60,0.12); color: #E2724C; }
.railmenu__item--quiet { color: var(--ink-3, #8a8a92); font-size: 0.76rem; }

/* Days left on a rail item: a bare number, ember under a week. */
.draft__days {
  margin-left: 8px;
  font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: 0.66rem;
  letter-spacing: 0.06em;
  color: var(--ink-3, #8a8a92);
}
.draft__days[data-urgent="true"] { color: #C0603C; }

/* ───────────────────────────────────────────────────────────────────────────
   54a · three answers, dismissible
   ─────────────────────────────────────────────────────────────────────── */

/* The banner. One sentence, above the writing, gone once acknowledged. */
/* Inside `.page`, not `.app` — `.app` is the rail/page grid, and a child of
   it becomes a COLUMN. The banner belongs above the writing, not beside it. */
.firstrun {
  display: flex; justify-content: center;
  padding: 14px 22px 0;
  flex: 0 0 auto;
}
.firstrun__inner {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  max-width: 860px; width: 100%;
  padding: 11px 16px;
  border-radius: 12px;
  background: rgba(226,114,76,0.09);
  border: 1px solid rgba(226,114,76,0.26);
}
.firstrun__eyebrow {
  font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: 0.62rem; letter-spacing: 0.22em; text-transform: uppercase;
  color: #E2724C;
}
.firstrun__line { flex: 1 1 260px; font-size: 0.84rem; color: var(--ink-2, #b9b9c0); }
.firstrun__ok {
  background: none; border: 1px solid rgba(255,255,255,0.18);
  border-radius: 999px; cursor: pointer;
  padding: 5px 14px; font-size: 0.76rem; color: var(--ink-2, #b9b9c0);
}
.firstrun__ok:hover { border-color: rgba(255,255,255,0.34); color: var(--ink, #EDEFEC); }

/* The panel. Same anatomy as the phone's settings guide — mono eyebrow,
   serif item names, gray body, one ember link — so it reads as the same
   document rather than a new one. */
.how {
  position: fixed; inset: 0; z-index: 60;
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
  background: rgba(4,5,6,0.72);
}
.how__panel {
  position: relative;
  width: min(520px, 100%);
  max-height: 86vh; overflow: auto;
  padding: 34px 34px 28px;
  background: #101116;
  border: 1px solid rgba(255,255,255,0.10);
  border-radius: 20px;
  box-shadow: 0 30px 80px rgba(0,0,0,0.6);
}
.how__close {
  position: absolute; top: 16px; right: 16px;
  background: none; border: 0; cursor: pointer;
  font-size: 0.9rem; color: var(--ink-3, #8a8a92);
}
.how__close:hover { color: var(--ink, #EDEFEC); }
.how__eyebrow {
  font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: 0.64rem; letter-spacing: 0.24em; text-transform: uppercase;
  color: #E2724C; margin-bottom: 12px;
}
.how__title {
  margin: 0 0 26px;
  font-family: 'Playfair Display', Georgia, serif;
  font-weight: 400; font-size: 1.85rem; line-height: 1.12;
  color: var(--ink, #EDEFEC);
}
.how__item { margin-bottom: 20px; }
.how__name {
  font-family: 'Playfair Display', Georgia, serif;
  font-size: 1.06rem; color: var(--ink, #EDEFEC); margin-bottom: 5px;
}
.how__body { margin: 0; font-size: 0.85rem; line-height: 1.5; color: var(--ink-2, #b9b9c0); }
.how__foot {
  margin: 26px 0 0; padding-top: 18px;
  border-top: 1px solid rgba(255,255,255,0.08);
  font-size: 0.8rem; line-height: 1.5; color: var(--ink-3, #8a8a92);
}
.how__link { color: #E2724C; }

/* ═══════════════════════════════════════════════════════════════════════════
   56a · left-anchored · the date becomes a masthead
   "The fix isn't more content, it's structure that reaches the edges."
   ═══════════════════════════════════════════════════════════════════════ */

/* Three real columns. The measure is the only fixed thing in the middle;
   the gap absorbs the width, and the rail is where the extra pixels go. */
.sheet {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 300px;
  gap: 48px;
  align-items: start;
  padding: 34px 40px 64px 62px;   /* 62px from the sidebar — where reading starts */
  overflow: auto;
  min-height: 0;
}
.desk { max-width: 640px; }        /* long lines are genuinely harder to read */

/* The date does the work the empty space was failing to do. */
.hero__date { font-size: clamp(52px, 6.4vw, 78px); line-height: 0.96; }
.hero__weekday { margin-bottom: 6px; }

/* An empty well, so it is obvious photos can go here. */
.photowell {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 6px; margin-top: 26px;
  width: 128px; height: 96px;
  background: none; cursor: pointer;
  border: 1px dashed rgba(255,255,255,0.16);
  border-radius: 14px;
  color: var(--ink-3, #8a8a92);
}
.photowell:hover { border-color: rgba(255,255,255,0.30); color: var(--ink-2, #b9b9c0); }
.photowell__plus { font-size: 1.1rem; line-height: 1; }
.photowell__label {
  font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: 0.64rem; letter-spacing: 0.14em; text-transform: uppercase;
}

/* ── the sidebar header, unpacked ─────────────────────────────────────────
   Row one: the mark and the ··· at opposite edges. Row two: a real button
   with the shortcut inside it, not trailing behind the word. */
.rail__id {
  display: flex; align-items: center; justify-content: space-between;
  padding: 16px 16px 10px;
}
.rail__new {
  display: flex; align-items: center; justify-content: space-between;
  width: calc(100% - 32px); height: 40px;
  margin: 0 16px 14px; padding: 0 12px;
  background: rgba(255,255,255,0.05);
  border: 1px solid rgba(255,255,255,0.10);
  border-radius: 10px; cursor: pointer;
  color: var(--ink, #EDEFEC); font-size: 0.84rem;
}
.rail__new:hover { background: rgba(255,255,255,0.09); }
.rail__newlabel { font-weight: 500; }
.rail__new .kbd { margin-left: 0; }

.rail__label {
  display: flex; justify-content: space-between; align-items: center;
  padding: 14px 18px 8px;
  font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: 0.62rem; letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--ink-3, #8a8a92);
  border-top: 1px solid rgba(255,255,255,0.06);
}
.rail__foot {
  margin-top: auto;
  padding: 12px 18px;
  border-top: 1px solid rgba(255,255,255,0.06);
  font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: 0.62rem; letter-spacing: 0.08em;
  color: var(--ink-3, #8a8a92);
}

/* ── the right rail ───────────────────────────────────────────────────── */
.side {
  display: flex; flex-direction: column; gap: 20px;
  position: sticky; top: 0;
}
.side__foot {
  margin-top: 8px; padding-top: 16px;
  border-top: 1px solid rgba(255,255,255,0.08);
}
.side__meta {
  display: flex; gap: 10px; flex-wrap: wrap;
  font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: 0.64rem; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--ink-3, #8a8a92);
}

/* ── "how the web works" — ATTACHED, not floating ──────────────────────────
   Mark: *"why did you make it a pop-up? … should have been on the right-hand
   side, connected to the editor with an X."* A modal covers the work; a panel
   beside it can be read while you write. */
.how {
  position: static; inset: auto; display: block;
  padding: 20px 20px 18px;
  background: rgba(255,255,255,0.035);
  border: 1px solid rgba(255,255,255,0.09);
  border-radius: 14px;
}
.how__panel { all: unset; }
.how__head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 12px;
}
.how__close { position: static; }
.how__title { font-size: 1.4rem; margin-bottom: 20px; }
.how__item { margin-bottom: 16px; }
.how__name { font-size: 1rem; }
.how__body { font-size: 0.8rem; }
.how__foot { margin-top: 18px; padding-top: 14px; font-size: 0.76rem; }

/* Narrow windows: the rail drops under the writing rather than squeezing it. */
@media (max-width: 1080px) {
  .sheet { grid-template-columns: minmax(0, 1fr); gap: 28px; padding: 28px 24px 56px; }
  .side { position: static; }
}

/* The 1400px block above still names grid areas for the OLD `.sheet__inner`
   structure, and `.side { grid-area: side }` was placing the rail into an
   area this grid does not define — which collapsed the writing column to
   zero width. `.sheet__inner` no longer exists; these reclaim placement for
   the two children that do. */
.sheet > .desk { grid-column: 1; width: 100%; }
.sheet > .side { grid-area: auto; grid-column: 2; position: sticky; top: 0; }
@media (max-width: 1080px) {
  .sheet > .desk,
  .sheet > .side { grid-column: 1; position: static; }
}

/* ── what's new ─────────────────────────────────────────────────────────
   Same anatomy as the how panel — it reuses .how__head / .how__item /
   .how__name / .how__body deliberately, so the rail reads as one piece of
   furniture with two faces rather than two competing designs. Only what is
   genuinely new to this panel is defined here. */
.news {
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 16px 16px 6px;
  margin-bottom: 18px;
  background: var(--card);
}
.news__stream + .news__stream { margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--line); }
.news__where {
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink4);
  margin-bottom: 10px;
}
.news__when {
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.08em;
  color: var(--ember);
  margin-bottom: 2px;
}

/* 2026-09-24 · the privacy cover — the page's own ground, one word, one line.
   Not a blur: a blur of a journal is still a journal to someone standing close. */
.veil {
  position: fixed; inset: 0; z-index: 1000;
  display: grid; place-items: center;
  background: var(--bg);
  cursor: pointer;
}
.veil[hidden] { display: none; }
.veil__inner { text-align: center; padding: var(--s-xl); }
.veil__logo {
  width: 72px; height: 72px; border-radius: 22.37%;
  display: block; margin: 0 auto var(--s-lg);
}
.veil__mark {
  font-family: var(--display); font-style: italic; font-weight: 500;
  font-size: 48px; line-height: 1.1; color: var(--ink);
}
.veil__tag {
  margin-top: var(--s-xs);
  font-family: var(--body); font-weight: 600;
  font-size: 1.125rem; color: var(--ink);
}
.veil__hint {
  margin-top: var(--s-xl);
  font-family: var(--body); font-weight: 600; font-size: 0.875rem;
  color: var(--ink3);
}

/* ── today's prompt (2026-09-24) ───────────────────────────────────────── */
.prompt {
  border: 1px solid var(--line);
  background: var(--card);
  border-radius: var(--r-lg);
  padding: var(--s-lg);
  margin-bottom: var(--s-lg);
}
.prompt__eyebrow {
  font-family: var(--mono); font-size: 0.6875rem; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--ember);
}
.prompt__q {
  font-family: var(--display); font-style: italic; font-weight: 500;
  font-size: 1.5rem; line-height: 1.3; color: var(--ink);
  margin: var(--s-sm) 0 var(--s-md);
}
.prompt__row { display: flex; align-items: center; justify-content: space-between; gap: var(--s-md); }
.prompt__use {
  color: var(--ember); border: 1px solid rgba(226, 114, 76, 0.45);
  border-radius: 9999px; padding: var(--s-xs) var(--s-md); font-weight: 500;
}
.prompt__use:hover { background: rgba(226, 114, 76, 0.12); }
.prompt__next {
  font-family: var(--mono); font-size: 0.75rem; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--ink3);
}
.prompt__next:hover { color: var(--ink); }
.letterhead {
  display: flex; align-items: flex-start; gap: var(--s-sm);
  font-family: var(--display); font-style: italic; font-size: 1.25rem;
  color: var(--ink2); margin: 0 0 var(--s-md);
}
.letterhead__x { color: var(--ink4); font-size: 0.75rem; margin-top: 0.4rem; }
.letterhead__x:hover { color: var(--ink); }

/* 2026-09-24 · "done" — putting the page away is the finishing action, so it
   reads as one (it was a grey mono ghost Mark did not see). */
.done {
  display: inline-flex; align-items: center; gap: var(--s-sm);
  background: var(--ember); color: #fff; font-weight: 600; font-size: 0.875rem;
  padding: var(--s-xs) var(--s-md); border-radius: 9999px;
  transition: filter 120ms ease;
}
.done:hover { filter: brightness(1.08); }
.done .kbd { color: rgba(255,255,255,0.8); border-color: rgba(255,255,255,0.35); background: transparent; }
