/* ===== TOKENS ===== */
:root {
  --accent-h: 217;
  --bg-h: var(--accent-h);
  --accent:        oklch(0.56 0.2  var(--accent-h));
  --accent-mid:    oklch(0.62 0.18 var(--accent-h));
  --accent-soft:   oklch(0.56 0.2  var(--accent-h) / 0.11);
  --accent-text:   oklch(0.56 0.2  var(--accent-h));

  --green:         oklch(0.52 0.16 145);
  --green-soft:    oklch(0.52 0.16 145 / 0.12);
  --amber:         oklch(0.58 0.18 72);
  --amber-soft:    oklch(0.58 0.18 72 / 0.12);
  --red:           oklch(0.52 0.2  22);
  --red-soft:      oklch(0.52 0.2  22 / 0.12);
  --purple:        oklch(0.52 0.17 305);
  --purple-soft:   oklch(0.52 0.17 305 / 0.12);

  --bg:            oklch(0.975 0.008 var(--bg-h));
  --surface:       #ffffff;
  --surface2:      oklch(0.965 0.008 var(--bg-h));
  --border:        oklch(0.91 0.012 var(--bg-h));
  --border2:       oklch(0.945 0.008 var(--bg-h));
  --text1:         oklch(0.14 0.02  var(--bg-h));
  --text2:         oklch(0.52 0.02  var(--bg-h));
  --input-bg:      oklch(0.97 0.007 var(--bg-h));
  --input-focus-bg:#fff;

  --shadow-sm:     0 1px 2px oklch(0.14 0.02 var(--bg-h) / 0.05),
                   0 2px 6px oklch(0.14 0.02 var(--bg-h) / 0.04);
  --shadow-md:     0 2px 8px oklch(0.14 0.02 var(--bg-h) / 0.07),
                   0 6px 20px oklch(0.14 0.02 var(--bg-h) / 0.05);

  --btn-secondary-bg:   oklch(0.95 0.01 var(--bg-h));
  --btn-secondary-color:var(--text1);
  --ai-bg:              oklch(0.95 0.03 var(--accent-h));
  --ai-border:          oklch(0.84 0.07 var(--accent-h));
  --ai-label:           var(--accent);
  --ai-text:            oklch(0.38 0.1 var(--accent-h));
  --goal-tag-bg:        var(--accent-soft);
  --goal-tag-text:      var(--accent-text);
  --connected-bg:       var(--green-soft);
  --connected-color:    var(--green);
  --sync-btn-bg:        var(--green-soft);
  --sync-btn-color:     var(--green);
  --sync-btn-border:    oklch(0.52 0.16 145 / 0.28);
  --disconnect-bg:      var(--red-soft);
  --disconnect-color:   var(--red);
  --disconnect-border:  oklch(0.52 0.2 22 / 0.28);
  --success-bg:         var(--green-soft);
  --success-color:      var(--green);
  --error-bg:           var(--red-soft);
  --error-color:        var(--red);
  --grade-sep:          var(--border);
  --grade-letter-bg:    var(--surface2);
  --on-accent:          #ffffff;
  --btn-bg:             var(--accent);
  --btn-fg:             var(--on-accent);

  --card-radius: 14px;
  --font-scale: 1;
}

[data-theme="dark"] {
  /* Near-black immersive surfaces; accent hue follows the user's Appearance pick (--accent-h),
     with green/amber/red/purple kept as fixed semantic colors (success/warn/error/discussion). */
  --bg:            #000000;
  --surface:       #101010;
  --surface2:      #171717;
  --border:        transparent;
  --border2:       #262626;
  --text1:         #ffffff;
  --text2:         #b3b3b3;
  --input-bg:      #1a1a1a;
  --input-focus-bg:#242424;
  --shadow-sm:     rgba(0,0,0,0.3) 0px 4px 8px;
  --shadow-md:     rgba(0,0,0,0.5) 0px 8px 24px;
  --card-radius: 8px;

  /* Default palette is plain black and white -- white marks anything
     clickable. Picking a color in Settings (data-btn-accent) swaps this
     over to the user's chosen hue everywhere that reads --accent. */
  --accent:        #ffffff;
  --accent-mid:    #e0e0e0;
  --accent-soft:   rgba(255,255,255,0.16);
  --accent-text:   #ffffff;
  --green:         #1ed760;
  --green-soft:    rgba(30,215,96,0.16);
  --amber:         #ffa42b;
  --amber-soft:    rgba(255,164,43,0.16);
  --red:           #f3727f;
  --red-soft:      rgba(243,114,127,0.16);
  --purple:        #539df5;
  --purple-soft:   rgba(83,157,245,0.16);

  --btn-secondary-bg:    #1f1f1f;
  --btn-secondary-color: var(--text1);
  --ai-bg:               color-mix(in oklch, var(--accent) 12%, transparent);
  --ai-border:           color-mix(in oklch, var(--accent) 30%, transparent);
  --ai-label:            var(--accent);
  --ai-text:             #cbcbcb;
  --goal-tag-bg:         var(--accent-soft);
  --goal-tag-text:       var(--accent-text);
  --connected-bg:        var(--green-soft);
  --connected-color:     var(--green);
  --sync-btn-bg:         var(--green-soft);
  --sync-btn-color:      var(--green);
  --sync-btn-border:     rgba(30,215,96,0.35);
  --disconnect-bg:       var(--red-soft);
  --disconnect-color:    var(--red);
  --disconnect-border:   rgba(243,114,127,0.35);
  --success-bg:          var(--green-soft);
  --success-color:       var(--green);
  --error-bg:            var(--red-soft);
  --error-color:         var(--red);
  --grade-sep:           var(--border2);
  --grade-letter-bg:     var(--surface2);
  /* Dark text on the accent -- clears WCAG AA whether the accent is plain
     white or a chosen hue at 0.72 lightness. */
  --on-accent:           #0f0f0f;
  --btn-bg:              var(--accent);
  --btn-fg:              var(--on-accent);
}
/* Picking a color in Settings switches the whole app over from the plain
   black/white default to that hue -- badges, checks, buttons, everything
   that reads --accent, not just buttons. */
[data-theme="dark"][data-btn-accent] {
  --accent:        oklch(0.72 0.17 var(--accent-h));
  --accent-mid:    oklch(0.66 0.18 var(--accent-h));
  --accent-soft:   oklch(0.72 0.17 var(--accent-h) / 0.16);
  --accent-text:   oklch(0.72 0.17 var(--accent-h));
}

/* Pill/circle geometry + uppercase button labels, Spotify-style -- dark theme only */
[data-theme="dark"] .settings-btn,
[data-theme="dark"] .sync-btn,
[data-theme="dark"] .change-courses-btn,
[data-theme="dark"] .disconnect-btn {
  border-radius: 9999px;
  text-transform: uppercase;
  letter-spacing: 1.4px;
  font-weight: 700;
  font-size: 12.5px;
}
[data-theme="dark"] .card { border-color: transparent; box-shadow: none; }
/* --border is transparent in dark mode for the seamless card look, but that also made
   unchecked checkbox rings invisible until checked -- give them a real outline here. */
[data-theme="dark"] .done-check,
[data-theme="dark"] .priority-check,
[data-theme="dark"] .course-check {
  border-color: var(--border2);
}
[data-theme="dark"] .tab.active { font-weight: 700; }

/* A flat near-black reads as empty, not premium -- a faint fixed grain gives
   the background real texture without adding any color or motion. Fixed
   (not on a scrolling container) so it never repaints on scroll, and low
   enough opacity that it reads as material, not noise. */
[data-theme="dark"] body::before {
  content: '';
  position: fixed; inset: 0; z-index: -1;
  pointer-events: none;
  opacity: 0.035;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ===== RESET ===== */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { font-size: calc(var(--font-scale, 1) * 16px); }
body {
  font-family: 'DM Sans', -apple-system, sans-serif;
  background: var(--bg);
  min-height: 100vh;
  display: flex; justify-content: center;
  padding: 20px;
  color: var(--text1);
  transition: background 0.25s, color 0.25s;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
.app { width: 100%; min-height: 100vh; }

/* Pinned to the viewport while any login/onboarding screen is up (class
   toggled on both <html> and <body> in showAuthGlow()/hideAll() -- <html> is
   the element that actually scrolls here, overflow:hidden on body alone
   doesn't stop it) so the page can't be scrolled to reveal empty space
   around the centered card, or drag the desktop brand panel around.
   .auth-form-col gets its own internal scroll (and .auth-page is clipped to
   the viewport so an overly-tall grid track, e.g. the brand panel's text,
   can't push it taller) so a long onboarding list -- many classes, several
   goals typed in -- still stays fully reachable, just scrolling within its
   own column instead of the whole page moving. */
html.auth-mode, body.auth-mode { height: 100vh; overflow: hidden; }
/* .app is the actual scroll container for the onboarding screens specifically
   (#onboard-canvas/courses/goals/tour) -- they're plain siblings of
   #auth-page under .app, not nested inside it, each already using a fixed
   top margin rather than flex-centering, so they don't need the same
   overflow-hides-the-top fix .auth-form-col does below. */
body.auth-mode .app { height: 100%; overflow-y: auto; -webkit-overflow-scrolling: touch; }
body.auth-mode .auth-page { height: 100%; overflow: hidden; }
/* align-items:center (the cross-axis centering on .auth-form-col below) is
   exactly what was breaking this: centering a child taller than its
   container makes the overflow extend equally above and below, so with
   overflow-y:auto's default scrollTop of 0, the *top* of an overly-tall
   card renders below the fold, invisible, and scrolling down never reaches
   it either -- flex centering doesn't clamp to a real top edge on its own.
   Overriding to flex-start and centering instead via auto margins on the
   card itself avoids that: auto margins consume the extra space when the
   card fits (so it still looks centered normally) but collapse to 0 and
   fall back to a plain top-aligned, scrollable layout once it doesn't. */
body.auth-mode .auth-form-col {
  height: 100%; overflow-y: auto; -webkit-overflow-scrolling: touch;
  /* Only the cross-axis (vertical, since .auth-form-col is row-direction)
     needs to change -- justify-content:center (horizontal) is unaffected
     and still centers the card left-to-right same as before. */
  align-items: flex-start;
}
body.auth-mode .auth-form-col > .auth-screen {
  margin: auto 0;
}

/* ===== LOGO =====
   A graduation cap perched over the "S" of "Duesday" -- one monochrome
   mark instead of the wordmark plus a separate colored icon tile. */
.logo { display: flex; align-items: center; gap: 9px; position: relative; padding-left: 3px; }
.logo-mark {
  position: absolute; top: -9px; left: 1px; z-index: 1;
  width: 19px; height: 19px;
  color: var(--text1);
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0; pointer-events: none;
  transform: rotate(-24deg);
}
.logo-mark svg { width: 100%; height: 100%; overflow: visible; }
.logo-word {
  font-family: 'Playfair Display', 'DM Sans', serif; font-size: 20px; font-weight: 700;
  color: var(--text1); letter-spacing: -0.3px; white-space: nowrap; padding-left: 15px;
}
.logo-word em { font-style: normal; font-weight: 700; color: inherit; }
.topbar-logo .logo-mark { width: 16px; height: 16px; top: -7px; left: 0; }
.topbar-logo .logo-word { font-size: 18px; padding-left: 13px; }

/* ===== AUTH =====
   Split layout instead of a small card floating alone in a black void:
   a static brand panel on the left gives the space a reason to exist,
   the form sits in its own column at a size that matches the page
   instead of shrinking to fit its own content. */
.auth-page {
  display: grid;
  grid-template-columns: 60% 40%;
  min-height: 100vh;
}
.auth-brand {
  display: flex; align-items: center; justify-content: center;
  padding: 48px; border-right: 1px solid var(--border);
}
[data-theme="dark"] .auth-brand { border-right-color: var(--border2); }
.auth-brand-inner { max-width: 520px; }
.auth-brand-logo { margin-bottom: 40px; display: flex; align-items: center; }
.auth-brand-logo .logo-mark { width: 48px; height: 48px; }
.auth-brand-logo .logo-word { font-size: 34px; padding-left: 30px; }
.auth-brand-tagline {
  font-size: 38px; font-weight: 600; line-height: 1.3;
  color: var(--text1); letter-spacing: -0.6px; margin-bottom: 44px;
}
.auth-brand-points { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 22px; }
.auth-brand-points li { display: flex; align-items: center; gap: 14px; font-size: 17px; color: var(--text2); }
.auth-brand-points li::before {
  content: ''; width: 7px; height: 7px; border-radius: 50%;
  background: var(--accent); flex-shrink: 0;
}
.auth-form-col { display: flex; align-items: center; justify-content: center; padding: 40px; }

.auth-screen {
  width: 100%;
  max-width: 480px;
}
.auth-logo { margin-bottom: 12px; }
.auth-logo .logo-mark { width: 30px; height: 30px; }
.auth-logo .logo-word { font-size: 28px; padding-left: 19px; }
.auth-sub { font-size: 17px; color: var(--text2); margin-bottom: 36px; line-height: 1.5; }
.auth-label {
  font-size: 13px; font-weight: 600; color: var(--text2);
  text-transform: uppercase; letter-spacing: 0.07em; margin-bottom: 8px; display: block;
}
.auth-input {
  width: 100%; padding: 16px 18px;
  border-radius: 12px; border: 1px solid var(--border);
  font-size: 17px; color: var(--text1);
  background: var(--input-bg); margin-bottom: 18px; outline: none;
  font-family: inherit; transition: border-color 0.15s, box-shadow 0.15s, background 0.15s;
}
.auth-input:focus {
  border-color: var(--accent);
  background: var(--input-focus-bg);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.auth-btn {
  width: 100%; padding: 17px;
  border-radius: 12px; background: var(--btn-bg);
  color: var(--btn-fg); font-size: 17px; font-weight: 600;
  border: none; cursor: pointer; margin-top: 6px; font-family: inherit;
  letter-spacing: -0.1px;
  transition: opacity 0.15s, transform 0.1s, box-shadow 0.15s;
  box-shadow: 0 2px 10px color-mix(in oklch, var(--btn-bg) 30%, transparent);
}
.auth-btn:hover { opacity: 0.9; box-shadow: 0 4px 16px color-mix(in oklch, var(--btn-bg) 40%, transparent); }
.auth-btn:active { transform: scale(0.98); }
.auth-btn:disabled { opacity: 0.45; cursor: not-allowed; box-shadow: none; }
.auth-switch { text-align: center; margin-top: 24px; font-size: 16px; color: var(--text2); }
.auth-switch a { color: var(--accent); cursor: pointer; font-weight: 600; text-decoration: none; }

.msg-error {
  background: var(--red-soft); border-radius: 10px;
  padding: 10px 13px; font-size: 13px; color: var(--red);
  margin-bottom: 14px; border: 1px solid oklch(0.52 0.2 22 / 0.2);
}
.msg-success {
  background: var(--green-soft); border-radius: 10px;
  padding: 10px 13px; font-size: 13px; color: var(--green);
  margin-bottom: 14px; border: 1px solid oklch(0.52 0.16 145 / 0.2);
}

/* ===== ONBOARDING =====
   Full-page flow: a persistent header (progress + step label) that never
   moves, a horizontally sliding track holding all 4 steps side by side, and
   each step's own content area + bottom-pinned button filling the rest of
   the viewport. Replaces the old single floating card -- see git history
   for that version if it's ever needed again. */
.onboard-flow {
  display: none; flex-direction: column;
  position: fixed; inset: 0; z-index: 3;
  background: var(--surface);
  height: 100dvh;
}
.onboard-flow-header {
  flex-shrink: 0; text-align: center;
  padding: max(22px, env(safe-area-inset-top)) 24px 14px;
  border-bottom: 1px solid var(--border2);
}
.onboard-flow-header .onboard-progress { margin-bottom: 10px; }
.onboard-flow-viewport { flex: 1; min-height: 0; overflow: hidden; position: relative; }
.onboard-flow-track {
  display: flex; height: 100%; width: 400%;
  transition: transform 0.38s cubic-bezier(.22,1,.36,1);
}
.onboard-flow-track.no-anim { transition: none; }
.onboard-flow-panel {
  width: 25%; height: 100%; flex-shrink: 0;
  display: flex; flex-direction: column;
  padding: 0 24px;
}
.onboard-flow-panel-body {
  flex: 1; min-height: 0; overflow-y: auto; -webkit-overflow-scrolling: touch;
  max-width: 560px; width: 100%; margin: 0 auto; padding-top: 28px;
}
.onboard-flow-panel-footer {
  flex-shrink: 0; max-width: 560px; width: 100%; margin: 0 auto;
  padding: 14px 0 calc(14px + env(safe-area-inset-bottom));
}
.onboard-step { font-size: 12px; font-weight: 600; color: var(--text2); text-transform: uppercase; letter-spacing: 0.07em; margin-bottom: 8px; }
.onboard-title { font-size: 28px; font-weight: 700; color: var(--text1); margin-bottom: 8px; letter-spacing: -0.3px; }
.onboard-title-row { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.onboard-title-row .onboard-title { margin-bottom: 0; }
.onboard-title-icon {
  width: 30px; height: 30px; border-radius: 9px; flex-shrink: 0;
  background: var(--accent-soft); color: var(--accent);
  display: flex; align-items: center; justify-content: center;
}
.onboard-title-icon svg { width: 17px; height: 17px; }
.onboard-sub { font-size: 15px; color: var(--text2); margin-bottom: 28px; line-height: 1.6; }
.onboard-btn {
  width: 100%; padding: 13px; border-radius: 12px;
  background: var(--btn-bg); color: var(--btn-fg); font-size: 15px; font-weight: 600;
  border: none; cursor: pointer; margin-top: 8px; font-family: inherit;
  transition: opacity 0.15s, transform 0.1s, box-shadow 0.15s;
  box-shadow: 0 2px 10px color-mix(in oklch, var(--btn-bg) 28%, transparent);
}
.onboard-btn:hover { opacity: 0.9; }
.onboard-btn:active { transform: scale(0.98); }
.onboard-btn:disabled { opacity: 0.45; cursor: not-allowed; box-shadow: none; }
.onboard-btn-secondary {
  width: 100%; padding: 13px; border-radius: 12px;
  background: var(--btn-secondary-bg); color: var(--btn-secondary-color);
  font-size: 15px; font-weight: 500; border: none; cursor: pointer;
  margin-top: 8px; font-family: inherit; transition: background 0.15s, transform 0.1s;
}
.onboard-btn-secondary:hover { background: var(--border2); }
.onboard-btn-secondary:active { transform: scale(0.98); }

/* Plain-text link pair for "Go back"/"Skip for now" -- demoted below the
   primary CTA instead of stacked as equal-weight buttons. */
.onboard-link-row { display: flex; align-items: center; justify-content: center; gap: 20px; margin-top: 14px; }
.onboard-link {
  background: none; border: none; cursor: pointer; font-family: inherit;
  font-size: 13px; font-weight: 600; color: var(--text2); padding: 4px 2px;
  transition: color 0.15s;
}
.onboard-link:hover { color: var(--text1); }
.onboard-link:active { opacity: 0.7; }

.progress-dots { display: flex; gap: 7px; justify-content: center; margin-bottom: 26px; }
.dot { width: 6px; height: 6px; border-radius: 50%; background: var(--border2); transition: all 0.2s; }
.dot.active { background: var(--accent); width: 18px; border-radius: 3px; }
/* Main 4-step onboarding indicator -- same pill shape at every step instead
   of a lone wide dot among round ones. Scoped with .onboard-progress so the
   plain .dot/.dot.active pair above still works unchanged for the tour's
   mini-dots and the links tutorial, which reuse .progress-dots/.dot too. */
.onboard-progress .dot {
  width: 22px; height: 6px; border-radius: 3px;
  background: transparent; border: 1.5px solid var(--border2);
  transition: all 0.25s cubic-bezier(.16,1,.3,1);
}
.onboard-progress .dot.complete { background: var(--text1); border-color: var(--text1); opacity: 0.85; }
.onboard-progress .dot.current { background: var(--accent); border-color: var(--accent); width: 28px; }
.onboard-progress .dot.upcoming { background: transparent; border-color: var(--border2); }

/* Onboarding step 4 -- a short feature tour instead of dropping students
   straight onto the dashboard cold. Reuses the onboarding shell (dots,
   title, sub) so it doesn't feel like a different screen bolted on. */
.tour-slide { text-align: center; padding: 12px 0 28px; animation: fadeUp 0.3s cubic-bezier(.16,1,.3,1) both; }
.tour-slide-icon {
  width: 64px; height: 64px; margin: 0 auto 18px; border-radius: 18px;
  background: var(--surface2); display: flex; align-items: center; justify-content: center;
  font-size: 30px;
}
.tour-slide .onboard-title, .tour-slide .onboard-sub { margin-bottom: 0; }
.tour-slide .onboard-sub { margin-top: 8px; }

/* Small, stylized mockups of the real UI per slide -- a description of
   "Due has a calendar" means a lot less than actually seeing a calendar. */
.tour-mock {
  background: var(--surface2); border-radius: 16px; padding: 16px;
  margin-bottom: 18px; min-height: 112px; display: flex; flex-direction: column;
  justify-content: center; gap: 8px; text-align: left;
  animation: fadeUp 0.3s cubic-bezier(.16,1,.3,1) both;
}
.tour-mock-stat { display: flex; align-items: baseline; gap: 8px; margin-bottom: 2px; }
.tour-mock-stat-num { font-size: 28px; font-weight: 800; color: var(--text1); line-height: 1; }
.tour-mock-stat-label { font-size: 12.5px; color: var(--text2); }
.tour-mock-row { display: flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--text1); background: var(--surface); border-radius: 8px; padding: 8px 10px; }
.tour-mock-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--accent); flex-shrink: 0; }
.tour-mock-cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
.tour-mock-cal-cell {
  aspect-ratio: 1; border-radius: 6px; background: var(--surface); display: flex; align-items: center; justify-content: center;
  font-size: 10px; color: var(--text2); position: relative;
}
.tour-mock-cal-cell.active { background: var(--btn-bg); color: var(--btn-fg); font-weight: 700; }
.tour-mock-cal-dot { position: absolute; bottom: 3px; width: 3px; height: 3px; border-radius: 50%; background: var(--btn-fg); }
.tour-mock-priority-row { display: flex; align-items: center; gap: 10px; font-size: 12.5px; color: var(--text1); background: var(--surface); border-radius: 8px; padding: 9px 10px; }
.tour-mock-rank {
  width: 20px; height: 20px; border-radius: 50%; background: var(--btn-bg); color: var(--btn-fg);
  font-size: 11px; font-weight: 800; display: flex; align-items: center; justify-content: center; flex-shrink: 0;
}
.tour-mock-timer { display: flex; flex-direction: column; align-items: center; gap: 8px; }
.tour-mock-timer-ring {
  width: 72px; height: 72px; border-radius: 50%; border: 4px solid var(--border2);
  border-top-color: var(--accent); display: flex; align-items: center; justify-content: center;
  font-size: 13px; font-weight: 700; color: var(--text1);
}
.tour-mock-timer-label { font-size: 12px; color: var(--text2); }
.tour-mock-bubble { font-size: 12px; padding: 9px 12px; border-radius: 14px; max-width: 90%; line-height: 1.4; }
.tour-mock-bubble-q { align-self: flex-end; background: var(--btn-bg); color: var(--btn-fg); border-bottom-right-radius: 4px; }
.tour-mock-bubble-a { align-self: flex-start; background: var(--surface); color: var(--text1); border-bottom-left-radius: 4px; }

.course-item {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 14px; background: var(--input-bg);
  border-radius: 12px; margin-bottom: 8px; cursor: pointer;
  border: 1.5px solid transparent; transition: all 0.15s;
}
.course-item.selected { background: var(--accent-soft); border-color: var(--accent); }
.course-check {
  width: 20px; height: 20px; border-radius: 50%;
  border: 1.5px solid var(--border); flex-shrink: 0;
  display: flex; align-items: center; justify-content: center; transition: all 0.15s;
}
.course-item.selected .course-check { background: var(--accent); border-color: var(--accent); }
.course-check-inner { width: 8px; height: 8px; border-radius: 50%; background: var(--on-accent); display: none; }
.course-item.selected .course-check-inner { display: block; }
.course-name { font-size: 14px; font-weight: 500; color: var(--text1); }
.course-loading { text-align: center; padding: 20px; color: var(--text2); font-size: 14px; }
.course-section-title { font-size: 11px; font-weight: 600; color: var(--text2); text-transform: uppercase; letter-spacing: 0.07em; margin: 12px 0 8px; }
.previous-courses-toggle {
  display: flex; align-items: center; justify-content: space-between;
  width: 100%; padding: 12px 14px; background: var(--input-bg);
  border-radius: 12px; border: none; cursor: pointer;
  font-size: 13px; font-weight: 600; color: var(--text2); margin-top: 8px; font-family: inherit;
}
.previous-courses-toggle .arrow { transition: transform 0.15s; }
.previous-courses-toggle.open .arrow { transform: rotate(90deg); }
.previous-courses-list { display: none; margin-top: 8px; }
.previous-courses-list.open { display: block; }

.goal-input-row { display: flex; gap: 8px; margin-bottom: 8px; }
.goal-input {
  flex: 1; padding: 11px 14px; border-radius: 12px;
  border: 1px solid var(--border); font-size: 14px; color: var(--text1);
  background: var(--input-bg); outline: none; font-family: inherit;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.goal-input:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.goal-add-btn {
  padding: 11px 16px; border-radius: 12px;
  background: var(--btn-bg); color: var(--btn-fg); font-size: 14px; font-weight: 600;
  border: none; cursor: pointer; font-family: inherit;
  transition: opacity 0.15s, transform 0.1s;
}
.goal-add-btn:hover { opacity: 0.9; }
.goal-add-btn:active { transform: scale(0.96); }
.goal-tag {
  display: flex; align-items: center; gap: 8px;
  background: var(--accent-soft); border-radius: 10px;
  padding: 9px 12px; margin-bottom: 8px;
}
.goal-tag-text { font-size: 13px; color: var(--text1); flex: 1; font-weight: 500; }
.goal-tag-remove { font-size: 20px; color: var(--text2); cursor: pointer; background: none; border: none; line-height: 1; opacity: 0.6; }
.goal-tag.goal-tag-new { animation: goalChipIn 0.3s cubic-bezier(.16,1,.3,1) both; }
@keyframes goalChipIn {
  from { opacity: 0; transform: translateY(-6px) scale(0.96); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}

/* ===== MAIN APP ===== */
.main-app { display: none; flex-direction: row; align-items: stretch; min-height: 100vh; }
.main-col { flex: 1; min-width: 0; min-height: 0; display: flex; flex-direction: column; overflow-x: hidden; }

.topbar {
  background: var(--surface);
  padding: 13px 18px 11px;
  border-bottom: 1px solid var(--border);
  display: flex; justify-content: space-between; align-items: center;
  position: sticky; top: 0; z-index: 100;
  backdrop-filter: blur(24px);
  -webkit-backdrop-filter: blur(24px);
}
.topbar-right { display: flex; align-items: center; gap: 6px; margin-left: auto; }
.topbar-sub { font-size: 10.5px; color: var(--text2); margin-top: 1.5px; letter-spacing: 0.01em; }

/* ===== SIDEBAR (laptop/desktop) ===== */
.sidebar-logo { display: none; }
@media (min-width: 601px) {
  .app { max-width: none; }
  .main-app { display: flex; }
  .sidebar-logo {
    display: flex; align-items: center; gap: 10px;
    padding: 4px 10px 22px;
  }
  .tabs {
    position: sticky; top: 0; align-self: flex-start;
    width: 232px; flex: 0 0 232px; height: 100vh;
    flex-direction: column; align-items: stretch;
    border-bottom: none; border-right: 1px solid var(--border);
    overflow-x: visible; overflow-y: auto;
    padding: 22px 14px; gap: 2px;
    transition: width 0.22s cubic-bezier(.16,1,.3,1), flex-basis 0.22s cubic-bezier(.16,1,.3,1);
  }
  /* Collapsed sidebar: icon rail only -- lets the layout feel less boxed-in
     without giving up quick access to every tab. */
  .sidebar-toggle-btn {
    display: flex; align-items: center; justify-content: center; margin-left: auto;
    width: 26px; height: 26px; border-radius: 6px; flex-shrink: 0;
    background: none; border: none;
    color: var(--text2); cursor: pointer; padding: 0;
    transition: background 0.15s, color 0.15s;
  }
  .sidebar-toggle-btn:hover { background: var(--surface2); color: var(--text1); }
  .sidebar-toggle-btn svg { width: 16px; height: 16px; }
  .tabs.collapsed { width: 76px; flex: 0 0 76px; }
  .tabs.collapsed .sidebar-logo { justify-content: center; padding-left: 0; padding-right: 0; }
  .tabs.collapsed .sidebar-toggle-btn { margin-left: 0; }
  .tabs.collapsed .logo-word,
  .tabs.collapsed .tab span:not(.tab-icon),
  .tabs.collapsed .nav-group-label,
  .tabs.collapsed .sidebar-sync-text { display: none; }
  .tabs.collapsed .tab { justify-content: center; padding: 10px; }
  .tabs.collapsed .sidebar-sync { justify-content: center; padding: 10px; }
  /* With the wordmark hidden there's no "S" left to sit on -- fall back to
     a plain centered cap icon instead of an absolute mark floating with
     nothing to anchor to. */
  .tabs.collapsed .logo-mark {
    position: static; transform: none; width: 20px; height: 20px; margin: 0 auto;
  }
  .tab {
    display: flex; align-items: center; gap: 11px;
    padding: 10px 12px; border-radius: 10px;
    border-bottom: none !important; font-size: 13.5px; font-weight: 500;
    justify-content: flex-start;
  }
  .tab:hover { background: var(--surface2); color: var(--text1); }
  .tab.active { background: var(--accent-soft); color: var(--accent-text); }
  .tab-icon { width: 18px; height: 18px; flex-shrink: 0; display: flex; }
  .tab-icon svg { width: 100%; height: 100%; }
  .nav-group-label {
    font-size: 10px; font-weight: 700; color: var(--text2);
    text-transform: uppercase; letter-spacing: 0.08em;
    padding: 16px 12px 6px;
  }
  .nav-group-label:first-of-type { padding-top: 6px; }
  .topbar-logo { display: none; }
  .content { width: 100%; max-width: 1440px; margin: 0 auto; padding: 28px 40px 40px; box-sizing: border-box; }
  .bottom-nav { display: none !important; }
  #tab-settings { margin-top: auto; }
}
@media (min-width: 900px) {
  .home-columns { display: flex; gap: 24px; align-items: flex-start; }
  .home-col-main { flex: 1.6; min-width: 0; }
  .home-col-side { flex: 1; min-width: 0; }

  #allwork-list, #priority-list, #grades-cards, #goals-display, #syllabus-list,
  #overdue-list, #due-cal-selected-list, #nodate-list {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 10px;
  }
  #allwork-list > .section-label { grid-column: 1 / -1; }
}

/* Round icon buttons in the top bar (bug report, theme). */
.topbar-icon-btn {
  position: relative; width: 30px; height: 30px; border-radius: 50%; flex-shrink: 0;
  background: var(--surface2); border: 1px solid var(--border); color: var(--text2);
  cursor: pointer; display: flex; align-items: center; justify-content: center; padding: 0;
  transition: background 0.15s, color 0.15s, transform 0.15s;
}
.topbar-icon-btn:hover { background: var(--btn-secondary-bg); color: var(--text1); }
.topbar-icon-btn:active { transform: scale(0.92); }
.topbar-icon-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.topbar-icon-btn svg { width: 16px; height: 16px; }
.bug-btn:hover { color: var(--red); }
/* Theme: moon in light mode (tap for dark), sun in dark mode (tap for light).
   The icon turning swaps in place rather than blinking. */
.theme-btn .ti { position: absolute; transition: opacity 0.25s, transform 0.4s var(--ease-spring, ease-out); }
.theme-btn .ti-sun { opacity: 0; transform: rotate(-90deg) scale(0.6); }
[data-theme="dark"] .theme-btn .ti-moon { opacity: 0; transform: rotate(90deg) scale(0.6); }
[data-theme="dark"] .theme-btn .ti-sun { opacity: 1; transform: none; }
.theme-btn:hover .ti-sun { color: oklch(0.8 0.15 85); }
.theme-btn:hover .ti-moon { color: oklch(0.6 0.15 270); }
@media (prefers-reduced-motion: reduce) { .theme-btn .ti { transition: opacity 0.15s; } }
.signout-btn {
  font-size: 12.5px; color: var(--text2); cursor: pointer;
  background: none; border: none; font-weight: 500; font-family: inherit;
  padding: 5px 9px; border-radius: 8px; transition: color 0.15s, background 0.15s;
  display: flex; align-items: center; gap: 5px; flex-shrink: 0;
}
.signout-btn:hover { color: var(--red); background: var(--red-soft); }
.signout-btn-icon { width: 15px; height: 15px; flex-shrink: 0; }
/* Icon-only past a certain width so this never gets clipped or crowded out
   by the sync/theme buttons on a narrow phone -- it stays visible, just
   loses the label instead of losing the whole button. */
@media (max-width: 420px) {
  .signout-btn-text { display: none; }
  .signout-btn { padding: 7px; }
}

.tabs {
  display: flex; background: var(--surface);
  border-bottom: 1px solid var(--border); overflow-x: auto;
}
.tabs::-webkit-scrollbar { display: none; }
.tab {
  flex-shrink: 0; padding: 11px 14px; font-size: 13px; font-weight: 500;
  color: var(--text2); cursor: pointer;
  border-bottom: 2px solid transparent; white-space: nowrap;
  font-family: inherit; transition: color 0.15s, transform 0.12s; background: none; border-top: none; border-left: none; border-right: none;
}
.tab.active { color: var(--accent); border-bottom-color: var(--accent); }
.tab:active { transform: scale(0.96); }

.content { padding: 16px 16px 24px; }
/* Dashboard slides in from the right as the sync overlay fades away, instead
   of just sitting there already-rendered once the overlay disappears. */
.content.dashboard-slide-in { animation: dashboardSlideIn 0.5s cubic-bezier(.16,1,.3,1) both; }
@keyframes dashboardSlideIn {
  from { opacity: 0; transform: translateX(48px); }
  to   { opacity: 1; transform: translateX(0); }
}
.page { display: none; }
.page.active { display: block; }

/* ===== SECTION LABELS ===== */
.section-label {
  font-size: 10.5px; font-weight: 700; color: var(--text2);
  text-transform: uppercase; letter-spacing: 0.08em;
  margin-bottom: 10px; margin-top: 22px;
}
.section-label:first-child { margin-top: 0; }

/* ===== CARDS ===== */
.card {
  background: var(--surface);
  border-radius: var(--card-radius);
  border: 1px solid var(--border);
  padding: 13px 15px; margin-bottom: 9px;
  box-shadow: var(--shadow-sm);
  transition: border-color 0.15s, transform 0.15s, box-shadow 0.15s;
  animation: cardIn 0.55s cubic-bezier(.16,1,.3,1) both;
}
.card:has(.card-title-link):hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
}
@keyframes cardIn {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}
.card:nth-of-type(1)  { animation-delay: 0ms; }
.card:nth-of-type(2)  { animation-delay: 70ms; }
.card:nth-of-type(3)  { animation-delay: 140ms; }
.card:nth-of-type(4)  { animation-delay: 210ms; }
.card:nth-of-type(5)  { animation-delay: 280ms; }
.card:nth-of-type(6)  { animation-delay: 350ms; }
.card:nth-of-type(7)  { animation-delay: 420ms; }
.card:nth-of-type(8)  { animation-delay: 490ms; }
.card:nth-of-type(n+9) { animation-delay: 560ms; }
.card-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; }
.card-title { font-size: 14px; font-weight: 500; color: var(--text1); line-height: 1.4; }
.card-sub { font-size: 11.5px; color: var(--text2); margin-top: 2px; }

.badge {
  font-size: 10px; padding: 3px 8px; border-radius: 99px;
  white-space: nowrap; font-weight: 700; letter-spacing: 0.03em; flex-shrink: 0;
}
.badge-test       { background: var(--red-soft);    color: var(--red);    }
.badge-hw         { background: var(--accent-soft);  color: var(--accent-text); }
.badge-quiz       { background: var(--amber-soft);   color: var(--amber);  }
.badge-essay      { background: var(--green-soft);   color: var(--green);  }
.badge-discussion { background: var(--purple-soft);  color: var(--purple); }

.due-soon { color: var(--red); font-size: 12px; font-weight: 500; margin-top: 6px; }
.due-ok   { color: var(--text2); font-size: 12px; margin-top: 6px; }
.due-locked { color: var(--amber); font-size: 12px; font-weight: 600; margin-top: 6px; }

.card.overdue-card {
  border-color: oklch(0.52 0.2 22 / 0.28);
  background: linear-gradient(135deg, var(--surface) 0%, oklch(0.52 0.2 22 / 0.035) 100%);
}
.overdue-pill {
  display: inline-block; font-size: 9px; font-weight: 700;
  color: var(--red); background: var(--red-soft); border-radius: 4px;
  padding: 2px 5px; margin-left: 5px; vertical-align: middle; letter-spacing: 0.04em;
}
.card.done .card-row > div:last-child { opacity: 0.42; }
.card.done .card-title { text-decoration: line-through; }
.done-check {
  width: 22px; height: 22px; border-radius: 50%;
  border: 1.5px solid var(--border); flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; background: none; transition: all 0.18s; padding: 0;
}
.done-check:active { transform: scale(0.85); }
.done-check.checked { background: var(--green); border-color: var(--green); animation: checkPop 0.5s cubic-bezier(.34,1.56,.64,1); }
.done-check-icon { font-size: 11px; color: var(--on-accent); display: none; line-height: 1; }
.done-check.checked .done-check-icon { display: block; }
@keyframes checkPop {
  0%   { transform: scale(0.55); }
  65%  { transform: scale(1.18); }
  100% { transform: scale(1); }
}

/* Stats -- one bordered strip with internal dividers instead of N identical
   floating cards side by side (the generic "KPI row" every AI dashboard ships). */
.home-stats-strip {
  display: flex; background: var(--surface); border-radius: var(--card-radius);
  border: 1px solid var(--border); box-shadow: var(--shadow-sm); margin-bottom: 20px;
  overflow: hidden;
  animation: cardIn 0.6s cubic-bezier(.16,1,.3,1) both;
}
.home-stat { flex: 1; min-width: 0; padding: 15px 16px; }
.home-stat + .home-stat { border-left: 1px solid var(--border2); }
.stat-label { font-size: 10.5px; color: var(--text2); margin-bottom: 5px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; }
.stat-val { font-size: 30px; font-weight: 700; color: var(--text1); letter-spacing: -0.5px; line-height: 1; display: inline-block; }
@keyframes statPop {
  0%   { opacity: 0; transform: translateY(8px) scale(0.75); }
  45%  { opacity: 1; transform: translateY(0) scale(1.18); }
  70%  { transform: scale(1.06); }
  100% { transform: scale(1); }
}
.stat-val.stat-pop { animation: statPop 0.9s cubic-bezier(.22,1,.36,1); }
@keyframes overdueFlash {
  0%   { opacity: 0; transform: translateY(8px) scale(0.7); text-shadow: 0 0 0 transparent; }
  40%  { opacity: 1; transform: translateY(0) scale(1.3); text-shadow: 0 0 18px oklch(0.52 0.2 22 / 0.8); }
  70%  { transform: scale(0.96); text-shadow: 0 0 10px oklch(0.52 0.2 22 / 0.5); }
  100% { transform: scale(1); text-shadow: 0 0 0 transparent; }
}
#stat-overdue.stat-pop { animation: overdueFlash 0.7s cubic-bezier(.22,1,.36,1); }

/* ===== DASHBOARD (home) ===============================================
   Scoped overrides (not touched: the shared .card used on every other
   page) -- the one due-next assignment gets real visual weight instead
   of sitting in an identical bordered box next to everything else, and
   "This week" reads as one clean list instead of a stack of repeated
   cards. This is what breaks the generic "row of KPI cards + row of
   identical list cards" dashboard template. */
#home-upnext .card {
  border: 1px solid var(--glass-border); border-radius: 20px;
  background: var(--glass-bg);
  box-shadow: var(--glass-shadow);
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  padding: 18px 20px 18px 17px;
  border-left: 3px solid var(--accent);
}
#home-upnext .card-title { font-size: 15.5px; font-weight: 700; letter-spacing: -0.2px; }
#home-upnext .done-check { width: 25px; height: 25px; }

#home-thisweek {
  background: var(--glass-bg); border: 1px solid var(--glass-border);
  border-radius: 20px; box-shadow: var(--glass-shadow); overflow: hidden;
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
}
#home-thisweek .card {
  border: none; border-radius: 0; box-shadow: none; margin-bottom: 0;
  padding: 12px 16px; border-bottom: 1px solid var(--border2);
  background: transparent; animation: none;
}
#home-thisweek .card:last-child { border-bottom: none; }
#home-thisweek .card:hover,
#home-thisweek .card:has(.card-title-link):hover {
  transform: none; box-shadow: none; background: var(--glass-bg);
}

/* The grades panel is a glass card like the rest of the sidebar column
   (see .glass); only its padding is specific to it. */
#home-grades.card { padding: 8px 18px; }

/* Announcements -- sits full-width right under the hero, above the two-column
   layout, so a new teacher post is one of the first things a student sees,
   not buried in a side list. Unread ones carry an accent dot and slightly
   bolder title; clicking expands the message in place and marks it read. */
.announcements-section { margin: 22px 0 28px; }
.announcements-section-label { display: flex; align-items: center; gap: 7px; }
.announcements-icon { width: 14px; height: 14px; color: var(--text2); flex-shrink: 0; transition: color 0.2s; }
.announcements-section-label.has-unread .announcements-icon { color: var(--accent); }
.announcements-badge {
  display: none; font-size: 10px; font-weight: 700; color: var(--on-accent);
  background: var(--accent); border-radius: 99px; min-width: 15px; height: 15px;
  padding: 0 4px; align-items: center; justify-content: center; line-height: 1;
  animation: wsSummaryPop 0.4s cubic-bezier(.16,1,.3,1) both;
}
.announcements-badge:not(:empty) { display: inline-flex; }
.announcements-see-all { margin-left: auto; font-size: 11px; font-weight: 600; color: var(--text2); text-transform: none; letter-spacing: normal; }
.announcements-section-label:hover .announcements-see-all { color: var(--text1); }
#home-announcements.has-unread {
  border-color: var(--accent-soft);
  box-shadow: var(--shadow-sm), 0 0 0 3px var(--accent-soft);
}
.announcement-card {
  display: flex; gap: 11px; align-items: flex-start; cursor: pointer;
  padding: 12px 34px 12px 12px; border-bottom: 1px solid var(--border2);
  border-left: 3px solid transparent; position: relative; overflow: hidden;
  transition: background 0.15s, border-color 0.15s,
    max-height 0.32s cubic-bezier(.4,0,.2,1), opacity 0.28s ease,
    padding-top 0.32s ease, padding-bottom 0.32s ease, border-bottom-color 0.32s ease;
}
.announcement-card.announcement-dismissing {
  max-height: 0 !important; opacity: 0;
  padding-top: 0; padding-bottom: 0;
  border-bottom-color: transparent;
  pointer-events: none;
}
.announcement-dismiss {
  position: absolute; top: 10px; right: 8px; width: 22px; height: 22px;
  border-radius: 50%; border: none; background: transparent; color: var(--text2);
  display: none; align-items: center; justify-content: center; cursor: pointer;
  font-size: 13px; line-height: 1; padding: 0; transition: background 0.15s, color 0.15s;
}
.announcement-card.read .announcement-dismiss { display: flex; }
.announcement-dismiss:hover { background: var(--border2); color: var(--text1); }
.announcement-card:hover { background: var(--surface2); }
.announcement-card:last-child { border-bottom: none; }
.announcement-card.unread { border-left-color: var(--accent); background: var(--accent-soft); }
.announcement-card.unread:hover { background: var(--accent-soft); filter: brightness(0.97); }
.announcement-unread-dot {
  width: 7px; height: 7px; border-radius: 50%; background: var(--accent);
  flex-shrink: 0; margin-top: 6px; opacity: 0; transition: opacity 0.15s;
}
.announcement-card.unread .announcement-unread-dot { opacity: 1; }
.announcement-main { flex: 1; min-width: 0; }
.announcement-course {
  font-size: 10.5px; font-weight: 700; color: var(--accent-text);
  text-transform: uppercase; letter-spacing: 0.05em;
}
.announcement-title { font-size: 13.5px; font-weight: 500; color: var(--text1); margin-top: 2px; }
.announcement-card.unread .announcement-title { font-weight: 700; }
.announcement-meta { font-size: 11.5px; color: var(--text2); margin-top: 2px; }
.announcement-body {
  font-size: 13px; color: var(--text1); line-height: 1.55; margin-top: 10px;
  white-space: pre-wrap; animation: fadeUp 0.25s cubic-bezier(.16,1,.3,1) both;
}
.announcement-body .canvas-link { display: inline-block; margin-top: 8px; }
#home-announcements {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--card-radius); box-shadow: var(--shadow-sm); overflow: hidden;
  animation: cardIn 0.55s cubic-bezier(.16,1,.3,1) both;
  transition: box-shadow 0.2s, border-color 0.2s;
}

/* ===== CELEBRATION (assignment / task completion) ===== */
.confetti-piece {
  position: fixed; width: 7px; height: 7px; border-radius: 2px;
  pointer-events: none; z-index: 9999; top: 0; left: 0;
  animation: confettiBurst 0.75s cubic-bezier(.16,.8,.3,1) forwards;
}
@keyframes confettiBurst {
  0%   { transform: translate(-50%,-50%) scale(1) rotate(0deg); opacity: 1; }
  100% { transform: translate(calc(-50% + var(--dx)), calc(-50% + var(--dy))) scale(0.3) rotate(var(--rot)); opacity: 0; }
}
.confetti-piece.confetti-rise {
  width: 10px; height: 10px;
  animation: confettiRise 1.5s cubic-bezier(.12,.7,.3,1) forwards;
}
@keyframes confettiRise {
  0%   { transform: translate(-50%,-50%) scale(1) rotate(0deg); opacity: 1; }
  75%  { opacity: 1; }
  100% { transform: translate(calc(-50% + var(--dx)), calc(-50% + var(--dy))) scale(0.5) rotate(var(--rot)); opacity: 0; }
}

/* ===== PRIORITY ===== */
.priority-card {
  background: var(--surface); border-radius: var(--card-radius);
  border: 1px solid var(--border); padding: 13px 15px; margin-bottom: 9px;
  display: flex; align-items: center; gap: 11px; box-shadow: var(--shadow-sm);
  animation: cardIn 0.55s cubic-bezier(.16,1,.3,1) both;
  transition: transform 0.15s, box-shadow 0.15s;
}
.priority-card:hover { transform: translateY(-1px); box-shadow: var(--shadow-md); }
.priority-card:nth-of-type(1) { animation-delay: 0ms; }
.priority-card:nth-of-type(2) { animation-delay: 70ms; }
.priority-card:nth-of-type(3) { animation-delay: 140ms; }
.priority-card:nth-of-type(4) { animation-delay: 210ms; }
.priority-card:nth-of-type(n+5) { animation-delay: 280ms; }
.priority-num {
  width: 26px; height: 26px; border-radius: 7px;
  display: flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 700; flex-shrink: 0;
}
.p1 { background: oklch(0.52 0.2  22  / 0.14); color: oklch(0.52 0.2  22 ); }
.p2 { background: oklch(0.58 0.18 38  / 0.14); color: oklch(0.58 0.18 38 ); }
.p3 { background: oklch(0.58 0.18 72  / 0.14); color: oklch(0.58 0.18 72 ); }
.p4 { background: oklch(0.56 0.2  var(--accent-h) / 0.14); color: var(--accent); }
.p5 { background: oklch(0.52 0.16 145 / 0.14); color: oklch(0.52 0.16 145); }
[data-theme="dark"] .p1 { background: oklch(0.65 0.18 22  / 0.2); color: oklch(0.65 0.18 22 ); }
[data-theme="dark"] .p2 { background: oklch(0.70 0.16 38  / 0.2); color: oklch(0.70 0.16 38 ); }
[data-theme="dark"] .p3 { background: oklch(0.72 0.16 72  / 0.2); color: oklch(0.72 0.16 72 ); }
[data-theme="dark"] .p4 { background: oklch(0.68 0.18 var(--accent-h) / 0.2); color: var(--accent); }
[data-theme="dark"] .p5 { background: oklch(0.65 0.15 145 / 0.2); color: oklch(0.65 0.15 145); }

.priority-check {
  width: 28px; height: 28px; border-radius: 50%;
  border: 1.5px solid var(--border); background: transparent;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; flex-shrink: 0; font-size: 13px; color: transparent;
  transition: all 0.18s;
}
.priority-check:hover { border-color: var(--green); color: var(--green); background: var(--green-soft); }
.priority-check:active { transform: scale(0.88); }
.priority-completed-section { margin-top: 20px; }
.priority-completed-label { font-size: 10.5px; font-weight: 700; color: var(--text2); text-transform: uppercase; letter-spacing: 0.07em; margin-bottom: 10px; }
.priority-card.completed-card .priority-num,
.priority-card.completed-card .priority-info { opacity: 0.48; }
.priority-card.completed-card .card-title { text-decoration: line-through; }
.priority-info { flex: 1; min-width: 0; }

/* AI box */
.ai-box {
  background: var(--ai-bg); border-radius: var(--card-radius);
  border: 1px solid var(--ai-border); padding: 14px 16px; margin-bottom: 18px;
}
.ai-label {
  font-size: 10px; font-weight: 700; color: var(--ai-label);
  text-transform: uppercase; letter-spacing: 0.09em; margin-bottom: 6px;
  display: flex; align-items: center; gap: 6px;
}
.ai-dot {
  width: 12px; height: 12px; color: var(--accent); display: inline-flex;
  animation: pulse 2.4s infinite;
}
.ai-dot svg { width: 100%; height: 100%; }
@keyframes pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.55; } }
.ai-text { font-size: 13px; color: var(--ai-text); line-height: 1.55; }

/* ===== GOALS ===== */
.goal-card {
  background: var(--surface); border-radius: var(--card-radius);
  border: 1px solid var(--border); padding: 15px 16px;
  margin-bottom: 10px; box-shadow: var(--shadow-sm);
  animation: cardIn 0.55s cubic-bezier(.16,1,.3,1) both;
}
.goal-card:nth-of-type(1) { animation-delay: 0ms; }
.goal-card:nth-of-type(2) { animation-delay: 90ms; }
.goal-card:nth-of-type(3) { animation-delay: 180ms; }
.goal-card:nth-of-type(n+4) { animation-delay: 280ms; }
.goal-row { display: flex; align-items: flex-start; gap: 10px; }
.goal-dot { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; margin-top: 4px; }
.goal-text { font-size: 14px; font-weight: 600; color: var(--text1); flex: 1; line-height: 1.4; }
.goal-remove { background: none; border: none; color: var(--text2); font-size: 18px; cursor: pointer; opacity: 0.5; line-height: 1; margin-top: -1px; }
.goal-remove:hover { color: var(--red); opacity: 1; }
.goal-plan { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--border); display: flex; flex-direction: column; gap: 7px; }
.goal-step { font-size: 13px; color: var(--text2); line-height: 1.45; display: flex; gap: 7px; }
.goal-step-arrow { color: var(--accent); font-weight: 700; flex-shrink: 0; }
.add-goal-row { display: flex; gap: 8px; margin-top: 12px; }
.add-goal-input {
  flex: 1; padding: 11px 13px; border-radius: 12px;
  border: 1px solid var(--border); font-size: 13px; color: var(--text1);
  background: var(--input-bg); outline: none; font-family: inherit;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.add-goal-input:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.add-goal-btn {
  padding: 11px 14px; border-radius: 12px; background: var(--btn-bg);
  color: var(--btn-fg); font-size: 13px; font-weight: 600; border: none; cursor: pointer; font-family: inherit;
  transition: opacity 0.15s, transform 0.1s;
}
.add-goal-btn:hover { opacity: 0.9; }
.add-goal-btn:active { transform: scale(0.96); }

/* ===== GRADES ===== */
.grade-card {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 16px; margin-bottom: 9px;
  background: var(--surface); border-radius: var(--card-radius);
  border: 1px solid var(--border); box-shadow: var(--shadow-sm);
  animation: cardIn 0.55s cubic-bezier(.16,1,.3,1) both;
  cursor: pointer; transition: border-color 0.15s, transform 0.1s;
}
.grade-card:hover { border-color: var(--accent); }
.grade-card:active { transform: scale(0.99); }
.grade-breakdown-hint { font-size: 10.5px; color: var(--text2); margin-top: 4px; }
.grade-tips-box { margin-top: 18px; padding: 14px; }
.grade-card:nth-of-type(1) { animation-delay: 0ms; }
.grade-card:nth-of-type(2) { animation-delay: 70ms; }
.grade-card:nth-of-type(3) { animation-delay: 140ms; }
.grade-card:nth-of-type(4) { animation-delay: 210ms; }
.grade-card:nth-of-type(n+5) { animation-delay: 280ms; }
.grade-card-left { flex: 1; min-width: 0; padding-right: 12px; }
.grade-card-name { font-size: 14px; font-weight: 500; color: var(--text1); }
.grade-bar-wrap { height: 3px; border-radius: 99px; background: var(--border); margin-top: 8px; overflow: hidden; }
.grade-bar { height: 100%; border-radius: 99px; width: 0; animation: growBar 1.3s 0.25s cubic-bezier(.4,0,.2,1) both; }
@keyframes growBar { to { width: var(--w, 100%); } }
.grade-card-right { text-align: right; flex-shrink: 0; }
.grade-card-letter { font-size: 24px; font-weight: 700; line-height: 1; }
.grade-card-pct { font-size: 11px; color: var(--text2); margin-top: 2px; font-weight: 500; }
.grade-a  { color: var(--green);  }
.grade-b  { color: var(--accent); }
.grade-c  { color: var(--amber);  }
.grade-df { color: var(--red);    }
/* No letter and nothing counted yet: a plain dash, not a failing-red one. */
.grade-none { color: var(--text2); }
/* "est." beside a letter estimated from the percentage (displayLetter). */
.grade-est {
  display: inline-block; margin-left: 3px; vertical-align: super;
  font-size: 9px; font-weight: 500; letter-spacing: 0.02em; color: var(--text2);
}
.grade-row { display: flex; justify-content: space-between; align-items: center; padding: 7px 0; border-bottom: 1px solid var(--grade-sep); }
.grade-row:last-child { border-bottom: none; }
.grade-name { font-size: 13px; color: var(--text1); }
.grade-score { font-size: 14px; font-weight: 600; color: var(--text1); }
.grade-score.good { color: var(--green); }
.grade-score.warn { color: var(--amber); }
.grade-score.bad  { color: var(--red);   }
.effort-badge {
  font-size: 10px; font-weight: 600; letter-spacing: 0.02em;
  padding: 2px 7px; border-radius: 99px; flex-shrink: 0; margin-left: 8px;
  color: var(--text2); background: var(--border2); white-space: nowrap;
}
.grade-open-row { display: flex; justify-content: space-between; align-items: center; padding: 7px 0; border-bottom: 1px solid var(--grade-sep); gap: 8px; }
.grade-open-row:last-child { border-bottom: none; }
.grade-open-name { font-size: 13px; color: var(--text1); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.grade-open-pts { font-size: 11px; color: var(--text2); flex-shrink: 0; }
.grade-letter { display: inline-block; font-size: 11px; font-weight: 700; padding: 2px 7px; border-radius: 6px; background: var(--grade-letter-bg); color: var(--text2); margin-left: 6px; }

/* Final calc */
.calc-row { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 10px; margin-bottom: 4px; }
.calc-label { font-size: 10px; font-weight: 600; color: var(--text2); text-transform: uppercase; letter-spacing: 0.06em; margin-bottom: 6px; }
.calc-input-wrap { position: relative; }
.calc-input {
  width: 100%; padding: 10px 22px 10px 8px;
  border-radius: 10px; border: 1px solid var(--border);
  font-size: 18px; font-weight: 700; color: var(--text1);
  background: var(--input-bg); outline: none; text-align: center;
  -moz-appearance: textfield; font-family: inherit;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.calc-input::-webkit-outer-spin-button, .calc-input::-webkit-inner-spin-button { -webkit-appearance: none; }
.calc-input:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.calc-unit { position: absolute; right: 8px; top: 50%; transform: translateY(-50%); font-size: 12px; color: var(--text2); pointer-events: none; font-weight: 500; }
.calc-result { border-radius: 12px; padding: 18px; text-align: center; margin-top: 12px; display: none; }
.calc-result-label { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; margin-bottom: 4px; }
.calc-result-score { font-size: 46px; font-weight: 700; line-height: 1; margin-bottom: 6px; letter-spacing: -1px; }
.calc-result-msg { font-size: 13px; line-height: 1.4; }

/* Settings */
.settings-input {
  width: 100%; padding: 12px 14px; border-radius: 12px; border: 1px solid var(--border);
  font-size: 14px; color: var(--text1); background: var(--input-bg); margin-bottom: 14px;
  outline: none; font-family: inherit; transition: border-color 0.15s, box-shadow 0.15s;
}
.settings-input:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.settings-btn {
  width: 100%; padding: 13px; border-radius: 12px; background: var(--btn-bg);
  color: var(--btn-fg); font-size: 14px; font-weight: 600; border: none; cursor: pointer; font-family: inherit;
  box-shadow: 0 2px 10px color-mix(in oklch, var(--btn-bg) 28%, transparent);
  transition: opacity 0.15s, transform 0.1s;
}
.settings-btn:hover { opacity: 0.9; }
.settings-btn:active { transform: scale(0.98); }
.settings-btn:disabled { opacity: 0.45; cursor: not-allowed; box-shadow: none; }
/* Same shape as .settings-btn, but its own color -- a dedicated class
   instead of an inline background override, so the shadow tint (which
   .settings-btn keys off --btn-bg) actually matches the button color
   instead of staying accent-colored under an orange/red fill. Red to
   match the deep-work X on the study tracker calendar. */
.deepwork-btn {
  width: 100%; padding: 13px; border-radius: 12px; background: var(--red);
  color: #fff; font-size: 14px; font-weight: 600; border: none; cursor: pointer; font-family: inherit;
  box-shadow: 0 2px 10px color-mix(in oklch, var(--red) 28%, transparent);
  transition: opacity 0.15s, transform 0.1s;
}
.deepwork-btn:hover { opacity: 0.9; }
.deepwork-btn:active { transform: scale(0.98); }
.settings-note { font-size: 12px; color: var(--text2); line-height: 1.6; margin-bottom: 14px; }
.connected-badge {
  display: inline-flex; align-items: center; gap: 7px;
  background: var(--connected-bg); border-radius: 10px;
  padding: 7px 12px; font-size: 13px; color: var(--connected-color); font-weight: 600; margin-bottom: 12px;
}
.connected-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--green); }
.sync-btn {
  width: 100%; padding: 13px; border-radius: 12px;
  background: var(--sync-btn-bg); color: var(--sync-btn-color); font-size: 14px; font-weight: 600;
  border: 1px solid var(--sync-btn-border); cursor: pointer; margin-bottom: 8px; font-family: inherit;
  transition: opacity 0.15s, transform 0.1s;
}
.sync-btn:hover:not(:disabled) { opacity: 0.85; }
.sync-btn:active:not(:disabled) { transform: scale(0.98); }
.sync-btn:disabled { background: var(--btn-secondary-bg); color: var(--text2); cursor: not-allowed; border-color: var(--border); }
.disconnect-btn {
  width: 100%; padding: 13px; border-radius: 12px;
  background: var(--disconnect-bg); color: var(--disconnect-color); font-size: 14px; font-weight: 600;
  border: 1px solid var(--disconnect-border); cursor: pointer; font-family: inherit;
  transition: opacity 0.15s, transform 0.1s;
}
.disconnect-btn:hover { opacity: 0.85; }
.disconnect-btn:active { transform: scale(0.98); }

/* Sign-out confirmation -- a real disclaimer instead of a native confirm(),
   so it matches the rest of the app instead of looking like a browser alert. */
#signout-confirm-overlay {
  display: none; position: fixed; inset: 0; z-index: 2300;
  background: oklch(0.1 0.02 var(--bg-h) / 0.55);
  backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px);
  align-items: center; justify-content: center; padding: 24px;
  animation: fadeUp 0.2s ease both;
}
#signout-confirm-card {
  background: var(--surface); border-radius: 16px; box-shadow: var(--shadow-md);
  width: 100%; max-width: 340px; padding: 26px 24px 22px; text-align: center;
  animation: wsCardIn 0.35s cubic-bezier(.16,1,.3,1) both;
}
#signout-confirm-icon {
  width: 46px; height: 46px; margin: 0 auto 14px; border-radius: 50%;
  background: var(--disconnect-bg); color: var(--disconnect-color);
  display: flex; align-items: center; justify-content: center;
}
#signout-confirm-icon svg { width: 22px; height: 22px; }
#signout-confirm-title { font-size: 16.5px; font-weight: 700; color: var(--text1); margin-bottom: 8px; }
#signout-confirm-text { font-size: 13px; color: var(--text2); line-height: 1.55; margin-bottom: 22px; }
#signout-confirm-actions { display: flex; gap: 10px; }
#signout-confirm-actions button {
  flex: 1; padding: 12px; border-radius: 10px; font-size: 14px; font-weight: 600;
  font-family: inherit; cursor: pointer; border: none; transition: opacity 0.15s, transform 0.1s;
}
#signout-confirm-actions button:active { transform: scale(0.97); }
#signout-cancel-btn { background: var(--btn-secondary-bg); color: var(--btn-secondary-color); }
#signout-cancel-btn:hover { opacity: 0.85; }
#signout-confirm-btn { background: var(--disconnect-color); color: #fff; }
#signout-confirm-btn:hover { opacity: 0.88; }
.sync-status { border-radius: 10px; padding: 10px 13px; font-size: 13px; margin-top: 10px; display: none; }
.sync-status.success { background: var(--success-bg); color: var(--success-color); display: block; }
.sync-status.error   { background: var(--error-bg);   color: var(--error-color);   display: block; }
.change-courses-btn {
  width: 100%; padding: 13px; border-radius: 12px;
  background: var(--btn-secondary-bg); color: var(--btn-secondary-color);
  font-size: 14px; font-weight: 600; border: none; cursor: pointer; margin-bottom: 8px; font-family: inherit;
  transition: background 0.15s, transform 0.1s;
}
.change-courses-btn:hover { background: var(--border2); }
.change-courses-btn:active { transform: scale(0.98); }

/* Empty / Loading */
.loading-box { text-align: center; padding: 48px 0; color: var(--text2); font-size: 14px; }
.loading-box::before {
  content: ''; display: block;
  width: 28px; height: 28px;
  border: 2.5px solid var(--border); border-top-color: var(--accent);
  border-radius: 50%; animation: spin 0.7s linear infinite; margin: 0 auto 14px;
}
.course-loading::before {
  content: ''; display: inline-block;
  width: 14px; height: 14px;
  border: 2px solid var(--border); border-top-color: var(--accent);
  border-radius: 50%; animation: spin 0.7s linear infinite;
  vertical-align: middle; margin-right: 8px;
}
.empty-box {
  background: var(--surface); border-radius: var(--card-radius);
  border: 1px solid var(--border); padding: 36px 24px; text-align: center;
}
.empty-icon {
  width: 52px; height: 52px; margin: 0 auto 14px; border-radius: 50%;
  background: var(--accent-soft); color: var(--accent-text);
  display: flex; align-items: center; justify-content: center;
}
.empty-icon svg { width: 24px; height: 24px; }
.empty-title { font-size: 15px; font-weight: 600; color: var(--text1); margin-bottom: 6px; }
.empty-sub { font-size: 13px; color: var(--text2); line-height: 1.5; }

/* Help */
.help-toggle-btn {
  width: 100%; background: none; border: none; cursor: pointer;
  display: flex; align-items: center; justify-content: space-between;
  font-size: 14px; font-weight: 500; color: var(--accent); padding: 0; text-align: left; font-family: inherit;
}
.help-toggle-arrow { font-size: 20px; transition: transform 0.2s; display: inline-block; color: var(--accent); }
.help-toggle-arrow.open { transform: rotate(90deg); }
.help-note { font-size: 13px; color: var(--text2); background: var(--surface2); border-radius: 10px; padding: 12px; margin-bottom: 14px; line-height: 1.5; }
.help-steps { display: flex; flex-direction: column; gap: 14px; }
.help-step { display: flex; align-items: flex-start; gap: 12px; }
.help-step-num { width: 24px; height: 24px; border-radius: 50%; background: var(--accent); color: var(--on-accent); font-size: 12px; font-weight: 700; display: flex; align-items: center; justify-content: center; flex-shrink: 0; margin-top: 2px; }
.help-step-text { font-size: 13px; color: var(--text1); line-height: 1.55; padding-top: 3px; }
.help-step-text strong { font-weight: 600; }

/* Spinner + btn loading */
@keyframes spin { to { transform: rotate(360deg); } }
.btn-loading { position: relative; color: transparent !important; pointer-events: none; }
.btn-loading::after {
  content: ''; position: absolute; top: 50%; left: 50%;
  width: 18px; height: 18px; margin: -9px 0 0 -9px;
  border: 2px solid rgba(255,255,255,0.35); border-top-color: #fff;
  border-radius: 50%; animation: spin 0.7s linear infinite;
}
.btn-loading.sync-btn::after { border-top-color: var(--green); border-color: var(--border); }
.btn-loading.onboard-btn::after { border-top-color: #fff; }

/* ===== BOTTOM NAV ===== */
.bottom-nav { display: none; overflow-x: auto; -webkit-overflow-scrolling: touch; }
.bottom-nav::-webkit-scrollbar { display: none; }
.nav-item {
  flex: 1 0 auto; min-width: 58px; display: flex; flex-direction: column; align-items: center;
  padding: 7px 2px 4px; background: none; border: none; cursor: pointer;
  color: var(--text2); gap: 3px; transition: color 0.18s; font-family: inherit;
  position: relative;
}
.nav-item.active { color: var(--accent); }
.nav-icon { position: relative; width: 46px; height: 28px; display: flex; align-items: center; justify-content: center; }
.nav-icon::before {
  content: ''; position: absolute; inset: 0;
  background: transparent; border-radius: 99px;
  transition: background 0.18s;
}
.nav-item.active .nav-icon::before { background: var(--accent-soft); }
.nav-icon svg { position: relative; z-index: 1; width: 20px; height: 20px; }
.nav-label { font-size: 9.5px; font-weight: 600; letter-spacing: 0.02em; }

/* ===== APPEARANCE SWATCHES (Settings) ===== */
.tweak-row { margin-bottom: 14px; }
.tweak-label { font-size: 11px; font-weight: 600; color: var(--text2); text-transform: uppercase; letter-spacing: 0.06em; margin-bottom: 8px; }
.tweak-swatches { display: flex; gap: 8px; flex-wrap: wrap; }
.swatch {
  width: 26px; height: 26px; border-radius: 50%; cursor: pointer;
  border: 2px solid transparent; transition: transform 0.15s, border-color 0.15s;
}
.swatch:hover { transform: scale(1.1); }
.swatch.active { border-color: var(--text1); }
.tweak-slider { width: 100%; accent-color: var(--accent); }

/* Welcome toast */
#welcome-toast { font-family: 'DM Sans', sans-serif !important; }

/* Brand panel needs real room to breathe -- below that it competes with
   the form column for space, so drop to a single centered column instead
   of squeezing both. */
@media (max-width: 900px) {
  .auth-page { grid-template-columns: 1fr; }
  .auth-brand { display: none; }
}

/* ===== MOBILE ===== */
@media (max-width: 600px) {
  body { padding: 0; align-items: stretch; }
  .app { max-width: 100%; }
  .auth-form-col { padding: 0 16px; }
  .auth-screen { max-width: none; }
  .onboard-flow-header { padding-left: 16px; padding-right: 16px; }
  .onboard-flow-panel { padding: 0 16px; }
  .onboard-title { font-size: 24px; }
  .main-app { display: flex; flex-direction: column; height: 100dvh; }
  .tabs { display: none; }
  .content { flex: 1; overflow-y: auto; -webkit-overflow-scrolling: touch; padding-bottom: calc(76px + env(safe-area-inset-bottom, 0px)); }
  .bottom-nav {
    display: flex; position: fixed; bottom: 0; left: 0; right: 0;
    background: var(--surface); border-top: 1px solid var(--border);
    padding-bottom: env(safe-area-inset-bottom, 0px);
    z-index: 100; backdrop-filter: blur(24px); -webkit-backdrop-filter: blur(24px);
  }
}

/* Animate page entry */
.page.active { animation: fadeUp 0.4s ease both; }
@keyframes fadeUp {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes fadeIn  { from { opacity: 0; } to { opacity: 1; } }
@keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } }
/* A noticeably bigger, snappier entrance/exit than fadeUp -- for a full
   detail view taking over the screen (assignment/grade/syllabus/etc.),
   fadeUp's 6px nudge reads as no animation at all. No blur/scale here
   (unlike wsCardIn below) since this rides on a large, often long,
   scrolling content area rather than a small fixed-size card -- blur+scale
   on something that big is the kind of thing that visibly stutters on a
   weaker device. */
@keyframes detailSlideUp   { from { opacity: 0; transform: translateY(28px); } to   { opacity: 1; transform: translateY(0); } }
@keyframes detailSlideDown { from { opacity: 1; transform: translateY(0); }   to   { opacity: 0; transform: translateY(18px); } }
/* Same idea, tuned for a small fixed-size card (focus/deep-work timer). */
@keyframes cardPopOut {
  from { opacity: 1; transform: translateY(0) scale(1); filter: blur(0); }
  to   { opacity: 0; transform: translateY(10px) scale(0.96); filter: blur(6px); }
}

/* ── Welcome Screen ── */
#ws-overlay {
  position: fixed; inset: 0; z-index: 2000;
  background: var(--bg);
  display: flex; align-items: center; justify-content: center;
  padding: 24px; overflow: hidden;
  opacity: 1; transition: opacity 0.7s ease;
  isolation: isolate;
}
#ws-overlay.fade-out { opacity: 0; }
/* No card, no box -- the greeting lives directly on the page, flat black
   like the rest of the app, so it reads as its own screen (the way a
   splash/landing moment should) rather than a popup. */
#ws-card {
  width: 100%; max-width: 520px;
  padding: 20px 12px;
  position: relative;
  text-align: center;
  animation: wsCardIn 0.65s cubic-bezier(.16,1,.3,1) both;
}
@keyframes wsCardIn {
  0%   { opacity: 0; transform: translateY(26px) scale(0.96); filter: blur(10px); }
  100% { opacity: 1; transform: translateY(0) scale(1); filter: blur(0); }
}
/* Everything below has to actually fit in the viewport -- #ws-overlay is
   overflow:hidden (a splash screen that scrolls looks broken), so on short
   viewports the type scale and gaps compress instead of quietly relying on
   a scrollbar to bail it out. */
@media (max-height: 780px) {
  #ws-overlay { padding: 16px; }
  #ws-card { padding: 10px 12px; }
  #ws-heading { font-size: 28px; margin-bottom: 6px; }
  #ws-date { font-size: 15px; margin-bottom: 6px; }
  #ws-streak { margin: 0 auto 12px; padding: 6px 13px; font-size: 14px; }
  #ws-subtitle { font-size: 16px; margin-bottom: 16px; }
  #ws-summary { gap: 6px; margin: -6px 0 14px; }
  .ws-summary-row { padding: 9px 12px; font-size: 13px; }
  #ws-sync-btn { padding: 15px; font-size: 15.5px; }
  #ws-welcome { min-height: min(480px, 62dvh); }
}
@media (max-height: 620px) {
  #ws-heading { font-size: 23px; }
  #ws-date { font-size: 13.5px; }
  #ws-streak { font-size: 12.5px; padding: 5px 12px; }
  #ws-subtitle { font-size: 14px; margin-bottom: 10px; }
  #ws-summary-row, .ws-summary-row { padding: 7px 10px; }
  #ws-welcome { min-height: min(420px, 56dvh); }
}
/* The welcome state gets real top/bottom structure -- greeting content
   centered in the available space, sync action pinned to the bottom edge --
   instead of everything bunched into one dense cluster the way it looked
   when a card boundary made that cluster feel intentional. Syncing/result
   states aren't affected; they stay simply centered. */
#ws-welcome { display: flex; flex-direction: column; min-height: min(560px, 68dvh); }
#ws-greeting-block { flex: 1; display: flex; flex-direction: column; justify-content: center; }
#ws-action-block { flex-shrink: 0; }
@media (prefers-reduced-motion: reduce) {
  #ws-card { animation: fadeUp 0.25s ease both; }
}
#ws-close {
  position: fixed; top: 20px; right: 20px; z-index: 1;
  background: var(--surface2); border: none; cursor: pointer;
  width: 34px; height: 34px; border-radius: 50%;
  font-size: 16px; color: var(--text2);
  display: flex; align-items: center; justify-content: center;
  font-family: inherit; line-height: 1;
  transition: background 0.15s, color 0.15s, transform 0.3s cubic-bezier(.34,1.56,.64,1);
  animation: fadeUp 0.4s ease both; animation-delay: 0.05s;
}
#ws-close:hover { background: var(--border); color: var(--text1); transform: rotate(90deg); }
@media (prefers-reduced-motion: reduce) { #ws-close { animation: none; } }
/* Pinned to its own corner (mirroring #ws-close on the opposite side) now
   that the greeting isn't boxed in a card -- reads like a page header, not
   part of the centered content stack. */
#ws-logo-row {
  display: inline-flex; align-items: center; gap: 10px; position: fixed; top: 24px; left: 24px; z-index: 1;
  animation: fadeUp 0.5s cubic-bezier(.16,1,.3,1) both; animation-delay: 0.08s;
}
#ws-logo-row .logo-mark {
  width: 25px; height: 25px; top: -11px; left: 0;
  animation: wsLogoPop 0.6s cubic-bezier(.34,1.56,.64,1) both; animation-delay: 0.1s;
}
@media (max-width: 420px) {
  #ws-logo-row .logo-mark { width: 20px; height: 20px; top: -9px; }
}
@keyframes wsLogoPop {
  from { opacity: 0; transform: scale(0.3) rotate(-70deg); }
  to   { opacity: 1; transform: scale(1) rotate(-24deg); }
}
#ws-logo-name {
  font-family: 'Playfair Display', 'DM Sans', serif; font-size: 25px; font-weight: 700;
  color: var(--text1); padding-left: 20px;
}
#ws-logo-name em { font-style: normal; color: inherit; }
@media (max-width: 420px) {
  #ws-logo-name { font-size: 20px; padding-left: 16px; }
}
#ws-heading {
  font-size: 38px; font-weight: 800; color: var(--accent); margin-bottom: 10px;
  line-height: 1.15; letter-spacing: -0.7px;
  animation: wsHeadingReveal 0.6s cubic-bezier(.16,1,.3,1) both; animation-delay: 0.16s;
}
@media (max-width: 400px) { #ws-heading { font-size: 30px; } }
@keyframes wsHeadingReveal {
  from { opacity: 0; transform: translateY(12px); filter: blur(5px); }
  to   { opacity: 1; transform: translateY(0); filter: blur(0); }
}
#ws-date {
  font-size: 18px; color: var(--text2); margin-bottom: 12px;
  animation: fadeUp 0.5s cubic-bezier(.16,1,.3,1) both; animation-delay: 0.22s;
}
#ws-streak {
  display: none; align-items: center; gap: 7px; font-size: 17px; font-weight: 700;
  color: var(--accent-text); background: var(--accent-soft); border-radius: 99px;
  padding: 8px 16px; margin: 0 auto 22px; width: fit-content;
  animation: wsBadgePop 0.5s cubic-bezier(.34,1.56,.64,1) both; animation-delay: 0.28s;
}
.ws-flame { display: inline-block; animation: wsFlameFlicker 1.6s ease-in-out infinite; }
@keyframes wsFlameFlicker {
  0%, 100% { transform: scale(1) rotate(0deg); }
  25%      { transform: scale(1.12) rotate(-4deg); }
  50%      { transform: scale(0.96) rotate(3deg); }
  75%      { transform: scale(1.08) rotate(-2deg); }
}
#ws-subtitle {
  font-size: 19px; color: var(--text2); margin-bottom: 30px; line-height: 1.45;
  animation: fadeUp 0.5s cubic-bezier(.16,1,.3,1) both; animation-delay: 0.34s;
}
@media (prefers-reduced-motion: reduce) {
  #ws-logo-row, #ws-logo-row .logo-mark, #ws-heading, #ws-date, #ws-streak, #ws-subtitle { animation: none; }
  .ws-flame { animation: none; }
}
#ws-summary { display: flex; flex-direction: column; gap: 8px; margin: -12px 0 22px; }
.ws-summary-row {
  display: flex; align-items: center; gap: 12px; padding: 13px 15px;
  border-radius: 12px; background: var(--surface2); font-size: 14.5px; font-weight: 600; color: var(--text1);
  animation: wsSummaryPop 0.45s cubic-bezier(.16,1,.3,1) both;
}
.ws-summary-row:nth-child(1) { animation-delay: 0.4s; }
.ws-summary-row:nth-child(2) { animation-delay: 0.47s; }
.ws-summary-row:nth-child(3) { animation-delay: 0.54s; }
.ws-summary-row .ws-summary-icon {
  width: 22px; height: 22px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--border2); color: var(--text2);
  animation: wsBadgePop 0.4s cubic-bezier(.34,1.56,.64,1) both;
}
.ws-summary-row .ws-summary-icon svg { width: 12px; height: 12px; }
/* Icon lands a beat after its row slides in, so the reveal feels like two
   connected motions instead of the whole row popping in as one flat unit. */
.ws-summary-row:nth-child(1) .ws-summary-icon { animation-delay: 0.58s; }
.ws-summary-row:nth-child(2) .ws-summary-icon { animation-delay: 0.65s; }
.ws-summary-row:nth-child(3) .ws-summary-icon { animation-delay: 0.72s; }
@media (prefers-reduced-motion: reduce) {
  .ws-summary-row, .ws-summary-row .ws-summary-icon { animation: none; }
}
.ws-summary-row.ws-summary-announce {
  background: var(--accent-soft); color: var(--accent-text);
  box-shadow: inset 0 0 0 1px var(--accent-soft);
}
.ws-summary-row.ws-summary-announce .ws-summary-icon { background: var(--accent); color: var(--on-accent); }
@keyframes wsSummaryPop {
  0%   { transform: scale(0.94); opacity: 0; }
  100% { transform: scale(1); opacity: 1; }
}

/* ===== REWARD BAR (immediate positive feedback) =====
   A full-width neutral strip that slides up from the bottom edge instead of
   a small colored pill floating over the content -- bigger, calmer, and out
   of the way of the bottom nav on mobile. */
.reward-toast {
  position: fixed; left: 0; right: 0; bottom: 0; width: 100%;
  background: var(--surface); border-top: 1px solid var(--border2); color: var(--text1);
  display: flex; align-items: center; justify-content: center; gap: 12px;
  padding: 16px 24px; box-shadow: 0 -10px 28px rgba(0,0,0,0.18);
  z-index: 10000; opacity: 0; pointer-events: none;
  transform: translateY(100%);
  transition: opacity 0.4s cubic-bezier(.22,1,.36,1), transform 0.4s cubic-bezier(.22,1,.36,1);
}
.reward-toast-show { opacity: 1; transform: translateY(0); }
.reward-toast-icon {
  width: 26px; height: 26px; border-radius: 50%; background: var(--surface2); color: var(--text2);
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
}
.reward-toast-icon svg { width: 14px; height: 14px; }
.reward-toast-text { font-size: 15px; font-weight: 600; text-align: center; }
@media (max-width: 600px) {
  .reward-toast { bottom: calc(76px + env(safe-area-inset-bottom, 0px)); box-shadow: 0 -6px 20px rgba(0,0,0,0.18); }
}
#ws-sync-btn {
  width: 100%; padding: 20px; background: var(--btn-bg); color: var(--btn-fg);
  border: none; border-radius: 14px; font-size: 17px; font-weight: 700;
  cursor: pointer; font-family: inherit; transition: opacity 0.15s, transform 0.12s;
  position: relative; overflow: hidden;
  display: flex; align-items: center; justify-content: center; gap: 9px;
  animation: fadeUp 0.5s cubic-bezier(.16,1,.3,1) both; animation-delay: 0.85s;
}
#ws-sync-btn:hover { opacity: 0.88; }
#ws-sync-btn:active { transform: scale(0.97); }
#ws-sync-btn:disabled { opacity: 0.6; cursor: default; }
#ws-sync-btn-icon { width: 19px; height: 19px; flex-shrink: 0; }
#ws-sync-btn-icon.spinning { animation: wsSyncIconSpin 0.8s linear infinite; }
@keyframes wsSyncIconSpin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { #ws-sync-btn-icon.spinning { animation: none; } }
#ws-sync-btn::after {
  content: ''; position: absolute; top: 0; left: -60%; width: 45%; height: 100%;
  background: linear-gradient(120deg, transparent, oklch(1 0 0 / 0.35), transparent);
  animation: wsBtnShimmer 3.4s ease-in-out 1.4s infinite;
}
@keyframes wsBtnShimmer {
  0%, 15%  { left: -60%; }
  55%, 100% { left: 130%; }
}
.ws-skip {
  background: none; border: none; color: var(--text2); font-size: 13px; cursor: pointer;
  font-family: inherit; display: block; margin: 14px auto 0; transition: color 0.15s;
  animation: fadeUp 0.5s cubic-bezier(.16,1,.3,1) both; animation-delay: 0.92s;
}
.ws-skip:hover { color: var(--text1); }
@media (prefers-reduced-motion: reduce) {
  #ws-sync-btn, .ws-skip { animation: none; }
  #ws-sync-btn::after { animation: none; display: none; }
}
#ws-result.ws-anim-in { animation: fadeUp 0.4s cubic-bezier(.16,1,.3,1) both; }

/* Dashboard "drop-in" -- assignment cards fall into place with a little bounce
   right as the sync popup closes, so the freshly-synced work visibly lands
   instead of just being there when the overlay disappears. */
@keyframes cardDrop {
  0%   { opacity: 0; transform: translateY(-22px) rotate(-1.5deg); }
  55%  { opacity: 1; transform: translateY(5px) rotate(1deg); }
  100% { transform: translateY(0) rotate(0deg); }
}
.drop-in .card { animation: cardDrop 0.55s cubic-bezier(.34,1.56,.64,1) both; }
.drop-in .card:nth-of-type(1)   { animation-delay: 0ms; }
.drop-in .card:nth-of-type(2)   { animation-delay: 70ms; }
.drop-in .card:nth-of-type(3)   { animation-delay: 140ms; }
.drop-in .card:nth-of-type(n+4) { animation-delay: 210ms; }
/* Syncing screen: a circular progress ring (matching the ring's own shape,
   not a squared-off halo that would poke past it at the corners) plus a big
   percentage number give something concrete to watch fill up. The logo mark
   sits centered inside with room to spare, breathing gently on its own. */
.ws-sync-logo-wrap {
  position: relative; width: 128px; height: 128px; margin: 6px auto 4px;
  display: flex; align-items: center; justify-content: center;
}
.ws-sync-progress-ring {
  position: absolute; inset: 0; width: 128px; height: 128px;
  transform: rotate(-90deg);
}
.ws-sync-progress-track { fill: none; stroke: var(--border2); stroke-width: 5; }
.ws-sync-progress-fill {
  fill: none; stroke: var(--accent); stroke-width: 5; stroke-linecap: round;
  stroke-dasharray: 283; stroke-dashoffset: 283;
  transition: stroke-dashoffset 0.3s ease-out;
}
/* Spin lives on the wrapper so it can run forever, uninterrupted; tick (a
   bounce on each status change) lives on the mark itself and gets toggled
   via a class -- keeping them on separate elements means restarting the tick
   animation never resets the spin's rotation partway through. */
.ws-sync-logo-spin { animation: wsLogoSpin 2.2s linear infinite; display: flex; }
.ws-sync-logo-mark {
  position: relative; width: 56px; height: 56px; border-radius: 16px;
  background: var(--accent); display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  box-shadow: 0 6px 22px color-mix(in oklch, var(--accent) 40%, transparent);
}
.ws-sync-logo-mark svg { width: 30px; height: 30px; color: var(--on-accent); }
.ws-sync-logo-mark.tick { animation: wsLogoTick 0.45s cubic-bezier(.34,1.56,.64,1); }
@keyframes wsLogoSpin {
  from { rotate: 0deg; }
  to   { rotate: 360deg; }
}
@keyframes wsLogoTick {
  0%   { scale: 1; }
  40%  { scale: 1.18; }
  70%  { scale: 0.94; }
  100% { scale: 1; }
}
@keyframes wsLogoBreathe {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.06); }
}
#ws-sync-percent {
  font-size: 34px; font-weight: 800; color: var(--text1); letter-spacing: -0.5px;
  font-variant-numeric: tabular-nums; margin-top: 4px;
}
#ws-syncing-msg { margin-top: 4px; font-size: 13.5px; color: var(--text2); }
.ws-check-badge {
  width: 56px; height: 56px; border-radius: 50%; background: var(--green-soft);
  display: flex; align-items: center; justify-content: center; margin: 0 auto 16px;
  animation: wsBadgePop 0.5s cubic-bezier(.34,1.56,.64,1) both;
}
.ws-check-badge svg { width: 30px; height: 30px; }
.ws-check-path { stroke-dasharray: 20; stroke-dashoffset: 20; animation: wsCheckDraw 0.4s 0.2s cubic-bezier(.65,0,.35,1) forwards; }
@keyframes wsBadgePop { from { transform: scale(0.4); opacity: 0; } to { transform: scale(1); opacity: 1; } }
@keyframes wsCheckDraw { to { stroke-dashoffset: 0; } }
#ws-result-count { font-size: 20px; font-weight: 700; color: var(--text1); margin-bottom: 6px; text-align: center; }
#ws-result-sub { font-size: 13px; color: var(--text2); margin-bottom: 22px; line-height: 1.45; text-align: center; }

/* "Nothing new" gets its own quieter, ambient moment instead of the same
   checkmark-and-caption used when there's actually something to review. */
#ws-result.ws-result-calm .ws-check-badge { position: relative; }
#ws-result.ws-result-calm .ws-check-badge::before {
  content: ''; position: absolute; inset: -20px; border-radius: 50%; z-index: -1;
  background: radial-gradient(circle, var(--accent-soft) 0%, transparent 70%);
  animation: wsCalmGlow 2.4s ease-in-out infinite;
}
@keyframes wsCalmGlow {
  0%, 100% { opacity: 0.45; transform: scale(0.85); }
  50%      { opacity: 1; transform: scale(1.2); }
}
#ws-result.ws-result-calm #ws-result-count { font-size: 27px; letter-spacing: -0.4px; }
#ws-result.ws-result-calm #ws-result-sub { font-size: 12px; font-style: italic; opacity: 0.75; }
#ws-view-btn {
  width: 100%; padding: 14px; background: var(--accent-soft); color: var(--accent-text);
  border: 1px solid var(--accent-soft); border-radius: 12px; font-size: 14px; font-weight: 600;
  cursor: pointer; font-family: inherit; transition: opacity 0.15s; margin-bottom: 0;
}
#ws-view-btn:hover { opacity: 0.8; }
/* State 3: sync failed -- same badge/title/sub rhythm as the success result,
   just in the error palette, so a failure reads as a designed state instead
   of the calm "all caught up" message quietly (and wrongly) standing in for it. */
.ws-error-badge {
  width: 56px; height: 56px; border-radius: 50%; background: var(--disconnect-bg);
  display: flex; align-items: center; justify-content: center; margin: 0 auto 16px;
  animation: wsBadgePop 0.5s cubic-bezier(.34,1.56,.64,1) both;
}
.ws-error-badge svg { width: 28px; height: 28px; }
#ws-error-title { font-size: 20px; font-weight: 700; color: var(--text1); margin-bottom: 6px; text-align: center; }
#ws-error-sub { font-size: 13px; color: var(--text2); margin-bottom: 10px; line-height: 1.45; text-align: center; }
#ws-error-detail {
  font-size: 11.5px; color: var(--text2); text-align: center; margin-bottom: 20px;
  font-family: ui-monospace, monospace; opacity: 0.7; word-break: break-word;
}
#ws-error-actions { display: flex; flex-direction: column; gap: 10px; margin-bottom: 4px; }
#ws-error-retry-btn {
  width: 100%; padding: 15px; background: var(--btn-bg); color: var(--btn-fg);
  border: none; border-radius: 12px; font-size: 15px; font-weight: 700;
  cursor: pointer; font-family: inherit; transition: opacity 0.15s, transform 0.1s;
}
#ws-error-retry-btn:hover { opacity: 0.88; }
#ws-error-retry-btn:active { transform: scale(0.97); }
/* Report panel -- quick preset chips for the common cases (one click, no
   typing) plus a free-text box for anything else, instead of a single canned
   "Report this problem" button that can't say what's actually wrong. */
#ws-error-report-panel {
  text-align: left; background: var(--surface2); border-radius: 14px;
  padding: 16px; margin-bottom: 4px;
}
#ws-error-report-label { font-size: 13px; font-weight: 700; color: var(--text1); margin-bottom: 10px; }
#ws-error-quick-options { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; }
.ws-quick-report-btn {
  padding: 8px 13px; border-radius: 99px; font-size: 12.5px; font-weight: 600;
  background: var(--surface); color: var(--text1); border: 1px solid var(--border2);
  cursor: pointer; font-family: inherit; transition: background 0.15s, border-color 0.15s, opacity 0.15s;
}
.ws-quick-report-btn:hover { border-color: var(--accent); color: var(--accent-text); }
.ws-quick-report-btn:disabled { cursor: default; opacity: 0.7; }
.ws-quick-report-btn.reported { background: var(--green-soft); color: var(--green); border-color: transparent; }
#ws-error-report-text { margin-bottom: 10px; }
#ws-error-report-send-btn {
  width: 100%; padding: 12px; background: var(--disconnect-bg); color: var(--disconnect-color);
  border: 1px solid var(--disconnect-border); border-radius: 10px; font-size: 13.5px; font-weight: 600;
  cursor: pointer; font-family: inherit; transition: opacity 0.15s;
}
#ws-error-report-send-btn:hover { opacity: 0.85; }
#ws-error-report-send-btn:disabled { cursor: default; opacity: 0.7; }
#ws-error-report-status { font-size: 12px; margin-top: 8px; text-align: center; min-height: 15px; }
#ws-list-overlay {
  position: fixed; inset: 0; z-index: 2100;
  background: var(--bg); overflow-y: auto;
}
/* A static `animation` on the base rule only ever plays once (the first
   time the browser computes its style), not every time display flips from
   none to block -- so this has to be a class, removed/reflowed/re-added on
   each open, to actually fade in instead of just snapping into view. */
#ws-list-overlay.ws-anim-in { animation: fadeUp 0.25s cubic-bezier(.16,1,.3,1) both; }
#ws-list-inner {
  max-width: 500px; margin: 0 auto; padding: 20px 20px 40px;
}
#ws-list-header {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 18px;
}
#ws-list-title { font-size: 18px; font-weight: 700; color: var(--text1); }
#ws-list-close {
  background: var(--surface2); border: none; cursor: pointer;
  width: 30px; height: 30px; border-radius: 50%;
  font-size: 16px; color: var(--text2);
  display: flex; align-items: center; justify-content: center;
  font-family: inherit;
}
#ws-list-close:hover { background: var(--border); color: var(--text1); }
.ws-a-card {
  background: var(--surface); border-radius: var(--card-radius);
  border: 1px solid var(--border); padding: 14px 16px; margin-bottom: 10px;
}
.ws-a-title { font-size: 14px; font-weight: 600; color: var(--text1); margin-bottom: 4px; }
.ws-a-meta { font-size: 12px; color: var(--text2); }
.card-title-link { color: inherit; text-decoration: none; cursor: pointer; }
.card-title-link:hover { color: var(--accent); }
.canvas-link {
  display: inline-block; margin-top: 7px;
  font-size: 11.5px; font-weight: 500; color: var(--text2);
  text-decoration: none; letter-spacing: 0.01em;
}
.canvas-link:hover { color: var(--accent); }

/* ===== AUTH BACKDROP =====
   Flat solid black, no texture or glow -- Kevin wants the login page
   background plain, not decorated. */
.auth-bg-glow {
  position: fixed; inset: 0; z-index: -1; overflow: hidden; pointer-events: none;
  background: #000;
}
/* Grad caps raining down behind the login form -- pure ambience, so kept
   soft enough to never compete with the actual sign-in fields. */
.auth-float-cap {
  position: absolute; top: 0;
  color: #ffffff;
  animation: authCapRain var(--dur, 14s) linear infinite;
  animation-delay: var(--delay, 0s);
  will-change: transform, opacity;
}
.auth-float-cap svg { width: 100%; height: 100%; display: block; }
@keyframes authCapRain {
  0%   { transform: translateY(-12vh) rotate(-8deg); opacity: 0; }
  10%  { opacity: 1; }
  85%  { opacity: 1; }
  100% { transform: translateY(112vh) rotate(16deg); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .auth-float-cap { animation: none; opacity: 0.15; }
}

/* Onboarding reuses the same fixed backdrop as login, but swaps the raining
   caps (fine as login ambience, too busy/literal behind a multi-step form)
   for a quiet accent-colored glow centered behind the card. */
.auth-bg-glow.onboard-glow .auth-float-cap { display: none; }
.auth-bg-glow.onboard-glow::before {
  content: '';
  position: absolute; top: 50%; left: 50%;
  width: min(1100px, 150vw); height: min(1100px, 150vw);
  transform: translate(-50%, -50%);
  background: radial-gradient(circle, color-mix(in oklch, var(--accent) 45%, transparent) 0%, transparent 68%);
  filter: blur(10px);
}

/* ===== HOME ===== */
#home-greeting { margin-bottom: 6px; }
.home-greeting-eyebrow {
  font-size: 15px; font-weight: 700; color: var(--text1); letter-spacing: -0.2px;
  margin-bottom: 4px;
  animation: fadeUp 0.5s cubic-bezier(.16,1,.3,1) both;
}
/* One dominant number instead of three equal KPI boxes -- whichever count
   is most urgent (overdue, then due-this-week, then a calm all-caught-up
   state) leads, with the rest folded into a quiet sentence underneath. */
.home-hero-stat {
  display: flex; align-items: baseline; gap: 10px; margin-top: 16px;
  animation: fadeUp 0.5s cubic-bezier(.16,1,.3,1) both; animation-delay: 120ms;
}
.home-hero-num {
  font-size: 46px; font-weight: 800; letter-spacing: -1.5px; line-height: 1;
  font-variant-numeric: tabular-nums; color: var(--text1); display: inline-block;
}
.home-hero-num.hero-overdue { color: var(--red); }
.home-hero-num.hero-calm { color: var(--green); }
.home-hero-num.stat-pop { animation: statPop 0.9s cubic-bezier(.22,1,.36,1); }
.home-hero-label { font-size: 14.5px; font-weight: 600; color: var(--text2); }
.home-hero-sub {
  font-size: 12.5px; color: var(--text2); margin-top: 6px;
  animation: fadeUp 0.5s cubic-bezier(.16,1,.3,1) both; animation-delay: 200ms;
}
@keyframes greetReveal {
  from { opacity: 0; transform: translateY(14px); filter: blur(6px); }
  to   { opacity: 1; transform: translateY(0); filter: blur(0); }
}
@media (max-width: 600px) {
  .home-hero-num { font-size: 36px; }
}
.home-quicklinks { display: grid; grid-template-columns: 1fr 1fr; gap: 9px; }
.home-qlink {
  display: flex; align-items: center; gap: 10px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--card-radius);
  padding: 13px 14px; cursor: pointer; box-shadow: var(--shadow-sm);
  font-family: inherit; font-size: 13px; font-weight: 600; color: var(--text1);
  text-decoration: none; overflow: hidden;
  transition: border-color 0.15s, transform 0.15s, box-shadow 0.15s;
  animation: cardIn 0.5s cubic-bezier(.16,1,.3,1) both;
}
.home-qlink:nth-of-type(1) { animation-delay: 0ms; }
.home-qlink:nth-of-type(2) { animation-delay: 60ms; }
.home-qlink:nth-of-type(3) { animation-delay: 120ms; }
.home-qlink:nth-of-type(n+4) { animation-delay: 180ms; }
.home-qlink:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); }
.home-qlink:active { transform: scale(0.98) translateY(0); }
.home-qlink span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.home-qlink-icon {
  width: 30px; height: 30px; border-radius: 9px; background: var(--accent-soft);
  color: var(--accent); display: flex; align-items: center; justify-content: center; flex-shrink: 0;
  font-size: 15px; font-weight: 700;
}
.home-qlink-icon svg { width: 16px; height: 16px; }
.home-qlink-icon img { width: 16px; height: 16px; border-radius: 3px; }

/* ===== CUSTOM LINKS (Links tab + Home) ===== */
.link-card {
  transition: opacity 0.25s ease, transform 0.25s ease, max-height 0.25s ease, padding 0.25s ease, margin 0.25s ease, border-color 0.15s;
  max-height: 80px; overflow: hidden;
}
.link-card:active { transform: scale(0.98); }
.link-card.removing {
  opacity: 0; transform: translateX(8px); max-height: 0; padding-top: 0; padding-bottom: 0; margin-bottom: 0; border-width: 0;
}

/* Links tab tutorial: a small multi-slide walkthrough (one idea per slide)
   instead of one card cramming every step in at once -- shows on first visit,
   replayable any time via the button below the form. Rendered as a centered
   modal over a blurred backdrop rather than sitting inline in the page. */
.links-tutorial-overlay {
  display: none; position: fixed; inset: 0; z-index: 2200;
  background: rgba(0,0,0,0.45);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  align-items: center; justify-content: center; padding: 24px;
  animation: fadeUp 0.2s ease;
}
.links-tutorial-overlay.show { display: flex; }
.links-tutorial-card {
  animation: cardIn 0.35s cubic-bezier(.16,1,.3,1) both;
  width: 100%; max-width: 620px; box-shadow: var(--shadow-md);
  position: relative; display: flex; overflow: hidden;
}
.links-tutorial-card #links-tutorial-dismiss { position: absolute; top: 12px; right: 12px; z-index: 2; }
.links-tutorial-col { flex: 1 1 50%; min-width: 0; display: flex; flex-direction: column; text-align: left; padding-right: 20px; }
.links-tutorial-slide-icon {
  width: 48px; height: 48px; border-radius: 14px; background: var(--accent-soft); color: var(--accent);
  display: flex; align-items: center; justify-content: center; font-size: 22px; margin: 6px 0 14px;
  animation: wsBadgePop 0.4s cubic-bezier(.34,1.56,.64,1) both;
}
.links-tutorial-slide-title { font-size: 18px; font-weight: 700; color: var(--text1); margin-bottom: 6px; }
.links-tutorial-slide-body { font-size: 13.5px; color: var(--text2); line-height: 1.55; }
.links-tutorial-nav { display: flex; gap: 8px; margin-top: auto; padding-top: 16px; }
.links-tutorial-example {
  flex: 1 1 50%; min-width: 0; background: var(--bg); border-radius: 12px;
  display: flex; align-items: center; justify-content: center; padding: 16px;
}

/* 16:9-ish widescreen card: two columns side by side (text | live example). */
@media (min-width: 601px) {
  .links-tutorial-card { aspect-ratio: 16 / 9; padding: 24px; align-items: stretch; }
}
/* Too narrow for a real 16:9 split -- stack the example under the text instead. */
@media (max-width: 600px) {
  .links-tutorial-card { max-width: 380px; flex-direction: column; }
  .links-tutorial-col { padding-right: 0; }
  .links-tutorial-example { margin-top: 16px; min-height: 90px; }
}

/* Slide transition between tutorial steps -- direction matches Next vs Back
   instead of the text and example just snapping to their new values. */
.tut-slide-next { animation: tutSlideInFromRight 0.5s cubic-bezier(.16,1,.3,1) both; }
.tut-slide-back { animation: tutSlideInFromLeft 0.5s cubic-bezier(.16,1,.3,1) both; }
@keyframes tutSlideInFromRight { from { opacity: 0; transform: translateX(100vw); } to { opacity: 1; transform: translateX(0); } }
@keyframes tutSlideInFromLeft  { from { opacity: 0; transform: translateX(-100vw); } to { opacity: 1; transform: translateX(0); } }
/* Old slide eases out first instead of vanishing the same frame the new one
   pops in -- reads as one continuous motion rather than a jump-cut. Distance
   is viewport-wide (not just the card) so it reads as a full page swipe. */
.tut-slide-out-next { animation: tutSlideOutToLeft 0.3s cubic-bezier(.4,0,1,1) both; }
.tut-slide-out-back { animation: tutSlideOutToRight 0.3s cubic-bezier(.4,0,1,1) both; }
@keyframes tutSlideOutToLeft  { from { opacity: 1; transform: translateX(0); } to { opacity: 0; transform: translateX(-100vw); } }
@keyframes tutSlideOutToRight { from { opacity: 1; transform: translateX(0); } to { opacity: 0; transform: translateX(100vw); } }

/* Per-slide mock illustrations -- non-interactive, just showing what the real
   thing looks like filled in, instead of describing it in prose alone. */
.tut-ex-browser { width: 100%; max-width: 220px; border-radius: 10px; background: var(--surface); border: 1px solid var(--border2); overflow: hidden; box-shadow: var(--shadow-sm); }
.tut-ex-browser-dots { display: flex; gap: 4px; padding: 8px 10px 6px; }
.tut-ex-browser-dots span { width: 6px; height: 6px; border-radius: 50%; background: var(--border2); display: block; }
.tut-ex-browser-url { margin: 0 10px 10px; padding: 6px 8px; background: var(--input-bg); border-radius: 6px; font-size: 10.5px; color: var(--text2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tut-ex-copied { margin: 0 10px 10px; font-size: 11px; font-weight: 700; color: var(--green); }

.tut-ex-field-mock { width: 100%; max-width: 200px; }
.tut-ex-field-label { font-size: 10px; font-weight: 700; color: var(--text2); text-transform: uppercase; letter-spacing: 0.07em; margin-bottom: 6px; }
.tut-ex-field-value { padding: 12px 15px; border-radius: 12px; background: var(--input-bg); border: 1px solid var(--accent); color: var(--text1); font-size: 14px; font-weight: 500; box-shadow: 0 0 0 3px var(--accent-soft); }

.tut-ex-form { width: 100%; max-width: 200px; display: flex; flex-direction: column; gap: 8px; }
.tut-ex-input { padding: 10px 13px; border-radius: 10px; background: var(--input-bg); border: 1px solid var(--border2); color: var(--text1); font-size: 12.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tut-ex-btn { padding: 10px; border-radius: 10px; background: var(--accent); color: var(--on-accent); font-size: 12.5px; font-weight: 700; text-align: center; }

.tut-ex-chip {
  display: inline-flex; align-items: center; gap: 8px; padding: 12px 18px; border-radius: 14px;
  background: var(--surface); border: 1px solid var(--border2); box-shadow: var(--shadow-sm);
  font-size: 13px; font-weight: 600; color: var(--text1);
  animation: wsLogoBreathe 1.8s ease-in-out infinite;
}
.tut-ex-chip-icon { width: 26px; height: 26px; border-radius: 50%; background: var(--accent-soft); color: var(--accent); display: flex; align-items: center; justify-content: center; font-size: 13px; }

/* A couple of gentle pulses on the actual inputs so the tutorial points at
   where to act instead of just describing it. */
.field-pulse { animation: fieldPulse 1.1s ease-in-out 2; }
@keyframes fieldPulse {
  0%, 100% { box-shadow: 0 0 0 0 var(--accent-soft); }
  50%      { box-shadow: 0 0 0 5px var(--accent-soft); }
}

/* ===== SYLLABUS ===== */
.syllabus-card { cursor: pointer; transition: border-color 0.15s, transform 0.1s; }
.syllabus-card:active { transform: scale(0.99); }
.more-title { display: flex; align-items: center; gap: 11px; }
.more-icon {
  width: 30px; height: 30px; border-radius: 9px; flex-shrink: 0;
  background: var(--accent-soft); color: var(--accent-text);
  display: flex; align-items: center; justify-content: center;
}
.more-icon svg { width: 16px; height: 16px; }
.more-chevron { opacity: 0.4; }
.admin-reports-badge {
  display: none; font-size: 10px; font-weight: 700; color: #fff;
  background: var(--red); border-radius: 99px; min-width: 16px; height: 16px;
  padding: 0 5px; align-items: center; justify-content: center; line-height: 1;
  margin-left: 6px;
}
.admin-reports-badge:not(:empty) { display: inline-flex; }

/* ===== ADMIN REPORTS ===== */
.report-card { padding: 14px 16px; }
.report-card-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 8px; }
.report-type-badge { font-size: 10px; font-weight: 700; padding: 3px 9px; border-radius: 99px; text-transform: uppercase; letter-spacing: 0.04em; }
.report-type-badge.type-bug   { background: var(--red-soft); color: var(--red); }
.report-type-badge.type-idea  { background: var(--amber-soft); color: var(--amber); }
.report-type-badge.type-other { background: var(--border2); color: var(--text2); }
.report-card-time { font-size: 11.5px; color: var(--text2); }
.report-card-message { font-size: 13.5px; color: var(--text1); line-height: 1.5; white-space: pre-wrap; margin-bottom: 8px; }
.report-card-email { font-size: 11.5px; color: var(--text2); margin-bottom: 4px; }
.report-card-actions { display: flex; justify-content: flex-end; margin-top: 6px; }
.report-delete-btn {
  font-size: 11.5px; font-weight: 600; color: var(--text2); background: none; border: none;
  cursor: pointer; font-family: inherit; padding: 4px 8px; border-radius: 6px; transition: color 0.15s, background 0.15s;
}
.report-delete-btn:hover { color: var(--red); background: var(--red-soft); }
.syllabus-preview { margin-top: 6px; line-height: 1.5; }
.syllabus-text {
  font-size: 13px; color: var(--text1); line-height: 1.6; white-space: pre-wrap;
  background: var(--surface2); border-radius: 12px; padding: 14px;
  overflow-wrap: anywhere;
}
.syllabus-text a { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; }
.syllabus-text a:hover { opacity: 0.8; }
.syllabus-textarea {
  width: 100%; min-height: 200px; padding: 12px 14px; border-radius: 12px;
  border: 1px solid var(--border); font-size: 13px; color: var(--text1);
  background: var(--input-bg); outline: none; font-family: inherit; line-height: 1.55;
  resize: vertical; transition: border-color 0.15s, box-shadow 0.15s;
}
.syllabus-textarea:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.detail-overlay {
  display: none; position: fixed; inset: 0; z-index: 2100;
  background: var(--bg); overflow-y: auto; animation: fadeIn 0.15s ease;
}
.detail-overlay.closing { animation: fadeOut 0.18s ease forwards; }
.detail-inner {
  max-width: 1440px; margin: 0 auto; padding: 20px 20px 40px;
  animation: detailSlideUp 0.32s cubic-bezier(.16,1,.3,1) both;
}
.detail-overlay.closing .detail-inner { animation: detailSlideDown 0.18s cubic-bezier(.4,0,1,1) forwards; }
.detail-header {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  margin-bottom: 18px; position: sticky; top: 0; background: var(--bg);
  padding-top: 2px; padding-bottom: 4px; z-index: 1;
}
.detail-title { font-size: 19px; font-weight: 700; color: var(--text1); letter-spacing: -0.3px; }
.detail-close {
  background: var(--surface2); border: none; cursor: pointer;
  width: 32px; height: 32px; border-radius: 50%; font-size: 16px; color: var(--text2);
  display: flex; align-items: center; justify-content: center; font-family: inherit; flex-shrink: 0;
  transition: background 0.15s, color 0.15s;
}
.detail-close:hover { background: var(--border); color: var(--text1); }
@media (min-width: 601px) {
  .detail-overlay { left: 232px; }
  .detail-inner { max-width: 1440px; padding: 32px 40px 56px; }
  .syllabus-text { font-size: 14px; line-height: 1.75; padding: 24px 28px; }
}
mark { background: var(--accent-soft); color: var(--accent-text); padding: 0 2px; border-radius: 3px; }
mark.syl-mark-active { background: var(--accent); color: var(--on-accent); }

/* ===== LEGAL DOCS (Privacy Policy, Terms) =====
   No sidebar offset, unlike .detail-overlay -- this needs to render the same
   way whether opened from Settings (inside the app) or from the signup
   screen (before a session even exists). */
.legal-overlay {
  display: none; position: fixed; inset: 0; z-index: 2300;
  background: var(--bg); overflow-y: auto; animation: fadeUp 0.2s ease;
}
.legal-inner { max-width: 720px; margin: 0 auto; padding: 20px 20px 60px; }
.legal-header {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  position: sticky; top: 0; background: var(--bg);
  padding: 2px 0 10px; z-index: 1;
}
.legal-title { font-size: 19px; font-weight: 700; color: var(--text1); letter-spacing: -0.3px; }
.legal-updated { font-size: 12px; color: var(--text2); margin-bottom: 20px; }
.legal-body h2 { font-size: 15px; font-weight: 700; color: var(--text1); margin: 22px 0 8px; }
.legal-body p, .legal-body li { font-size: 13.5px; line-height: 1.65; color: var(--text2); margin-bottom: 10px; }
.legal-body ul { padding-left: 18px; margin-bottom: 10px; }
.legal-body strong { color: var(--text1); }
.legal-body a { color: var(--accent-text); }
.syl-inline-search-row { display: flex; gap: 8px; align-items: center; }

/* ===== DUE CALENDAR ===== */
.cal-tip-banner {
  display: flex; align-items: center; gap: 12px; padding: 12px 14px; margin-bottom: 12px;
  background: var(--ai-bg); border: 1px solid var(--ai-border);
}
.cal-tip-text { flex: 1; font-size: 12.5px; color: var(--ai-text); line-height: 1.45; }
.cal-tip-text strong { color: var(--text1); }
.cal-tip-actions { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.cal-tip-btn {
  background: var(--btn-bg); color: var(--btn-fg); border: none; border-radius: 8px;
  padding: 7px 12px; font-size: 12px; font-weight: 700; cursor: pointer; font-family: inherit;
  white-space: nowrap;
}
.cal-tip-dismiss {
  background: none; border: none; cursor: pointer; color: var(--text2); font-size: 13px;
  width: 22px; height: 22px; display: flex; align-items: center; justify-content: center; flex-shrink: 0;
}
.due-cal-card { padding: 14px 12px; }
.cal-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; padding: 0 2px; }
.cal-title { font-size: 14px; font-weight: 700; color: var(--text1); letter-spacing: -0.2px; }
.cal-nav-btn {
  width: 28px; height: 28px; border-radius: 50%; background: var(--surface2);
  border: 1px solid var(--border); cursor: pointer; font-size: 14px; color: var(--text2);
  display: flex; align-items: center; justify-content: center; transition: background 0.15s; font-family: inherit;
}
.cal-nav-btn:hover { background: var(--btn-secondary-bg); }
.cal-today-btn {
  font-size: 11.5px; font-weight: 700; color: var(--accent-text); background: var(--accent-soft);
  border: none; border-radius: 8px; padding: 6px 10px; cursor: pointer; font-family: inherit;
}
.cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
.cal-dow-row { margin-bottom: 4px; }
.cal-dow { font-size: 10px; font-weight: 700; color: var(--text2); text-align: center; text-transform: uppercase; letter-spacing: 0.04em; }
.cal-day {
  aspect-ratio: 1; border-radius: 10px; border: 1.5px solid var(--glass-border); position: relative;
  background: var(--glass-bg); display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 2px; cursor: pointer; transition: background 0.15s, border-color 0.15s; min-height: 0;
}
.cal-day:hover { background: var(--btn-secondary-bg); }
.cal-day.other-month { opacity: 0.35; }
.cal-day.today { border-color: var(--accent); }
.cal-day.selected { background: var(--accent-soft); border-color: var(--accent); }
.cal-day-num { position: relative; z-index: 1; font-size: 12px; font-weight: 600; color: var(--text1); line-height: 1; }
.cal-day-count {
  font-size: 9.5px; font-weight: 700; color: var(--on-accent); background: var(--accent);
  border-radius: 99px; min-width: 15px; height: 15px; padding: 0 3px;
  display: flex; align-items: center; justify-content: center; line-height: 1;
}
.cal-day-dots { display: flex; gap: 2px; align-items: center; }
.cal-day-study-dot { width: 5px; height: 5px; border-radius: 50%; background: var(--green, #2ea043); }
@media (min-width: 601px) {
  .due-cal-card { max-width: 480px; }
  .cal-day-num { font-size: 13px; }
}

/* ===== STUDY CHAIN (Seinfeld "don't break the chain" calendar) =====
   A red X marks a deep-work day specifically -- the rarer, bigger-effort
   day is the one that gets the bold cross-out mark. A day that just hit
   the 15-minute study threshold (no deep work) instead gets a plain green
   background, so the two kinds of "done" read differently at a glance
   without needing two X styles. The X is drawn as two rotated bars
   spanning the cell's own diagonal (100% * sqrt(2) ≈ 141%) rather than a
   font glyph, so it reaches the actual corners of the box at any cell
   size instead of being constrained by however a "✕" character happens to
   be drawn -- the whole point being that the chain, not the date numbers,
   is what your eye catches scanning the calendar. */
.cal-day.study-complete { background: var(--green-soft); }
/* A day with nothing logged, once it's actually past (not today -- there's
   still time left in today) -- the visible "broken chain" day. */
.cal-day.missed { background: var(--red-soft); }
.cal-day-chain-x {
  position: absolute; inset: 2px; pointer-events: none;
  filter: drop-shadow(0 1px 1.5px rgba(0,0,0,0.35));
}
.cal-day-chain-x::before, .cal-day-chain-x::after {
  content: ''; position: absolute; top: 50%; left: 50%;
  width: 141%; height: 11px; background: var(--red);
  /* Tapered ends instead of a blunt rectangle -- reads like an actual
     marker stroke instead of two crossed bars. */
  clip-path: polygon(0% 50%, 10% 8%, 90% 8%, 100% 50%, 90% 92%, 10% 92%);
}
/* --x-tilt is a small per-day offset (see chainXTilt in the JS) so the
   whole X leans a couple degrees differently day to day, like it was
   actually marked by hand rather than stamped identically every time. */
.cal-day-chain-x::before { transform: translate(-50%, -50%) rotate(calc(45deg + var(--x-tilt, 0deg))); }
.cal-day-chain-x::after  { transform: translate(-50%, -50%) rotate(calc(-45deg + var(--x-tilt, 0deg))); }
/* The date number moves out of the way into a corner (rather than sitting
   centered, competing with the X for the same spot) so the X can actually
   be the thing the eye lands on, same as a marked-up wall calendar --
   scoped to just this calendar so the due-soon one keeps its centered
   number + dot layout. */
#study-chain-grid .cal-day-num {
  position: absolute; top: 4px; left: 6px; z-index: 1;
  font-size: 10.5px; font-weight: 600; color: var(--text2);
}
#study-chain-grid .cal-day.today .cal-day-num { color: var(--accent); }
.chain-lead-lag-row { display: flex; gap: 10px; margin-top: 14px; }
.chain-lead-lag-card {
  flex: 1; background: var(--surface2); border-radius: 12px; padding: 12px 14px; cursor: default;
}
.chain-lead-lag-card.clickable { cursor: pointer; }
.chain-lead-lag-card.clickable:hover { background: var(--btn-secondary-bg); }
.chain-lead-lag-label { font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text2); margin-bottom: 3px; }
.chain-lead-lag-value { font-size: 15px; font-weight: 700; color: var(--text1); }
.chain-lead-lag-sub { font-size: 11px; color: var(--text2); margin-top: 1px; }
#study-chain-detail { font-size: 12.5px; color: var(--text2); text-align: center; min-height: 16px; margin-top: 10px; }

/* ===== STUDY SESSIONS ===== */
.study-session-card {
  display: flex; align-items: center; gap: 10px;
  background: var(--surface2); border-radius: 12px;
  padding: 11px 12px; margin-bottom: 8px;
}
.study-session-info { flex: 1; min-width: 0; }
.study-session-title { font-size: 13.5px; font-weight: 600; color: var(--text1); }
.study-session-card.done .study-session-info { opacity: 0.5; }
.study-session-card.done .study-session-title { text-decoration: line-through; }
.study-session-meta { font-size: 11.5px; color: var(--text2); margin-top: 1px; }
.study-session-del {
  font-size: 18px; color: var(--text2); cursor: pointer; background: none; border: none;
  line-height: 1; opacity: 0.6; padding: 4px; flex-shrink: 0;
}
.study-session-del:hover { opacity: 1; color: var(--error-color); }
.study-session-start {
  font-size: 12px; font-weight: 700; color: var(--accent-text); background: var(--accent-soft);
  border: none; border-radius: 8px; padding: 7px 11px; cursor: pointer; flex-shrink: 0; font-family: inherit;
}
.study-session-start:hover { filter: brightness(1.08); }

/* ===== FOCUS TIMER ===== */
#focus-overlay, #deepwork-overlay {
  display: none; position: fixed; inset: 0; z-index: 10001;
  background: rgba(0,0,0,0.55); align-items: center; justify-content: center; padding: 16px;
  animation: fadeIn 0.15s ease;
}
#focus-overlay.closing, #deepwork-overlay.closing { animation: fadeOut 0.18s ease forwards; }
#focus-card, #deepwork-card {
  background: var(--surface); border-radius: 20px; max-width: 380px; width: 100%;
  padding: 30px 24px 26px; text-align: center; position: relative; box-shadow: 0 20px 60px rgba(0,0,0,0.4);
  animation: wsCardIn 0.3s cubic-bezier(.16,1,.3,1) both;
}
#focus-overlay.closing #focus-card, #deepwork-overlay.closing #deepwork-card {
  animation: cardPopOut 0.18s cubic-bezier(.4,0,1,1) forwards;
}
#focus-close, #deepwork-close {
  position: absolute; top: 12px; right: 12px; width: 30px; height: 30px; border-radius: 50%;
  background: var(--surface2); border: none; cursor: pointer; color: var(--text2); font-family: inherit; font-size: 14px;
}

/* ===== PERSISTENT TIMER BAR =====
   Sits above the mobile nav so a running session stays visible and pausable
   while the student browses assignments — the whole reason they're in the app.
   Shared rules also drive the deep-work minibar (#deepwork-minibar etc.). */
#focus-minibar, #deepwork-minibar {
  position: fixed; z-index: 9998;
  left: 12px; right: 12px;
  bottom: calc(84px + env(safe-area-inset-bottom, 0px));
  display: flex; align-items: stretch; gap: 6px;
  animation: minibarSlideIn 0.25s cubic-bezier(.16,1,.3,1);
}
#focus-minibar-main, #deepwork-minibar-main {
  flex: 1; min-width: 0; display: flex; align-items: center; gap: 10px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--card-radius);
  padding: 11px 14px; cursor: pointer; font-family: inherit; text-align: left;
  box-shadow: 0 6px 24px rgba(0,0,0,0.22);
}
#focus-minibar-dot, #deepwork-minibar-dot {
  width: 8px; height: 8px; border-radius: 50%; background: var(--accent); flex-shrink: 0;
  animation: focusPulse 2s ease-in-out infinite;
}
#focus-minibar.is-paused #focus-minibar-dot,
#deepwork-minibar.is-paused #deepwork-minibar-dot { background: var(--text2); animation: none; }
@keyframes focusPulse { 0%,100% { opacity: 1; } 50% { opacity: 0.35; } }
#focus-minibar-label, #deepwork-minibar-label {
  flex: 1; min-width: 0; font-size: 13px; font-weight: 600; color: var(--text1);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#focus-minibar-time, #deepwork-minibar-time {
  font-size: 15px; font-weight: 800; color: var(--accent); font-variant-numeric: tabular-nums; flex-shrink: 0;
}
#focus-minibar-pause, #deepwork-minibar-pause {
  width: 46px; flex-shrink: 0; background: var(--surface); border: 1px solid var(--border);
  border-radius: 14px; cursor: pointer; font-family: inherit; font-size: 15px; color: var(--text1);
  box-shadow: 0 6px 24px rgba(0,0,0,0.22);
}
#focus-minibar-pause:hover, #focus-minibar-main:hover,
#deepwork-minibar-pause:hover, #deepwork-minibar-main:hover { border-color: var(--accent); }
@media (min-width: 601px) {
  #focus-minibar, #deepwork-minibar { left: auto; right: 20px; bottom: 20px; width: 320px; }
}

/* ===== STUDY GOAL ONBOARDING (blocking, like the sync welcome screen) ===== */
#study-goal-onboard-overlay {
  position: fixed; inset: 0; z-index: 2000;
  background: var(--bg);
  display: flex; align-items: center; justify-content: center;
  padding: 24px; overflow-y: auto;
}
#study-goal-onboard-card {
  background: var(--surface); border-radius: 14px; box-shadow: var(--shadow-md);
  width: 100%; max-width: 420px; padding: 32px 28px 28px;
  animation: fadeUp 0.25s ease;
}
#focus-close:hover, #deepwork-close:hover { background: var(--border); color: var(--text1); }
.focus-title { font-size: 18px; font-weight: 700; color: var(--text1); margin-bottom: 6px; }
.focus-sub { font-size: 13px; color: var(--text2); margin-bottom: 18px; line-height: 1.5; }
.focus-phase-label { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text2); margin-bottom: 8px; margin-top: 4px; }
.focus-duration-row { display: flex; gap: 8px; flex-wrap: wrap; justify-content: center; margin-bottom: 18px; }
.focus-duration-btn {
  padding: 10px 15px; border-radius: 12px; border: 1.5px solid var(--border);
  background: var(--surface2); color: var(--text1); font-size: 13.5px; font-weight: 600;
  cursor: pointer; font-family: inherit; transition: all 0.15s;
}
.focus-duration-btn.active { border-color: var(--accent); background: var(--accent-soft); color: var(--accent-text); }
.focus-timer-display { font-size: 52px; font-weight: 800; color: var(--accent); letter-spacing: -1px; margin: 10px 0 18px; font-variant-numeric: tabular-nums; }
.focus-btn-row { display: flex; gap: 8px; flex-wrap: wrap; justify-content: center; margin-top: 6px; }
.focus-btn-row.stack { flex-direction: column; }

/* ===== STUDY GOALS ===== */
.goal-progress-label { display: flex; justify-content: space-between; font-size: 14.5px; color: var(--text1); font-weight: 700; margin-bottom: 10px; }
.goal-progress-label span:last-child { color: var(--text2); font-weight: 500; }
.goal-progress-track { height: 12px; border-radius: 99px; background: var(--surface2); overflow: hidden; }
.goal-progress-fill { height: 100%; border-radius: 99px; background: var(--accent); transition: width 0.3s; }
.goal-progress-fill.goal-met { background: var(--green, #2ea043); }

/* Study hero -- one dominant "studied today" number with week/all-time folded
   in underneath, instead of three disconnected boxes floating in a row. */
.study-hero-card {
  background: linear-gradient(135deg, var(--accent-soft) 0%, var(--surface) 65%);
  border-radius: calc(var(--card-radius) + 2px); border: 1px solid var(--border);
  padding: 22px 22px 18px; margin-bottom: 28px; box-shadow: var(--shadow-sm);
  animation: cardIn 0.55s cubic-bezier(.16,1,.3,1) both;
}
.study-hero-num { font-size: 44px; font-weight: 800; letter-spacing: -1.5px; line-height: 1; color: var(--text1); font-variant-numeric: tabular-nums; }
.study-hero-label { font-size: 13.5px; font-weight: 600; color: var(--text2); margin-top: 4px; }
.study-hero-row { display: flex; gap: 20px; margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--border2); }
.study-hero-mini { display: flex; flex-direction: column; gap: 2px; }
.study-hero-mini-val { font-size: 17px; font-weight: 700; color: var(--text1); font-variant-numeric: tabular-nums; }
.study-hero-mini-label { font-size: 11px; color: var(--text2); text-transform: uppercase; letter-spacing: 0.05em; font-weight: 600; }
.study-form-row { display: flex; gap: 8px; }
.study-form-row .settings-input { flex: 1; }
.add-study-btn {
  width: 100%; padding: 11px; border-radius: 12px; background: var(--accent-soft);
  color: var(--accent-text); font-size: 13.5px; font-weight: 600; border: 1px dashed var(--accent);
  cursor: pointer; font-family: inherit; margin-bottom: 10px;
}

/* ===== SETTINGS CONTROLS ===== */
.toggle-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 11px 0; }
.toggle-row + .toggle-row { border-top: 1px solid var(--border); }
.toggle-row-label { font-size: 13.5px; font-weight: 500; color: var(--text1); }
.toggle-row-sub { font-size: 11.5px; color: var(--text2); margin-top: 2px; line-height: 1.4; }
.switch { position: relative; display: inline-block; width: 40px; height: 23px; flex-shrink: 0; }
.switch input { position: absolute; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.switch-track { position: absolute; inset: 0; background: var(--border2); border-radius: 99px; transition: background 0.15s; pointer-events: none; }
.switch-thumb {
  position: absolute; width: 19px; height: 19px; border-radius: 50%; background: #fff; top: 2px; left: 2px;
  transition: transform 0.15s; box-shadow: 0 1px 3px rgba(0,0,0,0.25); pointer-events: none;
}
.switch input:checked ~ .switch-track { background: var(--accent); }
.switch input:checked ~ .switch-thumb { transform: translateX(17px); background: var(--on-accent); }
.seg-control { display: flex; background: var(--surface2); border-radius: 10px; padding: 3px; gap: 2px; }
.seg-btn {
  flex: 1; padding: 8px 6px; border-radius: 8px; border: none; background: none;
  font-size: 12.5px; font-weight: 600; color: var(--text2); cursor: pointer; font-family: inherit; transition: background 0.15s, color 0.15s;
}
.seg-btn.active { background: var(--surface); color: var(--text1); box-shadow: var(--shadow-sm); }
.settings-select {
  width: 100%; padding: 11px 14px; border-radius: 12px; border: 1px solid var(--border);
  background: var(--input-bg); color: var(--text1); font-size: 14px; font-family: inherit; outline: none;
  cursor: pointer; transition: border-color 0.15s;
}
.settings-select:focus { border-color: var(--accent); }
.num-input-row { display: flex; align-items: center; gap: 10px; }
.num-input {
  width: 64px; padding: 9px 10px; border-radius: 10px; border: 1px solid var(--border);
  background: var(--input-bg); color: var(--text1); font-size: 14px; font-family: inherit; outline: none; text-align: center;
}
.num-input:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.settings-subsection-label { font-size: 11px; font-weight: 700; color: var(--text2); text-transform: uppercase; letter-spacing: 0.06em; margin: 14px 0 8px; }
.settings-subsection-label:first-child { margin-top: 0; }

/* density */
body.density-compact .card { padding: 8px 11px; margin-bottom: 6px; }
body.density-compact .content { padding-top: 14px; }
body.density-compact .section-label { margin-top: 12px; margin-bottom: 6px; }
body.density-compact .home-stat { padding: 10px 11px; }
body.density-compact .home-stats-strip { margin-bottom: 12px; }

/* ===== SIDEBAR / MOBILE SYNC ===== */
.sidebar-sync {
  display: flex; align-items: center; gap: 10px; width: 100%;
  background: var(--surface2); border: 1px solid var(--border); border-radius: 12px;
  padding: 10px 12px; margin: 0 0 16px; cursor: pointer; transition: background 0.15s;
  font-family: inherit; text-align: left;
}
.sidebar-sync:hover { background: var(--btn-secondary-bg); }
.sidebar-sync:disabled { opacity: 0.7; cursor: default; }
.sidebar-sync-icon { width: 18px; height: 18px; flex-shrink: 0; color: var(--accent); display: flex; }
.sidebar-sync-icon svg { width: 100%; height: 100%; }
.sidebar-sync-icon.spinning svg { animation: spin 0.8s linear infinite; }
.sidebar-sync-text { min-width: 0; }
.sidebar-sync-label { font-size: 12.5px; font-weight: 700; color: var(--text1); }
.sidebar-sync-sub { font-size: 10.5px; color: var(--text2); margin-top: 1px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.mobile-sync-btn {
  width: 30px; height: 30px; border-radius: 50%;
  background: var(--surface2); border: 1px solid var(--border);
  cursor: pointer; display: flex; align-items: center; justify-content: center;
  transition: background 0.15s; flex-shrink: 0;
}
.mobile-sync-btn:hover { background: var(--btn-secondary-bg); }
.mobile-sync-icon { width: 15px; height: 15px; color: var(--accent); display: flex; }
.mobile-sync-icon svg { width: 100%; height: 100%; }
.mobile-sync-icon.spinning svg { animation: spin 0.8s linear infinite; }
@media (min-width: 601px) {
  .mobile-sync-btn { display: none; }
}

/* ===== ASK CITATIONS ===== */
.ask-answer-text { font-size: 13.5px; color: var(--text1); line-height: 1.6; margin-bottom: 10px; }
.ask-source-chip {
  display: inline-flex; align-items: center; gap: 7px;
  background: var(--surface); border: 1px solid var(--accent-soft); border-radius: 99px;
  padding: 7px 13px; font-size: 12px; font-weight: 600; color: var(--accent-text);
  cursor: pointer; font-family: inherit; transition: background 0.15s, border-color 0.15s;
}
.ask-source-chip:hover { background: var(--accent-soft); }
.ask-source-icon { font-size: 12px; }
.ask-source-arrow { opacity: 0.7; }
.ask-more-label { font-size: 10.5px; font-weight: 700; color: var(--text2); text-transform: uppercase; letter-spacing: 0.06em; margin: 14px 0 8px; }
.ask-source-chip-secondary {
  display: flex; width: 100%; text-align: left; flex-direction: column; align-items: flex-start; gap: 3px;
  border-radius: 10px; margin-bottom: 6px; border: 1px solid var(--border); background: var(--surface);
  padding: 8px 12px; cursor: pointer; font-family: inherit; transition: border-color 0.15s, background 0.15s;
}
.ask-source-chip-secondary:hover { border-color: var(--accent-soft); background: var(--surface2); }
.ask-source-chip-course { font-size: 11.5px; font-weight: 700; color: var(--text1); }
.ask-source-snippet { font-size: 11.5px; color: var(--text2); font-weight: 400; line-height: 1.4; }

/* ===== SCHOOL AI ===== */
.school-ai-banner {
  background: var(--ai-bg); border: 1px solid var(--ai-border); border-radius: 12px;
  padding: 12px 14px; margin-bottom: 12px; display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
}
.school-ai-banner-text { flex: 1; min-width: 160px; }
.school-ai-banner-title { font-size: 12.5px; font-weight: 700; color: var(--ai-label); }
.school-ai-banner-sub { font-size: 11.5px; color: var(--ai-text); margin-top: 2px; line-height: 1.4; }
.school-ai-enable-btn {
  flex-shrink: 0; background: var(--btn-bg); color: var(--btn-fg); border: none; border-radius: 10px;
  padding: 8px 14px; font-size: 12.5px; font-weight: 700; cursor: pointer; font-family: inherit;
  transition: opacity 0.15s;
}
.school-ai-enable-btn:hover { opacity: 0.9; }
.school-ai-enable-btn:disabled { opacity: 0.6; cursor: default; }
.school-ai-progress-wrap { margin-top: 8px; width: 100%; }
.school-ai-progress-bar { height: 6px; border-radius: 99px; background: var(--border); overflow: hidden; }
.school-ai-progress-fill { height: 100%; background: var(--accent); border-radius: 99px; transition: width 0.3s ease; width: 0%; }
.school-ai-progress-label { font-size: 10.5px; color: var(--ai-text); margin-top: 5px; }
.school-ai-badge {
  display: inline-flex; align-items: center; gap: 5px; font-size: 10.5px; font-weight: 700;
  color: var(--ai-label); background: var(--ai-bg); border: 1px solid var(--ai-border);
  border-radius: 99px; padding: 3px 9px; margin-bottom: 8px;
}
.school-ai-disclaimer { font-size: 10.5px; color: var(--text2); line-height: 1.4; margin: 4px 0 10px; }
.coco-feedback-row { display: flex; align-items: center; gap: 8px; margin-top: 6px; }
.coco-feedback-label { font-size: 11.5px; color: var(--text2); }
.coco-feedback-label a { color: var(--accent-text); cursor: pointer; }
.coco-feedback-btn {
  background: none; border: 1px solid var(--border2); border-radius: 8px; cursor: pointer;
  font-size: 12px; padding: 3px 7px; line-height: 1; transition: background 0.15s, border-color 0.15s;
}
.coco-feedback-btn:hover { background: var(--surface2); border-color: var(--accent); }
.coco-suggest-row { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.coco-suggest-chip {
  background: var(--surface); border: 1px solid var(--border2); border-radius: 99px;
  padding: 6px 11px; font-size: 11.5px; color: var(--text2); cursor: pointer; font-family: inherit;
  transition: border-color 0.15s, color 0.15s;
}
.coco-suggest-chip:hover { border-color: var(--accent); color: var(--text1); }
.coco-chat-note { font-size: 11px; color: var(--text2); margin-top: 8px; }
.coco-chat-note a { color: var(--accent-text); cursor: pointer; }

/* ===== MOTION SYSTEM =====================================================
   One shared easing vocabulary + the layers that make the app feel alive:
   tactile buttons/cards, a living nav, a front door that arrives instead of
   appearing, and numbers with momentum (see js/motion-utils.js). All of it
   is transform/opacity (cheap on a weak phone) and hover effects are gated
   to devices that can actually hover, so touch screens never get a stuck
   "hover" state after a tap. Reduced-motion users get the end states with
   none of the movement (block at the very bottom). */
:root {
  --ease-out: cubic-bezier(.16,1,.3,1);
  --ease-spring: cubic-bezier(.34,1.56,.64,1);
}

/* -- Fix: `animation-fill-mode: both` on these kept the final keyframe's
   transform applied forever, which silently overrode their own hover/press
   transforms (an animation beats a normal declaration in the cascade). With
   `backwards` they still wait hidden through their stagger delay, then hand
   control back to normal styles once the entrance finishes. -- */
.card, .home-qlink { animation-fill-mode: backwards; }

/* -- Pages arrive with a bit more presence than a 6px nudge -- */
.page.active { animation: pageEnter 0.5s var(--ease-out) both; }
@keyframes pageEnter {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* -- Tactile cards: anything clickable lifts toward you and warms to the
   accent; pressing it pushes back in. -- */
.card { transition: border-color 0.2s, transform 0.35s var(--ease-spring), box-shadow 0.25s; }
.syllabus-card { transition: border-color 0.2s, transform 0.35s var(--ease-spring), box-shadow 0.25s; }
.home-qlink { transition: border-color 0.2s, transform 0.35s var(--ease-spring), box-shadow 0.25s; }
.card[onclick]:active, .syllabus-card:active { transform: scale(0.985); transition-duration: 0.1s; }
@media (hover: hover) and (pointer: fine) {
  .card[onclick]:hover, .syllabus-card:hover, .home-qlink:hover {
    transform: translateY(-3px);
    box-shadow: var(--shadow-md);
    border-color: color-mix(in oklch, var(--accent) 35%, var(--border));
  }
}
.card .card-row > div:last-child { transition: opacity 0.3s; }

/* -- Buttons: lift + glow on hover, squish on press. A spring easing on
   transform is what makes it feel physical rather than just fading. -- */
.auth-btn, .onboard-btn, .settings-btn, .goal-add-btn, .deepwork-btn {
  transition: transform 0.3s var(--ease-spring), box-shadow 0.25s, opacity 0.15s, filter 0.2s;
}
@media (hover: hover) and (pointer: fine) {
  .auth-btn:hover:not(:disabled), .onboard-btn:hover:not(:disabled),
  .settings-btn:hover:not(:disabled), .goal-add-btn:hover:not(:disabled) {
    transform: translateY(-1px); opacity: 1;
    box-shadow: 0 6px 16px -8px rgba(0,0,0,0.5);
  }
  .deepwork-btn:hover {
    transform: translateY(-1px); opacity: 1;
    box-shadow: 0 6px 16px -8px rgba(0,0,0,0.5);
  }
  .sync-btn:hover:not(:disabled), .change-courses-btn:hover { transform: translateY(-1px); }
}
.auth-btn:active:not(:disabled), .onboard-btn:active:not(:disabled), .settings-btn:active:not(:disabled),
.goal-add-btn:active:not(:disabled), .deepwork-btn:active {
  transform: translateY(0) scale(0.97); filter: none; transition-duration: 0.08s;
}
.sync-btn, .change-courses-btn { transition: transform 0.3s var(--ease-spring), opacity 0.15s, background 0.15s; }

/* -- Desktop sidebar: the active tab carries a bar that springs in, and
   icons react to the cursor instead of sitting there inert. -- */
@media (min-width: 601px) {
  .tab { position: relative; transition: background 0.2s, color 0.2s; }
  .tab::before {
    content: ''; position: absolute; left: 0; top: 24%; bottom: 24%; width: 3px;
    border-radius: 99px; background: var(--accent);
    transform: scaleY(0); transform-origin: center;
    transition: transform 0.4s var(--ease-spring);
  }
  .tab.active::before { transform: scaleY(1); }
  .tab-icon { transition: transform 0.35s var(--ease-spring); }
  .tab:hover .tab-icon { transform: scale(1.14); }
  .tab.active .tab-icon { transform: scale(1.08); }
  .tab:active .tab-icon { transform: scale(0.92); }
}

/* -- Mobile bottom nav: the active pill grows out from the center and the
   icon lifts with it. -- */
.nav-icon::before {
  background: var(--accent-soft); opacity: 0; transform: scaleX(0.45);
  transition: transform 0.4s var(--ease-spring), opacity 0.2s;
}
.nav-item.active .nav-icon::before { opacity: 1; transform: scaleX(1); }
.nav-icon svg { transition: transform 0.35s var(--ease-spring); }
.nav-item.active .nav-icon svg { transform: translateY(-1px) scale(1.1); }
.nav-item:active .nav-icon svg { transform: scale(0.88); }

/* -- The logo cap tips as you reach for it -- */
.logo-mark { transition: transform 0.45s var(--ease-spring); }
@media (hover: hover) and (pointer: fine) {
  .logo:hover .logo-mark { transform: rotate(-10deg) translateY(-2px); }
}

/* -- The one thing due next breathes with a slow glow, so the top priority
   quietly holds the eye (red when it is already overdue). -- */
#home-upnext .card {
  animation: cardIn 0.55s var(--ease-out) 0s backwards, upnextPulse 5.5s ease-in-out 1s infinite;
}
#home-upnext .card.overdue-card { --pulse: var(--red); }
@keyframes upnextPulse {
  0%, 100% { box-shadow: var(--glass-shadow), 0 0 0 0 transparent; }
  50%      { box-shadow: var(--glass-shadow), 0 0 36px -8px color-mix(in oklch, var(--pulse, var(--accent)) 55%, transparent); }
}

/* -- Numbers keep a fixed width while they count, so the layout does not
   shimmy as digits change -- */
.stat-val, .grade-card-pct, .study-hero-num { font-variant-numeric: tabular-nums; }

/* -- Front door: the login/signup form and brand panel arrive in sequence
   instead of the whole screen appearing at once. `backwards` so the
   buttons own hover/press transforms still work afterward. -- */
.auth-screen > * { animation: fadeUp 0.6s var(--ease-out) backwards; }
.auth-screen > *:nth-child(1) { animation-delay: 0ms; }
.auth-screen > *:nth-child(2) { animation-delay: 50ms; }
.auth-screen > *:nth-child(3) { animation-delay: 100ms; }
.auth-screen > *:nth-child(4) { animation-delay: 150ms; }
.auth-screen > *:nth-child(5) { animation-delay: 200ms; }
.auth-screen > *:nth-child(6) { animation-delay: 250ms; }
.auth-screen > *:nth-child(7) { animation-delay: 300ms; }
.auth-screen > *:nth-child(n+8) { animation-delay: 350ms; }
.auth-brand-inner > * { animation: greetReveal 0.9s var(--ease-out) backwards; }
.auth-brand-inner > *:nth-child(1) { animation-delay: 80ms; }
.auth-brand-inner > *:nth-child(2) { animation-delay: 220ms; }
.auth-brand-inner > *:nth-child(3) { animation-delay: 360ms; }

/* -- Feedback messages: errors nudge sideways so a failed action is felt,
   successes just settle in. (`translate` for the entrance so it does not
   fight the shake's `transform`.) -- */
@keyframes msgIn { from { opacity: 0; translate: 0 -6px; } to { opacity: 1; translate: 0 0; } }
@keyframes msgShake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-5px); } 40% { transform: translateX(5px); }
  60% { transform: translateX(-3px); } 80% { transform: translateX(2px); }
}
.msg-error   { animation: msgIn 0.35s var(--ease-out) backwards, msgShake 0.45s 0.08s ease-in-out; }
.msg-success { animation: msgIn 0.4s var(--ease-out) backwards; }

/* -- Choom answers resolve into place rather than blinking in -- */
#syllabus-ask-result > *, #syl-ai-answer > *, #planning-ai-result > * {
  animation: fadeUp 0.45s var(--ease-out) backwards;
}

/* -- Loading: a soft shimmer bar under the spinner reads as "content is
   coming" instead of a spinner on an empty void. -- */
@keyframes shimmer { from { background-position: 100% 0; } to { background-position: -100% 0; } }
.loading-box::after {
  content: ''; display: block; height: 62px; max-width: 420px; margin: 22px auto 0;
  border-radius: 12px;
  background: linear-gradient(90deg, var(--surface2) 30%, var(--surface) 50%, var(--surface2) 70%);
  background-size: 300% 100%; animation: shimmer 1.6s ease-in-out infinite;
}

/* -- Scroll reveal (see js/motion-utils.js). Cards wait lowered, shrunk and
   blurred until they scroll into view, then rise into place in a stagger.
   Replaces the old load-time cardIn for anything it registers (.sr beats it
   on order); `backwards` fill so hover/press transforms work afterward.
   :where() keeps the revealed state at zero specificity so those hover
   rules still win. The delay is !important only because the older
   :nth-of-type stagger rules would otherwise out-rank it. -- */
.sr { opacity: 0; transform: translateY(44px) scale(0.96); filter: blur(5px); animation: none; }
:where(.sr).sr-in {
  opacity: 1; transform: none; filter: none;
  animation: srIn 0.85s var(--ease-out) backwards;
  animation-delay: var(--sr-delay, 0ms) !important;
}
@keyframes srIn {
  from { opacity: 0; transform: translateY(44px) scale(0.96); filter: blur(5px); }
  to   { opacity: 1; transform: none; filter: blur(0); }
}
/* Re-rendered in place while already on screen: no entrance of any kind. */
.sr-seen { animation: none; }
/* Setting switched off: everything already registered just shows. */
html.no-scroll-reveal .sr { opacity: 1; transform: none; filter: none; animation: none; }

/* -- Reduced motion: keep the end states, drop the movement -- */
@media (prefers-reduced-motion: reduce) {
  .page.active, .card, .home-qlink, .auth-screen > *, .auth-brand-inner > *,
  .msg-error, .msg-success, #home-upnext .card,
  #syllabus-ask-result > *, #syl-ai-answer > *, #planning-ai-result > *,
  .loading-box::after { animation: none; }
  .card, .syllabus-card, .home-qlink, .auth-btn, .onboard-btn, .settings-btn, .goal-add-btn,
  .deepwork-btn, .sync-btn, .change-courses-btn, .tab::before, .tab-icon, .nav-icon::before,
  .nav-icon svg, .logo-mark { transition-duration: 0.01ms; }
  .card[onclick]:hover, .syllabus-card:hover, .home-qlink:hover, .logo:hover .logo-mark,
  .auth-btn:hover, .onboard-btn:hover, .settings-btn:hover, .goal-add-btn:hover, .deepwork-btn:hover { transform: none; }
}

/* ===== AUTH + LOADING =====================================================
   Deliberately plain: flat black, no glows or gradients. */

/* -- Auth screens are always dark: their backdrop is hardcoded black, so in
   light theme the wordmark and labels (which read --text1/--text2) were
   near-black on black. Redefining the tokens on the auth page itself fixes
   every descendant at once. --btn-bg/--btn-fg are set explicitly because they
   were already resolved from --accent up on :root and would not follow an
   --accent override. The connection-problem screen shares the same set. -- */
.auth-page, #conn-problem {
  --bg: #000; --surface: #101010; --surface2: #171717;
  --border: transparent; --border2: #262626;
  --text1: #ffffff; --text2: #b3b3b3;
  --input-bg: #1a1a1a; --input-focus-bg: #242424;
  --accent: #ffffff; --accent-soft: rgba(255,255,255,0.16); --accent-text: #ffffff;
  --on-accent: #0f0f0f; --btn-bg: #ffffff; --btn-fg: #0f0f0f;
  --red: #f3727f; --red-soft: rgba(243,114,127,0.16);
  --green: #1ed760; --green-soft: rgba(30,215,96,0.16);
  color-scheme: dark;
}
.auth-brand { border-right-color: #262626; }

/* -- The falling caps stay (they are the brand's one flourish) but quieter,
   so they never compete with the form. -- */
@keyframes authCapRain {
  0%   { transform: translateY(-12vh) rotate(-8deg); opacity: 0; }
  12%  { opacity: 0.3; }
  85%  { opacity: 0.3; }
  100% { transform: translateY(112vh) rotate(16deg); opacity: 0; }
}

/* -- Primary buttons on the dark auth screens keep their soft white halo
   (the base .auth-btn glow); on hover it brightens rather than being
   replaced by the neutral shadow the rest of the app's buttons use. -- */
@media (hover: hover) and (pointer: fine) {
  .auth-page .auth-btn:hover:not(:disabled), #conn-problem .auth-btn:hover:not(:disabled) {
    box-shadow: 0 4px 20px color-mix(in oklch, var(--btn-bg) 45%, transparent);
  }
}

/* -- Password show/hide (button is added by js/auth-ui.js) -- */
.auth-input-wrap { position: relative; margin-bottom: 18px; }
.auth-input-wrap .auth-input { margin-bottom: 0; padding-right: 54px; }
.auth-eye {
  position: absolute; right: 6px; top: 0; bottom: 0; width: 44px;
  display: flex; align-items: center; justify-content: center;
  background: none; border: none; border-radius: 10px; cursor: pointer;
  color: var(--text2); transition: color 0.15s, background 0.15s;
}
.auth-eye:hover { color: var(--text1); background: rgba(255,255,255,0.07); }
.auth-eye svg { width: 20px; height: 20px; }
.auth-eye .eye-off { display: none; }
.auth-eye[aria-pressed="true"] .eye-on { display: none; }
.auth-eye[aria-pressed="true"] .eye-off { display: block; }

/* -- Startup splash: shown from first paint until the saved session has been
   checked, so a returning student never sees the sign-in page flash by. -- */
#boot-splash {
  position: fixed; inset: 0; z-index: 6000;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 28px;
  background: #000; color: #fff; overflow: hidden;
  transition: opacity 0.6s var(--ease-out), transform 0.6s var(--ease-out), visibility 0s 0.6s;
}
#boot-splash.done { opacity: 0; transform: scale(1.04); visibility: hidden; pointer-events: none; }
.boot-logo { position: relative; animation: bootIn 1s var(--ease-out) both; }
.boot-logo .logo-mark { color: #fff; width: 48px; height: 48px; }
.boot-logo .logo-word {
  font-size: 34px; padding-left: 30px; color: transparent;
  background: linear-gradient(100deg, #7d7d7d 20%, #ffffff 45%, #7d7d7d 70%);
  background-size: 250% 100%; -webkit-background-clip: text; background-clip: text;
  animation: bootShine 2.4s ease-in-out infinite;
}
.boot-bar {
  position: relative; width: 120px; height: 2px; border-radius: 2px;
  background: rgba(255,255,255,0.12); overflow: hidden;
  animation: bootIn 1s 0.2s var(--ease-out) both;
}
.boot-bar::after {
  content: ''; position: absolute; top: 0; bottom: 0; left: 0; width: 45%;
  background: linear-gradient(90deg, transparent, #fff, transparent);
  animation: bootSweep 1.3s ease-in-out infinite;
}
.boot-slow {
  text-align: center; font-size: 13px; color: #9a9a9a; line-height: 1.5;
  max-height: 0; margin-top: 0; overflow: hidden; opacity: 0;
  transition: max-height 0.4s ease, margin-top 0.4s ease, opacity 0.4s;
}
#boot-splash.slow .boot-slow { max-height: 64px; margin-top: 4px; opacity: 1; }
.boot-slow button {
  margin-left: 8px; background: none; border: none; color: #fff; font: inherit;
  font-weight: 700; text-decoration: underline; cursor: pointer;
}
@keyframes bootIn { from { opacity: 0; transform: translateY(10px) scale(0.96); filter: blur(6px); } to { opacity: 1; transform: none; filter: blur(0); } }
@keyframes bootShine { 0% { background-position: 100% 0; } 100% { background-position: -100% 0; } }
@keyframes bootSweep { 0% { transform: translateX(-110%); } 100% { transform: translateX(260%); } }

/* -- Shown when the app cannot reach the server on startup (offline, outage)
   instead of mistaking that for "no Canvas connected yet". -- */
#conn-problem {
  position: fixed; inset: 0; z-index: 6100; display: none;
  align-items: center; justify-content: center; padding: 24px;
  background: #000; color: #fff;
}
#conn-problem.show { display: flex; animation: fadeIn 0.3s ease both; }
.conn-card { width: 100%; max-width: 360px; }
.conn-title { font-size: 22px; font-weight: 700; letter-spacing: -0.3px; margin: 8px 0 8px; }
.conn-sub { font-size: 15px; line-height: 1.55; color: var(--text2); margin-bottom: 26px; }

/* -- Sync/loading screen: the logo tile used to spin a full 360 degrees,
   which just turned its glyph upside down on every lap. It now stays
   upright and breathes, and activity is shown by a ripple leaving the ring
   plus a soft ambient glow -- so the screen still reads as alive when the
   percentage parks at its cap while waiting on Canvas. -- */
.ws-sync-logo-spin { animation: wsLogoBreathe 2.8s ease-in-out infinite; }
.ws-sync-logo-wrap::before {
  content: ''; position: absolute; inset: -52px; border-radius: 50%; pointer-events: none;
  background: radial-gradient(circle, color-mix(in oklch, var(--accent) 20%, transparent) 0%, transparent 64%);
  animation: wsAmbient 3.2s ease-in-out infinite;
}
.ws-sync-logo-wrap::after {
  content: ''; position: absolute; inset: 0; border-radius: 50%; pointer-events: none;
  border: 1.5px solid var(--accent); opacity: 0;
  animation: wsRipple 2.2s ease-out infinite;
}
.ws-sync-progress-fill { filter: drop-shadow(0 0 5px color-mix(in oklch, var(--accent) 70%, transparent)); }
@keyframes wsAmbient { 0%, 100% { opacity: 0.45; transform: scale(0.92); } 50% { opacity: 1; transform: scale(1.06); } }
@keyframes wsRipple { 0% { transform: scale(1); opacity: 0.45; } 100% { transform: scale(1.5); opacity: 0; } }
#ws-syncing-msg.swap { animation: msgSwap 0.5s var(--ease-out); }
@keyframes msgSwap { from { opacity: 0; transform: translateY(7px); } to { opacity: 1; transform: translateY(0); } }

/* -- Brand panel product preview: shows what the app is on large screens
   (decorative; hidden anywhere it would not fit). -- */
.auth-preview { display: none; }
@media (min-width: 1100px) and (min-height: 820px) {
  .auth-brand-inner > *:nth-child(4) { animation-delay: 520ms; }
  .auth-preview { display: block; position: relative; height: 205px; margin-top: 52px; }
  .ap-card {
    position: absolute; display: flex; align-items: center; gap: 12px;
    padding: 13px 16px; border-radius: 16px;
    background: rgba(255,255,255,0.055); border: 1px solid rgba(255,255,255,0.09);
    box-shadow: 0 24px 50px -24px rgba(0,0,0,0.9);
    -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
    animation: apFloat 7s ease-in-out infinite;
  }
  .ap-card.c1 { top: 0; left: 0; width: 330px; }
  .ap-card.c2 { top: 64px; left: 150px; width: 300px; animation-delay: -2.3s; }
  .ap-card.c3 { top: 130px; left: 36px; width: 300px; animation-delay: -4.6s; }
  .ap-ring { width: 18px; height: 18px; border-radius: 50%; border: 2px solid rgba(255,255,255,0.35); flex-shrink: 0; }
  .ap-rank { width: 22px; height: 22px; border-radius: 50%; background: #fff; color: #0f0f0f; font-size: 11px; font-weight: 800; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
  .ap-body { flex: 1; min-width: 0; }
  .ap-title { font-size: 13.5px; font-weight: 600; color: #fff; }
  .ap-sub { font-size: 11.5px; color: #9a9a9a; margin-top: 2px; }
  .ap-badge { font-size: 10px; font-weight: 700; padding: 3px 8px; border-radius: 99px; background: rgba(30,215,96,0.16); color: #1ed760; }
  .ap-bar { height: 3px; border-radius: 99px; background: rgba(255,255,255,0.12); margin-top: 7px; overflow: hidden; }
  .ap-bar i { display: block; height: 100%; width: 94%; border-radius: 99px; background: #1ed760; }
  .ap-grade { font-size: 18px; font-weight: 800; color: #1ed760; }
}
@keyframes apFloat { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-9px); } }

/* -- One visual language across the whole sign-in screen, taken from the
   preview cards: translucent glass, a hairline border, soft dark shadow,
   small muted captions, and green as the single accent. The form panel,
   fields, brand bullets and connection screen all use the same values. -- */
.auth-form-col .auth-screen, .conn-card {
  padding: 32px 30px 28px; border-radius: 20px;
  background: rgba(255,255,255,0.055); border: 1px solid rgba(255,255,255,0.09);
  box-shadow: 0 24px 50px -24px rgba(0,0,0,0.9);
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
}
@media (max-width: 1000px) {
  .auth-form-col .auth-screen, .conn-card { padding: 26px 22px 22px; }
}
.auth-page .auth-input {
  background: rgba(255,255,255,0.05); border: 1px solid rgba(255,255,255,0.09); border-radius: 12px;
  transition: border-color 0.15s, background 0.15s, box-shadow 0.15s;
}
.auth-page .auth-input::placeholder { color: #7d7d7d; }
.auth-page .auth-input:focus {
  background: rgba(255,255,255,0.08); border-color: rgba(255,255,255,0.32);
  box-shadow: 0 0 0 3px rgba(255,255,255,0.07);
}
.auth-page .auth-label { font-size: 11.5px; color: #9a9a9a; }
.auth-page .auth-sub { color: #9a9a9a; }
.auth-page .auth-switch { color: #9a9a9a; }
.auth-page .auth-switch a { white-space: nowrap; }
@media (max-width: 420px) {
  .auth-form-col .auth-screen, .conn-card { padding: 24px 18px 20px; }
  .auth-page .auth-switch { font-size: 14.5px; }
}

/* -- The splash and the sync/welcome overlay get the same glass card. Their
   values come from tokens because the overlay follows the app theme (light
   mode needs a dark-on-light version of the glass); the splash is always
   black, so it pins the dark values. -- */
:root {
  --glass-bg: rgba(15,15,25,0.035); --glass-border: rgba(15,15,25,0.1);
  --glass-shadow: 0 24px 50px -28px rgba(0,0,0,0.28);
}
[data-theme="dark"], #boot-splash {
  --glass-bg: rgba(255,255,255,0.055); --glass-border: rgba(255,255,255,0.09);
  --glass-shadow: 0 24px 50px -24px rgba(0,0,0,0.9);
}
.boot-card, #ws-card {
  background: var(--glass-bg); border: 1px solid var(--glass-border);
  box-shadow: var(--glass-shadow); border-radius: 20px;
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
}
.boot-card {
  position: relative; display: flex; flex-direction: column; align-items: center; gap: 26px;
  padding: 38px 46px 34px; animation: bootIn 1s var(--ease-out) both;
}
.boot-card .boot-logo, .boot-card .boot-bar { animation: none; }
@media (max-width: 420px) { .boot-card { padding: 30px 26px 28px; max-width: calc(100vw - 48px); } .boot-logo .logo-word { font-size: 30px; padding-left: 26px; } .boot-logo .logo-mark { width: 42px; height: 42px; } }
#ws-card { padding: 34px 28px 30px; }
@media (max-height: 780px) { #ws-card { padding: 22px 20px 20px; } }

/* ===== UPCOMING: calendar + day panel ====================================
   Wide screens put the selected day's assignments beside the calendar
   instead of far below it (hover a day to preview it, click to select).
   Under 1100px it stays stacked exactly as before. */
/* The calendar card shares the day panel's glass, and so do its day cells
   (see .cal-day): glass is set on the base rule, with the selected / today
   / study-streak states layered over it by their own more specific rules. */
.card.due-cal-card {
  background: var(--glass-bg); border: 1px solid var(--glass-border); border-radius: 20px;
  box-shadow: var(--glass-shadow);
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
}
@media (min-width: 601px) { .card.due-cal-card { padding: 18px 16px; } }
.due-day-head { display: flex; align-items: center; gap: 10px; }
.due-day-preview-tag {
  display: none; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--text2); background: var(--surface2); padding: 3px 8px; border-radius: 99px;
}
.due-day-panel.previewing .due-day-preview-tag { display: inline-block; }
.day-swap { animation: daySwap 0.22s var(--ease-out); }
@keyframes daySwap { from { opacity: 0.35; transform: translateY(5px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .day-swap { animation: none; } }
/* Stacked (phone/narrow) the panel is just a wrapper: the cards inside
   reveal on their own, so the wrapper must not hide and reveal as well. */
@media (max-width: 1099px) {
  .due-day-panel.sr, :where(.due-day-panel.sr).sr-in { opacity: 1; transform: none; filter: none; animation: none; }
}

@media (min-width: 1100px) {
  .due-cal-layout {
    display: grid; grid-template-columns: minmax(380px, 480px) minmax(0, 1fr);
    gap: 24px; align-items: start;
  }
  .due-cal-layout .due-cal-card { max-width: none; }
  .due-day-panel {
    position: sticky; top: 16px; max-height: calc(100vh - 32px); overflow-y: auto;
    background: var(--glass-bg); border: 1px solid var(--glass-border); border-radius: 20px;
    box-shadow: var(--glass-shadow); padding: 20px 20px 10px;
    -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  }
  .due-day-head { margin-bottom: 14px; }
  #due-cal-selected-label {
    font-size: 16px; font-weight: 700; color: var(--text1); text-transform: none;
    letter-spacing: -0.2px; margin: 0;
  }
  /* The page-wide grid rule for this list assumes a full-width column; the
     panel is a single narrow column. */
  .due-day-panel #due-cal-selected-list { display: block; }
}

/* ===== HOME OVERVIEW ====================================================
   Stat tiles, a 7-day strip, and the study-goals card, all on the shared
   glass (the .glass utility, same values as the sign-in / calendar glass). */
.glass, .card.glass {
  background: var(--glass-bg); border: 1px solid var(--glass-border); border-radius: 20px;
  box-shadow: var(--glass-shadow);
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
}
.home-hero-sub { margin-top: 2px; }

.home-tiles { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin: 18px 0 14px; }
@media (min-width: 1000px) { .home-tiles { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.home-tile {
  display: flex; flex-direction: column; align-items: flex-start; gap: 4px; text-align: left;
  padding: 16px 18px; font-family: inherit; color: var(--text1); cursor: pointer; min-width: 0;
  transition: transform 0.35s var(--ease-spring), border-color 0.2s, box-shadow 0.25s;
}
@media (hover: hover) and (pointer: fine) {
  .home-tile:hover { transform: translateY(-3px); border-color: color-mix(in oklch, var(--accent) 35%, var(--glass-border)); }
}
.home-tile:active { transform: scale(0.985); transition-duration: 0.1s; }
.ht-top { display: flex; align-items: center; gap: 9px; margin-bottom: 4px; }
.ht-icon {
  width: 28px; height: 28px; border-radius: 9px; flex-shrink: 0;
  background: var(--accent-soft); color: var(--accent);
  display: flex; align-items: center; justify-content: center;
}
.ht-icon svg { width: 16px; height: 16px; }
.ht-label { font-size: 11px; font-weight: 700; letter-spacing: 0.07em; text-transform: uppercase; color: var(--text2); }
.ht-value { font-size: 32px; font-weight: 800; letter-spacing: -1px; line-height: 1.05; font-variant-numeric: tabular-nums; }
.ht-sub {
  font-size: 12px; color: var(--text2); max-width: 100%; line-height: 1.35;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden;
}
.home-tile.tone-red .ht-icon { background: var(--red-soft); color: var(--red); }
.home-tile.tone-red .ht-value { color: var(--red); }
.ht-bar {
  width: 100%; height: 4px; border-radius: 99px; overflow: hidden; margin-top: 6px;
  background: color-mix(in oklch, var(--text1) 10%, transparent);
}
.ht-bar i { display: block; height: 100%; border-radius: 99px; background: var(--accent); animation: htBar 0.9s var(--ease-out) backwards; }
.ht-bar i.met { background: var(--green); }
@keyframes htBar { from { width: 0; } }

.home-week { padding: 16px 18px 18px; margin-bottom: 8px; }
.hw-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.hw-title { font-size: 11px; font-weight: 700; letter-spacing: 0.07em; text-transform: uppercase; color: var(--text2); }
.hw-link { background: none; border: none; font: inherit; font-size: 12px; font-weight: 600; color: var(--text2); cursor: pointer; padding: 2px 0; transition: color 0.15s; }
.hw-link:hover { color: var(--text1); }
.hw-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 8px; }
.hw-day {
  display: flex; flex-direction: column; align-items: center; gap: 3px; padding: 10px 0 9px;
  border-radius: 12px; border: 1.5px solid var(--glass-border); background: var(--glass-bg);
  color: var(--text1); font-family: inherit; cursor: pointer; min-width: 0;
  transition: background 0.15s, border-color 0.15s, transform 0.3s var(--ease-spring);
}
.hw-day:hover { background: var(--btn-secondary-bg); }
.hw-day:active { transform: scale(0.95); }
.hw-day.today { border-color: var(--accent); }
.hw-dow { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text2); }
.hw-num { font-size: 17px; font-weight: 700; font-variant-numeric: tabular-nums; line-height: 1.1; }
.hw-count {
  min-width: 16px; height: 16px; padding: 0 5px; border-radius: 99px; font-size: 10px; font-weight: 700;
  display: flex; align-items: center; justify-content: center; line-height: 1;
}
.hw-day.has .hw-count { background: var(--accent); color: var(--on-accent); }
.hw-dow { max-width: 100%; overflow: hidden; }
@media (max-width: 420px) { .hw-grid { gap: 4px; } .hw-num { font-size: 15px; } .hw-dow { font-size: 8.5px; letter-spacing: 0; } }

/* Grades at a glance: course, a thin bar, percent and letter. */
.hg-row { padding: 9px 0; }
.hg-row + .hg-row { border-top: 1px solid var(--glass-border); }
.hg-top { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.hg-name { font-size: 13px; font-weight: 600; color: var(--text1); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hg-score { display: flex; align-items: baseline; gap: 8px; flex-shrink: 0; }
.hg-pct { font-size: 12px; color: var(--text2); font-variant-numeric: tabular-nums; }
.hg-letter { font-size: 14px; font-weight: 800; }
.hg-row .ht-bar { margin-top: 7px; height: 3px; }

/* Study goals card */
.home-study { padding: 16px 18px; cursor: pointer; }
.hs-row + .hs-row { margin-top: 14px; }
.hs-top { display: flex; align-items: baseline; justify-content: space-between; font-size: 13px; font-weight: 600; color: var(--text1); }
.hs-val { font-variant-numeric: tabular-nums; }
.hs-val em { font-style: normal; font-weight: 500; color: var(--text2); }
.hs-foot { display: flex; flex-direction: column; gap: 3px; margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--glass-border); font-size: 12px; color: var(--text2); }
.hs-goal { color: var(--text1); font-weight: 500; }

@media (prefers-reduced-motion: reduce) { .ht-bar i, .home-tile { animation: none; transition-duration: 0.01ms; } }
.auth-brand-points li::before {
  width: 20px; height: 20px; border-radius: 50%;
  background: rgba(30,215,96,0.16) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='none' stroke='%231ed760' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2.5 6.2l2.3 2.3 4.7-5'/%3E%3C/svg%3E") center / 11px no-repeat;
}

@media (prefers-reduced-motion: reduce) {
  .boot-card, .boot-logo, .boot-logo .logo-word, .boot-bar, .boot-bar::after,
  .ws-sync-logo-spin, .ws-sync-logo-wrap::before, .ws-sync-logo-wrap::after,
  #ws-syncing-msg.swap, .ap-card { animation: none; }
  .boot-logo .logo-word { color: #fff; background: none; }
  .boot-bar::after { width: 100%; }
  #boot-splash { transition-duration: 0.01ms; }
}

/* ===== HOME: box corners ================================================
   The Home dashboard's boxes follow Settings > Display > Card corners like
   every other tab (Square, Sharp, Rounded, Pill). Small pieces inside the
   boxes (day cells, icons, progress bars) get a smaller version so a big
   setting doesn't turn them into circles. Count badges and the round
   check-off circles are labels/controls, not boxes, so they keep their shape. */
#page-home {
  --home-radius: var(--card-radius, 14px);
  --home-radius-sm: min(var(--card-radius, 14px), 10px);
}
#page-home .home-tile,
#page-home .home-week,
#page-home #home-upnext .card,
#page-home #home-thisweek,
#page-home #home-grades,
#page-home #home-study,
#page-home .home-qlink,
#page-home #home-announcements { border-radius: var(--home-radius); }
#page-home .hw-day,
#page-home .ht-icon,
#page-home .ht-bar, #page-home .ht-bar i,
#page-home .home-qlink-icon { border-radius: var(--home-radius-sm); }

/* ===== LOGIN: motion =====================================================
   A choreographed arrival rather than everything fading at once: panel ->
   logo cap -> fields (existing stagger) on the right; headline word by word
   -> bullets -> preview cards on the left, with the first card's assignment
   getting ticked off as a quiet demo of the product. All transform/opacity
   (plus one short blur), all one-shot except the cards' float, and all off
   under prefers-reduced-motion. */

/* The glass panel rises in under its own fields instead of popping in. */
.auth-form-col .auth-screen { animation: authPanelIn 0.7s var(--ease-out) backwards; }
@keyframes authPanelIn { from { opacity: 0; transform: translateY(18px) scale(0.985); } to { opacity: 1; transform: none; } }

/* The cap drops onto the S. The end frame matches the logo's resting
   rotate(-24deg), so it hands off seamlessly. */
.auth-logo .logo-mark, .auth-brand-logo .logo-mark { animation: capSettle 0.9s 0.25s var(--ease-spring) backwards; }
@keyframes capSettle { from { opacity: 0; transform: translateY(-12px) rotate(-75deg); } to { opacity: 1; transform: rotate(-24deg); } }

/* Headline reveals word by word (words are wrapped by js/auth-ui.js). */
.auth-brand-tagline { animation: none; }
.auth-brand-tagline .tw {
  display: inline-block; animation: wordIn 0.7s var(--ease-out) backwards;
  animation-delay: calc(200ms + var(--i, 0) * 45ms);
}
@keyframes wordIn { from { opacity: 0; transform: translateY(12px); filter: blur(6px); } to { opacity: 1; transform: none; filter: blur(0); } }

/* Bullets slide in one after another; their green checks pop. */
.auth-brand-points { animation: none; }
.auth-brand-points li { animation: bulletIn 0.6s var(--ease-out) backwards; }
.auth-brand-points li:nth-child(1) { animation-delay: 0.75s; }
.auth-brand-points li:nth-child(2) { animation-delay: 0.87s; }
.auth-brand-points li:nth-child(3) { animation-delay: 0.99s; }
.auth-brand-points li::before { animation: chipPop 0.5s var(--ease-spring) backwards; animation-delay: inherit; }
@keyframes bulletIn { from { opacity: 0; transform: translateX(-10px); } to { opacity: 1; transform: none; } }
@keyframes chipPop { from { transform: scale(0); } to { transform: scale(1); } }

/* Field labels brighten while their field has focus. */
.auth-page .auth-label { transition: color 0.2s; }
.auth-page .auth-label:has(+ .auth-input:focus),
.auth-page .auth-label:has(+ .auth-input-wrap .auth-input:focus) { color: #fff; }

/* Preview cards: arrive one at a time, then float; the grade bar fills; the
   first card's assignment gets checked off. `translate` (entrance + cursor
   depth) and `transform` (float) are separate properties so they never
   fight. --px/--py are set by js/auth-ui.js from the cursor position. */
@media (min-width: 1100px) and (min-height: 820px) {
  .auth-preview { animation: none; }
  .ap-card {
    translate: calc(var(--px, 0) * var(--d, 8) * 1px) calc(var(--py, 0) * var(--d, 8) * 1px);
    transition: translate 0.6s var(--ease-out);
  }
  .ap-card.c1 { --d: 8;  animation: apIn 0.9s 1.05s var(--ease-out) backwards, apFloat 7s ease-in-out 0s infinite; }
  .ap-card.c2 { --d: 14; animation: apIn 0.9s 1.2s var(--ease-out) backwards, apFloat 7s ease-in-out -2.3s infinite; }
  .ap-card.c3 { --d: 20; animation: apIn 0.9s 1.35s var(--ease-out) backwards, apFloat 7s ease-in-out -4.6s infinite; }
  .ap-bar i { animation: apBarFill 1.4s 1.7s var(--ease-out) backwards; }
  .ap-ring { position: relative; animation: apRingDone 0.45s 2.8s ease forwards; }
  .ap-ring::after {
    content: ''; position: absolute; left: 6px; top: 2.5px; width: 4px; height: 8px;
    border: solid #1ed760; border-width: 0 2px 2px 0;
    transform: rotate(45deg) scale(0); animation: apTick 0.4s 2.95s var(--ease-spring) forwards;
  }
}
@keyframes apIn { from { opacity: 0; translate: 0 26px; filter: blur(6px); } to { opacity: 1; filter: blur(0); } }
@keyframes apBarFill { from { width: 0; } }
@keyframes apRingDone { to { border-color: #1ed760; background: rgba(30,215,96,0.16); } }
@keyframes apTick { to { transform: rotate(45deg) scale(1); } }

@media (prefers-reduced-motion: reduce) {
  .auth-form-col .auth-screen, .auth-logo .logo-mark, .auth-brand-logo .logo-mark,
  .auth-brand-tagline .tw, .auth-brand-points li, .auth-brand-points li::before,
  .ap-card.c1, .ap-card.c2, .ap-card.c3, .ap-bar i { animation: none; }
  .ap-card { translate: none; transition: none; }
  .ap-ring { animation: none; }
  .ap-ring::after { animation: none; display: none; }
}

/* ===== LOGIN: motion, part 2 ============================================ */

/* The Sign in halo swells and relaxes once after the form settles, drawing
   the eye to the one action on the screen. The fadeUp is restated here
   because setting `animation` replaces the stagger rule's list. */
.auth-page .auth-btn {
  animation: fadeUp 0.6s var(--ease-out) 350ms backwards, haloOnce 1.4s ease-out 1.1s;
}
@keyframes haloOnce {
  0%, 100% { box-shadow: 0 2px 10px color-mix(in oklch, var(--btn-bg) 30%, transparent); }
  35%      { box-shadow: 0 0 0 7px color-mix(in oklch, var(--btn-bg) 14%, transparent), 0 4px 22px color-mix(in oklch, var(--btn-bg) 45%, transparent); }
}

/* Success: the button confirms, then the panel lifts and dims while the app
   loads. Dimmed rather than hidden, so a slow network never shows a blank
   page; hideAll() clears .auth-leaving when the screens swap. */
.auth-btn.btn-success::before {
  content: ''; display: inline-block; width: 5px; height: 10px; margin-right: 10px; vertical-align: 1px;
  border: solid currentColor; border-width: 0 2px 2px 0;
  transform: rotate(45deg); animation: btnTick 0.35s var(--ease-spring) both;
}
@keyframes btnTick { from { transform: rotate(45deg) scale(0); } to { transform: rotate(45deg) scale(1); } }
#auth-page.auth-leaving .auth-form-col .auth-screen { animation: authPanelOut 0.45s var(--ease-out) forwards; }
#auth-page.auth-leaving .auth-brand-inner { animation: authBrandOut 0.45s var(--ease-out) forwards; }
@keyframes authPanelOut { to { opacity: 0.55; transform: translateY(-8px) scale(0.99); filter: blur(1.5px); } }
@keyframes authBrandOut { to { opacity: 0.4; transform: translateY(-6px); } }

/* Preview story, continued: once the first card's assignment is ticked, its
   title is struck through and dims, as a finished task would. */
@media (min-width: 1100px) and (min-height: 820px) {
  .ap-card.c1 .ap-title {
    background: linear-gradient(currentColor, currentColor) no-repeat 0 55% / 0% 1.5px;
    animation: apStrike 0.5s 3.15s var(--ease-out) forwards;
  }
}
@keyframes apStrike { to { background-size: 100% 1.5px; color: #9a9a9a; } }

/* A faint light travels down the divider between the two halves on load,
   then again every ~10s -- most of each cycle is idle. */
@media (min-width: 901px) {
  .auth-brand { position: relative; }
  .auth-brand::after {
    content: ''; position: absolute; top: 0; right: -1px; width: 1px; height: 32%;
    background: linear-gradient(transparent, rgba(255,255,255,0.55), transparent);
    opacity: 0; pointer-events: none;
    animation: dividerSweep 10s 0.6s ease-in-out infinite;
  }
}
@keyframes dividerSweep {
  0%   { transform: translateY(-100%); opacity: 0; }
  4%   { opacity: 1; }
  22%  { transform: translateY(320%); opacity: 0; }
  100% { transform: translateY(320%); opacity: 0; }
}

/* Links draw their underline on hover. */
.auth-page .auth-switch a {
  background: linear-gradient(currentColor, currentColor) no-repeat 0 100% / 0% 1px;
  padding-bottom: 1px; transition: background-size 0.3s var(--ease-out);
}
.auth-page .auth-switch a:hover { background-size: 100% 1px; }

/* The show/hide-password icon morphs in rather than swapping instantly
   (the newly displayed icon replays this each toggle). */
.auth-eye[aria-pressed="false"] .eye-on,
.auth-eye[aria-pressed="true"] .eye-off { animation: eyeSwap 0.3s var(--ease-spring); }
@keyframes eyeSwap { from { opacity: 0; transform: scale(0.6) rotate(-25deg); } to { opacity: 1; transform: none; } }

@media (prefers-reduced-motion: reduce) {
  .auth-page .auth-btn { animation: none; }
  .auth-btn.btn-success::before, .auth-eye .eye-on, .auth-eye .eye-off { animation: none; }
  #auth-page.auth-leaving .auth-form-col .auth-screen, #auth-page.auth-leaving .auth-brand-inner { animation: none; }
  .ap-card.c1 .ap-title { animation: none; }
  .auth-brand::after { animation: none; display: none; }
  .auth-page .auth-switch a { transition: none; }
}

/* ===== LOGIN: refreshed copy, wordmark, divider =========================== */

/* "Welcome back" / "Create your account" etc. -- a real heading on each
   sign-in screen, with the subtitle beneath it as supporting text. */
.auth-heading {
  font-size: 26px; font-weight: 700; color: var(--text1); letter-spacing: -0.5px; line-height: 1.2;
  margin: 18px 0 6px;
}
.auth-page .auth-sub { font-size: 15px; margin-bottom: 26px; }
@media (max-width: 420px) { .auth-heading { font-size: 23px; } }

/* Wordmark: "Flow" set in Playfair's italic for a bit of motion in the
   name itself, with slightly tighter tracking. Applies to every logo. */
.logo-word { letter-spacing: -0.4px; }
.logo-word em { font-style: italic; font-weight: 700; }

/* Divider: instead of a hard full-height rule, a hairline that fades out
   toward the top and bottom and draws itself in from the middle on load.
   The traveling light (.auth-brand::after) still runs along it. */
@media (min-width: 901px) {
  .auth-page .auth-brand { border-right-color: transparent; }
  .auth-brand::before {
    content: ''; position: absolute; top: 0; bottom: 0; right: -1px; width: 1px; pointer-events: none;
    background: linear-gradient(to bottom, transparent, rgba(255,255,255,0.14) 18%, rgba(255,255,255,0.14) 82%, transparent);
    transform-origin: center; animation: dividerGrow 1.1s 0.15s var(--ease-out) backwards;
  }
}
@keyframes dividerGrow { from { transform: scaleY(0); opacity: 0; } to { transform: scaleY(1); opacity: 1; } }

/* Logo proportions. Every wordmark now uses the same ratios, taken from the
   large brand logo (f = the wordmark's font size): cap 1.41f square, perched
   0.5f above the text, wordmark indented 0.88f -- so the refined cap (which
   has a base under its board) rests ON the S at every size instead of
   covering it on big logos or floating beside it on small ones. */
.logo-mark { width: 28px; height: 28px; top: -10px; left: 1px; }              /* f = 20 (sidebar) */
.logo-word { padding-left: 18px; }
.topbar-logo .logo-mark { width: 25px; height: 25px; top: -9px; left: 1px; }  /* f = 18 */
.topbar-logo .logo-word { padding-left: 16px; }
.auth-logo .logo-mark { width: 40px; height: 40px; top: -14px; left: 1px; }   /* f = 28 */
.auth-logo .logo-word { padding-left: 25px; }
.auth-brand-logo .logo-mark, .boot-logo .logo-mark { top: -17px; left: 1px; } /* f = 34: 48px cap, 30px indent */
/* The sidebar logo has its own padding (4px top, 10px left) that shifts the
   text but not the absolutely positioned cap, so the cap shifts to match. */
.sidebar-logo .logo-mark { top: -6px; left: 11px; }
@media (max-width: 420px) {
  .boot-logo .logo-mark { top: -15px; }                                        /* f = 30: 42px cap, 26px indent */
}
@media (prefers-reduced-motion: reduce) { .auth-brand::before { animation: none; } }

/* ===========================
   WELCOME SCREEN: logo badge
   A glass badge carrying the cap, centered above the greeting, so the
   space between the greeting and the sync button has an anchor instead of
   reading as empty. Same glass + soft halo as the login's mock cards.
=========================== */
#ws-badge {
  width: 84px; height: 84px; margin: 0 auto 26px; border-radius: 24px;
  display: flex; align-items: center; justify-content: center;
  background: var(--glass-bg); border: 1px solid var(--glass-border);
  box-shadow: var(--glass-shadow), 0 0 60px rgba(255,255,255,0.07);
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  color: var(--text1); position: relative;
  animation: wsBadgeIn 0.7s 0.05s var(--ease-spring) backwards;
}
#ws-badge::before {
  content: ''; position: absolute; inset: -18px; border-radius: 50%; z-index: -1;
  background: radial-gradient(closest-side, rgba(255,255,255,0.10), transparent);
  animation: wsBadgeGlow 4s ease-in-out 0.8s infinite;
}
#ws-badge svg { width: 46px; height: 46px; transform: rotate(-12deg); animation: wsBadgeCap 0.9s 0.2s var(--ease-spring) backwards; }
@keyframes wsBadgeIn { from { opacity: 0; transform: translateY(14px) scale(0.85); } to { opacity: 1; transform: none; } }
@keyframes wsBadgeCap { from { opacity: 0; transform: translateY(-10px) rotate(-60deg); } to { opacity: 1; transform: rotate(-12deg); } }
@keyframes wsBadgeGlow { 0%, 100% { opacity: 0.6; transform: scale(0.95); } 50% { opacity: 1; transform: scale(1.06); } }
#ws-logo-name em { font-style: italic; }
@media (max-height: 780px) {
  #ws-badge { width: 68px; height: 68px; border-radius: 20px; margin-bottom: 18px; }
  #ws-badge svg { width: 38px; height: 38px; }
}
@media (max-height: 620px) { #ws-badge { display: none; } }
@media (prefers-reduced-motion: reduce) {
  #ws-badge, #ws-badge::before, #ws-badge svg { animation: none; }
}
/* With the badge filling the top, the card no longer needs the tall fixed
   height that left a dead band above the sync button; it still grows to fit
   when the summary rows are showing. */
#ws-welcome { min-height: min(470px, 62dvh); }
#ws-greeting-block { padding-bottom: 28px; }
#study-goal-onboard-card .ws-skip { animation-delay: 0.2s; }
/* Card-corner choices: visible against dark surfaces, and the selected one
   actually shows (it used to carry an inline border that hid .active). */
.radius-swatch { width: 32px; height: 32px; background: var(--surface2); border: 2px solid var(--border2); }
.radius-swatch.active { border-color: var(--text1); background: var(--surface3, var(--surface2)); }
/* A ring just outside the selected swatch reads on every color, including
   the white accent (a white border on a white dot disappears). */
.swatch.active { outline: 2px solid var(--text1); outline-offset: 2px; }
@media (max-width: 600px) { .eyebrow-date { display: none; } }

/* ===========================
   ASSIGNMENTS: search
   Filters the list in place as you type (title, class, or type badge).
=========================== */
.aw-search { position: relative; display: flex; align-items: center; margin-bottom: 6px; }
.aw-search-icon { position: absolute; left: 14px; width: 17px; height: 17px; color: var(--text2); pointer-events: none; }
#allwork-search {
  width: 100%; height: 44px; padding: 0 42px; box-sizing: border-box;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--card-radius, 14px);
  color: var(--text1); font: inherit; font-size: 14.5px; outline: none;
  transition: border-color 0.15s, box-shadow 0.2s;
}
[data-theme="dark"] #allwork-search { border-color: rgba(255,255,255,0.08); }
#allwork-search::placeholder { color: var(--text2); }
#allwork-search::-webkit-search-cancel-button { display: none; }
#allwork-search:focus { border-color: var(--border2); box-shadow: 0 0 0 3px color-mix(in oklch, var(--text1) 8%, transparent); }
[data-theme="dark"] #allwork-search:focus { border-color: rgba(255,255,255,0.22); }
.aw-search-clear {
  position: absolute; right: 8px; width: 28px; height: 28px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--surface2); border: none; color: var(--text2); cursor: pointer;
  opacity: 0; transform: scale(0.7); pointer-events: none;
  transition: opacity 0.15s, transform 0.2s var(--ease-spring), color 0.15s;
}
.aw-search-clear.show { opacity: 1; transform: none; pointer-events: auto; }
.aw-search-clear:hover { color: var(--text1); }
.aw-search-clear svg { width: 13px; height: 13px; }
.aw-search-count { min-height: 18px; font-size: 12px; color: var(--text2); padding: 2px 4px 10px; }
@media (max-width: 600px) { #allwork-search { font-size: 16px; } } /* below 16px iOS zooms on focus */
@media (prefers-reduced-motion: reduce) { .aw-search-clear { transition: none; } }
[data-theme="dark"] .aw-search-clear { background: rgba(255,255,255,0.1); color: var(--text1); }

/* ===========================
   ASSIGNMENTS: "By class" view
   A toggle beside the search count, then one group per class: a header
   (name, how many left / overdue, current grade) that folds the class's
   assignments away when clicked.
=========================== */
.aw-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin: 4px 0 12px; }
.aw-toolbar .aw-search-count { padding: 0 4px; min-height: 0; }
.aw-view { flex: 0 0 auto; width: auto; }
.aw-view .seg-btn { padding-left: 14px; padding-right: 14px; white-space: nowrap; }

.awc-group { margin-bottom: 14px; }
.awc-head {
  display: flex; align-items: center; gap: 10px; padding: 12px 14px; cursor: pointer;
  background: var(--glass-bg); border: 1px solid var(--glass-border); border-radius: var(--card-radius, 14px);
  box-shadow: var(--glass-shadow); transition: background 0.15s, border-color 0.15s;
  -webkit-user-select: none; user-select: none;
}
.awc-head:hover { border-color: var(--border2); }
.awc-head:focus-visible { outline: 2px solid var(--text1); outline-offset: 2px; }
.awc-chevron { width: 16px; height: 16px; flex-shrink: 0; color: var(--text2); transform: rotate(90deg); transition: transform 0.25s var(--ease-out); }
.awc-group.collapsed .awc-chevron { transform: none; }
.awc-title { flex: 1; min-width: 0; }
.awc-name { font-size: 15px; font-weight: 700; color: var(--text1); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.awc-meta { font-size: 12px; color: var(--text2); margin-top: 2px; }
.awc-overdue { color: var(--red); font-weight: 600; }
.awc-grade {
  flex-shrink: 0; display: flex; align-items: baseline; gap: 6px; padding: 6px 10px;
  background: var(--surface2); border: 1px solid var(--border); border-radius: 9px;
  color: var(--text1); font: inherit; cursor: pointer; transition: border-color 0.15s;
}
[data-theme="dark"] .awc-grade { background: rgba(255,255,255,0.06); border-color: rgba(255,255,255,0.08); }
.awc-grade:hover { border-color: var(--border2); }
.awc-grade b { font-size: 15px; }
.awc-grade span { font-size: 12px; color: var(--text2); }

/* Fold: grid rows animate from the content's height to 0 without JS
   measuring anything. */
.awc-body {
  display: grid; grid-template-rows: 1fr; padding: 8px 0 0 12px; margin-left: 7px;
  border-left: 1px solid var(--border2);
  transition: grid-template-rows 0.3s var(--ease-out), opacity 0.2s, padding 0.3s var(--ease-out);
}
.awc-inner { min-height: 0; overflow: hidden; }
.awc-group.collapsed .awc-body { grid-template-rows: 0fr; opacity: 0; padding-top: 0; }

@media (max-width: 600px) {
  .aw-toolbar { flex-wrap: wrap; }
  .aw-view { width: 100%; }
  .aw-view .seg-btn { flex: 1; }
  .awc-body { padding-left: 8px; margin-left: 4px; }
}
@media (prefers-reduced-motion: reduce) {
  .awc-body, .awc-chevron { transition: none; }
}
/* By class: each class spans the full width (so they read top to bottom in
   due order), and its own assignments use the list's usual card grid. */
#allwork-list > .awc-group { grid-column: 1 / -1; }
@media (min-width: 601px) {
  .awc-inner { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 10px; align-content: start; }
  .awc-inner > .card { margin-bottom: 0; }
}

/* ===========================
   UPDATES (teacher feed)
=========================== */
.tab-badge:empty { display: none; }
.tab-badge {
  margin-left: auto; min-width: 18px; height: 18px; padding: 0 5px; box-sizing: border-box;
  border-radius: 9px; background: var(--accent); color: var(--on-accent);
  font-size: 11px; font-weight: 700; line-height: 18px; text-align: center;
  animation: chipPop 0.35s var(--ease-spring) backwards;
}
.tabs.collapsed .tab-badge { position: absolute; top: 4px; right: 6px; margin: 0; min-width: 8px; height: 8px; padding: 0; font-size: 0; }

.upd-toolbar { display: flex; align-items: center; gap: 12px; margin-bottom: 6px; }
.upd-filter { flex: 0 1 auto; width: auto; overflow-x: auto; scrollbar-width: none; }
.upd-filter::-webkit-scrollbar { display: none; }
.upd-filter .seg-btn { white-space: nowrap; padding-left: 14px; padding-right: 14px; display: inline-flex; align-items: center; gap: 6px; }
.upd-count {
  min-width: 17px; height: 17px; padding: 0 4px; box-sizing: border-box; border-radius: 9px;
  background: var(--accent); color: var(--on-accent); font-size: 10.5px; font-weight: 700; line-height: 17px;
}
.upd-markall {
  margin-left: auto; flex-shrink: 0; background: none; border: none; cursor: pointer; font: inherit;
  font-size: 13px; font-weight: 600; color: var(--text2); padding: 6px 4px; transition: color 0.15s, opacity 0.15s;
}
.upd-markall:hover:not(:disabled) { color: var(--text1); }
.upd-markall:disabled { opacity: 0.4; cursor: default; }

.upd-day { margin-top: 18px; }
#updates-list > .upd-day:first-child { margin-top: 8px; }
#updates-list .upd-card { margin-bottom: 8px; }
.upd-top { display: flex; align-items: center; gap: 8px; min-width: 0; }
.upd-top .announcement-course { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.upd-kind {
  flex-shrink: 0; font-size: 10px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
  padding: 2px 7px; border-radius: 6px;
}
.upd-kind-announcement { background: var(--accent-soft); color: var(--accent-text); }
.upd-kind-feedback { background: var(--green-soft); color: var(--green); }
.upd-kind-message { background: var(--purple-soft); color: var(--purple); }
.upd-card:focus-visible { outline: 2px solid var(--text1); outline-offset: 2px; }

@media (max-width: 600px) {
  .upd-toolbar { flex-wrap: wrap; }
  .upd-filter { width: 100%; }
  .upd-filter .seg-btn { flex: 1; padding-left: 10px; padding-right: 10px; }
}
.announcement-body a { color: var(--text1); text-decoration: underline; text-underline-offset: 2px; word-break: break-all; }
@media (max-width: 600px) {
  .upd-filter .seg-btn { flex: 0 0 auto; }
  .upd-filter { -webkit-mask-image: linear-gradient(to right, #000 85%, transparent); mask-image: linear-gradient(to right, #000 85%, transparent); }
}

/* ===========================
   DONE CELEBRATION
=========================== */
/* Confetti that bursts outward, then tumbles down under "gravity". */
.confetti-piece.confetti-fall { width: 8px; height: 8px; animation: confettiFall 1.2s cubic-bezier(.2,.7,.4,1) forwards; }
.confetti-piece.confetti-dot { border-radius: 50%; width: 7px; height: 7px; }
.confetti-piece.confetti-strip { width: 4px; height: 11px; border-radius: 2px; }
@keyframes confettiFall {
  0%   { transform: translate(-50%,-50%) scale(0.4) rotate(0deg); opacity: 1; }
  35%  { transform: translate(calc(-50% + var(--dx)), calc(-50% + var(--dy))) scale(1) rotate(calc(var(--rot) * 0.4)); opacity: 1; }
  100% { transform: translate(calc(-50% + var(--dx) * 1.25), calc(-50% + var(--dy) + var(--fall))) scale(0.85) rotate(var(--rot)); opacity: 0; }
}

/* Checkbox: a spring pop plus a ring that ripples out. */
.done-check.just-checked, .priority-check.just-checked, #a-detail-done-btn.just-checked { animation: checkPop 0.5s var(--ease-spring); position: relative; }
.done-check.just-checked::after, .priority-check.just-checked::after {
  content: ''; position: absolute; inset: -2px; border-radius: 50%; border: 2px solid var(--green);
  animation: checkRing 0.6s var(--ease-out) forwards; pointer-events: none;
}
@keyframes checkPop { 0% { transform: scale(1); } 30% { transform: scale(0.82); } 65% { transform: scale(1.22); } 100% { transform: scale(1); } }
@keyframes checkRing { from { transform: scale(1); opacity: 0.9; } to { transform: scale(2.4); opacity: 0; } }

/* Card: a soft green wash that sweeps across once. */
.card.done-flash, .priority-card.done-flash { position: relative; overflow: hidden; }
.card.done-flash::after, .priority-card.done-flash::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(100deg, transparent 20%, color-mix(in oklch, var(--green) 22%, transparent) 50%, transparent 80%);
  animation: doneSweep 0.8s var(--ease-out) forwards;
}
@keyframes doneSweep { from { transform: translateX(-100%); } to { transform: translateX(100%); } }

/* The bar that slides up from the bottom. */
.done-toast {
  position: fixed; left: 50%; bottom: 24px; z-index: 10001;
  display: flex; align-items: center; gap: 14px; min-width: 300px; max-width: calc(100vw - 32px);
  padding: 14px 20px 14px 14px; box-sizing: border-box;
  background: var(--surface); border: 1px solid var(--border2); border-radius: 16px;
  box-shadow: 0 18px 50px rgba(0,0,0,0.35);
  opacity: 0; pointer-events: none; transform: translate(-50%, 24px) scale(0.96);
  transition: opacity 0.25s, transform 0.4s var(--ease-spring);
}
[data-theme="dark"] .done-toast { background: #151515; border-color: rgba(255,255,255,0.1); }
.done-toast.show { opacity: 1; transform: translate(-50%, 0) scale(1); }
.done-toast.dt-big { border-color: color-mix(in oklch, var(--green) 55%, transparent); box-shadow: 0 18px 50px rgba(0,0,0,0.35), 0 0 0 4px color-mix(in oklch, var(--green) 14%, transparent); }
.dt-badge {
  width: 40px; height: 40px; border-radius: 50%; flex-shrink: 0; display: flex; align-items: center; justify-content: center;
  background: var(--green); color: #fff;
}
.done-toast.show .dt-badge { animation: checkPop 0.55s 0.1s var(--ease-spring) backwards; }
.dt-badge svg { width: 22px; height: 22px; }
.dt-tick { stroke-dasharray: 16; stroke-dashoffset: 16; }
.done-toast.show .dt-tick { animation: dtTick 0.35s 0.25s var(--ease-out) forwards; }
@keyframes dtTick { to { stroke-dashoffset: 0; } }
.dt-main { min-width: 0; flex: 1; }
.dt-line { display: flex; align-items: baseline; gap: 7px; }
.dt-label { font-size: 14px; font-weight: 600; color: var(--text1); }
.dt-msg { font-size: 12.5px; color: var(--text2); margin-top: 2px; }

/* Odometer: the old number rolls up and out as the new one rolls in. */
.dt-odo { position: relative; display: inline-block; height: 26px; overflow: hidden; font-size: 24px; font-weight: 800; line-height: 26px; color: var(--text1); font-variant-numeric: tabular-nums; }
.dt-old, .dt-new { display: block; }
.dt-new { position: absolute; left: 0; top: 0; transform: translateY(100%); }
.done-toast.show .dt-old { animation: odoOut 0.45s 0.35s var(--ease-out) forwards; }
.done-toast.show .dt-new { animation: odoIn 0.45s 0.35s var(--ease-spring) forwards; color: var(--green); }
@keyframes odoOut { to { transform: translateY(-100%); opacity: 0; } }
@keyframes odoIn { to { transform: translateY(0); } }

.dt-week { display: flex; align-items: center; gap: 10px; margin-top: 8px; }
.dt-bar { flex: 1; height: 6px; border-radius: 3px; background: var(--surface2); overflow: hidden; min-width: 90px; }
[data-theme="dark"] .dt-bar { background: rgba(255,255,255,0.08); }
.dt-bar i { display: block; height: 100%; background: var(--green); transform-origin: left; transform: scaleX(0); transition: transform 0.7s 0.45s var(--ease-out); }
.dt-week-text { font-size: 11.5px; font-weight: 600; color: var(--text2); white-space: nowrap; font-variant-numeric: tabular-nums; }

@media (max-width: 600px) {
  .done-toast { bottom: calc(84px + env(safe-area-inset-bottom, 0px)); min-width: 0; width: calc(100vw - 24px); }
}
@media (prefers-reduced-motion: reduce) {
  .done-toast { transition: opacity 0.2s; transform: translate(-50%, 0); }
  .done-toast.show .dt-badge, .done-toast.show .dt-old, .done-toast.show .dt-new { animation: none; }
  .done-toast.show .dt-old { display: none; }
  .done-toast.show .dt-new { position: static; transform: none; }
  .dt-tick { stroke-dashoffset: 0; }
  .done-toast.show .dt-tick { animation: none; }
  .dt-bar i { transition: none; }
}

/* ===========================
   LINKS: "Your classes"
=========================== */
#class-links-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 10px; }
.class-link-card { padding: 0; margin: 0; overflow: hidden; display: flex; flex-direction: column; }
.class-link-main {
  display: flex; align-items: center; gap: 12px; padding: 14px 14px 10px; text-decoration: none; color: inherit;
  transition: background 0.15s;
}
.class-link-main:hover { background: color-mix(in oklch, var(--text1) 4%, transparent); }
.class-link-avatar {
  width: 38px; height: 38px; border-radius: 11px; flex-shrink: 0; display: flex; align-items: center; justify-content: center;
  font-size: 16px; font-weight: 800; color: oklch(0.82 0.12 var(--h)); background: oklch(0.6 0.14 var(--h) / 0.18);
}
[data-theme="light"] .class-link-avatar { color: oklch(0.45 0.15 var(--h)); background: oklch(0.6 0.14 var(--h) / 0.14); }
.class-link-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.class-link-name { font-size: 14.5px; font-weight: 700; color: var(--text1); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.class-link-sub { font-size: 12px; color: var(--text2); }
.class-link-out { width: 16px; height: 16px; color: var(--text2); flex-shrink: 0; transition: transform 0.2s var(--ease-out), color 0.15s; }
.class-link-main:hover .class-link-out { color: var(--text1); transform: translate(2px, -2px); }
.class-link-chips { display: flex; gap: 6px; padding: 0 14px 14px 64px; flex-wrap: wrap; }
.class-link-chip {
  font-size: 12px; font-weight: 600; color: var(--text2); text-decoration: none;
  padding: 5px 10px; border-radius: 8px; background: var(--surface2); border: 1px solid var(--border);
  transition: color 0.15s, border-color 0.15s;
}
[data-theme="dark"] .class-link-chip { background: rgba(255,255,255,0.05); border-color: rgba(255,255,255,0.07); }
.class-link-chip:hover { color: var(--text1); border-color: var(--border2); }
@media (max-width: 600px) { .class-link-chips { padding-left: 14px; } }

/* ===========================
   GOALS ↔ PRIORITY
=========================== */
.goal-linked { display: flex; flex-wrap: wrap; align-items: center; gap: 5px; margin-top: 6px; font-size: 11.5px; font-weight: 500; color: var(--text2); }
.goal-linked span { padding: 2px 8px; border-radius: 6px; background: var(--accent-soft); color: var(--accent-text); font-weight: 600; }
.priority-goal-tag {
  display: inline-flex; align-items: center; gap: 5px; margin-top: 6px; max-width: 100%;
  font-size: 11.5px; font-weight: 600; color: var(--accent-text);
  padding: 3px 9px 3px 7px; border-radius: 7px; background: var(--accent-soft);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.priority-goal-tag svg { width: 12px; height: 12px; flex-shrink: 0; }

/* ===========================
   COLORS: custom hue + light-mode logo
=========================== */
.swatch-custom {
  padding: 0; display: flex; align-items: center; justify-content: center; color: #fff;
  background: conic-gradient(from 0deg, oklch(0.62 0.2 0), oklch(0.7 0.17 90), oklch(0.62 0.18 180), oklch(0.56 0.2 270), oklch(0.62 0.2 360));
  font: inherit;
}
.swatch-custom svg { width: 13px; height: 13px; filter: drop-shadow(0 1px 1px rgba(0,0,0,0.4)); }
/* Once a custom color is chosen the swatch shows it, with the plus kept. */
.swatch-custom.has-color.active { background: var(--custom); }
.hue-picker { display: flex; align-items: center; gap: 12px; margin-top: 12px; animation: fadeUp 0.25s var(--ease-out); }
.hue-picker[hidden] { display: none; }
.hue-slider {
  -webkit-appearance: none; appearance: none; flex: 1; height: 14px; border-radius: 7px; cursor: pointer; outline: none;
  background: linear-gradient(to right, oklch(0.62 0.2 0), oklch(0.66 0.18 45), oklch(0.72 0.16 90), oklch(0.66 0.18 135), oklch(0.62 0.16 180), oklch(0.6 0.16 225), oklch(0.56 0.2 270), oklch(0.58 0.2 315), oklch(0.62 0.2 359));
}
.hue-slider::-webkit-slider-thumb { -webkit-appearance: none; width: 22px; height: 22px; border-radius: 50%; background: #fff; border: 2px solid rgba(0,0,0,0.25); box-shadow: 0 1px 4px rgba(0,0,0,0.35); }
.hue-slider::-moz-range-thumb { width: 22px; height: 22px; border-radius: 50%; background: #fff; border: 2px solid rgba(0,0,0,0.25); box-shadow: 0 1px 4px rgba(0,0,0,0.35); }
.hue-slider:focus-visible { box-shadow: 0 0 0 3px color-mix(in oklch, var(--text1) 20%, transparent); }
.hue-preview { width: 30px; height: 30px; border-radius: 9px; flex-shrink: 0; box-shadow: inset 0 0 0 1px rgba(0,0,0,0.12); }

/* Light mode: the cap and "Flow" carry the accent color (a soft gradient on
   "Flow") so the logo matches whatever color the student picked, instead of
   sitting there as the one plain-black thing on the page. Dark mode and the
   always-dark sign-in / splash screens keep the white mark. */
[data-theme="light"] .main-app .logo-mark { color: var(--accent); }
[data-theme="light"] .main-app .logo-word em {
  color: var(--accent-text);
  background: linear-gradient(100deg, var(--accent) 10%, oklch(0.5 0.2 calc(var(--accent-h) + 35)) 90%);
  -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
  padding-right: 2px; /* italic overhang would otherwise clip the last letter */
}

/* ===========================
   ONBOARDING + TUTORIALS: logo, motion
=========================== */
/* Logo in the onboarding header, settling in like the sign-in screen's. */
.onboard-flow-header { position: relative; }
.onboard-logo { justify-content: center; margin: 0 auto 14px; width: fit-content; }
.onboard-logo .logo-mark { animation: capSettle 0.9s 0.15s var(--ease-spring) backwards; }
.onboard-logo .logo-word { animation: fadeUp 0.5s 0.05s var(--ease-out) backwards; }
@media (min-width: 701px) {
  .onboard-logo { position: absolute; left: 28px; top: 50%; margin: 0; transform: translateY(-40%); }
}

/* Progress: the current pill fills in from the left as you arrive. */
.onboard-progress .dot.current { position: relative; overflow: hidden; }
.onboard-progress .dot.current::after {
  content: ''; position: absolute; inset: 0; background: color-mix(in oklch, var(--text1) 35%, transparent);
  transform-origin: left; animation: dotFill 0.6s var(--ease-out) forwards;
}
@keyframes dotFill { from { transform: scaleX(0); } to { transform: scaleX(1); opacity: 0; } }

/* Arriving step: icon pops, then title, text and fields cascade in. */
.onboard-flow-panel.is-current .onboard-flow-panel-body > * { animation: obIn 0.5s var(--ease-out) backwards; }
.onboard-flow-panel.is-current .onboard-flow-panel-body > :nth-child(1) { animation-delay: 0.12s; }
.onboard-flow-panel.is-current .onboard-flow-panel-body > :nth-child(2) { animation-delay: 0.18s; }
.onboard-flow-panel.is-current .onboard-flow-panel-body > :nth-child(3) { animation-delay: 0.24s; }
.onboard-flow-panel.is-current .onboard-flow-panel-body > :nth-child(4) { animation-delay: 0.29s; }
.onboard-flow-panel.is-current .onboard-flow-panel-body > :nth-child(5) { animation-delay: 0.34s; }
.onboard-flow-panel.is-current .onboard-flow-panel-body > :nth-child(6) { animation-delay: 0.39s; }
.onboard-flow-panel.is-current .onboard-flow-panel-body > :nth-child(n+7) { animation-delay: 0.44s; }
.onboard-flow-panel.is-current .onboard-flow-panel-footer { animation: obIn 0.5s 0.3s var(--ease-out) backwards; }
.onboard-flow-panel.is-current .onboard-title-icon { animation: obIconPop 0.6s 0.1s var(--ease-spring) backwards; }
@keyframes obIn { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
@keyframes obIconPop { from { opacity: 0; transform: scale(0.4) rotate(-18deg); } to { opacity: 1; transform: none; } }
.onboard-title-icon { width: 36px; height: 36px; border-radius: 11px; }
.onboard-title-icon svg { width: 19px; height: 19px; }
/* The tour step's slide handles its own entrance (below). */
#onboard-tour.is-current .onboard-flow-panel-body > .tour-slide { animation: none; }

/* Token instructions: a numbered checklist instead of a line-broken blob. */
.token-steps { list-style: none; margin: 4px 0 0; padding: 0; counter-reset: tok; display: grid; gap: 8px; }
.token-steps li {
  counter-increment: tok; display: flex; align-items: center; gap: 10px;
  font-size: 13px; color: var(--text2); line-height: 1.4;
}
.token-steps li b { color: var(--text1); font-weight: 600; }
.token-steps li::before {
  content: counter(tok); flex-shrink: 0; width: 22px; height: 22px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 700; color: var(--text1);
  background: var(--surface2); border: 1px solid var(--border2);
}
.onboard-flow-panel.is-current .token-steps li { animation: obIn 0.4s var(--ease-out) backwards; }
.onboard-flow-panel.is-current .token-steps li:nth-child(1) { animation-delay: 0.45s; }
.onboard-flow-panel.is-current .token-steps li:nth-child(2) { animation-delay: 0.5s; }
.onboard-flow-panel.is-current .token-steps li:nth-child(3) { animation-delay: 0.55s; }
.onboard-flow-panel.is-current .token-steps li:nth-child(4) { animation-delay: 0.6s; }
.onboard-flow-panel.is-current .token-steps li:nth-child(5) { animation-delay: 0.65s; }
.onboard-flow-panel.is-current .token-steps li:nth-child(6) { animation-delay: 0.7s; }

/* Finish button: turns green for the send-off. */
.onboard-btn.btn-success { background: var(--green); color: #fff; transition: background 0.25s; }

/* Tour: slides come in from the direction you are going, then the mock
   builds up piece by piece. */
.tour-slide { animation: none; }
.tour-slide.tour-in-next { animation: tourInNext 0.42s var(--ease-out); }
.tour-slide.tour-in-back { animation: tourInBack 0.42s var(--ease-out); }
@keyframes tourInNext { from { opacity: 0; transform: translateX(36px); } to { opacity: 1; transform: none; } }
@keyframes tourInBack { from { opacity: 0; transform: translateX(-36px); } to { opacity: 1; transform: none; } }
.tour-slide-icon { color: var(--text1); }
.tour-slide-icon svg { width: 28px; height: 28px; }
.tour-slide.tour-in-next .tour-slide-icon, .tour-slide.tour-in-back .tour-slide-icon { animation: obIconPop 0.55s 0.12s var(--ease-spring) backwards; }
.tour-mock { animation: none; }
.tour-slide.tour-in-next .tour-mock > *, .tour-slide.tour-in-back .tour-mock > * { animation: obIn 0.4s var(--ease-out) backwards; }
.tour-mock > :nth-child(1) { animation-delay: 0.15s !important; }
.tour-mock > :nth-child(2) { animation-delay: 0.25s !important; }
.tour-mock > :nth-child(3) { animation-delay: 0.35s !important; }
.tour-mock-tag { margin-left: auto; font-size: 10.5px; color: var(--text2); }
.tour-mock-goal { margin-left: auto; font-size: 10px; font-weight: 700; padding: 2px 7px; border-radius: 6px; background: var(--accent-soft); color: var(--accent-text); }
.tour-mock-kind { flex-shrink: 0; font-size: 9.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; padding: 2px 6px; border-radius: 5px; }
.tour-mock-kind.fb { background: var(--green-soft); color: var(--green); }
.tour-mock-kind.an { background: var(--accent-soft); color: var(--accent-text); }
.tour-mock-cal-cell.active { animation: chipPop 0.4s 0.5s var(--ease-spring) backwards; }
/* Timer ring that actually ticks down while you look at it. */
.tour-mock-timer-ring { position: relative; border: none; }
.tour-mock-timer-ring svg { position: absolute; inset: 0; width: 100%; height: 100%; transform: rotate(-90deg); }
.tour-mock-timer-ring circle { fill: none; stroke: var(--accent); stroke-width: 4; stroke-linecap: round; stroke-dasharray: 195; stroke-dashoffset: 0; animation: tourRing 6s linear infinite; }
@keyframes tourRing { to { stroke-dashoffset: 195; } }
.tour-mock-timer-ring span { position: relative; }
.tour-mock-bubble-a { animation-delay: 0.6s !important; }

/* Tutorial brand badge (Links tutorial, study-goal popup). */
.tut-brand {
  display: inline-flex; align-items: center; gap: 7px; margin-bottom: 12px;
  font-size: 11px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--text2);
}
.tut-brand-cap { width: 20px; height: 20px; display: flex; color: var(--text1); transform: rotate(-24deg); animation: capSettle 0.8s 0.1s var(--ease-spring) backwards; }
.tut-brand-cap svg { width: 100%; height: 100%; }
.links-tutorial-slide-icon svg { width: 24px; height: 24px; }
.tut-slide-next .tut-ex-browser > *, .tut-slide-next .tut-ex-form > *, .tut-slide-back .tut-ex-browser > *, .tut-slide-back .tut-ex-form > * { animation: obIn 0.35s var(--ease-out) backwards; }
.tut-ex-form > :nth-child(2), .tut-ex-browser > :nth-child(2) { animation-delay: 0.1s !important; }
.tut-ex-form > :nth-child(3), .tut-ex-browser > :nth-child(3) { animation-delay: 0.2s !important; }

/* Study-goal popup: a proper entrance instead of a plain fade. */
#study-goal-onboard-card { animation: obCardIn 0.5s var(--ease-spring); }
@keyframes obCardIn { from { opacity: 0; transform: translateY(18px) scale(0.96); } to { opacity: 1; transform: none; } }
#study-goal-onboard-card .focus-duration-row > * { animation: chipPop 0.35s var(--ease-spring) backwards; }
#study-goal-onboard-card .focus-duration-row > :nth-child(2) { animation-delay: 0.04s; }
#study-goal-onboard-card .focus-duration-row > :nth-child(3) { animation-delay: 0.08s; }
#study-goal-onboard-card .focus-duration-row > :nth-child(4) { animation-delay: 0.12s; }
#study-goal-onboard-card .focus-duration-row > :nth-child(5) { animation-delay: 0.16s; }

@media (prefers-reduced-motion: reduce) {
  .onboard-logo .logo-mark, .onboard-logo .logo-word, .onboard-progress .dot.current::after,
  .onboard-flow-panel.is-current .onboard-flow-panel-body > *, .onboard-flow-panel.is-current .onboard-flow-panel-footer,
  .onboard-flow-panel.is-current .onboard-title-icon, .onboard-flow-panel.is-current .token-steps li,
  .tour-slide.tour-in-next, .tour-slide.tour-in-back, .tour-slide .tour-slide-icon, .tour-mock > *,
  .tour-mock-cal-cell.active, .tour-mock-timer-ring circle, .tut-brand-cap,
  .tut-ex-form > *, .tut-ex-browser > *, #study-goal-onboard-card, #study-goal-onboard-card .focus-duration-row > * { animation: none !important; }
}

/* ===========================
   TOUR: interactive calendar + working timer
=========================== */
/* Calendar days behave like the real Upcoming calendar: hover lifts and
   previews, click pins (the pinned day is the solid one). */
.tour-mock-cal-cell {
  border: 1px solid var(--border2); font: inherit; font-size: 11px; font-weight: 600; color: var(--text2);
  cursor: pointer; flex-direction: column; gap: 2px; padding: 0;
  transition: transform 0.18s var(--ease-out), background 0.15s, border-color 0.15s, color 0.15s;
}
[data-theme="dark"] .tour-mock-cal-cell, .onboard-flow .tour-mock-cal-cell { background: rgba(255,255,255,0.04); border-color: rgba(255,255,255,0.08); }
.tour-mock-cal-cell:hover, .tour-mock-cal-cell:focus-visible { transform: translateY(-2px); border-color: var(--border2); color: var(--text1); background: rgba(255,255,255,0.09); outline: none; }
.tour-mock-cal-cell.active { background: var(--btn-bg); color: var(--btn-fg); border-color: transparent; }
.tour-mock-cal-count {
  min-width: 13px; height: 13px; padding: 0 3px; box-sizing: border-box; border-radius: 7px;
  background: var(--text1); color: var(--bg); font-size: 8.5px; font-weight: 800; line-height: 13px; text-align: center;
}
.tour-mock-cal-cell.active .tour-mock-cal-count { background: var(--btn-fg); color: var(--btn-bg); }
.tour-mock-cal-preview {
  margin-top: 4px; padding: 10px 12px; border-radius: 10px; background: var(--surface);
  border: 1px solid var(--border2); text-align: left; transition: border-color 0.15s;
}
.onboard-flow .tour-mock-cal-preview { background: rgba(255,255,255,0.04); border-color: rgba(255,255,255,0.08); }
.tour-mock-cal-preview.previewing { border-style: dashed; }
.tour-mock-cal-preview.swap > * { animation: obIn 0.25s var(--ease-out) backwards; }
.tcp-head { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; font-size: 12px; font-weight: 700; color: var(--text1); margin-bottom: 6px; }
.tcp-hint { font-size: 10px; font-weight: 600; color: var(--text2); text-transform: uppercase; letter-spacing: 0.05em; }
.tcp-item { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--text1); padding: 3px 0; }
.tcp-empty { font-size: 12px; color: var(--text2); }

/* Working timer: the ring drains in step with the countdown. */
.tour-mock-timer-ring { width: 96px; height: 96px; font-size: 17px; font-variant-numeric: tabular-nums; }
.tour-mock-timer-ring circle { animation: none; }
.tour-mock-timer-ring .tt-track { fill: none; stroke: var(--border2); stroke-width: 4; }
.onboard-flow .tour-mock-timer-ring .tt-track { stroke: rgba(255,255,255,0.1); }
.tour-mock-timer-ring .tt-arc { fill: none; stroke: var(--accent); stroke-width: 4; stroke-linecap: round; transition: stroke-dashoffset 0.25s linear, stroke 0.3s; }
.tour-mock-timer.paused .tt-time { animation: ttBlink 1.2s ease-in-out infinite; }
@keyframes ttBlink { 50% { opacity: 0.35; } }
.tour-mock-timer.done .tt-arc { stroke: var(--green); }
.tt-controls { display: flex; gap: 8px; }
.tt-btn {
  width: 34px; height: 34px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--border2); background: var(--surface); color: var(--text1); cursor: pointer;
  transition: transform 0.15s var(--ease-spring), background 0.15s;
}
.onboard-flow .tt-btn { background: rgba(255,255,255,0.06); border-color: rgba(255,255,255,0.1); }
.tt-btn:hover { transform: scale(1.08); }
.tt-btn:active { transform: scale(0.94); }
.tt-btn svg { width: 15px; height: 15px; }
.tt-toggle { background: var(--btn-bg); color: var(--btn-fg); border-color: transparent; }
.onboard-flow .tt-toggle { background: var(--btn-bg); border-color: transparent; }
@media (prefers-reduced-motion: reduce) {
  .tour-mock-cal-cell, .tour-mock-timer-ring .tt-arc { transition: none; }
  .tour-mock-cal-cell:hover { transform: none; }
  .tour-mock-cal-preview.swap > *, .tour-mock-timer.paused .tt-time { animation: none; }
}

/* ===========================
   STUDY TIMERS: drain ring (focus + deep work)
=========================== */
.ft { display: flex; flex-direction: column; align-items: center; }
.ft-title { margin-bottom: 4px !important; }
.ft-ring { position: relative; width: 210px; height: 210px; margin: 14px 0 10px; }
.ft-ring svg { width: 100%; height: 100%; transform: rotate(-90deg); overflow: visible; }
.ft-track { fill: none; stroke: var(--border2); stroke-width: 10; }
[data-theme="dark"] .ft-track { stroke: rgba(255,255,255,0.08); }
.ft-arc {
  fill: none; stroke: var(--accent); stroke-width: 10; stroke-linecap: round;
  transition: stroke-dashoffset 0.3s linear, stroke 0.3s;
  filter: drop-shadow(0 0 6px color-mix(in oklch, var(--accent) 45%, transparent));
}
.ft-break .ft-arc { stroke: var(--green); filter: drop-shadow(0 0 6px color-mix(in oklch, var(--green) 45%, transparent)); }
.ft-deep .ft-arc { stroke: var(--red); filter: drop-shadow(0 0 6px color-mix(in oklch, var(--red) 40%, transparent)); }
.ft-center { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; }
.ft-time { font-size: 46px; font-weight: 800; letter-spacing: -1px; color: var(--text1); font-variant-numeric: tabular-nums; line-height: 1; }
.ft-of { font-size: 12px; font-weight: 600; color: var(--text2); margin-top: 6px; text-transform: uppercase; letter-spacing: 0.06em; }
/* Paused: the number breathes and the ring dims, so it reads as on hold. */
.ft-ring.is-paused .ft-time { animation: ftBreathe 1.6s ease-in-out infinite; }
.ft-ring.is-paused .ft-arc { opacity: 0.45; }
@keyframes ftBreathe { 50% { opacity: 0.4; } }
.ft-rounds { display: flex; gap: 6px; justify-content: center; min-height: 8px; margin-bottom: 10px; }
.ft-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--border2); }
[data-theme="dark"] .ft-dot { background: rgba(255,255,255,0.12); }
.ft-dot.done { background: var(--accent); }
.ft-dot.now { background: var(--accent); animation: ftPulse 1.4s ease-in-out infinite; }
@keyframes ftPulse { 50% { transform: scale(1.5); opacity: 0.55; } }
.ft-note { margin: 0 0 10px !important; }
.ft-controls { display: flex; gap: 14px; justify-content: center; align-items: center; margin: 4px 0 12px; }
.ft-btn {
  width: 48px; height: 48px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
  background: var(--surface2); border: 1px solid var(--border2); color: var(--text1); cursor: pointer;
  transition: transform 0.18s var(--ease-spring), background 0.15s;
}
[data-theme="dark"] .ft-btn { background: rgba(255,255,255,0.06); border-color: rgba(255,255,255,0.1); }
.ft-btn:hover { transform: scale(1.07); }
.ft-btn:active { transform: scale(0.93); }
.ft-btn svg { width: 18px; height: 18px; }
.ft-btn.ft-main { width: 62px; height: 62px; background: var(--btn-bg); color: var(--btn-fg); border-color: transparent; box-shadow: 0 6px 20px color-mix(in oklch, var(--btn-bg) 30%, transparent); }
.ft-btn.ft-main svg { width: 22px; height: 22px; }
.ft-hint { font-size: 12px !important; margin-bottom: 0 !important; }
/* Entrance when a phase starts (the layout is only rebuilt on phase or
   pause changes, so this plays at those moments, not every second). */
.ft .ft-ring { animation: ftRingIn 0.55s var(--ease-spring) backwards; }
.ft .ft-controls { animation: obIn 0.4s 0.15s var(--ease-out) backwards; }
@keyframes ftRingIn { from { opacity: 0; transform: scale(0.85); } to { opacity: 1; transform: none; } }
#focus-minibar-pause, #deepwork-minibar-pause { display: flex; align-items: center; justify-content: center; }
#focus-minibar-pause svg, #deepwork-minibar-pause svg { width: 15px; height: 15px; }
@media (max-width: 420px) { .ft-ring { width: 180px; height: 180px; } .ft-time { font-size: 40px; } }
@media (prefers-reduced-motion: reduce) {
  .ft-arc { transition: none; }
  .ft-ring.is-paused .ft-time, .ft-dot.now, .ft .ft-ring, .ft .ft-controls { animation: none; }
}

/* ===========================
   APP-WIDE: the sign-in screen's look, everywhere
   Glass cards (the same tokens as the login's mock cards), headings in the
   login's voice, and buttons that match its button instead of the older
   all-caps pills.
=========================== */
/* Page header: glass icon tile + title + one live line. */
.page-head { display: flex; align-items: center; gap: 14px; margin: 2px 0 22px; }
.page-head-icon {
  width: 44px; height: 44px; border-radius: 13px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center; color: var(--text1);
  background: var(--glass-bg); border: 1px solid var(--glass-border);
  box-shadow: var(--glass-shadow), 0 0 32px color-mix(in oklch, var(--text1) 7%, transparent);
}
.page-head-icon svg { width: 21px; height: 21px; }
.page-head-text { min-width: 0; }
.page-head-title { margin: 0; font-size: 26px; font-weight: 700; letter-spacing: -0.5px; line-height: 1.15; color: var(--text1); }
.page-head-sub { font-size: 14px; color: var(--text2); margin-top: 3px; min-height: 1.3em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.page-head.in .page-head-icon { animation: obIconPop 0.55s var(--ease-spring) backwards; }
.page-head.in .page-head-title { animation: obIn 0.45s 0.05s var(--ease-out) backwards; }
.page-head.in .page-head-sub { animation: obIn 0.45s 0.12s var(--ease-out) backwards; }
/* The header now opens each page, so the first section label sits under it. */
.page > .page-head + .section-label { margin-top: 0; }
@media (max-width: 600px) {
  .page-head { margin-bottom: 16px; gap: 12px; }
  .page-head-icon { width: 38px; height: 38px; border-radius: 11px; }
  .page-head-icon svg { width: 18px; height: 18px; }
  .page-head-title { font-size: 22px; }
  .page-head-sub { font-size: 13px; }
}

/* Glass surfaces for every card-like block, light and dark. */
.card, .priority-card, .goal-card, .study-session-card, .ai-box, .empty-box {
  background: var(--glass-bg); border: 1px solid var(--glass-border); box-shadow: var(--glass-shadow);
}
[data-theme="dark"] .card { border-color: var(--glass-border); box-shadow: var(--glass-shadow); }
.card:has(.card-title-link):hover, .card[onclick]:hover { border-color: color-mix(in oklch, var(--text1) 18%, var(--glass-border)); }
/* Overdue keeps its red edge and a faint red wash on top of the glass. */
.card.overdue-card, [data-theme="dark"] .card.overdue-card {
  border-color: oklch(0.62 0.2 22 / 0.4);
  background: linear-gradient(135deg, var(--glass-bg) 0%, oklch(0.62 0.2 22 / 0.08) 100%);
}

/* Buttons: the login button's shape and voice (sentence case, 12px radius)
   instead of all-caps pills; the old green secondary becomes neutral glass. */
[data-theme="dark"] .settings-btn,
[data-theme="dark"] .sync-btn,
[data-theme="dark"] .change-courses-btn,
[data-theme="dark"] .disconnect-btn {
  border-radius: 12px; text-transform: none; letter-spacing: 0; font-size: 14px; font-weight: 600;
}
.settings-btn { border-radius: 12px; }
.sync-btn {
  background: var(--glass-bg); color: var(--text1); border: 1px solid var(--glass-border); border-radius: 12px;
}
.sync-btn:hover:not(:disabled) { opacity: 1; border-color: color-mix(in oklch, var(--text1) 22%, var(--glass-border)); }

/* Section labels: a hairline under the label ties each section together. */
/* Plain labels only: ones carrying a badge or a "See all" link keep their
   own layout. */
.section-label:not(:has(*)) { display: flex; align-items: center; gap: 10px; }
.section-label:not(:has(*))::after { content: ''; flex: 1; height: 1px; background: linear-gradient(to right, var(--glass-border), transparent); }

@media (prefers-reduced-motion: reduce) {
  .page-head.in .page-head-icon, .page-head.in .page-head-title, .page-head.in .page-head-sub { animation: none; }
}

/* ===========================
   HOME: Focus now  |  LINKS: pin + class groups
=========================== */
.home-focus-now {
  width: 100%; display: flex; align-items: center; gap: 12px; margin: 2px 0 14px; padding: 12px 14px; text-align: left;
  background: var(--glass-bg); border: 1px solid var(--glass-border); border-radius: var(--card-radius, 14px);
  color: var(--text1); font: inherit; cursor: pointer;
  transition: transform 0.3s var(--ease-spring), border-color 0.2s, background 0.2s;
}
.home-focus-now:hover { transform: translateY(-2px); border-color: color-mix(in oklch, var(--accent) 45%, var(--glass-border)); }
.home-focus-now:active { transform: scale(0.99); }
.home-focus-now:disabled { opacity: 0.6; cursor: progress; }
.hfn-icon {
  width: 38px; height: 38px; border-radius: 50%; flex-shrink: 0; display: flex; align-items: center; justify-content: center;
  background: var(--btn-bg); color: var(--btn-fg); box-shadow: 0 6px 18px color-mix(in oklch, var(--btn-bg) 28%, transparent);
}
.hfn-icon svg { width: 16px; height: 16px; margin-left: 2px; }
.hfn-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.hfn-text b { font-size: 14px; font-weight: 700; }
.hfn-text span { font-size: 12px; color: var(--text2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hfn-arrow { width: 16px; height: 16px; color: var(--text2); flex-shrink: 0; transition: transform 0.2s var(--ease-out); }
.home-focus-now:hover .hfn-arrow { transform: translateX(3px); color: var(--text1); }

.home-qlink.is-pinned { border-color: color-mix(in oklch, var(--accent) 35%, var(--glass-border)); }
.link-pin, .link-card .goal-remove { flex-shrink: 0; }
.link-pin {
  width: 30px; height: 30px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
  background: none; border: none; color: var(--text2); cursor: pointer; transition: color 0.15s, transform 0.25s var(--ease-spring);
}
.link-pin svg { width: 16px; height: 16px; fill: none; }
.link-pin:hover { color: var(--text1); transform: scale(1.12); }
.link-pin.on { color: var(--amber); }
.link-pin.on svg { fill: currentColor; }
.link-card.pinned { border-color: color-mix(in oklch, var(--amber) 28%, var(--glass-border)); }
.link-class-select {
  flex-shrink: 0; max-width: 130px; font: inherit; font-size: 12px; color: var(--text2); cursor: pointer;
  background: var(--surface2); border: 1px solid var(--border2); border-radius: 8px; padding: 5px 8px; outline: none;
}
[data-theme="dark"] .link-class-select { background: rgba(255,255,255,0.05); border-color: rgba(255,255,255,0.09); }
.link-class-select:hover, .link-class-select:focus-visible { color: var(--text1); border-color: color-mix(in oklch, var(--text1) 25%, transparent); }
.link-group { margin-bottom: 10px; }
.link-group-head {
  display: flex; align-items: center; gap: 8px; margin: 14px 2px 8px;
  font-size: 12px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--text2);
}
.link-group-count { padding: 1px 7px; border-radius: 9px; background: var(--surface2); font-size: 10.5px; }
@media (max-width: 600px) {
  .link-card { flex-wrap: wrap; }
  .link-class-select { max-width: none; order: 5; flex: 1 0 100%; }
}
@media (prefers-reduced-motion: reduce) { .home-focus-now, .link-pin, .hfn-arrow { transition: none; } }

/* ===========================
   UPDATES: save for later + mute a class
=========================== */
.upd-card { position: relative; }
.upd-save {
  flex-shrink: 0; align-self: flex-start; width: 32px; height: 32px; margin: -4px -6px 0 0; border-radius: 50%;
  display: flex; align-items: center; justify-content: center; background: none; border: none;
  color: var(--text2); cursor: pointer; transition: color 0.15s, transform 0.25s var(--ease-spring), background 0.15s;
}
.upd-save svg { width: 17px; height: 17px; fill: none; }
.upd-save:hover { color: var(--text1); background: var(--surface2); transform: scale(1.08); }
.upd-save.on { color: var(--amber); }
.upd-save.on svg { fill: currentColor; animation: chipPop 0.35s var(--ease-spring); }
.upd-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; margin-top: 8px; }
.upd-actions .canvas-link { margin: 0; }
.upd-mute {
  background: none; border: none; padding: 0; font: inherit; font-size: 12.5px; font-weight: 600;
  color: var(--text2); cursor: pointer; text-decoration: underline; text-underline-offset: 3px; text-decoration-color: color-mix(in oklch, currentColor 40%, transparent);
}
.upd-mute:hover { color: var(--text1); }
.upd-muted { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: 4px 0 10px; }
.upd-muted-label { font-size: 11px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--text2); margin-right: 2px; }
.upd-muted-chip {
  display: inline-flex; align-items: center; gap: 6px; padding: 4px 8px 4px 10px; border-radius: 99px;
  background: var(--surface2); border: 1px solid var(--border2); color: var(--text2); font: inherit; font-size: 12px; font-weight: 600; cursor: pointer;
  transition: color 0.15s, border-color 0.15s;
}
.upd-muted-chip svg { width: 11px; height: 11px; }
.upd-muted-chip:hover { color: var(--text1); border-color: color-mix(in oklch, var(--text1) 30%, transparent); }
.upd-count.quiet { background: var(--surface2); color: var(--text2); }
@media (prefers-reduced-motion: reduce) { .upd-save.on svg { animation: none; } .upd-save { transition: none; } }

/* ===========================
   UPCOMING: week view + drag and drop
=========================== */
.cal-view { flex: 0 0 auto; width: auto; padding: 2px; }
.cal-view .seg-btn { padding: 4px 10px; font-size: 11.5px; }
.due-cal-card .cal-header { gap: 8px; flex-wrap: wrap; }

/* Week view: the calendar takes the full width, the day panel sits under it. */
.due-cal-card.week-view { max-width: none; }
@media (min-width: 1100px) {
  .due-cal-layout:has(.week-view) { grid-template-columns: minmax(0, 1fr); }
  .due-cal-layout:has(.week-view) .due-day-panel { position: static; max-height: none; }
}
.cal-week-grid { gap: 8px; }
.cal-wday {
  aspect-ratio: auto; min-height: 168px; align-items: stretch; justify-content: flex-start;
  padding: 10px 8px; gap: 8px; text-align: left; min-width: 0;
}
.cwd-head { display: flex; align-items: baseline; justify-content: space-between; gap: 6px; }
.cwd-dow { font-size: 10.5px; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase; color: var(--text2); }
.cal-wday .cal-day-num { font-size: 18px; font-weight: 700; }
.cal-wday.today .cal-day-num { color: var(--accent-text); }
.cwd-items { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.cwd-item {
  display: flex; align-items: center; gap: 6px; min-width: 0; padding: 4px 6px; border-radius: 6px;
  font-size: 11.5px; line-height: 1.25; color: var(--text1); background: var(--surface2);
}
[data-theme="dark"] .cwd-item { background: rgba(255,255,255,0.06); }
.cwd-dot { width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0; background: var(--accent); }
.cwd-item.study .cwd-dot { background: var(--green); }
.cwd-item.done { opacity: 0.5; text-decoration: line-through; }
.cwd-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cwd-more, .cwd-empty { font-size: 11px; color: var(--text2); padding: 0 6px; }
.cwd-empty { opacity: 0.55; }
@media (max-width: 760px) {
  /* Seven columns are too narrow on a phone: stack the days as rows. */
  .cal-week-grid { grid-template-columns: 1fr; gap: 6px; }
  .cal-wday { min-height: 0; flex-direction: row; gap: 12px; align-items: flex-start; }
  .cwd-head { flex-direction: column; align-items: flex-start; gap: 2px; width: 44px; flex-shrink: 0; }
  .cwd-items { flex: 1; }
}
.cal-dow-row { display: grid; }
.due-cal-card.week-view .cal-dow-row { display: none; }

/* Dragging */
.cal-drag-row { display: flex; align-items: center; gap: 12px; margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--glass-border); }
.cal-drag-chip {
  display: inline-flex; align-items: center; gap: 7px; padding: 6px 12px 6px 8px; border-radius: 9px; flex-shrink: 0;
  font-size: 12px; font-weight: 700; color: var(--text1); background: var(--surface2); border: 1px dashed var(--border2);
  cursor: grab; user-select: none; -webkit-user-select: none; transition: transform 0.2s var(--ease-spring), border-color 0.15s;
}
[data-theme="dark"] .cal-drag-chip { background: rgba(255,255,255,0.06); border-color: rgba(255,255,255,0.18); }
.cal-drag-chip svg { width: 12px; height: 12px; color: var(--text2); }
.cal-drag-chip:hover { transform: translateY(-1px); border-color: color-mix(in oklch, var(--text1) 35%, transparent); }
.cal-drag-chip:active { cursor: grabbing; }
.cal-drag-hint { font-size: 11.5px; color: var(--text2); line-height: 1.4; }
/* Touch screens cannot drag: the + Schedule study time button covers them. */
@media (hover: none) { .cal-drag-row { display: none; } }
.dragging { opacity: 0.45; }
.study-session-card[draggable="true"] { cursor: grab; }
.cal-day.drop-target {
  background: var(--accent-soft); border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in oklch, var(--accent) 22%, transparent); transform: scale(1.03);
}
@media (prefers-reduced-motion: reduce) { .cal-drag-chip { transition: none; } .cal-day.drop-target { transform: none; } }

/* ===========================
   ASSIGNMENTS: type chips + private notes
=========================== */
.aw-chips { display: flex; gap: 8px; overflow-x: auto; scrollbar-width: none; padding: 2px 1px 6px; margin-bottom: 2px; }
.aw-chips::-webkit-scrollbar { display: none; }
.aw-chip {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 7px; padding: 6px 12px; border-radius: 99px;
  font: inherit; font-size: 12.5px; font-weight: 600; color: var(--text2); cursor: pointer;
  background: var(--glass-bg); border: 1px solid var(--glass-border);
  transition: color 0.15s, border-color 0.15s, background 0.15s, transform 0.2s var(--ease-spring);
}
.aw-chip span { font-size: 11px; font-weight: 700; padding: 1px 6px; border-radius: 9px; background: var(--surface2); color: var(--text2); }
.aw-chip:hover { color: var(--text1); transform: translateY(-1px); }
.aw-chip.active { color: var(--btn-fg); background: var(--btn-bg); border-color: transparent; }
.aw-chip.active span { background: color-mix(in oklch, var(--btn-fg) 18%, transparent); color: var(--btn-fg); }

.a-note-ind { display: inline-flex; vertical-align: -2px; margin-left: 7px; color: var(--text2); }
.a-note-ind svg { width: 14px; height: 14px; }
.a-note-input { width: 100%; box-sizing: border-box; resize: none; line-height: 1.5; min-height: 84px; font-size: 14px; margin-bottom: 4px; }
.a-note-status { min-height: 16px; font-size: 11.5px; color: var(--text2); text-align: right; }
@media (prefers-reduced-motion: reduce) { .aw-chip { transition: none; } }

/* ===========================
   PRIORITY: "Why this rank?"
=========================== */
.priority-why {
  display: inline-flex; align-items: center; gap: 4px; margin: 6px 8px 0 0; padding: 2px 0; background: none; border: none;
  font: inherit; font-size: 12px; font-weight: 600; color: var(--text2); cursor: pointer; transition: color 0.15s;
}
.priority-why:hover { color: var(--text1); }
.priority-why svg { width: 13px; height: 13px; transition: transform 0.25s var(--ease-out); }
.priority-why.open svg { transform: rotate(180deg); }
/* Grid-rows trick: animates open to the content's own height. */
.priority-why-panel { display: grid; grid-template-rows: 0fr; opacity: 0; transition: grid-template-rows 0.3s var(--ease-out), opacity 0.2s; }
.priority-why-panel > ul { min-height: 0; overflow: hidden; margin: 0; padding: 0; list-style: none; }
.priority-card.why-open .priority-why-panel { grid-template-rows: 1fr; opacity: 1; }
.priority-why-panel li {
  position: relative; padding: 5px 0 0 14px; font-size: 12.5px; line-height: 1.5; color: var(--text2);
}
.priority-why-panel li::before { content: ''; position: absolute; left: 2px; top: 12px; width: 5px; height: 5px; border-radius: 50%; background: var(--text2); opacity: 0.7; }
.priority-why-panel ul { padding-bottom: 2px; }
@media (prefers-reduced-motion: reduce) { .priority-why-panel, .priority-why svg { transition: none; } }

/* ===========================
   STUDY: weekly chart + background sound
=========================== */
.study-chart { padding: 18px 18px 14px; }
.sc-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-bottom: 14px; }
.sc-total { display: flex; align-items: baseline; gap: 8px; }
.sc-total b { font-size: 24px; font-weight: 800; letter-spacing: -0.5px; color: var(--text1); }
.sc-total span, .sc-delta { font-size: 12.5px; color: var(--text2); }
.sc-delta.up { color: var(--green); font-weight: 600; }
.sc-delta.down { color: var(--amber); font-weight: 600; }
.sc-plot { position: relative; height: 150px; padding-top: 4px; }
.sc-cols { position: relative; z-index: 1; display: grid; grid-template-columns: repeat(7, 1fr); gap: 8px; height: 100%; }
.sc-col { display: flex; flex-direction: column; align-items: center; min-width: 0; height: 100%; }
.sc-track { flex: 1; width: 100%; max-width: 44px; display: flex; align-items: flex-end; min-height: 0; }
.sc-bar {
  width: 100%; border-radius: 8px 8px 3px 3px; transform-origin: bottom;
  background: color-mix(in oklch, var(--text1) 22%, transparent);
  animation: scGrow 0.7s calc(var(--i) * 0.05s) var(--ease-out) backwards; transition: background 0.2s;
}
.sc-col.met .sc-bar { background: var(--green); }
.sc-col.today .sc-bar { background: var(--accent); }
.sc-col.today.met .sc-bar { background: var(--green); }
.sc-col:hover .sc-bar { filter: brightness(1.2); }
.sc-val { height: 16px; font-size: 11px; font-weight: 700; color: var(--text2); font-variant-numeric: tabular-nums; }
.sc-day { margin-top: 8px; font-size: 11px; font-weight: 600; color: var(--text2); }
.sc-col.today .sc-day { color: var(--text1); }
/* Daily goal as a dashed line across the bars. */
.sc-goal { position: absolute; left: 0; right: 0; z-index: 0; border-top: 1px dashed color-mix(in oklch, var(--text1) 35%, transparent); pointer-events: none; margin-bottom: 38px; }
.sc-goal span { position: absolute; right: 0; top: -17px; font-size: 10.5px; font-weight: 600; color: var(--text2); background: var(--bg); padding: 0 4px; }
@keyframes scGrow { from { transform: scaleY(0); } to { transform: scaleY(1); } }

.ft-sound { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 6px; margin: 4px 0 10px; }
.ft-sound-icon { display: flex; color: var(--text2); margin-right: 2px; }
.ft-sound-icon svg { width: 16px; height: 16px; }
.ft-sound-btn {
  padding: 5px 10px; border-radius: 99px; font: inherit; font-size: 12px; font-weight: 600; cursor: pointer;
  color: var(--text2); background: var(--surface2); border: 1px solid var(--border2); transition: color 0.15s, background 0.15s, border-color 0.15s;
}
[data-theme="dark"] .ft-sound-btn { background: rgba(255,255,255,0.05); border-color: rgba(255,255,255,0.09); }
.ft-sound-btn:hover { color: var(--text1); }
.ft-sound-btn.active { color: var(--btn-fg); background: var(--btn-bg); border-color: transparent; }
.ft-sound-vol { width: 100%; max-width: 180px; margin-top: 4px; accent-color: var(--accent); cursor: pointer; }
#focus-body > .focus-phase-label + .ft-sound, #deepwork-body > .focus-phase-label + .ft-sound { margin-bottom: 14px; }
@media (max-width: 420px) { .sc-plot { height: 130px; } .sc-cols { gap: 4px; } }
@media (prefers-reduced-motion: reduce) { .sc-bar { animation: none; } .ft-sound-btn { transition: none; } }

/* ===========================
   GRADES: trend line + what-if calculator
=========================== */
.grade-spark { display: flex; align-items: center; gap: 8px; margin: 8px 0 2px; }
.grade-spark svg { width: 100px; height: 26px; overflow: visible; }
.gs-line, .gt-line { fill: none; stroke: var(--text2); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; vector-effect: non-scaling-stroke; stroke-dasharray: 1; stroke-dashoffset: 0; animation: gsDraw 0.9s var(--ease-out) backwards; }
@keyframes gsDraw { from { stroke-dashoffset: 1; } }
.gs-end, .gt-dot { fill: var(--text2); }
.grade-spark.up .gs-line, .gt.up .gt-line { stroke: var(--green); }
.grade-spark.up .gs-end, .gt.up .gt-dot { fill: var(--green); }
.grade-spark.down .gs-line, .gt.down .gt-line { stroke: var(--amber); }
.grade-spark.down .gs-end, .gt.down .gt-dot { fill: var(--amber); }
.gs-delta { font-size: 11px; font-weight: 700; color: var(--text2); font-variant-numeric: tabular-nums; }
.grade-spark.up .gs-delta { color: var(--green); }
.grade-spark.down .gs-delta { color: var(--amber); }

.gt { margin: 0 0 16px; padding: 14px 16px 10px; border-radius: var(--card-radius, 14px); background: var(--glass-bg); border: 1px solid var(--glass-border); }
.gt-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-bottom: 8px; }
.gt-title { font-size: 12px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--text2); }
.gt-note { font-size: 12.5px; font-weight: 600; color: var(--text2); }
.gt.up .gt-note { color: var(--green); }
.gt.down .gt-note { color: var(--amber); }
.gt svg { width: 100%; height: 90px; overflow: visible; }
.gt-area { fill: color-mix(in oklch, var(--text2) 10%, transparent); stroke: none; }
.gt.up .gt-area { fill: color-mix(in oklch, var(--green) 12%, transparent); }
.gt.down .gt-area { fill: color-mix(in oklch, var(--amber) 12%, transparent); }
.gt-axis { display: flex; justify-content: space-between; margin-top: 6px; font-size: 11px; color: var(--text2); }

.gw { padding: 16px 18px; margin-bottom: 16px; }
.gw-title { font-size: 16px; font-weight: 700; color: var(--text1); margin-bottom: 12px; }
.gw-label { display: block; font-size: 12px; font-weight: 600; color: var(--text2); margin: 10px 0 6px; }
.gw-select { margin-bottom: 0 !important; }
.gw-custom { display: flex; align-items: center; gap: 8px; margin-top: 8px; font-size: 13px; color: var(--text2); }
.gw-custom input { width: 100px; margin-bottom: 0; }
.gw-slider { display: flex; align-items: center; gap: 14px; }
.gw-slider input { flex: 1; accent-color: var(--accent); cursor: pointer; }
.gw-slider b { min-width: 46px; text-align: right; font-size: 15px; font-variant-numeric: tabular-nums; }
.gw-result { margin: 16px 0 6px; padding: 14px; border-radius: 12px; background: var(--surface2); text-align: center; }
[data-theme="dark"] .gw-result { background: rgba(255,255,255,0.05); }
.gw-big { display: flex; align-items: center; justify-content: center; gap: 12px; font-size: 20px; color: var(--text2); font-variant-numeric: tabular-nums; }
.gw-big svg { width: 18px; height: 18px; }
.gw-big b { font-size: 30px; font-weight: 800; letter-spacing: -0.5px; color: var(--text1); }
.gw-big b.up { color: var(--green); }
.gw-big b.down { color: var(--amber); }
.gw-sub { margin-top: 4px; font-size: 13px; font-weight: 600; color: var(--text2); }
.gw-sub.up { color: var(--green); }
.gw-sub.down { color: var(--amber); }
.gw-targets-label { margin: 14px 0 8px; font-size: 12px; font-weight: 600; color: var(--text2); }
.gw-targets { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 8px; }
.gw-target { display: flex; flex-direction: column; gap: 2px; padding: 10px 12px; border-radius: 10px; background: var(--surface2); border: 1px solid var(--border2); }
[data-theme="dark"] .gw-target { background: rgba(255,255,255,0.05); border-color: rgba(255,255,255,0.08); }
.gw-target b { font-size: 16px; }
.gw-target span { font-size: 11px; color: var(--text2); }
.gw-target em { font-style: normal; font-size: 12.5px; font-weight: 600; color: var(--text1); margin-top: 2px; }
.gw-target.far em { color: var(--text2); font-weight: 500; }
.gw-note { margin-top: 12px; font-size: 11.5px; color: var(--text2); line-height: 1.45; }
@media (prefers-reduced-motion: reduce) { .gs-line, .gt-line { animation: none; } }

/* ===========================
   GOALS: progress toward the target grade
=========================== */
.gp { margin: 12px 0 4px; }
.gp-top { display: flex; align-items: baseline; gap: 10px; margin-bottom: 7px; font-variant-numeric: tabular-nums; }
.gp-now { font-size: 15px; font-weight: 800; color: var(--text1); }
.gp-now small { font-size: 11px; font-weight: 700; color: var(--text2); margin-left: 2px; }
.gp-state { flex: 1; font-size: 12.5px; font-weight: 600; color: var(--text2); }
.gp.met .gp-state { color: var(--green); }
.gp-target { font-size: 12px; font-weight: 700; color: var(--text2); }
.gp-track { position: relative; height: 8px; border-radius: 4px; background: var(--surface2); overflow: visible; }
[data-theme="dark"] .gp-track { background: rgba(255,255,255,0.08); }
.gp-fill { height: 100%; border-radius: 4px; background: var(--accent); transform-origin: left; animation: gpFill 0.9s var(--ease-out) backwards; }
.gp.met .gp-fill { background: var(--green); }
.gp-mark { position: absolute; top: -4px; width: 2px; height: 16px; margin-left: -1px; border-radius: 1px; background: var(--text1); }
@keyframes gpFill { from { transform: scaleX(0); } }
@media (prefers-reduced-motion: reduce) { .gp-fill { animation: none; } }

/* ===========================
   SYLLABUS: key dates (+ their markers on Upcoming)
=========================== */
.syl-dates { padding: 16px 18px; margin-bottom: 16px; }
.syl-dates-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 14px; }
.syl-dates-title { font-size: 15px; font-weight: 700; color: var(--text1); }
.syl-dates-sub { font-size: 12px; color: var(--text2); margin-top: 2px; }
.syl-switch { display: inline-flex; align-items: center; gap: 8px; font-size: 12px; font-weight: 600; color: var(--text2); cursor: pointer; flex-shrink: 0; position: relative; }
.syl-dates-list { margin-top: 12px; display: flex; flex-direction: column; gap: 2px; }
.syl-date-row { display: flex; align-items: center; gap: 12px; padding: 8px 0; border-top: 1px solid var(--glass-border); }
.syl-date-row:first-child { border-top: none; }
.syl-date-chip {
  width: 44px; flex-shrink: 0; padding: 5px 0; border-radius: 10px; text-align: center; line-height: 1.1;
  background: color-mix(in oklch, var(--purple) 14%, transparent); color: var(--purple);
}
.syl-date-chip b { display: block; font-size: 17px; font-weight: 800; }
.syl-date-chip span { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; }
.syl-date-text { flex: 1; min-width: 0; }
.syl-date-label { font-size: 14px; font-weight: 600; color: var(--text1); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.syl-date-sub { font-size: 12px; color: var(--text2); margin-top: 1px; }
.badge-syl { background: color-mix(in oklch, var(--purple) 16%, transparent); color: var(--purple); }
.syl-date-x { flex-shrink: 0; width: 26px; height: 26px; border-radius: 50%; background: none; border: none; color: var(--text2); cursor: pointer; font-size: 12px; opacity: 0.55; transition: opacity 0.15s, background 0.15s; }
.syl-date-row:hover .syl-date-x, .syl-date-x:focus-visible { opacity: 1; background: var(--surface2); }
.syl-dates-foot { display: flex; gap: 16px; margin-top: 8px; }
.syl-link { background: none; border: none; padding: 4px 0; font: inherit; font-size: 12.5px; font-weight: 600; color: var(--text2); cursor: pointer; text-decoration: underline; text-underline-offset: 3px; }
.syl-link:hover { color: var(--text1); }
.cal-day-syl-dot { width: 5px; height: 5px; border-radius: 50%; background: var(--purple); }
.cwd-item.key .cwd-dot { background: var(--purple); }
.syl-day-item { border-color: color-mix(in oklch, var(--purple) 30%, var(--glass-border)); }
@media (max-width: 600px) { .syl-dates-head { flex-direction: column; gap: 8px; } }

/* Settings: quiet-hours time pickers need more room than the number boxes. */
.num-input[type="time"] { width: 128px; padding-right: 8px; }

.focus-btn-row.stack .help-toggle-btn { align-self: center; justify-content: center; margin-top: 4px; }

/* Done toast with text values (study time): the new value sets the width. */
.done-toast.dt-text-odo .dt-old { position: absolute; left: 0; top: 0; }
.done-toast.dt-text-odo .dt-new { position: relative; }

/* ===========================
   SETTINGS SUB-TABS
   One row of glass pills under the header; only the chosen panel shows.
=========================== */
.settings-tabs {
  display: flex; gap: 6px; padding: 5px; margin: 0 0 18px;
  background: var(--glass-bg, var(--surface)); border: 1px solid var(--glass-border, var(--border));
  border-radius: 999px; box-shadow: var(--glass-shadow, none);
  -webkit-backdrop-filter: blur(18px) saturate(1.4); backdrop-filter: blur(18px) saturate(1.4);
  overflow-x: auto; scrollbar-width: none; scroll-snap-type: x proximity;
}
.settings-tabs::-webkit-scrollbar { display: none; }
.settings-tab {
  flex: 1 0 auto; scroll-snap-align: start;
  border: 0; background: transparent; color: var(--text2); font: inherit; font-size: 13.5px; font-weight: 600;
  padding: 8px 14px; border-radius: 999px; cursor: pointer; white-space: nowrap;
  transition: background 0.2s, color 0.2s, transform 0.15s;
}
.settings-tab:hover { color: var(--text1); background: color-mix(in oklch, var(--text1) 6%, transparent); }
.settings-tab:active { transform: scale(0.96); }
.settings-tab.active { background: var(--surface); color: var(--text1); box-shadow: var(--shadow-sm), inset 0 -2px 0 var(--accent); }
.settings-tab:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.settings-panel.in { animation: settingsPanelIn 0.32s var(--ease-out, ease-out); }
@keyframes settingsPanelIn { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .settings-panel.in { animation: none; } }

/* The desktop More tab is only for admins; students already have a tab for
   everything in it. (On phones More stays: the bottom bar has 4 slots.) */
#tab-more:not(.admin-visible) { display: none; }

/* ===========================
   CLOSED WORK (Choom suggests)
   Work Canvas has closed, shown as suggestions rather than to-dos.
=========================== */
.closed-suggest { margin-top: 18px; padding: 16px; }
.closed-suggest-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.closed-suggest-count { font-size: 12px; color: var(--text2); font-weight: 600; }
.closed-suggest-sub { font-size: 13px; color: var(--text2); margin: 8px 0 4px; line-height: 1.45; }
.closed-item { padding: 12px 0 2px; border-top: 1px solid var(--border); margin-top: 10px; transition: opacity 0.25s, transform 0.25s; }
.closed-item.closed-leaving { opacity: 0; transform: translateX(14px); }
.closed-item-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.closed-item-title { border: 0; background: none; padding: 0; font: inherit; font-size: 14.5px; font-weight: 650; color: var(--text1); text-align: left; cursor: pointer; }
.closed-item-title:hover { text-decoration: underline; text-underline-offset: 3px; }
.closed-item-tag { flex-shrink: 0; font-size: 11px; font-weight: 700; letter-spacing: 0.02em; padding: 3px 8px; border-radius: 999px; background: color-mix(in oklch, var(--accent) 16%, transparent); color: var(--text1); }
.closed-item-meta { font-size: 12px; color: var(--text2); margin-top: 3px; }
.closed-item-text { font-size: 13.5px; color: var(--text1); line-height: 1.5; margin-top: 7px; }
.closed-item-actions { display: flex; flex-wrap: wrap; gap: 8px; margin: 10px 0 6px; }
.closed-btn {
  border: 1px solid var(--border2, var(--border)); background: var(--surface); color: var(--text1);
  font: inherit; font-size: 12.5px; font-weight: 600; padding: 7px 12px; border-radius: 999px; cursor: pointer; text-decoration: none;
  transition: transform 0.15s, background 0.2s;
}
.closed-btn:hover { background: var(--surface2, var(--surface)); }
.closed-btn:active { transform: scale(0.96); }
.closed-btn.primary { background: var(--text1); color: var(--bg, #000); border-color: transparent; }
.closed-see-all { border: 0; background: none; color: var(--text2); font: inherit; font-size: 13px; font-weight: 600; cursor: pointer; padding: 8px 0 0; }
.closed-see-all:hover { color: var(--text1); }
@media (prefers-reduced-motion: reduce) { .closed-item { transition: none; } }

/* Edge/IE draw their own "reveal password" eye inside password fields,
   next to ours (js/auth-ui.js). Hide the browser's so there is only one. */
input[type="password"]::-ms-reveal,
input[type="password"]::-ms-clear { display: none; }

/* Small explainer under each export button in Settings > Account. */
.export-note { font-size: 12px; color: var(--text2); line-height: 1.5; margin: 0 2px 14px; }
.export-note strong { color: var(--text1); font-weight: 600; }

/* ===========================
   SYNC WHILE BUSY (js/sync-extras.js)
=========================== */
.sync-busy-backdrop {
  position: fixed; inset: 0; z-index: 3000; display: flex; align-items: center; justify-content: center; padding: 16px;
  background: rgba(0,0,0,0.45); opacity: 0; transition: opacity 0.2s;
  -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
}
.sync-busy-backdrop.show { opacity: 1; }
.sync-busy-card {
  width: min(420px, 100%); padding: 22px; border-radius: 20px;
  background: var(--glass-bg, var(--surface)); border: 1px solid var(--glass-border, var(--border)); box-shadow: var(--glass-shadow, 0 20px 50px rgba(0,0,0,0.35));
  -webkit-backdrop-filter: blur(22px) saturate(1.4); backdrop-filter: blur(22px) saturate(1.4);
  transform: translateY(10px) scale(0.98); transition: transform 0.25s var(--ease-spring, ease-out);
}
.sync-busy-backdrop.show .sync-busy-card { transform: none; }
.sync-busy-title { font-size: 18px; font-weight: 700; color: var(--text1); }
.sync-busy-sub { font-size: 13.5px; color: var(--text2); line-height: 1.5; margin: 6px 0 16px; }
.sync-busy-actions { display: flex; flex-direction: column; gap: 8px; }
.sync-busy-actions .settings-btn, .sync-busy-actions .sync-btn { width: 100%; margin: 0; }
.sync-busy-skip { border: 0; background: none; color: var(--text2); font: inherit; font-size: 13px; font-weight: 600; padding: 8px; cursor: pointer; }
.sync-busy-skip:hover { color: var(--text1); }
@media (prefers-reduced-motion: reduce) { .sync-busy-backdrop, .sync-busy-card { transition: none; } }

/* Canvas connection error with a short "Possible fixes" list. */
.canvas-connect-error { text-align: left; line-height: 1.5; }
.cce-title { font-weight: 650; }
.cce-fixes-label { margin-top: 8px; font-size: 11.5px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; opacity: 0.85; }
.cce-fixes { margin: 4px 0 0; padding-left: 18px; }
.cce-fixes li { margin: 3px 0; }

/* Settings > Display: the look is saved to the account (js/display-sync.js). */
.display-sync-note { display: flex; align-items: center; gap: 8px; margin-top: 14px; font-size: 12.5px; color: var(--text2); line-height: 1.4; }
.display-sync-note svg { width: 18px; height: 18px; flex-shrink: 0; color: var(--text2); }

/* ===========================
   QUICK REPORT (top bar bug button, js/topbar-extras.js)
=========================== */
.quick-report-backdrop {
  position: fixed; inset: 0; z-index: 3000; display: flex; align-items: center; justify-content: center; padding: 16px;
  background: rgba(0,0,0,0.45); opacity: 0; transition: opacity 0.2s;
  -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
}
.quick-report-backdrop.show { opacity: 1; }
.quick-report-card {
  width: min(440px, 100%); padding: 20px; border-radius: 20px;
  background: var(--glass-bg, var(--surface)); border: 1px solid var(--glass-border, var(--border));
  box-shadow: var(--glass-shadow, 0 20px 50px rgba(0,0,0,0.35));
  -webkit-backdrop-filter: blur(22px) saturate(1.4); backdrop-filter: blur(22px) saturate(1.4);
  transform: translateY(10px) scale(0.98); transition: transform 0.25s var(--ease-spring, ease-out);
}
.quick-report-backdrop.show .quick-report-card { transform: none; }
.qr-head { display: flex; align-items: flex-start; gap: 12px; margin-bottom: 14px; }
.qr-icon { width: 36px; height: 36px; border-radius: 50%; flex-shrink: 0; display: flex; align-items: center; justify-content: center; background: var(--red-soft, rgba(255,0,0,0.1)); color: var(--red); }
.qr-icon svg { width: 19px; height: 19px; }
.qr-title { font-size: 17px; font-weight: 700; color: var(--text1); }
.qr-sub { font-size: 12.5px; color: var(--text2); line-height: 1.45; margin-top: 2px; }
.qr-sub strong { color: var(--text1); font-weight: 600; }
.qr-close { margin-left: auto; border: 0; background: none; color: var(--text2); font-size: 22px; line-height: 1; cursor: pointer; padding: 0 2px; }
.qr-close:hover { color: var(--text1); }
.qr-types { margin-bottom: 10px; }
.qr-types .seg-btn { flex: 1; }
.qr-text { width: 100%; min-height: 96px; margin: 0; resize: vertical; }
.qr-status { min-height: 18px; font-size: 12.5px; color: var(--text2); margin: 8px 0 2px; }
.qr-status.err { color: var(--error-color, var(--red)); }
.qr-status.ok { color: var(--green, #2ea043); font-weight: 600; }
.qr-actions { display: flex; gap: 8px; justify-content: flex-end; }
.qr-actions .sync-btn, .qr-actions .settings-btn { width: auto; margin: 0; padding-left: 18px; padding-right: 18px; }
.quick-report-card.sent .qr-icon { background: color-mix(in oklch, var(--green, #2ea043) 18%, transparent); color: var(--green, #2ea043); }
@media (prefers-reduced-motion: reduce) { .quick-report-backdrop, .quick-report-card { transition: none; } }

/* ===========================
   UPDATES CARD (background sync, js/sync-extras.js)
   What a background sync found, shown for a few seconds then gone.
=========================== */
.sync-updates {
  position: fixed; right: 18px; bottom: 18px; z-index: 2500; width: min(340px, calc(100vw - 24px));
  padding: 14px 14px 12px; border-radius: 18px;
  background: var(--glass-bg, var(--surface)); border: 1px solid var(--glass-border, var(--border));
  box-shadow: var(--glass-shadow, 0 18px 40px rgba(0,0,0,0.3));
  -webkit-backdrop-filter: blur(22px) saturate(1.4); backdrop-filter: blur(22px) saturate(1.4);
  opacity: 0; transform: translateY(14px) scale(0.98); pointer-events: none;
  transition: opacity 0.25s, transform 0.35s var(--ease-spring, ease-out);
}
.sync-updates.show { opacity: 1; transform: none; pointer-events: auto; }
[data-theme="dark"] .sync-updates { background: rgba(20,20,20,0.92); }
.su-head { display: flex; align-items: center; gap: 10px; }
.su-icon { width: 30px; height: 30px; border-radius: 50%; flex-shrink: 0; display: flex; align-items: center; justify-content: center; background: color-mix(in oklch, var(--accent) 18%, transparent); color: var(--accent); }
.su-icon svg { width: 16px; height: 16px; }
.su-title { font-size: 14.5px; font-weight: 700; color: var(--text1); }
.su-sub { font-size: 12px; color: var(--text2); }
.su-close { margin-left: auto; border: 0; background: none; color: var(--text2); font-size: 20px; line-height: 1; cursor: pointer; padding: 0 2px; }
.su-close:hover { color: var(--text1); }
.su-list { list-style: none; margin: 10px 0 0; padding: 0; }
.su-item { width: 100%; display: flex; flex-direction: column; align-items: flex-start; gap: 1px; text-align: left; border: 0; background: none; padding: 7px 8px; border-radius: 10px; cursor: pointer; font: inherit; color: var(--text1); }
.su-item:hover { background: color-mix(in oklch, var(--text1) 6%, transparent); }
.su-item-title { font-size: 13.5px; font-weight: 600; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.su-item-meta { font-size: 11.5px; color: var(--text2); }
.su-more { border: 0; background: none; color: var(--text2); font: inherit; font-size: 12.5px; font-weight: 600; padding: 6px 8px 0; cursor: pointer; }
.su-more:hover { color: var(--text1); }
.su-timer { height: 2px; margin-top: 10px; border-radius: 2px; background: color-mix(in oklch, var(--text1) 10%, transparent); overflow: hidden; }
.su-timer i { display: block; height: 100%; width: 100%; background: var(--accent); transform-origin: left; }
.sync-updates.show .su-timer i { animation: suTimer var(--su-ms, 8000ms) linear forwards; }
.sync-updates:hover .su-timer i, .sync-updates:focus-within .su-timer i { animation-play-state: paused; }
@keyframes suTimer { to { transform: scaleX(0); } }
@media (max-width: 600px) { .sync-updates { right: 12px; left: 12px; width: auto; bottom: calc(80px + env(safe-area-inset-bottom, 0px)); } }
@media (prefers-reduced-motion: reduce) { .sync-updates { transition: opacity 0.2s; transform: none; } .sync-updates.show .su-timer i { animation: none; } }

/* ===========================
   SQUARE EVERYTHING (Settings > Display > Card corners > Square)
   Every box, button, field, tab and pop-up goes square. Things that are
   round on purpose keep their shape: check-off circles, status dots, color
   swatches, on/off switches and progress rings. Pseudo-elements (spinners,
   decorations) are left alone.
=========================== */
[data-corners-square] *:not(.done-check):not(.priority-check):not(.course-check):not(.course-check-inner):not(.swatch):not(.switch-track):not(.switch-thumb):not(.dot):not(.connected-dot):not(.announcement-unread-dot):not(.cal-day-study-dot):not(.cal-day-syl-dot):not(.cwd-dot):not(.goal-dot):not(.ft-dot):not(#focus-minibar-dot):not(#deepwork-minibar-dot):not(.tour-mock-dot):not(.tour-mock-cal-dot):not(.confetti-piece):not(.ap-ring):not(.tour-mock-timer-ring):not(.nwc-dot) {
  border-radius: 0 !important;
}

/* Native controls (dropdown lists, date pickers, scrollbars) follow the app
   theme. Without this a <select>'s open list stayed white in dark mode while
   the options inherited white text, so they were invisible until hovered. */
:root { color-scheme: light; }
[data-theme="dark"] { color-scheme: dark; }
select option, select optgroup { background-color: var(--surface); color: var(--text1); }

/* ===========================
   NEW SINCE LAST SYNC (js/sync-extras.js)
=========================== */
.new-tag {
  display: inline-block; margin-left: 7px; padding: 1px 7px; border-radius: 999px; vertical-align: 2px;
  font-size: 10.5px; font-weight: 700; letter-spacing: 0.03em; text-transform: uppercase;
  background: color-mix(in oklch, var(--accent) 20%, transparent); color: var(--text1);
}
.new-work-link {
  display: block; width: 100%; margin: -2px 0 10px; padding: 4px 12px; border: 0; background: none; text-align: left;
  font: inherit; font-size: 12px; font-weight: 600; color: var(--text2); cursor: pointer; border-radius: 8px;
}
.new-work-link:hover { color: var(--text1); background: color-mix(in oklch, var(--text1) 6%, transparent); }
.tabs.collapsed .new-work-link { display: none; }
.new-work-chip {
  display: inline-flex; align-items: center; gap: 6px; height: 30px; padding: 0 11px; border-radius: 999px; flex-shrink: 0;
  background: var(--surface2); border: 1px solid var(--border); color: var(--text1);
  font: inherit; font-size: 12px; font-weight: 700; cursor: pointer;
}
.new-work-chip[hidden], .new-work-link[hidden] { display: none; }
.nwc-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--accent); }
@media (min-width: 601px) { .new-work-chip { display: none !important; } }

/* ===========================
   HOW IT WORKS: pinned scroll story (sign-in page, js/auth-how.js)
   The sign-in split is row 1 of the page grid; the story is row 2. The
   page (.app) scrolls in auth mode now; the story's stage sticks while its
   tall section scrolls past, and the script draws the scene from that.
=========================== */
body.auth-mode .auth-page { height: auto; min-height: 100%; overflow: visible; grid-template-rows: 100vh auto; }
.auth-page > .auth-brand { grid-row: 1; grid-column: 1; }
.auth-page > .auth-form-col { grid-row: 1; grid-column: 2; }
body.auth-mode .auth-page > .auth-form-col { height: 100vh; }
@media (max-width: 900px) { .auth-page > .auth-form-col { grid-column: 1; } }

.how-scroll-hint {
  grid-row: 1; grid-column: 1 / -1; align-self: end; justify-self: center; z-index: 3;
  display: inline-flex; align-items: center; gap: 6px; margin-bottom: 18px; padding: 7px 14px 7px 16px;
  border: 1px solid rgba(255,255,255,0.12); border-radius: 999px; background: rgba(255,255,255,0.04);
  color: #b3b3b3; font: inherit; font-size: 12.5px; font-weight: 600; cursor: pointer;
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  transition: opacity 0.35s, transform 0.35s, color 0.2s, border-color 0.2s;
  animation: howHintIn 0.8s 1.6s var(--ease-out, ease-out) backwards;
}
.how-scroll-hint:hover { color: #fff; border-color: rgba(255,255,255,0.28); }
.how-scroll-hint svg { width: 15px; height: 15px; animation: howHintBob 1.8s ease-in-out infinite; }
.how-scroll-hint.gone { opacity: 0; transform: translateY(8px); pointer-events: none; }
@keyframes howHintIn { from { opacity: 0; transform: translateY(10px); } }
@keyframes howHintBob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(3px); } }

.story { grid-row: 2; grid-column: 1 / -1; height: 440vh; position: relative; border-top: 1px solid #262626; color: #fff; }
.story-stage {
  position: sticky; top: 0; height: 100vh; overflow: hidden;
  display: grid; grid-template-columns: minmax(300px, 0.85fr) 1.15fr; gap: 40px; align-items: center;
  max-width: 1240px; margin: 0 auto; padding: 0 48px;
}
.story-eyebrow { font-size: 12px; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; color: #8a8a8a; }
.story-title { margin: 12px 0 0; font-size: clamp(26px, 2.8vw, 40px); line-height: 1.08; letter-spacing: -0.03em; font-weight: 700; }

.story-steps { list-style: none; margin: 34px 0 0; padding: 0 0 0 2px; position: relative; }
.story-steps::before { content: ''; position: absolute; left: 7px; top: 10px; bottom: 10px; width: 1px; background: rgba(255,255,255,0.12); }
.story-step button {
  display: flex; gap: 16px; align-items: flex-start; width: 100%; text-align: left;
  border: 0; background: none; color: inherit; font: inherit; padding: 10px 0; cursor: pointer;
}
.ss-dot { position: relative; z-index: 1; flex-shrink: 0; width: 12px; height: 12px; margin: 5px 0 0 1px; border-radius: 50%; background: #000; border: 1.5px solid rgba(255,255,255,0.3); transition: background 0.35s, border-color 0.35s, transform 0.45s var(--ease-spring, ease-out), box-shadow 0.35s; }
.ss-text b { display: block; font-size: 16.5px; font-weight: 650; color: #6f6f6f; transition: color 0.35s; }
.ss-text > span { display: block; max-height: 0; overflow: hidden; opacity: 0; margin-top: 0; font-size: 14.5px; line-height: 1.5; color: #9a9a9a; transition: max-height 0.5s cubic-bezier(.16,1,.3,1), opacity 0.35s, margin-top 0.4s; }
.story-step.past .ss-dot { background: rgba(255,255,255,0.55); border-color: transparent; }
.story-step.active .ss-dot { background: #fff; border-color: #fff; transform: scale(1.25); box-shadow: 0 0 0 5px rgba(255,255,255,0.10); }
.story-step.active .ss-text b, .story-step button:hover .ss-text b { color: #fff; }
.story-step.active .ss-text > span { max-height: 90px; opacity: 1; margin-top: 4px; }
.story-step button:focus-visible { outline: 2px solid #fff; outline-offset: 4px; border-radius: 8px; }

.story-cta { margin-top: 30px; display: flex; flex-wrap: wrap; align-items: center; gap: 12px 18px; }
.story-cta-btn { width: auto; padding-left: 24px; padding-right: 24px; margin: 0; }
.story-cta-link { border: 0; background: none; color: #9a9a9a; font: inherit; font-size: 14px; font-weight: 600; cursor: pointer; padding: 6px 2px; }
.story-cta-link:hover { color: #fff; }

/* ---- Scene ---- */
.story-scene { position: relative; height: min(78vh, 640px); border-radius: 30px; border: 1px solid rgba(255,255,255,0.08); background: radial-gradient(120% 90% at 50% 0%, rgba(255,255,255,0.05), transparent 60%), rgba(255,255,255,0.015); overflow: hidden; }
.sc-canvas-ghost { position: absolute; inset: 16px; display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 12px; pointer-events: none; }
.sc-canvas-ghost span { border-radius: 16px; border: 1px dashed rgba(255,255,255,0.08); }

.sc-card {
  position: absolute; left: 0; top: 0; height: 58px; display: flex; align-items: center; gap: 12px; padding: 0 14px;
  border-radius: 16px; background: #121212; border: 1px solid rgba(255,255,255,0.10);
  box-shadow: 0 16px 34px -18px rgba(0,0,0,0.9); transform-origin: center; will-change: transform, opacity;
}
.sc-card.top { border-color: rgba(255,255,255,0.55); box-shadow: 0 0 0 4px rgba(255,255,255,0.06), 0 22px 40px -18px rgba(0,0,0,0.9); }
.scx-dot { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; background: var(--tone); }
.tone-b { --tone: oklch(0.7 0.14 250); } .tone-g { --tone: oklch(0.75 0.16 150); } .tone-o { --tone: oklch(0.75 0.14 60); }
.tone-p { --tone: oklch(0.72 0.15 300); } .tone-r { --tone: oklch(0.68 0.17 20); } .tone-y { --tone: oklch(0.82 0.14 95); }
.scx-rank {
  width: calc(26px * var(--rank, 0)); margin-right: calc(-12px * (1 - var(--rank, 0))); height: 26px; flex-shrink: 0; overflow: hidden;
  border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 800;
  background: #fff; color: #000; opacity: var(--rank, 0);
}
.scx-body { min-width: 0; flex: 1; display: flex; flex-direction: column; }
.scx-body b { font-size: 14px; font-weight: 650; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.scx-body span { font-size: 11.5px; color: #8a8a8a; }
.scx-due { font-size: 11.5px; font-weight: 700; padding: 3px 9px; border-radius: 999px; background: rgba(255,255,255,0.07); color: #cfcfcf; opacity: var(--due, 0); transform: translateX(calc(8px * (1 - var(--due, 0)))); }

.sc-list-head { position: absolute; display: flex; justify-content: space-between; align-items: center; font-size: 11.5px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: #8a8a8a; }
.sc-count { letter-spacing: 0; text-transform: none; padding: 3px 10px; border-radius: 999px; background: #fff; color: #000; }
.sc-count b { font-variant-numeric: tabular-nums; }

.sc-why { position: absolute; padding: 12px 14px; border-radius: 0 0 14px 14px; border: 1px solid rgba(255,255,255,0.14); border-top: 0; background: rgba(255,255,255,0.04); overflow: hidden; }
.sc-why-title { font-size: 11.5px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: #fff; }
.sc-why ul { margin: 7px 0 0; padding: 0; list-style: none; display: grid; gap: 4px; }
.sc-why li { position: relative; padding-left: 16px; font-size: 12.5px; color: #b8b8b8; }
.sc-why li::before { content: ''; position: absolute; left: 2px; top: 6px; width: 6px; height: 6px; border-radius: 50%; background: #1ed760; }

.sc-timer { position: absolute; left: 50%; top: 46%; width: min(230px, 52%); aspect-ratio: 1; opacity: 0; transform: translate(-50%, -50%); }
.sc-timer svg { width: 100%; height: 100%; display: block; }
.sct-track { fill: none; stroke: rgba(255,255,255,0.09); stroke-width: 7; }
.sct-ring { fill: none; stroke: #fff; stroke-width: 7; stroke-linecap: round; stroke-dasharray: 100; stroke-dashoffset: 100; transform: rotate(-90deg); transform-origin: 60px 60px; }
.sct-read { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; }
.sct-time { font-size: clamp(26px, 3vw, 36px); font-weight: 750; font-variant-numeric: tabular-nums; letter-spacing: -0.02em; }
.sct-read span { font-size: 12.5px; color: #9a9a9a; }

.sc-chain { position: absolute; left: 50%; bottom: 7%; transform: translateX(-50%); display: flex; align-items: center; gap: 12px; opacity: 0; padding: 9px 14px; border-radius: 999px; background: rgba(255,255,255,0.05); border: 1px solid rgba(255,255,255,0.08); white-space: nowrap; }
.scc-label { font-size: 12px; color: #9a9a9a; font-weight: 600; }
.scc-days { display: flex; gap: 5px; }
.scc-days i { width: 10px; height: 10px; border-radius: 3px; background: rgba(255,255,255,0.12); transition: background 0.3s, transform 0.4s var(--ease-spring, ease-out); }
.scc-days i.on { background: #1ed760; }
.scc-days i.on:nth-child(5) { transform: scale(1.25); }
.scc-n { font-size: 12.5px; font-weight: 700; }

/* Phones and narrow windows: copy above, scene below, still pinned. */
@media (max-width: 900px) {
  .story { height: 400vh; }
  .story-stage { grid-template-columns: 1fr; grid-template-rows: auto 1fr; align-content: start; gap: 14px; padding: 22px 16px 16px; }
  .story-title { font-size: 22px; }
  .story-steps { margin-top: 14px; }
  .story-steps::before { display: none; }
  .story-step { display: none; }
  .story-step.active { display: block; }
  .story-step button { padding: 2px 0; }
  .story-cta { display: none; }
  .story-scene { height: auto; min-height: 0; align-self: stretch; }
}

/* Reduce motion: not pinned; the ranked list stands still. */
.story.story-static { height: auto; }
.story-static .story-stage { position: relative; height: auto; padding-top: 80px; padding-bottom: 80px; }
.story-static .story-scene { height: 560px; }
.story-static .story-step .ss-text > span { max-height: 90px; opacity: 1; margin-top: 4px; }
.story-static .story-step { display: block; }
@media (prefers-reduced-motion: reduce) { .how-scroll-hint, .how-scroll-hint svg { animation: none; } }
@media (max-width: 900px) { .story[data-phase="3"] .story-cta { display: flex; margin-top: 12px; } }

/* ===========================
   MOTION EXTRAS (js/motion-extras.js)
=========================== */
/* The detail overlay's own fade/slide steps aside while it grows from a card. */
.detail-overlay.grow, .detail-overlay.grow .detail-inner { animation: none; }

/* Sidebar highlight that glides between tabs (desktop). */
@media (min-width: 601px) {
  .tabs.has-glider { position: sticky; }
  .tab-glider {
    position: absolute; left: 0; top: 0; z-index: 0; pointer-events: none; opacity: 0;
    border-radius: 10px; background: var(--accent-soft);
    transition: transform 0.5s cubic-bezier(.3,1.25,.45,1), width 0.3s ease, height 0.3s ease, opacity 0.2s;
  }
  .tab-glider::before {
    content: ''; position: absolute; left: 0; top: 24%; bottom: 24%; width: 3px; border-radius: 99px; background: var(--accent);
  }
  .tabs.has-glider .tab { z-index: 1; }
  .tabs.has-glider .tab.active { background: transparent; }
  .tabs.has-glider .tab::before { display: none; }
}
@media (max-width: 600px) { .tab-glider { display: none; } }
@media (prefers-reduced-motion: reduce) { .tab-glider { transition: none; } }

/* Checking an assignment off draws a line through its title, like crossing
   it off by hand, instead of the strike-through just appearing. */
@property --sf-strike { syntax: '<percentage>'; inherits: false; initial-value: 100%; }
.card.done .card-title:has(.card-title-link) { text-decoration: none; }
.card.done .card-title-link {
  text-decoration: none; -webkit-box-decoration-break: clone; box-decoration-break: clone;
  background-image: linear-gradient(currentColor, currentColor); background-repeat: no-repeat;
  background-position: 0 56%; background-size: var(--sf-strike) 1.5px;
}
.card.done.done-flash .card-title-link { animation: sfStrike 0.5s 0.08s cubic-bezier(.6,0,.2,1) both; }
@keyframes sfStrike { from { --sf-strike: 0%; } to { --sf-strike: 100%; } }
@media (prefers-reduced-motion: reduce) { .card.done.done-flash .card-title-link { animation: none; } }

/* ===========================
   SIGN-IN SCREEN, ALIVE (js/auth-live.js) + story polish (js/auth-how.js)
=========================== */
/* The sign-in screen lifts away as the story scrolls up over it
   (--hero goes 0 -> 1 over the first screen of scrolling). */
.auth-page[data-lifting] > .auth-brand, .auth-page[data-lifting] > .auth-form-col {
  opacity: calc(1 - var(--hero, 0) * 0.85);
  translate: 0 calc(var(--hero, 0) * -70px);
  scale: calc(1 - var(--hero, 0) * 0.04);
}
/* Gentle stops: the top of the page, then each step of the story. */
body.auth-mode .app { scroll-snap-type: y proximity; }
.auth-page > .auth-brand, .auth-page > .auth-form-col { scroll-snap-align: start; }
.story-snap { position: absolute; left: 0; width: 1px; height: 1px; scroll-snap-align: start; pointer-events: none; }

/* Progress bar over the steps. */
.story-progress { display: flex; align-items: center; gap: 12px; margin-top: 26px; }
.sp-track { position: relative; flex: 1; max-width: 220px; height: 3px; border-radius: 99px; background: rgba(255,255,255,0.10); overflow: hidden; }
.sp-track i { position: absolute; inset: 0; border-radius: inherit; background: #fff; transform: scaleX(0); transform-origin: left; }
.sp-label { font-size: 12px; font-weight: 700; color: #8a8a8a; font-variant-numeric: tabular-nums; }
.story-steps { margin-top: 18px; }

/* "Keep scrolling" cue at the bottom of the scene, fading as the story starts. */
.story-cue { position: absolute; left: 50%; bottom: 18px; translate: -50% 0; display: flex; align-items: center; gap: 8px; font-size: 12.5px; font-weight: 600; color: #a0a0a0; pointer-events: none; }
.sc-mouse { width: 16px; height: 24px; border: 1.5px solid rgba(255,255,255,0.45); border-radius: 10px; position: relative; }
.sc-mouse i { position: absolute; left: 50%; top: 5px; width: 2px; height: 5px; margin-left: -1px; border-radius: 2px; background: #fff; animation: cueWheel 1.6s ease-in-out infinite; }
@keyframes cueWheel { 0% { opacity: 0; transform: translateY(-2px); } 30% { opacity: 1; } 80%, 100% { opacity: 0; transform: translateY(7px); } }

/* Headline: the last words cycle. */
.tw-rot { display: inline-block; white-space: nowrap; }

/* Preview cards on a loop: checked off, struck through, refilled. */
@media (min-width: 1100px) and (min-height: 820px) {
  .auth-preview.live .ap-ring, .auth-preview.live .ap-ring::after,
  .auth-preview.live .ap-card.c1 .ap-title, .auth-preview.live .ap-bar i { animation: none; }
  .auth-preview.live .ap-ring { transition: border-color 0.35s, background 0.35s; }
  .auth-preview.live .ap-ring::after { transform: rotate(45deg) scale(0); transition: transform 0.45s var(--ease-spring, ease-out); }
  .auth-preview.live .ap-card.c1 .ap-title { background-size: 0% 1.5px; color: #fff; transition: background-size 0.5s 0.2s cubic-bezier(.6,0,.2,1), color 0.4s 0.2s; }
  .auth-preview.live .c1.is-done .ap-ring { border-color: #1ed760; background: rgba(30,215,96,0.16); }
  .auth-preview.live .c1.is-done .ap-ring::after { transform: rotate(45deg) scale(1); }
  .auth-preview.live .c1.is-done .ap-title { background-size: 100% 1.5px; color: #9a9a9a; }
  .auth-preview.live .ap-bar i { transition: width 1s cubic-bezier(.16,1,.3,1); }
}

/* Pointer light on the brand panel. */
.auth-brand { position: relative; }
.auth-spot {
  position: absolute; inset: 0; pointer-events: none; z-index: 0; opacity: 0; transition: opacity 0.5s;
  background: radial-gradient(520px circle at var(--sx, 50%) var(--sy, 50%), rgba(255,255,255,0.055), transparent 60%);
}
.auth-spot.on { opacity: 1; }
.auth-brand-inner { position: relative; z-index: 1; }

/* Form: a soft glow grows around the box being typed in, and the main
   button gets a light sweep on hover. */
.auth-page .auth-input { transition: background 0.2s, box-shadow 0.35s cubic-bezier(.16,1,.3,1), border-color 0.2s; }
.auth-page .auth-input:focus { box-shadow: 0 0 0 1px rgba(255,255,255,0.32), 0 0 0 6px rgba(255,255,255,0.05), 0 10px 30px -12px rgba(255,255,255,0.18); }
.auth-btn { position: relative; overflow: hidden; }
.auth-btn::before {
  content: ''; position: absolute; top: 0; bottom: 0; left: -60%; width: 45%; pointer-events: none;
  background: linear-gradient(100deg, transparent, rgba(255,255,255,0.55), transparent);
  transform: skewX(-18deg); opacity: 0;
}
.auth-btn:hover::before { animation: authSweep 0.9s ease; }
@keyframes authSweep { 0% { left: -60%; opacity: 0; } 20% { opacity: 1; } 100% { left: 120%; opacity: 0; } }
.auth-btn:active { transform: scale(0.985); }

@media (prefers-reduced-motion: reduce) {
  .auth-page > .auth-brand, .auth-page > .auth-form-col { opacity: 1; translate: none; scale: none; filter: none; }
  .sc-mouse i, .auth-btn:hover::before { animation: none; }
  body.auth-mode .app { scroll-snap-type: none; }
}

/* ===========================
   DASHBOARD MOTION (js/dashboard-motion.js)
=========================== */
/* A checked-off card is held in its list (absolutely placed) while it leaves. */
#home-upnext, #home-thisweek { position: relative; }

/* The page being left stays put and fades out over the one arriving. */
.page.page-leaving {
  display: block; position: absolute; margin: 0; box-sizing: border-box;
  pointer-events: none; z-index: 0; animation: pageLeave 0.2s ease forwards;
}
@keyframes pageLeave { to { opacity: 0; transform: translateY(-6px); } }

/* Soft pointer light on Home's boxes (mouse only). */
@property --sf-lit { syntax: '<number>'; inherits: false; initial-value: 0; }
@media (hover: hover) and (pointer: fine) {
  #page-home :is(.home-tile, .home-week, #home-grades, #home-study, #home-upnext > .card, #home-thisweek > .card):not(.overdue-card) {
    background-image: radial-gradient(280px circle at var(--mx, 50%) var(--my, 50%), color-mix(in oklch, var(--accent) calc(var(--sf-lit) * 11%), transparent), transparent 70%);
  }
  #page-home .sf-lit { --sf-lit: 1; }
  #page-home .home-tile { transition: transform 0.35s var(--ease-spring), border-color 0.2s, box-shadow 0.25s, --sf-lit 0.4s; }
  #page-home .card { transition: border-color 0.2s, transform 0.35s var(--ease-spring), box-shadow 0.25s, --sf-lit 0.4s; }
  #page-home .home-week { transition: --sf-lit 0.4s; }
}
@media (prefers-reduced-motion: reduce) { .page.page-leaving { display: none; animation: none; } }

/* ===========================
   QUICK START vs FULL SYNC (js/canvas-feed.js)
=========================== */
/* Setup screen: one of three views at a time. */
#onboard-canvas .ob-view { display: none; }
#onboard-canvas[data-ob-view="choose"] .ob-view-choose,
#onboard-canvas[data-ob-view="feed"] .ob-view-feed,
#onboard-canvas[data-ob-view="token"] .ob-view-token { display: block; }
#onboard-canvas[data-ob-view="choose"] .onboard-flow-panel-footer { display: none; }
.ob-back-link {
  display: inline-flex; align-items: center; gap: 4px; margin: 0 0 14px; padding: 4px 0;
  background: none; border: 0; font: inherit; font-size: 13px; font-weight: 600; color: var(--text2); cursor: pointer;
}
.ob-back-link:hover, .ob-back-link:focus-visible { color: var(--text1); }

.cplan-choices { display: grid; gap: 12px; margin: -8px 0 22px; }
@media (min-width: 520px) { .cplan-choices { grid-template-columns: 1fr 1fr; } }
.cplan-card {
  position: relative; display: flex; flex-direction: column; align-items: flex-start; gap: 4px; min-width: 0;
  padding: 16px 16px 15px; text-align: left; font: inherit; color: var(--text1); cursor: pointer;
  background: var(--surface2); border: 1.5px solid var(--border2); border-radius: var(--card-radius, 14px);
  transition: border-color 0.2s, transform 0.3s var(--ease-spring, ease), box-shadow 0.2s;
}
.cplan-card:hover, .cplan-card:focus-visible { border-color: var(--accent); outline: none; }
.cplan-card:active { transform: scale(0.985); }
.cplan-card-feed { border-color: color-mix(in oklch, var(--accent) 55%, var(--border2)); }
.cplan-tag {
  font-size: 10.5px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
  padding: 2px 8px; border-radius: 999px; background: var(--accent-soft); color: var(--accent); margin-bottom: 4px;
}
.cplan-name { font-size: 17px; font-weight: 700; letter-spacing: -0.2px; }
.cplan-meta { font-size: 12px; font-weight: 600; color: var(--text2); }
.cplan-desc { font-size: 13.5px; color: var(--text2); line-height: 1.45; margin-top: 4px; }

/* The comparison table (setup and Settings). */
.cplan-compare-scroll { overflow-x: auto; }
.cplan-compare { width: 100%; border-collapse: collapse; font-size: 13px; min-width: 320px; }
.cplan-compare th, .cplan-compare td { padding: 9px 8px; text-align: left; vertical-align: top; border-bottom: 1px solid var(--border2); }
.cplan-compare thead th { font-size: 12px; font-weight: 700; color: var(--text1); border-bottom-width: 1.5px; }
.cplan-compare thead th small { display: block; font-size: 10.5px; font-weight: 600; color: var(--accent); margin-top: 1px; }
.cplan-compare tbody th { font-weight: 500; color: var(--text1); width: 46%; }
.cplan-compare td { width: 27%; color: var(--text2); }
.cplan-compare tr:last-child th, .cplan-compare tr:last-child td { border-bottom: 0; }
.cplan-yes { color: var(--green); font-weight: 800; }
.cplan-no { color: var(--text2); opacity: 0.6; }
.cplan-text { font-size: 12.5px; }
.cplan-compare .sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* Settings > Canvas */
.canvas-mode-label { font-size: 12.5px; font-weight: 600; color: var(--text2); margin: 2px 0 2px; }
.cplan-upgrade { margin-bottom: 8px; }
.cplan-upgrade-title { font-size: 15px; font-weight: 700; color: var(--text1); margin-bottom: 4px; }
.cplan-upgrade .card-sub { margin-bottom: 10px; }

/* "Comes with Full sync" cards: only for Quick start students. */
.feed-upgrade { display: none; }
.sf-feed-mode .feed-upgrade {
  display: block; padding: 18px; margin-bottom: 14px; border-radius: var(--card-radius, 14px);
  background: color-mix(in oklch, var(--accent) 8%, var(--surface)); border: 1px solid color-mix(in oklch, var(--accent) 25%, var(--border));
}
.feed-upgrade-title { font-size: 15px; font-weight: 700; color: var(--text1); margin-bottom: 4px; }
.feed-upgrade-body { font-size: 13.5px; color: var(--text2); line-height: 1.5; max-width: 60ch; }
.feed-upgrade-btn {
  margin-top: 12px; padding: 8px 14px; border-radius: 10px; border: 0; cursor: pointer; font: inherit; font-size: 13px; font-weight: 600;
  background: var(--btn-bg); color: var(--btn-fg); transition: transform 0.25s var(--ease-spring, ease), opacity 0.15s;
}
.feed-upgrade-btn:hover { opacity: 0.9; }
.feed-upgrade-btn:active { transform: scale(0.97); }
.sf-feed-mode .feed-upgrade-mini { padding: 14px 16px; }
.sf-feed-mode .feed-upgrade-mini .feed-upgrade-btn { margin-top: 10px; }
/* What the upgrade card stands in for. */
.sf-feed-mode #grades-empty, .sf-feed-mode #grades-loading, .sf-feed-mode #home-grades { display: none !important; }

/* ===========================
   QUICK START CHECK-INS (js/feed-checkin.js)
=========================== */
/* "Late": amber, never red -- the student told us, it isn't a failure. */
.card.feed-late { border-color: color-mix(in oklch, var(--amber) 45%, var(--border)); }
.late-pill {
  display: inline-block; margin-left: 7px; padding: 1px 7px; border-radius: 999px; vertical-align: 2px;
  font-size: 10.5px; font-weight: 700; letter-spacing: 0.03em;
  background: color-mix(in oklch, var(--amber) 22%, transparent); color: var(--text1);
}
.due-late { font-size: 12px; font-weight: 600; color: var(--amber); margin-top: 3px; }

/* Home: what's waiting for an answer. */
.feed-checkin-card {
  display: flex; align-items: center; gap: 12px; width: 100%; margin: 4px 0 14px; padding: 13px 16px;
  text-align: left; font: inherit; color: var(--text1); cursor: pointer;
  background: color-mix(in oklch, var(--accent) 9%, var(--surface)); border: 1px solid color-mix(in oklch, var(--accent) 30%, var(--border));
  border-radius: var(--home-radius, var(--card-radius, 14px));
  transition: transform 0.3s var(--ease-spring, ease), border-color 0.2s;
}
.feed-checkin-card:hover { border-color: var(--accent); }
.feed-checkin-card:active { transform: scale(0.985); }
.fcc-count {
  flex-shrink: 0; min-width: 28px; height: 28px; padding: 0 8px; border-radius: 999px;
  display: flex; align-items: center; justify-content: center;
  background: var(--accent); color: var(--on-accent, #fff); font-weight: 800; font-size: 13px; font-variant-numeric: tabular-nums;
}
.fcc-text { flex: 1; min-width: 0; font-size: 13.5px; color: var(--text2); line-height: 1.4; }
.fcc-text b { color: var(--text1); font-weight: 700; }
.fcc-arrow { font-size: 20px; color: var(--text2); }

/* The check-in window. */
.fci-overlay {
  position: fixed; inset: 0; z-index: 2200; display: none; align-items: center; justify-content: center;
  padding: 16px; background: rgba(0,0,0,0.5);
}
.fci-overlay.show { display: flex; animation: fciFade 0.2s ease; }
.fci-sheet {
  width: 100%; max-width: 520px; max-height: min(640px, 88dvh); display: flex; flex-direction: column;
  background: var(--surface); color: var(--text1); border: 1px solid var(--border2); border-radius: 18px;
  box-shadow: 0 24px 60px -20px rgba(0,0,0,0.6); overflow: hidden;
}
.fci-overlay.show .fci-sheet { animation: fciRise 0.32s cubic-bezier(.16,1,.3,1); }
@keyframes fciFade { from { opacity: 0; } }
@keyframes fciRise { from { opacity: 0; transform: translateY(14px) scale(0.98); } }
.fci-head { display: flex; align-items: flex-start; gap: 12px; padding: 18px 18px 12px; }
.fci-head > div { flex: 1; min-width: 0; }
.fci-title { font-size: 19px; font-weight: 800; letter-spacing: -0.2px; }
.fci-sub { font-size: 13px; color: var(--text2); margin-top: 4px; line-height: 1.45; }
.fci-close { background: none; border: 0; color: var(--text2); font-size: 16px; cursor: pointer; padding: 4px; }
.fci-list { overflow-y: auto; padding: 0 18px; flex: 1; min-height: 0; }
.fci-item { display: flex; align-items: center; gap: 12px; padding: 11px 0; border-top: 1px solid var(--border2); }
.fci-item-text { flex: 1; min-width: 0; }
.fci-item-title { font-size: 14px; font-weight: 600; overflow-wrap: anywhere; }
.fci-item-sub { font-size: 12px; color: var(--text2); margin-top: 2px; }
.fci-item-actions { display: flex; gap: 6px; flex-shrink: 0; }
.fci-done, .fci-late {
  padding: 7px 12px; border-radius: 9px; border: 0; cursor: pointer; font: inherit; font-size: 13px; font-weight: 600;
  transition: transform 0.2s var(--ease-spring, ease), opacity 0.15s;
}
.fci-done { background: var(--btn-bg); color: var(--btn-fg); }
.fci-late { background: color-mix(in oklch, var(--amber) 20%, transparent); color: var(--text1); }
.fci-done:active, .fci-late:active { transform: scale(0.95); }
.fci-empty { padding: 18px 0; color: var(--text2); font-size: 14px; }
.fci-foot { display: flex; gap: 8px; padding: 14px 18px 18px; border-top: 1px solid var(--border2); }
.fci-all { flex: 1; padding: 11px; border-radius: 11px; border: 0; cursor: pointer; font: inherit; font-weight: 700; background: var(--btn-bg); color: var(--btn-fg); }
.fci-later { padding: 11px 14px; border-radius: 11px; border: 0; cursor: pointer; font: inherit; font-weight: 600; background: var(--btn-secondary-bg); color: var(--btn-secondary-color, var(--text1)); }
@media (max-width: 420px) { .fci-item { flex-wrap: wrap; } .fci-item-actions { width: 100%; } .fci-done, .fci-late { flex: 1; } }

/* Due today, when browser notifications are off. */
.due-today-pop {
  position: fixed; right: 16px; bottom: calc(16px + env(safe-area-inset-bottom, 0px)); z-index: 2150;
  width: min(340px, calc(100vw - 32px)); padding: 14px 40px 14px 16px; border-radius: 14px;
  background: var(--surface); color: var(--text1); border: 1px solid color-mix(in oklch, var(--accent) 35%, var(--border2));
  box-shadow: 0 18px 44px -18px rgba(0,0,0,0.6);
  opacity: 0; transform: translateY(12px); transition: opacity 0.25s, transform 0.35s cubic-bezier(.16,1,.3,1);
}
.due-today-pop.show { opacity: 1; transform: none; }
@media (max-width: 600px) { .due-today-pop { bottom: calc(84px + env(safe-area-inset-bottom, 0px)); } }
.dtp-label { font-size: 11px; font-weight: 700; letter-spacing: 0.07em; text-transform: uppercase; color: var(--accent); }
.dtp-title { font-size: 14.5px; font-weight: 700; margin-top: 3px; overflow-wrap: anywhere; }
.dtp-sub { font-size: 12.5px; color: var(--text2); margin-top: 2px; }
.dtp-close { position: absolute; top: 10px; right: 10px; background: none; border: 0; color: var(--text2); cursor: pointer; font-size: 14px; padding: 4px; }
@media (prefers-reduced-motion: reduce) {
  .fci-overlay.show, .fci-overlay.show .fci-sheet { animation: none; }
  .due-today-pop { transition: none; }
}
.sf-feed-mode .hero-overdue { color: var(--amber) !important; }
.sf-feed-mode .home-tile.tone-red .ht-icon { background: color-mix(in oklch, var(--amber) 18%, transparent); color: var(--amber); }
.sf-feed-mode .home-tile.tone-red .ht-value { color: var(--amber); }

/* Updates card: what the sync graded (js/sync-extras.js). */
.su-section { font-size: 10.5px; font-weight: 700; letter-spacing: 0.07em; text-transform: uppercase; color: var(--text2); margin: 10px 0 2px; }
.su-graded .su-item-meta b { color: var(--text1); font-weight: 700; }

/* ===========================
   TODAY'S 3 (js/today-three.js)
=========================== */
/* It takes the place of "Up next". */
.home-col-main.has-today3 > #home-upnext,
.home-col-main.has-today3 > .section-label:has(+ #home-upnext) { display: none; }
.today3 {
  margin: 0 0 18px; padding: 16px 16px 12px;
  background: var(--glass-bg); border: 1px solid var(--glass-border); border-radius: var(--home-radius, 20px);
  box-shadow: var(--glass-shadow); -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
}
.t3-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 8px; }
.t3-title { margin: 0; font-size: 18px; font-weight: 800; letter-spacing: -0.2px; color: var(--text1); }
.t3-sub { font-size: 12.5px; color: var(--text2); margin-top: 2px; font-variant-numeric: tabular-nums; }
.t3-dots { display: flex; gap: 5px; padding-top: 8px; }
.t3-dots i { width: 8px; height: 8px; border-radius: 50%; background: color-mix(in oklch, var(--text1) 14%, transparent); transition: background 0.3s, transform 0.35s var(--ease-spring, ease); }
.t3-dots i.on { background: var(--green); transform: scale(1.15); }
.t3-list { list-style: none; margin: 0; padding: 0; }
.t3-item { display: flex; align-items: center; gap: 12px; padding: 11px 0; border-top: 1px solid var(--glass-border); min-width: 0; }
.t3-item:first-child { border-top: 0; }
.t3-check { position: relative; flex-shrink: 0; }
.t3-check .t3-num { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 800; color: var(--text2); }
.t3-check.checked .t3-num { display: none; }
.t3-check:not(.checked) .done-check-icon { opacity: 0; }
.t3-body { flex: 1; min-width: 0; }
.t3-name {
  display: block; max-width: 100%; padding: 0; border: 0; background: none; text-align: left; cursor: pointer;
  font: inherit; font-size: 14.5px; font-weight: 650; color: var(--text1);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.t3-name:hover, .t3-name:focus-visible { color: var(--accent); outline: none; }
.t3-meta { font-size: 12px; color: var(--text2); margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.t3-why { font-weight: 600; color: var(--text1); }
.t3-item.late .t3-why { color: var(--amber); }
.t3-time {
  flex-shrink: 0; padding: 3px 9px; border-radius: 999px; font-size: 12px; font-weight: 700; font-variant-numeric: tabular-nums;
  background: color-mix(in oklch, var(--accent) 12%, transparent); color: var(--text1); cursor: help;
}
.t3-go {
  flex-shrink: 0; width: 32px; height: 32px; border-radius: 50%; border: 0; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  background: var(--btn-bg); color: var(--btn-fg); transition: transform 0.25s var(--ease-spring, ease), opacity 0.15s;
}
.t3-go svg { width: 14px; height: 14px; margin-left: 2px; }
.t3-go:hover { opacity: 0.9; }
.t3-go:active { transform: scale(0.92); }
.t3-item.done .t3-name { color: var(--text2); text-decoration: line-through; text-decoration-thickness: 1.5px; }
.t3-item.done .t3-time { opacity: 0.5; }
.t3-more {
  display: block; width: 100%; margin-top: 8px; padding: 10px; border-radius: 11px; border: 0; cursor: pointer;
  font: inherit; font-weight: 700; background: var(--btn-secondary-bg); color: var(--btn-secondary-color, var(--text1));
}
.t3-note { font-size: 11.5px; color: var(--text2); margin-top: 8px; }
@media (max-width: 420px) { .t3-time { padding: 3px 7px; font-size: 11.5px; } .t3-item { gap: 9px; } }
@media (prefers-reduced-motion: reduce) { .t3-dots i { transition: none; } }

/* ===========================
   EXAM RADAR (js/exam-radar.js)
=========================== */
.exam-radar {
  margin: 0 0 18px; padding: 16px 16px 14px;
  background: var(--glass-bg); border: 1px solid var(--glass-border); border-radius: var(--home-radius, 20px);
  box-shadow: var(--glass-shadow); -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
}
.er-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 6px; }
.er-heading { margin: 0; font-size: 18px; font-weight: 800; letter-spacing: -0.2px; color: var(--text1); }
.er-sub { font-size: 12.5px; color: var(--text2); margin-top: 2px; }
.er-add, .er-plan, .er-save {
  border: 0; cursor: pointer; font: inherit; font-size: 13px; font-weight: 700; border-radius: 10px;
  transition: transform 0.25s var(--ease-spring, ease), opacity 0.15s;
}
.er-add { padding: 7px 12px; background: var(--btn-secondary-bg); color: var(--btn-secondary-color, var(--text1)); flex-shrink: 0; }
.er-plan, .er-save { padding: 7px 12px; background: var(--btn-bg); color: var(--btn-fg); }
.er-add:active, .er-plan:active, .er-save:active { transform: scale(0.96); }
.er-plan:disabled { opacity: 0.6; cursor: default; }
.er-list { list-style: none; margin: 0; padding: 0; }
.er-item { display: flex; gap: 14px; padding: 12px 0; border-top: 1px solid var(--glass-border); }
.er-item:first-child { border-top: 0; }
.er-when {
  flex-shrink: 0; width: 54px; height: 54px; border-radius: 14px; display: flex; flex-direction: column; align-items: center; justify-content: center;
  background: color-mix(in oklch, var(--accent) 12%, transparent); color: var(--text1); font-variant-numeric: tabular-nums;
}
.er-when b { font-size: 20px; font-weight: 800; line-height: 1; }
.er-when span { font-size: 10.5px; font-weight: 700; color: var(--text2); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 2px; }
.er-item.soon .er-when { background: color-mix(in oklch, var(--amber) 22%, transparent); }
.er-body { flex: 1; min-width: 0; }
.er-title { font-size: 14.5px; font-weight: 700; color: var(--text1); overflow-wrap: anywhere; }
.er-meta { font-size: 12px; color: var(--text2); margin-top: 2px; }
.er-tag { font-weight: 600; }
.er-worth { font-size: 12.5px; font-weight: 600; color: var(--text1); margin-top: 4px; }
.er-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-top: 8px; }
.er-planned { font-size: 12.5px; font-weight: 600; color: var(--green); }
.er-link { background: none; border: 0; padding: 4px 0; cursor: pointer; font: inherit; font-size: 12.5px; font-weight: 600; color: var(--text2); }
.er-link:hover, .er-link:focus-visible { color: var(--text1); }
.er-empty { font-size: 13px; color: var(--text2); line-height: 1.5; padding: 4px 0 2px; max-width: 60ch; }
.er-glimpse {
  display: block; width: 100%; margin-top: 10px; padding: 9px 12px; text-align: left; cursor: pointer;
  font: inherit; font-size: 12.5px; font-weight: 600; color: var(--text1); border-radius: 10px;
  background: color-mix(in oklch, var(--accent) 8%, transparent); border: 1px dashed color-mix(in oklch, var(--accent) 35%, var(--glass-border));
}
.er-form { display: grid; gap: 10px; margin: 10px 0 6px; padding: 12px; border-radius: 12px; background: color-mix(in oklch, var(--text1) 4%, transparent); }
.er-row { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.er-field { display: grid; gap: 4px; min-width: 0; }
.er-field span { font-size: 11px; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase; color: var(--text2); }
.er-field input, .er-field select {
  width: 100%; min-width: 0; padding: 9px 10px; border-radius: 9px; font: inherit; font-size: 14px;
  color: var(--text1); background: var(--surface); border: 1px solid var(--border2);
}
.er-form-actions { display: flex; align-items: center; gap: 14px; }
@media (max-width: 420px) { .er-row { grid-template-columns: 1fr; } .er-when { width: 48px; height: 48px; } }
.er-undated-head { font-size: 11px; font-weight: 700; letter-spacing: 0.07em; text-transform: uppercase; color: var(--text2); margin: 12px 0 2px; }
.er-undated { list-style: none; margin: 0; padding: 0; }
.er-undated li { display: flex; align-items: center; gap: 12px; padding: 9px 0; border-top: 1px solid var(--glass-border); }
.er-undated li:first-child { border-top: 0; }
.er-undated .er-meta b { color: var(--text1); font-weight: 600; }

/* ===========================
   SIGN-IN: NOTEBOOK REDESIGN
   Ruled notebook paper (navy "Notebook at night" in dark theme), a top bar,
   the headline and form on the left, a sample "Your week" ticket on the
   right. Covers the sign-in screens, the startup splash, the connection
   screen and the How it works story. Comes last so it overrides the older
   black-glass auth styles above without touching how any screen works.
=========================== */
.auth-page, #boot-splash, #conn-problem {
  --nb-paper: #f6f1e4; --nb-card: #fbf8f0; --nb-card-2: #f2ece0; --nb-input: #ffffff;
  --nb-ink: #1c2340; --nb-ink-2: #545b78; --nb-ink-3: #8b8fa3;
  --nb-line: rgba(40,50,90,0.11); --nb-line-2: rgba(40,50,90,0.2);
  --nb-rule: rgba(39,71,214,0.14); --nb-margin: rgba(229,72,77,0.55);
  --nb-blue: #2747d6; --nb-red: #e5484d; --nb-mark: #f3ff4a; --nb-mark-ink: #1c2340;
  --nb-btn: #1c2340; --nb-btn-fg: #fbf8f0; --nb-shadow: rgba(28,35,64,0.35);
  --nb-mono: "Geist Mono", ui-monospace, monospace; --nb-sans: "Geist", "DM Sans", system-ui, sans-serif;
  /* the shared tokens the auth screens read */
  --bg: var(--nb-paper); --surface: var(--nb-card); --surface2: var(--nb-card-2);
  --border: var(--nb-line-2); --border2: var(--nb-line-2);
  --text1: var(--nb-ink); --text2: var(--nb-ink-2);
  --input-bg: var(--nb-input); --input-focus-bg: var(--nb-input);
  --accent: var(--nb-blue); --accent-soft: rgba(39,71,214,0.14); --accent-text: var(--nb-blue);
  --on-accent: #fff; --btn-bg: var(--nb-btn); --btn-fg: var(--nb-btn-fg);
  --red: #c9363b; --red-soft: rgba(229,72,77,0.12);
  --green: #1f8a5b; --green-soft: rgba(31,138,91,0.12);
  color-scheme: light;
}
[data-theme="dark"] :is(.auth-page, #boot-splash, #conn-problem) {
  --nb-paper: #121628; --nb-card: #161a2e; --nb-card-2: #1f243d; --nb-input: #1f243d;
  --nb-ink: #eef0fb; --nb-ink-2: #aab0cc; --nb-ink-3: #757b98;
  --nb-line: rgba(190,200,255,0.09); --nb-line-2: rgba(190,200,255,0.18);
  --nb-rule: rgba(111,136,255,0.11); --nb-margin: rgba(255,107,111,0.45);
  --nb-blue: #6f88ff; --nb-red: #ff6b6f;
  --nb-btn: #eef0fb; --nb-btn-fg: #121628; --nb-shadow: rgba(0,0,0,0.6);
  --accent-soft: rgba(111,136,255,0.18); --on-accent: #0e1120;
  --red: #ff8a8d; --red-soft: rgba(255,107,111,0.14);
  --green: #4fd18b; --green-soft: rgba(79,209,139,0.14);
  color-scheme: dark;
}

/* -- Page and layout -- */
.auth-page {
  grid-template-columns: minmax(0, 1fr);
  font-family: var(--nb-sans); color: var(--nb-ink);
  background:
    linear-gradient(90deg, transparent 30px, var(--nb-margin) 30px, var(--nb-margin) 32px, transparent 32px),
    repeating-linear-gradient(180deg, transparent 0 31px, var(--nb-rule) 31px 32px),
    var(--nb-paper);
}
body.auth-mode .auth-page { grid-template-rows: auto auto; }
/* the old floating caps sit behind the sign-in page; onboarding keeps them */
#auth-bg-glow:not(.onboard-glow) { display: none !important; }
/* The body's 20px app padding would show around the paper as a strip (the old
   black backdrop used to cover it), so it goes while the sign-in page is up. */
body.auth-mode:has(#auth-page[style*="grid"]) { padding: 0; }

.nb-hero {
  grid-row: 1; grid-column: 1; position: relative;
  min-height: 100vh; width: 100%; max-width: 1220px; margin: 0 auto;
  display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr); grid-template-rows: auto 1fr;
  column-gap: 70px; padding: 0 56px 96px; scroll-snap-align: start;
}
.auth-page[data-lifting] .nb-hero {
  opacity: calc(1 - var(--hero, 0) * 0.85);
  translate: 0 calc(var(--hero, 0) * -70px);
}
.nb-top { grid-column: 1 / -1; display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 26px 0; }
.nb-nav { display: flex; align-items: center; gap: 20px; }
.nb-nav button { background: none; border: 0; font: inherit; font-size: 14px; color: var(--nb-ink); cursor: pointer; padding: 4px 0; }
.nb-nav .nb-out {
  padding: 9px 16px; border: 1.5px solid currentColor; border-radius: 999px;
  font-family: var(--nb-mono); font-size: 11.5px; letter-spacing: 0.08em; text-transform: uppercase;
}
.nb-left { grid-column: 1; align-self: center; padding: 16px 0; min-width: 0; }
.nb-right { grid-column: 2; align-self: center; position: relative; display: flex; justify-content: center; padding: 20px 0 110px; }

/* -- Logo: the grad cap tipped onto the first letter -- */
.nb-logo { position: relative; display: inline-flex; align-items: center; line-height: 1; padding-top: 6px; }
.nb-cap { position: absolute; left: -7px; top: -5px; width: 25px; height: 25px; transform: rotate(-22deg); color: var(--nb-blue); overflow: visible; }
.nb-word { font-family: "Space Grotesk", var(--nb-sans); font-weight: 700; font-size: 26px; letter-spacing: -0.045em; color: var(--nb-ink); white-space: nowrap; }
.nb-logo-lg .nb-cap { width: 36px; height: 36px; left: -10px; top: -8px; }
.nb-logo-lg .nb-word { font-size: 38px; }

/* -- Headline column (the old brand panel, now just the words) -- */
.auth-page .auth-brand { display: block; padding: 0; border: 0; position: static; }
.auth-page .auth-brand::before, .auth-page .auth-brand::after, .auth-page .auth-spot { display: none; }
.auth-page .auth-brand-inner { max-width: none; }
.nb-kicker {
  display: inline-flex; align-items: center; gap: 10px;
  font-family: var(--nb-mono); font-size: 12px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--nb-ink-2);
}
.nb-kicker::before { content: ''; width: 24px; height: 1.5px; background: currentColor; }
.nb-h {
  margin: 18px 0 22px; font-family: var(--nb-mono); font-weight: 300;
  font-size: clamp(42px, 5.4vw, 82px); line-height: 1.02; letter-spacing: -0.045em; color: var(--nb-ink);
}
.nb-hl { background: linear-gradient(transparent 58%, var(--nb-mark) 58%, var(--nb-mark) 92%, transparent 92%); padding: 0 0.06em; }
/* dark: the highlight covers the whole word so dark letters never sit on the navy page */
[data-theme="dark"] .nb-hl { background: var(--nb-mark); color: var(--nb-mark-ink); border-radius: 0.12em; padding: 0 0.08em 0.04em; }
.nb-sub { font-size: 17px; line-height: 1.55; max-width: 36ch; color: var(--nb-ink-2); margin: 0; }

/* -- Form column: no glass card, the fields sit on the page under the headline -- */
.auth-page .auth-form-col,
body.auth-mode .auth-page .auth-form-col {
  display: block; height: auto; overflow: visible; padding: 0; margin-top: 30px; max-width: 460px;
}
.auth-page .auth-form-col .auth-screen,
body.auth-mode .auth-page .auth-form-col > .auth-screen {
  max-width: none; margin: 0; padding: 0; border: 0; border-radius: 0;
  background: none; box-shadow: none; -webkit-backdrop-filter: none; backdrop-filter: none;
}
.auth-page .auth-form-col .auth-logo { display: none; }
.auth-page .auth-heading { font-family: var(--nb-sans); font-size: 22px; font-weight: 600; letter-spacing: -0.02em; color: var(--nb-ink); margin: 0 0 6px; }
.auth-page .auth-sub { font-size: 14.5px; color: var(--nb-ink-2); margin-bottom: 20px; }
/* the big headline already welcomes you on the sign-in screen; keep these for screen readers */
#login-screen .auth-heading, #login-screen .auth-sub {
  position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
}
.auth-page .auth-label {
  font-family: var(--nb-mono); font-size: 11px; font-weight: 500; letter-spacing: 0.1em; color: var(--nb-ink-2); margin-bottom: 6px;
}
.auth-page .auth-label:has(+ .auth-input:focus),
.auth-page .auth-label:has(+ .auth-input-wrap .auth-input:focus) { color: var(--nb-ink); }
.auth-page .auth-input {
  background: var(--nb-input); border: 1.5px solid var(--nb-line-2); border-radius: 12px;
  padding: 13px 15px; font-size: 15px; color: var(--nb-ink); margin-bottom: 14px;
}
.auth-page .auth-input-wrap { margin-bottom: 14px; }
.auth-page .auth-input-wrap .auth-input { margin-bottom: 0; }
.auth-page .auth-input::placeholder { color: var(--nb-ink-3); }
.auth-page .auth-input:focus { background: var(--nb-input); border-color: var(--nb-blue); box-shadow: 0 0 0 3px var(--accent-soft); }
.auth-page .auth-eye:hover { background: var(--nb-line); }
.auth-page .auth-btn {
  background: var(--nb-btn); color: var(--nb-btn-fg); border-radius: 12px;
  padding: 14px 24px; font-size: 15px; font-weight: 500; box-shadow: none; animation: fadeUp 0.6s var(--ease-out) 350ms backwards;
}
.auth-page .auth-btn::before { display: none; }
.auth-page .auth-btn:hover:not(:disabled) { opacity: 0.92; box-shadow: none; }
.nb-btns { display: flex; align-items: center; gap: 18px; margin-top: 4px; }
.nb-btns .auth-btn { width: auto; margin: 0; }
.nb-link { background: none; border: 0; padding: 0; font: inherit; font-size: 14px; color: var(--nb-ink); text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
.nb-link:hover { color: var(--nb-blue); }
.nb-strong { font-weight: 600; }
.nb-new {
  margin-top: 22px; padding: 12px 14px; border: 1.5px dashed var(--nb-line-2); border-radius: 12px;
  font-size: 13.5px; line-height: 1.5; color: var(--nb-ink-2);
}
.nb-new b { color: var(--nb-ink); font-weight: 600; }
.nb-new .nb-link { font-size: 13.5px; }
.auth-page .auth-switch { text-align: left; font-size: 14px; color: var(--nb-ink-2); margin-top: 16px; }
.auth-page .auth-switch a { color: var(--nb-blue); }

/* -- The sample week ticket -- */
.nb-slip { width: min(380px, 100%); transform: rotate(2.2deg); filter: drop-shadow(0 26px 28px var(--nb-shadow)); }
.nb-ticket {
  background: var(--nb-card); color: var(--nb-ink); padding: 32px 24px 28px;
  -webkit-mask: radial-gradient(circle at 9px 0, transparent 6px, #000 6.5px) top left / 18px 51% repeat-x,
                radial-gradient(circle at 9px 100%, transparent 6px, #000 6.5px) bottom left / 18px 51% repeat-x;
          mask: radial-gradient(circle at 9px 0, transparent 6px, #000 6.5px) top left / 18px 51% repeat-x,
                radial-gradient(circle at 9px 100%, transparent 6px, #000 6.5px) bottom left / 18px 51% repeat-x;
}
.nb-tk-head { display: flex; justify-content: space-between; align-items: baseline; padding-bottom: 14px; border-bottom: 1.5px dashed var(--nb-line-2); font-family: var(--nb-mono); font-size: 11.5px; letter-spacing: 0.12em; color: var(--nb-ink-2); }
.nb-tk-head b { font-family: var(--nb-sans); font-size: 18px; font-weight: 500; letter-spacing: -0.01em; color: var(--nb-ink); }
.nb-tk-list { list-style: none; margin: 6px 0 0; padding: 0; }
.nb-tk-list li { display: grid; grid-template-columns: 20px 1fr auto; gap: 12px; align-items: center; padding: 11px 0; border-bottom: 1px solid var(--nb-line); }
.nb-bx { width: 18px; height: 18px; border: 1.5px solid var(--nb-ink-3); border-radius: 5px; display: grid; place-items: center; font-size: 11px; line-height: 1; color: transparent; transition: background 0.25s, border-color 0.25s, color 0.25s; }
.nb-tk-list li.done .nb-bx { background: var(--nb-blue); border-color: var(--nb-blue); color: var(--on-accent); }
.nb-t { font-size: 14px; font-weight: 500; line-height: 1.25; min-width: 0; }
.nb-t small { display: block; margin-top: 3px; font-family: var(--nb-mono); font-size: 10.5px; font-weight: 400; letter-spacing: 0.04em; color: var(--nb-ink-3); }
.nb-nm { background: linear-gradient(currentColor, currentColor) left 55% / 0% 1.5px no-repeat; transition: background-size 0.55s ease, color 0.3s; }
.nb-tk-list li.done .nb-nm { background-size: 100% 1.5px; color: var(--nb-ink-3); }
.nb-d { font-family: var(--nb-mono); font-size: 11px; color: var(--nb-ink-2); white-space: nowrap; }
.nb-tk-list li.now .nb-d { background: var(--nb-mark); color: var(--nb-mark-ink); padding: 2px 6px; border-radius: 5px; }
.nb-tk-list li.exam .nb-nm, .nb-tk-list li.exam .nb-d { color: var(--nb-red); font-weight: 600; }
.nb-tk-list li.exam .nb-bx { border-color: var(--nb-red); border-style: dashed; }
.nb-tk-strip { display: grid; grid-template-columns: repeat(7, 1fr); gap: 7px; align-items: end; height: 52px; margin-top: 18px; }
.nb-tk-strip i { display: block; background: var(--nb-blue); border-radius: 4px 4px 0 0; }
.nb-tk-strip i.x { background: var(--nb-red); }
.nb-tk-days { display: grid; grid-template-columns: repeat(7, 1fr); gap: 7px; border-top: 1.5px solid var(--nb-ink); padding-top: 5px; }
.nb-tk-days span { text-align: center; font-family: var(--nb-mono); font-size: 9.5px; color: var(--nb-ink-3); }
.nb-tk-days span.t { background: var(--nb-mark); color: var(--nb-mark-ink); border-radius: 4px; }
.nb-tk-foot { display: flex; justify-content: space-between; margin-top: 16px; padding-top: 12px; border-top: 1.5px dashed var(--nb-line-2); font-family: var(--nb-mono); font-size: 11.5px; letter-spacing: 0.08em; color: var(--nb-ink-2); }
.nb-tk-foot b { color: var(--nb-ink); font-weight: 500; }

/* -- Choom on a sticky note, tucked under the ticket's corner -- */
.nb-sticky {
  position: absolute; right: -34px; bottom: -34px; z-index: 3; width: 210px; transform: rotate(-4deg);
  padding: 24px 18px 18px; border-radius: 2px 2px 16px 2px;
  background: color-mix(in srgb, var(--nb-mark) 55%, #fffbe8); color: var(--nb-mark-ink);
  box-shadow: 0 16px 24px -16px rgba(0,0,0,0.4); font-size: 15px; line-height: 1.38;
}
.nb-sticky::before { content: ''; position: absolute; top: -11px; left: 50%; width: 78px; height: 22px; transform: translateX(-50%) rotate(-3deg); background: rgba(255,255,255,0.55); box-shadow: 0 1px 2px rgba(0,0,0,0.08); }
.nb-sticky b { font-weight: 600; }
.nb-who { display: flex; align-items: center; gap: 7px; margin-bottom: 8px; font-family: var(--nb-mono); font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase; opacity: 0.75; }
.nb-who i { width: 7px; height: 7px; border-radius: 50%; background: #2747d6; }

/* -- "See how it works" pill, at the bottom of the first screen -- */
.nb-hero .how-scroll-hint {
  position: absolute; left: 0; right: 0; bottom: 22px; width: max-content; margin: 0 auto;
  background: var(--nb-card); border: 1.5px solid var(--nb-line-2); color: var(--nb-ink-2);
  -webkit-backdrop-filter: none; backdrop-filter: none;
}
.nb-hero .how-scroll-hint:hover { color: var(--nb-ink); border-color: var(--nb-ink-3); }

/* -- How it works story, on the same paper -- */
.auth-page .story { color: var(--nb-ink); border-top: 1.5px dashed var(--nb-line-2); }
.auth-page .story-eyebrow { font-family: var(--nb-mono); font-weight: 500; color: var(--nb-ink-2); }
.auth-page .story-title { font-family: var(--nb-sans); font-weight: 600; }
.auth-page .story-steps::before { background: var(--nb-line-2); }
.auth-page .ss-dot { background: var(--nb-paper); border-color: var(--nb-ink-3); }
.auth-page .ss-text b { color: var(--nb-ink-3); }
.auth-page .ss-text > span { color: var(--nb-ink-2); }
.auth-page .story-step.past .ss-dot { background: var(--nb-ink-3); border-color: transparent; }
.auth-page .story-step.active .ss-dot { background: var(--nb-blue); border-color: var(--nb-blue); box-shadow: 0 0 0 5px var(--accent-soft); }
.auth-page .story-step.active .ss-text b, .auth-page .story-step button:hover .ss-text b { color: var(--nb-ink); }
.auth-page .story-step button:focus-visible { outline-color: var(--nb-blue); }
.auth-page .story-cta-link { color: var(--nb-ink-2); }
.auth-page .story-cta-link:hover { color: var(--nb-ink); }
.auth-page .story-scene { background: var(--nb-card); border: 1.5px solid var(--nb-line-2); border-radius: 22px; }
.auth-page .sc-canvas-ghost span { border-color: var(--nb-line-2); }
.auth-page .sc-card { background: var(--nb-input); border-color: var(--nb-line-2); box-shadow: 0 10px 24px -16px var(--nb-shadow); }
.auth-page .sc-card.top { border: 2px solid var(--nb-ink); box-shadow: 0 14px 28px -16px var(--nb-shadow); }
.auth-page .scx-rank { background: var(--nb-mark); color: var(--nb-mark-ink); }
.auth-page .scx-body span { color: var(--nb-ink-3); }
.auth-page .scx-due { background: var(--nb-card-2); color: var(--nb-ink-2); }
.auth-page .sc-list-head { color: var(--nb-ink-2); font-family: var(--nb-mono); font-weight: 500; }
.auth-page .sc-count { background: var(--nb-ink); color: var(--nb-paper); }
.auth-page .sc-why { border-color: var(--nb-line-2); background: var(--nb-card-2); }
.auth-page .sc-why-title { color: var(--nb-ink); }
.auth-page .sc-why li { color: var(--nb-ink-2); }
.auth-page .sc-why li::before { background: var(--nb-blue); }
.auth-page .sct-track { stroke: var(--nb-line-2); }
.auth-page .sct-ring { stroke: var(--nb-blue); }
.auth-page .sct-read span { color: var(--nb-ink-2); }
.auth-page .sc-chain { background: var(--nb-card-2); border-color: var(--nb-line-2); }
.auth-page .scc-label { color: var(--nb-ink-2); }
.auth-page .scc-days i { background: var(--nb-line-2); }
.auth-page .scc-days i.on { background: var(--nb-blue); }
.auth-page .sp-track { background: var(--nb-line-2); }
.auth-page .sp-track i { background: var(--nb-blue); }
.auth-page .sp-label { color: var(--nb-ink-3); }
.auth-page .story-cue { color: var(--nb-ink-3); }
.auth-page .sc-mouse { border-color: var(--nb-ink-3); }
.auth-page .sc-mouse i { background: var(--nb-ink-2); }

/* the tagline, closing the How it works story */
.auth-page .story-tag {
  margin: 26px 0 0; font-family: "Space Grotesk", var(--nb-sans); font-weight: 700; font-size: 18px;
  letter-spacing: -0.02em; color: var(--nb-ink-2);
}

/* -- Startup splash and connection screen, on the same paper -- */
#boot-splash, #conn-problem {
  color: var(--nb-ink);
  background: repeating-linear-gradient(180deg, transparent 0 31px, var(--nb-rule) 31px 32px), var(--nb-paper);
  --glass-bg: var(--nb-card); --glass-border: var(--nb-line-2); --glass-shadow: 0 24px 50px -30px var(--nb-shadow);
}
#boot-splash .boot-card { -webkit-backdrop-filter: none; backdrop-filter: none; }
#boot-splash .nb-word {
  color: transparent; -webkit-background-clip: text; background-clip: text; background-size: 250% 100%;
  background-image: linear-gradient(100deg, var(--nb-ink-3) 20%, var(--nb-ink) 45%, var(--nb-ink-3) 70%);
  animation: bootShine 2.4s ease-in-out infinite;
}
#boot-splash .boot-bar { background: var(--nb-line-2); }
#boot-splash .boot-bar::after { background: linear-gradient(90deg, transparent, var(--nb-blue), transparent); }
#boot-splash .boot-slow { color: var(--nb-ink-2); }
#boot-splash .boot-slow button { color: var(--nb-ink); }
#conn-problem .conn-card {
  padding: 32px 30px 28px; border-radius: 20px; background: var(--nb-card); border: 1.5px solid var(--nb-line-2);
  box-shadow: 0 24px 50px -30px var(--nb-shadow); -webkit-backdrop-filter: none; backdrop-filter: none;
}
#conn-problem .nb-logo { margin-bottom: 18px; }
#conn-problem .auth-btn { background: var(--nb-btn); color: var(--nb-btn-fg); box-shadow: none; }

/* -- Phones and narrow windows: one column, ticket under the form -- */
@media (max-width: 900px) {
  .auth-page {
    background: repeating-linear-gradient(180deg, transparent 0 31px, var(--nb-rule) 31px 32px), var(--nb-paper);
  }
  .nb-hero { grid-template-columns: minmax(0, 1fr); column-gap: 0; padding: 0 20px 110px; }
  .nb-top { padding: 20px 0; }
  .nb-nav .nb-nav-how { display: none; }
  .nb-left { padding: 6px 0 0; }
  .nb-h { font-size: clamp(40px, 12vw, 64px); }
  .auth-page .auth-form-col, body.auth-mode .auth-page .auth-form-col { max-width: none; }
  .nb-right { grid-column: 1; padding: 44px 0 150px; }
  .nb-slip { transform: rotate(1.2deg); }
  .nb-sticky { right: 4px; bottom: -4px; width: 190px; }
  /* the ticket sits below the form here, so it must not fade while you scroll to it */
  .auth-page[data-lifting] .nb-hero { opacity: 1; translate: none; }
}
@media (prefers-reduced-motion: reduce) {
  .auth-page .auth-btn, #boot-splash .nb-word { animation: none; }
  .nb-tk-list li .nb-nm { transition: none; }
  #boot-splash .nb-word { color: var(--nb-ink); background: none; }
  .nb-nm, .nb-bx { transition: none; }
  .auth-page[data-lifting] .nb-hero { opacity: 1; translate: none; }
}

/* ===========================
   NOTEBOOK THEME: WHOLE APP
   Step 1 of the app-wide redesign: paper and ink for every page. The
   shared color tokens, fonts, cards, buttons, inputs and labels move to the
   notebook look (light = cream paper, dark = "Notebook at night" navy), so
   every page picks it up at once. Page layouts are redone separately.
   Card corners and font size from Settings still apply; the accent picker
   is replaced by themes later. Last in the file so it wins over the older
   black-and-glass look.
=========================== */
:root {
  --bg: #efe9dc; --surface: #fbf8f0; --surface2: #f3eee3;
  --border: rgba(40,50,90,0.14); --border2: rgba(40,50,90,0.09);
  --text1: #1c2340; --text2: #565d79;
  --input-bg: #ffffff; --input-focus-bg: #ffffff;
  --accent: #2747d6; --accent-mid: #3d5ce0; --accent-soft: rgba(39,71,214,0.11); --accent-text: #2747d6;
  --green: #1f8a5b; --green-soft: rgba(31,138,91,0.12);
  --amber: #a86400; --amber-soft: rgba(168,100,0,0.12);
  --red: #d13b40; --red-soft: rgba(229,72,77,0.12);
  --purple: #6b4fd8; --purple-soft: rgba(107,79,216,0.12);
  --shadow-sm: 0 1px 0 rgba(28,35,64,0.05), 0 8px 20px -16px rgba(28,35,64,0.35);
  --shadow-md: 0 2px 0 rgba(28,35,64,0.05), 0 16px 30px -18px rgba(28,35,64,0.45);
  --btn-secondary-bg: #f2ece0; --btn-secondary-color: var(--text1);
  --ai-bg: #faf6c8; --ai-border: rgba(28,35,64,0.14); --ai-label: #1c2340; --ai-text: #2a3050;
  --on-accent: #ffffff; --btn-bg: #1c2340; --btn-fg: #fbf8f0;
  --sync-btn-border: rgba(31,138,91,0.3); --disconnect-border: rgba(209,59,64,0.3);
  --glass-bg: var(--surface); --glass-border: var(--border); --glass-shadow: var(--shadow-md);
  --mark: #f3ff4a; --mark-ink: #1c2340;
  --font-sans: "Geist", "DM Sans", -apple-system, sans-serif;
  --font-mono: "Geist Mono", ui-monospace, monospace;
}
[data-theme="dark"], [data-theme="dark"][data-btn-accent] {
  --bg: #0e1120; --surface: #161a2e; --surface2: #1f243d;
  --border: rgba(190,200,255,0.12); --border2: rgba(190,200,255,0.08);
  --text1: #eef0fb; --text2: #aab0cc;
  --input-bg: #1f243d; --input-focus-bg: #232945;
  --accent: #6f88ff; --accent-mid: #8399ff; --accent-soft: rgba(111,136,255,0.16); --accent-text: #8ea2ff;
  --green: #4fd18b; --green-soft: rgba(79,209,139,0.14);
  --amber: #ffb347; --amber-soft: rgba(255,179,71,0.14);
  --red: #ff6b6f; --red-soft: rgba(255,107,111,0.14);
  --purple: #a78bfa; --purple-soft: rgba(167,139,250,0.14);
  --shadow-sm: 0 10px 22px -16px rgba(0,0,0,0.7);
  --shadow-md: 0 18px 34px -18px rgba(0,0,0,0.8);
  --btn-secondary-bg: #1f243d; --btn-secondary-color: var(--text1);
  --ai-bg: color-mix(in srgb, #f3ff4a 9%, #161a2e); --ai-border: rgba(243,255,74,0.28); --ai-label: #f3ff4a; --ai-text: #dfe2f3;
  --on-accent: #0e1120; --btn-bg: #eef0fb; --btn-fg: #0e1120;
  --sync-btn-border: rgba(79,209,139,0.35); --disconnect-border: rgba(255,107,111,0.35);
  --glass-bg: var(--surface); --glass-border: var(--border); --glass-shadow: var(--shadow-md);
}

/* -- Type: Geist for reading, Geist Mono for labels and numbers -- */
body { font-family: var(--font-sans); background: var(--bg); }
button, input, select, textarea { font-family: inherit; }
[data-theme="dark"] body::before { display: none; }
.section-label, .nav-group-label, .stat-label {
  font-family: var(--font-mono); font-weight: 500; letter-spacing: 0.12em;
}
.stat-val { font-family: var(--font-mono); font-weight: 300; letter-spacing: -0.04em; }

/* -- Logo: the grad cap on lowercase lettering -- */
.logo-word {
  font-family: "Space Grotesk", var(--font-sans); font-weight: 700; letter-spacing: -0.045em;
  text-transform: lowercase; color: var(--text1);
}
.logo-word em, [data-theme="light"] .main-app .logo-word em {
  font-style: normal; color: inherit; background: none; -webkit-text-fill-color: currentColor; padding-right: 0;
}
.main-app .logo-mark { color: var(--accent); }

/* -- Surfaces: paper cards with a hairline and a soft lift, in both themes -- */
.card, [data-theme="dark"] .card { border: 1px solid var(--border); box-shadow: var(--shadow-sm); }
.topbar { background: color-mix(in srgb, var(--bg) 88%, transparent); }
@media (min-width: 601px) {
  .tabs { background: var(--bg); border-right-color: var(--border); }
  .tab.active { background: var(--surface); color: var(--text1); box-shadow: inset 3px 0 0 var(--accent), var(--shadow-sm); }
}
.tab.active { color: var(--text1); }

/* -- Buttons: ink-filled primary, paper secondary; no more all-caps pills in dark -- */
[data-theme="dark"] :is(.settings-btn, .sync-btn, .change-courses-btn, .disconnect-btn) {
  border-radius: 12px; text-transform: none; letter-spacing: 0; font-weight: 600; font-size: 14px;
}

/* -- Checks: blue ink when done -- */
.done-check.checked { background: var(--accent); border-color: var(--accent); }

/* -- Unread updates: paper with the blue margin line, not a blue wash -- */
.announcement-card.unread { background: var(--surface); }

/* -- The welcome / sync screen's logo matches the new lettering -- */
#ws-logo-name, #ws-logo-name em {
  font-family: "Space Grotesk", var(--font-sans); font-weight: 700; font-style: normal;
  letter-spacing: -0.045em; text-transform: lowercase;
}
#ws-logo-row .logo-mark { color: var(--accent); }

/* ===========================
   NOTEBOOK THEME: BINDER TABS (step 2)
   Laptops and tablets: the sidebar becomes a row of binder tabs across the
   top, with the sync/theme/sign-out controls at the right end, and the page
   underneath is one paper sheet the active tab joins. Layout only, done in
   CSS: .main-col is display:contents so its top bar and content become cells
   of the same grid as the tabs; every button keeps its handler. Phones keep
   the bottom bar.
=========================== */
@media (min-width: 601px) {
  /* !important beats the inline display:flex the app sets when it shows
     itself; the :not() keeps its inline display:none (sign-in, setup) working */
  .main-app:not([style*="none"]) { display: grid !important; }
  .main-app {
    grid-template-columns: minmax(0, 1fr) auto; grid-template-rows: auto 1fr;
    align-items: end; min-height: 100vh;
  }
  .main-col { display: contents; }

  /* the tab strip */
  .tabs, .tabs.collapsed {
    grid-column: 1; grid-row: 1; position: sticky; top: 0; z-index: 101; align-self: stretch;
    display: flex; flex-direction: row; align-items: flex-end; gap: 3px;
    width: auto; flex: none; height: auto; padding: 16px 0 0 28px;
    overflow-x: auto; overflow-y: hidden; scrollbar-width: none;
    background: var(--bg); border: 0;
  }
  .sidebar-logo, .tabs.collapsed .sidebar-logo { align-self: center; padding: 0 22px 12px 2px; margin: 0; }
  .tabs.collapsed .logo-word { display: inline; }
  .tabs.collapsed .logo-mark { position: absolute; top: -10px; left: 1px; width: 28px; height: 28px; margin: 0; transform: rotate(-24deg); }
  .sidebar-toggle-btn, .nav-group-label, .tab-glider { display: none; }

  .tab, .tabs.collapsed .tab, .tabs.has-glider .tab {
    position: relative; top: 1px; flex: none; justify-content: center; gap: 6px;
    padding: 10px 14px; border-radius: 12px 12px 0 0; margin: 0;
    background: var(--surface2); color: var(--text2);
    border: 1px solid var(--border); border-bottom: 0 !important;
    font-size: 13.5px; font-weight: 500; white-space: nowrap; box-shadow: none;
  }
  .tab .tab-icon { display: none; }
  .tabs.collapsed .tab span:not(.tab-icon) { display: inline; }
  .tab:hover { background: var(--surface); color: var(--text1); }
  .tab.active, .tabs.has-glider .tab.active {
    background: var(--surface); color: var(--text1); font-weight: 600;
    padding-top: 13px; z-index: 2; box-shadow: none;
  }
  .tab.active::after {
    content: ''; position: absolute; left: 12px; right: 12px; top: 0; height: 3px;
    border-radius: 0 0 3px 3px; background: var(--accent);
  }
  #tab-settings { margin-top: 0; }
  .tab-badge, .tabs.collapsed .tab-badge {
    position: static; margin: 0 0 0 4px; min-width: 0; height: auto; padding: 0;
    background: none; color: var(--accent); font-family: var(--font-mono); font-size: 11px; font-weight: 500; line-height: 1;
  }

  /* sync: a compact pill at the end of the strip ("synced ..." moves to its tooltip) */
  .sidebar-sync {
    order: 99; align-self: center; flex: none; width: auto; margin: 0 0 12px 14px; padding: 7px 12px; gap: 8px;
    border-radius: 999px; border: 1px solid var(--border); background: var(--surface); box-shadow: none;
  }
  .sidebar-sync-sub, .tabs.collapsed .sidebar-sync-text { display: none; }
  .sidebar-sync-label { font-size: 12.5px; }

  /* the right end: report, theme, sign out */
  .topbar {
    grid-column: 2; grid-row: 1; position: sticky; top: 0; z-index: 101; align-self: stretch;
    padding: 16px 28px 12px 14px; background: var(--bg); border: 0;
    -webkit-backdrop-filter: none; backdrop-filter: none;
  }

  /* the page: one paper sheet the active tab sits on */
  .content {
    grid-column: 1 / -1; grid-row: 2; align-self: start; width: auto; max-width: none;
    margin: 0 28px 28px; padding: 28px 32px 36px;
    background: var(--surface); border: 1px solid var(--border); border-radius: 22px;
    box-shadow: var(--shadow-sm); position: relative; z-index: 1;
  }
  .content .card { background: var(--surface2); box-shadow: none; }
}
@media (min-width: 601px) and (max-width: 900px) {
  .tabs, .tabs.collapsed { padding-left: 16px; }
  .topbar { padding-right: 16px; }
  .content { margin: 0 16px 20px; padding: 22px 20px 28px; }
}
@media (min-width: 601px) {
  /* tighter tabs so the whole row fits a 1366px laptop; sync becomes a round icon button */
  .tabs, .tabs.collapsed { gap: 2px; }
  .sidebar-logo, .tabs.collapsed .sidebar-logo { padding-right: 16px; }
  .tab, .tabs.collapsed .tab, .tabs.has-glider .tab { padding: 10px 12px; font-size: 13px; }
  .tab.active, .tabs.has-glider .tab.active { padding-top: 13px; }
  .sidebar-sync { width: 34px; height: 34px; padding: 0; justify-content: center; border-radius: 50%; }
  .sidebar-sync-text, .sidebar-sync .sidebar-sync-label { display: none; }
  /* when the window is narrower than the row, the strip scrolls; a soft fade at
     the right edge says there is more */
  .tabs { -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 28px), transparent);
          mask-image: linear-gradient(90deg, #000 calc(100% - 28px), transparent); }
}
@media (min-width: 601px) {
  .tabs { -webkit-mask-image: none; mask-image: none; }
  .sidebar-sync { order: 0; margin: 0 14px 12px 0; }
  .sidebar-logo, .tabs.collapsed .sidebar-logo { padding-right: 12px; }
}
@media (min-width: 901px) { .tabs, .tabs.collapsed { padding-left: 24px; } }
@media (min-width: 601px) and (max-width: 1279px) {
  /* smaller laptops: icon-only sign out and slimmer tabs, so more of the row fits */
  .signout-btn-text { display: none; }
  .signout-btn { padding: 7px; }
  .tab, .tabs.collapsed .tab, .tabs.has-glider .tab { padding: 9px 10px; font-size: 12.5px; }
  .tab.active, .tabs.has-glider .tab.active { padding-top: 12px; }
  .topbar { padding-left: 8px; }
}

/* ===========================
   NOTEBOOK THEME: HOME (step 3)
   Home as one notebook page (js/home-notebook.js): a tear-off date, the
   greeting with Choom's sticky note, and Today's 3 across the top; the next
   14 days as solid bars; then the exam ticket beside the report card, and
   this week beside study goals and links. Calm on purpose: no glow, no
   counting numbers.
=========================== */
#page-home .sf-lit { --sf-lit: 0; }

/* -- top: date, greeting, Today's 3 -- */
.hm-today {
  display: grid; grid-template-columns: auto minmax(0, 1fr) minmax(0, 1.1fr); gap: 28px; align-items: start;
  padding-bottom: 26px; border-bottom: 1.5px dashed var(--border);
}
.hm-cal {
  position: relative; width: 96px; margin-top: 8px; text-align: center;
  border: 1.5px solid var(--text1); border-radius: 14px; background: var(--surface);
}
.hm-cal::before, .hm-cal::after {
  content: ''; position: absolute; top: -9px; width: 8px; height: 16px; border-radius: 4px; background: var(--text1);
}
.hm-cal::before { left: 24px; }
.hm-cal::after { right: 24px; }
.hm-cal-dow {
  display: block; padding: 7px 0 6px; border-radius: 12px 12px 0 0;
  background: var(--accent); color: var(--on-accent);
  font-family: var(--font-mono); font-size: 12px; letter-spacing: 0.16em;
}
.hm-cal-num {
  display: block; padding: 8px 0 2px; color: var(--text1);
  font-family: "Space Grotesk", var(--font-sans); font-weight: 700; font-size: 56px; line-height: 1; letter-spacing: -0.04em;
}
.hm-cal-mon { display: block; padding-bottom: 10px; font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.16em; color: var(--text2); }
/* The sheet that tears off on a new day (js/home-notebook.js): no rings,
   a ragged top edge where it ripped, lifted off the page */
.hm-cal.hm-cal-sheet {
  z-index: 3000; pointer-events: none; transform-origin: 12% 0;
  border-radius: 0 0 14px 14px; box-shadow: 0 10px 24px rgba(0, 0, 0, 0.18);
  -webkit-mask: conic-gradient(from -45deg at 50% 100%, #000 90deg, #0000 0) 0 0 / 7px 5px repeat-x,
                linear-gradient(#000 0 0) 0 5px / 100% calc(100% - 5px) no-repeat;
          mask: conic-gradient(from -45deg at 50% 100%, #000 90deg, #0000 0) 0 0 / 7px 5px repeat-x,
                linear-gradient(#000 0 0) 0 5px / 100% calc(100% - 5px) no-repeat;
}
.hm-cal.hm-cal-sheet::before, .hm-cal.hm-cal-sheet::after { display: none; }
.hm-cal.hm-cal-sheet .hm-cal-dow { border-radius: 0; padding-top: 10px; }

#home-greeting { margin: 0; min-width: 0; }
.hm-hello { margin: 0; font-size: 32px; font-weight: 600; letter-spacing: -0.02em; line-height: 1.1; color: var(--text1); }
.hm-sum { margin: 10px 0 0; font-size: 15px; line-height: 1.5; color: var(--text2); max-width: 52ch; }
.hm-sum:empty { display: none; }
.hm-sum b { color: var(--text1); font-weight: 600; }
.hm-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 18px; }
.hm-btn {
  padding: 10px 15px; border-radius: 12px; cursor: pointer;
  font: inherit; font-size: 14px; font-weight: 500;
  background: var(--surface2); color: var(--text1); border: 1px solid var(--border);
}
.hm-btn:hover { border-color: color-mix(in srgb, var(--text1) 30%, transparent); }
.hm-btn-p { background: var(--btn-bg); color: var(--btn-fg); border-color: transparent; }
.hm-btn-p:hover { border-color: transparent; opacity: 0.92; }

/* Choom's sticky note (highlighter yellow in both themes, ink stays dark) */
.hm-note {
  position: relative; max-width: 440px; margin-top: 26px; padding: 22px 18px 16px;
  background: color-mix(in srgb, var(--mark) 55%, #fffbe8); color: var(--mark-ink);
  border-radius: 2px 2px 16px 2px; transform: rotate(-1.2deg);
  box-shadow: 0 16px 24px -16px rgba(0, 0, 0, 0.4);
}
.hm-note[hidden] { display: none; }
.hm-note::before {
  content: ''; position: absolute; top: -10px; left: 50%; width: 76px; height: 20px;
  transform: translateX(-50%) rotate(-3deg); background: rgba(255, 255, 255, 0.55); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
}
.hm-note-who {
  display: flex; align-items: center; gap: 7px; margin-bottom: 8px; opacity: 0.75;
  font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase;
}
.hm-note-who i { width: 7px; height: 7px; border-radius: 50%; background: var(--accent); }
.hm-note-tip { margin: 0; font-size: 15px; line-height: 1.4; }
.hm-note-tip b { font-weight: 600; }
.hm-note-ask { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; }
.hm-note-ask button {
  padding: 5px 10px; border-radius: 8px; cursor: pointer; font: inherit; font-size: 12.5px;
  background: transparent; color: inherit; border: 1px solid rgba(0, 0, 0, 0.2);
}
.hm-note-ask button:hover { background: rgba(255, 255, 255, 0.45); }

/* Today's 3: numbered rows on the page, the first one highlighted */
.hm-focus { min-width: 0; }
.hm-focus > .section-label { margin-top: 0; }
.hm-focus .today3 {
  margin: 0; padding: 0; background: none; border: 0; border-radius: 0; box-shadow: none;
  -webkit-backdrop-filter: none; backdrop-filter: none;
}
.t3-title { font-size: 18px; font-weight: 600; letter-spacing: -0.01em; }
.t3-sub { font-family: var(--font-mono); font-size: 11.5px; letter-spacing: 0.02em; }
.hm-focus .t3-item {
  margin-top: 8px; padding: 11px 14px; border: 1px solid var(--border); border-radius: 14px; background: var(--surface2);
}
.hm-focus .t3-item:first-child { border-top: 1px solid var(--border); }
.t3-item:first-child:not(.done) .t3-check { background: var(--mark); border-color: var(--mark); }
.t3-item:first-child:not(.done) .t3-num { color: var(--mark-ink); }
.t3-num { font-family: var(--font-mono); font-weight: 500; }
.t3-time { background: none; padding: 0 2px; font-family: var(--font-mono); font-weight: 400; color: var(--text2); }

/* -- the next 14 days: solid bars, height = estimated hours of work due -- */
.hm-tide { padding-top: 26px; }
.hm-sec-h { display: flex; align-items: baseline; justify-content: space-between; flex-wrap: wrap; gap: 8px 12px; margin-bottom: 12px; }
.hm-sec-h h2 { margin: 0; font-size: 18px; font-weight: 600; letter-spacing: -0.01em; color: var(--text1); }
.hm-k {
  padding: 2px 0; background: none; border: 0; cursor: pointer;
  font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text2);
}
.hm-k:hover { color: var(--text1); }
.hm-legend { display: flex; flex-wrap: wrap; gap: 6px 16px; font-family: var(--font-mono); font-size: 11px; color: var(--text2); }
.hm-legend i { display: inline-block; width: 11px; height: 11px; margin-right: 6px; border-radius: 3px; vertical-align: -1px; background: var(--accent); }
.hm-legend i.x { background: var(--exam); }
.hm-legend i.m { background: var(--mark); }
[data-theme="dark"] .hm-legend i.m { opacity: 0.6; }
.td-grid { --td-plot-h: 150px; display: grid; grid-template-columns: repeat(14, minmax(0, 1fr)); }
.td-day {
  display: flex; flex-direction: column; min-width: 0; padding: 0; cursor: pointer;
  background: none; border: 0; font: inherit; color: inherit;
}
.td-plot {
  position: relative; box-sizing: content-box; height: var(--td-plot-h); padding-top: 36px;
  display: flex; flex-direction: column; justify-content: flex-end; align-items: center;
  border-bottom: 1.5px solid color-mix(in srgb, var(--text1) 55%, transparent);
  /* a faint rule for every hour */
  background-image: linear-gradient(to top, var(--border2) 1px, transparent 1px);
  background-size: 100% calc(var(--td-plot-h) / var(--td-hours, 5)); background-position: bottom;
  background-origin: content-box; background-clip: content-box;
}
.td-day.today .td-plot::before {
  content: ''; position: absolute; inset: 6px 2px 0; border-radius: 8px 8px 0 0;
  background: color-mix(in srgb, var(--mark) 45%, transparent);
}
[data-theme="dark"] .td-day.today .td-plot::before { background: color-mix(in srgb, var(--mark) 14%, transparent); }
.td-bar { position: relative; display: block; width: min(58%, 40px); border-radius: 5px 5px 0 0; background: var(--accent); }
.td-day.exam .td-bar { background: var(--exam); }
.td-hrs { position: relative; margin-bottom: 5px; font-family: var(--font-mono); font-size: 10.5px; color: var(--text2); white-space: nowrap; }
.td-pin {
  position: absolute; top: 8px; left: 50%; z-index: 1; transform: translateX(-50%);
  padding: 3px 6px; border-radius: 6px; white-space: nowrap;
  font-family: var(--font-mono); font-size: 10px; font-weight: 500; letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--exam); background: var(--surface); border: 1.5px solid var(--exam);
}
.td-day:first-child .td-pin { left: 0; transform: none; }
.td-day:nth-last-child(-n+2) .td-pin { left: auto; right: 0; transform: none; }
.td-lab { padding: 6px 0 2px; text-align: center; font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.04em; color: var(--text2); white-space: nowrap; overflow: hidden; }
.td-day.today .td-lab { color: var(--text1); font-weight: 600; }
.td-day.exam .td-lab { color: var(--exam); font-weight: 600; }
.td-day:hover .td-lab { color: var(--text1); }
.td-day:hover .td-bar { filter: brightness(1.1); }
.td-day:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 6px; }

.td-lab-s { display: none; }
@media (max-width: 900px) { .td-lab { font-size: 9.5px; letter-spacing: 0; } }

#page-home .announcements-section { margin-top: 24px; }

/* -- the rows below: exam ticket + report card, this week + study + links -- */
.hm-row { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.3fr); gap: 22px; align-items: start; margin-top: 26px; }
.hm-row-b { grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr); }
.hm-box { min-width: 0; padding: 20px; border: 1px solid var(--border); border-radius: 18px; background: var(--surface2); }
.hm-box .card { background: var(--surface); }
#page-home .home-col-side { display: flex; flex-direction: column; gap: 22px; min-width: 0; }
.hm-empty { font-size: 13px; color: var(--text2); }
#home-study { cursor: pointer; }

/* report card: ruled rows of class, bar, percent, letter */
.rc-list { list-style: none; margin: 0; padding: 0; }
.rc-row {
  display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr) 56px 58px; gap: 12px; align-items: center;
  padding: 11px 0; border-bottom: 1px dashed var(--border);
}
.rc-row:last-child { border-bottom: 0; }
.rc-name { font-size: 14px; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rc-bar { height: 8px; border-radius: 99px; overflow: hidden; background: var(--surface); border: 1px solid var(--border2); }
.rc-bar i { display: block; height: 100%; border-radius: 99px; background: var(--accent); }
.rc-pct { text-align: right; font-family: var(--font-mono); font-size: 13.5px; }
.rc-row .rc-letter { font-family: "Space Grotesk", var(--font-sans); font-weight: 700; font-size: 18px; white-space: nowrap; }
.rc-off { opacity: 0.55; }
#home-grades-upgrade { margin-top: 12px; }

/* exam radar as a ticket: the next exam gets a big countdown */
.exam-radar.hm-exam {
  margin: 0; padding: 26px 22px 24px; border: 0; border-radius: 0; box-shadow: none;
  background: var(--surface2); -webkit-backdrop-filter: none; backdrop-filter: none;
  -webkit-mask: radial-gradient(circle at 9px 0, transparent 6px, #000 6.5px) top left / 18px 51% repeat-x,
                radial-gradient(circle at 9px 100%, transparent 6px, #000 6.5px) bottom left / 18px 51% repeat-x;
          mask: radial-gradient(circle at 9px 0, transparent 6px, #000 6.5px) top left / 18px 51% repeat-x,
                radial-gradient(circle at 9px 100%, transparent 6px, #000 6.5px) bottom left / 18px 51% repeat-x;
}
.hm-exam .er-heading { font-size: 18px; font-weight: 600; letter-spacing: -0.01em; }
.hm-exam .er-sub { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase; }
.hm-exam .er-item { border-top: 1px dashed var(--border); }
.hm-exam .er-item:first-child { flex-direction: column; gap: 6px; border-top: 0; }
.hm-exam .er-when { background: var(--surface); border: 1px solid var(--border); font-family: var(--font-mono); }
.hm-exam .er-when b { font-family: var(--font-mono); font-weight: 500; }
.hm-exam .er-item.soon .er-when { background: var(--surface); border-color: var(--exam); }
.hm-exam .er-item:first-child .er-when {
  width: auto; height: auto; flex-direction: row; align-items: baseline; justify-content: flex-start; gap: 10px;
  background: none; border: 0;
}
.hm-exam .er-item:first-child .er-when b {
  font-family: "Space Grotesk", var(--font-sans); font-weight: 700; font-size: 64px; letter-spacing: -0.05em; line-height: 0.9; color: var(--exam);
}
.hm-exam .er-item:first-child .er-when span { font-size: 12px; letter-spacing: 0.1em; }
.hm-exam .er-item:first-child .er-when span::after { content: ' to go'; }
.hm-exam .er-item:first-child .er-title { font-size: 15.5px; font-weight: 600; }

/* -- smaller screens -- */
@media (max-width: 1100px) {
  .hm-today { grid-template-columns: auto minmax(0, 1fr); }
  .hm-focus { grid-column: 1 / -1; }
}
@media (max-width: 900px) {
  .hm-row, .hm-row-b { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 600px) {
  .hm-today { gap: 18px 16px; padding-bottom: 22px; }
  .hm-cal { width: 70px; margin-top: 6px; }
  .hm-cal::before { left: 16px; } .hm-cal::after { right: 16px; }
  .hm-cal-dow { font-size: 10.5px; padding: 5px 0 4px; }
  .hm-cal-num { font-size: 38px; padding-top: 6px; }
  .hm-cal-mon { font-size: 10px; padding-bottom: 7px; }
  .hm-hello { font-size: 25px; }
  .hm-sum { font-size: 14.5px; }
  .hm-actions .hm-btn { flex: 1 1 auto; }
  /* the date sits beside the greeting; the rest runs full width under them */
  .hm-greet { display: contents; }
  .hm-cal { grid-column: 1; grid-row: 1; }
  .hm-hello { grid-column: 2; grid-row: 1; align-self: center; }
  .hm-sum, .hm-actions, .hm-note { grid-column: 1 / -1; margin-top: 0; }
  .hm-note { margin: 8px 4px 0; max-width: none; }
  .td-grid { --td-plot-h: 120px; }
  .td-plot { padding-top: 18px; }
  .td-hrs, .td-pin { display: none; }
  .td-day.today .td-hrs { display: block; font-size: 9.5px; }
  .td-lab { font-size: 10.5px; letter-spacing: 0; }
  .td-lab-l { display: none; }
  .td-lab-s { display: inline; }
  .hm-box { padding: 16px; }
  .rc-row { grid-template-columns: minmax(0, 1fr) 54px 56px; }
  .rc-bar { display: none; }
}

/* ===========================
   NOTEBOOK THEME: UPCOMING, PRIORITY, GRADES (step 4)
   Page titles on every tab get the notebook heading (big title, one line
   under it, a dashed rule). Upcoming's month view lists each day's work
   (exams in red, study blocks dashed) next to the day panel; Priority puts
   Choom's suggestion on a sticky note beside the planner and ranks work
   with big numbers; Grades are ruled cards with a solid bar.
=========================== */
.page-head { display: block; margin: 0 0 22px; padding-bottom: 20px; border-bottom: 1.5px dashed var(--border); }
.page-head-icon { display: none; }
.page-head-title { font-size: 32px; font-weight: 600; letter-spacing: -0.02em; line-height: 1.05; }
.page-head-sub { margin-top: 6px; font-size: 15px; white-space: normal; }
@media (max-width: 600px) {
  .page-head { margin-bottom: 18px; padding-bottom: 16px; }
  .page-head-title { font-size: 26px; }
  .page-head-sub { font-size: 14px; }
}

/* -- Upcoming -- */
#page-due .home-stats-strip {
  display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 20px;
  background: none; border: 0; border-radius: 0; box-shadow: none; overflow: visible; animation: none;
}
#page-due .home-stat, #page-due .home-stat + .home-stat {
  flex: none; display: flex; flex-direction: row-reverse; align-items: baseline; gap: 6px;
  padding: 8px 12px; border-radius: 12px; border: 1px solid var(--border); background: var(--surface2);
}
#page-due .home-stat .stat-label {
  margin: 0; font-family: var(--font-sans); font-size: 13px; font-weight: 400; letter-spacing: 0; text-transform: lowercase; color: var(--text2);
}
#page-due .home-stat .stat-val { font-size: 14px; font-weight: 500; letter-spacing: 0; }
#page-due .home-stat:has(#stat-overdue) { border-color: color-mix(in srgb, var(--red) 45%, transparent); }

@media (min-width: 601px) { .due-cal-card { max-width: none; } }
@media (min-width: 1100px) {
  .due-cal-layout { grid-template-columns: minmax(0, 1.45fr) minmax(300px, 1fr); gap: 22px; }
  .due-day-panel {
    background: var(--surface2); border: 1px solid var(--border); border-radius: 18px; box-shadow: none;
    -webkit-backdrop-filter: none; backdrop-filter: none;
  }
  #due-cal-selected-label { font-size: 18px; font-weight: 600; }
}
.due-cal-card { container-type: inline-size; }
.due-cal-card .cal-title { font-size: 18px; font-weight: 600; letter-spacing: -0.01em; }
.cal-today-btn { background: var(--surface2); color: var(--text1); border: 1px solid var(--border); font-weight: 500; }
#due-cal-grid { gap: 6px; }
.due-cal-card .cal-dow-row { gap: 6px; }
.due-cal-card .cal-dow {
  font-family: var(--font-mono); font-weight: 500; font-size: 10.5px; letter-spacing: 0.1em;
  background: none; color: var(--text2); border: 0; box-shadow: none; padding: 0 0 4px;
}

/* month cells: the day number in a circle, then the day's work as chips */
#due-cal-grid .cal-day:not(.cal-wday) {
  aspect-ratio: auto; min-height: 84px; padding: 6px; gap: 4px; min-width: 0;
  align-items: stretch; justify-content: flex-start;
  border: 1px solid var(--border); border-radius: 12px; background: var(--surface);
}
#due-cal-grid .cal-day:not(.cal-wday) .cal-day-num {
  width: 24px; height: 24px; display: grid; place-items: center; border-radius: 50%;
  font-family: var(--font-mono); font-size: 12px; font-weight: 400; color: var(--text2);
}
#due-cal-grid .cal-day.today .cal-day-num { background: var(--mark); color: var(--mark-ink); font-weight: 600; }
#due-cal-grid .cal-day.today { border-color: var(--border); }
#due-cal-grid .cal-day.selected { border: 2px solid var(--accent); padding: 5px; background: var(--surface); }
#due-cal-grid .cal-day:hover { background: var(--surface2); }
#due-cal-grid .cal-day:not(.cal-wday) .cal-day-dots { position: absolute; top: 9px; right: 7px; }
.cal-day-items { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.cal-it {
  display: block; padding: 3px 5px; border-radius: 5px; min-width: 0;
  font-size: 10.5px; line-height: 1.2; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  background: color-mix(in srgb, var(--accent) 13%, transparent); color: var(--text1);
}
.cal-it.exam { background: var(--exam); color: var(--exam-ink); font-weight: 600; }
.cal-it.study { background: transparent; border: 1px dashed var(--accent); color: var(--accent); padding: 2px 4px; }
.cal-it.done { background: transparent; color: var(--text2); text-decoration: line-through; }
.cal-it-more { font-family: var(--font-mono); font-size: 10px; color: var(--text2); padding-left: 2px; }
/* with room for chips, the count bubble and study dot are redundant */
@container (min-width: 520px) {
  #due-cal-grid .cal-day-count, #due-cal-grid .cal-day-study-dot { display: none; }
}
/* a narrow calendar: chips shrink to thin colored bars */
@container (max-width: 519px) {
  #due-cal-grid .cal-day:not(.cal-wday) { min-height: 56px; padding: 4px; border-radius: 9px; }
  #due-cal-grid .cal-day.selected { padding: 3px; }
  #due-cal-grid .cal-day:not(.cal-wday) .cal-day-num { width: 20px; height: 20px; font-size: 11px; }
  #due-cal-grid .cal-day:not(.cal-wday) .cal-day-dots { top: 5px; right: 3px; }
  #due-cal-grid .cal-day-count { min-width: 13px; height: 13px; font-size: 8.5px; padding: 0 2px; }
  .cal-it { font-size: 0; padding: 0; height: 5px; border-radius: 3px; background: color-mix(in srgb, var(--accent) 45%, transparent); }
  .cal-it.study { padding: 0; }
  .cal-it-more { display: none; }
}
/* week view: exams and study in the same language */
.cwd-item.key .cwd-dot { background: var(--exam); }

.cal-drag-chip { border: 1.5px dashed var(--accent); color: var(--accent); background: none; border-radius: 10px; }
.cal-drag-hint { font-family: var(--font-mono); font-size: 11px; }

/* -- Priority -- */
@media (min-width: 901px) {
  #page-priority.active { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr); gap: 0 22px; align-items: start; }
  #page-priority > * { grid-column: 1 / -1; }
  #page-priority > .ai-box, #page-priority > #planning-ai-box { grid-column: auto; margin-top: 0 !important; }
}
#page-priority .ai-box {
  position: relative; margin: 8px 0 24px; padding: 22px 18px 18px; border: 0;
  background: color-mix(in srgb, var(--mark) 55%, #fffbe8); color: var(--mark-ink);
  border-radius: 2px 2px 16px 2px; transform: rotate(-1deg); box-shadow: 0 16px 24px -16px rgba(0, 0, 0, 0.4);
}
#page-priority .ai-box::before {
  content: ''; position: absolute; top: -10px; left: 50%; width: 76px; height: 20px;
  transform: translateX(-50%) rotate(-3deg); background: rgba(255, 255, 255, 0.55); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
}
#page-priority .ai-label { color: var(--mark-ink); opacity: 0.75; font-family: var(--font-mono); font-weight: 500; font-size: 11px; letter-spacing: 0.1em; }
#page-priority .ai-dot { color: var(--accent); animation: none; }
#page-priority .ai-text { color: var(--mark-ink); font-size: 15px; line-height: 1.4; }
#planning-ai-box { margin-bottom: 24px; padding: 20px !important; border-radius: 18px; }
#planning-ai-box .section-label { margin-bottom: 10px; }

#priority-list { display: block; }
#priority-list .priority-card {
  display: grid; grid-template-columns: auto 52px minmax(0, 1fr); gap: 14px; align-items: center;
  padding: 16px 18px; margin-bottom: 10px; border-radius: 16px;
  background: var(--surface2); border: 1px solid var(--border); box-shadow: none;
}
#priority-list .priority-card:hover { transform: none; box-shadow: none; border-color: color-mix(in srgb, var(--text1) 30%, transparent); }
#priority-list .priority-num {
  width: auto; height: auto; padding: 0; border-radius: 0; background: none; color: var(--text2); justify-self: start;
  font-family: "Space Grotesk", var(--font-sans); font-weight: 700; font-size: 36px; letter-spacing: -0.05em; line-height: 1;
}
#priority-list > .priority-card:first-child { border: 2px solid var(--text1); background: var(--surface); padding: 15px 17px; }
#priority-list > .priority-card:first-child .priority-num {
  color: var(--text1); background: linear-gradient(transparent 55%, var(--mark) 55%, var(--mark) 90%, transparent 90%);
  padding: 0 5px; margin-left: -5px;
}
[data-theme="dark"] #priority-list > .priority-card:first-child .priority-num {
  background: linear-gradient(transparent 88%, var(--mark) 88%);
}
#priority-list .card-title { font-size: 15.5px; font-weight: 600; }
#priority-list .card-sub { font-family: var(--font-mono); font-size: 11.5px; }
.priority-completed-label { font-family: var(--font-mono); font-weight: 500; letter-spacing: 0.12em; }
@media (max-width: 600px) {
  #priority-list .priority-card { grid-template-columns: auto 36px minmax(0, 1fr); gap: 10px; padding: 14px; }
  #priority-list > .priority-card:first-child { padding: 13px; }
  #priority-list .priority-num { font-size: 28px; }
}

/* -- Grades -- */
@media (min-width: 901px) {
  #grades-cards { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
}
#grades-cards .grade-card {
  margin: 0 0 10px; padding: 16px 18px; border-radius: 16px;
  background: var(--surface2); border: 1px solid var(--border); box-shadow: none;
}
@media (min-width: 901px) { #grades-cards .grade-card { margin: 0; } }
#grades-cards .grade-card:hover { border-color: var(--accent); }
#grades-cards .grade-card-off { opacity: 0.6; }
.grade-card-name { font-size: 15px; font-weight: 600; }
.grade-bar-wrap { height: 8px; margin-top: 10px; background: var(--surface); border: 1px solid var(--border2); }
.grade-bar { background: var(--accent); }
.grade-breakdown-hint { font-family: var(--font-mono); font-size: 10.5px; margin-top: 8px; }
.grade-card-right { padding-left: 6px; }
.grade-card-letter { font-family: "Space Grotesk", var(--font-sans); font-size: 28px; letter-spacing: -0.03em; }
.grade-card-pct { font-family: var(--font-mono); font-size: 12.5px; font-weight: 400; margin-top: 4px; }

/* ===========================
   NOTEBOOK THEME: THE OTHER PAGES, DETAIL PANEL, SETUP (step 5)
   Shared pieces that show up on every page (assignment cards, tags,
   checkboxes, filter chips, segmented switches), the Study page's big
   numbers and tracker, Syllabus dates, the assignment detail panel, and the
   setup screens on notebook paper. Calm: flat paper, no washes or glows.
=========================== */

/* -- assignment cards: overdue gets a red margin line, not a red wash -- */
.card.overdue-card, [data-theme="dark"] .card.overdue-card {
  background: var(--surface2); border-color: var(--border);
  box-shadow: inset 3px 0 0 var(--red);
}
#page-home .card.overdue-card, .hm-box .card.overdue-card { background: var(--surface); }
#home-upnext .card { animation-name: none; }
.done-check, [data-theme="dark"] .done-check { border: 1.5px solid color-mix(in srgb, var(--text1) 38%, transparent); }
.done-check.checked, [data-theme="dark"] .done-check.checked { border-color: var(--accent); }
.card-sub { font-family: var(--font-mono); font-size: 11.5px; letter-spacing: 0.01em; }
#syllabus-list .card-sub { font-family: var(--font-sans); font-size: 12.5px; letter-spacing: 0; }
.due-ok, .due-soon, .due-locked { font-family: var(--font-mono); font-size: 11.5px; }
.overdue-pill, .late-pill {
  font-family: var(--font-mono); font-weight: 500; letter-spacing: 0.08em; border-radius: 5px;
}
.canvas-link { font-size: 12.5px; }

/* tags: small mono labels with a hairline, one ink color each */
.badge {
  font-family: var(--font-mono); font-weight: 500; font-size: 10.5px; letter-spacing: 0.04em; text-transform: uppercase;
  border-radius: 6px; padding: 3px 7px; background: transparent !important; border: 1px solid currentColor;
}

/* filter chips and segmented switches */
.aw-chip { border-radius: 10px; }
.aw-chip span { font-family: var(--font-mono); font-weight: 500; }
.seg-control { border: 1px solid var(--border); border-radius: 11px; }
.seg-btn.active { box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08); }

/* -- Study: flat paper for the big number, ink for deep work -- */
.study-hero-card, [data-theme="dark"] .study-hero-card {
  background: var(--surface2); background-image: none; border: 1px solid var(--border); box-shadow: none;
}
.study-hero-num { font-family: "Space Grotesk", var(--font-sans); letter-spacing: -0.04em; }
.study-hero-row b, .study-hero-row strong { font-family: var(--font-mono); font-weight: 500; }
.deepwork-btn, [data-theme="dark"] .deepwork-btn { background: var(--btn-bg); color: var(--btn-fg); box-shadow: none; }
.cal-day.missed { background: color-mix(in srgb, var(--red) 7%, var(--surface)); }
.cal-day.study-complete { background: color-mix(in srgb, var(--green) 12%, var(--surface)); }

/* -- Syllabus: each key date is a tiny tear-off calendar -- */
.syl-date-chip {
  background: var(--surface); color: var(--text1); border: 1.5px solid var(--text1); border-radius: 9px; overflow: hidden; padding: 0;
}
.syl-date-chip b { font-family: "Space Grotesk", var(--font-sans); font-weight: 700; padding: 3px 0 1px; }
.syl-date-chip span { display: block; background: var(--accent); color: var(--on-accent); font-family: var(--font-mono); font-weight: 500; letter-spacing: 0.12em; padding: 1px 0 2px; }
.badge-syl { color: var(--accent-text); }

/* -- assignment detail panel: the description reads like a ruled page -- */
.detail-title { font-size: 22px; font-weight: 600; letter-spacing: -0.02em; }
#a-detail-body .syllabus-text {
  background:
    linear-gradient(90deg, transparent 22px, color-mix(in srgb, var(--red) 40%, transparent) 22px 23.5px, transparent 23.5px),
    repeating-linear-gradient(180deg, transparent 0 25px, var(--border2) 25px 26px),
    var(--surface);
  background-attachment: local; line-height: 26px; padding-left: 36px;
}

/* -- setup screens: the same notebook paper as sign-in -- */
#onboard-flow {
  background:
    linear-gradient(90deg, transparent 30px, color-mix(in srgb, var(--red) 35%, transparent) 30px 32px, transparent 32px),
    repeating-linear-gradient(180deg, transparent 0 31px, var(--border2) 31px 32px),
    var(--bg);
}
.onboard-flow-header { background: color-mix(in srgb, var(--bg) 94%, transparent); border-bottom: 1.5px dashed var(--border); }
.onboard-step { font-family: var(--font-mono); font-weight: 500; letter-spacing: 0.12em; }
.onboard-title-icon { display: none; }
.onboard-title { font-size: 32px; font-weight: 600; letter-spacing: -0.02em; }
.cplan-card { background: var(--surface); border: 1px solid var(--border); box-shadow: none; }
.cplan-tag { font-family: var(--font-mono); font-weight: 500; letter-spacing: 0.1em; background: var(--mark); color: var(--mark-ink); }
@media (max-width: 600px) {
  #onboard-flow { background: repeating-linear-gradient(180deg, transparent 0 31px, var(--border2) 31px 32px), var(--bg); }
  .onboard-title { font-size: 26px; }
}

/* ===========================
   THEMES (step 6)
   Notebook is the default (no data-palette). The others are picked in
   Settings and set data-palette on <html>; each has one look of its own
   (Glam and Club room light, the rest dark), so the app also forces the
   matching data-theme. They only swap colors and a few textures: every
   layout is the same. Inspired feel only, no characters, art or logos.
   The sign-in page keeps the notebook look.
=========================== */
:root { --exam: var(--red); --exam-ink: #fff; }

/* Glam: blush page, hot pink pen, golden highlighter, black for exams, stitched seams */
:root[data-palette="glam"] {
  --bg: #fff1ef; --surface: #fffcfa; --surface2: #fff0ee;
  --border: rgba(120,30,70,0.18); --border2: rgba(120,30,70,0.10);
  --text1: #2a1620; --text2: #6e4f5c;
  --input-bg: #ffffff; --input-focus-bg: #ffffff;
  --accent: #f0437e; --accent-mid: #f25a8e; --accent-soft: rgba(240,67,126,0.12); --accent-text: #d42a66; --on-accent: #ffffff;
  --btn-bg: #2a1620; --btn-fg: #fffcfa; --btn-secondary-bg: #fff0ee;
  --mark: #ffd45c; --mark-ink: #3a2410; --exam: #2a1620; --exam-ink: #fffcfa; --green: #e0861f;
  --ai-bg: #fff4d6; --ai-border: rgba(120,30,70,0.18); --ai-label: #2a1620; --ai-text: #3d2430;
  --glass-bg: var(--surface); --glass-border: var(--border);
}
[data-palette="glam"] body { background: linear-gradient(170deg, #fff6e0 0%, #fff1ef 45%, #ffe4ea 100%) fixed; }
[data-palette="glam"] .content { outline: 1.5px dashed rgba(240,67,126,0.32); outline-offset: -9px; }

/* Club room: watercolor sky, cherry blossom, ribbon red for exams, coffee-can yellow */
:root[data-palette="club"] {
  --bg: #edf2f6; --surface: #fdfdfb; --surface2: #f0f4f7;
  --border: rgba(30,50,80,0.18); --border2: rgba(30,50,80,0.10);
  --text1: #1d2738; --text2: #56627a;
  --input-bg: #ffffff; --input-focus-bg: #ffffff;
  --accent: #3f9ad6; --accent-mid: #56a7dd; --accent-soft: rgba(63,154,214,0.13); --accent-text: #2a82be; --on-accent: #ffffff;
  --btn-bg: #1d2738; --btn-fg: #fdfdfb; --btn-secondary-bg: #f0f4f7;
  --mark: #ffd84a; --mark-ink: #3a2a12; --exam: #d9455f; --exam-ink: #ffffff; --green: #3aa57a;
  --ai-bg: #fdf3d2; --ai-border: rgba(30,50,80,0.16); --ai-label: #1d2738; --ai-text: #2c3648;
  --glass-bg: var(--surface); --glass-border: var(--border);
}
[data-palette="club"] body { background: linear-gradient(180deg, #cfe7f6 0%, #edf2f6 38%, #f6f2f2 100%) fixed; }

/* Desk lamp: late-night studying, warm black and lamp orange */
:root[data-palette="lamp"] {
  --bg: #0d0a09; --surface: #17110e; --surface2: #221914;
  --border: rgba(255,200,160,0.2); --border2: rgba(255,200,160,0.10);
  --text1: #fbf3ea; --text2: #c4b3a4;
  --input-bg: #221914; --input-focus-bg: #2a1f19;
  --accent: #ff7a2f; --accent-mid: #ff8c4a; --accent-soft: rgba(255,122,47,0.16); --accent-text: #ff9a5c; --on-accent: #1a0f08;
  --btn-bg: #ff7a2f; --btn-fg: #1a0f08; --btn-secondary-bg: #221914;
  --mark: #e4ff3a; --mark-ink: #11140a; --exam: #ffc15c; --exam-ink: #1a0f08; --green: #9be37a;
  --ai-bg: color-mix(in srgb, #e4ff3a 8%, #17110e); --ai-border: rgba(228,255,58,0.25); --ai-label: #e4ff3a; --ai-text: #ece2d6;
  --glass-bg: var(--surface); --glass-border: var(--border);
}
[data-palette="lamp"] body { background: radial-gradient(60% 50% at 85% 0%, rgba(255,140,60,0.16), transparent 70%) fixed, #0d0a09; }

/* Chalkboard: classroom green, chalk white, chalk yellow */
:root[data-palette="chalk"] {
  --bg: #07110d; --surface: #0e1a15; --surface2: #15251e;
  --border: rgba(190,255,225,0.18); --border2: rgba(190,255,225,0.09);
  --text1: #effaf4; --text2: #a9c4b6;
  --input-bg: #15251e; --input-focus-bg: #1a2d25;
  --accent: #3ddc97; --accent-mid: #5ae3a7; --accent-soft: rgba(61,220,151,0.15); --accent-text: #5ae3a7; --on-accent: #06140d;
  --btn-bg: #effaf4; --btn-fg: #06140d; --btn-secondary-bg: #15251e;
  --mark: #ffe36e; --mark-ink: #1a1505; --exam: #ffe36e; --exam-ink: #1a1505; --green: #3ddc97;
  --ai-bg: color-mix(in srgb, #ffe36e 8%, #0e1a15); --ai-border: rgba(255,227,110,0.25); --ai-label: #ffe36e; --ai-text: #dcebe3;
  --glass-bg: var(--surface); --glass-border: var(--border);
}
[data-palette="chalk"] body { background: radial-gradient(70% 60% at 30% 10%, #163027, #07110d 70%) fixed; }

/* Doomsday: cyberpunk night. Neon cyan ink, doom-red exams, acid-yellow
   highlighter, a faint neon grid, a still "glitch" on headings, cut corners */
:root[data-palette="doom"] {
  --bg: #07050c; --surface: #100b18; --surface2: #1a1226;
  --border: rgba(0,240,255,0.22); --border2: rgba(0,240,255,0.10);
  --text1: #ece8ff; --text2: #a59cc4;
  --input-bg: #1a1226; --input-focus-bg: #201630;
  --accent: #00e5ff; --accent-mid: #33ebff; --accent-soft: rgba(0,229,255,0.14); --accent-text: #00e5ff; --on-accent: #05030a;
  --btn-bg: #00e5ff; --btn-fg: #05030a; --btn-secondary-bg: #1a1226;
  --mark: #f5ef0a; --mark-ink: #0b0a02; --exam: #ff2a55; --exam-ink: #ffffff; --red: #ff2a55; --green: #3dffa0;
  --ai-bg: color-mix(in srgb, #f5ef0a 7%, #100b18); --ai-border: rgba(245,239,10,0.28); --ai-label: #f5ef0a; --ai-text: #e2dcf7;
  --glass-bg: var(--surface); --glass-border: var(--border);
}
[data-palette="doom"] body {
  background:
    linear-gradient(rgba(0,229,255,0.035) 1px, transparent 1px) 0 0 / 100% 34px,
    linear-gradient(90deg, rgba(0,229,255,0.035) 1px, transparent 1px) 0 0 / 34px 100%,
    #07050c;
  background-attachment: fixed;
}
[data-palette="doom"] .content { box-shadow: 0 0 0 1px rgba(0,229,255,0.15), 0 30px 60px -40px rgba(0,229,255,0.35); }
[data-palette="doom"] :is(.page-head-title, .hm-hello) { text-shadow: 2px 0 rgba(255,42,85,0.6), -2px 0 rgba(0,229,255,0.5); }
[data-palette="doom"] :is(.hm-btn, .er-plan, .er-add, .settings-btn, .add-goal-btn, .goal-add-btn, .td-pin, #page-due .home-stat) {
  clip-path: polygon(0 0, calc(100% - 9px) 0, 100% 9px, 100% 100%, 9px 100%, 0 calc(100% - 9px)); border-radius: 0;
}
[data-palette="doom"] .hm-exam .er-item:first-child .er-when b { text-shadow: 0 0 18px rgba(255,42,85,0.55); }
[data-palette="doom"] :is(.hm-note, #page-priority .ai-box) { background: var(--mark); }

/* Navy & Orange: deep navy, burnt orange, cream for exams, faint yard lines
   (Chicago colors only, no team names or logos) */
:root[data-palette="bears"] {
  --bg: #0b162a; --surface: #11203a; --surface2: #1a2b4a;
  --border: rgba(244,241,234,0.18); --border2: rgba(244,241,234,0.09);
  --text1: #f4f1ea; --text2: #b7bfd0;
  --input-bg: #152640; --input-focus-bg: #1a2d4c;
  --accent: #e2571d; --accent-mid: #e8693a; --accent-soft: rgba(226,87,29,0.16); --accent-text: #ff8a3d; --on-accent: #ffffff;
  --btn-bg: #e2571d; --btn-fg: #ffffff; --btn-secondary-bg: #1a2b4a;
  --mark: #ff8a3d; --mark-ink: #0b162a; --exam: #f4f1ea; --exam-ink: #0b162a; --green: #5fd38a;
  --ai-bg: color-mix(in srgb, #ff8a3d 9%, #11203a); --ai-border: rgba(255,138,61,0.3); --ai-label: #ff8a3d; --ai-text: #e4e2dc;
  --glass-bg: var(--surface); --glass-border: var(--border);
}
[data-palette="bears"] body {
  background: repeating-linear-gradient(180deg, transparent 0 79px, rgba(244,241,234,0.05) 79px 81px) fixed, #0b162a;
}

/* Duesday logo: the cap is tipped onto the top of the "d" (it used to sit
   over the "S" of StudyFlow, which hid the d) */
@media (min-width: 601px) {
  .sidebar-logo .logo-mark, .tabs.collapsed .logo-mark { width: 22px; height: 22px; top: -7px; left: 1px; }
}

/* themes with one look don't use the sun/moon switch */
[data-palette] #theme-btn { display: none; }

/* -- the theme picker in Settings -- */
.theme-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; margin-top: 10px; }
.theme-card {
  display: flex; flex-direction: column; gap: 8px; padding: 10px; min-width: 0; cursor: pointer; text-align: left;
  font: inherit; color: var(--text1); background: var(--surface); border: 1px solid var(--border); border-radius: 14px;
}
.theme-card:hover { border-color: color-mix(in srgb, var(--text1) 35%, transparent); }
.theme-card[aria-checked="true"] { border: 2px solid var(--accent); padding: 9px; }
.theme-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.theme-prev {
  position: relative; display: flex; align-items: flex-end; gap: 5px; height: 58px; padding: 8px 10px 0;
  border-radius: 9px; overflow: hidden; background: var(--tp-bg); border: 1px solid rgba(127,127,127,0.25);
}
.theme-prev i { flex: 1; border-radius: 3px 3px 0 0; background: var(--tp-ink); }
.theme-prev i.x { background: var(--tp-exam); }
.theme-prev b { position: absolute; top: 9px; left: 10px; width: 44%; height: 7px; border-radius: 2px; background: var(--tp-mark); }
.theme-name { font-size: 14px; font-weight: 600; }
.theme-desc { font-size: 12px; line-height: 1.35; color: var(--text2); }
.theme-tag { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text2); }
.theme-mode-note { font-size: 12.5px; color: var(--text2); margin-top: 8px; }
#theme-mode-row.is-fixed .seg-control { opacity: 0.45; pointer-events: none; }

/* ===========================
   ASSIGNMENTS: A RULED TO-DO LIST
   One row per assignment on a ruled sheet with a red margin line, under a
   heading per day (Overdue, Today, Tomorrow, the weekday, Next week, Later).
   On laptops the search and the type / class filters are a column on the
   left like notebook dividers. js/assignments-extras.js, awRowHTML and
   allWorkBodyHTML in js/render-utils.js.
=========================== */
#allwork-list { display: block; }
.aw-idx-h {
  margin: 0 0 6px 2px; font-family: var(--font-mono); font-size: 11px; font-weight: 500;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--text2);
}
.aw-idx:has(> .aw-chips:empty) { display: none; }
.aw-done-toggle { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--text2); cursor: pointer; padding: 2px; }
.aw-done-toggle input { width: 16px; height: 16px; accent-color: var(--accent); margin: 0; }

.aw-sheet { border: 1px solid var(--border); border-radius: 18px; background: var(--surface); overflow: hidden; }
.aw-day {
  display: flex; justify-content: space-between; align-items: baseline; gap: 10px;
  padding: 16px 18px 8px 58px; border-bottom: 1.5px solid var(--border);
  font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text2);
}
.aw-day b { margin-right: 6px; font-family: var(--font-sans); font-size: 15px; font-weight: 600; letter-spacing: -0.01em; text-transform: none; color: var(--text1); }
.aw-day.overdue, .aw-day.overdue b { color: var(--red); }
.aw-row {
  position: relative; display: grid; grid-template-columns: 24px minmax(0, 1fr) auto 84px 22px; gap: 12px; align-items: center;
  min-height: 54px; padding: 8px 14px 8px 16px; border-bottom: 1px solid var(--border2);
}
.aw-row:last-child { border-bottom: 0; }
.aw-row::before { content: ''; position: absolute; left: 48px; top: 0; bottom: 0; width: 1.5px; background: color-mix(in srgb, var(--red) 32%, transparent); }
.aw-row:hover { background: var(--surface2); }
.aw-main { min-width: 0; padding-left: 12px; }
.aw-row .card-title { font-size: 14.5px; font-weight: 500; line-height: 1.3; color: var(--text1); }
.aw-row .card-title-link { cursor: pointer; }
.aw-row .card-title-link:hover { color: var(--accent); }
.aw-sub { margin-top: 2px; font-family: var(--font-mono); font-size: 11px; color: var(--text2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.aw-tag {
  padding: 3px 7px; border-radius: 6px; white-space: nowrap; background: transparent !important; border: 1px solid currentColor;
  font-family: var(--font-mono); font-size: 10px; font-weight: 500; letter-spacing: 0.05em; text-transform: uppercase;
}
.aw-when { text-align: right; white-space: nowrap; font-family: var(--font-mono); font-size: 12px; color: var(--text2); }
.aw-open { display: grid; place-items: center; width: 22px; height: 22px; color: var(--text2); opacity: 0.55; border-radius: 6px; }
.aw-open:hover { opacity: 1; color: var(--accent); }
.aw-open svg { width: 15px; height: 15px; }
.aw-row.overdue { box-shadow: inset 3px 0 0 var(--red); }
.aw-row.overdue .aw-when { color: var(--red); font-weight: 500; }
.aw-row.late .aw-when { color: var(--amber); }
.aw-row.exam .card-title, .aw-row.exam .aw-tag { color: var(--exam); }
.aw-row.exam .done-check { border-style: dashed; border-color: var(--exam); }
.aw-row.done .card-title { color: var(--text2); text-decoration: line-through; text-decoration-thickness: 1.5px; }
.aw-row.done .aw-tag, .aw-row.done .aw-when { opacity: 0.55; }
.awc-inner .aw-sheet { margin: 4px 0 12px; }

@media (min-width: 1100px) {
  .aw-layout { display: grid; grid-template-columns: 230px minmax(0, 1fr); gap: 26px; align-items: start; }
  .aw-rail { position: sticky; top: 80px; display: flex; flex-direction: column; gap: 18px; }
  .aw-rail .aw-search { margin: 0; }
  .aw-rail .aw-chips { flex-direction: column; gap: 2px; overflow: visible; padding: 0; margin: 0; }
  .aw-rail .aw-chip {
    justify-content: space-between; width: 100%; padding: 7px 10px 7px 12px; text-align: left;
    background: none; border: 0; border-left: 3px solid transparent; border-radius: 0 10px 10px 0; color: var(--text2);
  }
  .aw-rail .aw-chip:hover { transform: none; background: var(--surface2); }
  .aw-rail .aw-chip span { background: none; padding: 0; font-weight: 400; color: var(--text2); }
  .aw-rail .aw-chip.active { border-left-color: var(--accent); background: var(--surface2); color: var(--text1); font-weight: 600; }
  .aw-rail .aw-chip.active span { background: none; color: var(--text1); }
  .aw-col .aw-toolbar { margin-top: 0; }
}
@media (max-width: 1099px) {
  .aw-rail { display: flex; flex-direction: column; gap: 10px; margin-bottom: 8px; }
  .aw-idx-h { display: none; }
}
@media (max-width: 600px) {
  .aw-row { grid-template-columns: 24px minmax(0, 1fr) 66px; padding-right: 12px; }
  .aw-row .aw-tag, .aw-row .aw-open { display: none; }
  .aw-day { padding-left: 52px; }
}

/* ===========================
   STUDY: THE TIMER DESK
   The focus timer first (a ticket with a big clock), today's goals and a
   7-day chain beside it, then what's planned, the last 7 days as solid
   bars, and the month as a wall calendar beside deep work. Deep work days
   get a ✕ on a stroke of highlighter (Settings > Study can make it a bigger,
   bold ✕ instead), in the theme's exam color. js/study-desk.js.
=========================== */
.sd-top { display: grid; grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); gap: 22px; align-items: stretch; }
.sd-timer, .sd-deep {
  display: flex; flex-direction: column; gap: 14px; padding: 26px 24px 24px; background: var(--surface2);
  -webkit-mask: radial-gradient(circle at 9px 0, transparent 6px, #000 6.5px) top left / 18px 51% repeat-x,
                radial-gradient(circle at 9px 100%, transparent 6px, #000 6.5px) bottom left / 18px 51% repeat-x;
          mask: radial-gradient(circle at 9px 0, transparent 6px, #000 6.5px) top left / 18px 51% repeat-x,
                radial-gradient(circle at 9px 100%, transparent 6px, #000 6.5px) bottom left / 18px 51% repeat-x;
}
.sd-timer .hm-sec-h, .sd-deep .hm-sec-h, .sd-today .hm-sec-h { margin-bottom: 0; }
.sd-clock { font-family: "Space Grotesk", var(--font-sans); font-weight: 700; font-size: 88px; letter-spacing: -0.05em; line-height: 0.9; color: var(--text1); }
.sd-timer .settings-input, .sd-deep .settings-input { margin: 0; background: var(--surface); }
.sd-lens { display: flex; flex-wrap: wrap; gap: 6px; }
.sd-lens button {
  padding: 6px 11px; border-radius: 9px; cursor: pointer;
  font-family: var(--font-mono); font-size: 12px; color: var(--text2); background: var(--surface); border: 1px solid var(--border);
}
.sd-lens button.on { background: var(--text1); border-color: var(--text1); color: var(--surface); }
.sd-timer .hm-actions { margin-top: 2px; }

.sd-today { display: flex; flex-direction: column; gap: 16px; }
.sd-today .hm-k b { font-family: var(--font-mono); font-weight: 500; color: var(--text1); }
.sd-today .goal-progress-label { margin-bottom: 7px; font-size: 12px; font-weight: 500; font-family: var(--font-mono); letter-spacing: 0.06em; text-transform: uppercase; color: var(--text2); }
.sd-today .goal-progress-label span:last-child { text-transform: none; letter-spacing: 0; color: var(--text1); }
.sd-today .goal-progress-track { background: var(--surface); border: 1px solid var(--border2); }
.sd-chain7 { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 6px; }
.sd-chain7 span { text-align: center; font-family: var(--font-mono); font-size: 10px; color: var(--text2); }
.sd-chain7 i {
  display: grid; place-items: center; height: 30px; margin-bottom: 4px; border-radius: 8px; font-style: normal;
  font-size: 15px; font-weight: 700; color: var(--accent); background: var(--surface); border: 1px solid var(--border);
}
.sd-chain7 span.t i { border: 2px solid var(--accent); }
.sd-nudge { font-size: 13px; color: var(--text2); }
.sd-nudge:empty { display: none; }
.sd-foot { display: flex; flex-wrap: wrap; gap: 6px 16px; font-family: var(--font-mono); font-size: 11px; color: var(--text2); }
.sd-foot b { font-weight: 500; color: var(--text1); }
.sd-today .help-toggle-btn { margin-top: -4px; }

.sd-planned, .sd-week { margin-top: 26px; }
.sd-week .study-chart { padding: 0; }
.sd-row { display: grid; grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); gap: 22px; margin-top: 26px; align-items: start; }
.sd-wall .cal-title { margin: 0; font-size: 18px; font-weight: 600; }
.sd-deep-total b { display: block; font-family: "Space Grotesk", var(--font-sans); font-weight: 700; font-size: 40px; letter-spacing: -0.04em; line-height: 1; color: var(--text1); }
.sd-deep-total span { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.06em; color: var(--text2); }
.sd-deep-note { font-size: 12.5px; line-height: 1.45; color: var(--text2); }

/* the last 7 days: solid bars like Home, today in highlighter */
.sd-week .sc-total b { font-family: "Space Grotesk", var(--font-sans); font-weight: 700; }
.sd-week .sc-bar { background: var(--accent); border-radius: 5px 5px 0 0; }
.sd-week .sc-col.met .sc-bar, .sd-week .sc-col.today.met .sc-bar { background: var(--accent); }
.sd-week .sc-col.today .sc-bar { background: var(--mark); }
.sd-week .sc-val, .sd-week .sc-day { font-family: var(--font-mono); font-weight: 400; }
.sd-week .sc-plot { border-bottom: 1.5px solid color-mix(in srgb, var(--text1) 55%, transparent); }
.sd-week .sc-goal span { background: var(--surface); font-family: var(--font-mono); font-weight: 400; }

/* the wall calendar */
#study-chain-grid { gap: 4px; }
#study-chain-grid .cal-day {
  position: relative; aspect-ratio: 1.5; align-items: flex-start; justify-content: flex-start; padding: 4px 6px;
  border: 1px solid var(--border2); border-radius: 7px; background: var(--surface);
}
#study-chain-grid .cal-day-num { font-family: var(--font-mono); font-size: 11px; font-weight: 400; color: var(--text2); }
#study-chain-grid .cal-day.study-complete,
#study-chain-grid .cal-day:has(.cal-day-chain-x) { background: color-mix(in srgb, var(--accent) 12%, var(--surface)); }
#study-chain-grid .cal-day.missed { background: var(--surface); }
#study-chain-grid .cal-day.today { border: 2px solid var(--accent); }
#study-chain-grid .cal-day.selected { box-shadow: 0 0 0 2px var(--text1); }
#study-chain-grid .cal-day-dots { position: absolute; inset: 0; pointer-events: none; }
#study-chain-grid .cal-day-chain-x { position: absolute; inset: 0; filter: none; }
#study-chain-grid .cal-day-chain-x::before {
  content: ''; position: absolute; left: 16%; right: 16%; top: 46%; width: auto; height: 28%;
  background: var(--mark); opacity: 0.85; border-radius: 2px; clip-path: none; transform: rotate(-4deg);
}
#study-chain-grid .cal-day-chain-x::after {
  content: '✕'; position: absolute; inset: 0; top: 4px; width: auto; height: auto; display: grid; place-items: center;
  background: none; clip-path: none; transform: rotate(-6deg);
  font-size: 20px; font-weight: 800; line-height: 1; color: var(--dw-x, var(--exam));
}
[data-dwmark="bold"] #study-chain-grid .cal-day-chain-x::before { display: none; }
[data-dwmark="bold"] #study-chain-grid .cal-day-chain-x::after { font-size: 28px; font-weight: 900; color: var(--exam); }
/* themes whose exam color is too close to their highlighter get a darker ✕
   of their own on the swipe (the bold ✕ sits on the page, so it keeps the
   exam color) */
:root[data-palette="lamp"] { --dw-x: #c2410c; }
:root[data-palette="chalk"] { --dw-x: #0b5a3a; }
:root[data-palette="bears"] { --dw-x: #0b162a; }
.sd-key { display: flex; gap: 16px; margin-top: 12px; font-family: var(--font-mono); font-size: 11px; color: var(--text2); }
.sd-key i { display: inline-block; margin-right: 6px; font-style: normal; vertical-align: -1px; }
.sd-key i.s { width: 12px; height: 12px; border-radius: 3px; background: color-mix(in srgb, var(--accent) 18%, var(--surface)); border: 1px solid var(--border); vertical-align: -2px; }
.sd-key i.x { padding: 0 3px; font-weight: 800; font-size: 13px; color: var(--dw-x, var(--exam)); background: linear-gradient(transparent 40%, var(--mark) 40% 85%, transparent 85%); }
[data-dwmark="bold"] .sd-key i.x { background: none; color: var(--exam); }
#study-chain-detail { margin-top: 8px; font-size: 12.5px; color: var(--text2); }
#study-chain-detail:empty { display: none; }

@media (max-width: 900px) {
  .sd-top, .sd-row { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 600px) {
  .sd-clock { font-size: 64px; }
  .sd-timer, .sd-deep { padding: 22px 18px 20px; }
  #study-chain-grid .cal-day { aspect-ratio: 1; padding: 3px 4px; }
  #study-chain-grid .cal-day-chain-x::after { font-size: 16px; }
  [data-dwmark="bold"] #study-chain-grid .cal-day-chain-x::after { font-size: 22px; }
}

/* ===========================
   UPDATES: AN INBOX WITH A READING PANE
   On laptops the feed is a compact list (unread dot, a mono type label,
   title, class code and sender, time) beside a sticky reading pane that
   shows the picked update on ruled paper with a red margin line. Phones
   and tablets keep the expanding cards. js/updates-inbox.js.
=========================== */
.upd-pane { display: none; }
@media (min-width: 1100px) {
  .upd-inbox.on { display: grid; grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr); gap: 22px; align-items: start; margin-top: 12px; }
  .upd-inbox.on #updates-list { border: 1px solid var(--border); border-radius: 18px; background: var(--surface); overflow: hidden; }
  .upd-inbox.on .upd-day {
    margin: 0; padding: 18px 18px 8px; border-bottom: 1px solid var(--border2);
    font-family: var(--font-mono); font-size: 11px; font-weight: 500; letter-spacing: 0.12em; text-transform: uppercase; color: var(--text2);
  }
  .upd-inbox.on .upd-day::before, .upd-inbox.on .upd-day::after { display: none; }
  .upd-inbox.on .upd-pane {
    display: block; position: sticky; top: 80px; max-height: calc(100vh - 100px); overflow-y: auto;
    border: 1px solid var(--border); border-radius: 18px; background: var(--surface);
  }
}
.upd-row {
  position: relative; display: grid; grid-template-columns: 10px minmax(0, 1fr) auto; gap: 12px; align-items: start;
  padding: 13px 18px 13px 16px; border-bottom: 1px solid var(--border2); cursor: pointer;
}
.upd-row:last-child { border-bottom: 0; }
.upd-row:hover { background: var(--surface2); }
.upd-row.sel { background: var(--surface2); box-shadow: inset 3px 0 0 var(--accent); }
.upd-row:focus-visible { outline: 2px solid var(--text1); outline-offset: -2px; }
.upd-row-dot { width: 7px; height: 7px; margin-top: 6px; border-radius: 50%; }
.upd-row.unread .upd-row-dot { background: var(--accent); }
.upd-row-main { min-width: 0; }
.upd-row-t { font-size: 14.5px; line-height: 1.35; color: var(--text2); }
.upd-row.unread .upd-row-t { font-weight: 600; color: var(--text1); }
.upd-row-k {
  margin-right: 7px; font-family: var(--font-mono); font-size: 10px; font-weight: 500;
  letter-spacing: 0.06em; text-transform: uppercase; color: var(--accent);
}
.upd-row-sub { margin-top: 3px; font-family: var(--font-mono); font-size: 11px; color: var(--text2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.upd-row-when { padding-top: 2px; font-family: var(--font-mono); font-size: 11px; color: var(--text2); white-space: nowrap; }

.upd-pane-head { padding: 24px 26px 16px; border-bottom: 1px dashed var(--border); }
.upd-pane-k { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--accent); }
.upd-pane-title { margin: 8px 0 0; font-size: 24px; font-weight: 600; letter-spacing: -0.02em; line-height: 1.2; color: var(--text1); }
.upd-pane-meta { margin-top: 8px; font-family: var(--font-mono); font-size: 12px; color: var(--text2); }
.upd-pane-body {
  padding: 8px 26px 26px 60px; white-space: pre-line; overflow-wrap: anywhere;
  font-size: 15px; line-height: 28px; color: var(--text1);
  background:
    linear-gradient(90deg, transparent 36px, color-mix(in srgb, var(--red) 60%, transparent) 36px 37.5px, transparent 37.5px),
    repeating-linear-gradient(180deg, transparent 0 27px, var(--border2) 27px 28px);
}
.upd-pane-body a { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; }
.upd-pane-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 16px 26px 22px; border-top: 1px solid var(--border2); }
.upd-pane-actions .hm-btn { padding: 8px 13px; font-size: 13.5px; text-decoration: none; }
.upd-pane-actions .hm-btn.on { color: var(--amber); }
.upd-ask {
  padding: 8px 13px; border-radius: 12px; border: 0; cursor: pointer;
  font: inherit; font-size: 13.5px; font-weight: 500; background: var(--mark); color: var(--mark-ink);
}
.upd-ask:hover { opacity: 0.9; }
.upd-pane-mute { margin-left: auto; padding: 6px 4px; border: 0; background: none; cursor: pointer; font: inherit; font-size: 13px; color: var(--text2); }
.upd-pane-mute:hover { color: var(--text1); }
.upd-pane-empty { padding: 60px 26px; text-align: center; font-size: 14px; color: var(--text2); }

/* ===========================
   LINKS: INDEX CARDS
   Each class is a ruled index card with a colored left edge and the class
   code big; links not filed under a class are bookmark tabs with a colored
   bottom edge. "Edit links" folds out the full list and the add form.
   js/links-cards.js.
=========================== */
#class-links-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 16px; margin-bottom: 30px; }
.lk-card {
  --edge: oklch(0.58 0.15 var(--h));
  display: flex; flex-direction: column; min-width: 0; border: 1px solid var(--border); border-left: 5px solid var(--edge);
  border-radius: 6px 14px 14px 6px; overflow: hidden; background: var(--surface);
}
.lk-card-head { display: flex; flex-direction: column; gap: 6px; padding: 16px 20px 12px; border-bottom: 1px solid var(--border2); color: inherit; text-decoration: none; }
.lk-card-head:hover .lk-code { color: var(--accent); }
.lk-code { font-family: "Space Grotesk", var(--font-sans); font-weight: 700; font-size: 26px; letter-spacing: -0.03em; line-height: 1; color: var(--text1); overflow-wrap: anywhere; }
.lk-code.long { font-size: 19px; line-height: 1.15; }
.lk-name { font-size: 13px; color: var(--text2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lk-btns { display: flex; flex-wrap: wrap; gap: 6px; padding: 10px 14px 10px 20px; border-bottom: 1px solid var(--border2); }
.lk-btns .hm-btn { padding: 5px 8px; border-radius: 9px; font-size: 12px; text-decoration: none; background: var(--surface); }
.lk-saved {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; margin-top: auto; padding: 10px 20px 12px;
  font-family: var(--font-mono); font-size: 11px; color: var(--text2);
}
.lk-saved span { font-family: var(--font-mono); }
.lk-saved button { padding: 0; border: 0; background: none; cursor: pointer; font: inherit; font-family: var(--font-sans); font-size: 13px; color: var(--accent); }
.lk-saved button:hover { text-decoration: underline; text-underline-offset: 2px; }

.lk-marks-h { margin-bottom: 12px; }
.lk-marks { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px; margin-bottom: 26px; }
.lk-mark {
  display: inline-flex; align-items: center; gap: 9px; max-width: 100%; min-width: 0; padding: 10px 14px 9px;
  border: 1px solid var(--border); border-bottom: 3px solid oklch(0.58 0.15 var(--h)); border-radius: 12px 12px 3px 3px;
  background: var(--surface); cursor: pointer; font: inherit; font-size: 14px; color: var(--text1);
}
.lk-mark:hover { background: var(--surface2); }
.lk-fav { display: grid; place-items: center; width: 22px; height: 22px; flex-shrink: 0; border-radius: 6px; background: var(--surface2); font-size: 12px; color: var(--text2); }
.lk-fav img { width: 14px; height: 14px; }
.lk-mark-t { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lk-host { font-family: var(--font-mono); font-size: 11px; color: var(--text2); white-space: nowrap; }
.lk-add { border-style: dashed; border-bottom-width: 1px; border-radius: 12px; color: var(--text2); background: none; }
.lk-add:hover { color: var(--text1); }

.lk-manage { border-top: 1px dashed var(--border); padding-top: 14px; }
.lk-manage > summary {
  display: flex; align-items: baseline; gap: 10px; cursor: pointer; list-style: none;
  font-size: 15px; font-weight: 600; color: var(--text1);
}
.lk-manage > summary::-webkit-details-marker { display: none; }
.lk-manage > summary .hm-k { font-weight: 400; }
.lk-manage > summary::before { content: '▸'; font-size: 12px; color: var(--text2); transition: transform 0.15s; }
.lk-manage[open] > summary::before { transform: rotate(90deg); }
.lk-manage[open] > summary { margin-bottom: 14px; }
@media (max-width: 600px) {
  #class-links-list { grid-template-columns: minmax(0, 1fr); }
  .lk-host { display: none; }
}

/* ===========================
   GOALS: A GOAL SHEET AND A CALCULATOR TICKET
   Goal cards on the left (a bar from the grade now with a marker at the
   target, "Steering Priority" in highlighter when the goal is linked to a
   class), the final exam calculator as a ticket on the right with the
   answer big. js/goals-core.js, calculateFinal.
=========================== */
@media (min-width: 900px) {
  .gl-layout { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); gap: 26px; align-items: start; }
  .gl-side { position: sticky; top: 80px; }
}
#page-goals .goal-card { padding: 18px 20px; margin-bottom: 12px; border-radius: 16px; background: var(--surface); box-shadow: none; }
#page-goals .goal-row { align-items: flex-start; gap: 12px; }
#page-goals .goal-text { font-size: 15.5px; font-weight: 600; letter-spacing: -0.01em; }
#page-goals .goal-linked { gap: 6px; margin-top: 5px; font-family: var(--font-mono); font-size: 11px; font-weight: 400; }
#page-goals .goal-linked span { padding: 0; background: none; font-weight: 500; color: var(--accent); }
.goal-steer {
  flex-shrink: 0; margin-top: 1px; padding: 3px 7px; border-radius: 4px; white-space: nowrap;
  font-family: var(--font-mono); font-size: 10.5px; font-weight: 500; letter-spacing: 0.08em; text-transform: uppercase;
  background: var(--mark); color: var(--mark-ink);
}
#page-goals .gp { margin: 26px 0 2px; }
#page-goals .gp-track { height: 9px; border-radius: 5px; background: var(--surface2); border: 1px solid var(--border2); }
#page-goals .gp-mark { top: -6px; width: 2px; height: 21px; background: var(--text1); }
#page-goals .gp-mark span {
  position: absolute; bottom: calc(100% + 3px); left: 50%; transform: translateX(-50%); white-space: nowrap;
  font-family: var(--font-mono); font-size: 10.5px; color: var(--text1);
}
#page-goals .gp-mark.end span { left: auto; right: -1px; transform: none; }
#page-goals .gp-mark.start span { left: -1px; transform: none; }
.gp-foot { display: flex; justify-content: space-between; gap: 10px; margin-top: 7px; font-family: var(--font-mono); font-size: 11px; color: var(--text2); font-variant-numeric: tabular-nums; }
#page-goals .gp-now { font-size: 11px; font-weight: 400; color: var(--text2); }
#page-goals .gp-state { flex: 0 0 auto; font-size: 11px; font-weight: 400; }
#page-goals .gp.met .gp-state { color: var(--green); font-weight: 500; }
#page-goals .goal-plan { margin-top: 14px; padding-top: 12px; border-top: 1px dashed var(--border); }
#page-goals .add-goal-row { margin-top: 4px; }
#page-goals .add-goal-input { border-style: dashed; background: transparent; }

.gl-calc {
  display: flex; flex-direction: column; gap: 16px; padding: 28px 24px 26px; background: var(--surface2);
  -webkit-mask: radial-gradient(circle at 9px 0, transparent 6px, #000 6.5px) top left / 18px 51% repeat-x,
                radial-gradient(circle at 9px 100%, transparent 6px, #000 6.5px) bottom left / 18px 51% repeat-x;
          mask: radial-gradient(circle at 9px 0, transparent 6px, #000 6.5px) top left / 18px 51% repeat-x,
                radial-gradient(circle at 9px 100%, transparent 6px, #000 6.5px) bottom left / 18px 51% repeat-x;
}
.gl-calc .hm-sec-h { margin-bottom: 0; }
.gl-calc .calc-row { gap: 8px; margin: 0; padding-bottom: 18px; border-bottom: 1px dashed var(--border); }
.gl-calc .calc-label { font-family: var(--font-mono); font-size: 10.5px; font-weight: 400; letter-spacing: 0.1em; }
.gl-calc .calc-input { background: var(--surface); font-family: var(--font-mono); text-align: left; padding-left: 12px; }
.gl-calc .calc-result { margin: 0; padding: 0; border-radius: 0; text-align: left; background: none; }
.gl-calc .calc-result-label { margin-bottom: 6px; font-family: var(--font-mono); font-size: 11px; font-weight: 400; letter-spacing: 0.12em; color: var(--text2); }
.gl-calc .calc-result-score { margin-bottom: 10px; font-family: "Space Grotesk", var(--font-sans); font-size: 68px; font-weight: 700; letter-spacing: -0.05em; color: var(--text1); }
.gl-calc .calc-result-msg { font-size: 13.5px; line-height: 1.5; color: var(--text2); }
.gl-calc .calc-result[data-cat="secured"] .calc-result-score,
.gl-calc .calc-result[data-cat="secured"] .calc-result-label { color: var(--green); }
.gl-calc .calc-result[data-cat="impossible"] .calc-result-score,
.gl-calc .calc-result[data-cat="impossible"] .calc-result-label { color: var(--red); }
.gl-calc-hint { font-size: 13px; line-height: 1.5; color: var(--text2); }
.gl-classes-h { margin-top: 26px; }
@media (max-width: 899px) {
  .gl-side { margin-top: 26px; }
}
@media (max-width: 600px) {
  .gl-calc { padding: 24px 18px 22px; }
  .gl-calc .calc-result-score { font-size: 54px; }
  #page-goals .goal-row { flex-wrap: wrap; }
}

/* ===========================
   SYLLABUS: A COURSE BINDER
   On laptops the classes are binder tabs down the left (code big, found
   or not) and the open class sits beside them: its key dates as tear-off
   chips (exams in the exam color), then Ask / Search and the syllabus on
   ruled paper with matches in highlighter. js/syllabus-binder.js.
=========================== */
.syl-pane { display: none; }
@media (min-width: 1100px) {
  .syl-binder.on { display: grid; grid-template-columns: 230px minmax(0, 1fr); align-items: start; }
  .syl-binder.on #syllabus-list { display: flex !important; flex-direction: column; gap: 6px; padding-top: 14px; }
  .syl-binder.on:has(#syllabus-list[style*="none"]) { display: none; }
  .syl-binder.on .syl-pane {
    display: flex; flex-direction: column; gap: 14px; min-width: 0; min-height: 420px; padding: 26px 28px 28px;
    border: 1px solid var(--border); border-radius: 18px; background: var(--surface);
  }
}
.syl-tab {
  display: flex; flex-direction: column; gap: 4px; padding: 13px 14px; margin-right: -1px; text-align: left; cursor: pointer;
  border: 1px solid var(--border); border-right: 0; border-radius: 12px 0 0 12px; background: var(--surface2); font: inherit; color: var(--text1);
}
.syl-tab:hover { background: color-mix(in srgb, var(--surface) 60%, var(--surface2)); }
.syl-tab.on { position: relative; z-index: 1; background: var(--surface); box-shadow: inset 3px 0 0 var(--accent); }
.syl-tab-code { font-family: "Space Grotesk", var(--font-sans); font-weight: 700; font-size: 17px; letter-spacing: -0.02em; line-height: 1.15; overflow-wrap: anywhere; }
.syl-tab-st { font-family: var(--font-mono); font-size: 10.5px; color: var(--text2); }
.syl-tab-st.miss { color: var(--red); }

.syl-pane-code { font-family: "Space Grotesk", var(--font-sans); font-weight: 700; font-size: 30px; letter-spacing: -0.03em; line-height: 1.05; color: var(--text1); }
.syl-pane-name { margin-top: 4px; font-size: 13px; color: var(--text2); }
.syl-pane .hm-sec-h { margin: 8px 0 0; }
.syl-pane-dates { display: flex; flex-wrap: wrap; gap: 8px; }
.syl-pd { display: flex; align-items: center; gap: 10px; max-width: 260px; padding: 7px 12px 7px 8px; border: 1px solid var(--border); border-radius: 12px; background: var(--surface2); }
.syl-pd .syl-date-chip { flex-shrink: 0; width: 38px; text-align: center; }
.syl-pd .syl-date-chip span { font-size: 9.5px; }
.syl-pd .syl-date-chip b { font-size: 17px; }
.syl-pd.exam .syl-date-chip { border-color: var(--exam); }
.syl-pd.exam .syl-date-chip span { background: var(--exam); color: var(--exam-ink); }
.syl-pd-t { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.syl-pd-t b { font-size: 13.5px; font-weight: 500; color: var(--text1); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.syl-pd-t span { font-family: var(--font-mono); font-size: 10.5px; color: var(--text2); }
.syl-pane #syl-detail-body .syllabus-text {
  max-height: 62vh; overflow-y: auto; padding: 4px 18px 12px 40px; border-radius: 0; font-size: 14px; line-height: 28px;
  border-top: 1px solid var(--border2); border-bottom: 1px solid var(--border2);
  background:
    linear-gradient(90deg, transparent 22px, color-mix(in srgb, var(--red) 55%, transparent) 22px 23.5px, transparent 23.5px),
    repeating-linear-gradient(180deg, transparent 0 27px, var(--border2) 27px 28px),
    var(--surface);
  background-attachment: local;
}
.syl-pane mark { background: var(--mark); color: var(--mark-ink); border-radius: 2px; }
.syl-pane .syllabus-textarea { background: var(--surface2); }

/* ===========================
   SETTINGS: AN INDEX AND A PANEL
   On laptops the sections are a sticky list down the left (like the
   Assignments filter column) with a short status in mono, and the open
   section is on the right. Every setting reads as its own row: what it is
   on the left, the control on the right. Phones keep the tabs on top.
   js/settings-index.js.
=========================== */
.settings-tab .st-k { display: none; }
#page-settings .section-label {
  font-family: var(--font-mono); font-size: 11px; font-weight: 500; letter-spacing: 0.12em; text-transform: uppercase; color: var(--text2);
}
#page-settings .settings-panel .card { border-radius: 16px; background: var(--surface); box-shadow: none; }
#page-settings .tweak-label { font-family: var(--font-sans); font-size: 14px; font-weight: 600; letter-spacing: -0.005em; text-transform: none; color: var(--text1); }
#page-settings .toggle-row-label { font-size: 14px; font-weight: 600; }
#page-settings .toggle-row-sub { font-size: 12.5px; }
@media (min-width: 700px) {
  /* label (and its note) on the left, the control on the right */
  #page-settings .tweak-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: 18px; align-items: center; padding: 4px 0; }
  #page-settings .tweak-row > .tweak-label { grid-column: 1; margin: 0; }
  #page-settings .tweak-row > .card-sub { grid-column: 1; margin: 2px 0 0 !important; }
  #page-settings .tweak-row > :not(.tweak-label):not(.card-sub):not(.theme-mode-note) { grid-column: 2; grid-row: 1; }
  #page-settings .tweak-row:has(> .card-sub) > :not(.tweak-label):not(.card-sub):not(.theme-mode-note) { grid-row: 1 / span 2; }
  #page-settings .tweak-row > .seg-control .seg-btn { white-space: nowrap; }
  #page-settings .tweak-row > .theme-mode-note { grid-column: 1 / -1; }
  #page-settings .tweak-row:has(> .theme-grid) { display: block; }
  #page-settings .tweak-row:has(> .theme-grid) > .tweak-label { margin-bottom: 10px; }
  #page-settings .tweak-row + .tweak-row { border-top: 1px solid var(--border2); padding-top: 14px; }
  #page-settings .tweak-slider { width: 200px; }
}
@media (min-width: 1100px) {
  #page-settings.active { display: grid; grid-template-columns: 220px minmax(0, 1fr); column-gap: 30px; align-items: start; }
  #page-settings > .page-head { grid-column: 1 / -1; }
  #page-settings > .settings-tabs {
    grid-column: 1; grid-row: 2; position: sticky; top: 80px; flex-direction: column; gap: 2px; padding: 0; margin: 0;
    background: none; border: 0; border-radius: 0; box-shadow: none; -webkit-backdrop-filter: none; backdrop-filter: none; overflow: visible;
  }
  #page-settings > .settings-panel { grid-column: 2; grid-row: 2; min-width: 0; }
  #page-settings > .settings-panel[hidden] { display: none; }
  #page-settings > .settings-panel > .section-label:first-child { margin-top: 0; }
  #page-settings .settings-tab {
    display: flex; justify-content: space-between; align-items: baseline; gap: 10px; flex: none; width: 100%;
    padding: 10px 12px 10px 14px; text-align: left; font-size: 14.5px; font-weight: 400;
    border-left: 3px solid transparent; border-radius: 0 10px 10px 0;
  }
  #page-settings .settings-tab:active { transform: none; }
  #page-settings .settings-tab.active { background: var(--surface2); box-shadow: none; border-left-color: var(--accent); font-weight: 600; }
  #page-settings .settings-tab .st-k { display: inline; font-family: var(--font-mono); font-size: 10.5px; font-weight: 400; color: var(--text2); white-space: nowrap; }
}

/* ===========================
   SYNC SCREEN: A TICKET ON NOTEBOOK PAPER
   The welcome / syncing / done / error screen sits on the same ruled paper
   as setup, in a ticket like the Study timer: a mono label, the percent in
   big type, a solid bar, the status line. No glow, ring or spinning tile.
=========================== */
#ws-overlay {
  background:
    linear-gradient(90deg, transparent 30px, color-mix(in srgb, var(--red) 35%, transparent) 30px 32px, transparent 32px),
    repeating-linear-gradient(180deg, transparent 0 31px, var(--border2) 31px 32px),
    var(--bg);
}
#ws-card {
  max-width: 480px; padding: 34px 32px 30px; text-align: left; border: 0; border-radius: 0;
  box-shadow: inset 0 0 0 1px var(--border);
  background: var(--surface); -webkit-backdrop-filter: none; backdrop-filter: none;
  -webkit-mask: radial-gradient(circle at 9px 0, transparent 6px, #000 6.5px) top left / 18px 51% repeat-x,
                radial-gradient(circle at 9px 100%, transparent 6px, #000 6.5px) bottom left / 18px 51% repeat-x;
          mask: radial-gradient(circle at 9px 0, transparent 6px, #000 6.5px) top left / 18px 51% repeat-x,
                radial-gradient(circle at 9px 100%, transparent 6px, #000 6.5px) bottom left / 18px 51% repeat-x;
}
@media (max-height: 780px) { #ws-card { padding: 26px 24px 22px; } }
#ws-close { background: var(--surface); border: 1px solid var(--border); }
.ws-k { margin-bottom: 14px; font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--text2); }
.ws-k-err { color: var(--red); }

/* syncing */
#ws-syncing { text-align: left !important; padding: 0 !important; }
.ws-sync-logo-wrap { display: none; }
#ws-sync-percent {
  margin: 0; font-family: "Space Grotesk", var(--font-sans); font-weight: 700; font-size: 84px;
  letter-spacing: -0.05em; line-height: 0.9; color: var(--text1);
}
.ws-sync-bar { height: 10px; margin: 22px 0 14px; border-radius: 5px; background: var(--surface); border: 1px solid var(--border2); overflow: hidden; }
.ws-sync-bar i { position: relative; display: block; height: 100%; width: 0; overflow: hidden; background: var(--accent); transition: width 0.3s ease-out; }
/* A soft light sliding along the filled part: still working, even when
   the number moves slowly while Canvas answers. */
.ws-sync-bar i::after {
  content: ''; position: absolute; inset: 0; width: 40%;
  background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--surface) 55%, transparent), transparent);
  animation: wsBarSlide 1.6s ease-in-out infinite;
}
@keyframes wsBarSlide { from { transform: translateX(-100%); } to { transform: translateX(260%); } }
@media (prefers-reduced-motion: reduce) { .ws-sync-bar i::after { animation: none; display: none; } }
#ws-syncing-msg { margin: 0; font-size: 14px; color: var(--text2); }
.ws-slow { margin-top: 20px; padding-top: 16px; border-top: 1px dashed var(--border); }
.ws-slow[hidden] { display: none; }
.ws-slow p { margin: 0 0 12px; font-size: 13.5px; line-height: 1.5; color: var(--text2); }
.ws-slow .hm-btn { padding: 9px 14px; font-size: 14px; }

/* ===========================
   DONE POPUP: A TICKET STUB
   Checking work off (and finishing a study session) pops a small stub:
   the count big on a stroke of highlighter, rolling to its new value,
   a dashed tear line, then a mono label, the message and this week's bar
   in the theme's pen color. showDoneToast in index.html.
=========================== */
.done-toast, [data-theme="dark"] .done-toast {
  gap: 0; min-width: 320px; padding: 0; overflow: hidden;
  background: var(--surface); border: 1px solid var(--border); border-radius: 14px;
  box-shadow: 0 14px 34px rgba(0, 0, 0, 0.16);
}
.done-toast .dt-badge { display: none; }
/* The number's box is exactly one line tall so the roll hides the old and
   new values above and below it; the tear line is on the text side. */
.done-toast .dt-odo {
  display: grid; justify-items: center; flex-shrink: 0; overflow: hidden;
  min-width: 58px; height: 40px; margin: 0 14px 0 18px; padding: 0 6px;
  font-family: "Space Grotesk", var(--font-sans); font-size: 34px; font-weight: 700; letter-spacing: -0.03em; line-height: 40px;
  color: var(--mark-ink); background: var(--mark); border-radius: 3px; /* a swipe of highlighter, ink always on it */
}
.done-toast .dt-old, .done-toast .dt-new { grid-area: 1 / 1; height: 40px; }
.done-toast .dt-new { position: static; }
.done-toast.show .dt-new { color: var(--mark-ink); }
.done-toast .dt-main { align-self: stretch; padding: 13px 18px 13px 16px; border-left: 1.5px dashed var(--border); }
.done-toast .dt-label {
  display: block; margin-bottom: 4px; font-family: var(--font-mono); font-size: 10.5px; font-weight: 400;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--text2);
}
.done-toast .dt-msg { margin: 0; font-size: 14px; font-weight: 500; color: var(--text1); }
.done-toast .dt-week { margin-top: 9px; }
.done-toast .dt-bar, [data-theme="dark"] .done-toast .dt-bar { height: 7px; border-radius: 4px; background: var(--surface2); border: 1px solid var(--border2); }
.done-toast .dt-bar i { background: var(--accent); }
.done-toast .dt-week-text { font-family: var(--font-mono); font-size: 10.5px; font-weight: 400; letter-spacing: 0.08em; text-transform: uppercase; }
/* Clearing the week or every 10th: the pen color frames the stub */
.done-toast.dt-big { border-color: var(--accent); box-shadow: 0 14px 34px rgba(0, 0, 0, 0.16), 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent); }
/* Study time ("1h 30m"): text is wider, so a smaller number */
.done-toast.dt-text-odo .dt-odo { font-size: 22px; min-width: 88px; }
@media (max-width: 600px) {
  .done-toast, [data-theme="dark"] .done-toast { min-width: 0; }
  .done-toast .dt-odo { min-width: 48px; font-size: 30px; margin: 0 12px 0 14px; }
}

/* welcome */
#ws-badge { display: none; }
#ws-welcome { min-height: 0; }
#ws-greeting-block { justify-content: flex-start; padding-bottom: 26px; }
#ws-heading { font-size: 32px; font-weight: 600; letter-spacing: -0.02em; color: var(--text1); margin-bottom: 8px; }
#ws-date { font-family: var(--font-mono); font-size: 12px; letter-spacing: 0.12em; text-transform: uppercase; margin-bottom: 14px; }
#ws-streak { margin: 0 0 16px; padding: 4px 9px; border-radius: 4px; font-family: var(--font-mono); font-size: 12px; font-weight: 500; background: var(--mark); color: var(--mark-ink); }
.ws-flame { animation: none; }
#ws-subtitle { font-size: 15px; margin-bottom: 18px; }
#ws-summary { gap: 0; margin: 0; border-top: 1px solid var(--border2); }
.ws-summary-row { padding: 11px 2px; border-radius: 0; background: none; border-bottom: 1px solid var(--border2); font-size: 14px; font-weight: 500; animation: none; }
.ws-summary-row .ws-summary-icon { width: 20px; height: 20px; background: none; color: var(--accent); animation: none; }
.ws-summary-row.ws-summary-announce { background: none; box-shadow: none; color: var(--text1); }
.ws-summary-row.ws-summary-announce .ws-summary-icon { background: none; color: var(--accent); }
#ws-sync-btn { padding: 15px; border-radius: 12px; font-size: 15px; font-weight: 600; animation: none; }
#ws-sync-btn::after { display: none; }
.ws-skip { margin: 12px 0 0; padding: 0; font-family: var(--font-mono); font-size: 12px; animation: none; }

/* done and error */
#ws-result, #ws-error { text-align: left; }
.ws-check-badge, .ws-error-badge { display: none; }
#ws-result-count, #ws-error-title { text-align: left; font-family: "Space Grotesk", var(--font-sans); font-size: 34px; font-weight: 700; letter-spacing: -0.03em; line-height: 1.05; margin-bottom: 10px; }
#ws-result.ws-result-calm #ws-result-count { font-size: 34px; letter-spacing: -0.03em; }
#ws-result-sub, #ws-error-sub { text-align: left; font-size: 14px; margin-bottom: 20px; }
#ws-result.ws-result-calm #ws-result-sub { font-size: 14px; font-style: normal; opacity: 1; }
#ws-error-detail { text-align: left; font-family: var(--font-mono); }
#ws-view-btn { padding: 13px; border: 0; border-radius: 12px; background: var(--btn-bg); color: var(--btn-fg); font-size: 15px; }
#ws-error-retry-btn { padding: 13px; font-weight: 600; }
#ws-error-report-panel { background: var(--surface); border: 1px solid var(--border); }
@media (max-width: 420px) {
  #ws-card { padding: 28px 22px 24px; }
  #ws-sync-percent { font-size: 68px; }
  #ws-heading { font-size: 27px; }
}
