/* =============================================================================
   style.css : look and feel of the CS354 SQL Lab, "night campus" edition.

   THE IDEA
   The whole site is Calvin's campus at night. Each skill is a window that
   lights up when mastered (see campus.js). So the site is dark, the
   colour of the night sky, and lamp-light gold is the one bright colour:
   it marks what is lit, done, or the next thing to press. Calvin maroon is
   the brick of the buildings and the Knight Files case cards.

   Colours are defined once as variables below; change them here only.
   Type: Bricolage Grotesque (headings and text), IBM Plex Mono (SQL).
   Motion: see "Motion" near the end; all of it switches off for people who
   ask their computer for reduced motion.
   ============================================================================= */

:root {
  --night: #12142E;         /* page background: the sky */
  --dusk: #1C2048;          /* cards */
  --dusk-2: #242a5c;        /* raised cards, hover */
  --line: #2F3468;          /* borders */
  --text: #F4EFE6;          /* chalk white */
  --muted: #A3A7CC;         /* moonlit grey-blue */
  --lamp: #F2C14E;          /* lit windows, primary buttons */
  --lamp-soft: #3a3320;
  --gold: #C49A2C;          /* Calvin gold */
  --maroon: #8C2A3E;        /* Calvin maroon, a little lighter so it reads on the night */
  --brick: #6A2A2A;
  --ok: #7FDBA6;
  --ok-soft: #173b2c;
  --bad: #FF9B8F;
  --bad-soft: #3e1f25;
  --code-bg: #161938;
  --radius: 16px;
  --sans: "Bricolage Grotesque", system-ui, -apple-system, "Segoe UI", sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, Menlo, Consolas, monospace;
}

* { box-sizing: border-box; }
html, body { margin: 0; }
body { font-family: var(--sans); background: var(--night); color: var(--text); line-height: 1.5; }
a { color: var(--lamp); }
code, pre { font-family: var(--mono); font-size: 0.9em; }
:not(pre) > code { background: var(--code-bg); color: #FFE3A3; padding: 0.1em 0.35em; border-radius: 6px; }
pre { background: var(--code-bg); padding: 0.8rem 1rem; border-radius: 10px; overflow-x: auto; border: 1px solid var(--line); }
.muted { color: var(--muted); }
.small { font-size: 0.86rem; }
.error { color: var(--bad); }
[hidden] { display: none !important; }
:focus-visible { outline: 3px solid var(--lamp); outline-offset: 2px; }

/* ---------- buttons and inputs ---------- */
.btn {
  font: inherit; font-weight: 650; border: 1px solid var(--line); background: var(--dusk-2);
  color: var(--text); padding: 0.5rem 1.05rem; border-radius: 999px; cursor: pointer;
  text-decoration: none; display: inline-flex; align-items: center; gap: .4rem;
}
.btn:hover { border-color: var(--lamp); }
.btn.primary { background: var(--lamp); border-color: var(--lamp); color: #22190A; }
.btn.primary:hover { background: #FFD46B; }
.btn.gold { background: var(--gold); border-color: var(--gold); color: #1d1d1f; }
.btn.wide { width: 100%; justify-content: center; }
.btn.small { padding: 0.28rem 0.75rem; font-size: 0.85rem; }
.btn:disabled { opacity: 0.5; cursor: default; }
input, textarea, select {
  font: inherit; padding: 0.55rem 0.75rem; border: 1px solid var(--line); border-radius: 10px;
  background: var(--code-bg); color: var(--text);
}
select { padding: 0.35rem 0.6rem; }
textarea { font-family: var(--mono); font-size: 0.9rem; width: 100%; }

/* ---------- sign-in page: the campus behind a frosted card ---------- */
.login-body { min-height: 100vh; display: grid; place-items: center; padding: 16px; position: relative; overflow: hidden; }
.login-sky { position: fixed; inset: 0; z-index: 0; display: flex; align-items: flex-end; }
.login-sky svg { width: 100%; height: auto; min-height: 100%; }
.login-card {
  position: relative; z-index: 1; background: rgba(28, 32, 72, .84); backdrop-filter: blur(6px);
  border: 1px solid var(--line); border-radius: 22px; padding: 2rem; width: 100%; max-width: 390px;
}
.login-card h1 { margin: 0.4rem 0 0.2rem; font-size: 2rem; line-height: 1; letter-spacing: -.02em; }
.login-card form { display: grid; gap: 0.9rem; margin: 1.4rem 0 1rem; }
.login-card label { display: grid; gap: 0.3rem; font-weight: 600; font-size: 0.9rem; }
.wordmark { font-weight: 800; font-size: 1.05rem; letter-spacing: -.01em; }
.wordmark em { font-style: normal; color: var(--lamp); }

/* ---------- app shell ---------- */
.topbar {
  position: sticky; top: 0; z-index: 10; background: rgba(18, 20, 46, .92); backdrop-filter: blur(6px);
  border-bottom: 1px solid var(--line); display: flex; align-items: center; gap: 1.2rem;
  padding: 0.65rem 16px; flex-wrap: wrap;
}
.topbar .brand { text-decoration: none; color: var(--text); }
.topbar nav { display: flex; gap: 0.15rem; flex-wrap: wrap; }
.topbar nav a {
  text-decoration: none; color: var(--muted); font-weight: 600; padding: 0.3rem 0.65rem;
  border-bottom: 2px solid transparent;
}
.topbar nav a:hover { color: var(--text); }
.topbar nav a.active { color: var(--text); border-bottom-color: var(--lamp); }
.topbar nav a.staff { color: #C9B3FF; }
.topbar .stats { margin-left: auto; display: flex; gap: 0.7rem; align-items: center; flex-wrap: wrap; }
.pill {
  display: inline-flex; align-items: center; gap: 0.35rem; font-weight: 700; font-size: 0.85rem;
  padding: 0.22rem 0.7rem; border-radius: 999px; background: var(--dusk); border: 1px solid var(--line);
}
main.app { max-width: 1180px; margin: 0 auto; padding: 1.4rem 16px 4rem; }
main.app.wide { max-width: none; padding: 0 0 4rem; }
h1.page { margin: 0.2rem 0 1rem; font-size: clamp(1.8rem, 3.4vw, 2.6rem); line-height: 1.05; letter-spacing: -.02em; }
h2 { font-size: 1.3rem; margin: 1.8rem 0 0.7rem; letter-spacing: -.01em; }

.card { background: var(--dusk); border: 1px solid var(--line); border-radius: var(--radius); padding: 1.05rem 1.2rem; }
.grid { display: grid; gap: 0.9rem; }
.grid.cols-3 { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.grid.cols-2 { grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); max-width: 900px; }

/* banners: maroon brick for "do this now", green once done */
.banner { background: var(--maroon); border-color: #A84159; }
.banner .muted { color: #F1CFD7; }
.banner.done { background: var(--ok-soft); border-color: #2c6b4e; }
.daily { border-color: #5a4a20; }
.row-link {
  display: flex; align-items: center; gap: 0.6rem; padding: 0.5rem 0.1rem; text-decoration: none;
  color: var(--text); border-top: 1px solid var(--line);
}
.row-link:first-of-type { border-top: 0; }
.row-link:hover { color: var(--lamp); }
.status-dot { width: 1.2rem; text-align: center; flex: none; }
.tag { font-size: 0.72rem; font-weight: 700; padding: 0.1rem 0.5rem; border-radius: 999px; white-space: nowrap; }
.tag.core { color: var(--lamp); border: 1px solid var(--gold); }
.tag.mastered { background: var(--lamp); color: #22190A; }
.bar { height: 6px; background: var(--line); border-radius: 99px; margin-top: 0.5rem; overflow: hidden; }
.bar > span { display: block; height: 100%; background: #E8A93A; }

/* ---------- the campus (home page) ---------- */
.campus { position: relative; }
.campus svg { display: block; width: 100%; height: auto; }
.campus .greet { position: absolute; left: clamp(16px, 3vw, 40px); top: clamp(12px, 2.5vw, 30px); max-width: 560px; }
.campus .greet h1 { font-size: clamp(1.9rem, 4.6vw, 3.6rem); line-height: .98; margin: 0; letter-spacing: -.025em; }
.campus .greet p { color: #CDD0EA; font-size: clamp(.92rem, 1.4vw, 1.06rem); margin: .7rem 0 0; max-width: 31em; }
@media (max-width: 700px) {
  /* On a phone the greeting moves below the picture, so the empty top of the
     sky (about a fifth of the picture's width) is cropped away. */
  .campus { overflow: hidden; }
  .campus svg { margin-top: -20%; }
  .campus .greet { position: static; padding: 16px 16px 0; }
}
.campus .bname, .login-sky .bname { font: 700 13.5px var(--sans); fill: var(--text); }
.campus .wlabel, .login-sky .wlabel { font: 700 11px var(--sans); }
.campus a.window { cursor: pointer; }
.campus a.window:hover .pane, .campus a.window:focus .pane { stroke: var(--lamp); stroke-width: 3; }
.home-wrap { max-width: 1180px; margin: 0 auto; padding: 0 16px; }
.streakbar { display: flex; align-items: center; gap: .7rem; flex-wrap: wrap; margin: .2rem 0 1.2rem; color: var(--muted); }
.streakbar b { color: var(--lamp); font-size: 1.15rem; }
.days { display: flex; gap: 6px; }
.days i { width: 14px; height: 14px; border-radius: 50%; background: #2C3163; display: block; font-style: normal; }
.days i.on { background: var(--lamp); box-shadow: 0 0 10px #F2C14E88; }
.days i.today { outline: 2px solid var(--lamp); outline-offset: 1px; }
.days i.none { background: transparent; border: 1px dashed #3a3f78; }
.windowlist { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: .7rem; }
.wcard { display: flex; gap: .7rem; align-items: center; padding: .7rem .8rem; border-radius: 14px; text-decoration: none;
  color: var(--text); background: var(--dusk); border: 1px solid var(--line); }
.wcard:hover { border-color: var(--lamp); }
.wcard .pane { width: 30px; height: 40px; border-radius: 3px; flex: none; position: relative; overflow: hidden;
  background: #1C2046; border: 2px solid #3E4378; }
.wcard .pane i { position: absolute; left: 0; right: 0; bottom: 0; background: #E8A93A; opacity: .85; }
.wcard.lit .pane { background: linear-gradient(#FFEDB3, #F2B83B); border-color: var(--gold); box-shadow: 0 0 14px #F2C14E66; }
.wcard b { display: block; font-size: .92rem; line-height: 1.2; }
.wcard span { font-size: .78rem; color: var(--muted); }
.toast { position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%); z-index: 50; background: var(--lamp);
  color: #22190A; font-weight: 700; padding: .7rem 1.2rem; border-radius: 999px; box-shadow: 0 8px 30px #0008; }

/* ---------- course pages ---------- */
.course-head { display: grid; grid-template-columns: 1.4fr 1fr; gap: 1rem; }
@media (max-width: 860px) { .course-head { grid-template-columns: 1fr; } }
.facts { display: grid; grid-template-columns: auto 1fr; gap: .35rem 1rem; margin: 0; }
.facts dt { color: var(--muted); } .facts dd { margin: 0; font-weight: 600; }
.timeline { display: grid; gap: .6rem; }
.session { display: grid; grid-template-columns: 92px 1fr; gap: 1rem; padding: .9rem 1.1rem; border-radius: var(--radius);
  background: var(--dusk); border: 1px solid var(--line); }
.session.today { border-color: var(--lamp); box-shadow: 0 0 0 1px var(--lamp) inset; }
.session.past { opacity: .62; }
.session.check { background: #1e2252; }
.session.selfpaced { background: transparent; border-style: dashed; }
.session .when b { display: block; font-size: 1.25rem; line-height: 1.1; }
.session .when span { color: var(--muted); font-size: .85rem; }
.session h3 { margin: 0 0 .25rem; font-size: 1.08rem; }
.session .meta { display: flex; flex-wrap: wrap; gap: .4rem .9rem; font-size: .88rem; color: var(--muted); margin-top: .35rem; }
.chip { display: inline-block; font-size: .78rem; font-weight: 700; padding: .08rem .55rem; border-radius: 999px;
  border: 1px solid #4a4f8a; color: #DADCF2; text-decoration: none; }
.chip.lamp { border-color: var(--gold); color: var(--lamp); }
@media (max-width: 560px) { .session { grid-template-columns: 1fr; gap: .3rem; } }

/* ---------- questions editor (staff) ---------- */
.qfilters { display: flex; gap: .5rem; flex-wrap: wrap; align-items: center; margin-bottom: .8rem; }
.qrow { display: grid; grid-template-columns: 110px 70px 60px 1fr auto; gap: .8rem; align-items: center;
  padding: .55rem .2rem; border-top: 1px solid var(--line); text-decoration: none; color: var(--text); }
.qrow:hover { color: var(--lamp); }
.qrow.retired { opacity: .45; }
.qrow code { font-size: .8rem; }
@media (max-width: 700px) { .qrow { grid-template-columns: 1fr; gap: .1rem; } }
.form { display: grid; gap: .9rem; }
.form label { display: grid; gap: .3rem; font-weight: 650; font-size: .92rem; }
.form .row { display: flex; gap: .8rem; flex-wrap: wrap; }
.form .row > label { flex: 1 1 140px; }
.form .hint { font-weight: 400; color: var(--muted); font-size: .82rem; }
.varyrow { display: grid; grid-template-columns: 160px 1fr auto; gap: .5rem; margin-bottom: .4rem; }
.checks li { margin: .2rem 0; }

/* ---------- practice workspace ---------- */
.workspace { display: grid; grid-template-columns: minmax(0, 1fr) 270px; gap: 1rem; align-items: start; }
@media (max-width: 860px) { .workspace { grid-template-columns: 1fr; } }
.prompt { font-size: 1.04rem; }
.prompt p:first-child { margin-top: 0; }
.editor-wrap { border: 1px solid var(--line); border-radius: 12px; overflow: hidden; margin: 0.8rem 0; }
.toolbar { display: flex; gap: 0.5rem; flex-wrap: wrap; align-items: center; }
.kbd { font-family: var(--mono); font-size: 0.75rem; color: var(--muted); }
.feedback { margin: 0.9rem 0; padding: 0.7rem 0.95rem; border-radius: 12px; font-weight: 600; }
.feedback.ok { background: var(--ok-soft); color: var(--ok); }
.feedback.bad { background: var(--bad-soft); color: var(--bad); }
.feedback.info { background: var(--code-bg); color: var(--text); font-weight: 500; }
.choices { display: grid; gap: 0.5rem; margin: 0.9rem 0; }
.choice { display: flex; gap: 0.6rem; align-items: center; padding: 0.6rem 0.85rem; border: 1px solid var(--line);
  border-radius: 12px; cursor: pointer; background: var(--dusk); }
.choice:hover { border-color: var(--lamp); }

/* CodeMirror, night colours */
.CodeMirror { height: 190px; font-family: var(--mono); font-size: 14px; background: var(--code-bg); color: #E9E6F5; }
.CodeMirror-gutters { background: #13162f; border-right: 1px solid var(--line); }
.CodeMirror-linenumber { color: #5c6199; }
.CodeMirror-cursor { border-left: 2px solid var(--lamp); }
.CodeMirror-selected, .CodeMirror-focused .CodeMirror-selected { background: #2f3570; }
.cm-s-default .cm-keyword { color: #F2C14E; font-weight: 600; }
.cm-s-default .cm-string { color: #9BE3B4; }
.cm-s-default .cm-number { color: #F4A6B8; }
.cm-s-default .cm-comment { color: #7d82b5; font-style: italic; }
.cm-s-default .cm-builtin, .cm-s-default .cm-type { color: #9CC7FF; }
.cm-s-default .cm-operator { color: #E9E6F5; }

/* result table */
.result { overflow: auto; max-height: 420px; border: 1px solid var(--line); border-radius: 12px; }
table.data { border-collapse: collapse; width: 100%; font-size: 0.88rem; }
table.data th, table.data td { padding: 0.38rem 0.65rem; border-bottom: 1px solid var(--line); text-align: left; white-space: nowrap; }
table.data th { position: sticky; top: 0; background: #1a1e44; color: var(--lamp); font-weight: 650; }
table.data td.null { color: var(--muted); font-style: italic; }

/* schema sidebar */
.schema details { border-bottom: 1px solid var(--line); padding: 0.32rem 0; }
.schema summary { cursor: pointer; font-weight: 600; font-family: var(--mono); font-size: 0.88rem; }
.schema ul { list-style: none; padding: 0.2rem 0 0.2rem 0.9rem; margin: 0; font-size: 0.8rem; }
.schema li { display: flex; justify-content: space-between; gap: 0.5rem; font-family: var(--mono); }
.schema li span { color: var(--muted); }

/* leaderboard and other tables */
table.board { width: 100%; border-collapse: collapse; }
table.board td, table.board th { padding: 0.5rem 0.6rem; border-bottom: 1px solid var(--line); text-align: left; }
table.board th { color: var(--muted); font-weight: 600; }
table.board tr.me td { background: var(--lamp-soft); font-weight: 700; }
.medal { font-size: 1.1rem; }

/* Proctor page: the check-in code, large enough to read from the back of SB382. */
.checkin-code { font: 700 clamp(2.5rem, 9vw, 5rem)/1.1 var(--mono); letter-spacing: .25em; color: var(--lamp); margin: .3rem 0 .6rem; }

/* ---------- Motion ----------
   One orchestrated moment when the campus loads (windows switch on one by
   one, practice warmth rises), a quiet twinkle afterwards, and a celebration
   when a window or the A is earned. Nothing else moves. */
.star { animation: twinkle 5s ease-in-out infinite; }
@keyframes twinkle { 50% { opacity: .12; } }
.lit .pane { animation: switchon 1.1s ease-out both; }
.lit .halo { animation: halo 1.1s ease-out both; }
.justlit .pane { animation: switchon 2.2s ease-out both; }
.justlit .halo { animation: halo-big 2.4s ease-out both; }
@keyframes switchon { 0% { fill: #2A3070; } 30% { fill: #FFEDB3; } 42% { fill: #2A3070; } 58%, 100% { fill: url(#lit); } }
@keyframes halo { 0%, 45% { opacity: 0; } 100% { opacity: 1; } }
@keyframes halo-big { 0%, 40% { opacity: 0; transform: scale(.6); } 70% { opacity: 1; transform: scale(1.5); } 100% { opacity: 1; transform: scale(1); } }
.halo { transform-box: fill-box; transform-origin: center; }
.warmfill { animation: rise 1.6s .8s ease-out both; transform-box: fill-box; transform-origin: bottom; }
@keyframes rise { from { transform: scaleY(0); } to { transform: scaleY(1); } }
.lanternglow { animation: flicker 2.8s ease-in-out infinite; }
@keyframes flicker { 0%, 100% { opacity: 1; } 40% { opacity: .72; } 60% { opacity: .92; } }
.fw { animation: burst 2.6s ease-out infinite; transform-box: fill-box; transform-origin: center; opacity: 0; }
@keyframes burst { 0% { opacity: 0; transform: scale(.1); } 15% { opacity: 1; } 70% { opacity: .9; } 100% { opacity: 0; transform: scale(1.7); } }
.celebrate .greet h1 {
  background: linear-gradient(90deg, #FFE7A3, #F2C14E, #FFF6D8, #F2C14E); -webkit-background-clip: text;
  background-clip: text; color: transparent; background-size: 300% 100%; animation: shine 4s linear infinite;
}
@keyframes shine { to { background-position: 300% 0; } }
.toast { animation: toast 4.5s ease-out both; }
@keyframes toast { 0% { opacity: 0; transform: translate(-50%, 20px); } 10%, 85% { opacity: 1; transform: translate(-50%, 0); } 100% { opacity: 0; } }
/* The Chapel at the A: floodlights come on at the base, then the light
   climbs the spire from the bottom to the tip, then the finial glows. */
.floodlights { animation: halo 1.2s .4s ease-out both; }
.chapelglass { animation: halo .9s ease-out both; }
.spirelight { animation: climb 2.4s 1.4s ease-in-out both; }
.spirelight > g { transform-box: view-box; }
@keyframes climb { from { clip-path: inset(100% 0 0 0); } to { clip-path: inset(0 0 0 0); } }
.finial { animation: halo 1s 3.5s ease-out both; }
/* ---- Course schedule grouped by week; the current week glows ---------- */
.week { display: grid; gap: .6rem; padding: .2rem 0 .8rem; border-radius: calc(var(--radius) + 6px); }
.week-head { margin: .6rem 0 0; font-size: 1rem; display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.week.pastweek { opacity: .7; }
.week.thisweek { padding: .4rem .7rem 1rem; background: linear-gradient(180deg, rgba(242,193,78,.10), rgba(242,193,78,.02));
  box-shadow: 0 0 0 1px rgba(242,193,78,.55), 0 0 28px rgba(242,193,78,.12); }
.week.thisweek .week-head { color: var(--lamp); }
.week.thisweek .session.past { opacity: .75; }

/* ---- My grade ----------------------------------------------------------- */
.grade-hero { display: grid; grid-template-columns: auto 1fr; gap: 1.4rem; align-items: center; }
.big-letter { font-size: 3.6rem; font-weight: 800; line-height: 1; color: var(--lamp); }
.big-num { font-size: 2.4rem; font-weight: 800; line-height: 1.1; margin: .2rem 0; }
.big-num .muted { font-size: 1.1rem; }
.tag.bad { background: var(--bad-soft); color: var(--bad); border: 1px solid var(--bad); }
.grade-sessions tr.future td { color: var(--muted); }
.grade-sessions td { vertical-align: middle; }
details.card summary { cursor: pointer; }
@media (max-width: 560px) { .grade-hero { grid-template-columns: 1fr; gap: .4rem; } }

/* ---- Data page: one card per table ---------------------------------------- */
.chips { display: flex; flex-wrap: wrap; gap: .4rem; margin: .3rem 0 1rem; }
.chips .chip { font-size: .9rem; padding: .25rem .8rem; }
.tgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(290px, 1fr)); gap: .9rem; margin-top: 1rem; align-items: start; }
.tcard { scroll-margin-top: 90px; transition: box-shadow .3s; }
.tcard-head { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: .4rem;
  padding-bottom: .4rem; border-bottom: 1px solid var(--line); }
.tcard-head strong { font-family: var(--mono); color: var(--lamp); }
.tcard table.cols { width: 100%; border-collapse: collapse; }
.tcard table.cols td { padding: .16rem .3rem; vertical-align: top; }
.tcard table.cols td.key { width: 1.4rem; text-align: center; }
.tcard table.cols td { white-space: nowrap; }
.tcard table.cols td:last-child { text-align: right; }
.tcard code { background: none; padding: 0; }
.tcard .nn { color: var(--muted); margin-left: .15rem; }
.tcard.flash { animation: tflash 1.4s ease-out; }
@keyframes tflash { 0% { box-shadow: 0 0 0 2px var(--lamp), 0 0 30px rgba(242,193,78,.5); } 100% { box-shadow: 0 0 0 0 transparent; } }
ul.rels { columns: 2 260px; margin: .4rem 0 0; padding-left: 1.1rem; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
  .fw { opacity: 0 !important; }
}
.login-sky { pointer-events: none; }
