:root {
  color-scheme: light dark;

  --bg: #f5f6f8;
  --surface: #ffffff;
  --surface-2: #f0f1f4;
  --text: #1c1e21;
  --text-dim: #6b7078;
  --border: #e3e5e9;
  /* Darkened from the original #5b6ef5 — that combo with white text was
     4.21:1, just under WCAG AA's 4.5:1 minimum for normal-size text (used
     on the "today" badge and the Add button). This is 5.98:1. */
  --accent: #4655d9;
  --accent-text: #ffffff;

  --template: #7c5cff;
  --toddle: #e08a1e;
  --outlook: #1e88e5;
  --personal: #16a34a;
  --veracross: #0d9488;
  --tennis-boys: #9f1239;
  --tennis-girls: #db2777;
  /* Lighter than --tennis-boys on purpose — practice, not a game. */
  --tennis-practice: #e11d48;
  /* Subject colors: keyed off class/assignment title (app/subjects.py),
     not source — an AP Bio assignment synced from any feed reads as the
     same green as the AP Biology block. Deliberately distinct hues from
     the source colors above even where the same "color family" was
     requested (blue/green/orange), so a class block is never visually
     confusable with an Outlook/personal/Toddle entry that happens to
     land on the same day. */
  --subject-calc: #2563eb;
  --subject-bio: #15803d;
  --subject-history: #c2410c;
  /* "White" for Study Block/Office Hours/CQ — literal white would be
     invisible against this theme's near-white surface, so this reuses
     --text (already the theme-aware "ink" color: dark in light mode,
     near-white in dark mode) rather than a hardcoded hex. */
  --subject-neutral: var(--text);
  /* Was a flat #ef4444 for both modes — 3.76:1 on white, under the 4.5:1
     text minimum. Theme-aware like the other source colors: 6.47:1 here. */
  --danger: #b91c1c;

  --shadow: 0 1px 2px rgba(20, 20, 30, 0.04), 0 4px 16px rgba(20, 20, 30, 0.04);
  --radius: 10px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #101114;
    --surface: #17181c;
    --surface-2: #1d1f24;
    --text: #eceef1;
    --text-dim: #9297a1;
    --border: #2a2c32;
    --accent: #7d8bff;
    --accent-text: #10111a;

    --template: #a48bff;
    --toddle: #f0a63d;
    --outlook: #56aaf7;
    --personal: #3ecf7e;
    --veracross: #2dd4bf;
    --tennis-boys: #fb7185;
    --tennis-girls: #f472b6;
    --tennis-practice: #fda4af;
    --subject-calc: #60a5fa;
    --subject-bio: #4ade80;
    --subject-history: #fb923c;
    --subject-neutral: var(--text);
    --danger: #f87171;

    --shadow: 0 1px 2px rgba(0, 0, 0, 0.3), 0 8px 24px rgba(0, 0, 0, 0.25);
  }
}

* { box-sizing: border-box; }

html, body { height: 100%; }

body {
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", sans-serif;
  background: var(--bg);
  color: var(--text);
  margin: 0;
  -webkit-font-smoothing: antialiased;
}

main {
  max-width: 880px;
  margin: 0 auto;
  padding: 0 1.5rem 4rem;
}

a { color: inherit; }

/* Nav */

.topnav {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  /* iOS PWA safe-area: apple-mobile-web-app-status-bar-style is
     black-translucent (base.html) so content can draw under the status
     bar/Dynamic Island for a fuller-screen look — but that means we have
     to manually push real content below it, or it collides. env() falls
     back to 0 on non-notched devices/regular browsers, so max() keeps the
     normal 1rem there and only adds extra space where a safe area exists. */
  padding: max(1rem, env(safe-area-inset-top)) 1.5rem 1rem;
  max-width: 880px;
  margin: 0 auto;
  flex-wrap: wrap;
}

.topnav .brand {
  font-weight: 700;
  font-size: 1.05rem;
  text-decoration: none;
  margin-right: auto;
  letter-spacing: -0.01em;
}

.nav-links { display: flex; gap: 1.1rem; }
.nav-actions { display: flex; gap: 0.6rem; margin-left: auto; }

.topnav a:not(.brand) {
  text-decoration: none;
  color: var(--text-dim);
  font-size: 0.9rem;
  font-weight: 500;
  transition: color 0.15s ease;
}
.topnav a:not(.brand):hover { color: var(--text); }

.refresh-form button {
  font: inherit;
  font-size: 0.8rem;
  font-weight: 600;
  cursor: pointer;
  background: var(--surface-2);
  color: var(--text-dim);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0.4rem 0.9rem;
  transition: all 0.15s ease;
}
.refresh-form button:hover { color: var(--text); border-color: var(--text-dim); }

/* Day header */

.day-header {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1.25rem;
  padding: 1.25rem 0 1.5rem;
}
.day-header h1 {
  font-size: 1.4rem;
  font-weight: 700;
  margin: 0;
  letter-spacing: -0.01em;
  min-width: 15rem;
  text-align: center;
}
.nav-arrow {
  font-size: 1.1rem;
  text-decoration: none;
  color: var(--text-dim);
  width: 2rem;
  height: 2rem;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  transition: all 0.15s ease;
}
.nav-arrow:hover { background: var(--surface-2); color: var(--text); }

.badge {
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  background: var(--accent);
  color: var(--accent-text);
  padding: 0.15rem 0.55rem;
  border-radius: 1rem;
  vertical-align: middle;
}

/* All-day strip */

.all-day-strip {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 1rem;
}
.chip {
  font-size: 0.8rem;
  font-weight: 500;
  padding: 0.35rem 0.75rem;
  border-radius: 999px;
  border: 1.5px solid;
  background: var(--surface);
}

/* Checklist */

.checklist-section { margin-bottom: 1.75rem; }
.checklist-section h2, section h2 {
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-dim);
  margin: 0 0 0.6rem;
}

.checklist { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 0.4rem; }
.checklist-item {
  display: flex;
  align-items: flex-start;
  gap: 0.7rem;
  padding: 0.6rem 0.75rem;
  border-radius: 8px;
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow);
}
.checklist-item.is-overdue { border-color: var(--danger); }
.checklist-item.is-done { opacity: 0.55; }
.checklist-item.is-done .checklist-title { text-decoration: line-through; }
/* Class-colored border on assignments whose title matches a known
   subject (app/subjects.py) — e.g. a synced "AP Bio Lab Report" reads as
   the same green as the AP Biology block on the timeline, same treatment
   as .is-overdue above. The color itself comes from the shared
   .entry-bio/.entry-calc/etc. rules (they're bare class selectors, not
   scoped to a specific context, so they already apply here); the day.html
   template only adds that class at all when subjects.match() finds a
   real hit — not extended to every source, only ones a title can
   resolve to a class. */

.checklist-form { margin: 0; }
.checkbox {
  width: 1.3rem;
  height: 1.3rem;
  flex: 0 0 auto;
  border-radius: 50%;
  border: 1.5px solid var(--text-dim);
  background: transparent;
  color: var(--accent-text);
  font-size: 0.75rem;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-top: 0.1rem;
}
.checklist-item.is-done .checkbox { background: var(--accent); border-color: var(--accent); }

.checklist-body { display: flex; flex-direction: column; gap: 0.15rem; }
.checklist-title { font-size: 0.9rem; font-weight: 600; }
.priority-flag {
  display: inline-block;
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  margin-right: 0.3rem;
  vertical-align: middle;
}
.priority-flag.priority-high { background: var(--danger); }
.priority-flag.priority-medium { background: var(--toddle); }
.priority-flag.priority-low { background: var(--text-dim); }
.checklist-meta { font-size: 0.72rem; color: var(--text-dim); text-transform: capitalize; }

.due-badge {
  display: inline-flex;
  align-items: center;
  font-weight: 700;
  font-size: 0.68rem;
  letter-spacing: 0.01em;
  padding: 0.1rem 0.45rem;
  border-radius: 999px;
  text-transform: none;
}
.due-badge.due-overdue,
.due-badge.due-today {
  background: color-mix(in srgb, var(--danger) 16%, transparent);
  color: var(--danger);
}
.due-badge.due-tomorrow {
  background: color-mix(in srgb, var(--toddle) 18%, transparent);
  color: var(--toddle);
}
.due-badge.due-soon { color: var(--text); }
.due-badge.due-later { color: var(--text-dim); font-weight: 600; }

.entry-list { list-style: none; padding: 0; margin: 0; }
.entry {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.55rem 0.75rem;
  border-left: 3px solid var(--border);
  margin-bottom: 0.4rem;
  border-radius: 8px;
  background: var(--surface);
  box-shadow: var(--shadow);
}

.entry .time { font-variant-numeric: tabular-nums; color: var(--text-dim); min-width: 3.2rem; font-size: 0.85rem; }
.entry .title { flex: 1; font-size: 0.92rem; }
.entry .location { color: var(--text-dim); font-size: 0.8rem; }
.source-tag {
  font-size: 0.65rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-dim);
}

.inline-form { margin: 0; }
.link-button {
  background: none;
  border: none;
  color: var(--text-dim);
  font-size: 0.72rem;
  text-decoration: underline;
  padding: 0;
  cursor: pointer;
}

.empty { color: var(--text-dim); font-style: italic; font-size: 0.9rem; }
.sync-status { margin-top: 2.5rem; font-size: 0.72rem; color: var(--text-dim); text-align: center; }

/* Timeline */

.timeline {
  display: flex;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  overflow: hidden;
}

.timeline-hours {
  flex: 0 0 4rem;
  border-right: 1px solid var(--border);
}
.hour-row {
  position: relative;
  border-bottom: 1px solid transparent;
}
.hour-label {
  position: absolute;
  top: -0.55em;
  right: 0.6rem;
  font-size: 0.7rem;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}

.timeline-track {
  position: relative;
  flex: 1;
  height: var(--timeline-height);
}
.hour-line {
  position: absolute;
  left: 0;
  right: 0;
  border-top: 1px solid var(--border);
}

.now-line {
  position: absolute;
  left: 0;
  right: 0;
  border-top: 2px solid var(--danger);
  z-index: 5;
}
.now-dot {
  position: absolute;
  left: -4px;
  top: -4px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--danger);
}

.timeline-entry {
  position: absolute;
  border-left: 3px solid var(--border);
  background: var(--surface-2);
  border-radius: 6px;
  padding: 0.3rem 0.5rem;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  gap: 0.05rem;
  transition: box-shadow 0.15s ease;
}
.timeline-entry:hover { box-shadow: var(--shadow); z-index: 10; }

.te-time { font-size: 0.68rem; color: var(--text-dim); font-variant-numeric: tabular-nums; }
.te-title { font-size: 0.82rem; font-weight: 600; line-height: 1.2; }
.te-location { font-size: 0.7rem; color: var(--text-dim); }
.te-remove { position: absolute; top: 0.2rem; right: 0.4rem; }

/* Source colors — must come after .entry / .timeline-entry / .chip base
   rules so the border-color override wins the cascade tie. */
.entry-template, .chip-template { border-color: var(--template); }
.entry-toddle, .chip-toddle { border-color: var(--toddle); }
.entry-outlook, .chip-outlook { border-color: var(--outlook); }
.entry-personal, .chip-personal { border-color: var(--personal); }
.entry-veracross, .chip-veracross, .entry-veracross_hw, .chip-veracross_hw { border-color: var(--veracross); }
.entry-tennis_boys, .chip-tennis_boys { border-color: var(--tennis-boys); }
.entry-tennis_girls, .chip-tennis_girls { border-color: var(--tennis-girls); }
.entry-tennis_practice, .chip-tennis_practice { border-color: var(--tennis-practice); }
.entry-calc, .chip-calc { border-color: var(--subject-calc); }
.entry-bio, .chip-bio { border-color: var(--subject-bio); }
.entry-history, .chip-history { border-color: var(--subject-history); }
.entry-neutral, .chip-neutral { border-color: var(--subject-neutral); }
.te-remove .link-button { font-size: 0.62rem; }

/* Free/homework-time blocks (Office Hours, Study Block, CQ) — these are
   exactly the blocks app/subjects.py resolves to "neutral", so the
   striped background now tints toward that same color instead of a
   hardcoded green, and no longer needs its own border-left-color
   override (entry-neutral, above, already supplies it — this used to
   win over that on specificity when they disagreed). */
.timeline-entry.is-free {
  background: repeating-linear-gradient(
    135deg,
    var(--surface-2),
    var(--surface-2) 8px,
    color-mix(in srgb, var(--subject-neutral) 10%, var(--surface-2)) 8px,
    color-mix(in srgb, var(--subject-neutral) 10%, var(--surface-2)) 16px
  );
}
.te-free-tag {
  font-size: 0.6rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--personal);
}

.te-repeat-icon {
  color: var(--text-dim);
  font-size: 0.85em;
}

/* Login */

.login-wrap {
  min-height: calc(100dvh - 4rem);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.75rem;
}
.login-form { width: 100%; max-width: 320px; }
.login-form h1 { margin: 0 0 0.25rem; text-align: center; }
.verify-copy { color: var(--text-dim); font-size: 0.85rem; margin: -0.5rem 0 0; text-align: center; }
.verify-resend { margin: 0; }
.verify-resend .link-button { font-size: 0.8rem; }

/* Add form */

h1 { font-size: 1.3rem; }

.entry-form {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  max-width: 420px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.25rem;
  box-shadow: var(--shadow);
}
.entry-form label {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  font-size: 0.82rem;
  color: var(--text-dim);
  font-weight: 500;
}
.entry-form input, .entry-form select, .entry-form textarea {
  font: inherit;
  padding: 0.5rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
  color: var(--text);
}
.entry-form input:focus, .entry-form select:focus, .entry-form textarea:focus {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}
.entry-form button {
  align-self: flex-start;
  padding: 0.55rem 1.3rem;
  border: none;
  border-radius: 999px;
  background: var(--accent);
  color: var(--accent-text);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}

/* Week view */

.week-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 0.6rem;
}
.week-day {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.6rem;
  min-height: 7rem;
  font-size: 0.75rem;
  box-shadow: var(--shadow);
}
.week-day.is-today { border-color: var(--accent); border-width: 1.5px; }
.week-day h3 { margin: 0 0 0.5rem; font-size: 0.82rem; }
.week-day h3 a { color: inherit; text-decoration: none; }
.mini-entry {
  border-left: 2px solid var(--border);
  padding-left: 0.35rem;
  margin-bottom: 0.3rem;
  color: var(--text-dim);
}
.mini-entry.entry-template { border-left-color: var(--template); }
.mini-entry.entry-toddle { border-left-color: var(--toddle); }
.mini-entry.entry-outlook { border-left-color: var(--outlook); }
.mini-entry.entry-personal { border-left-color: var(--personal); }
.mini-entry.entry-veracross, .mini-entry.entry-veracross_hw { border-left-color: var(--veracross); }
.mini-entry.entry-tennis_boys { border-left-color: var(--tennis-boys); }
.mini-entry.entry-tennis_girls { border-left-color: var(--tennis-girls); }
.mini-entry.entry-tennis_practice { border-left-color: var(--tennis-practice); }
.mini-entry.entry-calc { border-left-color: var(--subject-calc); }
.mini-entry.entry-bio { border-left-color: var(--subject-bio); }
.mini-entry.entry-history { border-left-color: var(--subject-history); }
.mini-entry.entry-neutral { border-left-color: var(--subject-neutral); }
.mini-empty { color: var(--text-dim); opacity: 0.5; }

@media (max-width: 700px) {
  .week-grid { grid-template-columns: 1fr; }
  main { padding: 0 1rem 3rem; }
  .day-header h1 { font-size: 1.15rem; min-width: 0; }
}

/* Month view */

.month-weekdays {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 0.6rem;
  margin-bottom: 0.4rem;
  font-size: 0.72rem;
  color: var(--text-dim);
  text-align: center;
}
.month-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 0.6rem;
}
.month-day {
  display: block;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.5rem;
  min-height: 5.5rem;
  font-size: 0.72rem;
  box-shadow: var(--shadow);
  color: inherit;
  text-decoration: none;
}
.month-day.is-today { border-color: var(--accent); border-width: 1.5px; }
.month-day.is-outside { opacity: 0.4; }
.month-day-num { font-size: 0.78rem; font-weight: 600; }
.month-day-items { margin-top: 0.3rem; display: flex; flex-direction: column; gap: 0.2rem; }
.month-item {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  border-left: 2px solid var(--border);
  padding-left: 0.35rem;
  color: var(--text-dim);
}
.month-item.entry-toddle { border-left-color: var(--toddle); }
.month-item.entry-outlook { border-left-color: var(--outlook); }
.month-item.entry-personal { border-left-color: var(--personal); }
.month-item.entry-veracross, .month-item.entry-veracross_hw { border-left-color: var(--veracross); }
.month-item.entry-tennis_boys { border-left-color: var(--tennis-boys); }
.month-item.entry-tennis_girls { border-left-color: var(--tennis-girls); }
.month-item.entry-calc { border-left-color: var(--subject-calc); }
.month-item.entry-bio { border-left-color: var(--subject-bio); }
.month-item.entry-history { border-left-color: var(--subject-history); }
.month-item.entry-neutral { border-left-color: var(--subject-neutral); }
.month-item-more { color: var(--text-dim); opacity: 0.7; }

@media (max-width: 700px) {
  .month-weekdays { display: none; }
  .month-grid { grid-template-columns: 1fr; }
  .month-day { min-height: 0; }
  .month-day.is-outside { display: none; }
}

/* Focus timer */

.focus-wrap {
  max-width: 380px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.25rem;
  text-align: center;
}
.focus-ring {
  --progress: 0deg;
  width: 240px;
  height: 240px;
  border-radius: 50%;
  background: conic-gradient(var(--accent) var(--progress), var(--surface-2) 0);
  display: flex;
  align-items: center;
  justify-content: center;
}
.focus-ring.mode-break, .focus-ring.mode-long-break {
  background: conic-gradient(var(--personal) var(--progress), var(--surface-2) 0);
}
.focus-ring-inner {
  width: 200px;
  height: 200px;
  border-radius: 50%;
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.3rem;
}
.focus-mode { font-size: 0.78rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-dim); }
.focus-time { font-size: 2.6rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.focus-cycle { font-size: 0.72rem; color: var(--text-dim); }

.focus-task-label {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  font-size: 0.82rem;
  color: var(--text-dim);
  font-weight: 500;
  width: 100%;
  max-width: 320px;
}
.focus-task-label select {
  font: inherit;
  padding: 0.5rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
  color: var(--text);
}

.focus-controls { display: flex; gap: 0.6rem; }
.focus-btn {
  font: inherit;
  font-weight: 600;
  padding: 0.55rem 1.4rem;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--surface-2);
  color: var(--text);
  cursor: pointer;
}
.focus-btn-primary { background: var(--accent); color: var(--accent-text); border-color: transparent; }
.focus-btn-ghost { background: transparent; }
.focus-btn:hover { border-color: var(--text-dim); }

.focus-settings { width: 100%; max-width: 320px; font-size: 0.8rem; color: var(--text-dim); }
.focus-settings summary { cursor: pointer; padding: 0.3rem 0; }
.focus-settings-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0.6rem; margin-top: 0.6rem; }
.focus-settings-grid label { display: flex; flex-direction: column; gap: 0.25rem; font-size: 0.72rem; }
.focus-settings-grid input {
  font: inherit;
  padding: 0.4rem 0.5rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
  color: var(--text);
}

@media (max-width: 700px) {
  .focus-ring { width: 200px; height: 200px; }
  .focus-ring-inner { width: 165px; height: 165px; }
  .focus-time { font-size: 2.1rem; }
}

/* Accessibility: visible focus for every interactive element (WCAG 2.4.7),
   and respect reduced-motion preference. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--accent);
  color: var(--accent-text);
  padding: 0.6rem 1rem;
  border-radius: 0 0 6px 0;
  z-index: 100;
}
.skip-link:focus {
  left: 0;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.search-form { display: flex; gap: 0.5rem; max-width: 480px; margin-bottom: 1.5rem; }
.search-form input[type="search"] {
  flex: 1;
  font: inherit;
  padding: 0.5rem 0.75rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
  color: var(--text);
}
.search-form button {
  font: inherit;
  font-weight: 600;
  padding: 0.5rem 1.1rem;
  border: none;
  border-radius: 999px;
  background: var(--accent);
  color: var(--accent-text);
  cursor: pointer;
}

.search-results { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 0.4rem; }
.search-result {
  border-left: 3px solid var(--border);
  border-radius: 8px;
  background: var(--surface);
  box-shadow: var(--shadow);
}
.search-result-link {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.6rem 0.8rem;
  text-decoration: none;
  color: inherit;
}
.search-result-date { font-size: 0.78rem; color: var(--text-dim); min-width: 7.5rem; }
.search-result-title { flex: 1; font-size: 0.92rem; }
.search-result.is-past { opacity: 0.7; }

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

.form-error {
  color: var(--danger);
  background: color-mix(in srgb, var(--danger) 10%, var(--surface));
  border: 1px solid var(--danger);
  border-radius: 8px;
  padding: 0.6rem 0.9rem;
  font-size: 0.85rem;
  max-width: 420px;
}

/* Pull-to-refresh (standalone home-screen app only — see app.js; a
   regular Safari tab already has this built in, so it'd be redundant
   there). JS drives height directly via inline style as the finger
   moves; this transition only smooths the snap-back/settle at the end. */
.pull-indicator {
  height: 0;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: height 0.2s ease;
}
.pull-indicator.is-dragging { transition: none; }

.pull-spinner {
  width: 22px;
  height: 22px;
  border: 2px solid var(--border);
  border-top-color: var(--text-dim);
  border-radius: 50%;
  transition: border-top-color 0.15s ease;
}
.pull-indicator.is-armed .pull-spinner { border-top-color: var(--accent); }
.pull-indicator.is-refreshing .pull-spinner {
  border-top-color: var(--accent);
  animation: pull-spin 0.7s linear infinite;
}

@keyframes pull-spin {
  to { transform: rotate(360deg); }
}
