/*
 * Color tokens live entirely in this block plus its dark-mode counterpart
 * below. When adding a new page with its own palette, give that page's own
 * stylesheet the same two blocks (:root and :root[data-theme="dark"]) with
 * its own values — theme.js only flips the `data-theme` attribute, it has
 * no opinion on colors, so each page can define a fully independent scheme.
 */
:root {
  --bg: #99D4F1;
  --panel: #FFFFFF;
  --panel-border: #000000;
  --text: #000000;
  --text-dim: #4D4D4D;
  --accent: #249EDC;
  --accent-dim: #99D4F1;
  /* Plot line colors, one per data series (see plot.js / nasa-torque-app.js).
     Kept as tokens so a series keeps its identity across the two themes. */
  --series-1: #0F6FB8;
  --series-2: #C4471C;
  --series-3: #1D7A4D;
  --series-4: #7B3FA0;
  --series-5: #A87400;
  --plot-grid: #D7DEE3;
  /* Fills for the bolt size estimation table: the header rows, the recommended
     cell, and the header of a property class that has no size to recommend. */
  --est-head-bg: #E7EEF3;
  --pick-bg: #C2E6C7;
  --pick-text: #0E3D19;
  --fail-bg: #F2C4C0;
  --fail-text: #5C1512;
  --min-bg: #F5E4A3;
  --min-text: #4A3A00;
}

:root[data-theme="dark"] {
  --bg: #0B1620;
  --panel: #16232E;
  --panel-border: #3E5566;
  --text: #E8F1F5;
  --text-dim: #8DA3AF;
  --accent: #4FC3F7;
  --accent-dim: #1F3A47;
  --series-1: #56B6F2;
  --series-2: #FF8F5E;
  --series-3: #56CE92;
  --series-4: #C48CE6;
  --series-5: #E0BE55;
  --plot-grid: #2C3F4D;
  --est-head-bg: #1E2E3B;
  --pick-bg: #1F4B2C;
  --pick-text: #D6F2DC;
  --fail-bg: #5A211D;
  --fail-text: #F6D5D2;
  --min-bg: #4A3B12;
  --min-text: #F2E4B8;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  background: var(--bg);
  color: var(--text);
}

header {
  position: relative;
  padding: 0.75rem 1.5rem;
  text-align: center;
}

header h1 {
  margin: 0;
  font-size: 1.75rem;
}

header p {
  margin: 0;
  color: var(--text-dim);
}

/* --- Dark mode toggle --- */

.theme-toggle-wrap {
  position: absolute;
  top: 50%;
  right: 1.5rem;
  transform: translateY(-50%);
}

.theme-switch {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  cursor: pointer;
}

.theme-switch-icon {
  font-size: 0.9rem;
  line-height: 1;
  color: var(--text-dim);
}

.theme-switch input {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
}

.theme-switch-track {
  display: flex;
  align-items: center;
  width: 44px;
  height: 24px;
  padding: 2px;
  background: var(--panel);
  border: 1px solid var(--panel-border);
  box-sizing: border-box;
}

.theme-switch-thumb {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  background: var(--accent);
}

.theme-switch.interacted .theme-switch-thumb {
  transition: transform 0.15s ease;
}

.theme-switch input:checked + .theme-switch-track .theme-switch-thumb {
  transform: translateX(20px);
}

.theme-switch input:focus-visible + .theme-switch-track {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

main {
  max-width: 900px;
  margin: 0 auto;
  padding: 1.5rem;
}

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

/* --- Navigation --- */

/* Two stacked bars, both built by tab-nav.js and styled identically:
   .category-nav on top (top-level categories, as buttons — selecting one only
   swaps which tabs the lower bar shows) and .tab-nav below (the pages of the
   selected category, as real links). The wrapper carries the bleed out to the
   card edges so the bars sit flush with each other and with the card. */
.site-nav {
  margin: -1.5rem -1.5rem 1.5rem;
}

.category-nav,
.tab-nav {
  border-bottom: 1px solid var(--panel-border);
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
}

.category-nav ul,
.tab-nav ul {
  display: flex;
  list-style: none;
  margin: 0;
  padding: 0;
}

.category-nav li,
.tab-nav li {
  flex: 1 1 0;
  min-width: max-content;
  position: relative;
}

.category-nav li + li::before,
.tab-nav li + li::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: -1px;
  left: 0;
  width: 1px;
  background: var(--panel-border);
}

.category-nav-link,
.tab-nav-link {
  display: block;
  width: 100%;
  padding: 0.55rem 1rem;
  box-shadow: inset 0 2px 0 0 transparent;
  color: var(--text-dim);
  font-size: 0.9rem;
  font-weight: 700;
  text-decoration: none;
  text-align: center;
  white-space: nowrap;
}

/* Categories are <button>s, so the UA button styling has to be stripped for
   them to match the <a>s in the lower bar. */
.category-nav-link {
  background: none;
  border: 0;
  border-radius: 0;
  font-family: inherit;
  cursor: pointer;
}

.category-nav li:first-child .category-nav-link,
.tab-nav li:first-child .tab-nav-link {
  padding-left: 1.5rem;
}

.category-nav li:last-child .category-nav-link,
.tab-nav li:last-child .tab-nav-link {
  padding-right: 1.5rem;
}

.category-nav-link:hover,
.tab-nav-link:hover {
  color: var(--text);
}

.category-nav-link[aria-selected="true"],
.tab-nav-link[aria-current="page"] {
  color: var(--accent);
  box-shadow: inset 0 2px 0 0 var(--accent);
}

.category-nav-link:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

.placeholder-text {
  color: var(--text-dim);
  text-align: center;
  padding: 2rem 0;
}

.not-found-gif-link {
  display: block;
  width: max-content;
  max-width: 100%;
  margin: 0 auto 1rem;
  cursor: pointer;
}

.not-found-gif {
  display: block;
  max-width: 100%;
}

.chart-card h2 {
  margin: 0;
  font-size: 1.15rem;
}

.chart-card-header h3 {
  margin: 0;
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--text-dim);
}

.chart-card-header {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin-bottom: 1.25rem;
}

.chart-card-header h2 {
  text-align: center;
}

.chart-card-subheader {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem 1rem;
  /* Matches .flowchart-collapse-toggle's rendered height, so the row is the
     same height whether or not a page has the button. */
  min-height: 1.75rem;
}

.chart-card-subheader .flowchart-collapse-toggle {
  margin-left: auto;
}

.detail-toggle {
  display: flex;
  align-items: center;
  flex: 0 0 auto;
  gap: 0.4rem;
  margin-top: 0.5rem;
  font-size: 0.85rem;
  color: var(--text-dim);
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}

.detail-toggle input {
  width: 1rem;
  height: 1rem;
  margin: 0;
  accent-color: var(--accent);
  cursor: pointer;
}

.chart-layout {
  display: flex;
  flex-direction: column;
  gap: 2rem;
}

.chart-row {
  display: flex;
  gap: 2rem;
  align-items: center;
  flex-wrap: wrap;
  justify-content: center;
}

.spec-group {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  scroll-margin-top: 6rem;
}

.spec-group[hidden] {
  display: none;
}

.spec-group:not([hidden]) + .spec-group {
  border-top: 1px solid var(--panel-border);
  margin-left: -1.5rem;
  margin-right: -1.5rem;
  padding-left: 1.5rem;
  padding-right: 1.5rem;
  padding-top: 2rem;
}

/* Full-bleed rule closing off the card header from the first spec-group,
   matching the 1px lines drawn between the groups below it. */
.chart-card-rule {
  border: 0;
  border-top: 1px solid var(--panel-border);
  margin: 0.75rem -1.5rem 0;
}

.spec-group-title {
  margin: 0;
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--text-dim);
  text-align: center;
}

.flowchart-collapse-toggle {
  flex: 0 0 auto;
  padding: 0.3rem 0.6rem;
  font-size: 0.8rem;
  font-family: inherit;
  color: var(--text-dim);
  background: var(--panel);
  border: 1px solid var(--panel-border);
  border-radius: 0;
  cursor: pointer;
}

.flowchart-collapse-toggle:hover {
  color: var(--text);
  border-color: var(--accent);
}

.flowchart {
  padding: 1.25rem;
  background: var(--accent-dim);
  border: 1px solid var(--panel-border);
  color: var(--text);
  font-size: 0.85rem;
  overflow-x: auto;
}

/* --- Flowchart component (flowchart.js) --- */
/*
 * Rendered as a top-down tree: each <ul> is a flex row of one node's
 * children (<li>), fanning out left/right beneath it. A child <li>'s
 * ::before/::after draw its half of the horizontal crossbar connecting it
 * to its siblings, plus (via ::after's border-left) the vertical stem
 * dropping into the node itself — centered under that one child, not under
 * the row as a whole, so it still lands correctly even when siblings' own
 * subtrees are very different widths. The short .fc-decision-stub tail
 * (real DOM element, not a pseudo-element) is the only thing bridging a
 * parent's diamond down to that crossbar; there's deliberately no separate
 * "trunk" — a second line drawn there would either double up on the stub or,
 * once the two are centered on different things (the stub on one diamond,
 * a trunk on an entire uneven row), drift out of alignment with it. Because
 * each <li> shrinks to fit its content (align-items: center on a column
 * flex parent, rather than stretch), every level re-centers itself under
 * its parent automatically.
 */

.fc-title {
  margin: 0 0 1rem;
  font-weight: 700;
  text-align: center;
}

.fc-forest {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2.5rem;
}

.fc-tree,
.fc-tree ul {
  display: flex;
  list-style: none;
  margin: 0;
  padding: 0;
  justify-content: center;
}

/* Centered via auto margins (not the parent's align-items) so that when the
   tree is wider than the .flowchart viewport, the margins clamp to 0 and the
   tree flushes left instead of overflowing equally on both sides — flexbox's
   centering via align-items/justify-content spills hidden, unscrollable
   overflow off the start edge, but auto-margin centering can't go negative,
   so all the extra width ends up on the right where overflow-x:auto can
   actually reach it. */
.fc-tree {
  width: fit-content;
  margin-left: auto;
  margin-right: auto;
}

.fc-tree li {
  display: flex;
  flex-direction: column;
  align-items: center;
  position: relative;
  padding: 1.7rem 0.6rem 0;
}

/* The root node has no incoming branch, so it gets no connector at all. */
.fc-tree > li {
  padding-top: 0;
}

/* Left half of the crossbar connecting this node to its previous sibling. */
.fc-tree li::before {
  content: "";
  position: absolute;
  top: 0;
  right: 50%;
  width: 50%;
  height: 1.7rem;
  border-top: 1px solid var(--panel-border);
}

/* Right half of the crossbar, plus the vertical stem down into this node. */
.fc-tree li::after {
  content: "";
  position: absolute;
  top: 0;
  left: 50%;
  width: 50%;
  height: 1.7rem;
  border-top: 1px solid var(--panel-border);
  border-left: 1px solid var(--panel-border);
}

.fc-tree li:first-child::before {
  border-top: none;
}

.fc-tree li:last-child::after {
  border-top: none;
}

.fc-tree li:only-child::before,
.fc-tree li:only-child::after {
  border-top: none;
}

/* The root node has no incoming branch, so it gets no connector of its own —
   this has to come after the generic li::before/::after rules above (same
   specificity), otherwise those win the cascade by being declared later and
   the root ends up with a stray stem line drawn through its own diamond. */
.fc-tree > li::before,
.fc-tree > li::after {
  content: none;
}

/* Sits right where a branch leaves its parent diamond, breaking the line
   behind it so the answer reads as belonging to that specific arrow. */
.fc-edge-label {
  position: absolute;
  top: 0;
  left: 50%;
  transform: translate(-50%, -50%);
  background: var(--accent-dim);
  padding: 0.1rem 0.4rem;
  font-size: 0.7rem;
  font-weight: 700;
  color: var(--text-dim);
  white-space: nowrap;
  z-index: 1;
}

.fc-node {
  font-weight: 700;
}

.fc-node-labelwrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.3rem;
}

.fc-node-sublabel {
  font-size: 0.7rem;
  font-weight: 400;
  font-style: italic;
  color: var(--text-dim);
  text-align: center;
}

/* Diamond shape: an outer rhombus in the border color with an inner
   rhombus (inset by the border thickness) filled in the panel color,
   stacked to fake a diamond outline — clip-path can't render a real
   border along its own clipped edge. The inset must be a percentage,
   not a fixed px: it shrinks the inner rhombus proportionally on both
   axes, which is what keeps the border's perpendicular thickness equal
   on all four edges even though the diamond itself is wider than it is
   tall. A px inset shrinks both axes by the same absolute amount
   instead, which distorts the aspect ratio and makes the border look
   thicker at the top/bottom points than along the sides. */
.fc-decision {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 5.5rem;
  min-height: 3.6rem;
  padding: 1.5rem 1.9rem;
  background: var(--panel-border);
  clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
}

.fc-decision::before {
  content: "";
  position: absolute;
  inset: 2%;
  background: var(--panel);
  clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
}

.fc-decision--root {
  background: var(--accent);
}

.fc-decision-label {
  position: relative;
  z-index: 1;
  max-width: 8rem;
  font-size: 0.85rem;
  color: var(--text);
  text-align: center;
}

.fc-decision--root .fc-decision-label {
  font-size: 0.95rem;
}

.fc-decision-stub {
  display: block;
  width: 0;
  height: calc(0.8rem);
  border-left: 1px solid var(--panel-border);
}

.fc-result {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.1rem 0.5rem;
  padding: 0.3rem 0.6rem;
  background: var(--panel);
  border: 1px solid var(--panel-border);
  color: var(--text);
  text-decoration: none;
}

a.fc-result:hover {
  border-color: var(--accent);
}

a.fc-result .fc-result-label {
  color: var(--accent);
}

.fc-result-label {
  font-weight: 700;
  font-size: 0.9em;
}

.fc-result-note {
  color: var(--text-dim);
  font-weight: 400;
  font-size: 0.85em;
}

.fc-footnote {
  margin-left: -0.35rem;
  color: var(--accent);
  text-decoration: none;
  font-weight: 700;
}

.fc-result-meta {
  font-size: 0.7rem;
  font-weight: 400;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.fc-variant {
  display: flex;
  flex-direction: column;
  flex-basis: 100%;
  align-items: flex-start;
  gap: 0.1rem;
  margin-top: 0.15rem;
  padding-top: 0.3rem;
  border-top: 1px solid var(--panel-border);
}

.flowchart-disclaimer {
  margin: 0.5rem 0 0;
  color: var(--text-dim);
  font-size: 0.75rem;
  font-style: italic;
}

.flowchart-disclaimer:target {
  animation: flowchart-target-highlight 2s ease-out;
}

/* Clicking a result link in a flowchart jumps to the spec-group it points
   to; this flashes that group's title the same way a footnote jump flashes
   the disclaimer above, so the destination is obvious either way. The
   :target match lands on .spec-group (the id is on the container, not the
   heading), so the flash is applied to the descendant title instead. */
.spec-group:target .spec-group-title {
  animation: flowchart-target-highlight 2s ease-out;
}

@keyframes flowchart-target-highlight {
  from {
    background: var(--accent-dim);
    outline: 2px solid var(--accent);
  }
  to {
    background: transparent;
    outline-color: transparent;
  }
}

/* --- Size slider --- */

.slider-sticky {
  position: sticky;
  top: 0;
  z-index: 10;
  background: var(--panel);
  margin: 0 -1.5rem;
  padding: 0.75rem 1.5rem;
  border-bottom: 1px solid var(--panel-border);
}

.slider-block {
  display: flex;
  flex-direction: row;
  align-items: flex-start;
  gap: 1rem;
  user-select: none;
  width: 100%;
  max-width: 34rem;
  margin: 0 auto;
}

.size-readout {
  flex: 0 0 auto;
  width: 3.5rem;
  margin-top: 0.5rem;
  white-space: nowrap;
  font-size: 1.4rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--accent);
}

.slider-track-wrap {
  position: relative;
  flex: 1 1 auto;
  min-width: 0;
  width: 100%;
  padding-top: 0.5rem;
}

.size-slider {
  --thumb-width: 30px;
  -webkit-appearance: none;
  appearance: none;
  position: relative;
  z-index: 2;
  width: 100%;
  margin: 0;
  background: transparent;
  cursor: grab;
  touch-action: none;
}

.size-slider:active {
  cursor: grabbing;
}

.size-slider:focus-visible {
  outline: none;
}

/* Track */
.size-slider::-webkit-slider-runnable-track {
  height: 6px;
  background: var(--text);
}

.size-slider::-moz-range-track {
  height: 6px;
  background: var(--text);
}

/* Thumb */
.size-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: var(--thumb-width);
  height: 34px;
  margin-top: -14px;
  background: var(--accent);
  border: 1px solid var(--panel-border);
  border-radius: 0;
}

.size-slider::-moz-range-thumb {
  width: var(--thumb-width);
  height: 34px;
  background: var(--accent);
  border: 1px solid var(--panel-border);
  border-radius: 0;
}

.size-slider:focus-visible::-webkit-slider-thumb {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.size-slider:focus-visible::-moz-range-thumb {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.slider-ticks {
  position: relative;
  z-index: 1;
  height: 8px;
  margin-top: 2px;
}

.slider-tick {
  position: absolute;
  top: 0;
  width: 1px;
  height: 6px;
  background: var(--text-dim);
  transform: translateX(-0.5px);
}

.slider-endpoints {
  display: flex;
  justify-content: space-between;
  margin-top: 0.25rem;
  font-size: 0.75rem;
  color: var(--text-dim);
}

/* --- Plot (see plot.js for the renderer this styles) --- */

.plot {
  position: relative;
  width: 100%;
  /* The tooltip is positioned against this box, and the renderer measures
     clientWidth off it on every draw. */
}

.plot-svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
  touch-action: pan-y;
}

.plot-grid line {
  stroke: var(--plot-grid);
  stroke-width: 1;
}

.plot-grid-minor line {
  opacity: 0.5;
}

.plot-axis line {
  stroke: var(--text);
  stroke-width: 1;
}

.plot-tick-label text {
  fill: var(--text-dim);
  font-size: 0.7rem;
}

.plot-axis-title text {
  fill: var(--text);
  font-size: 0.75rem;
  font-weight: 600;
}

.plot-line {
  fill: none;
  stroke-width: 2;
  stroke-linejoin: miter;
  stroke-linecap: butt;
}

.plot-marker {
  stroke: var(--panel);
  stroke-width: 1;
}

.plot-marker.is-active {
  r: 5.5;
  stroke: var(--text);
}

.plot-overlay {
  cursor: crosshair;
}

/* The legend doubles as the plot's series control when the page passes
   legendItems with an onToggle (see plot.js): each row is then a real
   checkbox + swatch + label, and a row switched off — or one the data has
   nothing to draw for — stays listed so it can be switched back on. */
.plot-legend {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.35rem 1.25rem;
  margin-top: 0.75rem;
  font-size: 0.8rem;
  color: var(--text);
}

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

.plot-legend-item--toggle {
  cursor: pointer;
  user-select: none;
}

.plot-legend-item--toggle input {
  width: 1rem;
  height: 1rem;
  margin: 0;
  accent-color: var(--accent);
  cursor: pointer;
}

/* Switched off: the swatch keeps its color (that's the row's identity — it's
   what the line will be when it comes back), the text recedes. */
.plot-legend-item.is-off .plot-legend-label {
  color: var(--text-dim);
}

.plot-legend-item.is-off .plot-legend-swatch {
  opacity: 0.45;
}

.plot-legend-note {
  font-size: 0.75rem;
  font-style: italic;
  color: var(--text-dim);
}

.plot-legend-item.is-noted .plot-legend-label {
  color: var(--text-dim);
}

.plot-legend-swatch {
  flex: 0 0 auto;
  width: 0.85rem;
  height: 0.5rem;
  border: 1px solid var(--panel-border);
}

.plot-tooltip {
  position: absolute;
  z-index: 5;
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  padding: 0.4rem 0.55rem;
  background: var(--panel);
  border: 1px solid var(--panel-border);
  font-size: 0.75rem;
  line-height: 1.35;
  color: var(--text-dim);
  white-space: nowrap;
  pointer-events: none;
}

.plot-tooltip[hidden] {
  /* The display:flex above would otherwise beat the UA's [hidden] rule. */
  display: none;
}

.plot-tooltip-title {
  color: var(--text);
}

.plot-empty {
  margin: 0;
  padding: 3rem 1rem;
  text-align: center;
  color: var(--text-dim);
  border: 1px dashed var(--panel-border);
}

.plot-note {
  margin: 0.75rem 0 0;
  font-size: 0.75rem;
  line-height: 1.5;
  color: var(--text-dim);
}

.plot-note h4 {
  margin: 1rem 0 0.35rem;
  font-size: 0.8rem;
  color: var(--text);
}

.plot-note h4:first-child {
  margin-top: 0;
}

.plot-note ul {
  margin: 0;
  padding-left: 1.1rem;
  list-style: square;
}

.plot-note li {
  margin: 0.2rem 0;
}

.plot-note li ul {
  margin-top: 0.2rem;
  list-style: none;
  padding-left: 1rem;
}

/* --- Plot controls --- */

.metric-toggle {
  display: flex;
  justify-content: center;
  margin-bottom: 0.75rem;
}

.metric-option {
  padding: 0.3rem 0.85rem;
  background: var(--panel);
  border: 1px solid var(--panel-border);
  font: inherit;
  font-size: 0.8rem;
  color: var(--text);
  cursor: pointer;
}

.metric-option + .metric-option {
  border-left: none;
}

.metric-option:hover {
  background: var(--accent-dim);
}

.metric-option.is-active {
  background: var(--accent);
  color: var(--panel);
}

@media (max-width: 600px) {
  header {
    padding: 0.5rem 1rem;
  }

  .theme-toggle-wrap {
    right: 1rem;
  }

  main {
    padding: 1.5rem 0.75rem;
  }

  .chart-card {
    padding: 1rem 0.75rem;
  }

  .site-nav {
    margin: -1rem -0.75rem 1rem;
  }

  .category-nav li:first-child .category-nav-link,
  .tab-nav li:first-child .tab-nav-link {
    padding-left: 0.75rem;
  }

  .category-nav li:last-child .category-nav-link,
  .tab-nav li:last-child .tab-nav-link {
    padding-right: 0.75rem;
  }

  .spec-group:not([hidden]) + .spec-group {
    margin-left: -0.75rem;
    margin-right: -0.75rem;
    padding-left: 0.75rem;
    padding-right: 0.75rem;
  }

  .chart-card-rule {
    margin-left: -0.75rem;
    margin-right: -0.75rem;
  }

  .slider-sticky {
    margin: 0 -0.75rem;
    padding: 0.5rem 0.75rem;
  }

  .slider-block {
    gap: 0.5rem;
  }

  .size-readout {
    margin-top: 0.55rem;
    font-size: 1.1rem;
  }

  .detail-toggle {
    flex-direction: column;
    gap: 0.15rem;
    margin-top: 0.5rem;
    font-size: 0.65rem;
    line-height: 1.1;
    text-align: center;
  }

  .detail-toggle input {
    width: 0.8rem;
    height: 0.8rem;
  }

  .flowchart {
    padding: 1rem 0.75rem;
    font-size: 0.8rem;
  }

  .fc-tree li {
    padding: 1.3rem 0.4rem 0;
  }

  .fc-tree > li {
    padding-top: 0;
  }

  .fc-tree li::before,
  .fc-tree li::after {
    height: 1.3rem;
  }

  .fc-decision-stub {
    height: 0.4rem;
  }

  .fc-decision {
    min-width: 4.5rem;
    min-height: 3rem;
    padding: 1.1rem 1.3rem;
  }

  .fc-decision-label {
    max-width: 6rem;
    font-size: 0.78rem;
  }

  .plot-tick-label text {
    font-size: 0.65rem;
  }

  .plot-legend {
    gap: 0.35rem 0.9rem;
    font-size: 0.75rem;
  }

  .plot-legend-note {
    font-size: 0.7rem;
  }

  .plot-note {
    font-size: 0.7rem;
  }

}

/* --- Diagram panel --- */

.diagram-panel {
  flex: 1;
  min-width: 220px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.diagram-image {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--panel-border);
}

.diagram-image--sm {
  width: 75%;
}

:root[data-theme="dark"] .diagram-image {
  filter: invert(1);
}

/* --- Side spec panel --- */

.spec-panel {
  flex: 1;
  min-width: 220px;
}

.spec-panel-stack {
  display: grid;
  overflow-x: auto;
}

.spec-panel-stack > table {
  grid-area: 1 / 1;
}

.spec-panel-stack > table.spec-hidden {
  visibility: hidden;
}

.spec-panel table {
  width: 100%;
  border-collapse: collapse;
}

.spec-panel caption {
  text-align: left;
  font-weight: 700;
  font-size: 1.1rem;
  margin-bottom: 0.5rem;
  color: var(--accent);
}

.spec-panel td {
  padding: 0.5rem 0.25rem;
  border-bottom: 1px solid var(--panel-border);
}

.spec-panel td:first-child {
  color: var(--text-dim);
}

.spec-panel td:last-child {
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.sub-value {
  display: flex;
  justify-content: flex-end;
  gap: 0.75rem;
}

.sub-value + .sub-value {
  margin-top: 0.15rem;
}

.sub-label {
  color: var(--text-dim);
  font-size: 0.85em;
  white-space: nowrap;
  flex-shrink: 0;
  text-align: right;
}

.sub-label-bold {
  color: var(--text);
  font-weight: 700;
}

.sub-num {
  white-space: nowrap;
  flex-shrink: 0;
  text-align: right;
}

/* --- Valid length chart --- */

.length-chart {
  overflow-x: auto;
}

.length-table {
  border-collapse: collapse;
  margin: 0 auto;
  font-size: 0.85rem;
}

.length-table td {
  border: 1px solid var(--panel-border);
  padding: 0.3rem 0.4rem;
  text-align: center;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.length-row-label {
  text-align: left;
  color: var(--text-dim);
  padding-right: 0.5rem;
}

.length-empty-msg {
  color: var(--text-dim);
  font-style: italic;
  white-space: normal;
  min-width: 12rem;
}

/* --- Bolt size estimation --- */

.est-force-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
}

.est-force-input {
  width: 10rem;
  padding: 0.45rem 0.6rem;
  background: var(--panel);
  border: 1px solid var(--panel-border);
  border-radius: 0;
  color: var(--text);
  font: inherit;
  font-variant-numeric: tabular-nums;
  text-align: right;
  /* Drop the number input's spinners — stepping a bolt load one newton at a
     time is useless, and the arrows only eat width. The input stays
     type="number" for the numeric keypad and for validation. */
  appearance: textfield;
  -moz-appearance: textfield;
}

.est-force-input::-webkit-outer-spin-button,
.est-force-input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

.est-force-input:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

.est-force-unit {
  color: var(--text-dim);
}

.est-force-clear {
  padding: 0.45rem 0.7rem;
  background: var(--panel);
  border: 1px solid var(--panel-border);
  border-radius: 0;
  color: var(--text-dim);
  font: inherit;
  font-size: 0.8rem;
  cursor: pointer;
}

.est-force-clear:hover {
  border-color: var(--accent);
  color: var(--text);
}

.est-force-clear:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

/* Reference-only "Show UTS Load" toggle above the table. */
.est-toggle-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0.35rem 1.1rem;
  margin-bottom: 0.4rem;
}

.est-uts-toggle {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.35rem;
  color: var(--text-dim);
  font-size: 0.8rem;
  cursor: pointer;
  user-select: none;
}

.est-uts-toggle input {
  width: 1rem;
  height: 1rem;
  margin: 0;
  accent-color: var(--accent);
  cursor: pointer;
}

/* The minimum ultimate tensile load, shown under the proof load when the
   toggle is on. Dimmed via opacity so it reads as secondary on any cell
   background, including the highlighted pick. */
.est-cell-uts {
  display: block;
  font-size: 0.72rem;
  opacity: 0.7;
}

/* The selected load condition / tightening method, echoed in the heading
   above each picker. */
.est-selected {
  color: var(--accent);
}

.est-case-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.5rem;
}

/* Fixed basis with no grow: the buttons keep one size at every width, so a
   row that wraps leaves a gap rather than stretching whichever button lands
   on the last row. */
.est-case {
  flex: 0 1 8.5rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.35rem;
  padding: 0.5rem 0.4rem;
  background: var(--panel);
  border: 1px solid var(--panel-border);
  border-radius: 0;
  color: var(--text-dim);
  font: inherit;
  font-size: 0.75rem;
  text-align: center;
  cursor: pointer;
}

.est-method-list {
  display: flex;
  flex-direction: column;
}

.est-method {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.45rem 0.7rem;
  background: var(--panel);
  border: 1px solid var(--panel-border);
  border-radius: 0;
  color: var(--text-dim);
  font: inherit;
  font-size: 0.8rem;
  text-align: left;
  cursor: pointer;
}

/* The list is a single stack of boxes, so only the first one draws a top
   edge — the rest share their neighbour's. */
.est-method + .est-method {
  border-top: none;
}

.est-case:hover,
.est-method:hover {
  border-color: var(--accent);
  color: var(--text);
}

.est-case.is-active,
.est-method.is-active {
  border-color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent);
  color: var(--text);
}

.est-case:focus-visible,
.est-method:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

.est-case-img {
  display: block;
  width: 100%;
  height: auto;
}

:root[data-theme="dark"] .est-case-img {
  filter: invert(1);
}

.est-case-caption {
  font-weight: 700;
}

.est-steps-badge {
  color: var(--text-dim);
  font-size: 0.7rem;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.est-steps-note {
  margin: 0;
  text-align: center;
  color: var(--text-dim);
  font-size: 0.8rem;
}

.est-table-wrap {
  overflow-x: auto;
}

.est-table {
  border-collapse: collapse;
  margin: 0 auto;
  font-size: 0.85rem;
}

.est-table th,
.est-table td {
  border: 1px solid var(--panel-border);
  padding: 0.35rem 0.6rem;
  text-align: right;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.est-table th {
  color: var(--text-dim);
  font-weight: 700;
  text-align: center;
}

/* Both header rows get a light fill so they read as the header block. An
   unsupported class keeps its own (heavier) header fill — see below. */
.est-table thead th {
  background: var(--est-head-bg);
}

/* Heavier vertical rule splitting the "Thread" columns (Size, Pitch) from the
   "Strength Class" columns, carried all the way down the table. */
.est-table .est-col-divide {
  border-right-width: 2px;
}

.est-table .est-row-label {
  text-align: left;
  color: var(--text-dim);
}

/* The row label is a merged Size cell plus a per-row Pitch cell, with a
   heavier rule starting each size group. "Include Fine Pitches" adds the
   fine-thread rows a size spans; with it off every size is a lone coarse row. */
.est-table .est-row-size {
  vertical-align: middle;
  font-weight: 700;
  color: var(--text);
}

.est-table .est-row-pitch {
  text-align: right;
  color: var(--text-dim);
}

.est-table tbody tr.est-group-start > td {
  border-top-width: 2px;
}

/* Smallest size that carries the load, and the estimate the steps land on —
   both bold, since both are answers the table is pointing at. The bare
   minimum is filled yellow; where the steps land on that same cell the
   green pick fill wins (rule below, same specificity, later). The legend
   swatch needs the same fill, hence the second selector. */
.est-cell--min,
.est-legend-swatch.est-cell--min {
  background: var(--min-bg);
  color: var(--min-text);
  font-weight: 700;
}

.est-cell--pick {
  background: var(--pick-bg);
  color: var(--pick-text);
  font-weight: 700;
}

/* A property class with no size to recommend: either nothing in it carries
   the load, or the steps run off the bottom of it. Marked on the column
   header, since there's no cell in the column to point at. The legend swatch
   needs the same fill, hence the two selectors. */
.est-table th.est-col--unsupported,
.est-legend-swatch.est-col--unsupported {
  background: var(--fail-bg);
  color: var(--fail-text);
}

.est-legend {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.35rem 1.25rem;
  margin: 0;
  color: var(--text-dim);
  font-size: 0.8rem;
}

.est-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
}

.est-legend-swatch {
  display: inline-block;
  width: 0.9rem;
  height: 0.9rem;
  border: 1px solid var(--panel-border);
}

/* Sample cell in the legend, naming the two stacked values when the UTS load
   is shown. Matches a real cell's border, padding, alignment and font size,
   and reuses .est-cell-uts for its second line. */
.est-legend-cell {
  display: inline-block;
  padding: 0.35rem 0.6rem;
  border: 1px solid var(--panel-border);
  color: var(--text);
  font-size: 0.85rem;
  text-align: right;
  line-height: 1.25;
}

.est-message {
  margin: 0;
  text-align: center;
  color: var(--text-dim);
  font-size: 0.8rem;
  font-style: italic;
}

.est-message:empty {
  display: none;
}

.est-grade-preset {
  display: block;
  margin: 0 auto 0.75rem;
  padding: 0.4rem 0.8rem;
  background: var(--panel);
  border: 1px solid var(--panel-border);
  color: var(--text-dim);
  font: inherit;
  font-size: 0.85rem;
  cursor: pointer;
}

.est-grade-preset:hover {
  border-color: var(--accent);
  color: var(--text);
}

.est-grade-preset:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

.est-grades {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.4rem 1.1rem;
}

.est-grade-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  color: var(--text-dim);
  font-size: 0.85rem;
  cursor: pointer;
  user-select: none;
}

.est-grade-toggle input {
  width: 1rem;
  height: 1rem;
  margin: 0;
  accent-color: var(--accent);
  cursor: pointer;
}

/* The everyday high-strength classes (8.8, 10.9, 12.9), drawn bold so they
   stand out in the column picker. */
.est-grade-toggle--strong {
  font-weight: 700;
  color: var(--text);
}

/* This section's own mobile block. It can't live in the shared one further up
   the file — that block comes before these rules, so at equal specificity the
   base rules above would win and the overrides would do nothing. */
@media (max-width: 600px) {
  .est-case-row {
    gap: 0.35rem;
  }

  .est-case {
    flex-basis: 5.5rem;
    font-size: 0.68rem;
  }

  .est-method {
    font-size: 0.75rem;
  }

  .est-table {
    font-size: 0.78rem;
  }

  .est-table th,
  .est-table td,
  .est-legend-cell {
    padding: 0.3rem 0.4rem;
  }

  .est-legend-cell {
    font-size: 0.78rem;
  }
}

footer {
  text-align: center;
  color: var(--text-dim);
  font-size: 0.8rem;
  padding: 2rem 1rem;
}

footer p {
  margin: 0.3rem 0;
}

footer a {
  text-decoration: none;
}
