:root {
  --paper: #F5F6F1;
  --card: #FBFCF9;
  --ink: #1C2321;
  --ink-soft: #5B645F;
  --grid: #D9DED3;
  --grid-strong: #B9C2B2;
  --pencil: #2C4A7C;
  --pencil-dark: #23395F;
  --derivative: #BD5B2C;
  --integral: #1F7A6C;
  --font-sans: 'IBM Plex Sans', ui-sans-serif, system-ui, sans-serif;
  --font-mono: 'IBM Plex Mono', ui-monospace, SFMono-Regular, monospace;
  /* The bar's own face, loaded on every page in base.html. */
  --font-bar: 'Space Grotesk', 'IBM Plex Sans', ui-sans-serif, system-ui, sans-serif;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-sans);
  line-height: 1.6;
}

a { color: var(--pencil); }

/* The bar is the same on every page. It carries its own ground, ink and
   typeface rather than the page's, so the wordmark and the navigation do not
   change as you move between the homepage, the analyzer and the course. The
   values are the homepage's, which is where the bar was designed. */
.site-header {
  --bar-ground: #FFFFFF;
  --bar-rule: #DEDEDE;
  --bar-ink: #111214;
  --bar-ink-faint: #8A8E96;

  position: relative;
  /* Above the page: the homepage's graph paper stops at the bar rather than
     running up behind the navigation. */
  z-index: 2;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1.1rem clamp(1.25rem, 4vw, 3rem);
  background: var(--bar-ground);
  border-bottom: 1px solid var(--bar-rule);
  font-family: var(--font-bar);
  color: var(--bar-ink);
}

/* Two words set in two different worlds, and stepped apart so you read them
   as two things rather than one phrase. */
.wordmark {
  display: inline-flex;
  align-items: baseline;
  gap: 0.34rem;
  color: var(--bar-ink);
  text-decoration: none;
  font-size: 1.05rem;
  line-height: 1;
}

/* The same face the navigation beside it is set in, so the name and the
   links read as one bar. Only "comprehend" takes it -- "calculus" keeps the
   maths italic below. */
.wordmark-a {
  font-family: var(--font-sans);
  font-weight: 500;
  letter-spacing: -0.012em;
}

/* Set in the font TeX itself sets variables in. KaTeX ships KaTeX_Math and
   its stylesheet is loaded on every page, so the wordmark can borrow the
   face without running KaTeX over it. Colour is inherited, so it is the same
   ink as the word beside it rather than picked out in blue. */
.wordmark-b {
  font-family: 'KaTeX_Math', 'IBM Plex Serif', Georgia, 'Times New Roman', serif;
  font-style: italic;
  font-weight: 400;
  font-size: 1.24em;
}

.site-header nav a {
  color: var(--bar-ink-faint);
  text-decoration: none;
  margin-left: 1.75rem;
  padding-bottom: 0.35rem;
  border-bottom: 2px solid transparent;
}

.site-header nav a:hover,
.site-header nav a.active {
  color: var(--bar-ink);
  border-bottom-color: var(--bar-ink);
}

/* Signing in is a thing you do, not a place you go. It is set apart by a
   hairline and the bar's full ink rather than by being put in a box: the
   four links to the left are pages, and the rule says where that list ends.
   Written after the rules above so it wins the .active tie on source order. */
.site-header nav a.bar-action {
  position: relative;
  margin-left: 2.6rem;
  color: var(--bar-ink);
  font-weight: 500;
}

/* The divider. A pseudo-element rather than a border-left, so its height is
   the cap height of the row and not whatever the line box happens to be. */
.site-header nav a.bar-action::before {
  content: "";
  position: absolute;
  left: -1.3rem;
  top: 0.1em;
  height: 1em;
  border-left: 1px solid var(--bar-rule);
}

.site-header nav a.bar-action:hover { color: var(--bar-ink); }

main {
  max-width: 1100px;
  width: 100%;
  margin: 0 auto;
  padding: 2rem;
  box-sizing: border-box;
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

/* The analyzer is a working tool rather than a document, so it gets the
   whole window instead of the reading-width column the other pages use:
   no padding at all, so the graph can run to the right edge of the screen
   and the working to the left edge. */
body.analyze-page main {
  max-width: none;
  padding: 0;
}

/* The window is the frame: the working scrolls inside its own column and the
   graph stays where it is, rather than the page growing as steps are opened.
   Without this the two panes are the same height as the longest of them, the
   graph stretches to fill it, and the notes are carried to the bottom of the
   document instead of staying under the plot. */
body.analyze-page {
  height: 100vh;
  overflow: hidden;
}

.panel {
  background: var(--card);
  border: 1px solid var(--grid);
  border-radius: 6px;
  padding: 1.5rem;
}

main .panel > p {
  margin: 0 0 1rem;
  max-width: 65ch;
}

main .panel > p:last-child { margin-bottom: 0; }

/* Two panes, no gap and no cards: the working runs off the left edge of the
   screen and the graph off the right, with one hairline dividing them. */
.analyze-layout {
  display: grid;
  grid-template-columns: 3fr 4fr;   /* the graph takes 4/7 of the window */
  grid-template-rows: minmax(0, 1fr);
  flex: 1;
  min-height: 0;
}

/* --- left pane: entering a function, then the answers ------------------- */

.work-pane {
  --pane-pad: 1.5rem;
  min-width: 0;
  overflow-y: auto;
  padding: 0 2rem 4rem 0;
}

/* Text is inset by --pane-pad, but the blocks themselves start at x = 0, so
   every hairline runs all the way out to the edge of the screen. That's what
   makes the column read as attached to the window rather than floating in
   the middle of a card. */
.fn-form {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 1.25rem 0 1rem;
  border-bottom: 1px solid var(--grid-strong);
}

.fn-form:focus-within { border-bottom-color: var(--ink); }

/* The prompt is a button because it is also the way into limit mode, but it
   is dressed as the label it was: no border, no fill, nothing to click at
   until the pointer is on it. */
.fn-prompt {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.15rem 0.35rem 0.15rem var(--pane-pad);
  border: none;
  background: none;
  color: var(--ink-soft);
  font-family: inherit;
  font-size: 1.05rem;
  flex: none;
  cursor: pointer;
  border-bottom: 1px solid transparent;
}

.fn-prompt:hover,
.fn-prompt:focus-visible { color: var(--ink); }

.fn-prompt.is-limit {
  color: var(--ink);
  border-bottom-color: var(--grid-strong);
}

/* Only meaningful once there is something to open. */
.fn-caret {
  font-size: 0.6rem;
  opacity: 0;
  transition: opacity 0.12s;
}

.fn-prompt.is-limit .fn-caret,
.fn-prompt:hover .fn-caret { opacity: 0.55; }

/* --- what x is approaching ---------------------------------------------- */

/* Hangs under the prompt it belongs to, on the same hairline grid as
   everything else in this column. No card, no shadow, square corners. */
.lim-panel {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem 1.25rem;
  margin: 0;
  padding: 0.8rem 1.5rem 0.8rem var(--pane-pad);
  border-bottom: 1px solid var(--grid);
  background: var(--card);
}

/* display:flex above outranks the hidden attribute's own display:none, so
   hiding it has to be spelled out. */
.lim-panel[hidden] { display: none; }

.lim-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.lim-at {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  color: var(--ink-soft);
}

#limit-at {
  width: 5.5rem;
  padding: 0.2rem 0.4rem;
  border: 1px solid var(--grid-strong);
  border-radius: 2px;
  background: var(--paper);
  font-family: var(--font-mono);
  font-size: 0.95rem;
  color: var(--ink);
}

#limit-at:focus {
  outline: none;
  border-color: var(--ink);
}

.lim-quick button,
.lim-sides button,
.lim-exit {
  padding: 0.2rem 0.55rem;
  border: 1px solid var(--grid);
  border-radius: 2px;
  background: none;
  font-family: var(--font-sans);
  font-size: 0.82rem;
  color: var(--ink-soft);
  cursor: pointer;
}

.lim-quick button { font-family: var(--font-mono); }

.lim-quick button:hover,
.lim-sides button:hover,
.lim-exit:hover { color: var(--ink); border-color: var(--grid-strong); }

.lim-sides button.active {
  color: var(--paper);
  background: var(--ink);
  border-color: var(--ink);
}

/* Leaving is a quieter action than choosing, so it keeps no box until the
   pointer is on it. */
.lim-exit {
  margin-left: auto;
  border-color: transparent;
  text-decoration: underline;
  text-underline-offset: 3px;
}

.lim-exit:hover { border-color: transparent; }

#function-input {
  flex: 1;
  min-width: 0;
  border: none;
  background: none;
  padding: 0.1rem 0;
  font-family: var(--font-mono);
  font-size: 1.3rem;
  color: var(--ink);
}

#function-input:focus { outline: none; }

#function-input::placeholder {
  color: var(--ink-soft);
  opacity: 0.4;
}

/* A small square arrow rather than a full-width bar -- pressing Enter is the
   real way in, and this is here to say so quietly. */
.fn-go {
  flex: none;
  width: 2.15rem;
  height: 2.15rem;
  display: grid;
  place-items: center;
  border: 1px solid var(--grid-strong);
  border-radius: 2px;
  background: none;
  color: var(--ink-soft);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s, color 0.12s;
}

.fn-go:hover {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--paper);
}

.fn-hint {
  margin: 0.7rem 0 0;
  padding-left: var(--pane-pad);
  font-size: 0.85rem;
  color: var(--ink-soft);
}

.eg {
  opacity: 0.65;
  margin-right: 0.4rem;
}

/* The suggestion cycles while the box is empty, so there's always a fresh
   example of what the parser accepts without a wall of them on the page. */
.eg-chip {
  border: none;
  background: none;
  padding: 0;
  font-family: var(--font-mono);
  font-size: 0.85rem;
  color: var(--ink-soft);
  cursor: pointer;
  border-bottom: 1px dotted var(--grid-strong);
  transition: opacity 0.3s ease, color 0.12s;
}

.eg-chip:hover { color: var(--ink); }
.eg-chip.fading { opacity: 0; }

/* --- waiting for an answer ----------------------------------------------
   Only shown once the wait is long enough to be worth mentioning. The bar
   is indeterminate on purpose: the server has no idea how long SymPy will
   take, and a progress bar that guesses is a lie. */
.busy {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  margin: 1rem 0 0;
  padding-left: var(--pane-pad);
  font-size: 0.85rem;
  color: var(--ink-soft);
}

.busy[hidden] { display: none; }

.busy-bar {
  position: relative;
  flex: none;
  width: 4.5rem;
  height: 2px;
  overflow: hidden;
  background: var(--grid);
}

.busy-bar::after {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 40%;
  background: var(--pencil);
  animation: busy-slide 1.1s ease-in-out infinite;
}

@keyframes busy-slide {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(250%); }
}

.busy-seconds { font-family: var(--font-mono); font-size: 0.8rem; }

/* --- something this plan does not include -------------------------------
   Not a wall: it says what is behind it, in the same voice as the thing it
   is standing in for, and gives one way on. */
.lock {
  margin: 0;
  padding: 0.9rem 0 0.9rem 1rem;
  border-left: 3px solid var(--grid-strong);
}

.lock-title {
  margin: 0 0 0.25rem;
  font-size: 0.95rem;
  font-weight: 500;
  color: var(--ink);
}

.lock-line {
  margin: 0 0 0.7rem;
  max-width: 52ch;
  font-size: 0.9rem;
  color: var(--ink-soft);
}

.lock-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem 0.9rem;
  margin: 0;
}

.lock-go {
  display: inline-block;
  padding: 0.4rem 0.9rem;
  border: 1px solid var(--ink);
  border-radius: 2px;
  background: var(--ink);
  color: var(--paper);
  font-size: 0.85rem;
  text-decoration: none;
}

.lock-go:hover { background: transparent; color: var(--ink); }

.lock-alt {
  font-size: 0.82rem;
  color: var(--ink-soft);
  max-width: 40ch;
}

.steps-remaining {
  margin: 1rem 0 0;
  font-size: 0.82rem;
  color: var(--ink-soft);
}

/* A section on the course listing that cannot be opened yet: the lock sits
   where its lessons would have been, indented to the same place. */
.lesson-list-locked { padding: 0 0 1.25rem 3rem; }

.lesson-back { margin: 1.5rem 0 0; font-size: 0.9rem; }

/* --- signing in ---------------------------------------------------------- */

/* These pages are set in the bar's face, so the type does not change between
   the navigation and the form directly underneath it. The account page goes
   with them: it is where signing up lands, and switching back a click later
   would be the same jolt in the other direction. */
body.enter-page,
body.account-page {
  font-family: var(--font-bar);
}

.enter-wrap {
  width: 100%;
  max-width: 26rem;
  margin: 2rem auto 0;
}

.enter-title {
  margin: 0 0 0.4rem;
  font-size: 1.5rem;
  font-weight: 500;
}

.enter-standfirst {
  margin: 0 0 1.75rem;
  color: var(--ink-soft);
  font-size: 0.95rem;
}

.enter-error {
  margin: 0 0 1.25rem;
  padding: 0.6rem 0 0.6rem 0.9rem;
  border-left: 3px solid var(--derivative);
  color: var(--ink);
  font-size: 0.9rem;
}

.enter-form {
  display: flex;
  flex-direction: column;
  gap: 1.1rem;
}

.field {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}

.field-label {
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.field input {
  padding: 0.6rem 0.7rem;
  border: 1px solid var(--grid-strong);
  border-radius: 2px;
  background: var(--card);
  font-family: inherit;
  font-size: 1rem;
  color: var(--ink);
}

.field input:focus {
  outline: none;
  border-color: var(--pencil);
}

.field-note { font-size: 0.78rem; color: var(--ink-soft); }

/* A box that disagrees with the one above it. Said in words as well as in
   colour, so it does not depend on seeing the difference. */
.field-note.field-wrong { color: var(--derivative); }

.field input:invalid:not(:placeholder-shown) { border-color: var(--derivative); }

/* What a password has to be. Read as a plain list before anything is typed,
   then each line answers for itself.

   Named pw-rules, not rules: the home page's pair-of-rules section already
   owns .rules, and it carries six rem of vertical padding that landed on
   this list the moment the names collided. */
.pw-rules {
  margin: -0.35rem 0 0;
  padding: 0;
  list-style: none;
  font-size: 0.82rem;
  color: var(--ink-soft);
}

.pw-rules li {
  position: relative;
  padding: 0.15rem 0 0.15rem 1.4rem;
}

.pw-rules li::before {
  content: "\2014";                    /* not judged yet */
  position: absolute;
  left: 0;
  color: var(--grid-strong);
}

.pw-rules li.met { color: var(--ink-soft); }
.pw-rules li.met::before { content: "\2713"; color: var(--integral); }

.pw-rules li.unmet { color: var(--ink); }
.pw-rules li.unmet::before { content: "\00d7"; color: var(--derivative); }

.enter-go {
  padding: 0.7rem 1rem;
  border: 1px solid var(--ink);
  border-radius: 2px;
  background: var(--ink);
  color: var(--paper);
  font-family: inherit;
  font-size: 0.95rem;
  cursor: pointer;
}

.enter-go:hover { background: transparent; color: var(--ink); }

.enter-swap {
  margin: 1.5rem 0 0;
  font-size: 0.88rem;
  color: var(--ink-soft);
}

/* --- the account --------------------------------------------------------- */

.account-wrap { width: 100%; max-width: 42rem; margin: 1rem auto 0; }

.account-head { margin-bottom: 2.25rem; }
.account-head h1 { margin: 0 0 0.2rem; font-size: 1.5rem; font-weight: 500; }
.account-email { margin: 0; color: var(--ink-soft); font-family: var(--font-mono); font-size: 0.9rem; }

.account-label {
  margin: 0 0 0.35rem;
  font-size: 0.75rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.account-plan, .account-switch {
  padding-top: 1.25rem;
  margin-bottom: 2.25rem;
  border-top: 1px solid var(--grid);
}

.account-plan-name { margin: 0 0 1rem; font-size: 1.3rem; font-weight: 500; }

.account-features { margin: 0; padding: 0; list-style: none; font-size: 0.92rem; }

.account-features li {
  padding: 0.4rem 0 0.4rem 1.5rem;
  color: var(--ink-soft);
  border-top: 1px solid var(--grid);
  position: relative;
}

.account-features li:first-child { border-top: none; }

.account-features li::before {
  content: "\2014";                 /* not included */
  position: absolute;
  left: 0;
  color: var(--grid-strong);
}

.account-features li.on { color: var(--ink); }

.account-features li.on::before {
  content: "\2713";                 /* included */
  color: var(--integral);
}

.account-note { margin: 0 0 1rem; max-width: 52ch; font-size: 0.88rem; color: var(--ink-soft); }

.plan-row { display: flex; flex-wrap: wrap; gap: 0.6rem; }

.plan-button {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  padding: 0.6rem 1rem;
  border: 1px solid var(--grid-strong);
  border-radius: 2px;
  background: none;
  font-family: inherit;
  color: var(--ink);
  cursor: pointer;
  text-align: left;
}

.plan-button:hover:not(:disabled) { border-color: var(--ink); }

.plan-button.current {
  border-color: var(--ink);
  background: var(--ink);
  color: var(--paper);
  cursor: default;
}

.plan-name { font-size: 0.95rem; font-weight: 500; }
.plan-price { font-size: 0.78rem; opacity: 0.75; }

.account-out { margin-top: 2.5rem; }

.signout {
  padding: 0.5rem 0.9rem;
  border: 1px solid var(--grid-strong);
  border-radius: 2px;
  background: none;
  font-family: inherit;
  font-size: 0.88rem;
  color: var(--ink-soft);
  cursor: pointer;
}

.signout:hover { color: var(--ink); border-color: var(--ink); }

@media (prefers-reduced-motion: reduce) {
  .busy-bar::after { animation: none; width: 100%; opacity: 0.5; }
}

/* --- what has been asked before ----------------------------------------
   A word, and a list behind it. It sits under the box rather than beside it
   and is not there at all until something has been analyzed, so it costs the
   page nothing until it is worth something. */
.history {
  margin: 0.9rem 0 0;
  padding-left: var(--pane-pad);
}

.history[hidden] { display: none; }

.history-head {
  display: flex;
  align-items: baseline;
  gap: 1rem;
  margin: 0;
}

.history-toggle,
.history-clear {
  border: none;
  background: none;
  padding: 0;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  color: var(--ink-soft);
  cursor: pointer;
  border-bottom: 1px dotted var(--grid-strong);
}

.history-toggle:hover { color: var(--ink); }

/* Quieter than the toggle beside it: throwing the list away is not the
   thing anybody came here to do. */
.history-clear {
  margin-left: auto;
  color: var(--grid-strong);
  border-bottom-color: transparent;
}

.history-clear:hover {
  color: var(--derivative);
  border-bottom-color: currentColor;
}

.history-clear[hidden] { display: none; }

.history-list {
  margin: 0.7rem 0 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--grid);
}

.history-list[hidden] { display: none; }

.history-item {
  display: block;
  width: 100%;
  padding: 0.4rem 0;
  border: none;
  border-bottom: 1px solid var(--grid);
  background: none;
  font-family: var(--font-mono);
  font-size: 0.85rem;
  color: var(--ink);
  text-align: left;
  cursor: pointer;
}

.history-item:hover { color: var(--pencil); }

.error {
  color: var(--derivative);
  font-size: 0.9rem;
  margin: 0.9rem 0 0;
  padding-left: var(--pane-pad);
}

.read-as {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  margin: 1.1rem 0 0;
  padding-left: var(--pane-pad);
  font-size: 0.85rem;
  color: var(--ink-soft);
}

/* --- the answers: a rule above, a label, the maths. No card. ------------ */

.answer {
  margin-top: 1.6rem;
  padding: 1.1rem 0 0 var(--pane-pad);
  border-top: 1px solid var(--grid);
}

.answer-label {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  margin: 0 0 0.2rem;
  font-size: 1rem;
  font-weight: 500;
  color: var(--ink-soft);
}

.answer-caption {
  font-size: 0.78rem;
  opacity: 0.6;
}

.answer-math {
  font-size: 1.2rem;
  overflow-x: auto;
  overflow-y: hidden;
  padding: 0.3rem 0 0.1rem;
}

.answer-math .katex-display {
  margin: 0.3rem 0;
  text-align: left;
}

.swatch {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 2px;
  flex: none;
}

.swatch-f { background: var(--pencil); }
.swatch-fprime { background: var(--derivative); }
.swatch-F { background: var(--integral); }

/* --- right pane: the graph, running to the edge of the window ----------- */

.graph-pane {
  display: flex;
  flex-direction: column;
  min-width: 0;
  border-left: 1px solid var(--grid);
  background: var(--card);
  /* No padding on the right: the plot area touches the screen edge. */
  padding: 1rem 0 1.25rem 1.5rem;
}

.legend {
  display: flex;
  flex-wrap: wrap;
  gap: 1.25rem;
  font-size: 0.85rem;
  color: var(--ink-soft);
  margin-bottom: 0.5rem;
  padding-right: 1.5rem;
}

.legend span {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}

/* The legend entries double as on/off switches for the curves. They are
   buttons for keyboard/screen-reader reasons, so strip the button chrome
   and let them sit exactly where the old spans did. */
.legend-item {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  cursor: pointer;
  transition: opacity 0.15s ease;
}

.legend-item:hover { opacity: 0.75; }

/* Switched off: greyed out, with a hollow swatch so it reads as "not drawn"
   even without relying on the colour alone. */
.legend-item[aria-pressed="false"] {
  opacity: 0.45;
  text-decoration: line-through;
}

.legend-item[aria-pressed="false"] .swatch {
  background: transparent;
  box-shadow: inset 0 0 0 2px currentColor;
}

.legend-hint {
  margin-left: auto;
  opacity: 0.7;
}

/* The plot and the "nothing here yet" line share the same box, so the line
   sits where the graph will appear rather than pushing it around. It takes
   the space the notes underneath don't need, down to a floor it will not go
   below. */
.graph-area {
  position: relative;
  flex: 1 1 auto;
  min-height: min(240px, 35vh);
}

#graph {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.graph-empty {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0;
  padding: 0 1.5rem;
  text-align: center;
  color: var(--ink-soft);
  font-size: 0.95rem;
}

/* display:flex above outranks the hidden attribute's own display:none, so
   hiding it has to be spelled out. */
.graph-empty[hidden] { display: none; }

/* What is said about the curve sits directly under it, always: the plot
   above gives up space to it rather than the other way round. It is a column
   itself so that on a short window the reading shrinks and scrolls rather
   than running off the bottom of a page that cannot scroll. */
.graph-foot {
  display: flex;
  flex-direction: column;
  flex: 0 1 auto;
  min-height: 0;
  padding-right: 1.5rem;
  margin-top: 1.25rem;
  border-top: 1px solid var(--grid-strong);
}

.notes-toggle { flex: none; }

.notes-toggle {
  display: flex;
  gap: 0.5rem;
  margin: 0.9rem 0 1rem;
  border-bottom: 1px solid var(--grid);
}

.toggle-btn {
  background: none;
  border: none;
  padding: 0.5rem 0.9rem;
  font-size: 0.9rem;
  font-family: var(--font-sans);
  color: var(--ink-soft);
  cursor: pointer;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}

.toggle-btn:hover { color: var(--ink); }

.toggle-btn.active {
  color: var(--ink);
  border-bottom-color: var(--pencil);
}

/* The panel is a list of facts, not a paragraph, so it is set as rows: what
   is being reported on the left, what it says on the right. Deep enough to
   hold a handful of facts, and it scrolls rather than pushing the graph up
   when a function breaks in half a dozen places. */
.notes-text {
  margin: 0;
  flex: 1 1 auto;
  color: var(--ink);
  font-size: 0.9rem;
  min-height: 3em;
  max-height: 15rem;
  overflow-y: auto;
  padding-bottom: 0.25rem;
}

.fact {
  display: grid;
  grid-template-columns: 9.5rem 1fr;
  gap: 0 1.5rem;
  padding: 0.55rem 0;
  border-top: 1px solid var(--grid);
  line-height: 1.55;
}

.fact:first-child { border-top: none; padding-top: 0; }

/* The label is the quiet half of the row: small, upright and set apart from
   the reading, so the eye runs down the left edge and stops at the one it
   wants. */
.fact-label {
  color: var(--ink-soft);
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  line-height: 1.9;
}

/* Numbers and maths in the reading are what the row is for, so they get the
   ink and a little room around each entry. */
.fact-text {
  color: var(--ink);
}

.fact-text .katex { padding: 0 0.05em; }

/* A break is reported at a place, and that place can be a whole list of
   points, so it gets the full width of the panel instead of being squeezed
   into the label column. Indented so it reads as sitting under the
   Discontinuities heading above it. */
.fact-point {
  display: block;
  padding-left: 11rem;    /* the label column plus its gap, so it lines up
                             under the heading's empty right-hand side */
  padding-top: 0.35rem;
  border-top: none;
}

.fact-point .fact-label {
  color: var(--ink);
  margin-right: 0.5rem;
  font-size: inherit;
  letter-spacing: normal;
  text-transform: none;
  line-height: inherit;
}

/* Nothing to tabulate -- a sentence about the curve, running the full width
   of the panel. */
.fact-note {
  display: block;
  padding-top: 0.35rem;
  border-top: none;
}

/* The heading its points hang from: no value of its own, and no rule
   between it and the first of them. */
.fact-heading .fact-label { color: var(--ink-soft); }

/* The pricing page takes the bar's face, the way the account pages do, so
   the type does not change between the navigation and what is under it. */
body.pricing-page {
  font-family: var(--font-bar);
}

.pricing-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 1.25rem;
}

.pricing-card h2 {
  margin: 0 0 0.5rem;
  font-size: 1.1rem;
  font-weight: 500;
}

/* Not the mono face: its zero is struck through, which reads as a glyph
   with something wrong with it rather than as a price. The sans has a plain
   lining zero, so "$0" looks like nothing at all -- which is the point. */
.price {
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: 1.75rem;
  letter-spacing: -0.02em;
  margin: 0 0 0.5rem;
}

.price .period {
  font-weight: 400;
  font-size: 0.85rem;
  letter-spacing: 0;
  color: var(--ink-soft);
}

.pricing-card .blurb {
  color: var(--ink-soft);
  font-size: 0.9rem;
  margin: 0 0 1rem;
}

/* What each plan includes stays in the reading face it was set in before the
   page took the bar's: the list is prose about the product, not chrome. */
.pricing-card ul {
  margin: 0;
  padding-left: 1.1rem;
  font-family: var(--font-sans);
  font-size: 0.9rem;
}

.pricing-card li { margin-bottom: 0.4rem; }
.pricing-card li:last-child { margin-bottom: 0; }

/* Every card is as tall as the tallest, so the way onto a plan sits on one
   line across the row rather than wherever its own list happens to end. */
.pricing-card {
  display: flex;
  flex-direction: column;
}

.pricing-take {
  margin-top: auto;
  padding-top: 1.25rem;
}

.pricing-go {
  display: block;
  width: 100%;
  padding: 0.6rem 1rem;
  border: 1px solid var(--ink);
  border-radius: 2px;
  background: var(--ink);
  color: var(--paper);
  font-family: inherit;
  font-size: 0.92rem;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
}

.pricing-go:hover { background: transparent; color: var(--ink); }

/* The plan already held is stated rather than offered. */
.pricing-current {
  margin: 0;
  padding: 0.6rem 1rem;
  border: 1px solid var(--grid);
  border-radius: 2px;
  font-size: 0.92rem;
  text-align: center;
  color: var(--ink-soft);
}

.pricing-note {
  max-width: 62ch;
  margin: 1.75rem 0 0;
  font-size: 0.88rem;
  color: var(--ink-soft);
}

@media (max-width: 800px) {
  /* Side by side stops making sense on a phone: stack the panes and let the
     page scroll as one instead of two independently scrolling columns. */
  body.analyze-page {
    height: auto;
    overflow: visible;
  }

  .analyze-layout {
    grid-template-columns: 1fr;
    grid-template-rows: auto auto;
    flex: none;
  }

  .work-pane {
    overflow: visible;
    padding-right: 1.25rem;
  }

  .graph-pane {
    border-left: none;
    border-top: 1px solid var(--grid);
    padding: 1rem 1.25rem 1.25rem;
  }

  .graph-area {
    flex: none;
    height: 360px;
  }

  /* The label column costs more than it earns on a narrow screen: stack
     each fact instead, and let the panel run as long as it needs to now
     that the page scrolls as one. */
  .fact {
    display: block;
  }

  .fact-label { display: block; }

  .fact-point { padding-left: 1rem; }

  .notes-text { max-height: none; }

  /* The limit controls stack rather than run off the side of a phone. */
  .lim-panel {
    padding-right: 1.25rem;
  }

  .lim-exit { margin-left: 0; }
}

/* --------------------------------------------------------------------------
   Home page

   Black ink on white paper, and almost all of it is the paper. Every rule
   below is scoped to body.home-page, so the analyzer keeps its own look.
   No cards and no rounded panels -- the page is held together by hairlines,
   colour spines and the graph paper behind it. The only colour anywhere is
   on marks that mean something: f, f' and F keep the three colours the
   analyzer draws them in, and nothing else is coloured at all.
   -------------------------------------------------------------------------- */

body.home-page {
  --ground: #FFFFFF;
  --rule: #DEDEDE;
  --rule-soft: #EDEDED;
  --text: #111214;
  --text-soft: #55585E;
  --text-faint: #8A8E96;
  --f: #2C4A7C;
  --d: #BD5B2C;
  --i: #1F7A6C;
  --font-display: 'Fraunces', 'IBM Plex Serif', Georgia, serif;
  --font-ui: 'Space Grotesk', 'IBM Plex Sans', ui-sans-serif, system-ui, sans-serif;

  background: var(--ground);
  color: var(--text);
  font-family: var(--font-ui);
}

body.home-page main a { color: var(--text); }

/* The homepage runs edge to edge; each section pulls its own text back to a
   reading width with .home-wrap. */
body.home-page main {
  display: block;
  max-width: none;
  padding: 0;
}

body.home-page main > section {
  position: relative;
  z-index: 1;
}

.home-wrap {
  max-width: 1180px;
  margin: 0 auto;
  padding: 0 clamp(1.25rem, 4vw, 3rem);
}

/* --- the background ------------------------------------------------------ */

.home-bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: var(--ground);
}

/* Graph paper: a fine 32px grid with a heavier line every fifth one, faded
   out towards the edges so it never fights with the text on top of it. */
.home-grid {
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(rgba(17, 18, 20, 0.045) 1px, transparent 1px),
    linear-gradient(90deg, rgba(17, 18, 20, 0.045) 1px, transparent 1px),
    linear-gradient(rgba(17, 18, 20, 0.085) 1px, transparent 1px),
    linear-gradient(90deg, rgba(17, 18, 20, 0.085) 1px, transparent 1px);
  background-size: 32px 32px, 32px 32px, 160px 160px, 160px 160px;
  -webkit-mask-image: radial-gradient(ellipse 115% 85% at 50% 28%, #000 30%, transparent 86%);
  mask-image: radial-gradient(ellipse 115% 85% at 50% 28%, #000 30%, transparent 86%);
}

/* --- hero ---------------------------------------------------------------- */

.hero {
  display: grid;
  grid-template-columns: minmax(0, 4fr) minmax(0, 3fr);   /* the surface takes 3/7 */
  gap: clamp(1rem, 3vw, 3.5rem);
  width: 100%;
  max-width: 1560px;
  margin: 0 auto;
  padding: 0 clamp(1.25rem, 4vw, 3rem);
  min-height: calc(100vh - 4.3rem);
  min-height: calc(100svh - 4.3rem);
}

/* The title and the button sit a little above the middle of the hero. */
.hero-copy {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: clamp(1.5rem, 4vh, 2.5rem);
  padding-bottom: clamp(2rem, 11vh, 7rem);
  min-width: 0;
}

/* "Properly Comprehend" runs across one line. "Calculus" goes on the next,
   pushed right until half of it sits under "Comprehend" and the other half
   hangs off the end of the line. */
.hero-title {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  width: 100%;
  margin: 0;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(2.3rem, 5vw, 4.4rem);
  line-height: 0.98;
  letter-spacing: -0.025em;
}

.tl-line1 {
  display: flex;
  align-items: baseline;
  gap: 0.28em;
  white-space: nowrap;
}

/* home.js measures the two words and sets --calculus-offset so the halves
   land where they should; the em value is what it falls back to. */
.tl-line2 {
  margin-left: var(--calculus-offset, 6.4em);
  margin-top: 0.04em;
}

.tl-properly {
  color: var(--text-soft);
  font-size: 0.74em;
  letter-spacing: 0.005em;
}

/* The word itself is never quite still: the variable axes of Fraunces drift
   continuously, and every few seconds the whole face is swapped for another
   one behind a short blur. */
.tl-comprehend {
  display: inline-block;
  font-family: var(--morph-font, var(--font-display));
  font-optical-sizing: none;
  color: var(--text);
  transition: opacity 0.26s ease, filter 0.26s ease;
  animation: title-breathe 7s ease-in-out infinite;
}

.tl-comprehend.swapping {
  opacity: 0.25;
  filter: blur(3px);
}

@keyframes title-breathe {
  0%, 100% {
    font-variation-settings: "opsz" 18, "wght" 390, "SOFT" 0, "WONK" 0;
    letter-spacing: -0.021em;
  }
  50% {
    font-variation-settings: "opsz" 144, "wght" 545, "SOFT" 100, "WONK" 1;
    letter-spacing: -0.043em;
  }
}

.tl-calculus { white-space: nowrap; }

/* Set the way a variable is typeset in mathematics -- italic serif -- so the
   word looks like the subject it names. */
.mathword {
  font-family: 'IBM Plex Serif', Georgia, 'Times New Roman', serif;
  font-style: italic;
  font-weight: 500;
  color: var(--f);
  font-size: 1.2em;
  letter-spacing: -0.01em;
}

body.home-page .cta {
  display: inline-block;
  /* home.js measures where "Comprehend" begins and puts the button's left
     edge directly under it. Vertical position is untouched. */
  margin-left: var(--cta-offset, 0px);
  padding: 0.9rem 2.3rem;
  border: 1px solid var(--text);
  border-radius: 2px;
  background: var(--text);
  color: var(--ground);
  font-family: var(--font-ui);
  font-size: 1rem;
  font-weight: 500;
  letter-spacing: 0.01em;
  text-decoration: none;
  transition: background 0.15s ease, color 0.15s ease;
}

body.home-page .cta:hover {
  background: var(--ground);
  color: var(--text);
}

/* Only the last words of the line change. The phrase in front of them never
   moves, so it reads as one sentence being finished four different ways
   rather than as a ticker. */
.prep-word {
  transition: opacity 0.28s ease;
}

.prep-word.fading { opacity: 0; }

/* SAT, ACT and AP are other people's marks. Raised and set small, the way a
   mark is set. */
.tm {
  font-size: 0.62em;
  vertical-align: super;
  line-height: 0;
  letter-spacing: 0.02em;
}

/* --- the surface -------------------------------------------------------- */

.hero-figure {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-width: 0;
  margin: 0;
  padding: 0 0 clamp(2rem, 11vh, 7rem);
}

.hero-graph-wrap {
  position: relative;
  flex: none;
  width: 100%;
  height: min(56vh, 490px);
}

#hero-graph {
  position: relative;
  width: 100%;
  height: 100%;
}

/* The surface, then what it is, then how it changes in each direction. */
.hero-caption {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  padding-top: 0.9rem;
  border-top: 1px solid var(--rule);
}

.hero-eq {
  max-width: 100%;
  overflow-x: auto;
  overflow-y: hidden;
  font-size: 1.2rem;
  color: var(--text);
  scrollbar-width: none;
}

.hero-partials {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.4rem 2rem;
  max-width: 100%;
  color: var(--text-soft);
  font-size: 0.95rem;
}

.hero-eq::-webkit-scrollbar { display: none; }

/* --- shared section furniture ------------------------------------------- */

.rules {
  border-top: 1px solid var(--rule);
  padding: clamp(3rem, 8vh, 6rem) 0;
}

.eyebrow {
  margin: 0 0 0.9rem;
  font-size: 0.72rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.section-title {
  margin: 0 0 0.9rem;
  max-width: 20ch;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.7rem, 3.2vw, 2.7rem);
  line-height: 1.08;
  letter-spacing: -0.02em;
}

/* The heading and a hidden copy of its longest phrase in the same grid cell.
   The copy is never seen and only sets the height, so a short word like SAT
   reserves the room that "university courses" needs and the line underneath
   stays where it is however the words fall. */
.prep-heading {
  display: grid;
  /* No cap: at any comfortable width the longest of the four phrases fits on
     one line, so the reserved space below it is nothing at all. A little
     larger than the section headings it stands in for, and no larger --
     past about 3rem the longest phrase starts to take a second line. */
  max-width: none;
  font-size: clamp(1.9rem, 3.6vw, 3rem);
  color: var(--text-soft);
}

/* The words that change carry the ink, the way they did under the button:
   the phrase in front of them stays quiet. */
.prep-heading .prep-word { color: var(--text); }

.prep-heading > * { grid-area: 1 / 1; }

.prep-ghost { visibility: hidden; }

/* Below the fold, so it is never seen arriving: the first time it is
   scrolled to it rises the last of the way into place. */
.js .rise {
  opacity: 0;
  transform: translateY(1.1rem);
}

/* The transition lives on the arrival, not on the hidden state: hiding it in
   the first place is then instant, and only the rise is animated. */
.js .rise.revealed {
  opacity: 1;
  transform: none;
  transition: opacity 0.55s ease, transform 0.55s ease;
}

.section-lede {
  margin: 0 0 2.5rem;
  max-width: 58ch;
  color: var(--text-soft);
  font-size: 1rem;
}

.inline-math { color: var(--text); }

/* Rendered maths is an inline block, so a full stop straight after one can be
   left behind at the end of a line. Keeping the two together fixes it. */
.nowrap { white-space: nowrap; }

/* --- the rule, and the rule that undoes it ------------------------------ */

.rule-tabs {
  display: flex;
  gap: 1.75rem;
  margin-bottom: 2rem;
  border-bottom: 1px solid var(--rule);
}

.rule-tab {
  padding: 0 0 0.7rem;
  margin-bottom: -1px;
  border: 0;
  border-bottom: 2px solid transparent;
  background: none;
  color: var(--text-faint);
  font: inherit;
  font-size: 0.95rem;
  cursor: pointer;
}

.rule-tab:hover { color: var(--text-soft); }

.rule-tab.active {
  color: var(--text);
  border-bottom-color: var(--text);
}

.rule-take {
  margin: 0 0 1.75rem;
  color: var(--text-soft);
  font-size: 1rem;
}

.rule-take .inline-math { margin-left: 0.35rem; }

.rule-cols {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(1.5rem, 4vw, 3.5rem);
  /* Each colour spine should stop where its own working stops, rather than
     both being stretched to the height of the longer column. */
  align-items: start;
}

.rule-col {
  min-width: 0;
  padding-left: 1.15rem;
  border-left: 2px solid var(--accent);
}

.rule-forward { --accent: var(--d); }
.rule-backward { --accent: var(--i); }

.rule-name {
  margin: 0 0 0.6rem;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 1.35rem;
  letter-spacing: -0.01em;
  color: var(--accent);
}

.rule-law {
  padding: 0.4rem 0 1rem;
  border-bottom: 1px solid var(--rule);
  overflow-x: auto;
  overflow-y: hidden;
  font-size: 1.02rem;
}

.mini-step {
  padding: 1.05rem 0;
  border-bottom: 1px solid var(--rule-soft);
}

.mini-rule {
  margin: 0 0 0.4rem;
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.mini-intro {
  margin: 0 0 0.5rem;
  font-size: 0.9rem;
  line-height: 1.65;
  color: var(--text-soft);
}

.mini-line {
  overflow-x: auto;
  overflow-y: hidden;
  padding: 0.2rem 0;
  font-size: 0.98rem;
  scrollbar-width: thin;
}

.mini-note {
  margin: 0.5rem 0 0;
  font-size: 0.85rem;
  color: var(--text-faint);
  line-height: 1.6;
}

.rule-answer {
  margin-top: 1rem;
  padding-top: 0.85rem;
  border-top: 2px solid var(--accent);
  overflow-x: auto;
}

.rule-answer-label {
  margin: 0 0 0.2rem;
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
}

/* --- the analyzer, on one function ---------------------------------------
   The homepage's last word is the tool itself rather than a description of
   it. It is laid out the way the analyzer is -- what was found on the left,
   the plot and the facts read off it on the right -- so the page and the
   thing it is about look like each other. No cards: hairlines and the page
   underneath. */

.demo {
  border-top: 1px solid var(--rule);
  padding: clamp(3rem, 8vh, 6rem) 0;
}

.demo-body {
  display: grid;
  grid-template-columns: minmax(0, 3fr) minmax(0, 4fr);
  gap: clamp(1.5rem, 4vw, 3.5rem);
  align-items: start;
}

.demo-read {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  margin: 0;
  font-size: 1.05rem;
  color: var(--text);
}

.demo-read-label {
  font-size: 0.72rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.demo-answer {
  margin-top: 1.6rem;
  padding-top: 1.1rem;
  border-top: 1px solid var(--rule);
}

.demo-answer-label {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  margin: 0 0 0.2rem;
  font-size: 1rem;
  font-weight: 500;
  color: var(--text-soft);
}

.demo-caption {
  font-size: 0.78rem;
  color: var(--text-faint);
}

.demo-math {
  font-size: 1.15rem;
  overflow-x: auto;
  overflow-y: hidden;
  padding: 0.3rem 0 0.1rem;
}

.demo-math .katex-display { margin: 0.3rem 0; }

.demo-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 1.25rem;
  margin-bottom: 0.6rem;
  font-size: 0.85rem;
  color: var(--text-soft);
}

.demo-legend span {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}

/* The plot is a picture here, not an instrument: it does not take the
   scroll wheel, so the page keeps scrolling over it. */
.demo-graph-wrap {
  position: relative;
  width: 100%;
  height: min(46vh, 380px);
}

#demo-graph {
  position: absolute;
  inset: 0;
}

/* The same table the analyzer prints under its graph. */
.demo-facts {
  margin-top: 1.25rem;
  border-top: 1px solid var(--rule);
}

.demo-fact {
  display: grid;
  grid-template-columns: 9.5rem 1fr;
  gap: 0 1.5rem;
  padding: 0.55rem 0;
  border-top: 1px solid var(--rule-soft);
  font-size: 0.9rem;
  line-height: 1.55;
}

.demo-fact:first-child { border-top: none; }

.demo-fact-label {
  color: var(--text-faint);
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  line-height: 1.9;
}

.demo-fact-text { color: var(--text); }

/* Maths on this page is left-aligned like working on a page, not centred. */
body.home-page .katex-display {
  margin: 0.3rem 0;
  text-align: left;
}

body.home-page .katex-display > .katex { text-align: left; }

@media (max-width: 1000px) {
  .hero {
    grid-template-columns: 1fr;
    min-height: 0;
    padding-bottom: 3rem;
  }

  .hero-copy {
    order: 2;
    padding-bottom: 0;
    padding-top: 1.5rem;
  }

  .hero-figure {
    order: 1;
    padding: 2rem 0 0;
  }

  .hero-graph-wrap { height: 42vh; }

  .tl-line1 { flex-wrap: wrap; white-space: normal; }
  .tl-line2 { margin-left: 0; }
  body.home-page .cta { margin-left: 0; }
  .rule-cols { grid-template-columns: 1fr; gap: 2.5rem; }

  .demo-body { grid-template-columns: 1fr; }
  .demo-fact { display: block; }
  .demo-fact-label { display: block; }
}

@media (prefers-reduced-motion: reduce) {
  .tl-comprehend { animation: none; }
  /* The words still change -- each one says something the others don't --
     but they change without the fade, and the heading is simply there. */
  .prep-word { transition: none; }

  .js .rise { transform: none; }
  .js .rise.revealed { transition: none; }
}

/* --------------------------------------------------------------------------
   The written working
   -------------------------------------------------------------------------- */

.no-form {
  font-size: 0.95rem;
  color: var(--ink-soft);
  font-style: italic;
}

/* A quiet toggle rather than a button: the answer is the thing on the page,
   and the working is there for whoever wants it. */
.show-more {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  background: none;
  border: none;
  margin-top: 0.6rem;
  padding: 0;
  font-family: var(--font-sans);
  font-size: 0.85rem;
  color: var(--ink-soft);
  cursor: pointer;
}

.show-more::before {
  content: "";
  width: 0;
  height: 0;
  border-left: 5px solid currentColor;
  border-top: 4px solid transparent;
  border-bottom: 4px solid transparent;
  transition: transform 0.15s ease;
}

.show-more[aria-expanded="true"]::before { transform: rotate(90deg); }
.show-more:hover { color: var(--ink); }

/* No card, no fill -- the working sits directly on the page and gets the
   full width of the pane, because it's the longest thing on it. */
.steps {
  margin-top: 1rem;
  border-top: 1px solid var(--grid);
}

.step {
  padding: 2rem 0;
  border-bottom: 1px solid var(--grid);
}

.step:last-child { border-bottom: none; }

.step-rule {
  font-size: 0.72rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--ink-soft);
  margin-bottom: 0.85rem;
}

.step-intro {
  margin: 0 0 0.9rem;
  font-size: 0.95rem;
  line-height: 1.7;
}

.step-line {
  font-size: 1.05rem;
  overflow-x: auto;
  overflow-y: hidden;
  padding: 0.6rem 0;
}

.step-line .katex-display {
  margin: 0.3rem 0;
  text-align: left;
}

.step-note {
  margin: 0.9rem 0 0;
  font-size: 0.9rem;
  color: var(--ink-soft);
  line-height: 1.65;
}

/* The answer a marker would look for: ruled off and stated once more,
   rather than boxed into a panel of its own. */
.step-answer {
  margin-top: 0.4rem;
  padding-top: 0.9rem;
  border-top: 2px solid var(--ink);
  overflow-x: auto;
}

.step-answer .katex-display {
  margin: 0.2rem 0;
  text-align: left;
}

.legend-hint {
  font-size: 0.78rem;
}

/* --------------------------------------------------------------------------
   The course: the section list, and a lesson read one stage at a time.

   Same materials as the rest of the site -- hairlines, square corners, no
   cards and no shadows. What is different here is the measure: these pages
   are read rather than scanned, so the column is held to about 68 characters
   and the leading is opened up.
   -------------------------------------------------------------------------- */

.course-wrap,
.lesson-wrap {
  max-width: 46rem;
  margin: 0 auto;
  padding: 2.5rem 1.5rem 5rem;
}

.course-head h1,
.lesson-head h1 {
  margin: 0 0 0.6rem;
  font-size: 1.9rem;
  font-weight: 500;
  letter-spacing: -0.015em;
}

.course-intro {
  margin: 0 0 2.5rem;
  color: var(--ink-soft);
  max-width: 38rem;
}

/* --- the list of sections ----------------------------------------------- */

.section-list,
.lesson-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.section-item { border-top: 1px solid var(--grid-strong); }
.section-item:last-child { border-bottom: 1px solid var(--grid-strong); }

.section-summary {
  display: flex;
  align-items: baseline;
  gap: 1rem;
  padding: 1.1rem 0;
  cursor: pointer;
  list-style: none;
}

/* The default disclosure triangle is replaced by the number and the rule
   below it, so it is taken out on both engines. */
.section-summary::-webkit-details-marker { display: none; }
.section-summary::marker { content: ""; }

.section-number {
  flex: none;
  width: 2rem;
  font-family: var(--font-mono);
  font-size: 0.85rem;
  color: var(--grid-strong);
}

.section-name { flex: 1; min-width: 0; }

/* Scoped to the listing: the home page has a .section-title of its own,
   further up, and this one is later in the file so it was quietly winning
   there too and setting the home page's heading at 1.1rem. */
.section-summary .section-title {
  display: block;
  font-size: 1.1rem;
  font-weight: 500;
}

.section-count {
  flex: none;
  font-size: 0.8rem;
  color: var(--ink-soft);
}

.section[open] .section-count { color: var(--ink); }

/* Lessons hang under the section number rather than starting at the margin,
   so the indent alone says which section they belong to. */
.lesson-list { padding: 0 0 1rem 3rem; }

.lesson-link {
  display: flex;
  align-items: baseline;
  gap: 0.9rem;
  padding: 0.7rem 0.6rem 0.7rem 0;
  border-top: 1px solid var(--grid);
  color: var(--ink);
  text-decoration: none;
}

.lesson-link:hover { background: var(--card); }

.lesson-index {
  flex: none;
  width: 1.2rem;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  color: var(--grid-strong);
}

.lesson-text { flex: 1; min-width: 0; }

.lesson-title {
  display: block;
  font-weight: 500;
}

.lesson-go {
  flex: none;
  color: var(--grid-strong);
}

.lesson-link:hover .lesson-go { color: var(--ink); }

/* --- a lesson ------------------------------------------------------------ */

.lesson-crumb {
  margin: 0 0 0.8rem;
  font-size: 0.85rem;
  color: var(--ink-soft);
  display: flex;
  gap: 0.5rem;
}

.lesson-crumb a { text-decoration: none; }
.lesson-crumb a:hover { text-decoration: underline; }

.lesson-standfirst {
  margin: 0 0 2rem;
  color: var(--ink-soft);
  font-size: 1.02rem;
}

/* The four stages, as a row of numbered steps. It is a map of the lesson as
   much as a control: you can see what is coming. */
.stage-rail {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.4rem;
  padding: 0.9rem 0;
  border-top: 1px solid var(--grid-strong);
  border-bottom: 1px solid var(--grid-strong);
  margin-bottom: 2.2rem;
}

.stage-tab {
  display: inline-flex;
  align-items: baseline;
  gap: 0.45rem;
  padding: 0;
  border: none;
  background: none;
  font-family: var(--font-sans);
  font-size: 0.88rem;
  color: var(--ink-soft);
  cursor: pointer;
}

.stage-tab-number {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  color: var(--grid-strong);
}

.stage-tab:hover { color: var(--ink); }
.stage-tab.done .stage-tab-number { color: var(--ink-soft); }

.stage-tab.active {
  color: var(--ink);
  font-weight: 500;
}

.stage-tab.active .stage-tab-number { color: var(--pencil); }

.stage[hidden] { display: none; }

.stage-title {
  margin: 0 0 1.4rem;
  font-size: 0.78rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--ink-soft);
}

/* --- what a stage is made of --------------------------------------------- */

.block-text {
  margin: 0 0 1.1rem;
  line-height: 1.72;
}

.block-heading {
  margin: 2rem 0 0.9rem;
  font-size: 1.02rem;
  font-weight: 500;
}

.block-math {
  margin: 1.3rem 0;
  overflow-x: auto;
  overflow-y: hidden;
}

.block-math .katex-display { margin: 0; }

/* An aside: quieter than the argument it hangs off, and marked by a rule
   rather than a tint or a box. */
.block-note {
  margin: 1.3rem 0;
  padding-left: 1rem;
  border-left: 2px solid var(--grid-strong);
  font-size: 0.92rem;
  color: var(--ink-soft);
  line-height: 1.66;
}

/* The rule itself, set apart by two hairlines. No card. */
.block-law {
  margin: 1.6rem 0;
  padding: 1rem 0;
  border-top: 1px solid var(--grid-strong);
  border-bottom: 1px solid var(--grid-strong);
}

.law-name {
  margin: 0 0 0.5rem;
  font-size: 0.75rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--ink-soft);
}

.law-tex {
  overflow-x: auto;
  overflow-y: hidden;
  padding: 0.2rem 0;
}

.law-tex .katex-display { margin: 0.2rem 0; }

.law-says {
  margin: 0.6rem 0 0;
  font-size: 0.92rem;
  color: var(--ink-soft);
}

/* --- worked examples and practice problems ------------------------------- */

.block-work {
  margin: 1.6rem 0;
  padding-left: 1.1rem;
  border-left: 2px solid var(--pencil);
}

.block-work.is-problem { border-left-color: var(--derivative); }

.work-ask {
  margin: 0 0 0.6rem;
  font-size: 0.95rem;
}

.work-question {
  margin: 0 0 0.4rem;
  overflow-x: auto;
  overflow-y: hidden;
}

.work-question .katex-display { margin: 0.2rem 0; }

/* The answer box. A question is answered before it is explained, so this
   sits between the question and the working, on the same spine. Scoped to
   the lesson page: the analyze page has its own .answer, further up. */
.block-work .answer {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin: 0.8rem 0 0;
}

.answer-prompt {
  font-size: 0.95rem;
  color: var(--ink-soft);
}

.answer-input {
  flex: 1 1 12rem;
  min-width: 0;
  padding: 0.3rem 0.1rem;
  border: none;
  border-bottom: 1px solid var(--grid-strong);
  border-radius: 0;
  background: none;
  font-family: var(--font-mono);
  font-size: 0.95rem;
  color: var(--ink);
}

.answer-input:focus {
  outline: none;
  border-bottom-color: var(--pencil);
}

.answer-input::placeholder {
  color: var(--ink-soft);
  opacity: 0.6;
}

.answer-check {
  padding: 0.3rem 0.9rem;
  border: 1px solid var(--pencil);
  border-radius: 2px;
  background: var(--pencil);
  font-family: var(--font-sans);
  font-size: 0.82rem;
  color: var(--card);
  cursor: pointer;
}

.answer-check:hover { background: var(--pencil-dark); border-color: var(--pencil-dark); }

.answer-verdict {
  margin: 0.5rem 0 0;
  font-size: 0.88rem;
  color: var(--ink-soft);
}

.answer-verdict[hidden] { display: none; }
.answer-verdict.is-right { color: var(--integral); }
.answer-verdict.is-wrong { color: var(--derivative); }

.block-work.answered { border-left-color: var(--integral); }

.reveal {
  margin: 0.5rem 0 0;
  padding: 0.25rem 0.6rem;
  border: 1px solid var(--grid-strong);
  border-radius: 2px;
  background: none;
  font-family: var(--font-sans);
  font-size: 0.82rem;
  color: var(--ink-soft);
  cursor: pointer;
}

.reveal:hover { color: var(--ink); border-color: var(--ink); }

.work-body { margin-top: 0.6rem; }
.work-body[hidden] { display: none; }

.work-step {
  margin: 0 0 0.9rem;
  padding-top: 0.6rem;
  border-top: 1px solid var(--grid);
}

.work-step:first-child { border-top: none; padding-top: 0; }

.work-rule {
  margin: 0 0 0.3rem;
  font-size: 0.75rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--ink-soft);
}

.work-intro,
.work-note {
  margin: 0.2rem 0;
  font-size: 0.9rem;
  color: var(--ink-soft);
}

.work-line {
  margin: 0.35rem 0;
  overflow-x: auto;
  overflow-y: hidden;
}

.work-line .katex-display { margin: 0.25rem 0; }

.work-answer {
  margin-top: 0.7rem;
  padding-top: 0.6rem;
  border-top: 1px solid var(--grid-strong);
  overflow-x: auto;
  overflow-y: hidden;
}

.work-answer .katex-display { margin: 0.25rem 0; }

.work-hint {
  margin: 0.7rem 0 0;
  font-size: 0.88rem;
  color: var(--ink-soft);
}

.hint-label {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  margin-right: 0.5rem;
  color: var(--derivative);
}

.work-error {
  margin: 0;
  font-size: 0.9rem;
  color: var(--derivative);
}

/* The facts panel, borrowed whole from the analyzer for the continuity
   lessons. It is styled up there; only the spacing changes here. */
.block-work .fact { font-size: 0.88rem; }

/* --- moving through a lesson --------------------------------------------- */

.stage-foot {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-top: 2.5rem;
  padding-top: 1.2rem;
  border-top: 1px solid var(--grid-strong);
}

.stage-next,
.stage-back {
  display: inline-block;
  padding: 0.5rem 1rem;
  border: 1px solid var(--grid-strong);
  border-radius: 2px;
  background: none;
  font-family: var(--font-sans);
  font-size: 0.92rem;
  color: var(--ink);
  text-decoration: none;
  cursor: pointer;
}

.stage-next {
  background: var(--pencil);
  border-color: var(--pencil);
  color: #FFFFFF;
  order: 2;
  margin-left: auto;
}

.stage-next:hover { background: var(--pencil-dark); border-color: var(--pencil-dark); }
.stage-back:hover { border-color: var(--ink); }

.lesson-next { order: 2; margin-left: auto; }
.lesson-next .stage-next { margin-left: 0; }

.lesson-foot {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  margin-top: 3rem;
  padding-top: 1.2rem;
  border-top: 1px solid var(--grid);
  font-size: 0.9rem;
}

.foot-link {
  color: var(--ink-soft);
  text-decoration: none;
}

.foot-link:hover { color: var(--ink); text-decoration: underline; }

@media (max-width: 640px) {
  .course-wrap,
  .lesson-wrap { padding: 1.5rem 1.1rem 3.5rem; }

  .lesson-list { padding-left: 1.2rem; }

  .stage-rail { gap: 0.35rem 1rem; }

  .stage-tab-title { display: none; }
  .stage-tab-number { font-size: 0.85rem; }
  .stage-tab.active .stage-tab-title { display: inline; }
}
