/* SOLIDIUM — styles.css: the single stylesheet for the whole app; sections are numbered below. */

/* 1. DESIGN TOKENS ------------------------------------------------------- */
:root {
  --accent:        #325962;   /* deep teal-slate — calm, accessible (Silvallis Studios) */
  --accent-soft:   #e4eff1;
  --accent-ink:    #2e606b;
  --accent-strong: #325962;   /* accent is dark enough to carry white text directly */
  --on-accent:     #ffffff;   /* text/icon colour ON accent fills */

  --bg:            #f4f6f9;
  --surface:       #ffffff;
  --surface-2:     #f0f3f7;
  --border:        #e2e8f0;
  --text:          #1f2933;
  --muted:         #64748b;
  --danger:        #dc2626;
  --warn:          #d97706;
  --ok:            #16a34a;

  --radius:        14px;
  --radius-sm:     9px;
  --shadow:        0 1px 2px rgba(15,23,42,.06), 0 8px 24px rgba(15,23,42,.06);
  --shadow-sm:     0 1px 2px rgba(15,23,42,.08);

  --space:         16px;
  --sidebar-w:     232px;

  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica,
          Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
}

/* Dark-mode tokens. Two triggers, ONE token set (keep the blocks below in sync if you change a
   value): • the OS prefers dark AND the user hasn't forced Light → the @media block • the user
   explicitly picks Dark in Settings → data-theme="dark" Settings stamps data-theme on <html> (see
   theme.js); absent = follow the system. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --accent:      #72b9ca;
    --accent-soft: #223d44;
    --accent-ink:  #b5dae3;
    --accent-strong: #72b9ca;   /* accent carries dark text on dark-mode buttons */
    --on-accent:     #0f141a;
    --bg:          #0f141a;
    --surface:     #171d26;
    --surface-2:   #1e2530;
    --border:      #2a323d;
    --text:        #e6edf3;
    --muted:       #94a3b8;
    --shadow:      0 1px 2px rgba(0,0,0,.3), 0 10px 30px rgba(0,0,0,.35);
  }
}
:root[data-theme="dark"] {
  --accent:      #72b9ca;
  --accent-soft: #223d44;
  --accent-ink:  #b5dae3;
  --accent-strong: #72b9ca;
  --on-accent:     #0f141a;
  --bg:          #0f141a;
  --surface:     #171d26;
  --surface-2:   #1e2530;
  --border:      #2a323d;
  --text:        #e6edf3;
  --muted:       #94a3b8;
  --shadow:      0 1px 2px rgba(0,0,0,.3), 0 10px 30px rgba(0,0,0,.35);
}

/* 2. BASE + RESET ------------------------------------------------------- */
* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  font-family: var(--font);
  background: var(--bg);
  color: var(--text);
  -webkit-font-smoothing: antialiased;
  line-height: 1.45;
}
h1, h2, h3, h4 { margin: 0 0 .4em; line-height: 1.2; }
h1 { font-size: 1.5rem; letter-spacing: -.01em; }
h2 { font-size: 1.15rem; }
p  { margin: 0 0 .6em; }
a  { color: inherit; text-decoration: none; }
button { font-family: inherit; }

/* 3. APP SHELL ---------------------------------------------------------- */
.app { display: flex; flex-direction: column; min-height: 100%; }

/* Top header bar: brand · pill nav · utilities. */
.appbar {
  position: sticky; top: 0; z-index: 30;
  display: flex; align-items: center; gap: 16px;
  height: 56px; padding: 0 18px;
  background: var(--surface); border-bottom: 1px solid var(--border);
}
.appbar__brand { display: flex; align-items: center; gap: 9px; }
.brand__mark {
  display: grid; place-items: center;
  width: 30px; height: 30px; border-radius: 9px;
  background: var(--accent-strong); color: var(--on-accent); font-weight: 700;
}
.brand__name { font-weight: 700; font-size: 1.06rem; letter-spacing: -.02em; }

/* Primary nav = a pill group of text tabs on desktop (icons return on mobile). */
.nav {
  display: flex; align-items: center; gap: 2px;
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: 10px; padding: 3px;
}
.nav__link {
  display: flex; align-items: center; padding: 6px 13px;
  border-radius: 7px; color: var(--muted);
  font-weight: 600; font-size: .88rem; white-space: nowrap;
  transition: background .12s, color .12s;
}
/* `.nav__link { display: flex }` above would otherwise beat the UA [hidden] rule (equal
   specificity, author wins), leaving a `hidden` pill — e.g. Admin — visible. */
.nav__link[hidden] { display: none; }
.nav__link:hover { color: var(--text); }
.nav__link.is-active { background: var(--surface); color: var(--accent-ink); box-shadow: var(--shadow); }
.nav__ico { display: none; }
/* Desktop: the secondary group flows inline as pills; "More", the sheet header, and the sheet
   backdrop are mobile-only (see the phone bottom-bar rules below). */
.nav__secondary { display: contents; }
.nav__more, .nav__sheet-head, .nav-sheet-bd { display: none; }

/* Between the phone breakpoint (720px) and a roomy desktop, the full pill nav is wider than the
   window — nine text pills plus the brand and the utilities want ~1200px, but the desktop layout
   takes over at 721px. .appbar is a nowrap flex row and nothing in it can shrink, so the overflow
   widened the DOCUMENT: the header sat at its natural width while the main view scrolled sideways
   underneath it. Two tiers close the gap. First the pills fall back to the icon every link already
   carries (the `title` still names it on hover). */
@media (min-width: 721px) and (max-width: 1024px) {
  .brand__name { display: none; }
  .nav__link { padding: 6px 10px; }
  .nav__label { display: none; }
  .nav__ico { display: block; font-size: 1.05rem; line-height: 1; }
}
/* Last resort, so no future link can stretch the page again: the pill group scrolls inside itself.
   Desktop only — on phones .nav is the positioning context for the slide-up "More" sheet, and a
   scroll container would clip it. */
@media (min-width: 721px) {
  .nav { min-width: 0; overflow-x: auto; scrollbar-width: none; }
  .nav::-webkit-scrollbar { display: none; }
}

.appbar__util { margin-left: auto; display: flex; align-items: center; gap: 8px; }
/* Links to the server-rendered legal pages (privacy / terms / deletion). Quiet by design: they
   have to be FINDABLE — a payment processor and a Play reviewer both look for them — without
   competing with the app for attention. */
.legal-links {
  margin-top: 6px;
  font-size: .76rem;
  line-height: 1.5;
  color: var(--muted);
  text-align: center;
}
.legal-links a {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid transparent;
}
.legal-links a:hover,
.legal-links a:focus-visible {
  color: var(--accent);
  border-bottom-color: currentColor;
}
/* Inside a settings card the surrounding text is left-aligned, so these should be too. */
.card .legal-links { text-align: left; margin-top: 0; font-size: .9rem; }

.link-quiet {
  color: var(--muted);
  font-size: .9rem;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.link-quiet:hover { color: var(--accent); }

.sidebar__copyright,
.main__copyright,
.auth__copyright {
  color: var(--muted);
  font-size: .76rem;
  line-height: 1.4;
  text-align: center;
}
.sidebar__copyright {
  margin-top: 12px;
}

.main {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  min-width: 0;                     /* lets content shrink instead of overflow */
  width: 100%;
  margin: 0 auto;                   /* centre the reading column under the header */
  padding: 28px clamp(16px, 4vw, 40px) 80px;
  max-width: 1080px;
}
#view { flex: 1 1 auto; }
.main__copyright { display: block; padding-top: 18px; }
body[data-route="notes"] .main__copyright { display: none; }   /* the notes workspace is full-bleed */

/* The Notes app is a two-pane workspace (tree + editor), not prose — let it use the full desktop
   width, flush to the edges, below the header. */
body[data-route="notes"] .main { max-width: none; padding: 0; }

/* A standard page header used by every view */
.page-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; margin-bottom: 20px; flex-wrap: wrap;
}
.page-head .sub { color: var(--muted); font-size: .95rem; }

/* Unconfirmed-email reminder, sits above the routed view. Deliberately quiet — verification isn't
   enforced, so this informs rather than alarms: the accent tint rather than the danger red, and a
   dismiss button. */
.verify-bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap;
  margin-bottom: 18px; padding: 10px 14px;
  background: var(--accent-soft); color: var(--accent-ink);
  border: 1px solid var(--border); border-radius: var(--radius);
  font-size: .9rem;
}

/* The lapsed-subscription variant. Warm rather than red: edits not saving is a problem to fix,
   not a failure or a danger, and the red palette belongs to destructive actions like deleting an
   account. It is also not dismissible — it is the explanation for why the app stopped saving. */
.verify-bar--warn {
  background: color-mix(in srgb, var(--warn) 12%, var(--surface));
  color: var(--text);
  border-color: color-mix(in srgb, var(--warn) 40%, var(--border));
}
.verify-bar--warn .verify-bar__btn {
  background: var(--warn);
  border-color: var(--warn);
  color: #fff;
  text-decoration: none;
}

/* Subscription card: the current plan line, then the buttons. */
.sub-state { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; margin: .2rem 0 .8rem; }
.sub-state__badge {
  font-size: .74rem; font-weight: 650; letter-spacing: .02em; text-transform: uppercase;
  padding: 2px 8px; border-radius: 999px;
  background: var(--surface-2); color: var(--muted); border: 1px solid var(--border);
}
.sub-state__badge.is-ok   { background: color-mix(in srgb, var(--ok) 14%, var(--surface));
                            color: var(--ok); border-color: color-mix(in srgb, var(--ok) 38%, var(--border)); }
.sub-state__badge.is-warn { background: color-mix(in srgb, var(--warn) 14%, var(--surface));
                            color: var(--warn); border-color: color-mix(in srgb, var(--warn) 38%, var(--border)); }
.sub-plans { display: flex; gap: 10px; flex-wrap: wrap; }
.verify-bar__text { min-width: 0; }
.verify-bar__actions { display: flex; align-items: center; gap: 8px; flex: none; }
/* The banner sits on --accent-soft, which is close enough to --surface that a ghost button's
   border all but disappears. Solid fill instead, so the one thing worth pressing looks pressable. */
.verify-bar__btn { background: var(--accent-strong); color: var(--on-accent); border-color: transparent; }
.verify-bar__btn:hover { filter: brightness(1.08); }
.verify-bar__btn:disabled { opacity: .65; cursor: default; filter: none; }
/* Dismiss stays quiet — it's the secondary action, and the contrast between the two is what makes
   Resend read as primary. */
.verify-bar .icon-btn { background: transparent; border-color: transparent; color: inherit; opacity: .7; }
.verify-bar .icon-btn:hover { opacity: 1; background: rgb(0 0 0 / .06); }

/* 4. COMPONENTS --------------------------------------------------------- */

/* Buttons */
.btn {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 9px 15px; border-radius: 10px;
  border: 1px solid transparent; cursor: pointer;
  font-size: .92rem; font-weight: 600;
  background: var(--accent-strong); color: var(--on-accent);
  transition: filter .12s, background .12s, border-color .12s;
}
.btn:hover { filter: brightness(1.06); }
.btn:active { filter: brightness(.96); }
.btn--ghost { background: transparent; color: var(--text); border-color: var(--border); }
.btn--ghost:hover { background: var(--surface-2); filter: none; }
.btn--sm { padding: 6px 11px; font-size: .85rem; }
.btn--danger { background: var(--danger); color: #fff; border-color: var(--danger); }
.btn--block { width: 100%; justify-content: center; }

/* A visually separated "danger zone" for irreversible actions (delete account). */
.danger-zone { margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--border); }
.danger-zone__title { font-weight: 700; color: var(--danger); font-size: .95rem; margin-bottom: 2px; }

/* Cards */
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  padding: 18px;
}
.grid { display: grid; gap: 16px; }
.grid--2 { grid-template-columns: repeat(2, 1fr); }
.grid--3 { grid-template-columns: repeat(3, 1fr); }

/* Section titles inside cards */
.section-title {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 12px;
}
.section-title h2 { margin: 0; }

/* Form controls */
label.field { display: block; margin-bottom: 12px; }
label.field > span { display: block; font-size: .82rem; color: var(--muted); margin-bottom: 5px; font-weight: 600; }
.input, .select, .textarea {
  width: 100%; padding: 10px 12px;
  border: 1px solid var(--border); border-radius: 10px;
  background: var(--surface); color: var(--text);
  font-size: .95rem; font-family: inherit;
}
.input:focus, .select:focus, .textarea:focus {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.textarea { resize: vertical; min-height: 90px; }
.row { display: flex; gap: 12px; }
.row > * { flex: 1; }

/* Chips (little colored labels — used for course tags, priorities) */
.chip {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 9px; border-radius: 999px;
  font-size: .76rem; font-weight: 600;
  background: var(--surface-2); color: var(--muted);
}
.chip__dot { width: 8px; height: 8px; border-radius: 50%; background: currentColor; }
/* An affirmative chip — reads as a standing grant rather than neutral metadata. */
.chip--ok { background: var(--accent-soft); color: var(--accent-ink); }

/* Boot splash — a plain brand-colored screen that covers the app from the first paint until JS
   decides login-vs-app, so the internal UI never flashes on refresh. Driven by .is-booting on
   <body>, cleared at the end of boot. */
#splash {
  position: fixed; inset: 0; z-index: 4000;
  display: flex; align-items: center; justify-content: center;
  background: var(--accent); color: var(--on-accent);
  /* Fade OUT on exit (not a hard cut, which reads as a blink). visibility is delayed by the fade
     so the splash stays painted while it fades, then drops. */
  transition: opacity .3s ease, visibility 0s linear .3s;
}
.splash__mark { font-size: 3.2rem; opacity: .92; }
body.is-booting .app { visibility: hidden; }
/* Boot resolved → the login/app is revealed beneath and the splash fades away. */
body:not(.is-booting) #splash { opacity: 0; visibility: hidden; }
@media (prefers-reduced-motion: reduce) { #splash { transition: none; } }

/* Empty states */
.empty { text-align: center; color: var(--muted); padding: 42px 20px; }
.empty .big { font-size: 2rem; margin-bottom: 8px; opacity: .7; }

/* View error boundary — shown in place of a screen that failed to render, so a single broken view
   degrades gracefully instead of leaving a blank pane. */
.view-error { max-width: 460px; margin: 64px auto; text-align: center; padding: 28px 24px; }
.view-error h2 { margin: 0 0 8px; }
.view-error p { margin: 0 0 18px; }

/* Modal (pop-up dialog) */
.modal { position: fixed; inset: 0; z-index: 50; display: grid; place-items: center; padding: 16px; }
.modal[hidden] { display: none; }
.modal__backdrop { position: absolute; inset: 0; background: rgba(15,23,42,.45); backdrop-filter: blur(2px); }
.modal__card {
  position: relative; z-index: 1;
  background: var(--surface); border-radius: var(--radius);
  box-shadow: var(--shadow); width: min(520px, 100%);
  max-height: 88vh; overflow: auto; padding: 24px;
}
.modal__x {
  position: absolute; top: 12px; right: 12px;
  width: 32px; height: 32px; border-radius: 8px;
  border: none; background: var(--surface-2); color: var(--muted);
  cursor: pointer; font-size: .9rem;
}
.modal__x:hover { background: var(--border); }

/* Toast */
.toast {
  position: fixed; bottom: 24px; left: 50%; transform: translateX(-50%);
  background: var(--text); color: var(--bg);
  padding: 10px 18px; border-radius: 999px; font-size: .9rem; font-weight: 600;
  box-shadow: var(--shadow); z-index: 60; animation: toast-in .2s ease;
}
.toast[hidden] { display: none; }
@keyframes toast-in { from { opacity: 0; transform: translate(-50%, 8px); } }

/* 5. FEATURE-SPECIFIC --------------------------------------------------- */

/* Stat tiles (dashboard) */
.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 14px; }
.stat { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 16px; }
.stat__num { font-size: 1.8rem; font-weight: 700; letter-spacing: -.02em; }
.stat__label { color: var(--muted); font-size: .85rem; }

/* Generic list rows (tasks, events, study sessions) */
.list { display: flex; flex-direction: column; gap: 8px; }
.item {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 14px; background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--radius-sm);
}
.item__main { flex: 1; min-width: 0; }
.item__title { font-weight: 600; }
.item__meta { color: var(--muted); font-size: .82rem; display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
.item.is-done .item__title { text-decoration: line-through; color: var(--muted); }
.item__actions { display: flex; gap: 6px; }

/* A round checkbox for tasks */
.check {
  appearance: none; -webkit-appearance: none;
  width: 22px; height: 22px; border-radius: 50%;
  border: 2px solid var(--border); cursor: pointer; flex: none;
  display: grid; place-items: center; transition: .12s;
}
.check:checked { background: var(--accent-strong); border-color: var(--accent-strong); }
.check:checked::after { content: "✓"; color: var(--on-accent); font-size: .8rem; font-weight: 700; }

/* Icon button (small square, e.g. delete/edit) */
.icon-btn {
  width: 32px; height: 32px; border-radius: 15px; flex: none;
  padding: 5px;
  border: 1px solid var(--border); background: var(--surface);
  color: var(--muted); cursor: pointer; font-size: .85rem;
}
.icon-btn:hover { background: var(--surface-2); color: var(--text); }
.icon-btn--danger:hover { color: var(--danger); border-color: var(--danger); }

.icon-tree-btn {
  width: 60px; height: 32px; border-radius: 8px; flex: none;
  padding: 4px;
  border: 1px solid var(--border); background: var(--surface);
  color: var(--muted); cursor: pointer; font-size: .75rem;
}
.icon-tree-btn:hover { background: var(--surface-2); color: var(--text); }
.icon-tree-btn--danger:hover { color: var(--danger); border-color: var(--danger); }

/* Calendar grid */
/* The calendar's page head is two rows (see renderCalendar), not the shared .page-head — that one
   wrapping flex row put three groups wherever the width happened to leave them. Spacing comes
   from .cal-rows' gap, so .cal-head no longer carries a bottom margin of its own. */
.cal-rows { display: flex; flex-direction: column; gap: 12px; margin-bottom: 20px; }
.cal-bar { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.cal-head { display: flex; align-items: center; gap: 12px; }
.cal-head h2 { min-width: 190px; }
/* Phones: .cal-head doesn't wrap, so the title's min-width would push it past the viewport and
   scroll the whole page sideways. */
@media (max-width: 720px) {
  .cal-rows { gap: 10px; margin-bottom: 14px; }
  .cal-bar { gap: 10px; }
  .cal-head h2 { min-width: 0; font-size: 1.05rem; }
}
.cal-grid {
  display: grid; grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 6px; background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--radius); padding: 10px;
}
.cal-dow { text-align: center; font-size: .74rem; font-weight: 700; color: var(--muted); padding: 4px 0; text-transform: uppercase; letter-spacing: .04em; }
.cal-cell {
  min-width: 0;                    /* let the track shrink so long labels ellipsize, not stretch the grid */
  min-height: 84px; border-radius: var(--radius-sm);
  border: 1px solid transparent; padding: 6px; cursor: pointer;
  display: flex; flex-direction: column; gap: 3px;
  background: var(--surface-2); transition: border-color .12s;
  overflow: hidden;
}
.cal-ev, .cal-more, .cal-cell__num { max-width: 100%; }
.cal-cell:hover { border-color: var(--accent); }
.cal-cell.is-out { opacity: .4; }
.cal-cell.is-today { outline: 2px solid var(--accent); outline-offset: -2px; }
.cal-cell__num { font-size: .82rem; font-weight: 600; color: var(--muted); }
.cal-cell.is-today .cal-cell__num { color: var(--accent-ink); }
.cal-ev {
  font-size: .72rem; font-weight: 600; color: #fff;
  padding: 2px 6px; border-radius: 5px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.cal-more { font-size: .7rem; color: var(--muted); font-weight: 600; }

/* Study sessions on the calendar: outlined (not filled) so they read as a different layer from
   classes, with a 📚 marker. Colour comes from inline style. */
.cal-ev--study {
  color: var(--accent-ink); background: transparent;
  border: 1px dashed currentColor; font-weight: 600;
}
/* Deadlines (assignment/exam/study items): a SOLID outline in their colour, so they read as a
   third layer distinct from filled classes and dashed study. */
.cal-ev--deadline {
  background: transparent; border: 1px solid currentColor; font-weight: 600;
}
/* Calendar toolbar: the Classes/Study/All toggle sits beside "+ Class". */
.cal-tools { display: flex; align-items: center; gap: 10px; }

/* Imported-calendars dropdown, anchored under its button in .cal-tools. Same shape as .md-menu in
   the notes toolbar, but rows instead of swatches. */
.cal-menu-wrap { position: relative; display: inline-flex; }
.cal-menu {
  /* Anchored left, because the Calendars button sits at the START of row 1. Anchoring right would
     hang the 264px panel off the left edge of the screen. */
  position: absolute; top: calc(100% + 6px); left: 0; z-index: 40;
  min-width: 264px; max-width: min(340px, 90vw); max-height: 320px; overflow-y: auto;
  display: flex; flex-direction: column; gap: 2px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 6px; box-shadow: 0 8px 24px rgb(0 0 0 / .14);
}
.cal-menu[hidden] { display: none; }
.cal-menu__row { display: flex; align-items: center; gap: 8px; padding: 4px 6px; border-radius: 8px; }
.cal-menu__row:hover { background: var(--surface-2); }
/* The label takes the slack so the count and delete button stay put on every row. */
.cal-menu__show { display: flex; align-items: center; gap: 8px; flex: 1 1 auto; min-width: 0; cursor: pointer; }
.cal-menu__label { font-size: .88rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cal-menu__count { font-size: .74rem; color: var(--muted); flex: none; font-variant-numeric: tabular-nums; }
.cal-menu__empty { font-size: .85rem; color: var(--muted); margin: 0; padding: 6px; max-width: 30ch; }

/* Import review: one row per event about to come in, so an exam buried in a semester of lectures
   can be re-typed before it lands. Scrolls, because a school feed is routinely hundreds of
   events. */
.import-review {
  max-height: 240px; overflow-y: auto; margin: .4rem 0;
  border: 1px solid var(--border); border-radius: var(--radius); padding: 4px;
}
.import-review[hidden] { display: none; }
.import-review__row { display: flex; align-items: center; gap: 8px; padding: 3px 4px; border-radius: 6px; }
.import-review__row:hover { background: var(--surface-2); }
/* The name absorbs the slack so the date and type control line up down the list. */
.import-review__name { flex: 1 1 auto; min-width: 0; font-size: .85rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.import-review__when { flex: none; font-size: .74rem; color: var(--muted); font-variant-numeric: tabular-nums; }
.import-review__type { flex: none; width: auto; padding: 2px 4px; font-size: .78rem; }

/* Review reminders (Study Planner) + the "time to review" nudge (Today). */
.tagrow { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.reminder { align-items: center; }
.reminder__dot { font-size: 1.1rem; width: 1.4rem; text-align: center; flex: 0 0 auto; }
.reminder.is-fresh    { border-left: 3px solid var(--ok); }
.reminder.is-fresh    .reminder__dot { color: var(--ok); }
.reminder.is-overdue  { border-left: 3px solid var(--danger); }
.reminder.is-overdue  .reminder__dot { color: var(--danger); }
.reminder.is-stale    { border-left: 3px solid var(--warn); }
.reminder.is-stale    .reminder__dot { color: var(--warn); }
.review-nudge { border-left: 4px solid var(--warn); }

/* Notes: two-pane (list + editor) */
.notes { display: grid; grid-template-columns: 260px 1fr; gap: 16px; align-items: start; }
.note-list { display: flex; flex-direction: column; gap: 6px; }
.note-list__item { padding: 11px 13px; border-radius: var(--radius-sm); border: 1px solid var(--border); background: var(--surface); cursor: pointer; }
.note-list__item:hover { border-color: var(--accent); }
.note-list__item.is-active { border-color: var(--accent); background: var(--accent-soft); }
.note-list__item .t { font-weight: 600; font-size: .92rem; }
.note-list__item .d { font-size: .76rem; color: var(--muted); }

/* Notebook cards (the top level of the Notebooks view) */
.nb-card { cursor: pointer; transition: border-color .12s, box-shadow .12s, transform .12s; }
.nb-card:hover { border-color: var(--accent); box-shadow: var(--shadow); }
.nb-card .section-title { align-items: flex-start; }
.nb-head { display: flex; align-items: center; gap: 12px; }
.nb-head h1 { margin: 0; }

/* Note editor */
.note-editor__head { display: flex; align-items: center; gap: 8px; }
.note-title { font-weight: 700; font-size: 1.05rem; border: none; padding-left: 0; background: transparent; }
.note-title:focus { box-shadow: none; }
.note-editor__meta { margin-top: 10px; }
.note-editor__body { margin-top: 12px; }
.note-body { min-height: 340px; font-size: .95rem; line-height: 1.55; }
.note-editor__foot { font-size: .8rem; margin-top: 8px; }
/* Find-in-note bar + match highlights. */
.note-find { display: flex; align-items: center; gap: 6px; margin-bottom: 8px; padding: 5px 8px; background: var(--surface-2); border: 1px solid var(--border); border-radius: 8px; }
.note-find[hidden] { display: none; }
.note-find__input { flex: 1 1 auto; min-width: 120px; max-width: 280px; }
.note-find__count { font-size: .82rem; white-space: nowrap; min-width: 46px; }
mark.find-hit { background: var(--hl-yellow); color: inherit; border-radius: 2px; padding: 0 1px; }
mark.find-hit.is-current { background: var(--accent); color: #fff; }
.note-editor__tags { margin-top: 10px; }

/* Reusable tag editor (chips + type-to-add) */
.tagin {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  border: 1px solid var(--border); border-radius: 10px; padding: 6px 8px;
  background: var(--surface); min-height: 40px;
}
.tagin:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.tagin__chips { display: contents; }
.tagin__input {
  flex: 1; min-width: 90px; border: none; outline: none; background: transparent;
  color: var(--text); font-size: .9rem; font-family: inherit; padding: 2px;
}
.tagchip {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: .8rem; font-weight: 600;
  background: var(--surface-2); border-radius: 999px; padding: 2px 4px 2px 9px;
}
.tagchip__x {
  border: none; background: none; cursor: pointer; color: inherit; opacity: .55;
  font-size: .7rem; line-height: 1; padding: 2px 4px; border-radius: 50%;
}
.tagchip__x:hover { opacity: 1; background: color-mix(in srgb, currentColor 18%, transparent); }

/* Search + tag filter (Notebooks landing) */
.search { display: flex; flex-direction: column; gap: 10px; margin-bottom: 18px; }
.search__meta { font-size: .82rem; margin-bottom: 10px; }
.tagfilter { display: flex; flex-wrap: wrap; gap: 6px; }
.tagfilter__chip {
  border: 1px solid var(--border); background: var(--surface);
  border-radius: 999px; padding: 3px 11px; cursor: pointer;
  font-size: .8rem; font-weight: 600; color: var(--muted); font-family: inherit;
  transition: border-color .12s, color .12s, background .12s;
}
.tagfilter__chip:hover { border-color: var(--tc); color: var(--text); }
.tagfilter__chip.is-active { background: var(--tc); border-color: var(--tc); color: #fff; }
.search-result { cursor: pointer; }
.search-result:hover { border-color: var(--accent); }
.search-result__snippet { font-size: .84rem; margin-top: 5px; line-height: 1.45; }

.filter-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 16px;
  margin-bottom: 18px;
}
.filter-bar__item {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 220px;
}

/* ---- Obsidian-style Notebooks: tree panel + editor -------------------- */
.noteapp { display: flex; align-items: stretch; gap: 0; min-height: calc(100vh - 56px); }
.noteapp__tree {
  width: 288px; flex: 0 0 288px; display: flex; flex-direction: column; gap: 10px;
  background: var(--surface); border-right: 1px solid var(--border);
  padding: 16px 12px; position: sticky; top: 56px; height: calc(100vh - 56px); max-height: calc(100vh - 56px);
}
.noteapp__main { flex: 1 1 auto; min-width: 0; padding: 24px clamp(16px, 3vw, 34px); }
.noteapp__empty {
  display: grid; place-content: center; justify-items: center; gap: 8px;
  height: 100%; min-height: 320px; text-align: center; color: var(--muted);
  border: 1px dashed var(--border); border-radius: var(--radius); padding: 24px;
}
.noteapp__empty .big { font-size: 2.4rem; opacity: .5; }
.noteapp__empty p { max-width: 34ch; }
.noteapp__back { display: none; }

.tree__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.tree__title { font-weight: 700; font-size: 1rem; }
.tree__collapse { width: 32px; padding: 0; font-size: 1rem; line-height: 1; }

@media (min-width: 721px) {
  .noteapp__tree.is-collapsed { width: 44px; flex: 0 0 44px; padding: 16px 6px; }
  /* Everything goes except the header, which keeps the toggle on screen — it is the only way back
     out of the collapsed state. */
  .noteapp__tree.is-collapsed > *:not(.tree__head) { display: none; }
  .noteapp__tree.is-collapsed .tree__title { display: none; }
  .noteapp__tree.is-collapsed .tree__head { justify-content: center; }
}
.tree__footer {
  display: flex;
  gap: 4px;
  flex-wrap: wrap;
  justify-content: center;
  margin-top: auto;
  padding-top: 8px;
  border-top: 1px solid var(--border);
}
.tree__actions { display: none; }
.tree__search { font-size: .88rem; width: 100%; }
.tree__search::placeholder { text-align: center; }
.tree__tags { max-height: 70px; overflow-y: auto; }
.tree__filters { display: flex; gap: 6px; }
.tree__filters .select { flex: 1 1 0; min-width: 0; font-size: .8rem; padding: 6px 8px; }
.tree__filters[hidden] { display: none; }
.tree { flex: 1 1 auto; overflow-y: auto; margin: 0 -6px; padding: 2px 6px; }
.tree__group { margin-bottom: 1px; }
.tree__nb { display: flex; align-items: center; gap: 7px; padding: 7px 6px; border-radius: 8px; cursor: pointer; }
.tree__nb:hover { background: var(--surface-2); }
.tree__chev { font-size: .68rem; color: var(--muted); width: 12px; text-align: center; transition: transform .12s; flex: none; }
.tree__chev.is-open { transform: rotate(90deg); }
.tree__dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.tree__nbname { flex: 1; font-weight: 600; font-size: .9rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tree__count { font-size: .72rem; color: var(--muted); font-variant-numeric: tabular-nums; }
.tree__nbactions { display: none; gap: 1px; }
.tree__nb:hover .tree__nbactions { display: flex; }
.tree__nb:hover .tree__count { display: none; }
.tree__mini { border: none; background: none; cursor: pointer; color: var(--muted); font-size: .8rem; padding: 2px 4px; border-radius: 5px; line-height: 1; }
.tree__mini:hover { background: var(--border); color: var(--text); }
.tree__notes { margin-left: 15px; border-left: 1px solid var(--border); padding-left: 5px; }
.tree__note { padding: 6px 8px; border-radius: 8px; cursor: pointer; }
.tree__note:hover { background: var(--surface-2); }
.tree__note.is-active { background: var(--accent-soft); }
.tree__notetitle { font-size: .88rem; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tree__note.is-active .tree__notetitle { color: var(--accent-ink); }
.tree__notemeta { display: flex; flex-wrap: nowrap; gap: 2px 8px; font-size: .74rem; margin-top: 2px; color: var(--muted); overflow: hidden; }
.tree__notemeta span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tree__tag { font-weight: 600; }
.tree__empty, .tree__searchmeta { font-size: .8rem; padding: 6px 8px; }

@media (max-width: 720px) {
  .noteapp { flex-direction: column; min-height: 0; }
  .noteapp__tree { width: auto; flex: none; position: static; height: auto; max-height: none; border-right: none; }
  .noteapp__main { padding: 16px 16px 90px; }
  .noteapp.has-note .noteapp__tree { display: none; }
  .noteapp:not(.has-note) .noteapp__main { display: none; }
  .noteapp__back { display: inline-flex; margin-bottom: 10px; }
  .tree__collapse { display: none; }   /* the panel already gets out of the way here */
}

/* Formatting toolbar + Write/Preview toggle */
.md-toolbar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; flex-wrap: wrap; margin-top: 14px;
  padding: 6px; border: 1px solid var(--border); border-radius: 10px;
  background: var(--surface-2);
}
.md-toolbar__hint { font-size: .82rem; font-weight: 600; padding-left: 6px; }
/* Prose editor toolbar: pack left so the Write/Preview toggle keeps its spot. */
.md-toolbar--editor { justify-content: flex-start; }

/* Formatting & shortcuts cheatsheet (the editor "?" button). */
.kbd-grid { display: grid; gap: 18px; }
.kbd-sec__t { font-size: .74rem; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); margin: 0 0 6px; }
.kbd-row { display: grid; grid-template-columns: minmax(140px, max-content) 1fr; gap: 14px; align-items: baseline; padding: 4px 0; }
.kbd-row__d { color: var(--text); font-size: .9rem; }
.kbd-keys { display: inline-flex; gap: 4px; flex-wrap: wrap; }
.kbd-grid kbd {
  display: inline-block; padding: 2px 7px; border: 1px solid var(--border); border-bottom-width: 2px;
  border-radius: 6px; background: var(--surface-2); color: var(--text);
  font: 600 .78rem ui-monospace, SFMono-Regular, Menlo, monospace;
}
.kbd-grid code { background: var(--surface-2); padding: 2px 6px; border-radius: 5px; font-size: .82rem; }
@media (max-width: 520px) { .kbd-row { grid-template-columns: 1fr; gap: 2px; } }
.md-tools { display: flex; align-items: center; gap: 3px; flex-wrap: wrap; }
.md-tool {
  min-width: 30px; height: 30px; padding: 0 8px;
  border: 1px solid transparent; border-radius: 7px;
  background: transparent; color: var(--text); cursor: pointer;
  font-size: .85rem; font-weight: 600;
}
.md-tool:hover { background: var(--surface); border-color: var(--border); }
.md-tools__sep { width: 1px; height: 20px; background: var(--border); margin: 0 4px; }

.seg { display: inline-flex; background: var(--surface); border: 1px solid var(--border); border-radius: 8px; padding: 2px; }
.seg__btn {
  padding: 5px 12px; border: none; border-radius: 6px; cursor: pointer;
  background: transparent; color: var(--muted); font-size: .85rem; font-weight: 600;
}
.seg__btn.is-active { background: var(--accent-strong); color: var(--on-accent); }

/* Rendered Markdown ("prose") */
.prose { min-height: 340px; font-size: .96rem; line-height: 1.6; word-wrap: break-word; }
.prose > :first-child { margin-top: 0; }
.prose h1, .prose h2, .prose h3, .prose h4 { margin: 1.1em 0 .4em; line-height: 1.25; }
.prose h1 { font-size: 1.5rem; }
.prose h2 { font-size: 1.25rem; }
.prose h3 { font-size: 1.08rem; }
.prose p { margin: 0 0 .8em; }
.prose ul, .prose ol { margin: 0 0 .8em; padding-left: 1.4em; }
.prose li { margin: .2em 0; }
.prose blockquote {
  margin: 0 0 .8em; padding: 4px 14px;
  border-left: 3px solid var(--accent); color: var(--muted);
  background: var(--surface-2); border-radius: 0 8px 8px 0;
}
.prose a { color: var(--accent-ink); text-decoration: underline; text-underline-offset: 2px; }
.prose code {
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: .88em; background: var(--surface-2);
  padding: 1px 5px; border-radius: 5px;
}
.prose pre {
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: 10px; padding: 12px 14px; overflow-x: auto; margin: 0 0 .8em;
}
.prose pre code { background: none; padding: 0; font-size: .85rem; }
.prose hr { border: none; border-top: 1px solid var(--border); margin: 1.2em 0; }
.prose img { max-width: 100%; border-radius: 8px; }

/* Tables (scroll horizontally on their own so the page never does) */
.prose .table-wrap { overflow-x: auto; margin: 0 0 .9em; }
.prose table { border-collapse: collapse; width: 100%; font-size: .92rem; }
.prose th, .prose td { border: 1px solid var(--border); padding: 7px 11px; text-align: left; overflow-wrap: anywhere; }
.testmode td, .testmode th { overflow-wrap: anywhere; }
.prose thead th { background: var(--surface-2); font-weight: 700; }
.prose tbody tr:nth-child(even) td { background: color-mix(in srgb, var(--surface-2) 55%, transparent); }
.prose .ta-center { text-align: center; }
.prose .ta-right { text-align: right; }
.prose .ta-left { text-align: left; }

/* Test mode: fill-in-the-blank quiz built from a note's table. */
.testmode__hint { font-size: .88rem; margin: 0 0 12px; }
.testmode__controls { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin-bottom: 14px; }
.testmode__cols { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
/* Swap + its caption, for two-column sheets. Same shape as .testmode__cols so the controls row
   lines up whichever variant a sheet gets. */
.testmode__dir { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.testmode__col {
  font: inherit; font-size: .82rem; font-weight: 600; cursor: pointer;
  padding: 4px 10px; border-radius: 999px;
  border: 1px solid var(--border); background: var(--surface); color: var(--muted);
}
.testmode__col.is-hidden { background: var(--accent-strong); border-color: var(--accent-strong); color: var(--on-accent); }
.testmode__table { border-collapse: collapse; width: 100%; font-size: .92rem; }
.testmode__table th, .testmode__table td { border: 1px solid var(--border); padding: 7px 11px; text-align: left; vertical-align: top; }
.testmode__table thead th { background: var(--surface-2); font-weight: 700; }
.testmode__table thead th.is-blank { color: var(--accent-ink); }
.testmode__input { width: 100%; min-width: 90px; padding: 5px 8px; }
.testmode__img { display: block; max-width: 160px; max-height: 120px; margin-top: 6px; border-radius: 6px; }
.testmode__cell.is-correct { background: color-mix(in srgb, var(--ok) 16%, transparent); }
.testmode__cell.is-close   { background: color-mix(in srgb, var(--warn) 16%, transparent); }
.testmode__cell.is-wrong   { background: color-mix(in srgb, var(--danger) 14%, transparent); }
.testmode__cell.is-correct .testmode__input { border-color: var(--ok); }
.testmode__cell.is-close   .testmode__input { border-color: var(--warn); }
.testmode__cell.is-wrong   .testmode__input { border-color: var(--danger); }
.testmode__answer { display: block; margin-top: 4px; font-size: .85rem; font-weight: 600; color: var(--ok); }
.testmode__cell.is-close .testmode__answer { color: var(--warn); }
.testmode__foot { display: flex; align-items: center; gap: 14px; margin-top: 14px; }
.testmode__score { font-weight: 700; }
.testmode__score.is-perfect { color: var(--ok); }
.testmode__score.is-ok { color: var(--warn); }
.testmode__score.is-low { color: var(--danger); }

/* Alignment blocks ( ::: center … ::: ) */
.prose .align-center { text-align: center; }
.prose .align-right { text-align: right; }
.prose .align-left { text-align: left; }

/* Inline #tags */
.prose a.tag {
  color: var(--accent-ink); background: var(--accent-soft);
  border-radius: 5px; padding: 0 5px; font-weight: 600; font-size: .9em; text-decoration: none;
}
.prose a.tag:hover { filter: brightness(.97); }

/* Highlight + font colours. These class names are the ONLY ones markdown.js will emit from a
   [text]{.class} span, so notes can't inject arbitrary styling. */
:root {
  --hl-yellow: #fde68a; --hl-green: #bbf7d0; --hl-blue: #bfdbfe; --hl-pink: #fbcfe8;
  --fg-red: #e5484d; --fg-orange: #e5731b; --fg-green: #22a06b; --fg-blue: #3b82f6; --fg-purple: #8b5cf6;
}
.prose mark, .hl-yellow, .hl-green, .hl-blue, .hl-pink { color: #1e293b; border-radius: 3px; padding: 0 2px; }
.prose mark, .hl-yellow { background: var(--hl-yellow); }
.hl-green { background: var(--hl-green); }
.hl-blue  { background: var(--hl-blue); }
.hl-pink  { background: var(--hl-pink); }
.fg-red { color: var(--fg-red); } .fg-orange { color: var(--fg-orange); }
.fg-green { color: var(--fg-green); } .fg-blue { color: var(--fg-blue); } .fg-purple { color: var(--fg-purple); }

/* Block-swap live editor: one bordered editor pane (like the old textarea) with rendered blocks
   inside it; the block under the caret opens to raw Markdown in place. The frame stays put
   whether you're reading or editing — only the block you're in swaps to source — so it never
   flips between "loose text" and "a box". */
.live-editor {
  width: 100%; box-sizing: border-box;
  border: 1px solid var(--border); border-radius: 10px;
  background: var(--surface); color: var(--text);
  padding: 8px 10px; min-height: 340px; cursor: text;
  font-size: .95rem; line-height: 1.55;
  display: flex; flex-direction: column; gap: 1px;
}
.live-editor:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
/* The bottom "keep writing" affordance: a faint clickable line, and the blank pane below it grows
   to fill the pane so clicking anywhere down there works. */
.live-blk--trailing { min-height: 1.6em; flex: 1 0 auto; }
.live-blk--trailing .live-blk__ph { opacity: 0; transition: opacity .12s ease; }
.live-blk--trailing:hover .live-blk__ph { opacity: 1; }

/* Inline @ / [[ mention menu (see mention.js). */
.mention-menu {
  position: fixed; z-index: 60; max-height: 264px; overflow-y: auto;
  background: var(--surface); border: 1px solid var(--border); border-radius: 10px;
  box-shadow: var(--shadow); padding: 4px;
}
.mention-item {
  display: flex; align-items: center; gap: 8px; padding: 6px 8px;
  border-radius: 7px; cursor: pointer; font-size: .92rem;
}
.mention-item.is-sel, .mention-item:hover { background: var(--surface-2); }
.mention-item__ico { width: 18px; text-align: center; color: var(--muted); }
.mention-item__label { flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mention-item__sub { color: var(--muted); font-size: .78rem; white-space: nowrap; }
.live-blk { border-radius: 6px; padding: 2px 6px; cursor: text; transition: background .12s ease; }
.live-blk:hover { background: var(--surface-2); }
.live-blk > :first-child { margin-top: 0; }
.live-blk > :last-child { margin-bottom: 0; }
.live-blk--empty { min-height: 1.6em; }
.live-blk__ph { color: var(--muted); }
.live-blk__edit {
  display: block; width: 100%; box-sizing: border-box; margin: 0;
  border: none; outline: none; resize: none; overflow: hidden;
  background: transparent; padding: 2px 6px;
  font: inherit; line-height: inherit; color: var(--text);
}
.live-blk img { display: block; max-width: 100%; height: auto; border-radius: 6px; }

/* Toolbar dropdown menus (highlight/colour/align) + swatches */
.md-tool-wrap { position: relative; display: inline-flex; }
.md-menu {
  position: absolute; top: 100%; left: 0; margin-top: 5px; z-index: 30;
  background: var(--surface); border: 1px solid var(--border); border-radius: 9px;
  box-shadow: var(--shadow); padding: 5px; display: flex; gap: 4px;
}
.md-menu[hidden] { display: none; }
.md-menu__item {
  display: inline-flex; align-items: center; gap: 6px; padding: 5px 8px;
  border: 1px solid transparent; border-radius: 6px; background: transparent;
  cursor: pointer; font-size: .82rem; color: var(--text); white-space: nowrap;
}
.md-menu__item:hover { background: var(--surface-2); border-color: var(--border); }
.md-swatch { width: 18px; height: 18px; border-radius: 5px; border: 1px solid rgba(0,0,0,.18); display: inline-block; }

/* Searchable tag filter (scales past a wall of chips) */
.tagpick { display: flex; flex-direction: column; gap: 6px; }
.tagpick__chips { display: flex; flex-wrap: wrap; gap: 6px; }
.tagpick__chips:empty { display: none; }
.tagpick__field { position: relative; }
.tagpick__search { font-size: .88rem; }
.tagpick__menu {
  position: absolute; left: 0; right: 0; top: calc(100% + 4px); z-index: 30;
  max-height: 240px; overflow-y: auto; padding: 4px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-sm); box-shadow: var(--shadow);
}
.tagpick__menu[hidden] { display: none; }
.tagpick__opt {
  display: flex; align-items: center; gap: 8px; width: 100%; text-align: left;
  padding: 7px 9px; border: none; background: transparent; border-radius: 7px;
  font-size: .88rem; color: var(--text); cursor: pointer;
}
.tagpick__opt:hover { background: var(--accent-soft); color: var(--accent-ink); }
.tagpick__dot { width: 9px; height: 9px; border-radius: 50%; flex: none; }
.tagpick__empty { padding: 8px 9px; font-size: .85rem; }
/* Insert-table size picker (Word/Docs-style grid) */
.tablepick__grid { display: grid; grid-template-columns: repeat(8, 26px); gap: 4px; margin: 10px 0 2px; }
.tablepick__cell {
  width: 26px; height: 26px; border: 1px solid var(--border); border-radius: 4px;
  background: var(--surface-2); cursor: pointer; transition: background .08s, border-color .08s;
}
.tablepick__cell.is-on { background: var(--accent-soft); border-color: var(--accent); }
.tablepick__cap { font-weight: 700; text-align: center; color: var(--accent-ink); margin: 4px 0 2px; }

/* Visual table editor — a real bordered grid of cell inputs (Word-style) */
.tableedit__scroll { overflow-x: auto; margin: 8px 0 2px; }
/* Reorder controls (drag grip + move buttons) for sheet rows/columns. */
.grip-cell { width: 44px; padding: 2px; text-align: center; vertical-align: middle; }
/* Reorder controls and the delete sit SIDE BY SIDE. Stacking the delete under ↑ ⠿ ↓ made the
   column taller than the text cell, which then set the row height — every row in the sheet grew
   to make room for a button. Beside them, content decides the height again. Separating them also
   puts a gap between "move down" and "delete", which are not neighbours you want to mis-tap. */
.grip-cell__inner { display: flex; align-items: center; justify-content: center; gap: 1px; }
/* The prose-note table editor has a delete and nothing else in this column — no move buttons to
   make room for, so it does not need the sheet grid's width. */
.grip-cell--slim { width: 26px; }
.grip-stack { display: inline-flex; flex-direction: column; align-items: center; gap: 0; }
.grip-stack--col { flex-direction: row; align-items: center; }
.grip { display: inline-block; cursor: grab; color: var(--muted); user-select: none; line-height: 1; font-size: .8rem; padding: 1px; }
.grip:hover { color: var(--text); }
.grip:active { cursor: grabbing; }
.grip--col { padding: 0 2px; vertical-align: middle; }
.grip-btn { border: none; background: transparent; color: var(--muted); cursor: pointer; padding: 0 2px; line-height: 1; font-size: .72rem; }
.grip-btn:hover:not(:disabled) { color: var(--text); }
.grip-btn:disabled { opacity: .3; cursor: default; }
/* Delete this row / column. Quiet until hovered, like its neighbours, then red — it sits a
   thumb's width from the reorder buttons and should not read as one of them. */
.grip-btn--kill:hover:not(:disabled) { color: var(--danger); }
table.tableedit { border-collapse: collapse; }
table.tableedit th, table.tableedit td { border: 1px solid var(--border); padding: 0; }
.tableedit__cell {
  width: 100%; min-width: 96px; box-sizing: border-box; border: none; background: transparent;
  padding: 8px 10px; font: inherit; color: var(--text);
}
textarea.tableedit__cell {
  display: block; resize: none; overflow: hidden; line-height: 1.45;
  white-space: pre-wrap; overflow-wrap: anywhere;
}
.tableedit__cell:focus { outline: 2px solid var(--accent); outline-offset: -2px; }
.tableedit__cell.is-head { font-weight: 700; background: var(--surface-2); }
/* Header = editable title + sort caret. The input keeps the flexible space so long column names
   still get the full width. */
.sheet-head { display: flex; align-items: stretch; background: var(--surface-2); }
.sheet-head .tableedit__cell.is-head { flex: 1 1 auto; min-width: 0; }
.sheet-sort {
  flex: none; width: 22px; border: 0; background: transparent; cursor: pointer;
  color: var(--muted); font-size: .7rem; line-height: 1; padding: 0 2px;
}
/* Inactive carets stay faint so a wide sheet doesn't read as a row of arrows; they come up on
   hover, and the active one is full strength. */
.sheet-sort { opacity: .35; }
.sheet-head:hover .sheet-sort { opacity: .7; }
.sheet-sort:hover { opacity: 1; color: var(--text); }
.sheet-sort.is-active { opacity: 1; color: var(--accent-ink); }
/* A sheet cell: a text field with a strip of image thumbnails beneath it (a cell can hold text
   and one or more pasted images together). Each thumbnail has a hover-to-remove button. */
.sheetcell { display: flex; flex-direction: column; min-width: 96px; }
.sheetcell-imgs { display: flex; flex-wrap: wrap; gap: 6px; padding: 0 6px 6px; }
.sheetcell-img { position: relative; display: flex; }
.sheetcell-img img { max-width: 140px; max-height: 100px; border-radius: 6px; display: block; }
.sheetcell-img__x {
  position: absolute; top: 2px; right: 2px; width: 20px; height: 20px; padding: 0;
  border: none; border-radius: 50%; cursor: pointer; line-height: 20px; font-size: .7rem;
  background: rgba(0,0,0,.55); color: #fff; opacity: 0; transition: opacity .15s ease;
}
.sheetcell-img:hover .sheetcell-img__x, .sheetcell-img__x:focus { opacity: 1; }
.tree__kind {
  display: inline-block; margin-right: 6px; padding: 1px 6px; border-radius: 4px;
  background: var(--accent-soft); color: var(--accent-ink); font-size: .68rem; font-weight: 700;
  letter-spacing: .03em; text-transform: uppercase; vertical-align: middle;
}

/* Slide deck: PowerPoint "handout" layout — slide picture beside a notes field. */
.deck { display: flex; flex-direction: column; gap: 20px; }
.deck-slide {
  display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
  grid-template-areas: "num num" "stage side"; gap: 10px 16px; align-items: start;
}
.deck-slide__num { grid-area: num; font-size: .8rem; font-weight: 600; }
.deck-slide__stage {
  grid-area: stage; position: relative; line-height: 0; background: #fff;
  border: 1px solid var(--border); border-radius: 8px; overflow: hidden;
}
.deck-slide__img { display: block; width: 100%; height: auto; }
/* Slide number on the left, add/delete on the right. */
.deck-slide__num { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.deck-slide__tools { display: inline-flex; gap: 4px; }
.deck-slide__tools .icon-btn { width: 26px; height: 26px; font-size: .8rem; }
.deck-slide__ink { position: absolute; top: 0; left: 0; pointer-events: none; }
.deck-slide__annotate {
  position: absolute; top: 6px; right: 6px; z-index: 3; height: 30px; padding: 0 12px;
  border: 1px solid var(--border); border-radius: 8px; cursor: pointer; font-size: .82rem; font-weight: 600;
  background: color-mix(in srgb, var(--surface) 88%, transparent); color: var(--text); backdrop-filter: blur(2px);
}
.deck-slide__annotate:hover { background: var(--surface); border-color: var(--accent); }

/* Full-screen slide annotator. */
.slide-annotator { position: fixed; inset: 0; z-index: 1000; display: flex; flex-direction: column; background: var(--surface-2); }
.slide-annotator__bar { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; padding: 8px 10px; background: var(--surface); border-bottom: 1px solid var(--border); }
.slide-annotator__nav { display: inline-flex; align-items: center; gap: 8px; margin-left: auto; }
.slide-annotator__view { position: relative; flex: 1; overflow: hidden; touch-action: none; }
.slide-annotator__world { position: absolute; top: 0; left: 0; transform-origin: 0 0; will-change: transform; }
.slide-annotator__img { display: block; width: 100%; height: 100%; }
.slide-annotator__ink { position: absolute; top: 0; left: 0; touch-action: none; }
body.is-annotating { overflow: hidden; }

/* Ink toolbar: brush colour + size sit inline with the pen/eraser tools. */
.deck-ink__color { width: 34px; height: 30px; padding: 0; border: 1px solid var(--border); border-radius: 6px; background: none; cursor: pointer; }
.deck-ink__size { width: 96px; }
.deck-slide__side { grid-area: side; align-self: stretch; }
.deck-slide__notes { width: 100%; min-height: 100%; height: 100%; resize: vertical; min-height: 120px; }
/* On narrow screens (tablet portrait / phone) stack notes under the slide. */
@media (max-width: 720px) {
  .deck-slide { grid-template-columns: 1fr; grid-template-areas: "num" "stage" "side"; }
  .deck-slide__notes { min-height: 90px; }
}

/* Slim progress bar (slide-deck import). */
.progress { height: 8px; border-radius: 999px; background: var(--surface-2); overflow: hidden; }
.progress__fill { height: 100%; width: 0; background: var(--accent); transition: width .2s ease; }

/* Rendered tables in Preview are clickable to edit */
/* Hover "Edit" button pinned to a rendered table's top-right corner (Preview) */
.prose .table-holder { position: relative; }
.prose .table-holder:hover .table-wrap table { outline: 2px solid var(--accent-soft); outline-offset: 2px; }
.table-edit-btn {
  position: absolute; top: 6px; right: 6px; z-index: 2;
  display: none; align-items: center; gap: 4px;
  padding: 3px 9px; font-size: .76rem; font-weight: 600; line-height: 1.4;
  background: var(--accent-strong); color: var(--on-accent);
  border: none; border-radius: 7px; cursor: pointer; box-shadow: var(--shadow-sm);
}
.table-edit-btn__ico { font-size: .95em; }
.prose .table-holder:hover .table-edit-btn,
.table-edit-btn:focus-visible { display: inline-flex; }
@media (hover: none) { .table-edit-btn { display: inline-flex; opacity: .9; } }

/* Hover size controls on a rendered image (Preview), same idea as the table Edit button above. */
.prose .img-holder { position: relative; display: inline-block; max-width: 100%; line-height: 0; }
.prose .img-holder:hover img { outline: 2px solid var(--accent-soft); outline-offset: 2px; }
.img-tools {
  position: absolute; top: 6px; right: 6px; z-index: 2;
  display: none; gap: 2px; padding: 2px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 8px; box-shadow: var(--shadow-sm); line-height: 1;
}
.prose .img-holder:hover .img-tools,
.img-tools:focus-within { display: inline-flex; }
/* Touch has no hover, and this is the one control that makes a picture usable on a phone. */
@media (hover: none) { .img-tools { display: inline-flex; opacity: .9; } }
.img-tools button {
  border: none; background: transparent; color: var(--muted); cursor: pointer;
  font: 600 .8rem inherit; padding: 3px 7px; border-radius: 6px; line-height: 1;
}
.img-tools button:hover { background: var(--surface-2); color: var(--text); }

/* "New here?" card on Today — only drawn while the account is still empty. */
.welcome { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.welcome__main { flex: 1 1 260px; min-width: 0; }
.welcome__main h2 { margin: 0 0 .25em; }
.welcome__main p { margin: 0; font-size: .9rem; max-width: 62ch; }

/* The quiet, permanent link at the foot of Today. */
.today__help { margin-top: 22px; padding-top: 14px; border-top: 1px solid var(--border); font-size: .85rem; }
.today__help a { color: var(--accent-ink); font-weight: 600; }

/* "What's new" modal: one block per release since you last looked. */
.whatsnew { display: flex; flex-direction: column; gap: 16px; max-height: 55vh; overflow-y: auto; }
.whatsnew__rel + .whatsnew__rel { border-top: 1px solid var(--border); padding-top: 14px; }
.whatsnew__ver { display: flex; align-items: baseline; gap: 10px; margin-bottom: 6px; }
.whatsnew__ver strong { font-size: 1rem; color: var(--accent-ink); }
.whatsnew__ver .muted { font-size: .82rem; }
.whatsnew__list { margin: 0; padding-left: 1.15rem; display: flex; flex-direction: column; gap: 6px; }
.whatsnew__list li { font-size: .92rem; line-height: 1.5; }

/* Colour picker (swatches + native "any colour") */
.colorpick { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.color-swatch { width: 26px; height: 26px; border-radius: 50%; cursor: pointer; border: 3px solid transparent; padding: 0; }
.color-swatch.is-chosen { border-color: var(--text); }
.color-custom { width: 36px; height: 30px; padding: 2px; border: 1px solid var(--border); border-radius: 8px; background: var(--surface); cursor: pointer; }
.color-custom::-webkit-color-swatch-wrapper { padding: 0; }
.color-custom::-webkit-color-swatch { border: none; border-radius: 5px; }

/* Wikilinks: a note link, plus special colors for class / event links. "is-missing" = the target
   doesn't exist yet (Obsidian greys these out). */
.wikilink {
  cursor: pointer; text-decoration: none;
  border-radius: 5px; padding: 1px 5px;
  font-weight: 600; background: var(--accent-soft); color: var(--accent-ink);
}
.wikilink:hover { filter: brightness(.97); text-decoration: underline; }
.wikilink:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.wikilink.is-missing { background: transparent; color: var(--muted); border: 1px dashed var(--border); }
.wikilink--course::before   { content: "◈ "; opacity: .8; }
.wikilink--deadline::before { content: "⚑ "; opacity: .8; }
.wikilink--task::before     { content: "☑ "; opacity: .8; }
.wikilink--term::before     { content: "◆ "; opacity: .8; }
.wikilink--course, .wikilink--deadline, .wikilink--task, .wikilink--term {
  background: var(--surface-2); color: var(--text);
}

/* Deep-link highlight: a brief ring when you jump to a specific task or event from a [[task:…]] /
   [[deadline:…]] link. outline (not box-shadow) so a parent's overflow can't clip it. */
@keyframes flash-ring { 0% { outline-color: var(--accent); } 100% { outline-color: transparent; } }
.is-flash { outline: 3px solid transparent; outline-offset: 2px; animation: flash-ring 1.6s ease-out; }

/* Backlinks panel */
.backlinks { margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--border); }
.backlinks__title { font-size: .82rem; font-weight: 700; color: var(--muted); margin-bottom: 8px; }
.backlinks__list { display: flex; flex-wrap: wrap; gap: 6px; }
.backlinks__item {
  border: 1px solid var(--border); background: var(--surface);
  border-radius: 999px; padding: 4px 12px; cursor: pointer;
  font-size: .84rem; font-weight: 600; color: var(--text);
}
.backlinks__item:hover { border-color: var(--accent); color: var(--accent-ink); }

/* The link-picker list items shouldn't be centered like normal block buttons */
.picker__item { justify-content: flex-start; text-align: left; }

/* Study planner progress bar */
.progress { height: 8px; background: var(--surface-2); border-radius: 999px; overflow: hidden; }
.progress > span { display: block; height: 100%; background: var(--accent); border-radius: 999px; }

/* Sync status pill (bottom-right; created by js/sync.js) */
.sync-pill {
  position: fixed; bottom: 16px; right: 16px; z-index: 45;
  display: flex; align-items: center; gap: 7px;
  font-family: inherit; font-size: .74rem; font-weight: 600; color: var(--muted);
  background: var(--surface); border: 1px solid var(--border);
  padding: 6px 11px; border-radius: 999px; box-shadow: var(--shadow-sm);
  cursor: pointer; transition: border-color .15s, color .15s;
}
.sync-pill:hover { border-color: var(--muted); color: var(--text); }
.sync-pill__dot { width: 8px; height: 8px; border-radius: 50%; background: var(--muted); transition: background .2s; }
.sync-pill.is-ok .sync-pill__dot { background: var(--ok); }
.sync-pill.is-off .sync-pill__dot { background: var(--danger); }
.sync-pill.is-paused .sync-pill__dot { background: var(--warn); }
@media (max-width: 720px) { .sync-pill { bottom: 78px; } }  /* clear the mobile tab bar */

/* "Update ready" pill (js/appupdate.js). Sits above the sync pill in the same corner, and borrows
   its shape so a new build announces itself in the app's own voice rather than as a browser
   prompt. Accent-coloured because, unlike the sync pill, it is asking for a click. */
.update-pill {
  position: fixed; bottom: 56px; right: 16px; z-index: 46;
  display: flex; align-items: center; gap: 7px;
  font-family: inherit; font-size: .74rem; font-weight: 600;
  color: var(--accent-ink); background: var(--surface);
  border: 1px solid var(--accent); border-radius: 999px;
  padding: 6px 11px; box-shadow: var(--shadow-sm);
  cursor: pointer; transition: background .15s;
}
.update-pill:hover { background: var(--accent-soft); }
.update-pill__dot { width: 8px; height: 8px; border-radius: 50%; background: var(--accent); }
/* Clears the mobile tab bar, and stays clear of the sync pill that moved up with it. */
@media (max-width: 720px) { .update-pill { bottom: 118px; } }

/* Sub-tasks: indented under their parent, with the same hairline the notebook tree uses to show
   containment. Kept subtle — these are steps in one job, not a second list. */
.subtasks {
  margin-left: 26px;
  padding-left: 10px;
  border-left: 1px solid var(--border);
  display: flex; flex-direction: column; gap: 6px;
}
.subtasks .item { padding-top: 8px; padding-bottom: 8px; }
.subtasks .item__title { font-size: .93rem; }

/* ---- Focus timer (Pomodoro / Flowmodoro) ----------------------------- */
.focus { display: flex; flex-direction: column; align-items: center; gap: 22px; padding: 30px 18px; }
.focus + .card { margin-top: 12px; }
.focus-ring { position: relative; width: 240px; height: 240px; }
.focus-ring svg { width: 100%; height: 100%; transform: rotate(-90deg); }
.focus-ring__bg { fill: none; stroke: var(--surface-2); stroke-width: 8; }
.focus-ring__fg { fill: none; stroke: var(--accent); stroke-width: 8; stroke-linecap: round; transition: stroke-dashoffset .5s linear, stroke .3s; }
.focus-ring[data-phase="break"] .focus-ring__fg,
.focus-ring[data-phase="longbreak"] .focus-ring__fg { stroke: var(--ok); }
.focus-ring__center { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; }
.focus__time { font-size: 3.1rem; font-weight: 700; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.focus__phase { font-size: .9rem; font-weight: 600; }
.focus__controls { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; }
.focus__start { min-width: 130px; }
.focus__settings { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 14px 18px; align-items: end; margin-top: 4px; }
.focus__set span { display: block; font-size: .85rem; color: var(--muted); margin-bottom: 5px; }
.focus__num { display: flex; align-items: center; gap: 8px; }
.focus__num .input { max-width: 90px; }

/* Floating pill — visible whenever a session is running. */
.focus-pill {
  position: fixed; bottom: 16px; left: 16px; z-index: 45;
  display: flex; align-items: center; gap: 8px;
  background: var(--surface); border: 1px solid var(--border);
  padding: 5px 6px 5px 12px; border-radius: 999px; box-shadow: var(--shadow-sm);
}
.focus-pill__open { border: none; background: none; cursor: pointer; font: inherit; font-weight: 700; color: var(--accent-ink); padding: 0; }
.focus-pill[data-phase="break"] .focus-pill__open,
.focus-pill[data-phase="longbreak"] .focus-pill__open { color: var(--ok); }
.focus-pill__time { font-weight: 700; font-variant-numeric: tabular-nums; min-width: 46px; }
.focus-pill__btn { border: 1px solid var(--border); background: var(--surface-2); color: var(--text); border-radius: 999px; padding: 3px 12px; font: inherit; font-size: .78rem; font-weight: 600; cursor: pointer; }
.focus-pill__btn:hover { border-color: var(--accent); }
@media (max-width: 720px) { .focus-pill { bottom: 78px; } }  /* clear the mobile tab bar */

/* Login / register gate */
body.is-auth .appbar { display: none; }
body.is-auth .main { max-width: none; padding: 0; }
.auth { min-height: 100vh; display: grid; place-items: center; padding: 24px; }
.auth__card {
  width: min(400px, 100%);
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow); padding: 30px 28px;
}
.auth__brand { display: flex; align-items: center; gap: 10px; margin-bottom: 20px; }
.auth__title { font-size: 1.4rem; margin: 0 0 4px; }
.auth__sub { margin: 0 0 20px; font-size: .92rem; }
.auth__err {
  background: color-mix(in srgb, var(--danger) 12%, var(--surface));
  color: var(--danger); border: 1px solid color-mix(in srgb, var(--danger) 30%, transparent);
  border-radius: 9px; padding: 9px 12px; font-size: .86rem; font-weight: 500;
}
.auth__err[hidden] { display: none; }
.auth__or {
  display: flex; align-items: center; gap: 12px;
  color: var(--muted); font-size: .8rem; margin: 18px 0;
}
.auth__or::before, .auth__or::after { content: ""; flex: 1; height: 1px; background: var(--border); }
.auth__copyright { margin-top: 14px; }
.auth__g {
  display: grid; place-items: center; width: 18px; height: 18px; border-radius: 50%;
  background: #fff; color: #4285f4; font-weight: 800; font-size: .8rem;
  border: 1px solid var(--border);
}
.auth__switch { margin-top: 18px; text-align: center; font-size: .88rem; }
.auth__switch a { color: var(--accent-ink); font-weight: 600; }
/* A one-time success note above the form (e.g. after a password reset). */
.auth__banner {
  background: color-mix(in srgb, var(--accent) 12%, var(--surface));
  color: var(--accent-ink); border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  border-radius: 9px; padding: 9px 12px; font-size: .86rem; font-weight: 500; margin-bottom: 14px;
}
/* The "Forgot password?" link, right-aligned under the login form. */
.auth__forgot { margin-top: 10px; text-align: right; font-size: .85rem; }
.auth__forgot a { color: var(--accent-ink); font-weight: 600; }

/* Signed-in user chip in the header's utility area */
.user-chip { display: flex; align-items: center; gap: 8px; }
.user-chip__email { max-width: 180px; font-size: .8rem; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (max-width: 1200px) { .user-chip__email { display: none; } }
@media (max-width: 720px) { .user-chip { display: none; } }

/* Utility helpers */
.stack { display: flex; flex-direction: column; gap: 16px; }
.stack--roomy { gap: 16px; }
.muted { color: var(--muted); }
.right { margin-left: auto; }
.mt { margin-top: 16px; margin-bottom: 16px; }
.hidden { display: none !important; }
.badge-danger { color: var(--danger); }
.badge-warn { color: var(--warn); }

/* 6. RESPONSIVE (phones) ------------------------------------------------ */
@media (max-width: 720px) {
  /* The header collapses: brand + utilities hide, and the nav detaches into a fixed bottom tab
     bar (icons + labels) — the familiar phone layout. */
  .appbar {
    position: static; height: auto; min-height: 0;
    padding: 0; border-bottom: none; background: transparent;
  }
  .appbar__brand, .appbar__util { display: none; }

  .nav {
    position: fixed; bottom: 0; left: 0; right: 0; z-index: 40;
    background: var(--surface); border: none; border-top: 1px solid var(--border); border-radius: 0;
    padding: 8px; padding-bottom: max(8px, env(safe-area-inset-bottom));
    gap: 2px; justify-content: space-around;
  }
  /* Bar items: the four primary links + the "More" button. */
  .nav > .nav__link, .nav__more {
    flex: 1; display: flex; flex-direction: column; align-items: center; gap: 2px;
    text-align: center; padding: 6px 4px; font-size: .68rem; font-weight: 600;
    border-radius: 8px; color: var(--muted); background: transparent; border: none; cursor: pointer;
  }
  .nav > .nav__link.is-active, .nav__more.is-active { background: var(--accent-soft); color: var(--accent-ink); box-shadow: none; }
  .nav__ico { display: block; font-size: 1.1rem; }

  /* Secondary links become a slide-up sheet sitting directly above the bar. */
  .nav__secondary {
    display: flex; flex-direction: column;
    position: absolute; left: 0; right: 0; bottom: 100%;
    background: var(--surface); border-top: 1px solid var(--border);
    border-radius: 14px 14px 0 0; box-shadow: var(--shadow);
    padding: 4px 10px 10px;
    transform: translateY(110%); visibility: hidden; transition: transform .22s ease, visibility .22s;
  }
  body.is-nav-more .nav__secondary { transform: translateY(0); visibility: visible; }
  .nav__sheet-head { display: block; font-size: .72rem; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); padding: 10px 8px 4px; }
  .nav__secondary .nav__link {
    flex-direction: row; justify-content: flex-start; gap: 12px;
    padding: 12px 10px; font-size: .95rem; border-radius: 9px; color: var(--text);
  }
  .nav__secondary .nav__link.is-active { background: var(--accent-soft); color: var(--accent-ink); }
  .nav__secondary .nav__ico { display: block; font-size: 1.1rem; width: 22px; text-align: center; }

  .nav-sheet-bd { display: none; position: fixed; inset: 0; z-index: 39; background: rgba(0,0,0,.4); }
  body.is-nav-more .nav-sheet-bd { display: block; }

  .main { padding: 20px 16px 90px; }
  .main__copyright { display: block; padding-top: 14px; }
  .notes { grid-template-columns: 1fr; }
  .grid--2, .grid--3 { grid-template-columns: 1fr; }
  .cal-cell { min-height: 58px; }
}

/* ---- Mock exam (full-screen) -------------------------------------------- A multi-sheet paper.
   Full screen rather than a modal: thirty questions in a centred box with its own scrollbar
   fights the reader, and covering the page also means nothing behind it can cue an answer. */
.exam {
  /* Below #modal (z-index 50) on purpose: the exam's own "Leave this paper?" confirmation is a
     modal, and at a higher z-index the overlay would cover it — the dialog would be invisible and
     the app would look frozen. */
  position: fixed; inset: 0; z-index: 40;
  background: var(--bg); overflow-y: auto;
  /* Own scroll container, so the page behind keeps its position. */
  overscroll-behavior: contain;
}
body.is-exam-open { overflow: hidden; }          /* don't scroll two things at once */
.exam__inner { max-width: 720px; margin: 0 auto; padding: 20px 20px 60px; }
.exam__bar { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 6px; }
.exam__title { margin: 0; font-size: 1.15rem; }

/* Sheet picker */
.exam__picks { display: flex; flex-direction: column; gap: 2px; margin: 12px 0; }
.exam__pick {
  display: flex; align-items: center; gap: 10px; padding: 8px 10px;
  border: 1px solid var(--border); border-radius: 8px; background: var(--surface); cursor: pointer;
}
.exam__pick:hover { background: var(--surface-2); }
/* The name takes the slack so counts and chips align down the list. */
.exam__pickname { flex: 1 1 auto; min-width: 0; font-weight: 600; font-size: .9rem;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Questions input, then the direction checkbox on its own line beneath it. */
.exam__opts { display: flex; flex-direction: column; align-items: flex-start; gap: 12px; margin: 14px 0; }
/* Term + class selects, side by side above the list. */
.exam__filters { display: flex; flex-wrap: wrap; gap: 14px; margin: 12px 0 10px; }
.exam__filters .field { min-width: 170px; }
/* Tally on the left, bulk actions right, directly above the sheet list. */
.exam__tallybar {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
  margin: 10px 0 6px; font-size: .85rem;
}
.exam__tallybar .muted { margin-right: auto; }
.exam__nomatch { padding: 12px 10px; margin: 0; }

/* Collapsible term groups in the sheet picker. */
.exam__group { border: 1px solid var(--border); border-radius: 8px; background: var(--surface); }
.exam__group + .exam__group { margin-top: 6px; }
.exam__grouptop { display: flex; align-items: center; gap: 8px; padding: 4px 8px 4px 4px; }
/* The header is the click target for open/close, so it takes the width. */
.exam__grouphead {
  flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: 8px;
  background: none; border: 0; padding: 6px 4px; cursor: pointer;
  color: inherit; font: inherit; text-align: left;
}
.exam__caret { flex: none; width: 12px; color: var(--muted); font-size: .8rem; }
.exam__groupname { font-weight: 700; font-size: .9rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.exam__grouphead .muted { font-size: .78rem; white-space: nowrap; }
.exam__groupall { flex: none; }
/* Indented so a sheet reads as belonging to the term above it. */
.exam__grouprows { display: flex; flex-direction: column; gap: 2px; padding: 0 8px 8px 24px; }
.exam__group .exam__pick { border-color: transparent; background: transparent; }
.exam__group .exam__pick:hover { background: var(--surface-2); border-color: var(--border); }
.exam__mixed { display: flex; align-items: center; gap: 8px; font-size: .88rem; cursor: pointer; }
.exam__actions { display: flex; align-items: center; justify-content: flex-end; gap: 12px; margin-top: 18px; }
.exam__actions .muted { margin-right: auto; font-size: .85rem; }

/* The paper */
.exam__qs, .exam__results { list-style: decimal; padding-left: 26px; margin: 16px 0; display: flex; flex-direction: column; gap: 14px; }
.exam__q, .exam__result { padding-left: 4px; }
.exam__qbody { display: flex; flex-direction: column; gap: 6px; }
.exam__prompt { font-size: .95rem; font-weight: 600; }
.exam__ask { font-size: .78rem; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; }
.exam__answer { max-width: 340px; }

/* Results */
.exam__score { font-size: 1.1rem; font-weight: 700; padding: 10px 0; }
.exam__score.is-perfect { color: var(--ok); }
.exam__score.is-ok { color: var(--text); }
.exam__score.is-low { color: var(--danger); }
.exam__result { border-left: 3px solid var(--border); padding-left: 10px; }
.exam__result.is-correct { border-left-color: var(--ok); }
.exam__result.is-close { border-left-color: var(--warn); }
.exam__result.is-wrong { border-left-color: var(--danger); }
.exam__meta { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 4px 0; font-size: .78rem; }
.exam__answers { display: flex; flex-wrap: wrap; gap: 10px; font-size: .9rem; }
/* Matches the code-block stack at the top of this file — there's no --mono token. */
.exam__given { font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace; }
.exam__correct { color: var(--ok); font-weight: 600; }

@media (max-width: 720px) {
  .exam__inner { padding: 16px 14px 80px; }
  .exam__answer { max-width: 100%; }
}

/* Import preview: where these events will land, and the re-sort affordance. */
.import-split { font-size: .8rem; margin: .3rem 0 .1rem; line-height: 1.5; }
.cal-menu__foot, .cal-menu__note {
  display: flex; align-items: center; gap: 8px;
  border-top: 1px solid var(--border); margin-top: 4px; padding: 8px 6px 2px;
  font-size: .78rem; color: var(--muted);
}
.cal-menu__foot .cal-menu__count { margin-right: auto; }
