/* bujo — tasks on one page, events on a calendar.
   Light is "paper": warm off-white, dot grid, ink. Dark is the same page at
   night. Every colour is a token on :root so the two themes stay in step. */

:root {
  --paper: #faf7f0;
  --card: #fffdf8;
  --ink: #191713;
  --ink-2: #4e4840;
  --dim: #9b9287;
  --hair: #e7e0d4;
  --hair-2: #f0eae0;
  --dot: rgba(25, 23, 19, 0.11);
  --accent: #d2662c;
  --accent-soft: rgba(210, 102, 44, 0.12);
  --good: #4f8a4c;
  --good-soft: rgba(79, 138, 76, 0.14);
  --drop: #a8452f;
  --star: #d99a24;
  --veil: rgba(25, 23, 19, 0.34);
  --lift-1: 0 1px 2px rgba(25, 23, 19, 0.05);
  --lift-2: 0 8px 30px rgba(25, 23, 19, 0.13);
  --lift-3: 0 -6px 40px rgba(25, 23, 19, 0.16);
  --bar: rgba(250, 247, 240, 0.86);

  --fs: 1; /* text-size multiplier, set from the menu */
  --sans: ui-rounded, -apple-system, BlinkMacSystemFont, "SF Pro Rounded", "Segoe UI",
    Inter, system-ui, sans-serif;
  --tap: 44px;
  --safe-b: env(safe-area-inset-bottom, 0px);
  --safe-t: env(safe-area-inset-top, 0px);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --paper: #0f0e0d;
    --card: #191715;
    --ink: #f0eae0;
    --ink-2: #bdb4a8;
    --dim: #837b71;
    --hair: #2a2724;
    --hair-2: #211f1c;
    --dot: rgba(240, 234, 224, 0.09);
    --accent: #f09154;
    --accent-soft: rgba(240, 145, 84, 0.16);
    --good: #77b26f;
    --good-soft: rgba(119, 178, 111, 0.16);
    --drop: #d4705a;
    --star: #e8b850;
    --veil: rgba(0, 0, 0, 0.55);
    --lift-1: 0 1px 2px rgba(0, 0, 0, 0.4);
    --lift-2: 0 8px 30px rgba(0, 0, 0, 0.5);
    --lift-3: 0 -6px 40px rgba(0, 0, 0, 0.6);
    --bar: rgba(15, 14, 13, 0.84);
  }
}

:root[data-theme="dark"] {
  --paper: #0f0e0d;
  --card: #191715;
  --ink: #f0eae0;
  --ink-2: #bdb4a8;
  --dim: #837b71;
  --hair: #2a2724;
  --hair-2: #211f1c;
  --dot: rgba(240, 234, 224, 0.09);
  --accent: #f09154;
  --accent-soft: rgba(240, 145, 84, 0.16);
  --good: #77b26f;
  --good-soft: rgba(119, 178, 111, 0.16);
  --drop: #d4705a;
  --star: #e8b850;
  --veil: rgba(0, 0, 0, 0.55);
  --lift-1: 0 1px 2px rgba(0, 0, 0, 0.4);
  --lift-2: 0 8px 30px rgba(0, 0, 0, 0.5);
  --lift-3: 0 -6px 40px rgba(0, 0, 0, 0.6);
  --bar: rgba(15, 14, 13, 0.84);
}

* {
  box-sizing: border-box;
  -webkit-tap-highlight-color: transparent;
}

html {
  font-size: calc(16px * var(--fs));
}

html,
body {
  margin: 0;
  height: 100%;
  overscroll-behavior-y: none;
}

body {
  background: var(--paper);
  color: var(--ink);
  font: 400 1.0625rem/1.45 var(--sans);
  -webkit-font-smoothing: antialiased;
  display: flex;
  flex-direction: column;
  min-height: 100dvh;
  position: relative; /* the dot grid is bound to the page, not the viewport */
}

button,
input,
textarea {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
}
button { cursor: pointer; }

/* .toast/.sheet set display, which would otherwise beat [hidden] */
[hidden] { display: none !important; }

svg { fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }

/* The dot grid of a real bullet-journal page, fixed behind everything. */
.grid-bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  background-image: radial-gradient(var(--dot) 1.1px, transparent 1.2px);
  background-size: 23px 23px;
  background-position: 11px 11px;
  /* fades out under the sticky header and the composer, so both read clean
     while the page between them keeps the grid */
  --fade: linear-gradient(to bottom, transparent 0, #000 13%, #000 90%, transparent 100%);
  -webkit-mask-image: var(--fade);
  mask-image: var(--fade);
}

/* ── header ─────────────────────────────────────────────────────────── */

#head {
  position: sticky;
  top: 0;
  z-index: 30;
  padding: calc(var(--safe-t) + 6px) 12px 0;
  background: var(--bar);
  backdrop-filter: saturate(1.6) blur(14px);
  -webkit-backdrop-filter: saturate(1.6) blur(14px);
  border-bottom: 1px solid transparent;
  transition: border-color 0.2s;
}
#head.stuck { border-bottom-color: var(--hair); }

.head-row {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: var(--tap);
}
.spacer { flex: 1; }

/* ── the three pages ────────────────────────────────────────────────── */

/* Index | Journal | Calendar. A segmented control rather than a bottom bar:
   the composer already owns the bottom of the screen, and the switch belongs
   next to the notebook it applies to — which is also the reason there are
   three of them. Today applies to no notebook, so it hangs off the date on
   the row below instead, and the width that gave back is what paid for the
   icon sizing below. Icons only — even one name spelled out took width from
   the notebook button beside them, and the toast on arrival says which page
   you landed on better than a label you have to read sideways. */
.tabs {
  flex: none;
  display: flex;
  gap: 1px;
  padding: 3px;
  border-radius: 13px;
  background: var(--hair-2);
}
.tab {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 7px 11px;
  border-radius: 10px;
  color: var(--dim);
  transition: background 0.16s, color 0.16s, transform 0.12s;
}
.tab:active { transform: scale(0.94); }
.tab.is-on { background: var(--card); color: var(--ink); box-shadow: var(--lift-1); }
/* rem, like every other size in the app — but only because there are three.
   Four of these growing with the reading size ate eleven pixels of the
   notebook's name at the largest step, so they were pinned to the 19px that
   1.1875rem comes to at the default and read as furniture rather than type.
   Three leave that width to spare. A fourth tab would take it back, and this
   is the line that would pay. */
.tab svg { width: 1.1875rem; height: 1.1875rem; flex: none; }

.bookbtn {
  flex: 0 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 3px;
  max-width: 9.5em;
  padding: 7px 9px;
  border-radius: 11px;
  background: var(--hair-2);
  font-size: 0.84375rem;
  font-weight: 600;
  color: var(--ink-2);
  transition: transform 0.12s;
}
.bookbtn:active { transform: scale(0.94); }
.bookbtn span {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.bookbtn svg { width: 13px; height: 13px; flex: none; color: var(--dim); stroke-width: 2.6; }

.icon-btn {
  flex: none;
  width: var(--tap);
  height: var(--tap);
  display: grid;
  place-items: center;
  border-radius: 12px;
  color: var(--ink-2);
  transition: background 0.15s, transform 0.12s;
}
.icon-btn:active { transform: scale(0.9); background: var(--hair-2); }
.icon-btn svg { width: 22px; height: 22px; }

/* today, in words — the page's own date, not a filter on its lines, and on
   every page the way to Today */
.stamp {
  display: flex;
  align-items: baseline;
  gap: 8px;
  /* Tight under the date: it is the page's title, and a title belongs to what
     it names rather than floating above it. */
  padding: 2px 2px 4px;
  min-width: 0;
}
/* The date is a control, but it is still the date: no pill, no tint, the same
   paper as the page under it. It is the one place in the header where that is
   right — a button up here among the other buttons would read as a fourth tab
   by another name, which is exactly what moving Today off the strip was for.
   What is left is the press itself, and the padding that makes the day a
   thumb-sized target rather than a line of text you have to hit. The negative
   margins pay that padding back, so the day sits exactly where it sat when it
   was only a date, and the row is no taller for being tappable. */
.stamp-today {
  flex: none;
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin: -5px 0 -5px -10px;
  padding: 5px 10px;
  border-radius: 12px;
  transition: transform 0.12s;
}
.stamp-today:active { transform: scale(0.97); }

.stamp-d {
  flex: none;
  font-size: 1.375rem;
  font-weight: 700;
  letter-spacing: -0.03em;
  color: var(--accent);
}
.stamp-m {
  flex: none;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--dim);
  letter-spacing: -0.01em;
}
/* the page of the notebook the Journal is reading, at the far end of the date
   — it is the date that owns the row, so this takes what is left and trails
   off rather than pushing the day about */
.stamp-p {
  margin-left: auto;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 5px;
  padding-left: 10px;
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--dim);
  letter-spacing: -0.01em;
}
.stamp-p svg { width: 0.875rem; height: 0.875rem; flex: none; color: var(--hair); }
.stamp-p span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

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

#page {
  position: relative;
  z-index: 1;
  flex: 1;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 6px 0 0;
}
.tail { height: 24px; }

.list {
  list-style: none;
  margin: 0;
  padding: 0 12px;
}

/* A section heading in the list: a day on the Calendar, a bucket (In Progress)
   or one of the Backlog and Done folds on the Journal, and inside Done a day
   again — the one it was settled on. */
.sep {
  list-style: none;
  padding: 16px 14px 6px;
  font-size: 0.71875rem;
  font-weight: 700;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--dim);
}
.sep-day { color: var(--ink-2); }
.sep-day.is-today { color: var(--accent); }
.sep-day .sep-n,
.sep-bucket .sep-n,
.sep-settled .sep-n { float: right; letter-spacing: 0.04em; color: var(--dim); font-weight: 600; }

/* A day inside Done. It follows a heading rather than closing off the lines
   above it, so it sits tighter to what comes before; and it is all digits, so
   it drops the tracking the worded headings need to read as headings at this
   size. */
.sep-settled {
  padding-top: 9px;
  text-transform: none;
  letter-spacing: 0.04em;
}

/* A heading you can fold: the backlog starts closed, because it is not what
   you came to the page to read; Done starts open but can be put away. */
.sep-fold {
  display: flex;
  align-items: center;
  gap: 7px;
  width: 100%;
  text-align: left;
  font: inherit;
  font-size: 0.71875rem;
  font-weight: 700;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--dim);
  padding: 16px 14px 6px;
  border-radius: 12px;
}
.sep-fold:active { color: var(--ink-2); }
.sep-fold svg {
  width: 0.875rem;
  height: 0.875rem;
  stroke-width: 2.6;
  transition: transform 0.18s;
}
.sep-fold.open svg { transform: rotate(90deg); }
.sep-fold .sep-n { margin-left: auto; letter-spacing: 0.04em; font-weight: 600; }
.s-acts .sep { padding: 14px 8px 4px; }

.row {
  position: relative;
  border-radius: 14px;
  overflow: hidden;
  touch-action: pan-y;
}
.row + .row { margin-top: 2px; }

/* what a swipe reveals underneath */
.row-under {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 20px;
  border-radius: 14px;
  opacity: 0;
  background: var(--good-soft);
  color: var(--good);
}
.row-under svg { width: 21px; height: 21px; }
.row-under .u-r { opacity: 0; }
.row-under .u-l { opacity: 0; }
.row.sw-r .row-under { opacity: 1; background: var(--good-soft); color: var(--good); }
.row.sw-r .row-under .u-l { opacity: 1; }
.row.sw-l .row-under { opacity: 1; background: var(--accent-soft); color: var(--accent); }
.row.sw-l .row-under .u-r { opacity: 1; }

.row-face {
  position: relative;
  display: flex;
  align-items: flex-start;
  /* The bullet and the Today mark already sit in tap-sized boxes wider than
     what they draw, so the box itself is most of the space before the words;
     the gap only has to keep two boxes from touching. */
  gap: 5px;
  padding: 0.69rem 12px;
  background: var(--paper);
  border-radius: 14px;
  will-change: transform;
}
.row.dragging .row-face { transition: none; }
.row-face.snap { transition: transform 0.28s cubic-bezier(0.2, 0.9, 0.25, 1); }
/* a long press holds the row, so the text must not also start a selection */
.row-face { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }

/* held for a reorder: lifted off the page and carried under the finger, while
   the rest of its group slides aside to show where it will land */
.row.lifting { z-index: 2; overflow: visible; }
.row.lifting .row-face {
  box-shadow: 0 6px 22px rgba(0, 0, 0, 0.16), 0 0 0 1px var(--hair-2);
  transform: scale(1.02);
  transition: transform 0.15s, box-shadow 0.15s;
}
.row.shifting { transition: transform 0.18s cubic-bezier(0.2, 0.9, 0.25, 1); }

/* bullets — CSS shapes, no glyph fonts to fight with */
.bul {
  flex: none;
  width: 1.625rem;
  height: 1.625rem;
  margin-top: -1px;
  display: grid;
  place-items: center;
  position: relative;
  border-radius: 9px;
  transition: background 0.15s;
}
.bul:active { background: var(--hair-2); }
.b {
  display: block;
  position: relative;
  color: var(--ink);
}
.b-task { width: 0.5rem; height: 0.5rem; border-radius: 50%; background: currentColor; }
.b-event {
  width: 0.7rem;
  height: 0.7rem;
  border-radius: 50%;
  border: 2px solid currentColor;
}
/* × for complete, drawn as two strokes that sweep in */
.b-done { width: 0.8rem; height: 0.8rem; color: var(--good); }
.b-done::before,
.b-done::after {
  content: "";
  position: absolute;
  left: 0;
  top: calc(50% - 1px);
  width: 0.8rem;
  height: 2px;
  border-radius: 2px;
  background: currentColor;
  transform-origin: center;
}
.b-done::before { transform: rotate(45deg); }
.b-done::after { transform: rotate(-45deg); }
.row.anim .b-done::before { animation: strike-a 0.22s cubic-bezier(0.2, 0.9, 0.3, 1) both; }
.row.anim .b-done::after { animation: strike-b 0.22s 0.05s cubic-bezier(0.2, 0.9, 0.3, 1) both; }
@keyframes strike-a {
  from { transform: rotate(0deg) scaleX(0.1); opacity: 0; }
  to { transform: rotate(45deg) scaleX(1); opacity: 1; }
}
@keyframes strike-b {
  from { transform: rotate(0deg) scaleX(0.1); opacity: 0; }
  to { transform: rotate(-45deg) scaleX(1); opacity: 1; }
}

.row.is-dropped .b { color: var(--dim); }

.row-text {
  flex: 1;
  min-width: 0;
  padding: 1px 0;
  font-size: 1.03125rem;
  line-height: 1.36;
  letter-spacing: -0.005em;
  word-break: break-word;
  text-align: left;
  position: relative;
}
/* done: the ticked bullet says it, so the words stay readable — only a line
   struck out keeps a line through it */
.row.is-done .row-text { color: var(--dim); }
.row.is-dropped .row-text {
  color: var(--dim);
  text-decoration: line-through;
  text-decoration-thickness: 1.5px;
  text-decoration-color: currentColor;
}
.row.anim.is-dropped .row-text { animation: cross 0.3s 0.08s ease-out both; }
@keyframes cross {
  from { text-decoration-color: transparent; }
  to { text-decoration-color: currentColor; }
}
/* set aside, not finished: dim the line but leave it unstruck */
.row.is-backlog .row-text { color: var(--ink-2); }

/* under a task's words: the day it is due by */
.row-meta {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 3px;
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--dim);
}
/* the lateness is the date's, not the line's — the place beside it on Today
   is not news of any colour */
.row-meta .is-late { color: var(--accent); }
/* where a line actually lives, on the one page that reads across notebooks.
   The same ink as the deadline beside it, a weight lighter: it is the second
   thing you read on the line, not a hairline — --hair is for rules, and at
   night it would have been all but invisible. */
.row-where { color: var(--dim); font-weight: 500; }

.star {
  flex: none;
  width: 26px;
  height: 26px;
  display: grid;
  place-items: center;
  color: var(--star);
}
.star svg { width: 0.94rem; height: 0.94rem; }
/* Quick actions. Today sits beside the bullet on In Progress and lights up in
   the accent when the line is on it. The other three wait in the tray under
   the row's right edge, on a quiet ground rather than a coloured one: a
   coloured ground is what says a swipe is about to do something, and opening
   the tray does nothing yet. */
.qa {
  flex: none;
  width: 1.625rem;
  height: 1.625rem;
  margin-top: -1px;
  display: grid;
  place-items: center;
  border-radius: 9px;
  color: var(--dim);
  transition: background 0.15s, color 0.15s;
}
.qa:active { background: var(--hair-2); }
.qa svg { width: 1rem; height: 1rem; }
.qa-today { margin-left: -2px; }
.qa-today.on { color: var(--accent); }
.qa-done:active { color: var(--good); }

.qa-tray {
  position: absolute;
  top: 0;
  bottom: 0;
  right: 6px;
  display: flex;
  align-items: center;
  gap: 2px;
  opacity: 0;
  pointer-events: none;
}
.qa-tray .qa { width: 2.5rem; height: 2.5rem; color: var(--ink-2); }
.qa-tray .qa svg { width: 1.25rem; height: 1.25rem; }
.row.has-tray.sw-l .row-under { background: var(--hair-2); color: var(--ink-2); }
.row.has-tray.sw-l .row-under .u-r { opacity: 0; }
.row.has-tray.sw-l .qa-tray { opacity: 1; }
.row.tray-open .qa-tray { pointer-events: auto; }
/* past the tray, the swipe is setting the line aside again */
.row.has-tray.sw-full .row-under { background: var(--accent-soft); color: var(--accent); }
.row.has-tray.sw-full .row-under .u-r { opacity: 1; }
.row.has-tray.sw-full .qa-tray { opacity: 0; }

svg.fill, .s-act.on svg.fill { fill: currentColor; stroke: none; }

/* ── the Index's list of pages ──────────────────────────────────────── */

/* A group's heading, over the pages that carry its name. The fold takes the
   width and the pencil sits at the end of it, in the same column as the
   pencils on the rows below, so one line runs down the edge of the list. What
   falls under it is not indented: the Journal's buckets do not indent their
   lines either, and a heading already says what belongs to it. */
.grouphead {
  display: flex;
  align-items: flex-end;
  gap: 2px;
}
.grouphead .sep-fold {
  flex: 1;
  min-width: 0;
}
.grouphead .pagelink-edit {
  width: 2.25rem;
  height: 2.25rem;
}

/* One page of the notebook, as a row the width of the list: its name, what is
   still waiting on it, and a pencil. Shaped like the notebook rows in the
   sheets, because it is the same move one level down — turn to one of a short
   list, or rename it in place. */
.pagelink {
  display: flex;
  align-items: center;
  gap: 2px;
}
.pagelink + .pagelink { margin-top: 2px; }
.pagelink-pick {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0.72rem 12px;
  background: var(--paper);
  border-radius: 14px;
  text-align: left;
  transition: background 0.15s;
}
.pagelink-pick:active { background: var(--hair-2); }
.pagelink-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 1.03125rem;
  font-weight: 600;
  letter-spacing: -0.01em;
}
/* the page you are on, in the accent that only ever means "this is now" */
.pagelink.is-on .pagelink-name { color: var(--accent); }
/* What is still waiting on the page, at the end of its row — printed only when
   there is something, so an empty page ends in nothing rather than a nought. */
.pagelink-n {
  flex: none;
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--dim);
  font-variant-numeric: tabular-nums;
}
.pagelink-edit {
  flex: none;
  width: 2.5rem;
  height: 2.5rem;
  display: grid;
  place-items: center;
  border-radius: 12px;
  color: var(--dim);
  transition: background 0.15s, color 0.15s;
}
.pagelink-edit:active { background: var(--hair-2); color: var(--ink-2); }
.pagelink-edit svg { width: 1.125rem; height: 1.125rem; }

/* What a page is and is not, under the list — the Index is never empty, so
   there is no empty state to say it in. */
.index-note {
  margin: 16px 14px 0;
  font-size: 0.8125rem;
  line-height: 1.5;
  color: var(--dim);
}

.notemark {
  flex: none;
  width: 22px;
  height: 26px;
  display: grid;
  place-items: center;
  color: var(--dim);
}
.notemark svg { width: 0.88rem; height: 0.88rem; stroke-width: 2.2; }
.row.is-done .notemark, .row.is-dropped .notemark { opacity: 0.45; }

/* switching pages */
#list.slide-l { animation: slideL 0.26s cubic-bezier(0.16, 1, 0.3, 1); }
#list.slide-r { animation: slideR 0.26s cubic-bezier(0.16, 1, 0.3, 1); }
@keyframes slideL { from { opacity: 0; transform: translateX(22px); } }
@keyframes slideR { from { opacity: 0; transform: translateX(-22px); } }

.empty {
  margin: 18vh 32px 0;
  text-align: center;
  color: var(--dim);
  font-size: 0.96875rem;
  line-height: 1.55;
}
.empty b { display: block; color: var(--ink-2); font-size: 1.125rem; font-weight: 600; margin-bottom: 6px; }

.pill {
  flex: none;
  padding: 9px 15px;
  border-radius: 999px;
  background: var(--accent);
  color: #fff;
  font-size: 0.875rem;
  font-weight: 600;
  box-shadow: var(--lift-1);
  transition: transform 0.12s;
}
:root[data-theme="dark"] .pill { color: #21140c; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .pill { color: #21140c; }
}
.pill:active { transform: scale(0.94); }
.pill-wide { width: 100%; margin-top: 18px; padding: 15px; font-size: 0.96875rem; }

/* ── composer ───────────────────────────────────────────────────────── */

.composer {
  position: sticky;
  bottom: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 8px;
  /* The date row is a full-width child that wraps above the rest. Hidden it is
     display:none, so it costs no gap on the Journal. */
  flex-wrap: wrap;
  row-gap: 6px;
  padding: 8px 12px calc(8px + var(--safe-b));
  background: var(--bar);
  backdrop-filter: saturate(1.6) blur(14px);
  -webkit-backdrop-filter: saturate(1.6) blur(14px);
  border-top: 1px solid var(--hair);
}

#input {
  flex: 1;
  min-width: 0;
  height: 2.5rem;
  font-size: max(16px, 1rem); /* never below 16 — iOS zooms on focus otherwise */
  padding: 0 2px;
}
#input::placeholder { color: var(--dim); }
#input:focus { outline: none; }

.send {
  flex: none;
  width: 38px;
  height: 38px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--hair);
  color: var(--dim);
  transition: background 0.18s, color 0.18s, transform 0.14s, opacity 0.18s;
}
.send svg { width: 19px; height: 19px; stroke-width: 2.4; }
.composer.armed .send { background: var(--accent); color: #fff; transform: scale(1.04); }
:root[data-theme="dark"] .composer.armed .send { color: #21140c; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .composer.armed .send { color: #21140c; }
}
.send:active { transform: scale(0.88); }

/* the composer's day row, Calendar only */
.when {
  flex: 0 0 100%;
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  padding: 0 2px;
}
.when[hidden] { display: none; }
.when label {
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--dim);
}
.when-date { margin-left: 0; flex: 1 1 auto; min-width: 0; }

/* ── sheet ──────────────────────────────────────────────────────────── */

.sheet { position: fixed; inset: 0; z-index: 60; }
.sheet-scrim {
  position: absolute;
  inset: 0;
  background: var(--veil);
  animation: fade 0.22s ease both;
}
@keyframes fade { from { opacity: 0; } }
.sheet-card {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  max-height: 88dvh;
  overflow-y: auto;
  background: var(--card);
  border-radius: 26px 26px 0 0;
  box-shadow: var(--lift-3);
  padding: 8px 0 calc(18px + var(--safe-b));
  animation: rise 0.3s cubic-bezier(0.16, 1, 0.3, 1) both;
}
@keyframes rise { from { transform: translateY(101%); } }
.sheet.closing .sheet-card { animation: rise 0.2s ease-in reverse both; }
.sheet.closing .sheet-scrim { animation: fade 0.2s ease reverse both; }
.sheet-grip {
  width: 38px;
  height: 4.5px;
  border-radius: 3px;
  background: var(--hair);
  margin: 0 auto 6px;
}
.sheet-body { padding: 6px 18px 0; }

.s-title {
  font-size: 1.25rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  margin: 4px 0 14px;
}
.s-sub { font-size: 0.8125rem; color: var(--dim); margin: -10px 0 14px; }

.s-input {
  width: 100%;
  font-size: max(16px, 1.0625rem);
  line-height: 1.4;
  padding: 13px 14px;
  border-radius: 13px;
  background: var(--paper);
  border: 1px solid var(--hair);
  margin-bottom: 14px;
  resize: none;
  font-family: inherit;
  color: inherit;
}
.s-input:focus { outline: none; border-color: var(--accent); }

/* The notes a line carries: the quieter half of the sheet, same box, lighter
   ink, growing from two rows as you type (height is set in app.js). */
.s-note {
  color: var(--ink-2);
  background: var(--hair-2);
  border-color: transparent;
  font-size: max(16px, 0.9375rem);
  overflow-y: auto;
}
.s-note::placeholder { color: var(--dim); }
.s-note:focus { background: var(--paper); border-color: var(--accent); }

.s-acts { display: flex; flex-direction: column; gap: 2px; margin: 0 -8px; }
.s-act {
  display: flex;
  align-items: center;
  gap: 13px;
  width: 100%;
  padding: 13px 8px;
  border-radius: 12px;
  font-size: 1rem;
  font-weight: 500;
  text-align: left;
  transition: background 0.14s;
}
.s-act:active { background: var(--hair-2); }
/* a label can now be a page name of any length, so it trails off instead of
   wrapping under the icon or shoving the key at the end off the row */
.s-act > span:not(.k) {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.s-act svg { width: 1.25rem; height: 1.25rem; flex: none; color: var(--dim); }
.s-act .k { margin-left: auto; font-size: 0.8125rem; font-weight: 600; color: var(--dim); }
.s-act.danger { color: var(--drop); }
.s-act.danger svg { color: var(--drop); }
.s-act.on svg, .s-act.on .k { color: var(--accent); }

/* notebook rows: the width switches, the pencil at the end edits */
.s-book {
  display: flex;
  align-items: center;
  gap: 4px;
}
.s-book-pick {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 13px;
  padding: 13px 8px;
  border-radius: 12px;
  font-size: 1rem;
  font-weight: 500;
  text-align: left;
  transition: background 0.14s;
}
.s-book-pick:active { background: var(--hair-2); }
.s-book-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.s-book-pick .k { flex: none; font-size: 0.8125rem; font-weight: 600; color: var(--dim); }
.s-book-dot {
  flex: none;
  width: 1.125rem;
  height: 1.125rem;
  border-radius: 50%;
  border: 2px solid var(--hair);
}
.s-book.on .s-book-dot { border-color: var(--accent); background: var(--accent); }
.s-book.on .s-book-name { font-weight: 700; }
.s-book.off .s-book-name { color: var(--dim); }
.s-book.off .s-book-dot { border-style: dashed; }
.s-shelf-note { margin: 10px 0 0; }
.s-book-edit {
  flex: none;
  width: 38px;
  height: 38px;
  display: grid;
  place-items: center;
  border-radius: 11px;
  color: var(--dim);
}
.s-book-edit:active { background: var(--hair-2); color: var(--ink-2); }
.s-book-edit svg { width: 1.125rem; height: 1.125rem; }
.s-bookname { font-weight: 700; }

.s-block { padding: 10px 8px 14px; }
.s-block-h {
  display: flex;
  align-items: center;
  gap: 13px;
  font-size: 1rem;
  font-weight: 500;
  margin-bottom: 12px;
}
.s-block-h svg { width: 1.25rem; height: 1.25rem; flex: none; color: var(--dim); }

.s-seg {
  display: flex;
  gap: 2px;
  padding: 3px;
  border-radius: 13px;
  background: var(--hair-2);
  margin-left: auto;
}
.s-seg button {
  padding: 7px 13px;
  border-radius: 10px;
  font-size: 0.84375rem;
  font-weight: 600;
  color: var(--dim);
}
.s-seg button.on { background: var(--card); color: var(--ink); box-shadow: var(--lift-1); }
.s-seg-wide { margin-left: 0; width: 100%; }
.s-seg-wide button { flex: 1; padding: 10px 0; line-height: 1; }

/* A native field at the end of a sheet row — the day an event falls on.
   Shaped like a .s-seg so a row that asks for a value sits level with the
   rows that only offer choices. appearance:none keeps iOS from painting its own grey box
   over the card. */
.s-field {
  margin-left: auto;
  padding: 7px 10px;
  border-radius: 13px;
  background: var(--hair-2);
  color: var(--ink);
  font: inherit;
  font-size: 0.875rem;
  font-weight: 600;
  -webkit-appearance: none;
  appearance: none;
  min-height: 34px;
}
.s-field::-webkit-date-and-time-value { text-align: right; }
/* Takes a deadline back off a task. Sits beside the field rather than inside
   it, because every date picker hides its own clear somewhere different. */
.s-clear {
  margin-left: 8px;
  padding: 7px 10px;
  border-radius: 13px;
  color: var(--dim);
  font-size: 0.8125rem;
  font-weight: 600;
}
.s-field::-webkit-calendar-picker-indicator { opacity: 0.55; }

/* ── search ─────────────────────────────────────────────────────────── */

.s-search {
  width: 100%;
  font-size: max(16px, 1rem);
  padding: 12px 14px;
  border-radius: 13px;
  background: var(--paper);
  border: 1px solid var(--hair);
  margin-bottom: 10px;
}
.s-search:focus { outline: none; border-color: var(--accent); }
.hit {
  display: flex;
  gap: 11px;
  align-items: flex-start;
  width: 100%;
  padding: 11px 8px;
  border-radius: 12px;
  text-align: left;
  margin: 0 -8px;
}
.hit:active { background: var(--hair-2); }
.hit .h-t { flex: 1; min-width: 0; font-size: 0.96875rem; }
.hit .h-d { font-size: 0.75rem; font-weight: 600; color: var(--dim); margin-top: 2px; }
.hit mark { background: var(--accent-soft); color: inherit; border-radius: 3px; padding: 0 1px; }
/* a hit that matched inside a line's notes, not its words: show what matched
   so the row doesn't read as a false positive */
.hit .h-n {
  display: flex;
  align-items: flex-start;
  gap: 6px;
  margin-top: 3px;
  font-size: 0.8125rem;
  line-height: 1.4;
  color: var(--ink-2);
}
.hit .h-n svg { flex: none; width: 0.8125rem; height: 0.8125rem; margin-top: 3px; color: var(--dim); }
.hit .h-n span { min-width: 0; }

.lb { width: 1.375rem; display: grid; place-items: center; flex: none; align-self: center; }


/* ── toast ──────────────────────────────────────────────────────────── */

.toast {
  position: fixed;
  left: 50%;
  bottom: calc(4.9rem + var(--safe-b));
  z-index: 80;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 11px 12px 11px 17px;
  border-radius: 999px;
  background: var(--ink);
  color: var(--paper);
  font-size: 0.90625rem;
  font-weight: 500;
  box-shadow: var(--lift-2);
  animation: toastin 0.3s cubic-bezier(0.16, 1, 0.3, 1) both;
  max-width: calc(100vw - 32px);
}
@keyframes toastin { from { opacity: 0; transform: translate(-50%, 14px) scale(0.94); } }
.toast.closing { animation: toastin 0.18s ease-in reverse both; }
#toastMsg { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* a sheet owns the bottom of the screen, so the toast moves to the top */
body.sheet-open .toast { bottom: auto; top: calc(var(--safe-t) + 12px); }
/* Nothing to undo — a bare note, so the button comes off and the right edge
   gets the padding the button was holding. */
.toast.bare { padding-right: 17px; }
#toastUndo[hidden] { display: none; }
#toastUndo {
  font-weight: 700;
  color: var(--accent);
  padding: 3px 9px;
  border-radius: 999px;
}

/* ── desktop: keep the phone shape, centred ─────────────────────────── */

@media (min-width: 720px) {
  /* html gets its own background so body's doesn't propagate to the canvas */
  html { background: var(--hair-2); }
  body {
    max-width: 560px;
    margin: 0 auto;
    background: var(--paper);
    box-shadow: 0 0 0 1px var(--hair), var(--lift-2);
  }
  .row-face:hover { background: var(--hair-2); }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ── portrait only ──────────────────────────────────────────────────── */

/* The manifest asks for portrait at install time and app.js asks again at
   runtime, but neither lands in a plain Safari tab. When the page is short and
   wide anyway, the notebook steps aside for a full-viewport nudge rather than
   squeezing a header, a list and a composer into ~380px of height. */

.rotate { display: none; }

@media (orientation: landscape) and (max-height: 560px) {
  body { overflow: hidden; }
  body > *:not(.rotate) { display: none !important; }

  .rotate {
    display: flex;
    position: fixed;
    inset: 0;
    z-index: 100;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 16px;
    padding: max(20px, var(--safe-t)) max(20px, env(safe-area-inset-right, 0px))
      max(20px, var(--safe-b)) max(20px, env(safe-area-inset-left, 0px));
    background: var(--paper);
    color: var(--ink-2);
    text-align: center;
  }
  .rotate svg {
    width: 34px;
    height: 34px;
    color: var(--accent);
    transform: rotate(90deg);
    animation: uprighting 2.6s ease-in-out infinite;
  }
  .rotate p {
    font-size: 0.9375rem;
    font-weight: 500;
    line-height: 1.5;
    text-wrap: balance;
  }
}

/* tips back upright, then falls over again — the gesture we're asking for */
@keyframes uprighting {
  0%, 22% { transform: rotate(90deg); }
  45%, 78% { transform: rotate(0deg); }
  100% { transform: rotate(90deg); }
}
