/* Nora — readable at 3am with one hand, and not embarrassing on a laptop. */

/* ══ type ══════════════════════════════════════════════════════════════════
   Fraunces, self-hosted. A linked Google font would fail whenever the phone is
   offline — which is exactly when this app has to work — so the file ships with
   the app and the service worker caches it. One variable file covers the whole
   weight range we use.
   ═════════════════════════════════════════════════════════════════════════ */
@font-face {
  font-family: 'Fraunces';
  src: url('/fonts/fraunces-latin.woff2') format('woff2');
  font-weight: 300 700;
  font-style: normal;
  font-display: swap;           /* text shows immediately in the fallback */
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193,
                 U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ══ colour ═════════════════════════════════════════════════════════════════
   Built from the "Evergreen Dreams" palette:
     #C7A491 clay   #EECFCA blush   #919682 sage   #C7CDBF light sage
     #595E48 dark olive

   The two greens carry the structure (page, borders, primary), and the clay
   and blush warm it up so it doesn't read cold or clinical. Text colours are
   pushed darker than #595E48 — that olive is right for a button, but too light
   against a pale card for body copy.

   One theme, no light/dark switch. Nothing is pure white or pure black.
   ═════════════════════════════════════════════════════════════════════════ */
:root {
  --bg:#dde1d5;         /* light sage, a shade up from #C7CDBF */
  --bg-2:#d2d8c7;       /* bottom of the page wash */
  --card:#f7f6f1;       /* warm off-white, pulled toward the clay side */
  --card-2:#e7e9dd;     /* inset fields, chips, inactive segments */
  --ink:#2b2f23;
  --ink-2:#585e4a;
  --ink-3:#8a907e;
  --line:#c7cdbf;       /* the palette's light sage, used as the hairline */
  --line-2:#dde0d3;
  --accent:#595e48;     /* the palette's dark olive */
  --accent-2:#919682;   /* the palette's sage, for secondary marks */
  --accent-ink:#f7f6f1;
  --clay:#c7a491;
  --blush:#eecfca;

  --feed:#a9765c;       /* clay, deepened enough to read on a pale card */
  --diaper:#6f7760;     /* sage, deepened */
  --pump:#9d7f85;       /* blush, deepened */
  --sleep:#6a6f5c;
  --note:#8a907e;
  --milestone:#b5817a;
  --danger:#9c4f45;

  /* The border does the definition, the shadow only lifts. */
  --shadow:0 1px 1px rgba(43,47,35,.04), 0 6px 18px -6px rgba(43,47,35,.10);
  --shadow-md:0 2px 4px rgba(43,47,35,.06), 0 12px 28px -10px rgba(43,47,35,.16);
  --shadow-lg:0 2px 4px rgba(43,47,35,.06), 0 24px 48px -12px rgba(43,47,35,.24);

  --display:'Fraunces', 'Iowan Old Style', Georgia, 'Times New Roman', serif;
  --sans:-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif;

  --ease:cubic-bezier(.32,.72,0,1);

  color-scheme: light;
}

.display, h1, .since .value, .stat .n, .prompt-card .q, .jentry h3, .timer {
  font-family: var(--display);
  font-variation-settings: 'SOFT' 28, 'WONK' 0, 'opsz' 40;
  letter-spacing: -.005em;
}

:root {
  --radius:16px; --radius-sm:11px;
  --tap:52px;                       /* nothing interactive is smaller */
  --safe-b:env(safe-area-inset-bottom, 0px);
  --rail:232px;
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

html { background:var(--bg); }
body {
  margin:0; padding:0; color:var(--ink); font-family:var(--sans);
  font-size:16px; line-height:1.45; -webkit-font-smoothing:antialiased;
  overscroll-behavior-y:none;
  /* Fixed so the wash stays put while the list scrolls under it. */
  background:linear-gradient(176deg, var(--bg) 0%, var(--bg-2) 100%) fixed;
  min-height:100vh;
}
body { padding-bottom: calc(76px + var(--safe-b)); }

button, input, select, textarea { font:inherit; color:inherit; }
button { cursor:pointer; border:0; background:none; }
a { color:var(--accent); }

/* ── layout ────────────────────────────────────────────────────────────── */
.wrap { max-width:640px; margin:0 auto; padding:0 16px; }

.topbar { display:flex; align-items:center; justify-content:space-between; padding:18px 0 10px; }
.topbar h1 { font-size:26px; font-weight:600; margin:0; line-height:1.1; }
/* The page heading is the app name on a phone (no rail to carry it) and the
   section name on desktop (the rail already says whose app this is). */
.t-section { display:none; }
.topbar .sub { font-size:12px; color:var(--ink-3); margin-top:4px;
  text-transform:uppercase; letter-spacing:.1em; font-weight:650; }
.icon-btn { width:40px; height:40px; border-radius:50%; display:grid; place-items:center;
  color:var(--ink-2); font-size:19px; }
.icon-btn:hover { background:var(--card-2); }

.card { background:var(--card); border-radius:var(--radius); box-shadow:var(--shadow);
  border:1px solid var(--line-2); padding:17px; margin-bottom:12px; }
.card h2 { font-size:11px; letter-spacing:.11em; text-transform:uppercase;
  color:var(--ink-3); margin:0 0 13px; font-weight:700; }

/* ── "time since" ──────────────────────────────────────────────────────── */
.since-grid { display:grid; grid-template-columns:repeat(3,1fr); gap:10px; }
.since { background:var(--card); border-radius:var(--radius); padding:15px 10px 13px;
  text-align:center; box-shadow:var(--shadow); border:1px solid var(--line-2);
  position:relative; overflow:hidden; }
.since::before { content:''; position:absolute; inset:0 0 auto 0; height:3px;
  background:var(--c, var(--accent)); opacity:.85; }
.since .label { font-size:10px; letter-spacing:.12em; text-transform:uppercase;
  color:var(--ink-3); font-weight:700; }
.since .value { font-size:26px; font-weight:600; margin-top:4px;
  font-variant-numeric:tabular-nums; line-height:1.12; }
.since .meta { font-size:11.5px; color:var(--ink-2); margin-top:1px; }
.since.stale .value { color:var(--danger); }

/* ── actions ───────────────────────────────────────────────────────────── */
.actions { display:grid; grid-template-columns:repeat(4,1fr); gap:10px; margin:14px 0 4px; }
.action { background:var(--card); border-radius:var(--radius); box-shadow:var(--shadow);
  border:1px solid var(--line-2); min-height:80px; display:flex; flex-direction:column;
  align-items:center; justify-content:center; gap:6px; font-size:13px; font-weight:600;
  color:var(--ink); transition:transform .08s ease, border-color .15s ease; }
.action:active { transform:scale(.96); }
.action:hover { border-color:var(--line); }
.glyph { display:inline-flex; align-items:center; justify-content:center; line-height:0; }
.ic { display:block; flex:none; }
.action .glyph { line-height:0; }
.action[data-kind="feed"] .glyph { color:var(--feed); }
.action[data-kind="diaper"] .glyph { color:var(--diaper); }
.action[data-kind="pump"] .glyph { color:var(--pump); }
.action[data-kind="more"] .glyph { color:var(--ink-2); }

/* ── stats ─────────────────────────────────────────────────────────────── */
.stats { display:flex; gap:14px; flex-wrap:wrap; }
.stat { flex:1 1 auto; min-width:68px; }
.stat .n { font-size:23px; font-weight:600; font-variant-numeric:tabular-nums;
  line-height:1.15; }
.stat .k { font-size:11px; color:var(--ink-3); margin-top:2px;
  letter-spacing:.05em; text-transform:uppercase; font-weight:600; }

/* ── timeline ──────────────────────────────────────────────────────────── */
.entry { display:flex; gap:12px; padding:12px 0; border-bottom:1px solid var(--line-2);
  align-items:flex-start; width:100%; text-align:left; }
.entry:last-child { border-bottom:0; }
.entry .dot { width:9px; height:9px; border-radius:50%; margin-top:7px; flex:none;
  background:var(--c, var(--note)); }
.entry .body { flex:1; min-width:0; }
.entry .line1 { font-size:15px; font-weight:550; }
.entry .line2 { font-size:13px; color:var(--ink-2); margin-top:1px; }
.entry .when { font-size:12.5px; color:var(--ink-3); flex:none; text-align:right;
  font-variant-numeric:tabular-nums; padding-top:2px; }
.tagrow { display:flex; gap:5px; flex-wrap:wrap; margin-top:5px; }
.tag { font-size:11px; padding:2px 8px; border-radius:99px; background:var(--card-2); color:var(--ink-2); }

.day-head { font-size:12px; letter-spacing:.06em; text-transform:uppercase; color:var(--ink-3);
  font-weight:700; margin:18px 0 6px; }

/* ── journal ───────────────────────────────────────────────────────────── */
.prompt-card {
  position:relative; overflow:hidden;
  background:
    radial-gradient(120% 100% at 0% 0%, color-mix(in srgb, var(--accent) 13%, transparent), transparent 62%),
    var(--card);
  border:1px solid var(--line-2);
  border-radius:var(--radius); box-shadow:var(--shadow); padding:22px 20px; margin-bottom:12px;
}
.prompt-card::before {
  content:''; position:absolute; inset:0 0 auto 0; height:3px;
  background:linear-gradient(90deg, var(--accent), color-mix(in srgb, var(--accent) 25%, transparent));
}
.prompt-card .eyebrow { font-size:10px; letter-spacing:.14em; text-transform:uppercase;
  color:var(--accent); font-weight:700; margin-bottom:9px; }
.prompt-card .q { font-size:22px; font-weight:500; line-height:1.28;
  position:relative; z-index:1; }
.prompt-card .prompt-actions { margin-top:18px; }
.prompt-alt { display:flex; gap:8px; margin-top:10px; justify-content:center; flex-wrap:wrap; }
.prompt-alt button { font-size:13px; color:var(--ink-2); font-weight:550; padding:6px 10px;
  border-radius:8px; min-height:34px; }
.prompt-alt button:hover { background:var(--card-2); color:var(--ink); }

.jentry { background:var(--card); border-radius:var(--radius); box-shadow:var(--shadow);
  border:1px solid var(--line-2); padding:18px; margin-bottom:12px; }
.jentry .q { font-size:13px; color:var(--accent); font-weight:650; margin-bottom:6px;
  line-height:1.35; }
.jentry h3 { margin:0 0 6px; font-size:20px; font-weight:600; line-height:1.22; }
.jentry .meta { font-size:12px; color:var(--ink-3); margin-bottom:9px;
  display:flex; gap:7px; align-items:center; flex-wrap:wrap; }
.jentry .text { font-size:15.5px; line-height:1.62; white-space:pre-wrap;
  overflow-wrap:break-word; color:var(--ink); }
.jentry .photos { display:grid; grid-template-columns:repeat(auto-fill, minmax(96px,1fr));
  gap:6px; margin-top:12px; }
.jentry .photos img { width:100%; aspect-ratio:1; object-fit:cover; border-radius:10px;
  display:block; background:var(--card-2); }
.jentry .photos.single { grid-template-columns:1fr; }
.jentry .photos.single img { aspect-ratio:4/3; }
.vis-badge { font-size:10.5px; padding:2px 7px; border-radius:99px; font-weight:650;
  background:var(--card-2); color:var(--ink-2); text-transform:uppercase; letter-spacing:.04em; }
.vis-badge[data-v="private"] { background:color-mix(in srgb, var(--milestone) 18%, transparent);
  color:var(--milestone); }

.thumbs { display:flex; gap:7px; flex-wrap:wrap; margin-top:8px; }
.thumbs .thumb { width:64px; height:64px; border-radius:9px; object-fit:cover;
  background:var(--card-2); display:block; }

/* ── nav ───────────────────────────────────────────────────────────────── */
.nav { position:fixed; left:0; right:0; bottom:0; z-index:40;
  background:color-mix(in srgb, var(--card) 94%, transparent);
  backdrop-filter:blur(16px) saturate(1.2); -webkit-backdrop-filter:blur(16px) saturate(1.2);
  border-top:1px solid var(--line); padding-bottom:var(--safe-b); }
.nav-inner { max-width:640px; margin:0 auto; display:flex; }
.nav .brand { display:none; }
.nav button { flex:1; min-height:60px; display:flex; flex-direction:column; align-items:center;
  justify-content:center; gap:4px; font-size:10.5px; font-weight:600; color:var(--ink-3);
  padding-top:3px; }
/* The active tab was only ever a colour change, which is genuinely hard to
   read at a glance. Now the icon sits in a filled pill, the label goes bold,
   and both take the accent — three signals instead of one. */
.nav button .glyph { width:44px; height:27px; border-radius:99px;
  transition:background .18s var(--ease), color .18s var(--ease); }
.nav button .lbl { transition:color .18s var(--ease), font-weight .18s; }
.nav button[aria-current="page"] { color:var(--accent); }
.nav button[aria-current="page"] .glyph {
  background:color-mix(in srgb, var(--accent) 20%, transparent); }
.nav button[aria-current="page"] .lbl { font-weight:750; }
.nav button:active .glyph { transform:scale(.93); }

/* ── sheets ────────────────────────────────────────────────────────────── */
.scrim { position:fixed; inset:0; background:rgba(18,28,19,.46);
  backdrop-filter:blur(2px); -webkit-backdrop-filter:blur(2px); z-index:50;
  opacity:0; pointer-events:none; transition:opacity .2s ease; }
.scrim.open { opacity:1; pointer-events:auto; }
.sheet { position:fixed; left:0; right:0; bottom:0; z-index:51;
  background:var(--card); border-radius:22px 22px 0 0; max-height:92vh; overflow-y:auto;
  box-shadow:var(--shadow-lg);
  -webkit-overflow-scrolling:touch; transform:translateY(100%);
  transition:transform .24s cubic-bezier(.32,.72,0,1);
  padding-bottom:calc(20px + var(--safe-b)); }
.sheet.open { transform:translateY(0); }
.sheet-inner { max-width:640px; margin:0 auto; padding:8px 16px 0; }
.grabber { width:38px; height:4px; border-radius:99px; background:var(--line); margin:8px auto 12px; }
.sheet h3 { margin:0 0 16px; font-size:24px; font-weight:600; font-family:var(--display);
  font-variation-settings:'SOFT' 28, 'WONK' 0, 'opsz' 40; line-height:1.15; }

/* ── forms ─────────────────────────────────────────────────────────────── */
.field { margin-bottom:15px; }
.field > label { display:block; font-size:11px; font-weight:700; letter-spacing:.11em;
  text-transform:uppercase; color:var(--ink-3); margin-bottom:7px; }
/* Match by exclusion rather than listing every type. An attribute selector
   does NOT match an implied default, so `input[type="text"]` misses
   `<input value="...">` entirely — which is how the name field spent its life
   189px wide. */
input:not([type="file"]):not([type="checkbox"]):not([type="radio"]):not([type="range"]),
select, textarea {
  width:100%; min-height:var(--tap); padding:12px 14px; background:var(--card-2);
  border:1.5px solid var(--line-2); border-radius:var(--radius-sm); outline:none;
  font-size:16px;                   /* 16px stops iOS zooming on focus */
  transition:border-color .14s ease, box-shadow .14s ease;
}
input:focus, select:focus, textarea:focus { border-color:var(--accent);
  box-shadow:0 0 0 3px color-mix(in srgb, var(--accent) 15%, transparent); }
textarea { min-height:84px; resize:vertical; line-height:1.5; }
textarea.tall { min-height:190px; }

/* iOS sizing of date/time controls.
   Safari on iOS gives date and datetime-local inputs a native intrinsic width
   based on their formatted value, and that width wins over `width: 100%` — so
   "Sep 14, 2026 at 8:47 AM" pushed the field straight out past the card edge.
   Chromium doesn't do this, which is why it only showed up on the phone.
   Dropping the native appearance makes them size like every other field; the
   date picker still opens on tap. Scoped to iOS so desktop keeps its native
   calendar button. */
@supports (-webkit-touch-callout: none) {
  input[type="date"], input[type="datetime-local"], input[type="time"] {
    -webkit-appearance:none; appearance:none;
    min-width:0; max-width:100%; text-align:left;
  }
}

/* Belt and braces for every engine: a form control must never be allowed to
   push past its container, whatever intrinsic width it thinks it wants. */
input, select, textarea { min-width:0; max-width:100%; }

/* Flex children default to min-width:auto, which refuses to shrink below the
   input's intrinsic width and shoves the unit label out of the row. */
.unit-input { min-width:0; }
.unit-input input { flex:1; min-width:0; }
.unit-input .unit { flex:none; }

input[type="file"] { width:100%; font-size:14px; color:var(--ink-2);
  background:var(--card-2); border:1.5px dashed var(--line); border-radius:var(--radius-sm);
  padding:13px 14px; cursor:pointer; }
input[type="file"]::file-selector-button {
  font:inherit; font-weight:600; margin-right:12px; padding:7px 14px; cursor:pointer;
  border:0; border-radius:8px; background:var(--accent); color:var(--accent-ink); }

.seg { display:flex; background:var(--card-2); border-radius:var(--radius-sm); padding:3px; gap:3px; }
.seg button { flex:1; min-height:44px; border-radius:9px; font-size:14.5px; font-weight:600;
  color:var(--ink-2); }
.seg button[aria-pressed="true"] { background:var(--card); color:var(--ink); box-shadow:var(--shadow); }

.chips { display:flex; gap:7px; flex-wrap:wrap; }
.chip { min-height:42px; padding:0 15px; border-radius:99px; background:var(--card-2);
  font-size:14.5px; font-weight:550; color:var(--ink-2); display:inline-flex; align-items:center; }
.chip[aria-pressed="true"] { background:var(--accent); color:var(--accent-ink); }

.row { display:flex; gap:10px; }
.row > * { flex:1; min-width:0; }
.quick-row .btn { min-height:86px; flex-direction:column; gap:7px; font-size:14.5px; }
.quick-row .glyph { gap:2px; }

.unit-input { display:flex; gap:8px; align-items:stretch; }
.unit-input input { flex:1; }
.unit-input .unit { display:grid; place-items:center; padding:0 14px; background:var(--card-2);
  border-radius:var(--radius-sm); font-size:14px; font-weight:650; color:var(--ink-2); min-width:58px; }

.btn { width:100%; min-height:var(--tap); border-radius:var(--radius-sm); background:var(--accent);
  color:var(--accent-ink); font-size:16px; font-weight:600; display:grid; place-items:center;
  letter-spacing:.005em; box-shadow:0 1px 2px rgba(29,42,30,.14);
  transition:filter .12s ease, transform .08s ease; }
.btn:hover { filter:brightness(1.07); }
.btn:active { filter:brightness(.93); transform:translateY(1px); }
.btn.secondary { background:var(--card-2); color:var(--ink); }
.btn.ghost { background:transparent; color:var(--ink-2); font-weight:600;
  border:1.5px solid var(--line); }
.btn.danger { background:transparent; color:var(--danger); font-weight:600; }
.btn.small { min-height:42px; font-size:14.5px; }
.btn[disabled] { opacity:.5; }
.btn-row { display:flex; gap:10px; margin-top:4px; }

/* A real switch rather than an On/Off segmented control — it reads as a
   setting you flip, not a choice you're being asked to make. */
.switch { display:flex; align-items:flex-start; gap:14px; cursor:pointer; padding:2px 0 4px; }
.switch input { position:absolute; opacity:0; width:0; height:0; }
.switch-text { flex:1; min-width:0; }
.switch-label { display:block; font-size:15.5px; font-weight:600; }
.switch-hint { display:block; font-size:12.5px; color:var(--ink-3); margin-top:3px; line-height:1.45; }
.switch-track { flex:none; width:50px; height:30px; border-radius:99px; background:var(--card-2);
  border:1px solid var(--line); position:relative; margin-top:2px;
  transition:background .18s var(--ease), border-color .18s var(--ease); }
.switch-thumb { position:absolute; top:3px; left:3px; width:22px; height:22px; border-radius:50%;
  background:var(--card); box-shadow:0 1px 3px rgba(43,47,35,.28);
  transition:transform .2s var(--ease); }
.switch input:checked ~ .switch-track { background:var(--accent); border-color:var(--accent); }
.switch input:checked ~ .switch-track .switch-thumb { transform:translateX(20px); }
.switch input:focus-visible ~ .switch-track {
  box-shadow:0 0 0 3px color-mix(in srgb, var(--accent) 28%, transparent); }

.hint { font-size:12.5px; color:var(--ink-3); margin-top:6px; line-height:1.45; }
.warn { font-size:13px; color:var(--danger);
  background:color-mix(in srgb, var(--danger) 10%, transparent);
  padding:9px 12px; border-radius:var(--radius-sm); margin-top:8px; }

/* ── timer ─────────────────────────────────────────────────────────────── */
.timer { font-size:46px; font-weight:300; text-align:center; font-variant-numeric:tabular-nums;
  letter-spacing:-.02em; margin:6px 0 12px; }

/* ── growth ─────────────────────────────────────────────────────────────── */
.birth-line { display:flex; align-items:baseline; gap:7px; flex-wrap:wrap;
  padding:0 0 14px; margin-bottom:14px; border-bottom:1px solid var(--line-2);
  font-size:15px; }
.birth-line .k { color:var(--ink-3); font-size:13px; }
.birth-line strong { font-family:var(--display);
  font-variation-settings:'SOFT' 28, 'WONK' 0, 'opsz' 40; font-size:19px; font-weight:600; }

/* ── growth (rest) ────────────────────────────────────────────────────────────── */
.chart { width:100%; height:auto; display:block; overflow:visible; }
table.data { width:100%; border-collapse:collapse; font-size:14px; }
table.data th { text-align:left; font-size:10px; text-transform:uppercase; letter-spacing:.11em;
  color:var(--ink-3); font-weight:700; padding:6px 8px 8px 0; border-bottom:1px solid var(--line); }
table.data td { padding:10px 8px 10px 0; border-bottom:1px solid var(--line-2);
  font-variant-numeric:tabular-nums; }
table.data tr:last-child td { border-bottom:0; }

/* ── motion ────────────────────────────────────────────────────────────────
   Interaction only: presses, hovers, the sheet, the toast. Everything is short
   and nothing runs on load.

   There WAS a staggered entrance animation on cards here. It's gone on
   purpose. Animating opacity/transform on every card promotes each to its own
   compositing layer, and on at least one engine the layers never composited
   back — computed style reported opacity 1 while the screen stayed empty. A
   blank screen at 3am is not a trade worth making for a flourish nobody asked
   for. Interaction transitions don't have this problem: they're transient and
   the element sits in a plain, un-promoted state at rest.
   ═════════════════════════════════════════════════════════════════════════ */
.card, .action, .since, .jentry {
  transition:transform .18s var(--ease), box-shadow .18s var(--ease),
             border-color .18s var(--ease);
}
.chip, .seg button, .icon-btn {
  transition:background .15s ease, color .15s ease, transform .1s var(--ease);
}
.chip:active, .seg button:active { transform:scale(.96); }
.entry { transition:background .14s ease; border-radius:8px; }
@media (hover: hover) {
  .entry[data-edit]:hover, .entry[data-edit-journal]:hover { background:var(--card-2); }
}
.icon-btn:active { transform:scale(.92); }

/* ── misc ──────────────────────────────────────────────────────────────── */
.empty { text-align:center; color:var(--ink-3); padding:36px 20px; font-size:14.5px; }
.center-screen { min-height:78vh; display:grid; place-items:center; text-align:center; }
.hidden { display:none !important; }

.toast { position:fixed; left:50%; bottom:calc(86px + var(--safe-b)); transform:translate(-50%,14px);
  background:var(--ink); color:var(--bg); padding:11px 18px; border-radius:99px;
  font-size:14px; font-weight:550; z-index:80; opacity:0; pointer-events:none;
  transition:opacity .2s, transform .2s; max-width:calc(100vw - 32px); text-align:center; }
.toast.show { opacity:1; transform:translate(-50%,0); }

.offline-bar { background:var(--card-2); color:var(--ink-2); font-size:12.5px; text-align:center;
  padding:6px; border-radius:99px; margin-bottom:10px; }

.lightbox { position:fixed; inset:0; z-index:90; background:rgba(0,0,0,.92);
  display:grid; place-items:center; padding:20px; }
.lightbox img { max-width:100%; max-height:88vh; border-radius:10px; display:block; }
.lightbox .cap { color:#eee; font-size:14px; text-align:center; margin-top:12px; }

/* ══ desktop ════════════════════════════════════════════════════════════════
   The bottom bar becomes a left rail, content gets room to breathe, and the
   bottom sheet becomes a centred dialog — a sheet sliding off the bottom of a
   27" monitor looks like a phone app someone forgot to finish.
   ═════════════════════════════════════════════════════════════════════════ */
@media (min-width: 900px) {
  body { padding-bottom:0; }

  /* The rail offset lives on the BODY, not on .wrap. Putting it on .wrap meant
     setting margin-left, which killed `margin: 0 auto` — so content hugged the
     rail and every extra pixel of a wide monitor piled up on the right. It also
     offset the sign-in screen, which has no rail at all, pushing that card
     off-centre. Padding the body keeps .wrap centred in whatever space is left,
     and only when the shell is actually on screen. */
  body[data-view="app"] { padding-left:var(--rail); }

  .nav { top:0; right:auto; bottom:0; width:var(--rail); border-top:0;
    border-right:1px solid var(--line); backdrop-filter:none;
    background:var(--card); padding-bottom:0; }
  .nav-inner { flex-direction:column; max-width:none; padding:22px 12px; gap:3px;
    height:100%; overflow-y:auto; }
  .nav .brand { display:block; padding:2px 12px 22px; }
  .nav .brand .name { font-family:var(--display);
    font-variation-settings:'SOFT' 28, 'WONK' 0, 'opsz' 40;
    font-size:23px; font-weight:600; line-height:1.15; }
  .nav .brand .sub { font-size:11px; color:var(--ink-3); margin-top:5px;
    text-transform:uppercase; letter-spacing:.12em; font-weight:650; }
  .nav button { flex:none; flex-direction:row; justify-content:flex-start; gap:12px;
    min-height:46px; padding:0 12px; border-radius:10px; font-size:14.5px; font-weight:600;
    position:relative; transition:background .16s var(--ease), color .16s var(--ease); }
  .nav button .glyph { font-size:17px; width:22px; text-align:center; }
  .nav button:hover { background:var(--card-2); color:var(--ink-2); }
  .nav button[aria-current="page"] { background:var(--card-2); color:var(--accent); }
  .nav button[aria-current="page"]::before {
    content:''; position:absolute; left:-12px; top:11px; bottom:11px; width:3px;
    border-radius:0 3px 3px 0; background:var(--accent);
  }
  .nav button[aria-current="page"] .glyph { transform:none; }

  .wrap { margin:0 auto; max-width:1080px; padding:0 40px 72px; }

  /* The rail already says whose app this is, so the page heading names the
     section instead of repeating her name. */
  .topbar { padding:34px 0 18px; }
  .topbar h1 { font-size:30px; }
  .t-mobile, .t-mobile-sub { display:none; }
  .t-section { display:block; }

  .since-grid { gap:14px; }
  .since { padding:20px 14px 18px; }
  .since .value { font-size:31px; }
  .actions { grid-template-columns:repeat(4,1fr); gap:14px; margin:18px 0 6px; }
  .action { min-height:100px; font-size:14px; }
  .action .glyph { font-size:26px; }

  .deck { column-count:2; column-gap:16px; margin-top:16px; }
  .deck > * { break-inside:avoid; margin-bottom:16px; }
  .card { padding:20px; }

  /* Prose keeps a readable measure. A journal entry running the full width of a
     wide window is ~160 characters a line, which nobody reads. */
  .reading { max-width:680px; }

  /* Cards lift slightly on hover — enough to feel alive under a cursor,
     not enough to be noise. Touch devices never see this. */
  @media (hover: hover) {
    .card.tappable:hover, .action:hover, .since:hover {
      transform:translateY(-1px); box-shadow:var(--shadow-md); border-color:var(--line);
    }
  }

  .sheet { left:50%; right:auto; bottom:auto; top:50%; width:min(620px, 92vw);
    max-height:86vh; border-radius:20px; padding-bottom:22px;
    transform:translate(-50%,-46%) scale(.985); opacity:0;
    transition:transform .24s var(--ease), opacity .18s ease; }
  .sheet.open { transform:translate(-50%,-50%) scale(1); opacity:1; }
  .sheet-inner { padding:22px 26px 0; }
  .grabber { display:none; }

  .toast { bottom:34px; left:calc(50% + var(--rail) / 2); }
  .jentry .photos { grid-template-columns:repeat(auto-fill, minmax(120px,1fr)); }
}

/* Bigger monitors get more columns rather than more empty margin. */
@media (min-width: 1500px) {
  .wrap { max-width:1440px; }
  .deck { column-count:3; }
  .since-grid { gap:16px; }
  .actions { gap:16px; }
}

@media (min-width: 2000px) {
  .wrap { max-width:1680px; }
  /* A 4K screen still shouldn't stretch a row of four buttons across a metre
     of glass — cap them and let the rest of the width go to the card columns. */
  .actions { max-width:1100px; }
  .since-grid { max-width:1100px; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition:none !important; animation:none !important; }
}
