/* Thunk — shared theme.
 *
 * One stylesheet for the capture surface and the dashboard, served as-is with
 * no build step.
 *
 * The organising idea is a ledger, not a page. Every list in the dashboard is
 * the same three-column grid: a fixed left gutter holding a right-aligned mono
 * timestamp, a continuous hairline the timestamps hug, then content. Because
 * the gutter never changes width, the eye scans a column instead of reading
 * paragraphs, and a day's capture reads as a register rather than a feed.
 *
 * Both themes are designed rather than one derived from the other: capture
 * happens on a phone in a dark room, reading back happens at a desk in
 * daylight. Dark goes further than the dashboard on the capture surface,
 * because a bright screen at 1am is how the habit dies.
 *
 * Colour strategy is Restrained — deep tinted neutrals carry the surface and a
 * single accent stays under 10%, used only for primary action, current
 * selection, focus and links. The accent is teal-cyan rather than the indigo a
 * tool-for-thought reaches for by default, and sits on a hue that collides
 * with none of the semantic colours (success 150, warning 80, error 25,
 * info 245).
 *
 * Every pairing below is verified against WCAG AA: body text >= 4.5:1,
 * interface borders >= 1.4:1 against their ground.
 */

:root {
  color-scheme: light dark;

  /* Light — a true near-white with a faint cool tint toward the neutral hue.
     Not cream, not paper, no hidden warmth. */
  --bg:            #fbfcfe;
  --surface:       #f3f5f8;
  --raised:        #e9ecf1;
  --rule:          #d4d7de;  /* the ledger spine: quieter than a control border,
                                 but never so quiet it stops reading as a line */
  --border:        #cfd3db;
  --border-strong: #a3a8b3;
  --fg:            #171b23;
  --fg-muted:      #4e535d;
  --fg-dim:        #676b75;
  --accent:        #00727c;
  --accent-fill:   #006d76;
  --accent-ink:    #fdfdff;
  --accent-wash:   rgba(0, 114, 124, 0.09);
  --ok:            #00722e;
  --warn:          #8c5d00;
  --err:           #b32228;
  --info:          #0065a9;

  /* One family for everything, the same as the Mac notch app. */
  --font-ui:   'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, monospace;
  --font-mono: 'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, monospace;

  /* Fixed rem scale. Product UI is viewed at consistent DPI, and this is a
     dense log, so the body step sits at 14px and the mono metadata a full
     three steps below it. The gap between the two is the hierarchy. */
  --t-xs:   0.6875rem;  /* 11px — mono metadata, the gutter, chips */
  --t-sm:   0.75rem;    /* 12px — secondary, controls */
  --t-base: 0.875rem;   /* 14px — body, note summaries */
  --t-md:   1rem;
  --t-lg:   1.1875rem;
  --t-xl:   1.75rem;    /* readouts only */

  --space-1: 0.25rem; --space-2: 0.5rem;  --space-3: 0.75rem;
  --space-4: 1rem;    --space-5: 1.5rem;  --space-6: 2rem;  --space-7: 3rem;

  --radius: 4px;
  --radius-sm: 2px;

  /* The ledger geometry. --gutter is the single number the whole dashboard
     aligns to; changing it moves every timestamp, section label and rule
     together. */
  --gutter: 5rem;
  --gap: 1.1rem;
  --max-width: 920px;   /* prose measure only; the ledger is no longer capped by it */
  --rail-h: 2.75rem;

  /* The workspace shell. The rail is vertical above --w-two and the context
     panel appears above --w-three; both widths are fixed, because a nav column
     that reflows is a nav column you have to re-find. */
  --rail-w: 13.5rem;
  --aside-w: 21rem;
  --bar-h: 3.25rem;     /* the phone's bottom bar, before its safe-area inset */

  /* Exponential ease-out. No bounce, no elastic. */
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --fast: 120ms;
  --base: 180ms;

  --z-sticky: 100;
  --z-backdrop: 200;
  --z-modal: 300;
}

@media (prefers-color-scheme: dark) {
  :root {
    /* Dark — deep blue-black, never pure #000. The neutrals carry the seed's
       cobalt hue; the accent does not. The accent is pulled down off neon:
       an instrument indicator, not a highlighter. */
    --bg:            #0b0e14;
    --surface:       #131720;
    --raised:        #1b1f29;
    --rule:          #292e38;
    --border:        #2e333e;
    --border-strong: #464b57;
    --fg:            #eceef2;
    --fg-muted:      #a9adb6;
    --fg-dim:        #818691;
    --accent:        #2fc5cd;
    --accent-fill:   #00a2ac;
    --accent-ink:    #06090f;
    --accent-wash:   rgba(47, 197, 205, 0.10);
    --ok:            #6bd586;
    --warn:          #f3b94c;
    --err:           #fd736d;
    --info:          #71bfff;
  }
}

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

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

body {
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-ui);
  font-size: var(--t-base);
  line-height: 1.5;
  font-feature-settings: normal;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

::selection { background: var(--accent-wash); }

a { color: inherit; text-decoration: none; }

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

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--border);
  border-radius: 99px;
  border: 3px solid var(--bg);
}
::-webkit-scrollbar-thumb:hover { background: var(--border-strong); }

/* ---------------------------------------------------------------- type */

h1 { font-size: var(--t-lg); font-weight: 600; letter-spacing: -0.015em; text-wrap: balance; }
h2 { font-size: var(--t-base); font-weight: 600; letter-spacing: -0.01em; }
h3 { font-size: var(--t-sm); font-weight: 600; }

/* Metadata is monospaced throughout. It is what makes columns scannable and
   what gives the interface its character, in place of a display typeface. */
.mono, .meta, kbd, .num, .chip, .tag, .t {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-feature-settings: normal;
}

.meta { font-size: var(--t-xs); color: var(--fg-dim); letter-spacing: 0.01em; }
.sub  { color: var(--fg-muted); font-size: var(--t-sm); }
.dim  { color: var(--fg-dim); }

/* ---------------------------------------------------------------- controls */

button, .btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  font-family: var(--font-ui);
  font-size: var(--t-sm);
  font-weight: 500;
  line-height: 1;
  color: var(--fg-muted);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0.4rem 0.65rem;
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  transition: background var(--fast) var(--ease),
              border-color var(--fast) var(--ease),
              color var(--fast) var(--ease);
}
button:hover, .btn:hover { background: var(--raised); border-color: var(--border-strong); color: var(--fg); }
button:active, .btn:active { transform: translateY(0.5px); }

button.primary, .btn.primary {
  background: var(--accent-fill);
  border-color: var(--accent-fill);
  color: var(--accent-ink);
  font-weight: 600;
}
button.primary:hover, .btn.primary:hover {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
}

/* A quiet control for row-level actions: no chrome until you reach for it.
   Rows carry several of these and a full border on each would be a fence. */
button.ghost, .btn.ghost {
  background: transparent;
  border-color: transparent;
  color: var(--fg-dim);
  font-family: var(--font-mono);
  font-size: var(--t-xs);
  padding: 0.2rem 0.35rem;
}
button.ghost:hover, .btn.ghost:hover { background: var(--raised); border-color: var(--border); color: var(--fg); }

button:disabled, button[disabled],
button.primary:disabled, button.primary[disabled] {
  cursor: not-allowed;
  background: var(--surface);
  border-color: var(--border);
  color: var(--fg-dim);
  opacity: 0.7;
}
button:disabled:hover, button[disabled]:hover {
  background: var(--surface);
  border-color: var(--border);
  color: var(--fg-dim);
}
button.danger:hover { color: var(--err); border-color: var(--err); }

input, select, textarea {
  font-family: var(--font-ui);
  font-size: var(--t-sm);
  color: var(--fg);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0.4rem 0.55rem;
  transition: border-color var(--fast) var(--ease), background var(--fast) var(--ease);
}
input:hover, select:hover, textarea:hover { border-color: var(--border-strong); }
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-wash);
}
textarea { line-height: 1.55; resize: vertical; }
/* Placeholders carry the same contrast requirement as body text. */
::placeholder { color: var(--fg-dim); opacity: 1; }

input[type="search"], input[type="text"], input[type="date"], input[type="url"] {
  font-family: var(--font-mono);
  font-size: var(--t-xs);
}

/* A select is still a native select — a hand-built listbox is worse than the
   platform picker on a phone, and swapping one in is the "reinventing standard
   affordances" trap. Only its chrome is ours: the UA's bevel and arrow go, and
   a hairline chevron is painted in their place at the same weight as every
   other line in the interface. */
select {
  appearance: none;
  -webkit-appearance: none;
  font-family: var(--font-mono);
  font-size: var(--t-xs);
  padding-right: 1.6rem;
  background-image:
    linear-gradient(45deg, transparent 50%, currentColor 50%),
    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: right 0.75rem center, right 0.55rem center;
  background-size: 4px 4px, 4px 4px;
  background-repeat: no-repeat;
  color: var(--fg-muted);
}
select:hover { color: var(--fg); }
/* The option list is drawn by the OS, so it is the one surface here that can
   only be asked, not told. Naming both keeps it out of white-on-white. */
select option { background: var(--surface); color: var(--fg); }

/* The date field's own button is a UA asset that cannot be restyled, only
   recoloured. Inverting it in dark is the difference between a visible control
   and a black square on a black field. */
input[type="date"]::-webkit-calendar-picker-indicator {
  opacity: 0.45;
  cursor: pointer;
  transition: opacity var(--fast) var(--ease);
}
input[type="date"]:hover::-webkit-calendar-picker-indicator { opacity: 0.9; }
@media (prefers-color-scheme: dark) {
  input[type="date"]::-webkit-calendar-picker-indicator { filter: invert(1); }
}
input[type="search"]::-webkit-search-cancel-button { filter: grayscale(1); opacity: 0.5; }

/* ---------------------------------------------------------------- checkbox
   Completing a todo is the primary action of its page, so it is a control you
   can see at rest. It was a text button revealed on hover, which meant the
   page's whole purpose was invisible until the mouse happened to cross a row —
   and on touch there is no hover to cross with.

   It is a submit button rather than an <input type=checkbox> because the state
   change is a POST, not a form value; the accessible name is written by the
   template and names the todo. */
button.check {
  flex: none;
  width: 15px;
  height: 15px;
  padding: 0;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-strong);
  background: transparent;
  color: transparent;
  font-size: 10px;
  line-height: 1;
}
button.check:hover, button.check:focus-visible {
  border-color: var(--accent);
  background: var(--accent-wash);
  color: var(--accent);
}
/* Checked, i.e. reopen. Filled, because a completed todo reads as done from
   the column without reading the title. */
button.check.on {
  border-color: var(--accent-fill);
  background: var(--accent-fill);
  color: var(--accent-ink);
}
button.check.on:hover { background: var(--accent); border-color: var(--accent); }

kbd {
  font-size: var(--t-xs);
  color: var(--fg-muted);
  background: var(--raised);
  border: 1px solid var(--border);
  border-bottom-width: 2px;
  border-radius: var(--radius-sm);
  padding: 0.1rem 0.35rem;
}

/* ---------------------------------------------------------------- chips */

/* Chips are text with a hairline, never filled pills. A filled status pill on
   every row is the badge-soup that makes a log look like a ticket tracker. */
.chip {
  display: inline-flex;
  align-items: center;
  font-size: var(--t-xs);
  line-height: 1.45;
  color: var(--fg-muted);
  background: transparent;
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  padding: 0 0.3rem;
  white-space: nowrap;
}
.chip.project { color: var(--accent); border-color: color-mix(in oklab, var(--accent) 40%, transparent); }
.chip.review  { color: var(--warn); border-color: color-mix(in oklab, var(--warn) 45%, transparent); }
.chip.failed  { color: var(--err);  border-color: color-mix(in oklab, var(--err) 45%, transparent); }
.chip.live    { color: var(--ok);   border-color: color-mix(in oklab, var(--ok) 45%, transparent); }

/* A state you are waiting out is not a state you act on, so it loses its box.
   `queued` sat on most rows of a fresh register as the loudest mark on the
   page, which inverted the hierarchy: the outline drew the eye to the one fact
   that asks nothing of you. Read status in the library behaves the same way.
   `unfiled` and `failed` keep their outline, because those do ask. */
.chip.state {
  border-color: transparent;
  padding: 0;
  color: var(--fg-dim);
  font-size: var(--t-xs);
}
.chip.state.pending::before { content: "\00b7\00a0"; opacity: 0.6; }

.tag { font-size: var(--t-xs); color: var(--fg-dim); white-space: nowrap; }
.tag::before { content: "#"; opacity: 0.4; }
a.tag:hover { color: var(--accent); }

/* ---------------------------------------------------------------- notices */

.empty {
  grid-column: 2 / -1;
  color: var(--fg-dim);
  padding: var(--space-5) 0;
  font-size: var(--t-sm);
}

.warn, .flash {
  font-size: var(--t-sm);
  color: var(--fg);
  border-radius: var(--radius);
  padding: var(--space-2) var(--space-3);
  margin: var(--space-3) 0;
}
.warn  { background: color-mix(in oklab, var(--warn) 9%, transparent);   border: 1px solid color-mix(in oklab, var(--warn) 32%, transparent); }
.flash { background: var(--accent-wash); border: 1px solid color-mix(in oklab, var(--accent) 32%, transparent); }

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