/* ==========================================================================
   MHUB — draughting paper
   --------------------------------------------------------------------------
   The subject is a personal hub for someone who draws parametric CAD models,
   so the paper here is engineering grid paper, not aged parchment: cool,
   ruled, precise. Graphite on a gridded sheet.

   One rule governs colour: red is *only* ever "overdue". The margin rule, the
   markers on late tasks — that is the whole palette's saturation budget.
   Everything else is ink, pencil and paper, so the one red thing on screen is
   unmissable without needing to shout.

   Hand-written, no build step. The grid is a repeating gradient and the paper
   fibre is an inline SVG data URI, so the strict CSP in deploy/Caddyfile needs
   no exception and the page makes no network request for its texture.
   ========================================================================== */

/* --------------------------------------------------------------- typefaces */
/* Self-hosted: font-src 'self' allows no CDN. latin-ext is not optional — it
   carries the Lithuanian diacritics (ą č ę ė į š ų ū ž). */

@font-face {
  font-family: 'Plex Sans';
  src: url('/static/fonts/ibm-plex-sans-latin-400.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191,
    U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Plex Sans';
  src: url('/static/fonts/ibm-plex-sans-latin-ext-400.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
  unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF,
    U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Plex Sans';
  src: url('/static/fonts/ibm-plex-sans-latin-600.woff2') format('woff2');
  font-weight: 600; font-style: normal; font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191,
    U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Plex Sans';
  src: url('/static/fonts/ibm-plex-sans-latin-ext-600.woff2') format('woff2');
  font-weight: 600; font-style: normal; font-display: swap;
  unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF,
    U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Plex Mono';
  src: url('/static/fonts/ibm-plex-mono-latin-400.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191,
    U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Plex Mono';
  src: url('/static/fonts/ibm-plex-mono-latin-ext-400.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
  unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF,
    U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Plex Mono';
  src: url('/static/fonts/ibm-plex-mono-latin-500.woff2') format('woff2');
  font-weight: 500; font-style: normal; font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191,
    U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Plex Mono';
  src: url('/static/fonts/ibm-plex-mono-latin-ext-500.woff2') format('woff2');
  font-weight: 500; font-style: normal; font-display: swap;
  unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF,
    U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ------------------------------------------------------------------ tokens */

:root {
  color-scheme: light dark;

  --paper:      #edeff0;   /* the sheet: cool drafting stock, never cream   */
  --sheet:      #f7f8f9;   /* a second sheet laid on top: inputs, panels    */
  --rule:       #d3d9dc;   /* the printed grid                             */
  --ink:        #1c2024;   /* graphite                                     */
  --ink-soft:   #6b7480;   /* pencil, for anything secondary               */
  --pencil-red: #cc2936;   /* reserved. means overdue. nothing else.        */

  --grid:       24px;      /* the ruling, and the layout module            */
  --hairline:   1px;
  --tap:        44px;
  --margin-w:   14.5rem;   /* the notebook's left margin                   */
  --tabbar-h:   3.5rem;
  --measure:    46rem;     /* line length cap, for readable text           */

  --t-xs:   0.6875rem;
  --t-sm:   0.8125rem;
  --t-body: 0.9375rem;
  --t-lg:   1.0625rem;
  --t-xl:   1.75rem;

  --sans: 'Plex Sans', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
  --mono: 'Plex Mono', ui-monospace, 'SF Mono', 'Cascadia Mono', Consolas, monospace;

  --fibre-opacity: 0.5;
  --grid-strength: 1.3;
  --ease: cubic-bezier(0.2, 0, 0.2, 1);
}

@media (prefers-color-scheme: dark) {
  :root {
    /* Night is the blueprint half of the same world: the ground goes deep and
       blue-shifted, the ruling glows faintly, the ink turns to chalk. */
    --paper:      #14181d;
    --sheet:      #1b2027;
    --rule:       #333d49;
    --ink:        #e6ebf0;
    --ink-soft:   #8c97a3;
    --pencil-red: #ff5f5f;

    --fibre-opacity: 0.32;
    /* The ruling needs more contrast against a dark ground than a light one to
       read as the same paper — but only just: text sits on top of it. */
    --grid-strength: 1.3;
  }
}

/* ------------------------------------------------------------------- reset */

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  font-family: var(--sans);
  font-size: var(--t-body);
  line-height: 1.55;
  color: var(--ink);
  background-color: var(--paper);
  /* Paper fibre. An SVG turbulence field as a data: URI — no request, and
     img-src allows data:, so the CSP stays strict. */
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='f'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23f)' opacity='0.055'/%3E%3C/svg%3E");
  background-repeat: repeat;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

a { color: inherit; }

h1, h2, h3 { font-weight: 600; letter-spacing: -0.015em; }

:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
  border-radius: 2px;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  padding: 0.75rem 1rem;
  background: var(--sheet);
  border: var(--hairline) solid var(--ink);
}
.skip-link:focus { left: 0.5rem; top: 0.5rem; }

/* ------------------------------------------------------------------- shell */

.shell { min-height: 100dvh; }

/* The gridded sheet. Ruled both ways, aligned to --grid, so every rule and
   row in the interface lands on the paper's own lines. */
.main {
  --line: color-mix(in srgb, var(--rule) calc(78% * var(--grid-strength)), transparent);
  background-image:
    repeating-linear-gradient(to right, var(--line) 0 var(--hairline), transparent var(--hairline) var(--grid)),
    repeating-linear-gradient(to bottom, var(--line) 0 var(--hairline), transparent var(--hairline) var(--grid));
  background-position: 0 0;
  padding: calc(var(--grid) * 1.25) var(--grid);
  padding-bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom) + var(--grid) * 2);
  min-height: 100dvh;
}

.sheet { max-width: var(--measure); }

.main--bare {
  display: grid;
  place-items: center;
  padding-bottom: var(--grid);
}

/* ------------------------------------------------------- margin (desktop nav) */

.sidebar { display: none; }

.brand {
  font-family: var(--mono);
  font-size: var(--t-xs);
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink);
  padding-bottom: calc(var(--grid) * 1.25);
}

.nav-list {
  list-style: none;
  margin: 0;
  padding: 0;
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
}

.nav-link {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  min-height: 2.25rem;
  padding: 0 0.5rem 0 0;
  text-decoration: none;
  color: var(--ink-soft);
  transition: color 120ms var(--ease);
}
.nav-link:hover { color: var(--ink); }

/* The current page is marked the way you'd mark it by hand: a short bar in
   the margin, not a filled pill. */
.nav-link.is-active {
  color: var(--ink);
  font-weight: 600;
}
.nav-link.is-active::before {
  content: '';
  position: absolute;
  left: 0;
  /* Explicitly centred: an absolutely positioned pseudo-element inside a flex
     row otherwise lands at its static position, which is the top. */
  top: 50%;
  transform: translateY(-50%);
  width: 3px;
  height: 1.05rem;
  background: var(--ink);
}
.nav-list li { position: relative; padding-left: 0.9rem; }

.nav-link.is-pending { color: color-mix(in srgb, var(--ink-soft) 55%, transparent); cursor: default; }
.nav-link.is-pending:hover { color: color-mix(in srgb, var(--ink-soft) 55%, transparent); }

.nav-icon, .tab-icon {
  width: 1.05rem;
  height: 1.05rem;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.badge {
  margin-left: auto;
  font-family: var(--mono);
  font-style: normal;
  font-size: 0.5625rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-soft);
  opacity: 0.7;
}

.sidebar-foot {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding-top: 0.75rem;
  border-top: var(--hairline) solid var(--rule);
}

.who {
  flex: 1;
  font-family: var(--mono);
  font-size: var(--t-xs);
  color: var(--ink-soft);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ----------------------------------------------------------------- tab bar */

.tabbar {
  position: fixed;
  inset: auto 0 0 0;
  z-index: 20;
  display: flex;
  background: var(--paper);
  border-top: var(--hairline) solid var(--rule);
  padding-bottom: env(safe-area-inset-bottom);
}

.tab {
  flex: 1;
  min-height: var(--tabbar-h);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.25rem;
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.06em;
  text-decoration: none;
  color: var(--ink-soft);
  position: relative;
}
.tab.is-active { color: var(--ink); }
/* Same marker as the desktop margin, rotated to the top edge. */
.tab.is-active::before {
  content: '';
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 1.75rem;
  height: 2px;
  background: var(--ink);
}

/* --------------------------------------------------------------- headings */

.page-title {
  margin: 0 0 calc(var(--grid) * 1.25);
  font-size: var(--t-xl);
  line-height: 1.15;
  letter-spacing: -0.028em;
}

/* Section labels are set in mono because they name *data*, not prose. */
.section-title {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  margin: 0 0 0.5rem;
  font-family: var(--mono);
  font-size: var(--t-xs);
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.count { font-variant-numeric: tabular-nums; opacity: 0.75; }

/* The one place colour is spent. */
.task-section.is-danger .section-title { color: var(--pencil-red); }

.muted { color: var(--ink-soft); }

/* --------------------------------------------------------------- capture */

.quick-add {
  display: flex;
  align-items: stretch;
  gap: 0;
  margin-bottom: calc(var(--grid) * 1.25);
  /* Softer at rest, full ink on focus — the line itself is the focus indicator. */
  border-bottom: 1.5px solid color-mix(in srgb, var(--ink) 32%, transparent);
  transition: border-color 120ms var(--ease);
}

/* Matched on [type] so this beats the generic `input[type="text"]` block further
   down the file — equal specificity would otherwise let the later rule win and
   put a box back around the capture line. */
.quick-add input[type="text"] {
  flex: 1;
  min-width: 0;
  /* Written *on* the sheet, not into a box. */
  border: none;
  border-radius: 0;
  background: none;
  min-height: 0;
  padding: 0.5rem 0.25rem;
  font-size: 1rem;          /* 16px: anything less and iOS zooms on focus */
  color: var(--ink);
}
.quick-add input[type="text"]:focus,
.quick-add input[type="text"]:focus-visible { outline: none; border: none; }
.quick-add input::placeholder { color: var(--ink-soft); opacity: 0.7; }
.quick-add:focus-within { border-bottom-color: var(--ink); }

.quick-add button {
  flex: none;
  padding: 0 0.25rem 0 0.75rem;
  font-family: var(--mono);
  font-size: var(--t-xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-soft);
  background: none;
  border: none;
  cursor: pointer;
  transition: color 120ms var(--ease);
}
.quick-add button:hover { color: var(--ink); }

/* ------------------------------------------------------------------ tasks */

.task-section + .task-section { margin-top: calc(var(--grid) * 1.5); }

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

/* No row separator: the sheet is already ruled, and a second horizontal line
   system fighting the first is the kind of noise this design exists to avoid. */
.task {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  padding: 0.35rem 0;
}

/* Late work gets a red pencil stroke in the margin of its own row. */
.task-section.is-danger .task {
  box-shadow: inset 2px 0 0 var(--pencil-red);
  padding-left: 0.6rem;
}

.task-toggle { display: flex; flex: none; }

.checkbox {
  display: grid;
  place-items: center;
  width: var(--tap);
  height: var(--tap);
  margin: -0.45rem -0.5rem -0.45rem -0.65rem;
  background: none;
  border: none;
  cursor: pointer;
  color: var(--ink-soft);
  transition: color 120ms var(--ease);
}
/* Drawn at pencil weight: the box is a mark on the page, not a control that
   outweighs the task it belongs to. */
.checkbox svg {
  width: 0.8rem;
  height: 0.8rem;
  padding: 2px;
  fill: none;
  stroke: currentColor;
  stroke-width: 3;
  stroke-linecap: round;
  stroke-linejoin: round;
  border: 1px solid currentColor;
  border-radius: 2px;
  opacity: 0.55;
  stroke-dasharray: 26;
  stroke-dashoffset: 26;
  transition: stroke-dashoffset 160ms var(--ease), opacity 120ms var(--ease);
}
.checkbox:hover { color: var(--ink); }
.checkbox:hover svg { opacity: 1; }
/* Done is graphite, not red: red is spoken for. */
.checkbox.is-checked { color: var(--ink); }
.checkbox.is-checked svg { stroke-dashoffset: 0; opacity: 1; }

.task-body { flex: 1; min-width: 0; padding-top: 0.3rem; }

.task-title { overflow-wrap: anywhere; }
.task.is-done .task-title {
  color: var(--ink-soft);
  text-decoration: line-through;
  text-decoration-thickness: 1px;
}

.task-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin-top: 0.1rem;
  font-family: var(--mono);
  font-size: var(--t-xs);
  color: var(--ink-soft);
}

.due { font-variant-numeric: tabular-nums; }
.task-section.is-danger .due { color: var(--pencil-red); }

/* The '#' stays in the markup rather than becoming ::before content, so the tag
   can be selected and copied as the user actually typed it. */
.tag { color: var(--ink-soft); }

.repeat { opacity: 0.7; }

/* Priority is a count of marks, the way you'd underscore something twice. The
   number of marks is the level; a second encoding in opacity would be decoration. */
.prio { letter-spacing: -0.12em; color: var(--ink); }

.task-edit {
  flex: none;
  opacity: 0;
  transition: opacity 120ms var(--ease);
}
.task:hover .task-edit,
.task-edit:focus-visible { opacity: 0.6; }
.task-edit:hover { opacity: 1; }
/* Touch has no hover, so the control must always be reachable. */
@media (hover: none) {
  .task-edit { opacity: 0.5; }
}

.empty {
  font-family: var(--mono);
  font-size: var(--t-sm);
  color: var(--ink-soft);
  padding: calc(var(--grid) * 1.5) 0;
}

/* ------------------------------------------------------------------ forms */

.task--editing { display: block; padding: 0.75rem 0; }
.task-form { width: 100%; }

label {
  display: block;
  margin-bottom: 0.25rem;
  font-family: var(--mono);
  font-size: var(--t-xs);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

input[type="text"], input[type="password"], input[type="date"],
input[type="time"], input[type="search"], textarea, select {
  width: 100%;
  min-height: var(--tap);
  padding: 0.4rem 0.6rem;
  font-family: var(--sans);
  font-size: 1rem;
  color: var(--ink);
  background: var(--sheet);
  border: var(--hairline) solid var(--rule);
  border-radius: 2px;
}
input:focus-visible, textarea:focus-visible, select:focus-visible {
  border-color: var(--ink);
  outline: none;
}
textarea { min-height: 5rem; resize: vertical; line-height: 1.5; }

.stack > * + * { margin-top: 0.85rem; }
.field-row { display: flex; gap: 0.75rem; }
.field-row > * { flex: 1; min-width: 0; }

.form-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin-top: 1rem;
}

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 2.5rem;
  padding: 0 1.1rem;
  font-family: var(--mono);
  font-size: var(--t-xs);
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--paper);
  background: var(--ink);
  border: var(--hairline) solid var(--ink);
  border-radius: 2px;
  cursor: pointer;
  transition: opacity 120ms var(--ease);
}
.button:hover { opacity: 0.85; }
.button--full { width: 100%; }

.button--quiet {
  color: var(--ink-soft);
  background: none;
  border-color: var(--rule);
}
.button--quiet:hover { color: var(--ink); border-color: var(--ink); opacity: 1; }

.button--danger {
  margin-left: auto;
  color: var(--pencil-red);
  background: none;
  border-color: color-mix(in srgb, var(--pencil-red) 45%, transparent);
}
.button--danger:hover { border-color: var(--pencil-red); opacity: 1; }

.icon-button {
  display: grid;
  place-items: center;
  width: var(--tap);
  height: var(--tap);
  color: var(--ink-soft);
  background: none;
  border: none;
  border-radius: 2px;
  cursor: pointer;
}
.icon-button:hover { color: var(--ink); }

/* ------------------------------------------------------------- messages */

.flash:empty { display: none; }

.alert {
  padding: 0.6rem 0.8rem;
  margin-bottom: var(--grid);
  font-size: var(--t-sm);
  border-radius: 2px;
}
.alert--error {
  color: var(--pencil-red);
  border: var(--hairline) solid color-mix(in srgb, var(--pencil-red) 40%, transparent);
  background: color-mix(in srgb, var(--pencil-red) 7%, transparent);
}

/* ------------------------------------------------------------------ login */

.login { width: min(21rem, 100%); }

.login .brand {
  padding-bottom: 0;
  margin-bottom: 0.4rem;
}

.login-lede {
  margin: 0 0 calc(var(--grid) * 1.25);
  font-size: var(--t-sm);
  color: var(--ink-soft);
}

/* A panel laid on the sheet, held by a hairline rather than a shadow. */
.panel {
  padding: calc(var(--grid) * 1.1);
  background: var(--sheet);
  border: var(--hairline) solid var(--rule);
  border-radius: 2px;
}

/* --------------------------------------------------------- pending modules */

.pending-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.15rem;
  font-family: var(--mono);
  font-size: var(--t-xs);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-soft);
  opacity: 0.75;
}
.pending-list li { display: flex; align-items: center; gap: 0.4rem; }

.rule {
  height: var(--hairline);
  margin: calc(var(--grid) * 1.5) 0 var(--grid);
  background: var(--rule);
  border: none;
}

/* ------------------------------------------------------------------- tabs */

.tabs {
  display: flex;
  gap: 1.15rem;
  margin-bottom: calc(var(--grid) * 1.25);
  overflow-x: auto;
  scrollbar-width: none;
  border-bottom: var(--hairline) solid var(--rule);
}
.tabs::-webkit-scrollbar { display: none; }

.tabs-link {
  flex: none;
  padding: 0 0 0.5rem;
  font-family: var(--mono);
  font-size: var(--t-xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--ink-soft);
  border-bottom: 1.5px solid transparent;
  margin-bottom: -1px;
  transition: color 120ms var(--ease);
}
.tabs-link:hover { color: var(--ink); }
.tabs-link.is-active { color: var(--ink); border-bottom-color: var(--ink); }

/* ---------------------------------------------------------- desktop ≥ 52em */

@media (min-width: 52em) {
  .shell {
    display: grid;
    grid-template-columns: var(--margin-w) 1fr;
  }

  .sidebar {
    display: flex;
    flex-direction: column;
    position: sticky;
    top: 0;
    height: 100dvh;
    padding: calc(var(--grid) * 1.25) var(--grid);
    /* THE SIGNATURE — the red margin rule of a ruled exercise book, and the
       only red on a page with nothing overdue. */
    border-right: var(--hairline) solid color-mix(in srgb, var(--pencil-red) 55%, transparent);
  }

  .main {
    padding: calc(var(--grid) * 1.75) calc(var(--grid) * 1.75);
    padding-bottom: calc(var(--grid) * 2);
  }

  .tabbar { display: none; }

  .page-title { font-size: 2rem; }
}

/* ================================================================== notes
 *
 * Notes sit on the same ruled sheet as everything else — no cards, no boxes,
 * just entries divided by the ruling that is already there.
 *
 * The one new idea is the split between writing and reading. The editor is set
 * in mono because what you are editing is *source*: hashes, hyphens and back-
 * ticks that only line up if the glyphs are the same width. The reading pane
 * beside it is set in sans, because what it shows is prose. You can tell which
 * pane you are looking at without reading a word of it.
 */

/* The prose measure is right for prose and wrong for a two-pane editor, so the
   note page opts out of it rather than the cap being loosened for every page. */
.sheet--wide { max-width: 74rem; }

.breadcrumb {
  margin: 0 0 var(--grid);
  font-family: var(--mono);
  font-size: var(--t-xs);
  letter-spacing: 0.08em;
}
.breadcrumb a { color: var(--ink-soft); text-decoration: none; }
.breadcrumb a:hover { color: var(--ink); }

/* ------------------------------------------------------------ notes list */

.note-toolbar {
  display: flex;
  align-items: stretch;
  gap: 0.75rem;
  margin-bottom: calc(var(--grid) * 1.25);
}
.note-toolbar .note-search { flex: 1; min-width: 0; }
.note-toolbar .button { white-space: nowrap; }

/* Same treatment as the task capture line: a ruled line to write on, not a box.
   Matched on [type] because `.note-search input` and `input[type="search"]`
   have equal specificity and the later block would otherwise win. */
.note-search input[type="search"] {
  width: 100%;
  background: transparent;
  border: none;
  border-bottom: var(--hairline) solid var(--rule);
  border-radius: 0;
  padding-left: 0;
  font-family: var(--sans);
}
.note-search input[type="search"]:focus-visible {
  outline: none;
  border-bottom-color: var(--ink);
}

.results-count {
  margin: 0 0 0.75rem;
  font-family: var(--mono);
  font-size: var(--t-xs);
  letter-spacing: 0.08em;
  color: var(--ink-soft);
}

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

/* No row separator: the sheet is already ruled, and a second horizontal system
   fighting the first is the noise this design exists to avoid. */
.note-card {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  padding: 0.6rem 0;
}

.note-card-link {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  text-decoration: none;
  color: inherit;
}

.note-heading {
  font-size: var(--t-lg);
  line-height: 1.25;
  letter-spacing: -0.012em;
}
.note-card-link:hover .note-heading { text-decoration: underline; }

/* One line only: a list is for finding a note, not for reading it. */
.note-excerpt {
  font-size: var(--t-sm);
  color: var(--ink-soft);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.note-card-meta {
  flex: none;
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  font-family: var(--mono);
  font-size: var(--t-xs);
  color: var(--ink-soft);
  font-variant-numeric: tabular-nums;
}

/* Pinned is graphite, not colour. Red means overdue and nothing else, and a
   pinned note is not urgent — it is just near the top on purpose. */
.pin-mark { color: var(--ink); font-size: 0.6rem; }
.note-card.is-pinned .note-heading { font-weight: 600; }
.note-card.is-archived .note-heading,
.note-card.is-archived .note-excerpt { opacity: 0.6; }

/* The search hit: a wash of graphite, like something gone over with the side of
   a pencil. The saturation budget is spent entirely on overdue tasks. */
mark {
  background: color-mix(in srgb, var(--ink) 14%, transparent);
  color: inherit;
  border-radius: 1px;
  padding: 0 0.1em;
}

/* ------------------------------------------------------------ note editor */

.note-panes { display: grid; gap: calc(var(--grid) * 1.5); align-items: start; }

@media (min-width: 62rem) {
  .note-panes { grid-template-columns: 1fr 1fr; }
  /* The reading side stays put while you type, which is the whole point of
     having it beside the editor rather than below it. */
  .note-reading { position: sticky; top: var(--grid); }
}

.note-editor { display: flex; flex-direction: column; gap: 0.75rem; }

/* The title is the page's heading as much as it is a field, so it is sized like
   one and given a line to sit on rather than a box to sit in.

   Matched on [type] rather than by class alone: `input[type="text"]` scores 0,1,1
   and a bare `.note-title` only 0,1,0, so the generic field styling would win and
   put the box back. The same collision put a box around the task capture line. */
.note-title[type="text"] {
  font-size: var(--t-xl);
  font-weight: 600;
  letter-spacing: -0.028em;
  background: transparent;
  border: none;
  border-bottom: var(--hairline) solid var(--rule);
  border-radius: 0;
  padding-left: 0;
}
.note-title[type="text"]:focus-visible { outline: none; border-bottom-color: var(--ink); }

.note-body {
  min-height: 24rem;
  font-family: var(--mono);
  font-size: var(--t-sm);
  line-height: 1.6;
  tab-size: 2;
}

.note-editor-foot { display: flex; align-items: center; gap: 0.75rem; }

/* Matched on [type] for the same specificity reason as the title above. */
.note-tags[type="text"] {
  flex: 1;
  min-width: 0;
  min-height: 2rem;
  font-family: var(--mono);
  font-size: var(--t-sm);
  background: transparent;
  border: none;
  border-bottom: var(--hairline) solid var(--rule);
  border-radius: 0;
  padding-left: 0;
}
.note-tags[type="text"]:focus-visible { outline: none; border-bottom-color: var(--ink); }

.save-state {
  flex: none;
  font-family: var(--mono);
  font-size: var(--t-xs);
  letter-spacing: 0.08em;
  color: var(--ink-soft);
  font-variant-numeric: tabular-nums;
}
/* Dimmed while the save is in flight, solid once it lands. HTMX puts
   .htmx-request on the form for the duration of the exchange. */
.note-editor.htmx-request .save-state { opacity: 0.35; }

/* ----------------------------------------------------------- reading pane */

.prose { max-width: var(--measure); }
.prose > *:first-child { margin-top: 0; }
.prose > *:last-child { margin-bottom: 0; }

.prose h1, .prose h2, .prose h3, .prose h4 {
  margin: calc(var(--grid) * 1.15) 0 0.4rem;
  line-height: 1.2;
  letter-spacing: -0.02em;
}
.prose h1 { font-size: var(--t-xl); }
.prose h2 { font-size: var(--t-lg); }
.prose h3 { font-size: var(--t-body); }
.prose h4 { font-size: var(--t-sm); color: var(--ink-soft); }

.prose p { margin: 0 0 0.85rem; line-height: 1.65; }
.prose ul, .prose ol { margin: 0 0 0.85rem; padding-left: 1.35rem; }
.prose li { margin-bottom: 0.2rem; line-height: 1.6; }

.prose a { color: var(--ink); text-underline-offset: 0.15em; }

.prose code {
  font-family: var(--mono);
  font-size: 0.9em;
  background: var(--sheet);
  border: var(--hairline) solid var(--rule);
  border-radius: 2px;
  padding: 0.05em 0.3em;
}
/* Code does not reflow, so it scrolls inside its own box rather than pushing
   the whole page sideways. */
.prose pre {
  margin: 0 0 0.85rem;
  padding: 0.75rem 0.9rem;
  background: var(--sheet);
  border: var(--hairline) solid var(--rule);
  border-radius: 2px;
  overflow-x: auto;
}
.prose pre code { background: none; border: none; padding: 0; font-size: var(--t-sm); }

/* A quotation is set off by a rule, the same device the page uses down its
   own left edge. */
.prose blockquote {
  margin: 0 0 0.85rem;
  padding-left: 0.9rem;
  border-left: 2px solid var(--rule);
  color: var(--ink-soft);
}

.prose hr {
  border: none;
  border-top: var(--hairline) solid var(--rule);
  margin: var(--grid) 0;
}

.prose table {
  width: 100%;
  margin: 0 0 0.85rem;
  border-collapse: collapse;
  font-size: var(--t-sm);
}
.prose th, .prose td {
  padding: 0.35rem 0.5rem;
  border-bottom: var(--hairline) solid var(--rule);
  text-align: left;
}
.prose th {
  font-family: var(--mono);
  font-size: var(--t-xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-soft);
  font-weight: 500;
}

.prose img { max-width: 100%; height: auto; }

/* ---------------------------------------------------------------- actions */

.note-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: var(--grid);
}
.archived-mark {
  font-family: var(--mono);
  font-size: var(--t-xs);
  letter-spacing: 0.08em;
  color: var(--ink-soft);
}

/* ---------------------------------------------------------------- related */

.note-related { margin-top: calc(var(--grid) * 2); }
.related-list { list-style: none; margin: 0 0 0.75rem; padding: 0; }
.related-list li {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  padding: 0.35rem 0;
}
.related-kind {
  flex: none;
  font-family: var(--mono);
  font-size: var(--t-xs);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-soft);
  min-width: 3.2rem;
}
.related-label { flex: 1; min-width: 0; font-size: var(--t-sm); }
a.related-label { color: var(--ink); }

.link-add { display: flex; gap: 0.5rem; align-items: stretch; }
.link-add select { flex: 1; min-width: 0; font-size: var(--t-sm); }
.link-add .button { white-space: nowrap; }

/* -------------------------------------------------------- dashboard card */

.dash-notes { margin-top: calc(var(--grid) * 2); }
.section-more {
  margin-left: auto;
  font-family: var(--mono);
  font-size: var(--t-xs);
  letter-spacing: 0.08em;
  color: var(--ink-soft);
  text-decoration: none;
}
.section-more:hover { color: var(--ink); }
.note-list--compact .note-card { padding: 0.4rem 0; }
.note-list--compact .note-heading { font-size: var(--t-body); }

/* The <symbol> sprite carries no visual output of its own. This lives here rather
   than in a style attribute on the element because `style-src 'self'` discards
   those, which left the sprite occupying 300x150 at the top of every page. */
.icon-sprite { display: none; }

/* -------------------------------------------------------------- motion */

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