:root {
  --border: #d0d5dd;
  --header-bg: #f4f6f8;
  --header-fg: #6b7280;
  --accent: #2563eb;
  --accent-bg: #dbe7ff;
  --active-bg: #ffffff;
  --cell-fg: #1a1a1a;
  --label-fg: #444;          /* toolbar field labels, and anything that must read as one */
}

* { box-sizing: border-box; }

html, body {
  height: 100%;
  margin: 0;
}

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Arial, sans-serif;
  padding: 20px;
  background: #fafbfc;
  color: #1a1a1a;
  overflow: hidden;
}

#app {
  display: flex;
  flex-direction: column;
  height: 100%;
  gap: 14px;
}

.app-header { flex: none; }

.app-header .controls-row {
  margin-top: 0;
  align-items: center; /* .controls-row defaults to flex-end for label+input toolbar fields; the header just has a heading + buttons */
}
.app-header .teal-button-link {
  margin-top: 0;
  margin-bottom: 0;
}

.app-toolbar {
  flex: none;
  display: flex;
  align-items: center;
  gap: 5px;
}

.primary-btn {
  background: var(--accent);
  color: white;
  border: none;
  border-radius: 6px;
  padding: 8px 16px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}
.primary-btn:hover { background: #1d4ed8; }

.controls-row {
	margin-top: 20px;
	display: flex;
	gap: 20px;
	align-items: flex-end;
	flex-wrap: wrap;
}
.field label {
	display: block;
	font-size: 13px;
	color: var(--label-fg);
	margin-bottom: 4px;
}
.field input, .field select {
	padding: 5px 8px;
	font-size: 14px;
	border: 1px solid #bbb;
	border-radius: 4px;
}

.app-main {
  flex: 1;
  display: flex;
  gap: 16px;
  min-height: 0; /* required for flex children to shrink instead of overflowing */
}

.panel {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
}

/* 1 : 1 : 2 across the row. This said `flex: 3` until 2026-09-05 and was dead
   the whole time: every .panel-grid section carried an inline `style="flex: 1"`
   that won. The inline styles are gone and the value moved here unchanged, so
   the desktop layout is identical - but it can now be overridden below 900px,
   which an inline style could not be without !important. */
.panel-grid { flex: 1; }
.panel-chart { flex: 2; }

.panel-ad {
  flex: 0 0 160px;
  max-width: 160px;
}

.app-footer-ad {
  flex: none;
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 4px 0;
}

.ad-slot-banner {
  width: 728px;
  height: 90px;
  max-width: 100%; /* graceful shrink on narrow viewports */
  border: 1px dashed var(--border); /* remove once ads confirmed rendering */
  border-radius: 4px;
  overflow: hidden;
}

.ad-slot {
	min-height: 250px; /* reserves space for a standard rectangle unit before load */
	border: 1px dashed var(--border); /* optional: visualize the reserved slot pre-approval */
	border-radius: 6px;
}

.panel-body {
  flex: 1;
  min-height: 0;
}

/* ---- Grid root ---- */
.gt-root {
  border: 0px solid var(--border);
  border-radius: 8px;
  background: #fafbfc;
  overflow: hidden;
  user-select: none;
}

.gt-scroll {
  position: relative;
  overflow: auto;
  width: 100%;
}

.gt-sizer {
  position: relative;
}

.gt-canvas {
  position: sticky;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
  pointer-events: none; /* re-enabled on children */
}

.gt-canvas > * { pointer-events: auto; }

.gt-corner {
  position: absolute;
  top: 0; left: 0;
  background: var(--header-bg);
  border-right: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  z-index: 4;
}

.gt-colheader, .gt-rowheader, .gt-cells {
  position: absolute;
  top: 0; left: 0;
  width: 100%;
  height: 100%;
}

.gt-colheader { z-index: 3; pointer-events: none; }
.gt-rowheader { z-index: 3; pointer-events: none; }
.gt-cells { z-index: 1; }

.gt-header-cell { pointer-events: auto; }

.gt-header-cell {
  position: absolute;
  background: var(--header-bg);
  color: var(--header-fg);
  font-size: 12px;
  font-weight: 600;
  border-right: 1px solid var(--border);
  border-left: 1px solid var(--border);
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  padding: 0 5px;
  overflow: hidden;
  white-space: nowrap;
}

.gt-header-cell.rownum { justify-content: center; padding: 0; }

.gt-col-resizer, .gt-row-resizer {
  position: absolute;
  z-index: 5;
  background: transparent;
}
.gt-col-resizer {
  top: 0; right: -3px; width: 6px; height: 100%;
  cursor: col-resize;
}
.gt-row-resizer {
  left: 0; bottom: -3px; height: 6px; width: 100%;
  cursor: row-resize;
}
.gt-col-resizer:hover, .gt-row-resizer:hover { background: var(--accent); opacity: 0.5; }

.gt-cell {
  position: absolute;
  background: white;
  color: var(--cell-fg);
  font-size: 13px;
  border-right: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  padding: 5px 7px;
  overflow: hidden;
  white-space: pre;
  text-overflow: ellipsis;
  cursor: cell;
}

.gt-cell.selected { background: var(--accent-bg); }
.gt-cell.active {
  background: var(--active-bg);
  box-shadow: inset 0 0 0 2px var(--accent);
  z-index: 2;
}
.gt-cell.editing {
  outline: none;
  cursor: text;
  white-space: pre-wrap;
  overflow: visible;
}

/* Add a global state modification flag to root */
.gt-root.gt-readonly .gt-cell {
  cursor: not-allowed; /* Shows block symbol on hover */
}

.gt-root.gt-readonly .gt-cell.selected {
  background: #f2f4f7; /* Muted slate background instead of vibrant blue */
}

.gt-hidden-input {
  position: fixed;
  top: -1000px;
  left: -1000px;
  width: 1px;
  height: 1px;
  opacity: 0;
  border: none;
  padding: 0;
}

/* ---- Context menu ---- */
.gt-context-menu {
  position: fixed;
  background: white;
  border: 1px solid var(--border);
  border-radius: 6px;
  box-shadow: 0 4px 16px rgba(0,0,0,0.12);
  padding: 4px;
  z-index: 1000;
  min-width: 170px;
  font-size: 13px;
}
.gt-context-menu ul { list-style: none; margin: 0; padding: 0; }
.gt-context-menu li {
  padding: 7px 10px;
  border-radius: 4px;
  cursor: pointer;
  color: #1a1a1a;
}
.gt-context-menu li:hover { background: var(--header-bg); }
.gt-context-menu li.danger { color: #dc2626; }
.gt-context-menu li.sep {
  height: 1px;
  margin: 4px 2px;
  padding: 0;
  background: var(--border);
  cursor: default;
}

/* ---- Chart ---- */
.ct-root {
  position: relative;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: white;
  padding: 12px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  min-height: 0;
}

.ct-canvas {
  display: block;
  width: 100%;
  flex: 1;
  min-height: 0;
}

.ct-tooltip {
  position: absolute;
  pointer-events: none;
  background: #1a1a1a;
  color: white;
  font-size: 11px;
  line-height: 1.4;
  padding: 6px 8px;
  border-radius: 5px;
  white-space: nowrap;
  transform: translateY(-100%);
  z-index: 10;
}

.ct-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin-top: 8px;
  padding-left: 4px;
}

.ct-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: #374151;
}

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

.ct-context-menu {
  position: absolute;
  background: #ffffff;
  border: 1px solid #d0d5dd;
  border-radius: 6px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  padding: 4px 0;
  min-width: 120px;
  z-index: 9999;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  font-size: 12px;
  display: none;
}
.ct-menu-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px;
  cursor: pointer;
  color: #374151;
  user-select: none;
}
.ct-menu-item:hover {
  background-color: #f3f4f6;
}
.ct-menu-checkbox {
  width: 12px;
  height: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: bold;
}
.ct-menu-separator {
  height: 1px;
  background-color: #e5e7eb;
  margin: 4px 0;
}
.ct-legend-break {
	flex-basis: 100%;
	height: 0;
}
.custom-link {
  display: inline-block;
  color: #00bfa5;          
  text-decoration: none;   
  font-weight: bold;       
  transition: color 0.2s ease, transform 0.2s ease;;
}
.custom-link:hover {
  color: #008b78;	
  text-decoration: none;  
  transform: scale(1.05);
}
.teal-button-link {
  display: inline-block;         
  background-color: #21c2b5; 
  color: #ffffff;                
  text-decoration: none;         
  font-weight: normal;
  padding: 5px 10px;            
  border-radius: 6px;            
  margin: 25px -5px !important;
  
  transition: background-color 0.2s ease, transform 0.2s ease; 
}
.teal-button-link:hover {
  background-color: #00bfa5;
  color: #ffffff;
  text-decoration: none;

  transform: scale(1.02);
}

/* ---- Blog / article pages (e.g. interpolate_blog.html) ---- */
body.blog-page { overflow: auto; } /* articles run taller than the viewport; calculator pages keep overflow:hidden */

/* header shares the post's max-width so both start at the same left edge */
body.blog-page .app-header {
  max-width: 720px;
  /* centred with .post below, so header and article share one left edge.
     width:100% is required: auto margins on a flex item cancel the default
     stretch, and the header would otherwise shrink to fit its buttons and
     centre at the wrong width. */
  width: 100%;
  margin-left: auto;
  margin-right: auto;
}

.post {
  max-width: 720px;
  /* The COLUMN is centred in the viewport. Text inside stays left-aligned -
     no text-align here, and never add one: a centred paragraph is unreadable
     at this measure. */
  width: 100%;
  margin-left: auto;
  margin-right: auto;
  padding-bottom: 60px;
}
.post h1 { margin-bottom: 4px; }
.post .subtitle { color: var(--header-fg); font-size: 15px; margin-bottom: 28px; }
.post h2 { margin-top: 36px; font-size: 20px; }
.post p, .post li {
  line-height: 1.65;
  font-size: 15px;
  color: var(--header-fg); /* soft grey body text, matches the calculator's label/header grey */
}
.post code {
  background: var(--header-bg);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 1px 5px;
  font-size: 13px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}
.post pre {
  background: #1a1a1a;
  color: #e5e7eb;
  border-radius: 8px;
  padding: 16px;
  overflow-x: auto;
  font-size: 13px;
  line-height: 1.5;
}
.post pre code { background: none; border: none; padding: 0; color: inherit; }
.post .note {
  border-left: 3px solid var(--accent);
  background: var(--accent-bg);
  padding: 10px 14px;
  border-radius: 0 6px 6px 0;
  font-size: 14px;
}

/* ---- Home / topic index (index.html) ---- */
/* Shares the article max-width so home and blog line up at the same left edge. */
body.home-page { overflow: auto; }
/* Home is the same centred 720px column as a blog page. width:100% is required
   on every one of these: auto margins cancel a flex item's default stretch, and
   the block would otherwise shrink to its content and centre at its own width,
   off the column's left edge. */
body.home-page .app-header {
  max-width: 720px;
  width: 100%;
  margin-left: auto;
  margin-right: auto;
}

.topic-list {
  max-width: 720px;
  width: 100%;
  margin-left: auto;
  margin-right: auto;
  padding-bottom: 40px;
}

/* One topic = one compact row: name, level buttons, toggle. Detail hides until asked. */
.topic-item { border-bottom: 1px solid var(--border); }
.topic-item:first-child { border-top: 1px solid var(--border); }

.topic-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
  padding: 10px 4px;
}
.topic-name {
  font-weight: 700;
  font-size: 15px;
  color: var(--cell-fg);
  margin-right: 4px; /* buttons sit just after the title, not pushed to the edge */
}
/* base .teal-button-link carries `margin: 25px -5px !important` for the blog header;
   inside these compact rows the negative margin eats the flex gap, so cancel it. */
.topic-row .teal-button-link {
  font-size: 13px;
  margin: 0 !important;
}

/* bare caret - no chrome, the glyph itself is the affordance */
.topic-toggle {
  flex: none;
  width: 24px;
  height: 24px;
  padding: 0;
  line-height: 1;
  font-size: 18px;
  font-weight: 700;
  color: var(--header-fg);
  background: none;
  border: none;
  cursor: pointer;
  transition: color 0.15s ease;
}
.topic-toggle:hover { color: var(--accent); }
.topic-toggle[aria-expanded="true"] { color: var(--accent); }

.topic-detail {
  padding: 0 4px 12px;
  font-size: 14px;
  line-height: 1.6;
  color: var(--header-fg);
  max-width: 640px;
}
.topic-detail .topic-meta {
  margin: 6px 0 0;
  font-size: 11px;
  letter-spacing: 0.03em;
  text-transform: uppercase;
}

/* de-emphasized dev links, below the real content */
.dev-section {
  max-width: 720px;
  width: 100%;
  margin-left: auto;
  margin-right: auto;
  margin-top: 24px;
  padding-top: 16px;
  border-top: 1px solid var(--border);
}
.dev-section h3 {
  margin: 0 0 10px;
  font-size: 12px;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--header-fg);
  font-weight: 600;
}
.topic-links { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; }
.dev-section .topic-links a {
  font-size: 13px;
  opacity: 0.75;
  margin: 0 !important; /* same negative-margin cancel as .topic-row */
}

/* Panel action buttons — the import / export controls in a panel heading.
   Moved here from interpolation_style.css on 2026-09-04, alongside the code
   that draws them (dev_basic/csv.ts). */
.panel-actions {
  display: inline-flex;
  gap: 6px;
  margin-left: 12px;
  vertical-align: middle;
}

/* .primary-btn's outline sibling: same shape, no fill, so "interpolate" stays
   the one filled button on the page and these read as secondary. */
.ghost-btn {
  background: transparent;
  color: var(--accent);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 4px 10px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
}
.ghost-btn:hover {
  border-color: var(--accent);
  background: var(--accent-bg);
}

/* Format fallback beside the export button, revealed only where the save dialog
   cannot offer a type dropdown. Same border, radius and size as .ghost-btn so
   the pair reads as one control. */
.ghost-select {
  color: var(--accent);
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 4px 6px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
}

/* ==========================================================================
   Narrow screens
   ==========================================================================
   PC and large tablet are the reference layout and everything above this line
   is theirs. This block is purely additive: it changes no existing rule, so a
   desktop viewport never reaches any of it and cannot regress.

   The calculator is a three-panel row pinned to the viewport, which is exactly
   what a phone cannot show. Below the breakpoint it becomes a scrolling column.
   The grids still scroll sideways inside their own panels - that is what a
   spreadsheet does on a phone - but the PAGE must never scroll sideways. */
/* ---- hint row: the how-to manual and the request box, side by side ---- */
/* Both are one-line <details> summaries, so a row costs #app one line instead
   of two. It owns the positioning context for BOTH floating bodies: anchored to
   their own <details> instead, the request panel would open at its summary's x
   and run off the right of a narrow window. */
.panel-hints {
  flex: none;
  position: relative;
  display: flex;
  align-items: center;
  gap: 18px;
  flex-wrap: wrap;
}
.panel-hints .how-to {
  /* The ROW is the positioning context for both floating bodies. */
  position: static;
}
.panel-hints .how-to,
.panel-hints .feedback {
  /* A flex item defaults to min-width:auto, which refuses to shrink below its
     content. The how-to summary is a long sentence, so without this the row
     pushes past a narrow viewport and the page scrolls sideways. */
  min-width: 0;
  max-width: 100%;
}
/* fit-content is right when the summary owns its line. Inside the row it must
   be free to wrap instead of setting the row's width. */
.panel-hints > details > summary {
  width: auto;
}

/* ---- "Send a request" panel: on both calculators ---- */
/* Private by design: nothing typed here is ever rendered back, so there is no
   comment list to style and no moderation state to show. The panel is a
   <details> like the how-to one, so the form exists in the HTML before any
   script runs.

   Not on the blog. The user's call: a request belongs where someone is using
   the tool, not where they are reading about it. */
.feedback {
  flex: none;
}
.feedback > summary {
  cursor: pointer;
  width: fit-content;
  padding: 2px 4px;
  font-size: 13px;
  line-height: 1.5;
  color: var(--label-fg);
}
.feedback > summary:hover,
.feedback[open] > summary {
  color: var(--accent);
}

.feedback-body {
  /* Floats over the grids, exactly like .how-to-body and for the same reason:
     #app is a column flex at height 100%, so a panel in normal flow would take
     its height from them. .panel-hints is the positioning context, so this
     anchors to the row's left edge rather than to its own summary - anchored to
     the summary it would open at that x and run off a narrow window. */
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  z-index: 30;
  width: min(760px, calc(100vw - 60px));
  max-height: min(60vh, 520px);
  overflow-y: auto;
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.12);
  padding: 14px 18px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--active-bg);
  font-size: 13px;
  line-height: 1.6;
  color: var(--header-fg);
}

.feedback-intro {
  margin: 0 0 12px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--border);
  color: var(--cell-fg);
}

.feedback-form label {
  display: block;
  margin-bottom: 4px;
  color: var(--label-fg);
}
.feedback-form textarea,
.feedback-form input[type="text"] {
  width: 100%;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--active-bg);
  color: var(--cell-fg);
  font-family: inherit;
  font-size: 13px;
}
.feedback-form textarea {
  min-height: 96px;
  resize: vertical;
}
.feedback-field + .feedback-field { margin-top: 10px; }

.feedback-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 12px;
}
#feedbackStatus { color: var(--header-fg); }
#feedbackStatus.is-error { color: #b42318; }

/* The honeypot. Off-screen, NOT display:none - a bot that skips hidden inputs
   also skips display:none, and this field only works if it gets filled. Never
   reachable by Tab and never announced: tabindex="-1" and aria-hidden are on
   the input itself. */
.feedback-hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* ---- The "how to use this" manual, and the blog elements above ----

   These were written once in topics/interpolation/interpolation_style.css and
   then copied verbatim into smoothing's and fft's topic CSS. Both of those
   builds flagged the duplication and left it for an "integration pass"
   (CLAUDE.md rule 4: extract on second use). Regression would have been the
   FOURTH copy, so the rules live here now instead.

   Added, not moved: the three existing topic copies are untouched, so no other
   topic's pages or tests change. They load after this file with identical
   values, so they win the cascade and render exactly as before, and each can
   be deleted on its own once someone re-runs that topic's suite. fft's own
   .eq / .post code overrides and its .fft-quad layout are its own and stay
   where they are.

   Closed, the manual costs one line; #app is a column flex at height 100%, so
   every line here is a line taken from the grids. Open, the body is absolutely
   positioned and floats over them instead of resizing anything. */
.how-to {
  flex: none;
  position: relative;
}
.how-to > summary {
  cursor: pointer;
  width: fit-content;
  padding: 2px 4px;
  /* reads as one with the toolbar's own field labels */
  font-size: 13px;
  line-height: 1.5;
  color: var(--label-fg);
}
.how-to > summary:hover,
.how-to[open] > summary {
  color: var(--accent);
}

.how-to-body {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  z-index: 30;
  width: min(760px, calc(100vw - 60px));
  /* Both values are viewport-relative, so this panel was responsive before
     anything else was. Keep it that way. The cap was written because body is
     overflow:hidden and an over-tall panel would be unreachable. */
  max-height: min(60vh, 520px);
  overflow-y: auto;
  padding: 14px 18px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--active-bg);
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.12);
  font-size: 13px;
  line-height: 1.6;
  color: var(--header-fg);
}
/* Sits above the steps: what the tool is for, before how to drive it. */
.how-to-intro {
  margin: 0 0 12px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--border);
  color: var(--cell-fg);
}

.how-to-body ol {
  margin: 0 0 10px;
  padding-left: 20px;
}
.how-to-body li { margin: 4px 0; }
.how-to-body p { margin: 8px 0 0; }
.how-to-body strong { color: var(--cell-fg); font-weight: 600; }

/* Figures are SVG, generated by a topic's gen_figs.py. `width`, not
   `max-width`: max-width only caps a smaller intrinsic SVG size, and every
   figure should fill the column whatever its own pixel dimensions say. */
.post img {
  width: 100%;
  height: auto;
  display: block;
  margin: 24px auto;
}

.post table {
  border-collapse: collapse;
  width: 100%;
  margin: 20px 0;
  font-size: 14px;
}
.post th,
.post td {
  border: 1px solid var(--border);
  padding: 7px 10px;
  text-align: left;
  color: var(--header-fg);
}
.post th {
  background: var(--header-bg);
  color: var(--cell-fg);
  font-weight: 600;
}

/* Display equation. Same shaded box as a code fence so a formula reads as a
   block, not as prose. MathJax fills it after load; the box is there before. */
.post .eq {
  background: var(--header-bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 12px 16px;
  margin: 20px 0;
  overflow-x: auto;
  text-align: center;
}

/* ---- The generic result panel (dev_basic/summary-panel.ts) ----

   MOVED here 2026-09-12 from regression's own regression_style.css: calculus
   is the panel's second user (CLAUDE.md rule 4). A plain relocation, not a
   duplicate-then-extract — class names are unchanged, so neither topic's HTML
   needed to change, only the two `<script src>` tags that load the .ts/.js.

   Sits under a chart inside .panel-chart, not as a fourth column in
   .app-main: the row is a 1:1:2 flex and a fifth panel would squeeze the
   grids. The chart already carries an aspect-ratio, so it takes the height it
   needs and this scrolls in whatever is left. */
.fit-results {
  flex: none;
  max-height: 38%;
  overflow-y: auto;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--border);
  font-size: 13px;
  line-height: 1.55;
  color: var(--header-fg);
}

.fit-empty {
  margin: 0;
  color: var(--label-fg);
}

.fit-block + .fit-block {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
}

.fit-label {
  margin: 0 0 6px;
  font-size: 13px;
  font-weight: 600;
  color: var(--label-fg);
}

/* The equation is the panel's headline result where one exists (regression's
   equation; calculus may leave this blank and put its scalar in .fit-stats
   instead), so it gets the emphasis and a monospace face - meant to be read
   digit by digit and retyped. */
.fit-equation {
  margin: 0 0 10px;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--header-bg);
  font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
  font-size: 13px;
  color: var(--cell-fg);
  overflow-x: auto;
  white-space: nowrap;
}

.fit-coefficients {
  border-collapse: collapse;
  margin: 0 0 10px;
  font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
  font-size: 12px;
}
.fit-coefficients th,
.fit-coefficients td {
  padding: 2px 10px 2px 0;
  text-align: left;
  font-weight: 400;
  color: var(--cell-fg);
}
.fit-coefficients th {
  color: var(--label-fg);
}

/* Label above value in pairs, wrapping across the panel's width rather than
   forcing a horizontal scroll on a narrow column. */
.fit-stats {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 18px;
  margin: 0;
}
.fit-stats dt {
  margin: 0;
  color: var(--label-fg);
}
.fit-stats dd {
  margin: 0 12px 0 0;
  font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
  color: var(--cell-fg);
}

/* Which solver ran, an interpolating order, an extrapolated range, a unit.
   Every one of these is something the page must say rather than let a
   reader assume. */
.fit-note {
  margin: 8px 0 0;
  color: var(--label-fg);
}


@media (max-width: 900px) {

  /* The rule that made the calculator unreachable rather than merely cramped:
     height:100% plus body{overflow:hidden} means a narrow viewport shows the
     header and nothing else, with no way to scroll to the panels. */
  html, body {
    height: auto;
    min-height: 100%;
  }

  body {
    overflow: auto;
    /* 40px of horizontal padding is a tenth of a 390px screen. */
    padding: 12px;
  }

  #app {
    height: auto;
    gap: 10px;
  }

  /* Title and nav buttons stop competing for one line. */
  .app-header {
    flex-wrap: wrap;
    gap: 8px;
  }
  .app-header h1 {
    font-size: 20px;
    line-height: 1.25;
  }

  .app-main {
    flex-direction: column;
  }

  /* flex: 3 / flex: 2 divided the horizontal axis. Once the axis is vertical
     inside an auto-height column those ratios mean nothing, so each panel takes
     an explicit height instead.

     This is also the trap in stacking: calc-page.ts builds both grids with
     viewportHeight: '100%', and 100% of an auto height is zero. Without a real
     height here the grids render empty. */
  .panel-grid,
  .panel-chart {
    flex: none;
  }
  .panel-grid { height: 55vh; min-height: 300px; }
  .panel-chart { height: 40vh; min-height: 240px; }

  /* Regression's Results panel holds a chart AND the fitted model, so at the
     shared 40vh the chart was squeezed to about half the height every other
     topic's gets. This panel sizes to its contents instead, and the CHART takes
     the height the rule above gives the whole panel.

     Additive, and scoped to a class only regression's markup carries: no other
     topic's panel matches it, and no desktop rule was touched (CLAUDE.md's
     responsive rule). */
  .panel-chart.panel-with-model {
    height: auto;
    min-height: 0;
  }
  .panel-chart.panel-with-model .panel-body {
    height: 40vh;
    min-height: 240px;
  }
  .panel-chart.panel-with-model .fit-results {
    max-height: none;
    overflow: visible;
  }

  /* Ads are a desktop-only column; a 160px rail on a phone is pure cost. */
  .panel-ad { display: none; }
}
