/* Stupid Tasklist — a handwritten notebook on a warm desk.
   The three.js desk renders behind everything; the paper is built in CSS so
   ruled lines, the margin and the spiral binding stay crisp at any zoom.
   Palette follows the "Stupid — The Sigh" design system: cream page, brown-black
   ink, sage accent. Never pure black, never pure white on a full screen. */

:root {
  /* the Sigh palette */
  --cream:     #FBF3E7;
  --sand:      #E4D5C3;
  --blush:     #F3E4D3;
  --terracotta:#DE7A57;
  --sage:      #7FA98B;
  --over:      #B8523A;
  --muted:     #8A776E;

  /* paper + ink, keyed off the palette above */
  --paper:      var(--cream);
  --paper-edge: var(--sand);
  --rule:       rgba(59, 46, 42, 0.20);   /* feint rule, drawn in ink not blue */
  --rule-soft:  rgba(59, 46, 42, 0.12);
  --margin-red: rgba(222, 122, 87, 0.55); /* terracotta margin rule */
  --ink:        #3B2E2A;   /* brown-black ink */
  --ink-soft:   #5C4A44;
  --ink-faint:  var(--muted);

  /* the live accent. Tasklist is sage; the [data-app] hook mirrors the kit. */
  --accent:     var(--sage);
  --on-accent:  #fff;

  /* chrome (sidebar, tool bars, glass panels) — warm ink brown, not green */
  --brand:        var(--sage);
  --brand-deep:   #6B927A;
  --green-pastel: #C9DDD0;   /* soft chip / active fill */
  --green-soft:   #DDEAE1;
  --green-tint:   rgba(127, 169, 139, 0.16);
  --chrome:       rgba(46, 36, 33, 0.82);   /* ink-brown frosted glass */
  --chrome-edge:  rgba(228, 213, 195, 0.16);
  --on-chrome:    var(--cream);
  --on-chrome-soft: rgba(251, 243, 231, 0.72);

  /* the handwriting face + per-face scale, set live by fonts.js */
  --hand: 'Caveat', cursive;
  --hand-scale: 1.25;

  /* The page rhythm scales with the handwriting size, so the ruled lines grow
     and shrink with the text on screen-size changes. --rule-offset seats the
     feint line just under the text baseline (≈1px gap) instead of mid-band. */
  --hand-size: calc(clamp(1.15rem, 1rem + 0.45vw, 1.45rem) * var(--hand-scale));
  /* Round the line rhythm to a whole pixel. The feint-rule gradient repeats
     every --line and the text uses line-height:var(--line); if --line were
     fractional the two would drift apart over a page (the misalignment seen on
     tablet/portrait). Snapping to 1px keeps them locked on EVERY screen size. */
  --line: round(calc(var(--hand-size) * 1.45), 1px);
  --rule-offset: calc(var(--line) / 2 + 0.3 * var(--hand-size) + 1px);
  --check: clamp(16px, calc(var(--line) * 0.5), 24px);

  /* page padding (vars so the full-bleed rules can cancel it exactly) */
  --pad-t: 34px; --pad-r: 40px; --pad-b: 64px; --pad-l: 76px;
  /* x-position of the red vertical margin rule (and the notebook margin column
     width). Task sheets keep it tight; notebooks widen it ~2.5x below. */
  --rule-x: 56px;

  --ui: 'Nunito', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
  --serif: 'Fraunces', Georgia, 'Times New Roman', serif;
  --mono: 'JetBrains Mono', ui-monospace, monospace;
  --sidebar-w: 268px;
  --radius: 10px;

  /* motion — things settle, they do not bounce */
  --ease: cubic-bezier(.32,.72,.35,1);
  --dur: 220ms;
}
/* mirrors the kit's per-app accent hook */
[data-app="tasklist"] { --accent: var(--sage); --on-accent: #fff; }

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; height: 100%; }
body {
  font-family: var(--ui);
  color: var(--ink);
  background: #2E2421;            /* fallback behind the desk canvas */
  overflow: hidden;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
.hidden { display: none !important; }

/* ----------------------------------------------------------------- desk 3d */
#desk-canvas {
  position: fixed; inset: 0;
  width: 100vw; height: 100vh;
  display: block; z-index: 0;
}
/* Graceful gradient if WebGL is unavailable. */
body.no-webgl #desk-canvas { display: none; }
body.no-webgl::before {
  content: ''; position: fixed; inset: 0; z-index: 0;
  background:
    radial-gradient(120% 90% at 30% 20%, #6E5548 0%, #4A3931 55%, #2E2421 100%);
}

/* A soft warm pool of light + vignette over the desk, regardless of renderer. */
.app::after, .auth::after {
  content: ''; position: fixed; inset: 0; z-index: 1; pointer-events: none;
  background:
    radial-gradient(70% 60% at 50% 38%, rgba(255, 240, 210, 0.10), transparent 70%),
    radial-gradient(120% 120% at 50% 50%, transparent 55%, rgba(20, 14, 8, 0.55) 100%);
}

/* --------------------------------------------------------------- the paper */
/* Reusable notebook page. Ruled feint lines + red margin are drawn with
   gradients; a faint fibre noise and warm edge shadow sell the paper. */
.paper {
  position: relative;
  width: min(760px, 100%);
  margin: 0 auto;
  padding: var(--pad-t) var(--pad-r) var(--pad-b) var(--pad-l);
  background-color: var(--paper);
  background-image:
    /* red vertical margin rule (horizontal feint lines live on .paper-lines /
       .nb-grid so their grid origin lines up with the actual rows) */
    linear-gradient(to right, transparent var(--rule-x), var(--margin-red) var(--rule-x), var(--margin-red) calc(var(--rule-x) + 1px), transparent calc(var(--rule-x) + 1px));
  background-position: 0 0;
  border-radius: 4px 6px 6px 4px;
  box-shadow:
    0 1px 0 rgba(255,255,255,0.5) inset,
    0 22px 50px rgba(0, 0, 0, 0.45),
    0 4px 14px rgba(0, 0, 0, 0.30);
}
/* paper fibre + faint shading toward the spine */
.paper::before {
  content: ''; position: absolute; inset: 0; border-radius: inherit;
  pointer-events: none;
  background:
    linear-gradient(to right, rgba(0,0,0,0.05), transparent 8%, transparent 94%, rgba(0,0,0,0.04)),
    radial-gradient(140% 80% at 50% -10%, rgba(255,255,255,0.5), transparent 40%);
  mix-blend-mode: multiply;
  opacity: 0.6;
}

/* spiral binding along the top edge */
.paper-spiral {
  position: absolute; top: -9px; left: 22px; right: 22px; height: 18px;
  pointer-events: none;
  background-image: radial-gradient(circle at center,
    rgba(0,0,0,0.42) 0 3px, rgba(0,0,0,0.18) 3px 5px, transparent 6px);
  background-size: 34px 18px;
  background-repeat: repeat-x;
}

/* page header / handwritten title */
.paper-head {
  display: flex; align-items: baseline; gap: 12px;
  min-height: 50px; margin-bottom: 14px;
}
.sheet-title {
  font-family: var(--hand);
  font-size: calc(2.1rem * var(--hand-scale));
  line-height: 1; color: var(--ink); margin: 0;
  transform: rotate(-1.2deg);
}
.live-pill {
  font-family: var(--hand); font-size: 1.2rem; color: var(--accent);
  border: 1.5px solid var(--margin-red); border-radius: 999px;
  padding: 1px 12px; transform: rotate(-2deg);
}
.page-h, .set-h, .tool-label, .nb-status { font-family: var(--ui); }

/* ----------------------------------------------------------- task lines */
/* Each task sits on one ruled line. The grid: [margin] [check] [body]. */
.paper-lines {
  position: relative;
  /* The feint rules are NOT drawn here any more — see .tl / .tl-add below.
     Painting one continuous repeating gradient on this container let subpixel
     row heights accumulate over a page, so around the 8th line the text
     drifted off the rule. Attaching one rule to EACH row box instead locks
     every line to its own task, so they can never separate however the page
     scales. Each row bleeds to full page width itself, so this container keeps
     its normal padding box. */
  min-height: calc(var(--line) * 12);
}

/* the feint ruled line, tiled every --line and seated just under the text
   baseline. Shared by every row-shaped element so each carries its own rule. */
.tl, .tl-add {
  background-image: repeating-linear-gradient(to bottom,
    transparent 0,
    transparent calc(var(--rule-offset) - 1px),
    var(--rule) calc(var(--rule-offset) - 1px),
    var(--rule) var(--rule-offset),
    transparent var(--rule-offset),
    transparent var(--line));
  background-position: 0 0;
  /* let a row's rule bleed to the full page width, not just the text column */
  background-origin: border-box;
}

.tl {
  position: relative;
  display: grid;
  grid-template-columns: 20px 30px 1fr;
  align-items: start;
  min-height: var(--line);
  gap: 2px;
  /* stretch the rule across the full page width (cancels .paper-lines padding) */
  margin: 0 calc(-1 * var(--pad-r)) 0 calc(-1 * var(--pad-l));
  padding: 0 var(--pad-r) 0 var(--pad-l);
}
.tl-margin {
  grid-column: 1;
  position: relative; left: -64px; width: 56px;
  display: flex; justify-content: flex-end; align-items: baseline; gap: 3px;
  font-family: var(--hand); color: var(--accent);
  font-size: 1.4rem; line-height: var(--line);
  pointer-events: none;
}
.tl-mark.in  { color: var(--ink-faint); }
.tl-mark.out { color: var(--accent); }

/* checkbox — a hand-drawn square the ink tick lands inside */
.tl-check {
  grid-column: 2; align-self: start;
  margin-top: calc(var(--rule-offset) - var(--check));   /* box bottom rests on the rule */
  width: var(--check); height: var(--check); padding: 0;
  background: transparent; cursor: pointer;
  color: var(--ink);
  border: 2px solid var(--ink-soft);
  border-radius: 4px 6px 5px 7px;        /* uneven = hand-drawn */
  transform: rotate(-1.5deg);
  position: relative; display: grid; place-items: center;
  transition: background 0.2s ease;
}
.tl-check:hover { background: rgba(59, 46, 42, 0.06); }
.ink-check {
  position: absolute; inset: -5px -3px; width: 28px; height: 28px;
  color: var(--accent); pointer-events: none;
  transform: translateY(-9px);   /* lift the tick off the box bottom */
}

/* body: the text row, optional detail, and the edit toolbar */
.tl-body { grid-column: 3; min-width: 0; }
.tl-row { display: flex; align-items: flex-end; gap: 6px; min-height: var(--line); }

/* the bright-pink priority asterisk — lives in the margin, just before the ›/»
   carry markers, so it rides the same rule and reads uniformly out in the
   margin. Sized to a single ruled line so it never spills onto adjacent rows,
   and it matches the marks' baseline via the shared line-height. */
.tl-star {
  flex: none; display: none;
  font-family: var(--hand);
  height: var(--line);
  font-size: calc(var(--line) * 1.05);
  line-height: var(--line);
  color: var(--terracotta);
  transform: rotate(-8deg);
  pointer-events: none; user-select: none;
  overflow: hidden;
}
.tl.prio .tl-star { display: inline-block; }

/* the star toggle in the edit toolbar */
.tl-prio { color: var(--terracotta) !important; border-color: var(--terracotta) !important; }
.tl-prio.on { background: rgba(222,122,87,0.14) !important; }

/* do date — the scheduled date of a project task, pencilled into the margin */
.tl-do {
  flex: none; font-family: var(--hand); font-size: 0.95rem;
  line-height: var(--line); color: var(--ink-faint);
  white-space: nowrap; overflow: hidden;
}
/* the do-date picker in the edit toolbar */
.tl-date-field { display: inline-flex; align-items: center; gap: 4px;
  font-family: var(--ui); font-size: 0.75rem; color: var(--ink-soft); }
.tl-date { font-family: var(--ui); font-size: 0.75rem; color: var(--ink);
  background: rgba(238, 190, 78, 0.1); border: 1px dashed var(--ink-faint);
  border-radius: 6px; padding: 2px 5px; }
.tl-date:focus { outline: none; border-color: var(--accent); }

/* the project name on a task borrowed onto a day/week sheet by its do date */
.tl-project {
  flex: none; align-self: center;
  font-family: var(--ui); font-size: 0.66rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--ink-soft); background: rgba(127, 169, 139, 0.18);
  border-radius: 999px; padding: 1px 7px;
  max-width: 40%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.tl-text {
  flex: 1; min-width: 0;
  font-family: var(--hand);
  font-size: var(--hand-size);
  line-height: var(--line);
  color: var(--ink);
  position: relative;
  outline: none;
  word-break: break-word;
  padding-right: 4px;
  cursor: text;
}
.tl-text[contenteditable="true"] {
  background: rgba(238, 190, 78, 0.20);
  box-shadow: 0 0 0 2px rgba(238, 190, 78, 0.20);
  border-radius: 3px;
}
.tl.done .tl-text { color: var(--ink-soft); }

/* the big wavy strikethrough laid over the text */
.ink-strike {
  position: absolute; left: 0; top: 50%;
  transform: translateY(-50%);
  height: 22px; color: var(--accent);
  pointer-events: none; overflow: visible;
}

/* caret toggles the detail panel */
.tl-caret {
  flex: none; align-self: center;
  width: 26px; height: 26px; padding: 0;
  border: none; background: transparent; cursor: pointer;
  color: var(--ink-faint); font-size: 1rem;
  border-radius: 6px;
  transition: transform 0.2s ease, color 0.2s ease;
}
.tl-caret::before { content: '▾'; }
.tl-caret:hover { color: var(--ink); }
.tl-caret.open { transform: rotate(180deg); color: var(--ink); }

/* detail panel — sketched arrow + note that keeps riding the page's ruled
   lines (no vertical padding, line-height == one band) so every wrapped
   paragraph line lands on a feint rule just like the task title. */
.tl-detail { display: none; }
.tl-detail.open { display: flex; align-items: flex-start; gap: 8px; padding: 0 0 0 6px; }
.ink-arrow { flex: none; width: 30px; height: var(--line); color: var(--ink-faint); margin-top: 0; }
.tl-detail-text {
  margin: 0; font-family: var(--hand);
  font-size: calc(var(--hand-size) * 0.92);
  color: var(--ink-soft); line-height: var(--line);
}
.tl-detail-label { flex: none; width: 30px; text-align: right;
  font-family: var(--ui); font-size: 0.62rem; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--ink-faint); line-height: var(--line); }
.tl-detail-input {
  flex: 1; resize: vertical; min-height: calc(var(--line) * 2);
  font-family: var(--hand); font-size: calc(var(--hand-size) * 0.92);
  color: var(--ink-soft); line-height: var(--line);
  background: transparent;        /* let the page rules show through */
  border: none; border-radius: 0; padding: 0; outline: none;
}
.tl-detail-input:focus { background: rgba(238, 190, 78, 0.14); }

/* edit toolbar — only visible while editing */
.tl-tools { display: none; gap: 6px; padding: 2px 0 8px; }
.tl.editing .tl-tools { display: flex; }
.tl-save, .tl-del, .tl-cancel {
  font-family: var(--ui); font-size: 0.78rem; font-weight: 700;
  border: 2px solid var(--sand); background: #fff;
  border-radius: var(--radius); padding: 4px 10px; cursor: pointer; color: var(--ink);
}
.tl-save { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.tl-del { color: var(--over); }
.tl-save:hover, .tl-del:hover, .tl-cancel:hover { filter: brightness(0.97); }

/* the trailing "write a task" line — carries its own rule (see .tl,.tl-add
   above) and bleeds to the full page width so that rule lines up with the
   task rows'. The 52px text indent is layered on top of the page padding. */
.tl-add {
  display: block; min-height: var(--line); line-height: var(--line);
  font-family: var(--hand); font-size: var(--hand-size);
  color: var(--ink); outline: none; cursor: text;
  margin: 0 calc(-1 * var(--pad-r)) 0 calc(-1 * var(--pad-l));
  padding: 0 var(--pad-r) 0 calc(var(--pad-l) + 52px);
}
.tl-add:empty::before { content: attr(data-ph); color: var(--ink-faint); opacity: 0.6; }

.sheet-loading {
  font-family: var(--hand); font-size: calc(1.3rem * var(--hand-scale));
  color: var(--ink-faint); padding: var(--line) 0 0 52px;
}

/* Empty-state / instruction notes are drawn as a yellow sticky-note (post-it)
   with a red-highlighter swipe over the handwritten words. Centred with
   margin:auto so they land identically on every screen size (the task sheet
   note clears on the first keystroke; see sheet.js). */
.sheet-empty {
  font-family: var(--hand); font-size: calc(1.5rem * var(--hand-scale));
  color: var(--ink); line-height: 1.32; text-align: center;
  width: fit-content; max-width: min(300px, 100%);
  margin: calc(var(--line) + 6px) auto 0; padding: 18px 22px 24px;
  background: linear-gradient(168deg, #F6DFA6 0%, #EEBE4E 100%);
  border-radius: 2px; transform: rotate(-2.4deg);
  box-shadow: 0 12px 24px rgba(0,0,0,0.26), inset 0 1px 0 rgba(255,255,255,0.55);
}
/* the translucent red highlighter, cloned so each wrapped line gets a swipe */
.sheet-empty .hl {
  background: linear-gradient(to bottom, transparent 10%,
    rgba(222, 122, 87, 0.42) 10%, rgba(222, 122, 87, 0.42) 86%, transparent 86%);
  -webkit-box-decoration-break: clone; box-decoration-break: clone;
  padding: 0 3px; border-radius: 1px;
}
/* span the whole list width when the notebook grid is empty, so it centres */
.nb-list .sheet-empty { grid-column: 1 / -1; }

/* --------------------------------------------------------------- auth cover */
.auth {
  position: relative; z-index: 2;
  min-height: 100vh; display: grid; place-items: center;
  padding: 24px;
}
.cover {
  position: relative; z-index: 3;
  width: min(420px, 100%);
  background: #443430;
  color: var(--cream);
  border-radius: 8px 12px 12px 8px;
  padding: 44px 36px 40px;
  box-shadow: 0 30px 70px rgba(0,0,0,0.55), 0 6px 16px rgba(0,0,0,0.4);
  overflow: hidden;
}
/* cloth-band + elastic closure for the moleskine feel */
.cover-band { position: absolute; inset: 0 auto 0 14px; width: 6px;
  background: rgba(0,0,0,0.18); box-shadow: 1px 0 0 rgba(255,255,255,0.06); }
.cover-elastic { position: absolute; top: 0; bottom: 0; right: 34px; width: 12px;
  background: linear-gradient(to right, rgba(0,0,0,0.28), rgba(0,0,0,0.12));
  border-radius: 2px; }
.cover-inner { position: relative; }
.cover-mark { display: block; height: 140px; width: auto; max-width: 100%; }
.cover-sub { font-family: var(--hand); font-size: 1.5rem; color: rgba(251,243,231,0.85);
  margin: 14px 0 26px; }

.auth-tabs { display: flex; gap: 4px; background: rgba(0,0,0,0.2);
  padding: 4px; border-radius: var(--radius); margin-bottom: 20px; }
.auth-tab { flex: 1; border: none; background: transparent; color: rgba(251,243,231,0.7);
  font-family: var(--ui); font-weight: 700; font-size: 0.86rem; padding: 8px;
  border-radius: 8px; cursor: pointer;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease); }
.auth-tab.active { background: var(--accent); color: var(--on-accent); }

.auth-form { display: none; flex-direction: column; gap: 14px; }
.auth-form.active { display: flex; }
.auth-form label { display: flex; flex-direction: column; gap: 6px;
  font-size: 0.82rem; font-weight: 700; color: rgba(251,243,231,0.8); }
.auth-form input {
  font-family: var(--ui); font-size: 1rem; color: var(--ink);
  background: #fff; border: 2px solid var(--sand); border-radius: var(--radius);
  padding: 11px 13px; outline: none;
  transition: border-color var(--dur) var(--ease);
}
.auth-form input:focus { border-color: var(--accent); }
.btn-ink {
  margin-top: 8px; font-family: var(--ui); font-weight: 700; font-size: 1rem;
  background: var(--accent); color: var(--on-accent); border: none;
  border-radius: 22px; padding: 14px; cursor: pointer;
  transition: transform var(--dur) var(--ease), filter var(--dur) var(--ease);
}
.btn-ink:hover { filter: brightness(1.05); }
.btn-ink:active { transform: translateY(1px) scale(.99); }
.auth-error { min-height: 1em; margin: 0; color: #F0BDAF; font-size: 0.82rem; }

/* ------------------------------------------------------------------- shell */
.app { position: relative; z-index: 2; height: 100vh; display: flex; }

.topbar-mobile {
  display: none;
  position: fixed; top: 0; left: 0; right: 0; z-index: 30; height: 56px;
  align-items: center; gap: 12px; padding: 0 14px;
  background: var(--chrome); backdrop-filter: blur(8px);
  color: var(--on-chrome);
}
.topbar-brand { height: 38px; width: auto; display: block; }
.hamburger { display: grid; gap: 4px; background: none; border: none; cursor: pointer; padding: 8px; }
.hamburger span { width: 22px; height: 2px; background: var(--cream); border-radius: 2px; }

/* sidebar */
.sidebar {
  position: relative; z-index: 20; flex: none;
  width: var(--sidebar-w); height: 100vh;
  display: flex; flex-direction: column;
  background: var(--chrome); backdrop-filter: blur(10px);
  color: var(--on-chrome); padding: 18px 16px; gap: 16px;
  border-right: 1px solid var(--chrome-edge);
}
.side-brand { display: flex; align-items: center; gap: 8px; }
.side-title { height: 92px; width: auto; max-width: 100%; display: block; }
.side-close { display: none; margin-left: auto; background: none; border: none;
  color: var(--on-chrome); font-size: 1.1rem; cursor: pointer; }

.side-actions { display: flex; flex-direction: column; gap: 10px; }
.side-btn.primary { font-family: var(--ui); font-weight: 700; font-size: 0.95rem;
  color: var(--on-accent); background: var(--accent); border: none;
  border-radius: var(--radius); padding: 10px; cursor: pointer;
  transition: filter var(--dur) var(--ease); }
.side-btn.primary:hover { filter: brightness(1.05); }
.mode-toggle { display: flex; background: rgba(0,0,0,0.25); border-radius: var(--radius); padding: 3px; }
.mode-opt { flex: 1; border: none; background: transparent; color: var(--on-chrome-soft);
  font-family: var(--ui); font-weight: 700; font-size: 0.82rem; padding: 6px; border-radius: 8px; cursor: pointer;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease); }
.mode-opt.active { background: var(--accent); color: var(--on-accent); }

.side-nav { display: flex; flex-direction: column; gap: 2px; overflow-y: auto; flex: 1; }
.side-link { font-family: var(--ui); font-weight: 700; font-size: 0.9rem;
  color: var(--on-chrome-soft); padding: 8px 10px; border-radius: 8px; cursor: pointer; text-decoration: none; }
.side-link:hover { background: rgba(255,255,255,0.06); }
.side-link.active { background: var(--green-tint); color: var(--cream); }
.side-link-new { margin-top: 10px; }
.side-section { display: flex; flex-direction: column; gap: 1px; margin: 2px 0 6px; padding-left: 6px; }
.side-sub { display: flex; justify-content: space-between; align-items: center; gap: 8px;
  font-size: 0.82rem; color: rgba(251,243,231,0.6); padding: 5px 8px; border-radius: 8px;
  cursor: pointer; text-decoration: none; }
.side-sub:hover { background: rgba(255,255,255,0.05); color: rgba(251,243,231,0.9); }
.side-sub-count { font-variant-numeric: tabular-nums; font-family: var(--mono);
  color: rgba(251,243,231,0.45); font-size: 0.72rem; }
.side-foot { font-family: var(--hand); font-size: 1.1rem; color: rgba(251,243,231,0.4); margin: 0; }

.sidebar-scrim { display: none; position: fixed; inset: 0; z-index: 19;
  background: rgba(0,0,0,0.5); opacity: 0; pointer-events: none;
  transition: opacity 0.25s ease; }
.sidebar-scrim.show { opacity: 1; pointer-events: auto; }

/* stage */
.stage { flex: 1; height: 100vh; overflow-y: auto; padding: 28px 24px 80px;
  display: flex; flex-direction: column; align-items: center; }
.stage-tools {
  width: min(760px, 100%); display: flex; align-items: center; gap: 8px;
  margin-bottom: 16px; min-height: 38px; flex-wrap: wrap;
}
/* fixed width so the page can't grow/shrink with its own content */
.view-root { width: min(760px, 100%); }
.tool-btn {
  font-family: var(--ui); font-size: 0.85rem; font-weight: 700;
  color: var(--cream); background: rgba(0,0,0,0.3); border: 1px solid var(--chrome-edge);
  border-radius: 8px; padding: 7px 12px; cursor: pointer; backdrop-filter: blur(6px);
  transition: background var(--dur) var(--ease);
}
.tool-btn:hover { background: rgba(0,0,0,0.42); }
.tool-today { font-weight: 800; }
.tool-accent { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.tool-accent:hover { background: var(--accent); filter: brightness(1.05); }
.tool-danger { color: #F0BDAF; }
.tool-label { color: var(--cream); font-weight: 700; font-size: 0.85rem; }

/* ---------------------------------------------------------- notebook view */
.page-h { font-family: var(--serif);
  font-variation-settings: 'opsz' 144, 'SOFT' 100, 'WONK' 1; font-weight: 700;
  letter-spacing: -0.02em; font-size: 1.6rem; color: var(--cream);
  margin: 0 0 16px; width: min(760px, 100%); }

.nb-list { width: min(760px, 100%); display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 16px; }
.nb-card {
  position: relative; aspect-ratio: 3 / 4; cursor: pointer; text-align: left;
  background: #443430;
  border: none; border-radius: 4px 8px 8px 4px; padding: 16px 14px 14px 24px;
  color: var(--cream); box-shadow: 0 10px 24px rgba(0,0,0,0.4);
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.nb-card:hover { transform: translateY(-3px) rotate(-0.6deg); box-shadow: 0 16px 32px rgba(0,0,0,0.5); }
.nb-card-spine { position: absolute; top: 0; bottom: 0; left: 8px; width: 5px;
  background: rgba(0,0,0,0.25); border-radius: 2px; }
.nb-card-title { font-family: var(--hand); font-size: 1.6rem; line-height: 1.05; }
/* project cards: a sage spine so they read apart from the notebooks shelf */
.nb-card.project .nb-card-spine { background: var(--green-tint); }
.nb-card-count { position: absolute; bottom: 12px; right: 14px;
  font-family: var(--mono); font-size: 0.72rem; color: rgba(251,243,231,0.55); }

/* the open notebook: a margin column + the writing body */
.paper.notebook {
  padding-bottom: 80px;
  /* ~2.5x the task-sheet margin. The red rule (drawn on .paper via --rule-x)
     and the margin column (below) both read this var, so they always line up.
     Responsive so the wide margin still fits a phone. */
  --rule-x: clamp(96px, 18vw, 150px);
}
.nb-grid {
  /* The margin column fills the strip LEFT of the red rule, so margin notes
     write in the page margin. We drop the grid's left padding to 0 so column 1
     begins at the paper edge; the body column starts at the red rule and clears
     it with its own pad. Column 1 width == --rule-x == the red-rule position. */
  display: grid; grid-template-columns: var(--rule-x) 1fr; gap: 0;
  /* same full-bleed, baseline-seated ruling as the task sheet */
  margin: 0 calc(-1 * var(--pad-r)) 0 calc(-1 * var(--pad-l));
  padding: 0 var(--pad-r) 0 0;
  background-image: repeating-linear-gradient(to bottom,
    transparent 0,
    transparent calc(var(--rule-offset) - 1px),
    var(--rule) calc(var(--rule-offset) - 1px),
    var(--rule) var(--rule-offset),
    transparent var(--rule-offset),
    transparent var(--line));
}
.nb-margin, .nb-body {
  font-family: var(--hand); color: var(--ink); outline: none;
  /* Both ride the same ruled rhythm as the task sheet: one --line band per
     visual line, seated on the rule via the shared --rule-offset. Sharing
     --hand-size keeps the baseline seating identical everywhere. */
  font-size: var(--hand-size);
  line-height: var(--line); min-height: calc(var(--line) * 8);
}
.nb-margin {
  font-size: calc(var(--hand-size) * 0.82); color: var(--accent);
  text-align: right; padding-right: 10px; opacity: 0.85;
}
.nb-body { padding-left: 20px; word-break: break-word; }

/* Rich text inside the body keeps riding the ruled lines: lists get no block
   margins (which would knock following lines off-grid) and each item is one
   --line band. Bold is just weight, so it stays seated. */
.nb-body b, .nb-body strong { font-weight: 700; }
.nb-body ul, .nb-body ol { margin: 0; padding-left: 1.4em; }
.nb-body li { line-height: var(--line); }
.nb-body p { margin: 0; }

.nb-margin:empty::before, .nb-body:empty::before {
  content: attr(data-ph); color: var(--ink-faint); opacity: 0.5;
}
.nb-title-input {
  font-family: var(--hand); font-size: 1.5rem; color: var(--cream);
  background: rgba(0,0,0,0.28); border: 1px solid var(--chrome-edge);
  border-radius: 8px; padding: 5px 12px; outline: none; min-width: 160px; flex: 1;
  transition: border-color var(--dur) var(--ease);
}
.nb-title-input:focus { border-color: var(--accent); }
.nb-status { color: var(--on-chrome-soft); font-size: 0.8rem; min-width: 64px; }

/* page navigation within a notebook (prev / "Page x of n" / next / + Page) */
.nb-pager { display: inline-flex; align-items: center; gap: 6px; }
.nb-page-num { font-family: var(--ui); font-weight: 600; font-size: 0.82rem;
  color: var(--on-chrome); min-width: 78px; text-align: center; }
.nb-pg-btn { font-family: var(--ui); font-size: 0.85rem; font-weight: 700;
  color: var(--on-chrome); background: rgba(0,0,0,0.3); border: 1px solid var(--chrome-edge);
  border-radius: 7px; padding: 6px 10px; cursor: pointer; line-height: 1; }
.nb-pg-btn:hover { background: rgba(0,0,0,0.42); }
.nb-pg-btn:disabled { opacity: 0.4; cursor: default; }

/* floating rich-text toolbar — fixed to the top of the viewport, revealed only
   while text is selected inside a notebook. */
.fmt-bar {
  position: fixed; top: 14px; left: 50%; transform: translateX(-50%) translateY(-8px);
  z-index: 60; display: flex; gap: 4px; padding: 6px;
  background: var(--chrome); backdrop-filter: blur(10px);
  border: 1px solid var(--chrome-edge); border-radius: 10px;
  box-shadow: 0 10px 28px rgba(0,0,0,0.4);
  opacity: 0; pointer-events: none; transition: opacity 0.16s ease, transform 0.16s ease;
}
.fmt-bar.show { opacity: 1; pointer-events: auto; transform: translateX(-50%) translateY(0); }
.fmt-btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 34px; height: 32px; padding: 0 10px;
  font-family: var(--ui); font-size: 0.95rem; font-weight: 700;
  color: var(--on-chrome); background: rgba(0,0,0,0.25);
  border: 1px solid var(--chrome-edge); border-radius: 7px; cursor: pointer;
}
.fmt-btn:hover { background: rgba(0,0,0,0.4); }
.fmt-btn.active { background: var(--accent); color: var(--on-accent); border-color: transparent; }
.fmt-btn .fmt-bullet { font-size: 1.1rem; line-height: 1; }

/* ----------------------------------------------------------------- settings */
.set-h { font-family: var(--mono); font-size: 0.7rem; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--muted); margin: 26px 0 6px; }
.set-note { font-family: var(--hand); font-size: calc(1.2rem * var(--hand-scale));
  color: var(--ink-soft); margin: 0 0 12px; }
.font-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 10px; }
.font-card {
  position: relative; text-align: left; cursor: pointer;
  display: flex; flex-direction: column; gap: 4px;
  background: #fff; border: 2px solid var(--sand);
  border-radius: var(--radius); padding: 12px 14px;
  transition: border-color var(--dur) var(--ease);
}
.font-card:hover { border-color: var(--muted); }
.font-card.selected { border-color: var(--accent); background: var(--blush); }
.font-sample { font-size: 1.6rem; color: var(--ink); line-height: 1.1; }
.font-meta { display: flex; flex-direction: column; }
.font-name { font-family: var(--ui); font-weight: 700; font-size: 0.85rem; color: var(--ink); }
.font-vibe { font-family: var(--ui); font-size: 0.72rem; color: var(--muted); }
.font-tick { position: absolute; top: 10px; right: 12px; color: var(--accent);
  opacity: 0; font-weight: 700; }
.font-card.selected .font-tick, .mode-card.selected .font-tick { opacity: 1; }

.set-modes { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.mode-card {
  position: relative; text-align: left; cursor: pointer;
  display: flex; flex-direction: column; gap: 4px;
  background: #fff; border: 2px solid var(--sand);
  border-radius: var(--radius); padding: 14px;
  transition: border-color var(--dur) var(--ease);
}
.mode-card.selected { border-color: var(--accent); background: var(--blush); }
.mode-card-h { font-family: var(--hand); font-size: 1.5rem; color: var(--ink); }
.mode-card-d { font-family: var(--ui); font-size: 0.78rem; color: var(--ink-soft); }
.set-link { display: inline-block; font-family: var(--ui); font-weight: 700;
  font-size: 0.85rem; color: var(--accent); margin: 8px 0; text-decoration: none; }
.set-signout { display: block; margin-top: 12px; font-family: var(--ui); font-weight: 700;
  font-size: 0.82rem; color: var(--ink); background: transparent;
  border: 0; box-shadow: inset 0 0 0 2px var(--ink);
  border-radius: 22px; padding: 10px 18px; cursor: pointer; }

/* Jinsei OS upsell — a pinned card on the settings page. */
.upsell { border-radius: 14px; padding: 16px 18px; background: var(--blush);
  box-shadow: inset 0 0 0 2px var(--accent); }
.upsell-h { font-family: var(--hand); font-size: calc(1.8rem * var(--hand-scale));
  color: var(--ink); margin: 0 0 4px; }
.upsell-d { font-family: var(--ui); font-size: 0.82rem; line-height: 1.5;
  color: var(--ink-soft); margin: 0 0 12px; }
.upsell-cta { display: inline-block; font-family: var(--ui); font-weight: 700;
  font-size: 0.82rem; color: var(--on-accent); background: var(--accent);
  border-radius: 22px; padding: 9px 18px; text-decoration: none; }
.side-upsell { color: rgba(251,243,231,0.55) !important; }

/* ----------------------------------------------------------------- modal */
.modal-scrim {
  position: fixed; inset: 0; z-index: 40;
  display: grid; place-items: center;
  background: rgba(20,16,10,0.5);
  opacity: 0; pointer-events: none;
  transition: opacity 0.2s ease;
  padding: 20px;
}
.modal-scrim.show { opacity: 1; pointer-events: auto; }
.modal-card {
  width: min(420px, 100%);
  background: var(--paper);
  border-radius: 6px 8px 8px 6px;
  box-shadow: 0 18px 50px rgba(0,0,0,0.4);
  padding: 22px 22px 18px;
  transform: translateY(10px) rotate(-0.4deg);
  transition: transform 0.2s ease;
}
.modal-scrim.show .modal-card { transform: translateY(0) rotate(-0.4deg); }
.modal-title { font-family: var(--hand); font-size: calc(1.7rem * var(--hand-scale));
  color: var(--ink); margin: 0 0 8px; }
.modal-msg { font-family: var(--hand); font-size: calc(1.2rem * var(--hand-scale));
  color: var(--ink-soft); margin: 0 0 18px; line-height: 1.35; }
.modal-actions { display: flex; justify-content: flex-end; gap: 8px; }
.modal-btn { font-family: var(--ui); font-weight: 700; font-size: 0.85rem;
  border-radius: 22px; padding: 10px 18px; cursor: pointer;
  border: 2px solid var(--sand); background: #fff; color: var(--ink); }
.modal-cancel:hover { filter: brightness(0.97); }
.modal-ok { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.modal-ok.danger { background: var(--over); border-color: var(--over); color: #fff; }
.modal-ok:hover { filter: brightness(1.05); }

/* conversion button living in the stage tools next to the period arrows */
.tool-convert { font-family: var(--ui); font-weight: 700; font-size: 0.8rem;
  border: 2px solid var(--sand); background: #fff; color: var(--ink);
  border-radius: var(--radius); padding: 5px 12px; cursor: pointer; }
.tool-convert:hover { filter: brightness(0.97); }

/* new-task priority pre-toggle on the write line */
.tl-add-row { display: flex; align-items: center; gap: 6px; }
.add-prio { flex: none; font-family: var(--ui); font-size: 1.1rem; line-height: 1;
  color: var(--ink-faint); background: none; border: none; cursor: pointer;
  padding: 0 2px; margin-left: 44px; opacity: 0.5; }
.add-prio.on { color: var(--terracotta); opacity: 1; }
.tl-add-row .tl-add { padding-left: 8px; flex: 1; }

/* ------------------------------------------------------------ calendar roller */
.roller { padding: 6px 14px 12px; border-top: 1px solid rgba(251,243,231,0.12);
  border-bottom: 1px solid rgba(251,243,231,0.12); margin: 6px 0; }
.roller-head { display: flex; align-items: center; justify-content: space-between; gap: 6px; }
.roller-title { font-family: var(--hand); font-size: 1.15rem; color: var(--cream); }
.roller-nav { display: flex; gap: 4px; }
.roller-arrow { width: 26px; height: 26px; border-radius: 6px; cursor: pointer;
  border: 1px solid rgba(251,243,231,0.2); background: rgba(251,243,231,0.06);
  color: var(--cream); font-size: 1rem; line-height: 1; }
.roller-arrow:hover { background: rgba(251,243,231,0.14); }
.roller-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; margin-top: 8px; }
.roller-dow { font-family: var(--ui); font-size: 0.6rem; text-transform: uppercase;
  letter-spacing: 0.04em; text-align: center; color: rgba(251,243,231,0.45); padding-bottom: 2px; }
.roller-cell { aspect-ratio: 1; display: grid; place-items: center; cursor: pointer;
  font-family: var(--ui); font-size: 0.78rem; color: rgba(251,243,231,0.85);
  border-radius: 6px; border: 1px solid transparent; background: none; }
.roller-cell:hover { background: rgba(251,243,231,0.1); }
.roller-cell.other { color: rgba(251,243,231,0.28); }
.roller-cell.today { border-color: var(--accent); }
.roller-cell.sel { background: var(--accent); color: var(--on-accent); font-weight: 700; }
.roller-cell.has::after { content: ''; position: absolute; }
.roller-cell.dot { position: relative; }
.roller-cell.dot::after { content: ''; position: absolute; bottom: 4px; left: 50%;
  transform: translateX(-50%); width: 4px; height: 4px; border-radius: 50%;
  background: var(--accent); }
.roller-week { display: flex; flex-direction: column; gap: 2px; margin-top: 8px; }
.roller-wrow { display: flex; align-items: center; justify-content: space-between;
  font-family: var(--ui); font-size: 0.78rem; color: rgba(251,243,231,0.85);
  padding: 5px 8px; border-radius: 6px; cursor: pointer; border: 1px solid transparent; background: none; }
.roller-wrow:hover { background: rgba(251,243,231,0.1); }
.roller-wrow.today { border-color: var(--accent); }
.roller-wrow.sel { background: var(--accent); color: var(--on-accent); font-weight: 700; }

/* --------------------------------------------------------------- responsive */
@media (max-width: 820px) {
  .topbar-mobile { display: flex; }
  .app { display: block; }
  .side-close { display: block; }
  .sidebar-scrim { display: block; }
  .sidebar {
    position: fixed; top: 0; left: 0; height: 100vh; z-index: 25;
    transform: translateX(-104%); transition: transform 0.28s cubic-bezier(.4,0,.2,1);
    box-shadow: 0 0 40px rgba(0,0,0,0.5);
  }
  .sidebar.open { transform: translateX(0); }
  .stage { height: 100vh; padding: calc(56px + 16px) 12px 80px; }
  .stage-tools, .paper, .nb-list, .page-h, .view-root { width: 100%; }
  /* clear the fixed mobile top bar */
  .fmt-bar { top: calc(56px + 8px); }
}

@media (max-width: 560px) {
  :root { --pad-t: 26px; --pad-r: 18px; --pad-b: 56px; --pad-l: 60px; }
  .sheet-title { font-size: calc(1.7rem * var(--hand-scale)); }
  .tl { grid-template-columns: 14px 28px 1fr; }
  .tl-margin { left: -42px; width: 36px; }
  /* keep the full-page bleed (so the row rule still spans the width) but shrink
     the text indent to match the tighter phone margin column. */
  .tl-add { padding: 0 var(--pad-r) 0 calc(var(--pad-l) + 42px); }
  .sheet-loading { padding-left: 42px; }
  /* keep the wide notebook margin proportionate on phones */
  .paper.notebook { --rule-x: clamp(72px, 22vw, 112px); }
  .set-modes { grid-template-columns: 1fr; }
  .font-grid { grid-template-columns: 1fr; }
  .cover-title { font-size: 2.6rem; }
}

/* Honour reduced-motion: skip the ink draw-on animations. */
@media (prefers-reduced-motion: reduce) {
  .ink-check path, .ink-strike path { transition: none !important; }
}
