/* ════════════════════════════════════════════════════════════════════════
   StudyBuddy
   Look: a night-sky field notebook. Ink and paper pinned over deep space.
   Deliberately not a dashboard — no glassy cards, no gradient buttons,
   nothing centred in a 12-column grid. Things sit slightly crooked because
   a person put them there.
   ════════════════════════════════════════════════════════════════════════ */

:root {
  --void:        #070b12;
  --void-2:      #0c121d;
  --ink:         #131b28;
  --paper:       #f2ead9;
  --paper-line:  #d9cdb4;
  --paper-shade: #e6dcc6;
  --cream:       #efe6d4;
  --dim:         #9aa4b4;
  --dimmer:      #67717f;
  --brass:       #8fd4e8;
  --brass-ink:   #1f242c;
  --rust:        #c96f4a;
  --alarm:       #d4553f;
  --teal:        #4a9a8f;

  --edge: rgba(239,230,212,.14);

  --serif: "Fraunces", "Iowan Old Style", Georgia, serif;
  --sans:  "Karla", "Helvetica Neue", Arial, sans-serif;

  --r-card: 3px;
}

* { box-sizing: border-box; }

html, body {
  margin: 0; padding: 0;
  min-height: 100%;
  background: radial-gradient(120% 90% at 70% -10%, #14203a 0%, var(--void-2) 42%, var(--void) 100%);
  color: var(--cream);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

/* Film grain so the black is never a flat digital black. */
.grain {
  position: fixed; inset: 0; z-index: 0; pointer-events: none; opacity: .045;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.82' numOctaves='4'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}

#starfield { position: fixed; inset: 0; z-index: 0; pointer-events: none; }

/* ─────────────────────────────────────────────────────── the boot screen ──
   Sits over everything until the app has something to show. It carries the
   body's own gradient rather than going transparent, because the thing it is
   covering is an empty shell — placeholder cards, unpopulated lists, a nav
   still deciding whether it has an Admin tab. Showing that through the comet
   would leave the flicker exactly where it was. The starfield comes back with
   the app as this fades. */
.boot {
  position: fixed; inset: 0; z-index: 60;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 10px;
  padding: 24px;
  background: radial-gradient(120% 90% at 70% -10%, #14203a 0%, var(--void-2) 42%, var(--void) 100%);
  transition: opacity .45s ease;
}
.boot[hidden] { display: none; }
.boot.is-gone { opacity: 0; pointer-events: none; }

.boot-orrery { width: min(420px, 80vw); height: auto; overflow: visible; }

/* A tail is blown off by the sun, so it is longest at perihelion and nearly
   gone at the far end. The motion above puts the comet at perihelion at 0%
   and aphelion at 50%, so these keyframes line up with it. */
.boot-comet-tail {
  transform-origin: 0 0;
  animation: comet-tail 3.6s linear infinite;
}
@keyframes comet-tail {
  0%, 100% { transform: scaleX(1);   opacity: 1; }
  50%      { transform: scaleX(.42); opacity: .5; }
}

.boot-track {
  fill: none; stroke: rgba(239,230,212,.16);
  stroke-width: 1; stroke-dasharray: 3 7;
}

.boot-word {
  margin: 0;
  font-family: var(--sans); font-size: 11.5px;
  letter-spacing: .2em; text-transform: uppercase;
  color: rgba(239,230,212,.42);
}

/* SMIL ignores the blanket animation-duration override further down, so the
   comet has to be taken off the board by hand. What is left still reads as a
   solar system, just a still one. */
@media (prefers-reduced-motion: reduce) {
  .boot-comet { display: none; }
  .boot-track { stroke: rgba(239,230,212,.26); }
}

/* ─────────────────────────────────────────────────────────── masthead ── */

.masthead {
  position: relative; z-index: 3;
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 24px; flex-wrap: wrap;
  padding: 26px 34px 18px;
  border-bottom: 1px solid var(--edge);
}

.wordmark { position: relative; }

.lockup--header { height: 64px; width: auto; display: block; }

.nav { display: flex; gap: 4px; align-items: center; padding-bottom: 4px; }

.navbtn {
  background: none; border: 0; cursor: pointer;
  font-family: var(--sans); font-size: 14px; color: var(--dim);
  padding: 7px 13px; border-radius: 2px;
  border-bottom: 2px solid transparent;
  transition: color .15s, border-color .15s;
}
.navbtn:hover { color: var(--paper); }
.navbtn.is-on { color: var(--paper); border-bottom-color: var(--brass); }

.navbtn.ghost {
  margin-left: 10px;
  border: 1px solid var(--edge); border-radius: 999px;
  padding: 6px 16px; color: var(--cream);
}
.navbtn.ghost:hover { border-color: var(--brass); color: var(--brass); }

/* ─────────────────────────────────────────────────────────── auth gate ── */

.auth-gate {
  position: fixed; inset: 0; z-index: 50;
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
}
.auth-gate[hidden] { display: none; }

.auth-card {
  width: 100%; max-width: 340px;
  background: var(--paper); color: var(--ink);
  border-radius: var(--r-card);
  padding: 30px 28px 26px;
  box-shadow: 0 24px 50px -20px rgba(0,0,0,.9);
  text-align: center;
}

.lockup--auth { height: 72px; width: auto; margin: 0 auto 22px; display: block; }

.code-input {
  /* 6 x 40 + 5 x 7 = 275px, inside the auth card's 284px of usable width. */
  display: flex; gap: 7px; justify-content: center; margin: 4px 0 14px;
}
.code-input input {
  width: 40px; height: 52px; padding: 0; margin: 0;
  text-align: center; font-family: var(--sans); font-size: 22px; font-weight: 600;
  color: var(--ink); background: #fff;
  border: 1px solid rgba(0,0,0,.18); border-radius: 4px;
}
.code-input input:focus {
  outline: none; border-color: var(--ink); box-shadow: 0 0 0 2px rgba(0,0,0,.06);
}

.verify-actions {
  display: flex; justify-content: space-between; align-items: center; margin-top: 4px;
}
.verify-actions .auth-link { margin: 0; }

@media (max-width: 380px) {
  .code-input { gap: 5px; }
  .code-input input { width: 38px; height: 46px; font-size: 19px; }
}

.auth-tabs {
  display: flex; border-bottom: 1px solid rgba(0,0,0,.1); margin-bottom: 18px;
}
.auth-tabs[hidden] { display: none; }
.auth-tab {
  flex: 1; background: none; border: 0; cursor: pointer;
  font-family: var(--sans); font-size: 13.5px; color: #8a7c62;
  padding: 8px 4px; border-bottom: 2px solid transparent;
}
.auth-tab.is-on { color: var(--ink); border-bottom-color: var(--rust); }

#auth-form { display: flex; flex-direction: column; gap: 10px; text-align: left; }
#auth-form[hidden] { display: none; }
#auth-form input {
  font-family: var(--sans); font-size: 14px; color: var(--ink);
  background: rgba(255,255,255,.55); border: 1px solid rgba(0,0,0,.18);
  border-radius: 2px; padding: 10px 11px;
}
#auth-form .btn { margin-top: 4px; }

.auth-error {
  color: #9c3a26; font-size: 12.5px; margin: -2px 0 0;
}

.auth-link {
  display: block; margin: 12px auto 0; background: none; border: 0;
  cursor: pointer; font-family: var(--sans); font-size: 12.5px;
  color: #8a7c62; text-decoration: underline;
}
.auth-link:hover { color: var(--ink); }
.auth-link[hidden] { display: none; }
#reset-form[hidden], #newpw-form[hidden] { display: none; }
#reset-form, #newpw-form { display: flex; flex-direction: column; gap: 10px; text-align: left; }
.auth-hint { font-size: 12.5px; color: #8a7c62; margin: 0 0 2px; }

/* ────────────────────────────────────────────────────────────── stage ── */

.stage {
  position: relative; z-index: 2;
  display: grid;
  grid-template-columns: 320px minmax(0, 1fr);
  gap: 30px;
  padding: 26px 34px 60px;
  align-items: start;
}

.view { display: none; }
.view.is-on { display: block; }

/* The admin table needs the full stage width — a 320px rail alongside it
   squeezes the columns until the row actions fall off the edge. */
.stage:has(.view--admin.is-on) { grid-template-columns: minmax(0, 1fr); }
.stage:has(.view--admin.is-on) .rail { display: none; }

/* ─────────────────────────────────────────────────────── paper cards ── */

.card {
  position: relative;
  background: var(--paper);
  color: var(--ink);
  border-radius: var(--r-card);
  padding: 16px 18px 14px;
  margin-bottom: 16px;
  box-shadow: 0 14px 30px -18px rgba(0,0,0,.9), 0 2px 0 rgba(0,0,0,.25);
  /* faint ruled lines, like a notebook */
  background-image: repeating-linear-gradient(
      to bottom, transparent 0 27px, var(--paper-line) 27px 28px);
  background-position: 0 44px;
}
.card--today    { transform: rotate(-.55deg); }
.card--tomorrow { transform: rotate(.4deg); }
.card--study    { transform: rotate(-.3deg); }
.card--overdue  { transform: rotate(-.25deg); background: #f3ded5; }

/* a strip of tape holding the top card down */
.tape {
  position: absolute; top: -11px; left: 50%; width: 82px; height: 22px;
  transform: translateX(-50%) rotate(-2.5deg);
  background: rgba(226,214,180,.55);
  border-left: 1px dashed rgba(0,0,0,.08);
  border-right: 1px dashed rgba(0,0,0,.08);
  box-shadow: 0 1px 2px rgba(0,0,0,.12);
}

/* Craig — the chill weekly check-in. Defaults to a spot under the nav on
   the right, like a little note dropped near "Ask", but it's a floating
   widget: draggable anywhere by its grip, dismissible to a small pill,
   and poppable back out from there. Position and dismissed state persist
   in localStorage (static/js/app.js's CRAIG_* helpers), independent of
   any account -- purely a per-browser UI preference. */
.craig-bubble {
  position: fixed; top: 96px; right: 34px; z-index: 30;
  width: 250px;
  background: var(--paper); border-radius: 16px;
  padding: 8px 16px 15px;
  box-shadow: 0 10px 22px -10px rgba(0,0,0,.85);
}
.craig-bubble[hidden] { display: none; }
.craig-bubble--moved .craig-tail { display: none; }

/* Craig's line comes from /api/briefing, which lands a few seconds after the
   rest of the page. Drifting in is kinder than appearing mid-read. */
.craig-bubble { animation: craig-arrive .5s ease-out; }
@keyframes craig-arrive {
  from { opacity: 0; transform: translateY(-8px); }
}

.craig-handle {
  display: flex; align-items: center; justify-content: space-between;
  margin: 0 -4px 4px; padding: 2px 4px; border-radius: 8px;
  cursor: grab; touch-action: none;
}
.craig-handle:active { cursor: grabbing; }
.craig-grip {
  font-size: 10px; letter-spacing: 1px; color: rgba(0,0,0,.22);
  user-select: none;
}
.craig-dismiss {
  background: none; border: 0; cursor: pointer; line-height: 1;
  font-size: 17px; color: rgba(0,0,0,.35); padding: 0 2px;
}
.craig-dismiss:hover { color: rgba(0,0,0,.7); }

.craig-text {
  font-family: var(--serif); font-style: italic;
  font-size: 14px; line-height: 1.5; margin: 0; color: #4a4132;
}
.craig-tail {
  /* Lines the tail's apex up with the centre of the Ask button. The nav is
     right-aligned, so the button sits a fixed distance from the viewport edge
     and this offset holds at both desktop widths — the masthead padding and
     the bubble's own right offset shrink by the same 14px at 1000px. */
  position: absolute; right: 123px; top: -7px; width: 15px; height: 15px;
  background: var(--paper);
  clip-path: polygon(0 100%, 100% 100%, 100% 0);
}

.craig-pill {
  position: fixed; top: 96px; right: 34px; z-index: 30;
  width: 40px; height: 40px; border-radius: 50%;
  background: var(--paper); border: 0; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 10px 22px -10px rgba(0,0,0,.85);
  touch-action: none;
}
.craig-pill[hidden] { display: none; }
.craig-pill img { display: block; }
.craig-pill:hover { transform: scale(1.06); }

.card-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 10px; margin-bottom: 6px;
}
.card-head h2 {
  font-family: var(--serif); font-weight: 600; font-size: 19px;
  margin: 0; letter-spacing: -.01em;
}
.card--overdue .card-head h2 { color: #9c3a26; }

.date-stamp {
  font-size: 11px; letter-spacing: .1em; text-transform: uppercase;
  color: #8a7c62; white-space: nowrap;
}

.briefing {
  font-family: var(--serif); font-style: italic;
  font-size: 14.5px; line-height: 1.5;
  margin: 2px 0 12px; color: #4a4132;
  padding-bottom: 10px; border-bottom: 1px solid rgba(0,0,0,.09);
}

.duelist { list-style: none; margin: 0; padding: 0; }

.duelist li {
  display: flex; align-items: flex-start; gap: 9px;
  padding: 6px 0; line-height: 1.35;
  border-bottom: 1px solid rgba(0,0,0,.055);
}
.duelist li:last-child { border-bottom: 0; }

.tick {
  flex: 0 0 auto; margin-top: 2px;
  width: 15px; height: 15px; border-radius: 2px; cursor: pointer;
  border: 1.5px solid #9a8e74; background: transparent;
  transition: background .12s, border-color .12s;
}
.tick:hover { border-color: #4a4132; }
.tick.is-done { background: #7a8b5f; border-color: #7a8b5f; }

.due-body { min-width: 0; flex: 1; }
.due-course {
  font-size: 10.5px; letter-spacing: .09em; text-transform: uppercase;
  font-weight: 700; display: inline-flex; align-items: center; gap: 5px;
}
.due-dot { width: 7px; height: 7px; border-radius: 50%; display: inline-block; }
.due-title { font-size: 14px; color: #241f18; }
.due-meta { font-size: 11.5px; color: #7d7462; }
.is-done .due-title { text-decoration: line-through; opacity: .5; }

.nothing {
  font-family: var(--serif); font-style: italic;
  color: #8a7c62; font-size: 14px; padding: 4px 0 6px;
}

.study-flag {
  font-size: 10px; letter-spacing: .12em; text-transform: uppercase;
  color: #9a8f78; white-space: nowrap;
}

.studylist { list-style: none; margin: 0; padding: 0; }
.study-item {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 11px 0; cursor: pointer;
  border-bottom: 1px solid rgba(0,0,0,.09);
}
.studylist li:last-child { border-bottom: 0; padding-bottom: 2px; }

.study-ring {
  flex: 0 0 auto; margin-top: 2px; cursor: pointer;
  width: 15px; height: 15px; border-radius: 50%;
  border: 1.5px solid var(--ring-color, #9a8e74); background: transparent;
  transition: background .12s;
}
.study-ring.is-planned { background: var(--ring-color, #9a8e74); }

.study-body { min-width: 0; flex: 1; }
.study-title { font-size: 14px; font-weight: 700; color: #241f18; }
.study-reason { font-size: 12.5px; color: #7d7462; margin-top: 2px; }

.study-duration {
  font-family: var(--serif); font-weight: 600; font-size: 13px;
  color: var(--ring-color, #c96f4a); white-space: nowrap; flex: 0 0 auto;
}

.study-dismiss {
  flex: 0 0 auto; cursor: pointer; background: none; border: 0;
  color: #b2a68c; font-size: 15px; line-height: 1; padding: 2px 0 0 2px;
}
.study-dismiss:hover { color: #4a4132; }

.study-note {
  font-size: 12px; color: #9a8f78; margin: 8px 0 0;
}

/* ───────────────────────────────────────────────────────────── buttons ── */

/* Where you are in the term. A stretched-out arc rather than a progress bar,
   because a progress bar makes a semester feel like a software install. */
.semester { margin-top: 22px; color: var(--brass); }
.sem-head {
  display: flex; justify-content: space-between; align-items: baseline;
  font-size: 11px; letter-spacing: .13em; text-transform: uppercase;
  color: var(--dim); margin-bottom: 5px;
}
.sem-head span:last-child { color: var(--dimmer); }
.sem-arc { display: block; width: 100%; height: 12px; }
.sem-note {
  margin: 5px 0 0; font-size: 12px; color: var(--dimmer);
  font-family: var(--serif); font-style: italic;
}

.rail-actions { display: flex; flex-direction: column; gap: 8px; margin-top: 20px; }

.btn {
  font-family: var(--sans); font-size: 14px;
  padding: 10px 16px; cursor: pointer;
  background: transparent; color: var(--cream);
  border: 1px solid var(--edge); border-radius: 2px;
  transition: border-color .15s, color .15s, background .15s;
}
.btn:hover { border-color: rgba(239,230,212,.4); background: rgba(239,230,212,.05); }

.btn--primary {
  background: var(--brass); border-color: var(--brass); color: var(--brass-ink);
  font-weight: 700; letter-spacing: .01em;
}
.btn--primary:hover { background: #a9e2f0; border-color: #a9e2f0; color: var(--brass-ink); }

.btn--quiet { color: var(--dim); font-size: 13px; padding: 8px 14px; }

.btn--danger { color: var(--alarm); border-color: rgba(212,85,63,.4); }
.btn--danger:hover { background: rgba(212,85,63,.12); border-color: var(--alarm); }

/* ────────────────────────────────────────────────────────── admin ── */

.admin-stats { display: flex; gap: 16px; font-size: 13px; color: var(--dim); }
.admin-stats b { color: var(--cream); font-weight: 600; }

.admin-controls {
  display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin: 14px 0 12px;
}
.admin-controls input[type="search"] { flex: 1 1 220px; min-width: 180px; }
.admin-controls input[type="search"], .admin-controls select {
  font-family: var(--sans); font-size: 13.5px;
  padding: 9px 11px; color: var(--cream);
  background: rgba(239,230,212,.04);
  border: 1px solid var(--edge); border-radius: 2px;
}
.admin-controls select { cursor: pointer; }
.admin-controls input[type="search"]:focus, .admin-controls select:focus {
  outline: none; border-color: rgba(239,230,212,.4);
}

/* The table is the one thing here that genuinely needs width, so it scrolls
   inside its own box rather than pushing the page sideways. */
.admin-table-wrap { overflow-x: auto; border-top: 1px solid var(--edge); }

.admin-table { width: 100%; border-collapse: collapse; font-size: 13.5px; min-width: 760px; }
.admin-table th {
  text-align: left; font-weight: 600; color: var(--dim);
  font-size: 11.5px; letter-spacing: .08em; text-transform: uppercase;
  padding: 12px 10px; border-bottom: 1px solid var(--edge); white-space: nowrap;
}
.admin-table th.sortable { cursor: pointer; user-select: none; }
.admin-table th.sortable:hover { color: var(--cream); }
.admin-table th.is-sorted { color: var(--brass); }
.admin-table td {
  padding: 11px 10px; color: var(--cream);
  border-bottom: 1px solid rgba(239,230,212,.07); vertical-align: middle;
}
.admin-table tr:hover td { background: rgba(239,230,212,.03); }
.admin-table .col-email { font-weight: 600; }
.admin-table .muted { color: var(--dimmer); }
.admin-table .col-when { white-space: nowrap; }
.admin-table td:last-child { text-align: right; white-space: nowrap; }
.admin-table .num { font-variant-numeric: tabular-nums; }

.tag {
  display: inline-block; font-size: 11px; letter-spacing: .05em;
  text-transform: uppercase; padding: 3px 7px; border-radius: 2px;
  border: 1px solid transparent; white-space: nowrap;
}
.tag--admin { color: var(--brass); border-color: rgba(143,212,232,.4); }
.tag--user { color: var(--dim); border-color: var(--edge); }
.tag--suspended { color: var(--alarm); border-color: rgba(212,85,63,.45); }
.tag--active { color: var(--teal); border-color: rgba(74,154,143,.4); }
.tag--unverified { color: var(--rust); border-color: rgba(201,111,74,.4); }
.tag + .tag { margin-left: 5px; }
.admin-table td:nth-child(3) { white-space: nowrap; }

.admin-foot {
  display: flex; justify-content: space-between; align-items: center;
  margin-top: 14px; font-size: 13px; color: var(--dim);
}
.admin-pager { display: flex; gap: 6px; }

.admin-edit-meta { font-size: 13px; color: var(--dim); margin: -6px 0 18px; }
.admin-edit-actions {
  display: flex; justify-content: space-between; gap: 10px; margin-top: 22px;
}

/* The edit sheet is paper, not stage — dark ink on white, the way the rest
   of the sheets read. */
.fieldlabel {
  display: block; font-size: 11.5px; letter-spacing: .07em; text-transform: uppercase;
  color: #8a7c62; margin-bottom: 15px;
}
.fieldlabel input, .fieldlabel select {
  display: block; width: 100%; margin-top: 6px;
  font-family: var(--sans); font-size: 14.5px; text-transform: none; letter-spacing: 0;
  padding: 10px 11px; color: var(--ink); background: #fff;
  border: 1px solid rgba(0,0,0,.18); border-radius: 3px;
}
.fieldlabel select { cursor: pointer; }
.fieldlabel input:focus, .fieldlabel select:focus {
  outline: none; border-color: var(--ink); box-shadow: 0 0 0 2px rgba(0,0,0,.06);
}
.fieldlabel input::placeholder { color: #a99c85; }

/* Buttons inside a sheet sit on paper, so the stage's cream text vanishes. */
.sheet-body .btn { color: var(--ink); border-color: rgba(0,0,0,.22); }
.sheet-body .btn:hover { background: rgba(0,0,0,.05); border-color: rgba(0,0,0,.4); }
.sheet-body .btn--primary { color: var(--brass-ink); border-color: var(--brass); }
.sheet-body .btn--danger { color: var(--alarm); border-color: rgba(212,85,63,.5); }
.sheet-body .btn--danger:hover { background: rgba(212,85,63,.1); border-color: var(--alarm); }
.sheet-body .btn:disabled { opacity: .4; cursor: not-allowed; }
.sheet-body .btn:disabled:hover { background: transparent; border-color: rgba(0,0,0,.22); }

.sheet-body .checkline { color: var(--ink); }

@media (max-width: 620px) {
  .admin-controls input[type="search"] { flex-basis: 100%; }
  .admin-edit-actions { flex-direction: column; }
}

/* ───────────────────────────────────────────────────────────── orrery ── */

/* Nudged left of true-center so the sun, the legend, and the caption below
   all sit between the rail and Craig's corner bubble, not between the rail
   and the far page edge. One offset on the shared container so all three
   compute their own centering against the same narrowed box. */
.view--sky { padding-right: 260px; }

.orrery-wrap { position: relative; }

/* Sized so the ring labels, the legend, and the key all sit on one screen
   without scrolling on a laptop. */
#orrery {
  width: 100%; max-width: 720px; height: auto; display: block; margin: 0 auto;
  max-height: calc(100vh - 265px);
}

.ring-path { fill: none; stroke: rgba(239,230,212,.13); stroke-width: 1; }
.ring-path--near { stroke: rgba(239,230,212,.22); }

.ring-label {
  font-family: var(--sans); font-size: 10.5px; letter-spacing: .16em;
  text-transform: uppercase; fill: rgba(239,230,212,.4);
  /* a halo of background colour, so a planet drifting past the label
     never makes it unreadable */
  paint-order: stroke; stroke: #0b111b; stroke-width: 3.5px;
  stroke-linejoin: round;
}

.sun-label {
  font-family: var(--serif); font-size: 15px; fill: var(--paper);
  text-anchor: middle; font-weight: 600;
}
.sun-sub {
  font-family: var(--sans); font-size: 9.5px; letter-spacing: .17em;
  text-transform: uppercase; fill: rgba(239,230,212,.45); text-anchor: middle;
}

.body { cursor: pointer; }
.body circle { transition: r .18s ease, opacity .18s; }
.body:hover .body-core { opacity: 1; }
.body:hover .body-halo { opacity: .5; }
.body.is-done { opacity: .28; }

.body-halo { opacity: 0; transition: opacity .18s; }

.body-label {
  font-family: var(--sans); font-size: 10px; fill: rgba(239,230,212,.62);
  pointer-events: none;
}

.overdue-zone { fill: rgba(212,85,63,.055); stroke: rgba(212,85,63,.28); stroke-dasharray: 2 5; }

.tooltip {
  position: absolute; z-index: 8; pointer-events: none;
  background: var(--paper); color: var(--ink);
  padding: 9px 12px; border-radius: 2px; max-width: 250px;
  box-shadow: 0 12px 26px -12px rgba(0,0,0,.85);
  transform: translate(-50%, -100%) rotate(-.5deg);
  font-size: 13px; line-height: 1.4;
}
.tooltip strong { display: block; font-family: var(--serif); font-size: 14px; }
.tooltip .tt-course {
  font-size: 10.5px; letter-spacing: .09em; text-transform: uppercase;
  font-weight: 700; color: #6d6350;
}
.tooltip .tt-when { color: #7d7462; font-size: 12px; margin-top: 3px; }
.tooltip .tt-warn { color: #9c3a26; font-size: 11.5px; margin-top: 4px; font-style: italic; }

.legend {
  display: flex; flex-wrap: wrap; gap: 7px 16px; justify-content: center;
  margin: 10px auto 0; max-width: 760px;
}
.legend-item {
  display: inline-flex; align-items: center; gap: 7px;
  font-family: var(--sans); background: none; border: 0;
  font-size: 12.5px; color: var(--dim); cursor: pointer;
  padding: 3px 2px; border-bottom: 1px solid transparent;
}
.legend-item:focus-visible { outline: 1px solid var(--brass); outline-offset: 3px; }
.legend-item:hover { color: var(--paper); border-bottom-color: var(--edge); }
.legend-planet {
  width: 11px; height: 11px; border-radius: 50%;
  box-shadow: inset -2px -2px 3px rgba(0,0,0,.45);
}
.legend-count { color: var(--dimmer); font-size: 11.5px; }

.orrery-key {
  max-width: 620px; margin: 14px auto 0; text-align: center;
  font-size: 12.5px; color: var(--dimmer); line-height: 1.6;
}
.key-mark {
  display: inline-block; width: 9px; height: 9px; border-radius: 50%;
  background: var(--dim); vertical-align: middle; margin: 0 1px;
}

.empty-sky { text-align: center; padding: 70px 20px; color: var(--dim); }
.empty-planet { width: 130px; height: 130px; color: var(--dim); opacity: .8; }
.empty-sky h3 {
  font-family: var(--serif); font-size: 22px; font-weight: 600;
  color: var(--paper); margin: 14px 0 6px;
}
.empty-sky p { margin: 0 0 20px; font-size: 14.5px; }

/* ──────────────────────────────────────────────────────────── courses ── */

.course-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(268px, 1fr));
  gap: 18px;
}

.course-card {
  position: relative; overflow: hidden;
  background: rgba(239,230,212,.035);
  border: 1px solid var(--edge); border-radius: 3px;
  padding: 18px 18px 16px; cursor: pointer;
  transition: border-color .15s, transform .15s, background .15s;
}
.course-card:hover {
  border-color: rgba(239,230,212,.3); transform: translateY(-2px);
  background: rgba(239,230,212,.055);
}

.course-planet {
  position: absolute; top: -34px; right: -34px;
  width: 104px; height: 104px; border-radius: 50%;
  opacity: .18; filter: blur(.4px);
  box-shadow: inset -14px -14px 30px rgba(0,0,0,.6);
}

.course-code {
  font-family: var(--sans); font-weight: 700; font-size: 12px;
  letter-spacing: .12em; text-transform: uppercase;
}
.course-title {
  font-family: var(--serif); font-size: 19px; font-weight: 600;
  color: var(--paper); margin: 3px 0 8px; line-height: 1.25;
}
.course-meta { font-size: 13px; color: var(--dim); line-height: 1.55; }
.course-meta div { margin-bottom: 2px; }

.course-progress {
  margin-top: 13px; height: 3px; border-radius: 2px;
  background: rgba(239,230,212,.1); overflow: hidden;
}
.course-progress span { display: block; height: 100%; }
.course-foot {
  margin-top: 7px; font-size: 11.5px; color: var(--dimmer);
  display: flex; justify-content: space-between;
}

/* ─────────────────────────────────────────────────── everything list ── */

.list-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 16px; flex-wrap: wrap; margin-bottom: 16px;
}
.list-head h2 {
  font-family: var(--serif); font-size: 24px; font-weight: 600;
  margin: 0; color: var(--paper);
}
.checkline {
  font-size: 13px; color: var(--dim); display: inline-flex;
  align-items: center; gap: 7px; cursor: pointer;
}
.checkline--rail { margin: 2px 2px 0; }

.week-group { margin-bottom: 26px; }
.week-head {
  font-family: var(--sans); font-size: 11px; letter-spacing: .16em;
  text-transform: uppercase; color: var(--dimmer);
  padding-bottom: 6px; border-bottom: 1px solid var(--edge); margin-bottom: 6px;
}

.row {
  display: grid; grid-template-columns: 22px 92px 1fr auto;
  gap: 12px; align-items: center;
  padding: 9px 6px; border-bottom: 1px solid rgba(239,230,212,.06);
}
.row:hover { background: rgba(239,230,212,.03); }
.row .tick { border-color: var(--dimmer); }
.row .tick:hover { border-color: var(--paper); }
.row-date { font-size: 12.5px; color: var(--dim); white-space: nowrap; }
.row-title { font-size: 14.5px; color: var(--cream); }
.row-course {
  font-size: 11px; letter-spacing: .09em; text-transform: uppercase;
  font-weight: 700; display: inline-flex; align-items: center; gap: 6px;
}
.row-kind {
  font-size: 10.5px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--dimmer); border: 1px solid var(--edge);
  padding: 2px 7px; border-radius: 999px; white-space: nowrap;
}
.row.is-done .row-title { text-decoration: line-through; opacity: .42; }
.row.is-late .row-date { color: var(--alarm); }

.flag-low {
  display: inline-block; margin-left: 6px; font-size: 11px;
  color: var(--brass); cursor: help; border-bottom: 1px dotted var(--brass);
}

/* ────────────────────────────────────────────────── sheets & drawers ── */

.sheet, .drawer { position: fixed; inset: 0; z-index: 20; }
.sheet-scrim, .drawer-scrim {
  position: absolute; inset: 0;
  background: rgba(4,7,12,.72); backdrop-filter: blur(2px);
}

.sheet-body {
  position: relative; z-index: 1;
  width: min(560px, calc(100vw - 36px));
  max-height: calc(100vh - 90px); overflow-y: auto;
  margin: 60px auto 0;
  background: var(--paper); color: var(--ink);
  border-radius: 3px; padding: 30px 32px 32px;
  box-shadow: 0 40px 80px -30px rgba(0,0,0,.95);
  transform: rotate(-.3deg);
  animation: rise .22s ease-out;
}
.sheet-body--wide { width: min(680px, calc(100vw - 36px)); }

@keyframes rise { from { opacity: 0; transform: translateY(14px) rotate(-.3deg); } }

.sheet-x {
  position: absolute; top: 12px; right: 14px;
  background: none; border: 0; cursor: pointer;
  font-size: 27px; line-height: 1; color: #9a8e74;
}
.sheet-x:hover { color: var(--ink); }

.sheet-title {
  font-family: var(--serif); font-size: 25px; font-weight: 600;
  margin: 0 0 4px; letter-spacing: -.01em;
}
.sheet-sub { margin: 0 0 20px; color: #7d7462; font-size: 14px; }

.dropzone {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 3px; padding: 34px 20px; cursor: pointer;
  border: 1.5px dashed #b8ab90; border-radius: 3px; color: #6d6350;
  background: rgba(0,0,0,.015); transition: border-color .15s, background .15s;
}
.dropzone:hover, .dropzone.is-over { border-color: var(--rust); background: rgba(201,111,74,.06); }
.aperture { width: 66px; height: 66px; color: #8a7c62; margin-bottom: 4px; }
.dz-main { font-family: var(--serif); font-size: 17px; font-weight: 600; color: var(--ink); }
.dz-sub { font-size: 12.5px; color: #8a7c62; }

.upload-status {
  margin-top: 18px; font-size: 14px; color: #4a4132;
  display: flex; align-items: center; gap: 10px;
}
.upload-status[hidden] { display: none; }
.spinner {
  width: 15px; height: 15px; border-radius: 50%; flex: 0 0 auto;
  border: 2px solid #c6b99e; border-top-color: var(--rust);
  animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.upload-result { margin-top: 18px; font-size: 14px; }
.result-head {
  font-family: var(--serif); font-size: 18px; font-weight: 600; margin-bottom: 4px;
}
.result-sub { color: #7d7462; font-size: 13px; margin-bottom: 12px; }
.result-list {
  max-height: 260px; overflow-y: auto;
  border-top: 1px solid rgba(0,0,0,.09);
}
.result-list .ritem {
  display: flex; justify-content: space-between; gap: 12px;
  padding: 6px 0; border-bottom: 1px solid rgba(0,0,0,.055); font-size: 13.5px;
}
.result-list .ritem > span:first-child,
.cd-assign .ritem > span:first-child { flex: 1; min-width: 0; }
.ritem-date { color: #7d7462; white-space: nowrap; font-size: 12.5px; }
.warn-box {
  background: rgba(143,212,232,.16); border-left: 3px solid var(--brass);
  padding: 10px 12px; font-size: 13px; margin-bottom: 14px; color: #4a4132;
}
.err-box {
  background: rgba(212,85,63,.13); border-left: 3px solid var(--alarm);
  padding: 10px 12px; font-size: 13.5px; color: #7a2b1b;
}

/* course detail */
.cd-head { display: flex; align-items: flex-start; gap: 14px; margin-bottom: 4px; }
.cd-planet {
  width: 44px; height: 44px; border-radius: 50%; flex: 0 0 auto; margin-top: 4px;
  box-shadow: inset -8px -8px 14px rgba(0,0,0,.55);
}
.cd-code {
  font-size: 12px; letter-spacing: .12em; text-transform: uppercase; font-weight: 700;
}
.cd-title { font-family: var(--serif); font-size: 24px; font-weight: 600; margin: 1px 0 0; }

.cd-edit {
  flex: 0 0 auto; background: none; border: 0; cursor: pointer;
  color: #8a7c62; font-size: 12.5px; text-decoration: underline;
  padding: 4px 0;
}
.cd-edit:hover { color: var(--ink); }

.cd-input {
  display: block; width: 100%; font-family: inherit; color: var(--ink);
  background: rgba(255,255,255,.55); border: 1px solid rgba(0,0,0,.18);
  border-radius: 2px; padding: 5px 8px;
}
.cd-input--code {
  font-family: var(--sans); font-weight: 700; font-size: 12px;
  letter-spacing: .1em; text-transform: uppercase; margin-bottom: 6px;
}
.cd-input--title { font-family: var(--serif); font-weight: 600; font-size: 21px; }

.cd-name-actions { display: flex; gap: 8px; margin: 10px 0 4px; }

.cd-facts {
  display: grid; grid-template-columns: 108px 1fr; gap: 4px 14px;
  font-size: 13.5px; margin: 16px 0 18px;
  padding: 14px 0; border-top: 1px solid rgba(0,0,0,.09);
  border-bottom: 1px solid rgba(0,0,0,.09);
}
.cd-facts dt { color: #8a7c62; font-size: 12px; letter-spacing: .04em; }
.cd-facts dd { margin: 0; }
.cd-section-title {
  font-family: var(--serif); font-size: 16px; font-weight: 600; margin: 0 0 8px;
}
.cd-grade { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 18px; }
.cd-grade span {
  font-size: 12.5px; background: rgba(0,0,0,.05);
  border: 1px solid rgba(0,0,0,.09); padding: 3px 9px; border-radius: 999px;
}
.cd-policy {
  font-size: 13px; color: #4a4132; background: rgba(0,0,0,.03);
  padding: 11px 13px; border-left: 2px solid #c6b99e; margin-bottom: 18px;
  max-height: 150px; overflow-y: auto; white-space: pre-wrap;
}
.cd-assign { border-top: 1px solid rgba(0,0,0,.09); }
.cd-assign .ritem { align-items: center; }
.cd-actions { margin-top: 20px; display: flex; gap: 8px; }
.btn-dark {
  font-family: var(--sans); font-size: 13px; padding: 8px 14px; cursor: pointer;
  border: 1px solid rgba(0,0,0,.2); background: transparent; color: var(--ink);
  border-radius: 2px;
}
.btn-dark:hover { background: rgba(0,0,0,.05); }
.btn-danger { color: #9c3a26; border-color: rgba(156,58,38,.35); }
.btn-danger:hover { background: rgba(156,58,38,.08); }

/* ───────────────────────────────────────────────────────── chat drawer ── */

.drawer-body {
  position: absolute; top: 0; right: 0; bottom: 0;
  width: min(460px, 100vw);
  background: linear-gradient(180deg, #101828 0%, #0a0f18 100%);
  border-left: 1px solid var(--edge);
  display: flex; flex-direction: column;
  animation: slidein .24s ease-out;
}
@keyframes slidein { from { transform: translateX(30px); opacity: 0; } }

.drawer-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 12px; padding: 22px 22px 16px; border-bottom: 1px solid var(--edge);
}
.drawer-head h2 {
  font-family: var(--serif); font-size: 20px; font-weight: 600;
  margin: 0; color: var(--paper);
}
.drawer-sub { margin: 3px 0 0; font-size: 12.5px; color: var(--dimmer); }
.drawer-head .sheet-x { position: static; color: var(--dimmer); }
.drawer-head .sheet-x:hover { color: var(--paper); }

.chat-log { flex: 1; overflow-y: auto; padding: 18px 22px; }

.bubble { margin-bottom: 16px; max-width: 94%; }
.bubble.me { margin-left: auto; }
.bubble .who {
  font-size: 10.5px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--dimmer); margin-bottom: 4px;
}
.bubble.me .who { text-align: right; }
.bubble .said {
  font-size: 14.5px; line-height: 1.6; color: var(--cream); white-space: pre-wrap;
}
.bubble.me .said {
  background: rgba(239,230,212,.07); border: 1px solid var(--edge);
  padding: 9px 13px; border-radius: 3px;
}
.bubble.bot .said { border-left: 2px solid var(--brass); padding-left: 13px; }

.thinking { display: flex; gap: 4px; padding-left: 13px; }
.thinking i {
  width: 5px; height: 5px; border-radius: 50%; background: var(--brass);
  animation: pulse 1.1s infinite;
}
.thinking i:nth-child(2) { animation-delay: .15s; }
.thinking i:nth-child(3) { animation-delay: .3s; }
@keyframes pulse { 0%,100% { opacity: .25; } 50% { opacity: 1; } }

.chat-suggest {
  display: flex; flex-wrap: wrap; gap: 6px; padding: 0 22px 12px;
}
.chat-suggest[hidden] { display: none; }
.chat-suggest button {
  font-family: var(--sans); font-size: 12.5px; cursor: pointer;
  background: transparent; color: var(--dim);
  border: 1px solid var(--edge); border-radius: 999px; padding: 5px 12px;
}
.chat-suggest button:hover { color: var(--paper); border-color: rgba(239,230,212,.32); }

.chat-form {
  display: flex; gap: 8px; padding: 14px 22px 20px;
  border-top: 1px solid var(--edge);
}
.chat-form input {
  flex: 1; font-family: var(--sans); font-size: 14.5px;
  background: rgba(239,230,212,.05); color: var(--cream);
  border: 1px solid var(--edge); border-radius: 2px; padding: 10px 13px;
}
.chat-form input:focus { outline: none; border-color: rgba(143,212,232,.5); }
.chat-form input::placeholder { color: var(--dimmer); }
.chat-form button {
  background: var(--brass); border: 0; border-radius: 2px; cursor: pointer;
  color: var(--brass-ink); padding: 0 15px; display: grid; place-items: center;
}
.chat-form button:hover { background: #a9e2f0; }

/* ───────────────────────────────────────────────────────────── toast ── */

.toast {
  position: fixed; bottom: 26px; left: 50%; transform: translateX(-50%);
  z-index: 40; background: var(--paper); color: var(--ink);
  padding: 11px 20px; border-radius: 2px; font-size: 14px;
  box-shadow: 0 16px 34px -16px rgba(0,0,0,.9);
  animation: rise .2s ease-out;
}
.toast.bad { background: #f0d5cc; color: #7a2b1b; }

/* ────────────────────────────────────────────────────────── narrower ── */

@media (max-width: 1000px) {
  .stage { grid-template-columns: 1fr; padding: 20px 20px 50px; }
  .rail { order: 2; }
  .view { order: 1; }
  .masthead { padding: 20px 20px 14px; }
  .craig-bubble { right: 20px; }
  .view--sky { padding-right: 0; }
}

@media (max-width: 620px) {
  .nav { width: 100%; overflow-x: auto; }
  .navbtn { padding: 7px 10px; font-size: 13px; }
  .navbtn.ghost { margin-left: 4px; }
  .row { grid-template-columns: 22px 1fr; gap: 8px; }
  .row-date { grid-column: 2; font-size: 12px; }
  .row-kind { display: none; }
  .sheet-body { margin-top: 24px; padding: 24px 20px 26px; }
  .orrery-key { font-size: 12px; }
  .craig-bubble { width: calc(100vw - 40px); right: 20px; }
  .craig-tail { right: 24px; }
}

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