:root {
  /* Warm & personal palette (see .claude UI redesign pass) — a terracotta
     accent on a warm cream base, replacing the old Google-blue/grey scheme.
     Kept the same variable ROLES as before (bg < sidebar-bg < card-bg
     elevation, one accent, one danger) so no component needed restructuring,
     just recoloring. */
  --accent: oklch(64% 0.16 35);
  --accent-hover: oklch(58% 0.17 35);
  --accent-soft: oklch(93% 0.045 40);
  --accent-text: #ffffff;
  --border: oklch(90% 0.02 70);
  --text: oklch(24% 0.02 50);
  --muted: oklch(48% 0.02 55);
  --bg: oklch(98% 0.012 75);
  --sidebar-bg: oklch(95.5% 0.016 72);
  --card-bg: oklch(99.5% 0.006 75);
  --danger: oklch(58% 0.19 25);
  --warning: oklch(62% 0.15 75);
  --warning-soft: oklch(90% 0.06 75);

  --radius-sm: 10px;
  --radius-md: 16px;
  --radius-lg: 24px;
  --shadow-sm: 0 3px 10px -3px oklch(50% 0.1 35 / 0.3);
  --shadow: 0 14px 34px -12px oklch(45% 0.06 40 / 0.28), 0 4px 10px -4px oklch(45% 0.06 40 / 0.16);

  --font-display: "Comfortaa", "Segoe UI", sans-serif;
  --font-body: "Figtree", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;

  /* FullCalendar's own theming hooks (https://fullcalendar.io CSS custom
     properties) — defined once here (not per-theme) since they just
     reference our own semantic variables above, which already flip
     correctly under :root[data-theme="dark"] below. */
  --fc-border-color: var(--border);
  --fc-page-bg-color: var(--bg);
  --fc-neutral-bg-color: var(--sidebar-bg);
  --fc-neutral-text-color: var(--muted);
  --fc-list-event-hover-bg-color: var(--sidebar-bg);
  --fc-button-bg-color: var(--card-bg);
  --fc-button-border-color: var(--border);
  --fc-button-text-color: var(--text);
  --fc-button-hover-bg-color: var(--accent-soft);
  --fc-button-hover-border-color: var(--border);
  --fc-button-active-bg-color: var(--accent);
  --fc-button-active-border-color: var(--accent);
  --fc-more-link-bg-color: var(--sidebar-bg);
  --fc-more-link-text-color: var(--text);
  --fc-today-bg-color: var(--accent-soft);
}

/* Dark mode: theme.js sets data-theme on <html>, resolving system
   preference at load so there's no separate prefers-color-scheme block to
   keep in sync — see public/js/theme.js. */
:root[data-theme="dark"] {
  --accent: oklch(72% 0.15 35);
  --accent-hover: oklch(78% 0.15 35);
  --accent-soft: oklch(33% 0.05 38);
  --accent-text: oklch(15% 0.02 40);
  --border: oklch(34% 0.02 50);
  --text: oklch(93% 0.012 70);
  --muted: oklch(70% 0.02 60);
  --bg: oklch(20% 0.016 50);
  --sidebar-bg: oklch(24.5% 0.018 50);
  --card-bg: oklch(28% 0.02 48);
  --danger: oklch(70% 0.17 25);
  --warning: oklch(75% 0.14 75);
  --warning-soft: oklch(35% 0.06 75);

  --shadow-sm: 0 3px 10px -3px oklch(0% 0 0 / 0.5);
  --shadow: 0 16px 38px -12px oklch(0% 0 0 / 0.55), 0 4px 12px -4px oklch(0% 0 0 / 0.4);
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: var(--font-body);
  color: var(--text);
  background: var(--bg);
}

h1, h2, h3 { font-family: var(--font-display); font-weight: 700; letter-spacing: -0.01em; }

/* !important because #login-view/#app-view below set `display` via an ID
   selector, which otherwise outranks this class+attribute rule regardless
   of source order. */
.view[hidden] { display: none !important; }

/* Login */
#login-view {
  position: relative;
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--sidebar-bg);
  padding: 16px;
}
.login-card {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 32px;
  width: 100%;
  max-width: 360px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  box-shadow: var(--shadow);
}
.login-card h1 { margin: 0 0 16px; font-size: 1.5rem; }
.login-card input {
  padding: 11px 14px;
  border: 1.5px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: 1rem;
  background: var(--sidebar-bg);
  color: var(--text);
  font-family: inherit;
}
.login-card button {
  margin-top: 12px;
  padding: 11px;
  border: none;
  border-radius: 999px;
  background: var(--accent);
  color: var(--accent-text);
  font-size: 1rem;
  font-weight: 600;
  cursor: pointer;
  box-shadow: var(--shadow-sm);
  font-family: inherit;
}
.login-card button:hover { background: var(--accent-hover); }
/* .login-card's unconditional `display: flex` (author-origin) otherwise
   beats the [hidden] UA default the same way .field-row[hidden] below
   already has to guard against — #signup-form carries class="login-card"
   alongside `hidden` while the login form is showing. */
.login-card[hidden] { display: none; }

.auth-switch {
  margin: 4px 0 0;
  font-size: 0.9rem;
  color: var(--muted);
  text-align: center;
}
/* Higher specificity than `.login-card button` (needs to beat its solid
   pill styling, not just add to it). */
.auth-switch .link-button {
  margin: 0;
  padding: 0;
  border: none;
  border-radius: 0;
  background: none;
  box-shadow: none;
  font-size: inherit;
  color: var(--accent);
  cursor: pointer;
}
.auth-switch .link-button:hover { text-decoration: underline; }

.error { color: var(--danger); font-size: 0.9rem; }

/* Shared round icon-button look (theme toggle, push toggle, settings,
   timetable import, logout). Kept separate from .theme-toggle-button —
   that class is also theme.js's query selector for which buttons it wires
   up and rewrites the icon on, so anything sharing just the look but not
   the behavior (like the push toggle) must NOT have it, or clicking it
   would also silently toggle the theme. */
.icon-toggle-button {
  background: var(--card-bg);
  border: 1px solid var(--border);
  color: var(--muted);
  border-radius: 999px;
  width: 38px;
  height: 38px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  flex-shrink: 0;
}
.icon-toggle-button svg { width: 17px; height: 17px; }
#theme-toggle-login {
  position: absolute;
  top: 16px;
  right: 16px;
}

/* App shell */
#app-view { display: flex; flex-direction: column; height: 100vh; }

.topbar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 20px;
  background: var(--card-bg);
  border-bottom: 1px solid var(--border);
  flex-wrap: wrap;
}
.topbar h1 { font-size: 1.15rem; margin: 0; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.offline-banner {
  margin: 0;
  padding: 6px 20px;
  font-size: 0.8rem;
  text-align: center;
  color: var(--muted);
  background: var(--accent-soft);
  border-bottom: 1px solid var(--border);
}
/* #update-banner reuses .offline-banner's look verbatim (same tier of
   "small unobtrusive status strip") plus this one inline button. */
#update-refresh-button {
  margin-left: 8px;
  padding: 2px 10px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--card-bg);
  color: var(--text);
  font-size: 0.78rem;
  cursor: pointer;
}
.app-version { margin: 16px 0 0; font-size: 0.75rem; color: var(--muted); text-align: center; }
/* Delete-with-undo toasts (see js/toast.js) — floats above everything else,
   stacked bottom-up so the newest sits closest to the bottom edge. */
#toast-container {
  position: fixed;
  left: 50%;
  bottom: 20px;
  transform: translateX(-50%);
  z-index: 1000;
  display: flex;
  flex-direction: column-reverse;
  gap: 8px;
  width: min(360px, calc(100vw - 32px));
}
.toast {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 16px;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow);
  font-size: 0.9rem;
}
.toast-message { flex: 1; min-width: 0; }
.toast-undo {
  flex-shrink: 0;
  background: none;
  border: none;
  color: var(--accent);
  font-weight: 600;
  cursor: pointer;
  padding: 4px;
}
.toast-undo:hover { text-decoration: underline; }
.icon-button {
  background: none;
  border: none;
  color: var(--text);
  cursor: pointer;
  padding: 8px;
  border-radius: var(--radius-sm);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.icon-button svg { width: 19px; height: 19px; }
#menu-toggle { width: 40px; height: 40px; background: var(--sidebar-bg); }
#current-user-email {
  font-size: 0.78rem;
  color: var(--muted);
  flex-shrink: 0;
  max-width: 160px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
#current-user-email:empty { display: none; }
#new-event-button {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--accent);
  color: var(--accent-text);
  border: none;
  border-radius: 999px;
  padding: 9px 16px 9px 13px;
  cursor: pointer;
  font-size: 0.9rem;
  font-weight: 600;
  font-family: inherit;
  box-shadow: var(--shadow-sm);
  flex-shrink: 0;
}
#new-event-button:hover { background: var(--accent-hover); }
#new-event-button svg { width: 14px; height: 14px; }

.layout { display: flex; flex: 1; min-height: 0; }

#sidebar {
  width: 240px;
  background: var(--card-bg);
  border-right: 1px solid var(--border);
  padding: 20px 16px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
#sidebar h2 {
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--muted);
  margin: 0;
  padding: 0 4px;
}
#course-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
.course-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  font-size: 0.9rem;
  font-weight: 500;
}
.course-visible-toggle { flex-shrink: 0; width: 14px; height: 14px; margin: 0; accent-color: var(--accent); cursor: pointer; }
.course-dot { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; }
.course-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.course-row-hidden .course-dot,
.course-row-hidden .course-name { opacity: 0.45; }
.course-row-button {
  flex-shrink: 0;
  width: 22px;
  height: 22px;
  padding: 0;
  border: none;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--muted);
  cursor: pointer;
  font-size: 0.8rem;
  line-height: 1;
}
.course-row-button:hover { background: var(--sidebar-bg); color: var(--text); }
.course-row-delete:hover { color: var(--danger); }
.course-row.editing { gap: 6px; }
.course-edit-name {
  flex: 1;
  min-width: 0;
  padding: 5px 7px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--card-bg);
  color: var(--text);
  font-family: inherit;
  font-size: 0.85rem;
}
.course-edit-color { flex-shrink: 0; width: 26px; height: 26px; padding: 0; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--card-bg); }
#course-form {
  display: flex;
  flex-direction: column;
  gap: 8px;
  background: var(--sidebar-bg);
  border-radius: var(--radius-md);
  padding: 14px;
  margin-top: auto;
}
#course-form input[type="text"] {
  padding: 9px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--card-bg);
  color: var(--text);
  font-family: inherit;
  font-size: 0.85rem;
}
#course-form button {
  padding: 9px;
  border: none;
  border-radius: var(--radius-sm);
  background: var(--accent-soft);
  color: var(--accent);
  cursor: pointer;
  font-family: inherit;
  font-weight: 600;
  font-size: 0.85rem;
}

#main-content { flex: 1; display: flex; flex-direction: column; min-width: 0; }
#calendar { flex: 1; padding: 20px 28px; overflow: auto; display: flex; flex-direction: column; }
/* !important: FullCalendar sets its own display style directly on the
   element it's given, which otherwise beats the plain [hidden] UA rule —
   same class of bug as the earlier login/app-view [hidden] fix. */
#calendar[hidden], #today-view[hidden], #goals-view[hidden], #review-view[hidden], #grades-view[hidden] { display: none !important; }
#calendar-fc { flex: 1; min-height: 0; }

#calendar-select-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; flex: 0 0 auto; margin-bottom: 12px; }
#calendar-select-bar button {
  padding: 8px 16px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--card-bg);
  color: var(--text);
  cursor: pointer;
  font-family: inherit;
  font-weight: 600;
  font-size: 0.82rem;
}
#calendar-select-count { font-size: 0.85rem; color: var(--muted); font-weight: 500; }
#calendar-select-delete { color: var(--danger); border-color: var(--danger); }
#calendar-select-delete:disabled { opacity: 0.5; cursor: default; }
#calendar-undo-button:disabled { opacity: 0.5; cursor: default; }
#calendar-undo-button:not(:disabled) { background: var(--accent); color: var(--accent-text); border-color: var(--accent); }

/* Bigger, more discoverable search entry point sitting right above
   FullCalendar's own Month/Week/Day/List switcher (the right chunk of its
   header toolbar, inside #calendar-fc directly below this bar) — pushed to
   that same side so it lines up with it. The small round topbar icon
   (#search-toggle-button, search.js) stays too, since this one is only
   visible while the Calendar tab is open; Ctrl+K keeps working from any
   tab regardless of which button (if either) is on screen. */
/* Scoped as #calendar-select-bar #calendar-search-button (two id
   selectors), not just #calendar-search-button alone, so it out-specifies
   the shared "#calendar-select-bar button" rule above instead of losing to
   it (that rule is 1 id + 1 element, which beats a bare 1-id selector). */
#calendar-select-bar #calendar-search-button {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 9px 18px 9px 14px;
  border: none;
  background: var(--accent-soft);
  color: var(--accent);
  font-size: 0.85rem;
}
#calendar-search-button svg { width: 15px; height: 15px; }
#calendar-select-bar #calendar-search-button:hover { background: var(--accent-hover); color: var(--accent-text); }

/* FullCalendar theming beyond the CSS-custom-property hooks above */
.fc { font-family: var(--font-body); }
.fc .fc-toolbar-title { font-family: var(--font-display); font-weight: 700; font-size: 1.3rem; }
.fc .fc-button { border-radius: 999px; font-weight: 600; text-transform: capitalize; box-shadow: none; }
.fc .fc-button-group { border-radius: 999px; overflow: hidden; }
.fc .fc-button-group .fc-button { border-radius: 0; }
.fc .fc-today-button { border-radius: 999px !important; }
.fc-daygrid-day-frame { border-radius: var(--radius-md); }
.fc-daygrid-day.fc-day-today { border-radius: var(--radius-md); }
.fc-col-header-cell-cushion {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--muted);
  text-decoration: none;
}
.fc-daygrid-day-number { color: var(--text); font-weight: 600; font-size: 0.82rem; text-decoration: none; }
.fc-event { border-radius: 8px; border-width: 0; border-left-width: 3px; }
/* At mobile day-cell widths (~50px) "+N more" wraps onto two lines by
   default, and its box doesn't reserve height for the second line — the
   wrapped "more" collides with whatever's below it. One line, ellipsized
   instead. */
.fc-daygrid-more-link {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  display: block;
  font-size: 0.75rem;
  font-weight: 600;
}

/* Custom event rendering (see calendar.js's renderEventContent) — shows the
   end time on the right of the title, not just the start time on the left. */
.fc-event-custom { display: flex; align-items: baseline; gap: 4px; width: 100%; min-width: 0; padding: 2px 4px; line-height: 1.35; }
/* dayMaxEventRows above caps the row COUNT, but FullCalendar still sizes
   each row's box height off its own (shorter, single-line) default — give
   our taller custom row a touch more breathing room so consecutive events
   don't visually run into each other. */
.fc-daygrid-event-harness { margin-bottom: 1px; }
.fc-event-custom-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
.fc-event-custom-time { flex-shrink: 0; font-variant-numeric: tabular-nums; }
.fc-event-custom-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Groups end-time + the deadline chip (if any) as one row/line — see
   renderEventContent() in calendar.js for why they're not two independent
   stacked lines. */
.fc-event-custom-meta { display: flex; align-items: baseline; gap: 6px; flex-shrink: 0; margin-left: auto; line-height: 1; }
.fc-event-custom-end {
  flex-shrink: 0;
  font-variant-numeric: tabular-nums;
  opacity: 0.8;
  font-size: 0.85em;
}
.fc-event-custom-stacked {
  flex-direction: column;
  align-items: flex-start;
  gap: 0;
}
/* timeGrid boxes are sized purely off the event's time span, not its
   content — a long title wrapping to more lines than that fixed height
   allows would otherwise spill out past the box's rounded background
   instead of being contained by it. Clamp to 2 lines with an ellipsis so
   a long title degrades gracefully, and belt-and-braces clip the event
   box itself (below) in case even that doesn't fit a very short slot. */
.fc-event-custom-stacked .fc-event-custom-title {
  white-space: normal;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.fc-event-custom-stacked .fc-event-custom-meta { margin-left: 0; }
.fc-event-custom-stacked .fc-event-custom-end { opacity: 0.85; }
.fc-timegrid-event { overflow: hidden; }

/* A session "Plan my week" placed itself, as opposed to anything created by
   hand — dashed so it's obvious it'll be regenerated (moved/replaced) the
   next time the planner runs. */
.fc-event-auto-placed { border-style: dashed !important; }

/* Bulk-select mode (calendar.js) — every occurrence sharing the selected
   event's underlying event_id gets this, so a recurring series' whole
   spread of visible occurrences reads as one unit about to be deleted
   together, not just the one instance actually clicked. */
.fc-event-selected { outline: 3px solid var(--accent); outline-offset: 1px; }

.view-tabs { display: inline-flex; gap: 3px; padding: 20px 28px 0; }
.view-tab {
  padding: 9px 20px;
  border: none;
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  font-family: inherit;
  font-weight: 600;
  font-size: 0.87rem;
}
.view-tab.active { background: var(--card-bg); color: var(--text); box-shadow: var(--shadow-sm); }

#today-view { flex: 1; padding: 20px 28px; overflow: auto; display: flex; flex-wrap: wrap; align-items: flex-start; gap: 24px; }
#agenda-main { flex: 1 1 380px; min-width: 0; max-width: 640px; }

/* Right-hand column: weather + the glanceable cards beside it (streak,
   mini calendar, countdown hero, the "this week" snapshot) — one flex
   column so they stack with consistent spacing, replacing weather's old
   role as #today-view's lone second flex item. Kept modest (not just
   "however wide the row wants") — #today-view's flex-wrap decides whether
   to wrap onto a second line using each item's flex-basis, not its
   post-shrink size, so an oversized basis here wraps #agenda-side below
   #agenda-main even on a perfectly wide-enough screen. 560px keeps
   #agenda-main(380) + this + the 24px gap comfortably under a 1280px
   viewport's available width. */
#agenda-side { flex: 0 1 560px; min-width: 220px; max-width: 560px; display: flex; flex-direction: column; gap: 16px; }

/* Weather, the free-hours/study snapshot, and the mini calendar, side by
   side rather than stacked — stretch so the shorter cards match weather's
   height instead of leaving a short box next to a tall one. Same
   basis-sum-must-fit-#agenda-side caution as above: 190+190+130+2*16 gaps
   = 558px, just under #agenda-side's own 560px cap. */
#agenda-weather-row { display: flex; align-items: stretch; gap: 16px; }
#agenda-mini-calendar { flex: 0 0 190px; }

/* Shared card look for every #agenda-side card except weather (which stays
   its own illustrated visual world, see below) — same tokens
   .current-session/#upcoming-deadlines already use, factored out here
   since three cards would otherwise each redeclare it. */
.agenda-side-card {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  padding: 14px 16px;
}

/* Weather panel (public/js/weather.js) — a literal "window" onto the sky
   outside, deliberately its own visual world (a real sky gradient, white
   text) rather than themed off --bg/--text like the rest of the app, so
   it reads as an illustrated scene rather than another settings card. The
   loading/error states are the exception — those fall back to the app's
   own tokens since there's no scene to show yet. */
#agenda-weather {
  flex: 0 0 190px;
  min-height: 230px;
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  color: #fff;
  font-family: inherit;
}
#agenda-weather.wx-day { background: linear-gradient(180deg, #6fb1e8 0%, #a9d4f2 55%, #f6cf82 100%); }
#agenda-weather.wx-night { background: linear-gradient(180deg, #1b2340 0%, #2c3768 55%, #4a4f86 100%); }
#agenda-weather.wx-state-loading, #agenda-weather.wx-state-error {
  background: linear-gradient(180deg, var(--sidebar-bg), var(--card-bg));
  color: var(--muted);
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 20px;
  gap: 10px;
}
.wx-loading, .wx-error-message { font-size: 0.85rem; margin: 0; }
#agenda-weather.wx-state-error #wx-retry-button {
  padding: 8px 16px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--card-bg);
  color: var(--text);
  cursor: pointer;
  font-family: inherit;
  font-weight: 600;
  font-size: 0.82rem;
}

.wx-scene { width: 100%; height: auto; display: block; }
.wx-body {
  padding: 14px 18px 18px;
  background: linear-gradient(180deg, transparent, oklch(0% 0 0 / 0.28) 65%);
}
.wx-temp { font-family: var(--font-display); font-size: 2.4rem; font-weight: 700; line-height: 1; text-shadow: 0 2px 8px oklch(0% 0 0 / 0.25); }
.wx-unit { font-size: 1.1rem; font-weight: 600; opacity: 0.85; }
.wx-desc { font-weight: 600; margin-top: 2px; }
.wx-hilo { font-size: 0.85rem; opacity: 0.9; margin-top: 2px; }
.wx-meta { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 10px; font-size: 0.78rem; opacity: 0.92; }
.wx-meta span { display: inline-flex; align-items: center; gap: 4px; }
.wx-meta svg { width: 13px; height: 13px; flex-shrink: 0; }
.wx-updated { font-size: 0.7rem; opacity: 0.7; margin-top: 8px; }

#agenda-day-bar { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
#agenda-day-bar button {
  padding: 7px 12px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--card-bg);
  color: var(--text);
  cursor: pointer;
  font-family: inherit;
  font-weight: 600;
  font-size: 0.85rem;
}
#agenda-day-prev, #agenda-day-next { padding: 7px 13px; line-height: 1; font-size: 1rem; }
#agenda-day-today:disabled { opacity: 0.5; cursor: default; }
#agenda-day-picker {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--card-bg);
  color: var(--text);
  font-family: inherit;
  padding: 6px 10px;
  font-size: 0.85rem;
}

#today-date-heading { margin: 0 0 16px; font-size: 1.7rem; }
#today-list { list-style: none; margin: 0 0 28px; padding: 0; display: flex; flex-direction: column; gap: 10px; }
#today-list li {
  display: flex;
  align-items: center;
  gap: 14px;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 13px 16px;
  cursor: pointer;
}
.today-item-time { font-variant-numeric: tabular-nums; color: var(--muted); font-weight: 700; font-size: 0.82rem; width: 3.2em; flex-shrink: 0; }
.today-item-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
.today-item-body { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.today-item-title-row { display: flex; align-items: baseline; gap: 8px; }
.today-item-title { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.today-item-end-time { font-variant-numeric: tabular-nums; color: var(--muted); font-size: 0.8rem; flex-shrink: 0; margin-left: auto; }

/* Countdown chip — shared markup/class across the Agenda row
   (today.js), the Calendar tab's event chip (calendar.js), and the
   "Upcoming deadlines" widget below (deadlines.js), so all three read as
   the same visual "thing" rather than three bespoke badges. */
.deadline-chip {
  flex-shrink: 0;
  margin-left: auto;
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 2px 8px;
  border-radius: 999px;
  white-space: nowrap;
}
.deadline-chip-normal { background: var(--accent-soft); color: var(--accent); }
.deadline-chip-soon { background: var(--warning-soft); color: var(--warning); }
.deadline-chip-overdue { background: var(--danger); color: var(--accent-text); }
/* Calendar chip specifically: a timeGrid event's box height is fixed by
   its actual time span in pixels, not its content (see the 2026-08-22
   title-clipping fix) — a short event has very little vertical room, and
   the pill's own padding was enough to clip on a 1-hour box even sharing
   a line with the end-time. Tighter here only; the Agenda row and the
   widget (both plain flow, not height-constrained) keep the full size. */
.fc-event-custom-meta .deadline-chip { padding: 0 6px; font-size: 0.62rem; }
.today-item-location { font-size: 0.8rem; color: var(--muted); }
.today-item-notes {
  font-size: 0.8rem;
  color: var(--muted);
  font-style: italic;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* To-do section (inline on the Agenda page) */
#agenda-todo-due h3, #agenda-todo-nodate h3 {
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--muted);
  margin: 0 0 10px;
  font-family: inherit;
}
#agenda-todo-nodate { margin-top: 20px; }
.todo-group {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 14px 16px;
  margin-bottom: 16px;
}
.todo-group-header { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.todo-group-header h3 { margin: 0; flex: 1; font-size: 1rem; font-family: inherit; font-weight: 700; }
.todo-group-header button {
  padding: 7px 12px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--sidebar-bg);
  color: var(--danger);
  cursor: pointer;
  font-family: inherit;
  font-size: 0.8rem;
  white-space: nowrap;
}
.todo-item-list { list-style: none; margin: 0 0 8px; padding: 0; display: flex; flex-direction: column; gap: 5px; }
.todo-item {
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--sidebar-bg);
  border-radius: var(--radius-sm);
  padding: 8px 12px;
}
.todo-item.done .todo-item-title { text-decoration: line-through; color: var(--muted); }
.todo-item-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.todo-item-delete { background: none; border: none; color: var(--danger); cursor: pointer; font-size: 0.9rem; }

.todo-group-remind-at, .todo-item-remind-at {
  padding: 5px 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--card-bg);
  color: var(--text);
  font-family: inherit;
  font-size: 0.8rem;
}

.todo-add-form { display: flex; gap: 8px; margin-top: 4px; }
.todo-add-form input[type="text"] {
  flex: 1;
  min-width: 0;
  padding: 9px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--card-bg);
  color: var(--text);
  font-family: inherit;
}
.todo-add-form input[type="datetime-local"] {
  padding: 7px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--card-bg);
  color: var(--text);
  font-family: inherit;
  font-size: 0.85rem;
}
.todo-add-form button {
  padding: 9px 16px;
  border: none;
  border-radius: 999px;
  background: var(--accent);
  color: var(--accent-text);
  cursor: pointer;
  font-family: inherit;
  font-weight: 600;
  white-space: nowrap;
}
.todo-add-form button:hover { background: var(--accent-hover); }

#todo-group-form { margin-top: 8px; }

/* Goals view */
#goals-view, #review-view, #grades-view { flex: 1; padding: 20px 28px; overflow: auto; max-width: 640px; }

#goals-week-bar, #review-week-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 12px;
}
#goals-week-bar button, #review-week-bar button {
  padding: 7px 12px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--card-bg);
  color: var(--text);
  cursor: pointer;
  font-family: inherit;
  font-weight: 600;
  font-size: 0.85rem;
}
#goals-week-prev, #goals-week-next, #review-week-prev, #review-week-next { padding: 7px 13px; line-height: 1; font-size: 1rem; }
#goals-week-today:disabled, #review-week-today:disabled { opacity: 0.5; cursor: default; }
#goals-week-range, #review-week-range { flex: 1; font-weight: 500; color: var(--muted); font-size: 0.9rem; }
#goals-week-picker, #review-week-picker {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--card-bg);
  color: var(--text);
  font-family: inherit;
  padding: 6px 10px;
  font-size: 0.85rem;
}

#free-hours-summary {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 16px 18px;
  margin-bottom: 12px;
  font-size: 1.1rem;
  font-weight: 600;
  display: flex;
  align-items: center;
  gap: 12px;
}
#free-hours-summary span { flex: 1; }
#plan-week-button {
  padding: 9px 18px;
  border: none;
  border-radius: 999px;
  background: var(--accent);
  color: var(--accent-text);
  font-family: inherit;
  font-size: 0.88rem;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  box-shadow: var(--shadow-sm);
}
#plan-week-button:hover { background: var(--accent-hover); }
#plan-week-button:disabled { opacity: 0.6; cursor: default; background: var(--accent); }
#plan-week-result { margin: 0 0 16px; }

.goal-card {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-left: 4px solid var(--goal-color, var(--accent));
  border-radius: var(--radius-md);
  padding: 14px 16px;
  margin-bottom: 12px;
}
.goal-card-header { display: flex; align-items: center; gap: 8px; }
.goal-card-header h3 { margin: 0; flex: 1; font-size: 1rem; font-family: inherit; font-weight: 700; }
.goal-card-header button {
  padding: 7px 12px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--sidebar-bg);
  color: var(--muted);
  cursor: pointer;
  font-family: inherit;
  font-size: 0.8rem;
  white-space: nowrap;
}
.goal-progress-text { margin: 8px 0 6px; font-size: 0.88rem; color: var(--muted); }
.goal-progress-bar {
  height: 8px;
  border-radius: 999px;
  background: var(--sidebar-bg);
  overflow: hidden;
}
.goal-progress-fill {
  height: 100%;
  background: var(--goal-color, var(--accent));
  border-radius: 999px;
}

#goal-form {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 16px 18px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
#goal-form h3 { margin: 0 0 4px; font-size: 1rem; font-family: inherit; font-weight: 700; }
#goal-form label { font-size: 0.85rem; color: var(--muted); margin-top: 4px; }
#goal-form input, #goal-form select {
  padding: 9px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: 0.95rem;
  width: 100%;
  background: var(--sidebar-bg);
  color: var(--text);
  font-family: inherit;
}
#goal-form .field-row { display: flex; gap: 12px; }
#goal-form .field-row > div { flex: 1; }
#goal-form input[type="radio"] { width: auto; flex: 0 0 auto; }
#goal-form button[type="submit"] {
  margin-top: 4px;
  padding: 10px 16px;
  border: none;
  border-radius: 999px;
  background: var(--accent);
  color: var(--accent-text);
  cursor: pointer;
  font-family: inherit;
  font-weight: 600;
}
#goal-form button[type="submit"]:hover { background: var(--accent-hover); }

/* Review tab */
#review-headline {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 16px 18px;
  margin-bottom: 16px;
}
#review-headline-total { display: flex; align-items: baseline; gap: 10px; }
#review-total-hours { font-size: 1.4rem; font-weight: 700; }
.review-delta { font-size: 0.9rem; font-weight: 600; color: var(--muted); }
.review-delta.review-delta-up { color: var(--accent); }
#review-goals-met { margin: 6px 0 0; }

#review-by-goal, #review-by-course, #review-trend { margin-bottom: 20px; }
#review-by-goal h3, #review-by-course h3, #review-trend h3 {
  margin: 0 0 10px;
  font-size: 0.95rem;
  font-family: inherit;
  font-weight: 700;
}
.review-goal-target { color: var(--muted); font-weight: 500; }

.review-course-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 8px;
}
.review-course-label { flex: 0 0 120px; font-size: 0.85rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.review-course-bar-track {
  flex: 1;
  height: 10px;
  border-radius: 999px;
  background: var(--sidebar-bg);
  overflow: hidden;
}
.review-course-bar-fill { height: 100%; border-radius: 999px; background: var(--accent); }
.review-course-hours { flex: 0 0 auto; font-size: 0.85rem; font-weight: 600; color: var(--muted); min-width: 3.5em; text-align: right; }

#review-trend-bars {
  display: flex;
  align-items: flex-end;
  gap: 10px;
  height: 80px;
  padding: 0 4px;
}
.review-trend-bar { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; height: 100%; gap: 4px; }
.review-trend-bar-fill { width: 100%; max-width: 28px; border-radius: 4px 4px 0 0; background: var(--accent-soft); min-height: 3px; }
.review-trend-bar-current .review-trend-bar-fill { background: var(--accent); }
.review-trend-bar-label { font-size: 0.72rem; color: var(--muted); }

/* Grades tab — course cards reuse .goal-card's look/feel (left accent
   stripe off --goal-color, same card padding/radius) rather than inventing
   a new card style. */
.grade-course-card {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-left: 4px solid var(--goal-color, var(--accent));
  border-radius: var(--radius-md);
  padding: 14px 16px;
  margin-bottom: 12px;
}
.grade-course-header { display: flex; align-items: center; gap: 8px; }
.grade-course-header h3 { margin: 0; flex: 1; font-size: 1rem; font-family: inherit; font-weight: 700; }
.grade-course-badge {
  padding: 4px 10px;
  border-radius: 999px;
  background: var(--accent-soft);
  color: var(--accent);
  font-size: 0.9rem;
  font-weight: 700;
  white-space: nowrap;
}
.grade-course-badge-pending { background: var(--sidebar-bg); color: var(--muted); font-size: 0.8rem; font-weight: 600; }
.grade-course-note { margin: 8px 0 0; font-size: 0.85rem; color: var(--muted); }

.grade-item-list { margin-top: 10px; display: flex; flex-direction: column; gap: 6px; }
.grade-item-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 10px;
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  background: var(--sidebar-bg);
  font-size: 0.85rem;
}
.grade-item-title { flex: 1 1 120px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.grade-item-date { flex: 0 0 auto; color: var(--muted); font-size: 0.78rem; }
.grade-item-score { flex: 0 0 auto; font-weight: 600; min-width: 6em; text-align: right; }
.grade-item-score-pending { color: var(--muted); font-weight: 500; }
.grade-item-hours { flex: 0 0 auto; color: var(--muted); font-size: 0.78rem; min-width: 6em; text-align: right; }

/* The real-vs-mock reality check line — deliberately plain text, not a
   badge, so it doesn't compete visually with the actual grade badge above. */
.grade-course-compare { margin: 8px 0 0; font-size: 0.85rem; color: var(--muted); font-weight: 600; }

/* Mock exam trend — same bar-chart shape as Review's own trend
   (.review-trend-bar*), kept as separate classes rather than shared ones
   since a mock's bar height is the score percentage directly (0-100 maps
   straight to 0-100% height), not scaled relative to a running max the way
   Review's hours-based trend needs. Fill color is the fixed Mock Exam
   violet (matches EVENT_TYPE_COLORS.mock_exam in calendar.js/today.js),
   not the course's own color — ties every mock-trend bar in the app back
   to the same "this is practice" visual language regardless of course. */
.grade-mock-section { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--border); }
.grade-mock-header { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.grade-mock-header h4 { margin: 0; flex: 1; font-size: 0.85rem; font-family: inherit; font-weight: 700; color: var(--muted); }
.grade-mock-average { font-size: 0.85rem; font-weight: 700; color: #8a63d2; }

/* Per-real-exam sub-groups (migrations/0016) — each gets its own small
   heading/average/trend, nested under the course's overall Mock exams
   header above. */
.grade-mock-group { margin-top: 14px; }
.grade-mock-group-header { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.grade-mock-group-header h5 { margin: 0; flex: 1; font-size: 0.78rem; font-family: inherit; font-weight: 600; color: var(--text); }

/* Inline target-score editor (courses.target_mock_score) — same
   "click text to edit in place" shape as courses.js's own rename row. */
.grade-target-control { display: flex; align-items: center; gap: 8px; margin-bottom: 4px; }
.grade-target-label {
  padding: 0;
  border: none;
  background: none;
  color: var(--muted);
  font-family: inherit;
  font-size: 0.8rem;
  font-weight: 600;
  cursor: pointer;
  text-decoration: underline dotted;
}
.grade-target-label:hover { color: var(--text); }
.grade-target-met { font-size: 0.8rem; color: var(--muted); }
.grade-target-input {
  width: 5em;
  padding: 4px 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--sidebar-bg);
  color: var(--text);
  font-family: inherit;
  font-size: 0.85rem;
}
.grade-target-button {
  padding: 4px 9px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--card-bg);
  color: var(--muted);
  cursor: pointer;
  font-family: inherit;
  font-size: 0.78rem;
}

/* Fixed 64px chart box with a single positioned child (the fill) per bar —
   deliberately NOT a flex column with the label stacked inside it: two flex
   children (fill + label) sharing one height would flex-shrink the fill
   under label overhead, throwing off exactly how tall a given score's bar
   renders — and then a dashed target line (positioned against this same
   box, sharing no such shrink) would drift out of alignment with the bars
   it's meant to be compared against. Taking the label out of flow (absolute,
   below the box) keeps every bar's fill an exact, unshrunk percentage of
   the same 64px this container and the target line both use. */
.mock-trend-bars {
  position: relative;
  display: flex;
  align-items: flex-end;
  gap: 8px;
  height: 64px;
  padding: 0 2px;
  margin-bottom: 18px;
}
.mock-trend-bar { position: relative; flex: 1; height: 100%; max-width: 36px; }
.mock-trend-bar-fill { position: absolute; left: 0; right: 0; bottom: 0; border-radius: 4px 4px 0 0; background: #8a63d2; min-height: 3px; }
.mock-trend-bar-label {
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  margin-top: 4px;
  font-size: 0.68rem;
  color: var(--muted);
  white-space: nowrap;
}
.mock-trend-target-line {
  position: absolute;
  left: 0;
  right: 0;
  height: 0;
  border-top: 1px dashed var(--muted);
}

/* Study time vs. grade scatter (grades.js's renderStudyChart) — plain
   inline SVG, no charting library, same hand-built-chart precedent as the
   trend bars above. Point colors reuse the app's existing per-item-type
   coding: --accent for a real assignment/exam (matches the running-grade
   badge above), the fixed Mock Exam violet for a mock (matches
   EVENT_TYPE_COLORS.mock_exam and the trend-bar fill). */
.grade-study-section { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--border); }
.grade-study-header { display: flex; align-items: center; margin-bottom: 6px; }
.grade-study-header h4 { margin: 0; flex: 1; font-size: 0.85rem; font-family: inherit; font-weight: 700; color: var(--muted); }
.grade-study-legend { display: flex; gap: 14px; margin-bottom: 6px; }
.grade-study-legend-item { display: flex; align-items: center; gap: 5px; font-size: 0.75rem; color: var(--muted); }
.grade-study-dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }
.grade-study-dot-real { background: var(--accent); }
.grade-study-dot-mock { background: #8a63d2; }

.grade-study-chart { width: 100%; height: auto; max-width: 320px; }
.grade-study-axis { fill: none; stroke: var(--border); stroke-width: 1; }
.grade-study-tick { font-size: 7px; fill: var(--muted); }
.grade-study-point { stroke: var(--card-bg); stroke-width: 1; }
.grade-study-point-real { fill: var(--accent); }
.grade-study-point-mock { fill: #8a63d2; }

#review-placement-split { margin: 0; }
.review-scheduled-note { margin: -2px 0 6px; font-size: 0.82rem; color: var(--muted); font-weight: 500; }

/* Agenda "current session" widget (today.js) */
.current-session {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  padding: 14px 16px;
  margin-bottom: 12px;
}
.current-session-heading { margin: 0 0 4px; font-size: 0.78rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em; color: var(--accent); }

/* Agenda "this week at a glance" snapshot (agendaSnapshot.js) — same card
   treatment as .current-session above, but never hidden (a 0h/0-goals
   state is still shown, same "inaction stays visible" philosophy as
   Review's own goal cards). Two click-through rows rather than a heading
   + list. */
#agenda-snapshot { flex: 1 1 130px; min-width: 110px; display: flex; flex-direction: column; justify-content: center; gap: 10px; }
.agenda-snapshot-row { margin: 0; cursor: pointer; font-weight: 500; }
.agenda-snapshot-row:hover { color: var(--accent); }

/* Countdown hero (#agenda-countdown-hero) — the single soonest deadline,
   reusing deadlines.js's own countdown-chip colors/logic but bigger, so it
   reads as the headline of the sidebar rather than a list row. */
.agenda-hero-title { margin: 0 0 8px; font-weight: 700; }
.agenda-hero-chip { font-size: 0.95rem; padding: 6px 14px; }

/* Streak badge (#agenda-streak) — plain text, no extra chrome beyond the
   shared .agenda-side-card look. */
#agenda-streak-text { margin: 0; font-weight: 600; }

/* Mini month calendar (#agenda-mini-calendar, public/js/miniCalendar.js) —
   a hand-built 7-column grid, same "no library" precedent as the trend
   bars / weather illustration rather than a second FullCalendar instance. */
#mini-cal-bar { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
#mini-cal-bar button { background: none; border: none; color: var(--text); font-size: 1.1rem; cursor: pointer; padding: 2px 8px; }
#mini-cal-label { font-weight: 700; font-size: 0.9rem; }
#mini-cal-weekdays, #mini-cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); }
#mini-cal-weekdays { margin-bottom: 4px; }
#mini-cal-weekdays span { text-align: center; font-size: 0.7rem; color: var(--muted); font-weight: 600; }
.mini-cal-day {
  aspect-ratio: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  font-size: 0.8rem;
  border-radius: var(--radius-sm);
  cursor: pointer;
  background: none;
  border: none;
  color: var(--text);
  font-family: inherit;
}
.mini-cal-day:hover { background: var(--sidebar-bg); }
.mini-cal-day-outside { color: var(--muted); opacity: 0.5; }
.mini-cal-day-today { background: var(--accent); color: var(--accent-text); font-weight: 700; }
.mini-cal-dot { width: 4px; height: 4px; border-radius: 50%; background: var(--accent); }
.mini-cal-day-today .mini-cal-dot { background: var(--accent-text); }

/* "Upcoming deadlines" widget (deadlines.js) — same card treatment as
   .current-session above, but a plain list rather than a single record,
   and independent of the day-nav bar (a 7-day-forward window, not the
   selected day). Hidden entirely when nothing qualifies. */
#upcoming-deadlines {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  padding: 14px 16px;
  margin-bottom: 12px;
}
#upcoming-deadlines h3 { margin: 0 0 8px; font-size: 0.78rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em; color: var(--accent); }
#upcoming-deadlines-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.upcoming-deadline-item {
  display: flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
}
.upcoming-deadline-title { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.current-session-title { margin: 0; font-size: 1.05rem; font-weight: 700; }
.current-session-time { margin: 2px 0 10px; font-size: 0.85rem; color: var(--muted); }
.current-session .checkbox-label { margin: 0; }

/* Event modal */
dialog {
  border: none;
  border-radius: var(--radius-lg);
  padding: 0;
  width: min(520px, 92vw);
  max-height: 90vh;
  background: var(--card-bg);
  color: var(--text);
  box-shadow: var(--shadow);
}
dialog::backdrop { background: oklch(30% 0.03 50 / 0.42); }
:root[data-theme="dark"] dialog::backdrop { background: oklch(10% 0.01 50 / 0.6); }
#event-form {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 26px 28px;
  overflow-y: auto;
  max-height: 90vh;
}
#event-form h2 { margin: 0 0 8px; font-size: 1.25rem; }
#event-form label { font-size: 0.78rem; font-weight: 700; color: var(--muted); margin-top: 8px; }
#event-form input, #event-form select, #event-form textarea {
  padding: 10px 12px;
  border: 1.5px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: 0.92rem;
  width: 100%;
  background: var(--sidebar-bg);
  color: var(--text);
  font-family: inherit;
}
#event-form input:focus, #event-form select:focus, #event-form textarea:focus,
.login-card input:focus, #settings-form input:focus, #goal-form input:focus, #goal-form select:focus {
  outline: none;
  border-color: var(--accent);
}
.field-row { display: flex; gap: 12px; }
.field-row > div { flex: 1; }
/* .field-row's unconditional `display: flex` (author-origin) otherwise beats
   the [hidden] UA default (user-agent-origin) regardless of specificity —
   same class of bug as .timetable-new-course below. Bit ourselves already:
   #recurrence-until-row and #recurrence-days-row both carry class="field-row"
   alongside `hidden`, so without this they render visible even when hidden. */
.field-row[hidden] { display: none; }
.checkbox-label { display: flex; align-items: center; gap: 6px; font-size: 0.9rem; color: var(--text); }
/* .checkbox-label is normally one-per-line (apply-to-row); the reminders
   row needs several side by side instead, wrapping on narrow screens. */
.checkbox-group { display: flex; flex-wrap: wrap; gap: 4px 16px; }
/* #event-form input[type=...] beats #event-form input (both ID-rooted, but
   the type attribute adds specificity) so this reliably wins regardless of
   source order — same class-vs-ID trap as the view[hidden] rule above. */
#event-form input[type="checkbox"],
#event-form input[type="radio"] {
  width: auto;
  flex: 0 0 auto;
}

#settings-form {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 26px 28px;
  overflow-y: auto;
  max-height: 90vh;
}
#settings-form h2 { margin: 0 0 4px; font-size: 1.25rem; }
#settings-form label { font-size: 0.78rem; font-weight: 700; color: var(--muted); margin-top: 8px; }
#settings-form input {
  padding: 10px 12px;
  border: 1.5px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: 0.95rem;
  width: 100%;
  background: var(--sidebar-bg);
  color: var(--text);
  font-family: inherit;
}

/* #settings-form input's boxed/bordered text-field look (above) doesn't
   suit a native range slider — reset the parts that would otherwise box it. */
#settings-form input[type="range"] {
  padding: 0;
  border: none;
  background: none;
  accent-color: var(--accent);
}
#settings-form label span { font-weight: 400; }

#api-keys-section {
  padding: 18px 28px 26px;
  border-top: 1px solid var(--border);
  overflow-y: auto;
}
#api-keys-section h2 { margin: 0 0 4px; font-size: 1.1rem; }
.api-key-row { margin-top: 14px; }
.api-key-row label {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--muted);
  margin-bottom: 6px;
}
.api-key-row label a { font-weight: 600; color: var(--accent); text-decoration: none; }
.api-key-row label a:hover { text-decoration: underline; }
.api-key-status { color: var(--accent); font-weight: 700; }
.api-key-input-row { display: flex; gap: 8px; }
.api-key-input-row input {
  flex: 1;
  min-width: 0;
  padding: 10px 12px;
  border: 1.5px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: 0.92rem;
  background: var(--sidebar-bg);
  color: var(--text);
  font-family: inherit;
}
.api-key-input-row input:focus { outline: none; border-color: var(--accent); }
.api-key-input-row button {
  padding: 8px 16px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--card-bg);
  color: var(--text);
  cursor: pointer;
  font-family: inherit;
  font-weight: 600;
  font-size: 0.82rem;
  flex-shrink: 0;
}

/* Search (Ctrl+K) */
#search-modal { width: min(560px, 92vw); }
.search-modal-body {
  display: flex;
  flex-direction: column;
  padding: 18px;
  max-height: 90vh;
}
.search-modal-header { display: flex; gap: 8px; align-items: center; }
#search-input {
  flex: 1;
  min-width: 0;
  padding: 10px 12px;
  border: 1.5px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: 0.95rem;
  background: var(--sidebar-bg);
  color: var(--text);
  font-family: inherit;
}
#search-input:focus { outline: none; border-color: var(--accent); }
#search-results {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-top: 10px;
  overflow-y: auto;
  max-height: 60vh;
}
.search-result {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 10px;
  border-radius: var(--radius-sm);
  cursor: pointer;
}
.search-result.active, .search-result:hover { background: var(--sidebar-bg); }
.search-result-badge {
  flex-shrink: 0;
  width: 52px;
  text-align: center;
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 3px 0;
  border-radius: 999px;
  color: var(--accent);
  background: var(--accent-soft);
}
.search-result-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.search-result-title {
  font-size: 0.92rem;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.search-result-subtitle {
  font-size: 0.78rem;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
#search-hint { margin: 10px 0 0; font-size: 0.75rem; }

/* Brief flash on the Agenda's to-do list when search.js navigates to one —
   removed again after 2s (see search.js's highlightTodoRow). */
.search-highlight { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--radius-sm); }

/* Notifications dropdown + snooze (public/js/notifications.js) — a plain
   anchored panel rather than a <dialog>, since it needs to sit right below
   its own toggle button instead of centered/backdrop-covering the page like
   every other modal in this app. */
.notifications-wrapper { position: relative; display: inline-flex; }
.notifications-badge {
  position: absolute;
  top: -2px;
  right: -2px;
  min-width: 16px;
  height: 16px;
  padding: 0 3px;
  border-radius: 999px;
  background: var(--danger);
  color: #fff;
  font-size: 0.65rem;
  font-weight: 700;
  line-height: 16px;
  text-align: center;
}
.notifications-panel {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  width: min(340px, 90vw);
  max-height: 70vh;
  overflow-y: auto;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow);
  padding: 14px;
  z-index: 20;
}
.notifications-panel-heading { margin: 0 0 8px; font-size: 0.78rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em; color: var(--accent); }

/* Push on/off row — a real switch rather than a color-shifting pill, so
   the on/off state reads at a glance rather than needing a closer look. */
.notifications-push-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 8px;
  margin-bottom: 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--sidebar-bg);
}
.notifications-push-label { font-size: 0.82rem; font-weight: 600; flex: 1; min-width: 0; }
.notifications-push-status { font-size: 0.76rem; font-weight: 700; color: var(--muted); }
.notifications-push-status.is-on { color: var(--accent); }

.switch {
  position: relative;
  width: 38px;
  height: 22px;
  flex-shrink: 0;
  padding: 0;
  border: none;
  border-radius: 999px;
  background: var(--border);
  cursor: pointer;
}
.switch-thumb {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: #fff;
  box-shadow: var(--shadow-sm);
  transition: transform 0.15s ease;
}
.switch.is-on { background: var(--accent); }
.switch.is-on .switch-thumb { transform: translateX(16px); }

.notifications-empty { margin: 0; font-size: 0.85rem; color: var(--muted); }
.notifications-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.notification-row {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 8px 10px;
}
.notification-row-body { cursor: pointer; }
.notification-row-title { margin: 0; font-size: 0.88rem; font-weight: 600; }
.notification-row-subtitle {
  margin: 2px 0 0;
  font-size: 0.78rem;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.notification-row-time { margin: 2px 0 0; font-size: 0.72rem; color: var(--muted); }
.notification-row-actions { display: flex; gap: 4px; margin-top: 8px; flex-wrap: wrap; }
.notification-snooze-button, .notification-dismiss-button {
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--sidebar-bg);
  color: var(--text);
  font-family: inherit;
  font-size: 0.72rem;
  font-weight: 600;
  padding: 3px 9px;
  cursor: pointer;
}
.notification-snooze-button:hover, .notification-dismiss-button:hover { background: var(--accent-soft); }
.notification-dismiss-button { margin-left: auto; color: var(--danger); }

/* Admin: user management modal */
#admin-modal { width: min(560px, 92vw); }
.admin-modal-body {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 26px 28px;
  overflow-y: auto;
  max-height: 90vh;
}
.admin-modal-body h2 { margin: 0 0 4px; font-size: 1.25rem; }

#admin-user-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
.admin-user-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  font-size: 0.9rem;
  font-weight: 500;
}
.admin-user-email { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.admin-user-row-button {
  flex-shrink: 0;
  width: 22px;
  height: 22px;
  padding: 0;
  border: none;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--muted);
  cursor: pointer;
  font-size: 0.8rem;
  line-height: 1;
}
.admin-user-row-button:hover { background: var(--sidebar-bg); color: var(--text); }
.admin-user-row-button:disabled { opacity: 0.4; cursor: not-allowed; }
.admin-user-row-delete:hover { color: var(--danger); }
.admin-user-row.editing { gap: 6px; }
.admin-user-edit-password {
  flex: 1;
  min-width: 0;
  padding: 5px 7px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--card-bg);
  color: var(--text);
  font-family: inherit;
  font-size: 0.85rem;
}

#admin-create-form {
  display: flex;
  flex-direction: column;
  gap: 8px;
  background: var(--sidebar-bg);
  border-radius: var(--radius-md);
  padding: 14px;
  margin-top: 8px;
}
#admin-create-form input[type="email"],
#admin-create-form input[type="password"] {
  padding: 9px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--card-bg);
  color: var(--text);
  font-family: inherit;
  font-size: 0.85rem;
}
#admin-create-form button {
  padding: 9px;
  border: none;
  border-radius: var(--radius-sm);
  background: var(--accent-soft);
  color: var(--accent);
  cursor: pointer;
  font-family: inherit;
  font-weight: 600;
  font-size: 0.85rem;
}

.weekday-picker { display: flex; gap: 7px; flex-wrap: wrap; }
.weekday-picker button {
  width: 34px;
  height: 34px;
  border-radius: 999px;
  border: 1.5px solid var(--border);
  background: var(--sidebar-bg);
  color: var(--muted);
  font-family: inherit;
  font-size: 0.82rem;
  font-weight: 700;
  cursor: pointer;
}
.weekday-picker button.active { background: var(--accent); border-color: var(--accent); color: var(--accent-text); }

#apply-to-row { background: var(--sidebar-bg); border-radius: var(--radius-sm); padding: 10px 12px; margin: 4px 0; }
#apply-to-row .checkbox-label { margin: 2px 0; }
.help-text { font-size: 0.78rem; color: var(--muted); margin: 2px 0 6px; line-height: 1.5; }

#event-documents-section { margin-top: 10px; border-top: 1px solid var(--border); padding-top: 14px; }
#event-documents-section h3 { font-size: 0.78rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted); margin: 0 0 8px; font-family: inherit; }
#event-document-list { list-style: none; margin: 0 0 8px; padding: 0; display: flex; flex-direction: column; gap: 4px; }
#event-document-list li {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.9rem;
  background: var(--sidebar-bg);
  border-radius: var(--radius-sm);
  padding: 8px 10px;
}
#event-document-list a { flex: 1; color: var(--accent); text-decoration: none; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#event-document-list button {
  background: none;
  border: none;
  color: var(--danger);
  cursor: pointer;
  font-size: 0.85rem;
}
#event-documents-section .field-row { align-items: center; }
#add-document-button {
  white-space: nowrap;
  border: 1.5px dashed var(--border);
  background: none;
  color: var(--muted);
  font-family: inherit;
  font-weight: 600;
  border-radius: 999px;
  cursor: pointer;
  padding: 9px 14px;
  font-size: 0.82rem;
}

.study-helper-button {
  background: none;
  border: none;
  cursor: pointer;
  font-size: 0.95rem;
  padding: 0 2px;
}

/* AI study helper modal */
.summary-modal-body {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 26px 28px;
  overflow-y: auto;
  max-height: 90vh;
}
.summary-modal-body h2 { margin: 0 0 4px; font-size: 1.25rem; }
.summary-modal-body h3 { font-size: 0.9rem; color: var(--muted); margin: 12px 0 4px; font-family: inherit; }
.summary-modal-body p { margin: 0; line-height: 1.5; }
.summary-modal-body textarea {
  width: 100%;
  padding: 10px 12px;
  border: 1.5px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--sidebar-bg);
  color: var(--text);
  font-family: inherit;
  font-size: 0.9rem;
  margin: 8px 0;
}
.summary-modal-body > div > button {
  padding: 9px 16px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--card-bg);
  color: var(--text);
  font-family: inherit;
  font-weight: 600;
  cursor: pointer;
  margin-top: 8px;
}
#summarize-button, #summarize-pasted-button { background: var(--accent); color: var(--accent-text); border: none; }
#summarize-button:hover, #summarize-pasted-button:hover { background: var(--accent-hover); }

.summary-modal-body .field-row { align-items: center; margin-top: 8px; }
.summary-modal-body .field-row button {
  padding: 9px 16px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--card-bg);
  color: var(--text);
  font-family: inherit;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
}

#summary-topics { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.topic-row {
  background: var(--sidebar-bg);
  border-radius: var(--radius-sm);
  padding: 10px 12px;
}
.topic-row .topic-label { display: block; font-weight: 600; margin-bottom: 4px; }
.topic-row button {
  background: none;
  border: none;
  color: var(--accent);
  cursor: pointer;
  font-family: inherit;
  font-weight: 600;
  font-size: 0.85rem;
  padding: 0;
}
.topic-row button:disabled { opacity: 0.6; cursor: default; }
.topic-guidance { margin-top: 6px; white-space: pre-line; }

.modal-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 16px; }
.modal-actions button {
  padding: 10px 18px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--card-bg);
  color: var(--text);
  font-family: inherit;
  font-weight: 600;
  font-size: 0.88rem;
  cursor: pointer;
}
.modal-actions button[type="submit"] { background: var(--accent); color: var(--accent-text); border: none; }
.modal-actions button[type="submit"]:hover { background: var(--accent-hover); }
.modal-actions .danger { color: var(--danger); border: none; background: none; margin-right: auto; }

/* Timetable import modal */
#timetable-modal { width: min(760px, 95vw); }
.timetable-modal-body {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 26px 28px;
  overflow-y: auto;
  max-height: 90vh;
}
.timetable-modal-body h2 { margin: 0 0 4px; font-size: 1.25rem; }
#timetable-idle input[type="file"] { margin-top: 6px; }
#timetable-error button, #timetable-idle button {
  padding: 9px 16px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--card-bg);
  color: var(--text);
  font-family: inherit;
  font-weight: 600;
  cursor: pointer;
  margin-top: 8px;
}
#timetable-review .field-row { align-items: flex-end; margin-bottom: 10px; }

#timetable-rows-wrap { overflow-x: auto; }
#timetable-rows-table { width: 100%; border-collapse: collapse; font-size: 0.85rem; }
#timetable-rows-table th {
  text-align: left;
  font-weight: 700;
  color: var(--muted);
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 4px 6px;
  white-space: nowrap;
}
#timetable-rows-table td { padding: 5px 6px; vertical-align: top; }
#timetable-rows-table tr:not(:last-child) td { border-bottom: 1px solid var(--border); }
#timetable-rows-table input[type="text"],
#timetable-rows-table input[type="time"],
#timetable-rows-table select {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--sidebar-bg);
  color: var(--text);
  font-family: inherit;
  padding: 5px 7px;
  font-size: 0.85rem;
  width: 100%;
  min-width: 90px;
}
#timetable-rows-table td:first-child { width: 24px; min-width: 0; }
.timetable-new-course { display: flex; gap: 4px; margin-top: 4px; }
.timetable-new-course[hidden] { display: none; }
.timetable-new-course input[type="text"] { min-width: 100px; }
.timetable-new-course input[type="color"] { padding: 0; width: 32px; min-width: 32px; height: 30px; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--sidebar-bg); }

#timetable-import-button { background: var(--accent); color: var(--accent-text); border: none; }
#timetable-import-button:hover { background: var(--accent-hover); }

/* Syllabus import modal — same shape as the timetable one above (reuses
   .timetable-modal-body for the shared layout), just its own row table. */
#syllabus-modal { width: min(760px, 95vw); }
#syllabus-idle input[type="file"] { margin-top: 6px; }
#syllabus-error button, #syllabus-idle button {
  padding: 9px 16px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--card-bg);
  color: var(--text);
  font-family: inherit;
  font-weight: 600;
  cursor: pointer;
  margin-top: 8px;
}

#syllabus-rows-wrap { overflow-x: auto; }
#syllabus-rows-table { width: 100%; border-collapse: collapse; font-size: 0.85rem; }
#syllabus-rows-table th {
  text-align: left;
  font-weight: 700;
  color: var(--muted);
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 4px 6px;
  white-space: nowrap;
}
#syllabus-rows-table td { padding: 5px 6px; vertical-align: top; }
#syllabus-rows-table tr:not(:last-child) td { border-bottom: 1px solid var(--border); }
#syllabus-rows-table input[type="text"],
#syllabus-rows-table input[type="date"],
#syllabus-rows-table select {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--sidebar-bg);
  color: var(--text);
  font-family: inherit;
  padding: 5px 7px;
  font-size: 0.85rem;
  width: 100%;
  min-width: 90px;
}
#syllabus-rows-table td:first-child { width: 24px; min-width: 0; }
.syllabus-new-course { display: flex; gap: 4px; margin-top: 4px; }
.syllabus-new-course[hidden] { display: none; }
.syllabus-new-course input[type="text"] { min-width: 100px; }
.syllabus-new-course input[type="color"] { padding: 0; width: 32px; min-width: 32px; height: 30px; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--sidebar-bg); }

#syllabus-import-button { background: var(--accent); color: var(--accent-text); border: none; }
#syllabus-import-button:hover { background: var(--accent-hover); }

/* Mobile */
@media (max-width: 720px) {
  #sidebar {
    position: fixed;
    inset: 60px 0 0 0;
    z-index: 5;
    width: auto;
    transform: translateX(-100%);
    transition: transform 0.2s ease;
  }
  #sidebar.open { transform: translateX(0); }
  .topbar { padding: 10px 10px; gap: 5px; flex-wrap: nowrap; }
  /* The app title just loses to the action buttons for space below ~720px —
     the hamburger + being inside the app already are identity enough, so it
     drops rather than being left to truncate to one or two letters. This is
     the actual fix for the topbar wrapping/overlapping on phones. */
  .topbar h1 { display: none; }
  #current-user-email { display: none; }
  #new-event-button { padding: 8px 12px; font-size: 0.82rem; flex-shrink: 0; }
  #new-event-button svg { display: none; }
  .icon-toggle-button, .icon-button:not(#menu-toggle) { width: 33px; height: 33px; }
  .icon-toggle-button svg, .icon-button:not(#menu-toggle) svg { width: 15px; height: 15px; }
  .view-tabs { padding: 14px 16px 0; }
  #today-view, #calendar, #goals-view, #review-view, #grades-view { padding: 16px; }
  #today-view { flex-direction: column; }
  #agenda-main { max-width: none; }
  #agenda-side { max-width: none; width: 100%; }
  /* Weather + snapshot side by side is too cramped on a narrow phone —
     back to stacked, same as every other #agenda-side card. */
  #agenda-weather-row { flex-direction: column; }
  #agenda-weather, #agenda-mini-calendar { flex-basis: auto; }

  /* FullCalendar's own header toolbar (prev/next/today, title, the
     month/week/day/list switcher) lays its 3 chunks out with
     justify-content: space-between and no wrapping by default — on a
     phone-width screen that's real overlap, not just tightness. */
  .fc-header-toolbar { flex-wrap: wrap; row-gap: 8px; }
  .fc-toolbar-chunk { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }
  .fc .fc-toolbar-title { font-size: 1.05rem; }
}
