/* Clean flat 2.0 — Linear/shadcn-inspired. System fonts, neutral zinc palette,
   1px borders, small radii, subtle elevation. Dark mode via prefers-color-scheme. */

:root {
  --background: #fafafa;
  --surface: #ffffff;
  --foreground: #18181b;
  --muted-fg: #71717a;
  --faint: #a1a1aa;
  --border: #e4e4e7;
  --border-strong: #d4d4d8;
  --primary: #18181b;
  --primary-fg: #fafafa;
  --accent-bg: #f4f4f5;
  --ring: #a1a1aa;
  --amber: #b45309;
  --amber-bg: #fffbeb;
  --amber-border: #fde68a;
  --danger: #dc2626;
  --success: #15803d;
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.04);
  --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.06), 0 1px 3px rgba(0, 0, 0, 0.04);

  /* layout constants shared between the fixed dock and the page padding that
     keeps content out from under it — they must not drift apart */
  --tap: 44px;
  --tabbar-h: 56px;
  --dock-h: 112px;
  --sheet-radius: 18px;
  /* published by js/viewport.js from visualViewport; 0 unless a soft keyboard
     is up (iOS never resizes the layout viewport for it) */
  --kb-inset: 0px;
}

/* Dark tokens apply when the user forces dark, or in Auto mode when the
   system is dark. Forced light (data-theme="light") always wins. */
:root[data-theme="dark"] {
  --background: #09090b;
  --surface: #131316;
  --foreground: #f4f4f5;
  --muted-fg: #a1a1aa;
  --faint: #63636b;
  --border: #27272a;
  --border-strong: #3f3f46;
  --primary: #fafafa;
  --primary-fg: #18181b;
  --accent-bg: #1c1c1f;
  --ring: #52525b;
  --amber: #fbbf24;
  --amber-bg: #26200f;
  --amber-border: #453a16;
  --danger: #f87171;
  --success: #4ade80;
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
  --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.5), 0 1px 3px rgba(0, 0, 0, 0.4);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --background: #09090b;
    --surface: #131316;
    --foreground: #f4f4f5;
    --muted-fg: #a1a1aa;
    --faint: #63636b;
    --border: #27272a;
    --border-strong: #3f3f46;
    --primary: #fafafa;
    --primary-fg: #18181b;
    --accent-bg: #1c1c1f;
    --ring: #52525b;
    --amber: #fbbf24;
    --amber-bg: #26200f;
    --amber-border: #453a16;
    --danger: #f87171;
    --success: #4ade80;
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
    --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.5), 0 1px 3px rgba(0, 0, 0, 0.4);
  }
}

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

/* author display rules (e.g. flex) would otherwise beat the UA's [hidden] */
[hidden] {
  display: none !important;
}

html {
  /* no pull-to-refresh / rubber-band in a browser tab */
  overscroll-behavior-y: none;
}

body {
  background: var(--background);
  color: var(--foreground);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  /* 14px reads small at arm's length on a phone; 15 keeps the density that
     makes this app feel calm without needing a per-breakpoint scale */
  font-size: 15px;
  line-height: 1.5;
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
  overscroll-behavior-y: none;
  touch-action: manipulation; /* kills the 300ms double-tap-zoom delay */
}

/* Mobile-first: full-bleed column with room at the bottom for the fixed dock.
   The desktop column is restored at >=768px. */
.page {
  padding-left: max(16px, env(safe-area-inset-left));
  padding-right: max(16px, env(safe-area-inset-right));
  /* The keyboard term matters: the dock rides up by --kb-inset, so without it
     the last rows of a long list sit under the dock with nothing left to
     scroll. */
  padding-bottom: calc(var(--dock-h) + var(--kb-inset, 0px) + env(safe-area-inset-bottom) + 24px);
}

/* ---- views ---- */

/* Only the routed view renders. display:none (rather than visibility or
   aria-hidden) takes the others out of the accessibility tree and the tab
   order too, so nothing extra has to be bookkept. */
.view {
  display: none;
}

body[data-view="today"] #today-section,
body[data-view="inbox"] #inbox-section,
body[data-view="someday"] #someday-section,
body[data-view="more"] #more-section {
  display: block;
}

/* ---- appbar ---- */

.appbar {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  /* pays back the inset that black-translucent takes, so the date line never
     sits under the clock */
  padding: calc(env(safe-area-inset-top) + 8px) max(16px, env(safe-area-inset-left)) 8px
    max(16px, env(safe-area-inset-right));
  background: color-mix(in srgb, var(--background) 85%, transparent);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
}

#date-line {
  font-size: 16px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--foreground);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.appbar-actions {
  display: flex;
  gap: 6px;
  flex: none;
}

/* Each view gets at most two actions; the rest stay in the DOM but hidden.
   Desktop reveals them all (see the >=768px block). */
.appbar-actions .chip {
  display: none;
}

body[data-view="today"] #focus-toggle,
body[data-view="today"] #plan-btn,
body[data-view="inbox"] #review-btn {
  display: inline-flex;
}

.chip {
  position: relative;
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--muted-fg);
  font-family: inherit;
  font-size: 13.5px;
  font-weight: 500;
  padding: 0 14px;
  border-radius: 8px;
  cursor: pointer;
  box-shadow: var(--shadow-sm);
  transition: border-color 0.12s, color 0.12s, background 0.12s;
}

.chip.active {
  background: var(--primary);
  border-color: var(--primary);
  color: var(--primary-fg);
}

.badge {
  position: absolute;
  top: -3px;
  right: -3px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--danger);
  border: 2px solid var(--background);
}

/* ---- bottom dock: capture bar + tab bar ---- */

.bottom-dock {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 20;
  background: color-mix(in srgb, var(--background) 88%, transparent);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-top: 1px solid var(--border);
  padding: 8px max(12px, env(safe-area-inset-left)) 0 max(12px, env(safe-area-inset-right));
  padding-bottom: env(safe-area-inset-bottom);
  /* iOS never resizes the layout viewport for the keyboard, so a bottom-pinned
     element would sit behind it. js/viewport.js publishes the real inset. */
  transform: translateY(calc(-1 * var(--kb-inset, 0px)));
  transition: transform 0.15s ease-out;
}

/* Keyboard up: give the whole dock to the input. */
body.kb-open .bottom-dock {
  padding-bottom: 0;
}

body.kb-open .tabbar {
  display: none;
}

.capture {
  display: flex;
  gap: 8px;
  margin-bottom: 8px;
}

.capture-add {
  flex: none;
  min-height: var(--tap);
  padding: 0 18px;
  border: 1px solid var(--primary);
  border-radius: 8px;
  background: var(--primary);
  color: var(--primary-fg);
  font-size: 14.5px;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
}

.capture-add:active {
  opacity: 0.85;
}

/* Capture belongs on every list — GTD's premise is capturing the instant a
   thought arrives — but More is settings, and there is nothing to capture to. */
body[data-view="more"] .capture {
  display: none;
}

.tabbar {
  display: flex;
  align-items: stretch;
  height: var(--tabbar-h);
}

.tab {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  border: none;
  background: none;
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 500;
  color: var(--muted-fg);
  cursor: pointer;
  padding: 0 4px;
  border-radius: 8px;
  -webkit-tap-highlight-color: transparent;
  transition: color 0.12s;
}

.tab.active {
  color: var(--foreground);
  font-weight: 600;
}

.tab:active {
  background: var(--accent-bg);
}

.tab-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tab-count {
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  color: var(--muted-fg);
  background: var(--accent-bg);
  border-radius: 999px;
  padding: 1px 6px;
  min-width: 18px;
}

.tab-count:empty {
  display: none;
}

.tab.active .tab-count {
  background: var(--primary);
  color: var(--primary-fg);
}

.tab-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--danger);
}

#capture-input {
  flex: 1;
  min-width: 0;
  min-height: var(--tap);
  padding: 11px 14px;
  /* 16px is the threshold below which iOS Safari zooms the page on focus.
     Applied unconditionally — it looks fine on desktop too. */
  font-size: 16px;
  font-family: inherit;
  color: var(--foreground);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  outline: none;
  box-shadow: var(--shadow-sm);
  transition: border-color 0.12s, box-shadow 0.12s;
}

#capture-input:focus {
  border-color: var(--ring);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--ring) 20%, transparent);
}

#capture-input::placeholder {
  color: var(--faint);
}

/* ---- sections ---- */

.section {
  margin-bottom: 28px;
}

.section-head,
.recycle summary {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-bottom: 8px;
}

h2 {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted-fg);
  display: inline;
}

.section-meta {
  font-size: 11.5px;
  color: var(--muted-fg);
  font-variant-numeric: tabular-nums;
}

.tomorrow-note {
  font-size: 12px;
  color: var(--muted-fg);
  margin-bottom: 6px;
}

.hint {
  font-size: 12px;
  line-height: 1.55;
  color: var(--muted-fg);
  margin: -2px 0 10px;
  max-width: 56ch;
}

.hint strong {
  font-weight: 600;
  color: var(--foreground);
}

/* .hint-pinned survives the toggle: notices about data loss (the recycle
   bin's 30-day expiry) are warnings, not method teaching. */
body.hints-off .hint:not(.hint-pinned) {
  display: none;
}

.hint-example {
  display: flex;
  align-items: flex-start;
  gap: 8px;
}

.example-text {
  font-style: italic;
}

.example-btn {
  display: inline-grid;
  place-content: center;
  min-width: var(--tap);
  min-height: var(--tap);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--muted-fg);
  font-family: inherit;
  font-size: 13px;
  line-height: 1;
  padding: 0 8px;
  border-radius: 999px;
  cursor: pointer;
  white-space: nowrap;
  transition: border-color 0.12s, color 0.12s;
}

.dialog .hint-example {
  margin: -8px 0 16px;
}

.empty-hint {
  color: var(--muted-fg);
  font-size: 13px;
  padding: 6px 2px;
}

.recycle summary {
  cursor: pointer;
  list-style: none;
  user-select: none;
  min-height: var(--tap);
  align-items: center;
}

/* The title's usual bottom margin would lift it off the row's centre line,
   leaving the count looking sunken. */
.recycle summary .more-title {
  margin-bottom: 0;
}

.recycle summary::-webkit-details-marker {
  display: none;
}

.recycle summary::before {
  content: "▸";
  color: var(--faint);
  font-size: 9px;
  margin-right: 2px;
}

.recycle[open] summary::before {
  content: "▾";
}

/* Recycle-bin rows: muted text, per-row countdown to the 30-day prune */
.recycle .text {
  color: var(--muted-fg);
}

.expires {
  display: block;
  font-size: 11px;
  color: var(--faint);
  margin-top: 1px;
}

/* ---- task rows ---- */

.task-list {
  list-style: none;
}

#today-list {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}

#today-list:empty {
  display: none;
}

#today-list .task {
  border-radius: 0;
}

#today-list .swipe-fg {
  /* Right side hugs the action cluster — its outermost tap box already
     carries its own slack. */
  padding: 5px 8px 5px 14px;
}

#today-list .task + .task,
#today-list .bonus-divider + .task {
  border-top: 1px solid var(--border);
}

/* A row is a stack: the action background, and the foreground that slides
   over it. Only .swipe-fg moves. */
.task {
  position: relative;
  overflow: hidden;
  border-radius: 8px;
}

.swipe-fg {
  position: relative;
  display: flex;
  /* Only the migration prompt ever wraps: it is a full-width second line. */
  flex-wrap: wrap;
  row-gap: 0;
  /* The 44px controls set the row height, so top-aligning would leave dead
     space under a single line of text. */
  align-items: center;
  gap: 10px;
  padding: 4px 10px;
  /* Must be opaque, or the action background shows through at rest. */
  background: var(--background);
  transition: background 0.1s;
  /* Hands vertical scrolling to the compositor while leaving the horizontal
     axis to us. Never `none` here — that would kill scrolling over every row. */
  touch-action: pan-y;
}

#today-list .swipe-fg {
  background: var(--surface);
}

.swipe-bg {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 14px;
  background: var(--accent-bg);
  font-size: 13px;
  font-weight: 600;
}

/* The labels carry the meaning and the feedback: outlined while you're
   dragging, filled the moment the action is armed. No direction bookkeeping
   on the container. */
.bg-lead,
.bg-trail {
  padding: 7px 12px;
  border-radius: 999px;
  transition: background 0.12s, color 0.12s;
}

.bg-lead {
  color: var(--success);
}

.bg-trail {
  color: var(--muted-fg);
}

.bg-trail.danger {
  color: var(--danger);
}

.task.armed-lead .bg-lead {
  background: var(--success);
  color: var(--primary-fg);
}

.task.armed-trail .bg-trail {
  background: var(--muted-fg);
  color: var(--background);
}

.task.armed-trail .bg-trail.danger {
  background: var(--danger);
  color: var(--primary-fg);
}

.task.swiping .swipe-fg {
  transition: none;
}

#today-list .task.top .text {
  font-size: 14.5px;
  font-weight: 600;
  letter-spacing: -0.01em;
}

#today-list .bonus-divider {
  list-style: none;
  padding: 5px 14px 3px;
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted-fg);
  background: var(--accent-bg);
  border-top: 1px solid var(--border);
}

/* A 22px box centred in a full-size hit target: the checkbox stays visually
   quiet while the thing you actually tap meets the 44px minimum. */
.check-wrap {
  display: grid;
  place-items: center;
  width: var(--tap);
  height: var(--tap);
  min-width: var(--tap);
  margin: -6px 0 -6px -8px;
  cursor: pointer;
}

.task .check {
  appearance: none;
  width: 22px;
  height: 22px;
  min-width: 22px;
  border: 1.5px solid var(--border-strong);
  border-radius: 6px;
  cursor: pointer;
  display: grid;
  place-content: center;
  background: var(--surface);
  transition: background 0.1s, border-color 0.1s;
}

.task .check:checked {
  border-color: var(--primary);
  background: var(--primary);
}

.task .check:checked::before {
  content: "✓";
  color: var(--primary-fg);
  font-size: 13px;
  font-weight: 700;
  line-height: 1;
}

.task .body {
  flex: 1;
  min-width: 0;
}

.task .text {
  overflow-wrap: break-word;
  cursor: default;
}

.task.done-row .text {
  text-decoration: line-through;
  color: var(--muted-fg);
  font-weight: 400;
}

.task.locked {
  opacity: 0.4;
  pointer-events: none;
}

/* Focus mode: the one task you're working on is unmissable */
#today-list .task.focused .text {
  font-size: 2em;
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.25;
}



.migrations {
  color: var(--amber);
  font-weight: 700;
  letter-spacing: -0.06em;
  margin-left: 6px;
  font-size: 12px;
}

/* Touch shows each list's primary actions as visible buttons — swipe never
   announced itself, and there is no overflow menu. Non-primary actions are
   desktop-hover-only because their job is covered elsewhere on touch (Done
   by the checkbox, reordering hidden on done rows as noise). */
.task .actions {
  display: flex;
  gap: 0;
  transition: opacity 0.1s;
}

/* Squeeze the cluster: the 44px tap boxes stay (the touch test enforces
   them), but the glyphs are small and centred, so trimming padding and
   overlapping the boxes' dead outer edges buys the task text ~25px without
   shrinking any target below the floor. */
.task .actions .icon-btn {
  padding: 0 3px;
}

.task .actions .icon-btn + .icon-btn {
  margin-left: -6px;
}

.task .actions .icon-btn:not(.primary) {
  display: none;
}

.icon-btn svg {
  display: block;
}

.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--tap);
  min-width: var(--tap);
  border: none;
  background: none;
  color: var(--muted-fg);
  font-size: 13.5px;
  font-weight: 500;
  font-family: inherit;
  padding: 0 10px;
  border-radius: 8px;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.1s, color 0.1s;
}

.icon-btn:active {
  background: var(--accent-bg);
}

.icon-btn:disabled {
  opacity: 0.35;
  cursor: default;
}

.icon-btn:disabled:active {
  background: none;
}

.edit-input {
  width: 100%;
  font: inherit;
  font-size: 16px; /* iOS focus-zoom guard */
  color: inherit;
  background: var(--surface);
  border: 1px solid var(--ring);
  border-radius: 6px;
  padding: 2px 8px;
  outline: none;
}

/* the why: the post-it under the task */
.task .why {
  display: block;
  margin-top: 2px;
  font-size: 12.5px;
  font-weight: 400;
  line-height: 1.4;
  color: var(--muted-fg);
  overflow-wrap: break-word;
  white-space: pre-wrap;
  cursor: default;
}

.task.done-row .why,
.task.locked .why {
  display: none;
}

.why-input {
  margin-top: 4px;
}

.migration-prompt .why-input {
  margin-top: 0;
  flex-basis: 100%;
}

/* migration decision prompt */

.migration-prompt {
  flex-basis: 100%;
  margin: 0 0 6px;
  background: var(--amber-bg);
  border: 1px solid var(--amber-border);
  border-radius: 8px;
  padding: 7px 12px;
  font-size: 12.5px;
  font-weight: 400;
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.migration-prompt .q {
  color: var(--amber);
  font-weight: 500;
}

/* the choices move to the next line as a group, so Drop never sits alone */
.migration-prompt .choices {
  display: flex;
  gap: 8px;
  flex-wrap: nowrap;
}

/* ---- footer / done log ---- */

.footer {
  margin-top: 36px;
  border-top: 1px solid var(--border);
  padding-top: 14px;
}

.footer-row {
  display: flex;
  align-items: center;
  gap: 4px;
}

.footer-spacer {
  flex: 1;
}

.link-btn {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  border: none;
  background: none;
  color: var(--muted-fg);
  font-size: 13.5px;
  font-weight: 500;
  font-family: inherit;
  cursor: pointer;
  padding: 0 8px;
  border-radius: 8px;
  transition: color 0.1s, background 0.1s;
}

.link-btn:active {
  background: var(--accent-bg);
}

#done-toggle {
  color: var(--success);
}

.done-log {
  margin-top: 8px;
}

.done-log .task {
  display: flex;
  padding: 3px 10px;
  color: var(--muted-fg);
  font-size: 13px;
}

.done-log .text {
  text-decoration: line-through;
}

.history {
  margin-top: 10px;
}

.history summary {
  cursor: pointer;
  list-style: none;
  user-select: none;
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  color: var(--muted-fg);
  font-size: 13.5px;
  font-weight: 500;
  padding: 0 8px;
  border-radius: 8px;
  transition: color 0.1s, background 0.1s;
}

.history summary::-webkit-details-marker {
  display: none;
}

.history summary::before {
  content: "▸";
  color: var(--faint);
  font-size: 9px;
  margin-right: 4px;
}

.history[open] summary::before {
  content: "▾";
}

.history-date {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted-fg); /* --faint fails AA contrast at this size */
  margin: 12px 0 2px;
  padding-left: 6px;
}

/* ---- the More screen ---- */

.more-group {
  margin-bottom: 28px;
}

.more-title {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted-fg);
  margin-bottom: 8px;
  display: inline;
}

.more-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  min-height: 52px;
  padding: 0 14px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--foreground);
  font-family: inherit;
  font-size: 15px;
  text-align: left;
  cursor: pointer;
  border-radius: 10px;
  box-shadow: var(--shadow-sm);
  transition: background 0.1s, border-color 0.12s;
}

.more-row + .more-row {
  margin-top: 6px;
}

.more-row:active {
  background: var(--accent-bg);
}

.more-row-value {
  display: inline-flex;
  align-items: center;
  color: var(--muted-fg);
  font-size: 13.5px;
  flex: none;
}

.more-note {
  font-size: 12.5px;
  color: var(--muted-fg);
  margin-top: 8px;
}

/* segmented control (theme) */

.segmented {
  display: flex;
  gap: 4px;
  padding: 4px;
  border: 1px solid var(--border);
  background: var(--surface);
  border-radius: 12px;
  box-shadow: var(--shadow-sm);
}

.seg {
  flex: 1;
  min-height: var(--tap);
  border: none;
  background: none;
  border-radius: 9px;
  font-family: inherit;
  font-size: 14px;
  font-weight: 500;
  color: var(--muted-fg);
  cursor: pointer;
  transition: background 0.12s, color 0.12s;
}

.seg.active {
  background: var(--primary);
  color: var(--primary-fg);
}

.seg:not(.active):active {
  background: var(--accent-bg);
}

/* ---- toast ---- */

.toast {
  position: fixed;
  left: 12px;
  right: 12px;
  z-index: 30;
  bottom: calc(var(--dock-h) + env(safe-area-inset-bottom) + var(--kb-inset, 0px) + 12px);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 6px 8px 6px 16px;
  border-radius: 12px;
  background: var(--foreground);
  color: var(--background);
  font-size: 14px;
  box-shadow: var(--shadow-md);
  opacity: 0;
  translate: 0 8px;
  transition: opacity 0.18s, translate 0.18s;
}

.toast.show {
  opacity: 1;
  translate: 0 0;
}

.toast-action {
  flex: none;
  min-height: var(--tap);
  padding: 0 14px;
  border: none;
  border-radius: 8px;
  background: color-mix(in srgb, var(--background) 20%, transparent);
  color: inherit;
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}

/* ---- dialogs ---- */

.dialog {
  /* the * { margin: 0 } reset removes the UA's margin: auto that centers
     native dialogs — restore it */
  margin: auto;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--surface);
  color: var(--foreground);
  padding: 24px;
  width: min(520px, 92vw);
  box-shadow: var(--shadow-md);
}

.dialog::backdrop {
  background: rgba(0, 0, 0, 0.4);
  backdrop-filter: blur(2px);
}

/* ---- popup cards (mobile presentation of the dialogs) ---- */

/* The [open] qualifier is load-bearing: an unqualified author `display` beats
   the UA's `dialog:not([open]) { display: none }` and every sheet would render
   permanently. Same failure family as the [hidden] note in the reset above. */
.sheet[open] {
  display: flex;
  flex-direction: column;
}

.sheet {
  /* A floating popup card pinned near the top: the soft keyboard owns the
     bottom of the screen, so up here nothing can cover the form fields. The
     max-height still subtracts the keyboard inset so a tall card can't run
     underneath it — iOS never shrinks the layout viewport for the keyboard. */
  margin: calc(8px + env(safe-area-inset-top)) auto auto;
  width: min(520px, calc(100vw - 20px));
  max-width: none;
  /* The max() floor keeps a card usable even if --kb-inset goes bad — a
     stale visualViewport reading must degrade to "scroll the body", never to
     a card crushed to its header. */
  max-height: min(92dvh, max(280px, calc(100dvh - var(--kb-inset, 0px) - 32px)));
  border: 1px solid var(--border);
  border-radius: var(--sheet-radius);
  padding: 0;
}

/* A popup card is not draggable — the grab bar was a sheet affordance. The
   markup keeps the element so old markup and tests need no churn. */
.sheet-grab {
  display: none;
}

.sheet-head {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px 12px 8px 20px;
}

.sheet-close {
  flex: none;
  display: grid;
  place-content: center;
  width: var(--tap);
  height: var(--tap);
  border: none;
  background: none;
  border-radius: 999px;
  color: var(--muted-fg);
  font-size: 15px;
  cursor: pointer;
}

.sheet-close:active {
  background: var(--accent-bg);
}

/* The only scroller in the card. min-height:0 is required or the flex item
   refuses to shrink below its content and the card overflows instead.
   flex-basis must stay `auto` (never `flex: 1`, whose 0% basis lets older
   WebKit collapse an auto-height column container to head + foot with the
   body squeezed to nothing — Billy's phone showed exactly that). */
.sheet-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  /* No keyboard padding here — the whole sheet already moves up by the inset,
     and adding it again would push the content off the top. */
  padding: 0 20px 16px;
}

.sheet-foot {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 20px;
  border-top: 1px solid var(--border);
}

.sheet-foot-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

/* Stops the page behind a sheet from rubber-banding on iOS. */
body:has(dialog[open]) {
  overflow: hidden;
}

@media (prefers-reduced-motion: no-preference) {
  /* @starting-style + allow-discrete animate an element entering the top
     layer. Chrome 117+ / Safari 17.4+; older engines get an instant sheet that
     works identically, which is why there's no JS fallback. */
  .sheet {
    opacity: 0;
    translate: 0 -12px;
    transition: translate 0.2s ease-out, opacity 0.2s ease-out,
      overlay 0.2s allow-discrete, display 0.2s allow-discrete;
  }

  .sheet[open] {
    opacity: 1;
    translate: 0 0;
  }

  @starting-style {
    .sheet[open] {
      opacity: 0;
      translate: 0 -12px;
    }
  }

  .sheet::backdrop {
    opacity: 0;
    transition: opacity 0.28s, overlay 0.28s allow-discrete, display 0.28s allow-discrete;
  }

  .sheet[open]::backdrop {
    opacity: 1;
  }

  @starting-style {
    .sheet[open]::backdrop {
      opacity: 0;
    }
  }
}

.dialog h2 {
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -0.01em;
  text-transform: none;
  color: var(--foreground);
  display: block;
  margin-bottom: 4px;
}

.dialog-sub {
  font-size: 13px;
  color: var(--muted-fg);
  margin-bottom: 16px;
}

.review-card {
  background: var(--background);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 16px;
  margin-bottom: 14px;
  min-height: 80px;
}

.review-text {
  font-size: 14.5px;
  font-weight: 500;
  letter-spacing: -0.01em;
}

.review-meta {
  margin-top: 6px;
  font-size: 12px;
  color: var(--muted-fg);
}

.review-why-input {
  width: 100%;
  margin-top: 10px;
  font: inherit;
  font-size: 16px; /* iOS focus-zoom guard */
  color: inherit;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 5px 8px;
  outline: none;
}

.review-why-input:focus {
  border-color: var(--ring);
}

.review-card .hint {
  margin: 8px 0 0;
}

.dialog-actions {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  margin-bottom: 14px;
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--tap);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--foreground);
  font-size: 14px;
  font-weight: 500;
  font-family: inherit;
  padding: 0 16px;
  border-radius: 9px;
  cursor: pointer;
  box-shadow: var(--shadow-sm);
  transition: border-color 0.12s, background 0.12s, color 0.12s;
}

.btn:active {
  background: var(--accent-bg);
}

.btn:disabled {
  opacity: 0.4;
  cursor: default;
}

.btn:disabled:active {
  background: var(--surface);
}

.btn.danger:active {
  border-color: var(--danger);
  color: var(--danger);
  background: none;
}

#plan-save {
  background: var(--primary);
  border-color: var(--primary);
  color: var(--primary-fg);
}

#plan-save:active {
  opacity: 0.9;
  background: var(--primary);
}

.dialog-foot {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

/* plan tomorrow */

.plan-list {
  margin-bottom: 14px;
}

.plan-row {
  width: 100%;
  min-height: 52px;
  /* No .swipe-fg wrapper here, so the row itself must lay out its children. */
  display: flex;
  align-items: center;
  gap: 10px;
  font: inherit;
  color: inherit;
  text-align: left;
  background: none;
  cursor: pointer;
  border: 1px solid transparent;
  padding: 8px 10px;
}

.plan-row:active {
  background: var(--accent-bg);
}

.plan-row.selected {
  border-color: var(--border-strong);
  background: var(--accent-bg);
}

.plan-num {
  width: 20px;
  height: 20px;
  min-width: 20px;
  border-radius: 6px;
  border: 1.5px solid var(--border-strong);
  color: var(--muted-fg);
  font-size: 11px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  display: grid;
  place-content: center;
  margin-top: 1px;
}

.task.selected .plan-num {
  background: var(--primary);
  border-color: var(--primary);
  color: var(--primary-fg);
}

.plan-preview {
  border-top: 1px solid var(--border);
  padding-top: 12px;
  margin-bottom: 14px;
}

.preview-title {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted-fg);
  margin-bottom: 6px;
}

.preview-list {
  /* inside markers need inline-flow rows — don't flex these */
  list-style: decimal inside;
  font-variant-numeric: tabular-nums;
}

.preview-row {
  font-size: 13px;
  padding: 2px 0;
}

.preview-row .migrations {
  margin-left: 6px;
}

.preview-tag {
  margin-left: 6px;
  font-size: 11px;
  color: var(--muted-fg);
  border: 1px solid var(--border);
  border-radius: 5px;
  padding: 0 5px;
}

.preview-overflow {
  margin-top: 6px;
  font-size: 12px;
  color: var(--muted-fg);
}

/* ---- sync ---------------------------------------------------------------- */

.sync-dot {
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  margin-right: 5px;
  vertical-align: 1px;
  background: var(--success);
}

.sync-dot[data-state="offline"] {
  background: var(--amber);
}

.sync-dot[data-state="syncing"] {
  background: var(--faint);
}

.sync-form {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-bottom: 14px;
}

.sync-label {
  flex-basis: 100%;
  font-size: 12px;
  color: var(--muted-fg);
}

.sync-form input {
  flex: 1;
  min-width: 0;
  min-height: var(--tap);
  font: inherit;
  font-size: 16px; /* iOS focus-zoom guard */
  color: var(--foreground);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 9px;
  padding: 6px 12px;
  outline: none;
}

.sync-form input:focus {
  border-color: var(--ring);
}

.sync-account {
  font-size: 13px;
  color: var(--muted-fg);
  margin-bottom: 8px;
}

#sync-signedin {
  margin-bottom: 14px;
}

.sync-error {
  font-size: 12.5px;
  color: var(--danger);
  margin-bottom: 12px;
}

/* ---- hover enhancement -------------------------------------------------- */
/* Everything above is the touch baseline. Hover states live here, in one
   place, so a mouse gets richer feedback without touch inheriting affordances
   it can never trigger. Trailing position means these win on source order. */

@media (hover: hover) and (pointer: fine) {
  .chip:hover {
    color: var(--foreground);
    border-color: var(--border-strong);
    background: var(--accent-bg);
  }

  .example-btn:hover {
    color: var(--foreground);
    border-color: var(--border-strong);
  }

  .task .check:hover {
    border-color: var(--ring);
  }

  /* Actions stay visible on desktop too — hover-reveal made rows look empty
     and hid what the app can do. Same primary set as touch; the checkbox
     already covers Done. The mobile squeeze (zero gap, overlapped tap boxes)
     is undone here: these are small text buttons, not 44px boxes with dead
     edges to hide. */
  .task .actions {
    gap: 6px;
  }

  .task .actions .icon-btn {
    padding: 3px 7px;
  }

  .task .actions .icon-btn + .icon-btn {
    margin-left: 0;
  }

  .plain .swipe-fg:hover {
    background: var(--accent-bg);
  }

  .icon-btn:hover {
    background: var(--accent-bg);
    color: var(--foreground);
  }

  #today-list .icon-btn:hover {
    background: var(--background);
  }

  .icon-btn.danger:hover {
    color: var(--danger);
  }

  .icon-btn:disabled:hover {
    background: none;
    color: var(--muted-fg);
  }

  .migration-prompt .icon-btn:hover {
    background: color-mix(in srgb, var(--amber) 15%, transparent);
  }

  .link-btn:hover {
    color: var(--foreground);
    background: var(--accent-bg);
  }

  .history summary:hover {
    color: var(--foreground);
    background: var(--accent-bg);
  }

  .btn:hover {
    border-color: var(--border-strong);
    background: var(--accent-bg);
  }

  .btn:disabled:hover {
    border-color: var(--border);
    background: var(--surface);
  }

  .btn.danger:hover {
    border-color: var(--danger);
    color: var(--danger);
    background: none;
  }

  #plan-save:hover {
    opacity: 0.9;
    background: var(--primary);
  }

  .plan-row:hover {
    background: var(--accent-bg);
  }
}

/* ---- desktop ------------------------------------------------------------ */
/* The one width breakpoint in the file. Mobile is the base; this restores the
   centred reading column for a laptop. */

@media (min-width: 768px) {
  /* The extension's new-tab layout, faithfully: date masthead, capture bar
     right under it, then one calm 640px column of sections. The DOM stays
     mobile-first (capture lives in the dock element); flex order moves the
     dock up between the masthead and the page. */
  body {
    display: flex;
    flex-direction: column;
  }

  .appbar {
    order: 1;
    width: 100%;
    max-width: 640px;
    margin: 0 auto;
    padding: 8vh 24px 16px;
    background: none;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    position: static;
  }

  .bottom-dock {
    order: 2;
    position: static;
    width: 100%;
    max-width: 640px;
    margin: 0 auto;
    padding: 8px 24px 0;
    background: none;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    border: none;
    transform: none;
  }

  .page {
    order: 3;
    width: 100%;
    max-width: 640px;
    margin: 0 auto;
    padding: 0 24px 80px;
  }

  /* No tabs on a laptop: every section is on the page at once, the way the
     new-tab page always was. */
  .view {
    display: block;
  }

  .view + .view {
    margin-top: 28px;
  }

  .tabbar {
    display: none;
  }

  .capture {
    margin-bottom: 24px;
  }

  .appbar-actions .chip,
  body[data-view="today"] #focus-toggle,
  body[data-view="today"] #plan-btn,
  body[data-view="inbox"] #review-btn {
    display: inline-flex;
  }

  /* Settings live behind the ⚙ chip, not at the bottom of the page. The
     section node stays where the mobile shell needs it; here it presents as
     a popover anchored under the masthead's right edge. */
  #more-section {
    display: none;
  }

  body.more-open #more-section {
    display: block;
    position: fixed;
    top: calc(8vh + 52px);
    right: max(24px, calc((100vw - 640px) / 2));
    width: 400px;
    max-height: 72vh;
    overflow-y: auto;
    overscroll-behavior: contain;
    background: var(--surface);
    border: 1px solid var(--border-strong);
    border-radius: 14px;
    box-shadow: var(--shadow-md);
    padding: 18px 20px;
    z-index: 30;
  }

  /* The ⚙ chip is the title; "More" inside the popover would be noise. */
  body.more-open #more-section .section-head {
    display: none;
  }

  /* Back to a centred modal, not a sheet. */
  .sheet {
    margin: auto;
    width: min(520px, 92vw);
    max-height: 85vh;
    border: 1px solid var(--border);
    border-radius: 12px;
    translate: none;
  }

  @starting-style {
    .sheet[open] {
      translate: none;
    }
  }

  .sheet-grab {
    display: none;
  }

  .sheet-head {
    padding: 20px 12px 8px 24px;
  }

  .sheet-body {
    padding: 0 24px 16px;
  }

  .sheet-foot {
    padding: 12px 24px;
  }

  .plan-list {
    max-height: 46vh;
    overflow-y: auto;
  }

  .toast {
    left: auto;
    right: 24px;
    max-width: 380px;
  }

  /* A 44px hit box per row is right for a thumb and far too airy for a mouse. */
  .check-wrap {
    width: 24px;
    height: 24px;
    min-width: 24px;
    margin: 0;
  }

  .swipe-fg {
    align-items: flex-start;
    padding: 7px 10px;
  }

  #today-list .swipe-fg {
    padding: 11px 14px;
  }

  .check-wrap {
    margin-top: 2px;
  }

  .task .check {
    width: 17px;
    height: 17px;
    min-width: 17px;
  }

  .task .check:checked::before {
    font-size: 10px;
  }

  .chip,
  .icon-btn,
  .link-btn,
  .btn,
  .example-btn,
  .recycle summary,
  .history summary,
  #capture-input,
  .sync-form input {
    min-height: 0;
  }

  .icon-btn,
  .example-btn {
    min-width: 0;
  }

  .chip {
    padding: 5px 12px;
    font-size: 12.5px;
  }

  .icon-btn {
    padding: 3px 7px;
    font-size: 12px;
  }

  .link-btn {
    padding: 3px 6px;
    font-size: 12.5px;
  }

  .btn {
    padding: 6px 14px;
    font-size: 13px;
  }

  .example-btn {
    padding: 3px 8px;
    font-size: 11px;
  }

  .history summary {
    padding: 3px 6px;
    font-size: 12.5px;
  }

  .plan-row {
    min-height: 0;
    align-items: flex-start;
  }
}
