/* FastTool tool-page components, 2026-11-06.
   For new tool pages built from work/shell/tool-template.html (body.ft-page). Load after
   /css/ft-shell-20261106.css, which defines every --ft-* token used here.
   Builder's manual: work/shell/STYLEGUIDE.md */

/* 1. Page structure --------------------------------------------------------------------- */
.ft-main { display: block; padding-bottom: var(--ft-space-8); }
.ft-toolhead { padding-block: var(--ft-space-6) var(--ft-space-5); max-width: 52rem; }
.ft-toolhead__title {
  margin: 0;
  color: var(--ft-ink);
  font-size: var(--ft-text-h1);
  font-weight: 750;
  line-height: 1.12;
  letter-spacing: -0.015em;
}
.ft-toolhead__outcome { margin: var(--ft-space-3) 0 0; color: var(--ft-ink-2); font-size: var(--ft-text-lg); line-height: 1.5; }
.ft-privacy {
  display: inline-flex;
  align-items: center;
  gap: var(--ft-space-2);
  margin: var(--ft-space-3) 0 0;
  color: var(--ft-ink-2);
  font-size: var(--ft-text-sm);
  font-weight: 500;
}
.ft-privacy__icon { flex: none; width: 1.125rem; height: 1.125rem; fill: none; stroke: var(--ft-accent); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }

.ft-tool { display: block; margin-top: var(--ft-space-2); scroll-margin-top: var(--ft-space-4); }
.ft-section { margin-top: var(--ft-space-8); scroll-margin-top: var(--ft-space-4); }
.ft-section__title { margin: 0 0 var(--ft-space-4); color: var(--ft-ink); font-size: var(--ft-text-2xl); font-weight: 700; line-height: 1.2; letter-spacing: -0.01em; }
.ft-section__intro { margin: 0 0 var(--ft-space-4); max-width: var(--ft-measure); color: var(--ft-ink-2); }
.ft-updated { margin: var(--ft-space-7) 0 0; padding-top: var(--ft-space-4); border-top: 1px solid var(--ft-line); color: var(--ft-ink-3); font-size: var(--ft-text-sm); }

/* 2. Workspace layouts ----------------------------------------------------------------------
   Every one-column helper names its column minmax(0, 1fr): an implied "auto" column grows to the
   widest child's min-content width, so a chart, table, code line or long word would push the
   panel past the screen. Children of the wrapping rows may shrink for the same reason. */
.ft-workspace { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--ft-space-4); align-items: start; }
.ft-workspace > * { min-width: 0; }
@media (min-width: 56rem) {
  .ft-workspace--split { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); }
  .ft-workspace--split-even { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .ft-workspace--sidebar { grid-template-columns: minmax(16rem, 20rem) minmax(0, 1fr); }
}
.ft-workspace--wide { grid-template-columns: minmax(0, 1fr); }
.ft-sticky { position: sticky; top: var(--ft-space-4); }

.ft-panel {
  display: block;
  min-width: 0;
  padding: var(--ft-space-5);
  border: 1px solid var(--ft-line);
  border-radius: var(--ft-radius-l);
  background: var(--ft-surface);
  box-shadow: var(--ft-shadow);
}
.ft-panel--flat { box-shadow: none; }
.ft-panel--quiet { background: var(--ft-surface-2); box-shadow: none; }
.ft-panel__head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--ft-space-2) var(--ft-space-4); margin-bottom: var(--ft-space-4); }
.ft-panel__head > * { min-width: 0; }
.ft-panel__title { margin: 0; color: var(--ft-ink); font-size: var(--ft-text-lg); font-weight: 650; line-height: 1.3; }
.ft-panel__sub { margin: var(--ft-space-1) 0 0; color: var(--ft-ink-2); font-size: var(--ft-text-sm); }
.ft-stack { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--ft-space-4); }
.ft-stack--tight { gap: var(--ft-space-2); }
.ft-cluster { display: flex; flex-wrap: wrap; align-items: center; gap: var(--ft-space-2); }
.ft-cluster > * { min-width: 0; }
.ft-divider { height: 0; margin: var(--ft-space-5) 0; border: 0; border-top: 1px solid var(--ft-line); }
@media (max-width: 40rem) { .ft-panel { padding: var(--ft-space-4); } }

/* 3. Form controls ---------------------------------------------------------------------------- */
/* align-content: start keeps a field's rows their own height when a taller neighbour stretches the field
   (a long hint next door used to stretch the input). */
.ft-field { display: grid; grid-template-columns: minmax(0, 1fr); align-content: start; gap: var(--ft-space-1); min-width: 0; }
.ft-fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr)); gap: var(--ft-space-4); }
.ft-label { color: var(--ft-ink); font-size: var(--ft-text-sm); font-weight: 600; line-height: 1.35; }
.ft-label__opt { color: var(--ft-ink-3); font-weight: 400; }
.ft-hint { margin: 0; color: var(--ft-ink-2); font-size: var(--ft-text-xs); line-height: 1.45; }
.ft-error { display: flex; gap: var(--ft-space-1); margin: 0; color: var(--ft-bad); font-size: var(--ft-text-sm); font-weight: 600; }
.ft-error[hidden] { display: none; }

.ft-input, .ft-select, .ft-textarea {
  box-sizing: border-box;
  width: 100%;
  min-height: var(--ft-target);
  padding: 0.5rem 0.75rem;
  border: 1px solid var(--ft-line-strong);
  border-radius: var(--ft-radius);
  background: var(--ft-surface);
  color: var(--ft-ink);
  font: inherit;
  font-size: var(--ft-text-md);
  line-height: 1.4;
}
.ft-input::placeholder, .ft-textarea::placeholder { color: var(--ft-ink-3); opacity: 1; }
.ft-input:hover, .ft-select:hover, .ft-textarea:hover { border-color: var(--ft-ink-2); }
.ft-input:focus-visible, .ft-select:focus-visible, .ft-textarea:focus-visible { outline: 3px solid var(--ft-focus); outline-offset: 1px; border-color: var(--ft-focus); }
.ft-input[aria-invalid="true"], .ft-select[aria-invalid="true"], .ft-textarea[aria-invalid="true"] { border-color: var(--ft-bad); border-width: 2px; }
.ft-input:disabled, .ft-select:disabled, .ft-textarea:disabled { opacity: 0.6; cursor: not-allowed; }
.ft-input--num { font-variant-numeric: tabular-nums; }
.ft-textarea { min-height: 8rem; resize: vertical; font-family: var(--ft-font-mono); font-size: var(--ft-text-sm); line-height: 1.5; }
.ft-select {
  appearance: none;
  padding-right: 2.25rem;
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%), linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: right 1.05rem center, right 0.7rem center;
  background-size: 0.35rem 0.35rem, 0.35rem 0.35rem;
  background-repeat: no-repeat;
}

/* Hint and error in one place: <div class="ft-fieldmsg"><p class="ft-hint">…</p><p class="ft-error" hidden>…</p></div>
   Both lie in the same grid cell, so the row is as tall as the taller text from the start and nothing below moves
   when the error takes the hint's place (drop the error's `hidden` as usual; the hint steps back by itself). */
.ft-fieldmsg { display: grid; grid-template-columns: minmax(0, 1fr); }
.ft-fieldmsg > .ft-hint, .ft-fieldmsg > .ft-error { grid-area: 1 / 1; }
.ft-fieldmsg > .ft-error[hidden] { display: block !important; visibility: hidden; }
.ft-fieldmsg:has(> .ft-error:not([hidden])) > .ft-hint { visibility: hidden; }

/* Input with a unit: <div class="ft-inputgroup"><input class="ft-input"><span class="ft-inputgroup__unit">ms</span></div> */
.ft-inputgroup { display: flex; align-items: stretch; min-width: 0; }
.ft-inputgroup > .ft-input, .ft-inputgroup > .ft-select { flex: 1 1 auto; min-width: 0; border-top-right-radius: 0; border-bottom-right-radius: 0; }
.ft-inputgroup__unit {
  display: inline-flex;
  align-items: center;
  flex: none;
  padding: 0 0.75rem;
  border: 1px solid var(--ft-line-strong);
  border-left: 0;
  border-radius: 0 var(--ft-radius) var(--ft-radius) 0;
  /* background-color, not the shorthand: a unit picker (<select class="ft-select ft-inputgroup__unit">) keeps the arrow that .ft-select draws */
  background-color: var(--ft-surface-2);
  color: var(--ft-ink-2);
  font-size: var(--ft-text-sm);
  white-space: nowrap;
}
.ft-inputgroup > .ft-select.ft-inputgroup__unit { flex: 0 0 auto; width: auto; min-height: var(--ft-target); padding-right: 2rem; border-left: 0; border-radius: 0 var(--ft-radius) var(--ft-radius) 0; background-color: var(--ft-surface-2); }

/* Segmented control: a fieldset of radios. */
.ft-segmented { min-width: 0; margin: 0; padding: 0; border: 0; }
.ft-segmented__legend { margin-bottom: var(--ft-space-1); padding: 0; color: var(--ft-ink); font-size: var(--ft-text-sm); font-weight: 600; }
.ft-segmented__options {
  display: inline-flex;
  flex-wrap: wrap;
  max-width: 100%;
  padding: 3px;
  gap: 3px;
  border: 1px solid var(--ft-line-strong);
  border-radius: calc(var(--ft-radius) + 3px);
  background: var(--ft-surface-2);
}
.ft-segmented__option { position: relative; display: flex; }
.ft-segmented__option input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
.ft-segmented__option span {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: calc(var(--ft-target) - 8px);
  padding: 0 0.875rem;
  border-radius: var(--ft-radius);
  color: var(--ft-ink-2);
  font-size: var(--ft-text-sm);
  font-weight: 600;
  white-space: nowrap;
}
.ft-segmented__option input:checked + span { background: var(--ft-surface); color: var(--ft-ink); box-shadow: 0 0 0 1px var(--ft-line-strong), 0 1px 2px rgba(0, 0, 0, 0.08); }
.ft-segmented__option input:focus-visible + span { outline: 3px solid var(--ft-focus); outline-offset: 1px; }
.ft-segmented__option input:disabled + span { opacity: 0.55; }
/* Touch: the radio is the target. It reaches 4 px past its 36 px label above and below, to the edge of the
   44 px control, and every option is at least 44 px wide. Rows of a wrapped control sit 8 px apart so two
   targets never overlap. Nothing else changes size. */
@media (max-width: 40rem), (pointer: coarse) {
  .ft-segmented__options { row-gap: 8px; }
  .ft-segmented__option input { top: -4px; height: calc(100% + 8px); }
  .ft-segmented__option span { min-width: var(--ft-target); }
}

/* Slider with its value: <div class="ft-range"> label, <input type="range" class="ft-range__input">, <output class="ft-range__value"> */
.ft-range { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: var(--ft-space-1) var(--ft-space-3); }
.ft-range > .ft-label { grid-column: 1 / -1; }
.ft-range__input { width: 100%; min-height: var(--ft-target); margin: 0; accent-color: var(--ft-accent); background: transparent; cursor: pointer; }
.ft-range__input:focus-visible { outline: 3px solid var(--ft-focus); outline-offset: 2px; border-radius: var(--ft-radius-s); }
.ft-range__value { min-width: 4.5rem; color: var(--ft-ink); font-size: var(--ft-text-sm); font-weight: 650; font-variant-numeric: tabular-nums; text-align: right; }

/* Checkbox and switch */
.ft-check { display: inline-flex; align-items: center; gap: var(--ft-space-2); min-height: var(--ft-target); color: var(--ft-ink); font-size: var(--ft-text-sm); cursor: pointer; }
.ft-check input { flex: none; width: 1.25rem; height: 1.25rem; margin: 0; accent-color: var(--ft-accent); cursor: pointer; }
.ft-check input:focus-visible { outline: 3px solid var(--ft-focus); outline-offset: 2px; }
.ft-switch { display: inline-flex; align-items: center; gap: var(--ft-space-3); min-height: var(--ft-target); color: var(--ft-ink); font-size: var(--ft-text-sm); cursor: pointer; }
.ft-switch input {
  appearance: none;
  position: relative;
  flex: none;
  width: 2.75rem;
  height: 1.5rem;
  margin: 0;
  border: 1px solid var(--ft-line-strong);
  border-radius: 999px;
  background: var(--ft-surface-2);
  cursor: pointer;
}
.ft-switch input::before {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: calc(1.5rem - 6px);
  height: calc(1.5rem - 6px);
  border-radius: 50%;
  background: var(--ft-ink-2);
}
.ft-switch input:checked { border-color: var(--ft-accent); background: var(--ft-accent); }
.ft-switch input:checked::before { left: calc(100% - 1.5rem + 4px); background: var(--ft-accent-ink); }
.ft-switch input:focus-visible { outline: 3px solid var(--ft-focus); outline-offset: 2px; }
/* Touch: the whole label is the target (44 px tall already); a checkbox or switch with a very short label is still 44 px wide. */
@media (max-width: 40rem), (pointer: coarse) {
  .ft-check, .ft-switch { min-width: var(--ft-target); }
}

/* File drop zone: the real file input stays focusable; the label is the target. */
.ft-drop { position: relative; display: block; }
.ft-drop__input { position: absolute; width: 1px; height: 1px; margin: 0; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; opacity: 0; }
.ft-drop__label {
  display: grid;
  justify-items: center;
  gap: var(--ft-space-2);
  min-height: 9rem;
  padding: var(--ft-space-5) var(--ft-space-4);
  border: 2px dashed var(--ft-line-strong);
  border-radius: var(--ft-radius-l);
  background: var(--ft-surface-2);
  color: var(--ft-ink-2);
  font-size: var(--ft-text-sm);
  text-align: center;
  cursor: pointer;
  align-content: center;
}
.ft-drop__label strong { color: var(--ft-ink); font-size: var(--ft-text-md); font-weight: 650; }
.ft-drop__icon { width: 1.75rem; height: 1.75rem; fill: none; stroke: var(--ft-accent); stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.ft-drop__button { display: inline-flex; align-items: center; min-height: 2.5rem; padding: 0 1rem; border: 1px solid var(--ft-line-strong); border-radius: var(--ft-radius); background: var(--ft-surface); color: var(--ft-ink); font-weight: 600; }
.ft-drop:hover .ft-drop__label, .ft-drop.is-dragover .ft-drop__label { border-color: var(--ft-accent); background: var(--ft-accent-soft); }
.ft-drop__input:focus-visible + .ft-drop__label { outline: 3px solid var(--ft-focus); outline-offset: 2px; border-color: var(--ft-focus); }
.ft-drop__file { margin: var(--ft-space-2) 0 0; color: var(--ft-ink); font-size: var(--ft-text-sm); font-weight: 600; overflow-wrap: anywhere; }

/* 4. Buttons ------------------------------------------------------------------------------- */
.ft-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--ft-space-2);
  box-sizing: border-box;
  min-height: var(--ft-target);
  padding: 0 1.125rem;
  border: 1px solid var(--ft-line-strong);
  border-radius: var(--ft-radius);
  background: var(--ft-surface);
  color: var(--ft-ink);
  font: inherit;
  font-size: var(--ft-text-sm);
  font-weight: 650;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
}
.ft-btn:hover { border-color: var(--ft-ink-2); background: var(--ft-surface-2); }
.ft-btn:focus-visible { outline: 3px solid var(--ft-focus); outline-offset: 2px; }
.ft-btn:disabled, .ft-btn[aria-disabled="true"] { opacity: 0.55; cursor: not-allowed; }
.ft-btn--primary { border-color: var(--ft-accent); background: var(--ft-accent); color: var(--ft-accent-ink); }
.ft-btn--primary:hover { border-color: var(--ft-accent-hover); background: var(--ft-accent-hover); color: var(--ft-accent-ink); }
.ft-btn--secondary { background: var(--ft-surface); }
.ft-btn--quiet { border-color: transparent; background: transparent; color: var(--ft-link); text-decoration: underline; text-underline-offset: 0.2em; }
.ft-btn--quiet:hover { border-color: transparent; background: var(--ft-accent-soft); }
.ft-btn--icon { width: var(--ft-target); padding: 0; }
.ft-btn--block { width: 100%; }
/* Toggle buttons (aria-pressed="true"): the pressed state shows, it is not only announced. Low specificity on
   purpose, so a page can give its own toggles another look; primary buttons keep their fill. */
.ft-btn[aria-pressed="true"]:where(:not(.ft-btn--primary)) { border-color: var(--ft-accent); background: var(--ft-accent-soft); color: var(--ft-ink); }
.ft-btn__icon { flex: none; width: 1.125rem; height: 1.125rem; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.ft-btnrow { display: flex; flex-wrap: wrap; align-items: center; gap: var(--ft-space-2); }
.ft-btnrow > * { min-width: 0; }
@media (max-width: 40rem) { .ft-btn { white-space: normal; } }
@media (max-width: 40rem), (pointer: coarse) { .ft-btn { min-width: var(--ft-target); } }

/* 5. Results ------------------------------------------------------------------------------- */
.ft-result { padding: var(--ft-space-5); border: 1px solid var(--ft-line); border-radius: var(--ft-radius-l); background: var(--ft-surface); }
.ft-result__label { margin: 0; color: var(--ft-ink-2); font-size: var(--ft-text-sm); font-weight: 600; }
.ft-result__value { margin: var(--ft-space-1) 0 0; color: var(--ft-ink); font-size: clamp(1.75rem, 1.3rem + 2vw, 2.5rem); font-weight: 700; line-height: 1.1; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.ft-result__unit { margin-left: 0.25em; color: var(--ft-ink-2); font-size: 0.55em; font-weight: 600; }
.ft-result__note { margin: var(--ft-space-2) 0 0; color: var(--ft-ink-2); font-size: var(--ft-text-sm); }
.ft-stats { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 10rem), 1fr)); gap: var(--ft-space-3); margin: 0; padding: 0; list-style: none; }
.ft-stat { display: grid; grid-template-columns: minmax(0, 1fr); align-content: start; gap: 2px; min-width: 0; padding: var(--ft-space-3) var(--ft-space-4); border: 1px solid var(--ft-line); border-radius: var(--ft-radius); background: var(--ft-surface); }
.ft-stat__label { order: 1; margin: 0; color: var(--ft-ink-2); font-size: var(--ft-text-xs); font-weight: 600; }
.ft-stat__value { order: 2; margin: 0; color: var(--ft-ink); font-size: var(--ft-text-xl); font-weight: 700; line-height: 1.2; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.ft-stat__unit { margin-left: 0.2em; color: var(--ft-ink-2); font-size: var(--ft-text-sm); font-weight: 600; }
.ft-stat__note { order: 3; margin: 0; color: var(--ft-ink-2); font-size: var(--ft-text-xs); }
.ft-stat--ok { border-left: 4px solid var(--ft-ok); }
.ft-stat--warn { border-left: 4px solid var(--ft-warn); }
.ft-stat--bad { border-left: 4px solid var(--ft-bad); }
.ft-placeholder { display: grid; place-items: center; min-height: 10rem; padding: var(--ft-space-5); border: 1px dashed var(--ft-line-strong); border-radius: var(--ft-radius-l); color: var(--ft-ink-2); font-size: var(--ft-text-sm); text-align: center; }

/* 6. Tables -------------------------------------------------------------------------------- */
.ft-tablewrap { max-width: 100%; overflow: auto; border: 1px solid var(--ft-line); border-radius: var(--ft-radius); background: var(--ft-surface); }
.ft-tablewrap--tall { max-height: 28rem; }
.ft-tablewrap:focus-visible { outline: 3px solid var(--ft-focus); outline-offset: 2px; }
/* In running text the paragraph gap goes under the table box, not inside it. */
.ft-prose :where(.ft-tablewrap) { margin: 0 0 1em; }
.ft-tablewrap > .ft-table { margin: 0; }
.ft-table { width: 100%; border-collapse: separate; border-spacing: 0; color: var(--ft-ink); font-size: var(--ft-text-sm); line-height: 1.4; }
.ft-table caption { padding: var(--ft-space-3) var(--ft-space-4); color: var(--ft-ink-2); font-size: var(--ft-text-sm); text-align: left; caption-side: top; }
.ft-table th, .ft-table td { padding: 0.5rem 0.75rem; border-bottom: 1px solid var(--ft-line); text-align: left; vertical-align: top; }
.ft-table thead th { position: sticky; top: 0; z-index: 1; background: var(--ft-surface-2); color: var(--ft-ink); font-weight: 650; white-space: nowrap; }
.ft-table tbody tr:last-child > * { border-bottom: 0; }
.ft-table tbody th { font-weight: 600; }
.ft-table .ft-num, .ft-table td.ft-num, .ft-table th.ft-num { text-align: right; font-variant-numeric: tabular-nums; }
/* Numbers never wrap. Column headers get their nowrap from the "thead th" rule above only, so a page can let
   long headers wrap with one rule (.my-table thead th { white-space: normal }), numeric columns included. */
.ft-table .ft-num:not(thead th) { white-space: nowrap; }
.ft-table tr.is-flagged > * { background: var(--ft-warn-soft); }
.ft-table--compact th, .ft-table--compact td { padding: 0.3rem 0.6rem; }
.ft-num { font-variant-numeric: tabular-nums; }

/* 7. Tabs ---------------------------------------------------------------------------------- */
.ft-tabs__list { display: flex; flex-wrap: wrap; gap: var(--ft-space-1); margin-bottom: var(--ft-space-4); border-bottom: 1px solid var(--ft-line); }
.ft-tab {
  position: relative;
  display: inline-flex;
  align-items: center;
  min-height: var(--ft-target);
  margin-bottom: -1px;
  padding: 0 var(--ft-space-4);
  border: 1px solid transparent;
  border-bottom: 0;
  border-radius: var(--ft-radius) var(--ft-radius) 0 0;
  background: transparent;
  color: var(--ft-ink-2);
  font: inherit;
  font-size: var(--ft-text-sm);
  font-weight: 650;
  cursor: pointer;
}
.ft-tab:hover { color: var(--ft-ink); background: var(--ft-surface-2); }
.ft-tab[aria-selected="true"] { border-color: var(--ft-line); background: var(--ft-surface); color: var(--ft-ink); box-shadow: inset 0 3px 0 var(--ft-accent); }
.ft-tab:focus-visible { outline: 3px solid var(--ft-focus); outline-offset: -3px; }
.ft-tabpanel:focus-visible { outline: 3px solid var(--ft-focus); outline-offset: 4px; border-radius: var(--ft-radius-s); }
@media (max-width: 40rem), (pointer: coarse) { .ft-tab { min-width: var(--ft-target); justify-content: center; } }

/* 8. Status, notes and toasts -------------------------------------------------------------- */
.ft-status { min-height: 1.5em; margin: var(--ft-space-2) 0 0; color: var(--ft-ink-2); font-size: var(--ft-text-sm); }
.ft-status--ok { color: var(--ft-ok); }
.ft-status--bad { color: var(--ft-bad); }
.ft-note { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--ft-space-3); margin: var(--ft-space-4) 0; padding: var(--ft-space-3) var(--ft-space-4); border: 1px solid transparent; border-left-width: 4px; border-radius: var(--ft-radius); background: var(--ft-info-soft); border-color: var(--ft-info); color: var(--ft-ink); font-size: var(--ft-text-sm); }
.ft-note > :last-child { margin-bottom: 0; }
.ft-note__icon { width: 1.25rem; height: 1.25rem; margin-top: 1px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; color: var(--ft-info); }
.ft-note__title { margin: 0 0 2px; font-weight: 700; }
.ft-note p { margin: 0 0 var(--ft-space-1); }
.ft-note--ok { background: var(--ft-ok-soft); border-color: var(--ft-ok); }
.ft-note--ok .ft-note__icon { color: var(--ft-ok); }
.ft-note--warn { background: var(--ft-warn-soft); border-color: var(--ft-warn); }
.ft-note--warn .ft-note__icon { color: var(--ft-warn); }
.ft-note--bad { background: var(--ft-bad-soft); border-color: var(--ft-bad); }
.ft-note--bad .ft-note__icon { color: var(--ft-bad); }
.ft-badge { display: inline-flex; align-items: center; gap: 0.3em; padding: 0.1rem 0.5rem; border-radius: 999px; background: var(--ft-surface-2); color: var(--ft-ink-2); font-size: var(--ft-text-xs); font-weight: 650; white-space: nowrap; }
.ft-badge--ok { background: var(--ft-ok-soft); color: var(--ft-ok); }
.ft-badge--warn { background: var(--ft-warn-soft); color: var(--ft-warn); }
.ft-badge--bad { background: var(--ft-bad-soft); color: var(--ft-bad); }
/* Toasts sit top right: 1rem from the edges (0.75rem on phones), or just under the site frame while the frame
   is on screen (the shell sets --ft-toast-top when it shows one). The region never reaches into the cookie
   banner (--ft-consent-h, kept by the consent script) and never takes a click. Its padding only keeps the
   toasts' shadows from being clipped. */
.ft-toasts {
  position: fixed;
  z-index: 60;
  top: calc(var(--ft-toast-top, 1rem) - 0.75rem);
  right: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-content: start;
  gap: var(--ft-space-2);
  box-sizing: border-box;
  width: min(26rem, 100vw);
  max-height: calc(100vh - var(--ft-toast-top, 1rem) - var(--ft-consent-h, 0px));
  max-height: calc(100dvh - var(--ft-toast-top, 1rem) - var(--ft-consent-h, 0px));
  padding: 0.75rem 1rem 1.25rem;
  overflow: hidden;
  pointer-events: none;
}
.ft-toast {
  margin: 0;
  padding: var(--ft-space-3) var(--ft-space-4);
  border: 1px solid var(--ft-line);
  border-left: 4px solid var(--ft-info);
  border-radius: var(--ft-radius);
  background: var(--ft-surface);
  box-shadow: var(--ft-shadow);
  color: var(--ft-ink);
  font-size: var(--ft-text-sm);
  overflow-wrap: anywhere;
  pointer-events: none;
}
.ft-toast--ok { border-left-color: var(--ft-ok); }
.ft-toast--warn { border-left-color: var(--ft-warn); }
.ft-toast--bad { border-left-color: var(--ft-bad); }
@media (max-width: 40rem) { .ft-toasts { left: 0; width: auto; padding-inline: 0.75rem; } }

/* 9. Charts and canvases -------------------------------------------------------------------- */
.ft-chart { margin: 0; }
.ft-chart__frame {
  position: relative;
  width: 100%;
  aspect-ratio: var(--ft-chart-ratio, 16 / 9);
  overflow: hidden;
  border: 1px solid var(--ft-line);
  border-radius: var(--ft-radius);
  background: var(--ft-plot-surface);
}
.ft-chart__frame > canvas, .ft-chart__frame > svg { position: absolute; inset: 0; display: block; width: 100%; height: 100%; }
.ft-chart--square .ft-chart__frame { --ft-chart-ratio: 1 / 1; }
.ft-chart--wide .ft-chart__frame { --ft-chart-ratio: 21 / 9; }
@media (max-width: 40rem) { .ft-chart__frame { aspect-ratio: var(--ft-chart-ratio-narrow, 4 / 3); } .ft-chart--square .ft-chart__frame { aspect-ratio: 1 / 1; } }
.ft-chart__legend { display: flex; flex-wrap: wrap; gap: var(--ft-space-1) var(--ft-space-4); margin: var(--ft-space-2) 0 0; padding: 0; list-style: none; color: var(--ft-ink-2); font-size: var(--ft-text-sm); }
.ft-chart__key { display: inline-flex; align-items: center; gap: var(--ft-space-2); }
.ft-swatch { display: inline-block; flex: none; width: 0.75rem; height: 0.75rem; border-radius: 3px; background: var(--ft-swatch, var(--ft-plot-1)); }
.ft-swatch--line { height: 3px; width: 1rem; border-radius: 2px; }
.ft-chart__caption { margin: var(--ft-space-2) 0 0; color: var(--ft-ink-2); font-size: var(--ft-text-sm); }

/* 10. Help sections ------------------------------------------------------------------------- */
.ft-steps { counter-reset: ft-step; display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--ft-space-3); margin: 0; padding: 0; list-style: none; max-width: var(--ft-measure); }
.ft-steps > li { counter-increment: ft-step; position: relative; min-height: 2rem; padding-left: 2.75rem; color: var(--ft-ink); line-height: 1.55; }
.ft-steps > li::before {
  content: counter(ft-step);
  position: absolute;
  left: 0;
  top: -0.1rem;
  display: grid;
  place-items: center;
  width: 1.875rem;
  height: 1.875rem;
  border-radius: 50%;
  background: var(--ft-accent-soft);
  color: var(--ft-ink);
  font-size: var(--ft-text-sm);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.ft-example { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--ft-space-4); }
@media (min-width: 56rem) { .ft-example--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.ft-example__step { padding: var(--ft-space-4); border: 1px solid var(--ft-line); border-radius: var(--ft-radius); background: var(--ft-surface); }
.ft-example__label { margin: 0 0 var(--ft-space-1); color: var(--ft-ink-2); font-size: var(--ft-text-xs); font-weight: 700; }
.ft-formula {
  display: block;
  max-width: 100%;
  margin: var(--ft-space-4) 0;
  padding: var(--ft-space-3) var(--ft-space-4);
  overflow-x: auto;
  border-left: 3px solid var(--ft-accent);
  border-radius: 0 var(--ft-radius) var(--ft-radius) 0;
  background: var(--ft-surface-2);
  color: var(--ft-ink);
  font-family: var(--ft-font-mono);
  font-size: 0.95rem;
  line-height: 1.6;
  white-space: pre-wrap;
}
.ft-faq { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--ft-space-2); max-width: 52rem; }
.ft-faq__item, .ft-disclosure { border: 1px solid var(--ft-line); border-radius: var(--ft-radius); background: var(--ft-surface); }
.ft-faq__item > summary, .ft-disclosure > summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ft-space-3);
  min-height: var(--ft-target);
  padding: var(--ft-space-3) var(--ft-space-4);
  color: var(--ft-ink);
  font-weight: 650;
  line-height: 1.4;
  cursor: pointer;
  list-style: none;
}
.ft-faq__item > summary::-webkit-details-marker, .ft-disclosure > summary::-webkit-details-marker { display: none; }
.ft-faq__item > summary::after, .ft-disclosure > summary::after {
  content: "";
  flex: none;
  width: 0.5rem;
  height: 0.5rem;
  margin-right: 0.25rem;
  border-right: 2px solid var(--ft-ink-2);
  border-bottom: 2px solid var(--ft-ink-2);
  transform: rotate(45deg) translateY(-2px);
}
.ft-faq__item[open] > summary::after, .ft-disclosure[open] > summary::after { transform: rotate(-135deg) translateY(-2px); }
.ft-faq__item > summary:focus-visible, .ft-disclosure > summary:focus-visible { outline: 3px solid var(--ft-focus); outline-offset: 2px; border-radius: var(--ft-radius); }
.ft-faq__answer, .ft-disclosure__body { padding: 0 var(--ft-space-4) var(--ft-space-4); color: var(--ft-ink); }
.ft-faq__answer > :first-child, .ft-disclosure__body > :first-child { margin-top: 0; }
.ft-faq__answer > :last-child, .ft-disclosure__body > :last-child { margin-bottom: 0; }

/* 11. Motion and print ------------------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  body.ft-page *, body.ft-page *::before, body.ft-page *::after { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; scroll-behavior: auto !important; }
}
@media print {
  /* Paper is white and ink is dark whatever theme the screen shows: ft-shell-20261106.css sets every colour
     token back to its light value for print, so nothing here needs a dark-theme exception. */
  body.ft-page { background: #fff; color: #000; display: block; }
  /* No use on paper: buttons, button rows, file pickers, tab strips, toasts, related links. A page keeps one
     of the first four by adding data-ft-print="show" to it (a row also stays when something inside it has it). */
  .ft-toasts, .ft-privacy__icon, #ft-related { display: none !important; }
  .ft-btn:not([data-ft-print="show"]), .ft-drop:not([data-ft-print="show"]), .ft-tabs__list:not([data-ft-print="show"]) { display: none !important; }
  .ft-btnrow:not([data-ft-print="show"]) { display: none !important; }
  .ft-btnrow:has([data-ft-print="show"]) { display: flex !important; }
  .ft-panel, .ft-result, .ft-stat, .ft-tablewrap, .ft-faq__item, .ft-disclosure, .ft-example__step { box-shadow: none !important; border-color: #999 !important; background: #fff !important; }
  /* Small blocks stay in one piece. Panels and tables may run over a page break (a panel taller than the rest of
     the sheet used to leave that sheet empty); headings stay with what follows and table rows stay whole. */
  .ft-result, .ft-stat, .ft-note, .ft-faq__item, .ft-example__step, .ft-chart, .ft-table tr, .ft-steps > li { break-inside: avoid; }
  .ft-panel__head, .ft-panel__title, .ft-section__title { break-after: avoid; }
  .ft-tablewrap { max-height: none !important; overflow: visible !important; }
  .ft-table thead th { position: static; }
  .ft-sticky { position: static; }
  /* Every tab panel prints, each under its tab's name (the shell copies the name to data-ft-tab-label). */
  .ft-tabpanel[hidden] { display: block !important; }
  .ft-tabpanel[data-ft-tab-label]::before { content: attr(data-ft-tab-label); display: block; margin: 0 0 0.5rem; color: var(--ft-ink); font-size: var(--ft-text-md); font-weight: 700; break-after: avoid; }
  .ft-tabpanel[data-ft-tab-label] + .ft-tabpanel[data-ft-tab-label]::before { margin-top: 1.25rem; }
  .ft-faq__item::details-content, .ft-disclosure::details-content { content-visibility: visible; display: block; }
  .ft-chart__frame { border-color: #999; }
  .ft-section { margin-top: 1.5rem; break-inside: auto; }
  /* States drawn with a fill print as fills even with "background graphics" off; the chosen option of a
     segmented control also gets a line around it. */
  .ft-swatch, .ft-switch input, .ft-switch input::before, .ft-segmented__option input:checked + span { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  .ft-segmented__option input:checked + span { box-shadow: none; outline: 2px solid var(--ft-ink); outline-offset: -2px; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 0.85em; }
}

/* 12. Forced colours (Windows high contrast) ---------------------------------------------------
   This mode drops fills, shadows and gradients, so every state that was drawn with one is drawn again
   with system colours. Focus rings are outlines already; here they take the system highlight colour. */
@media (forced-colors: active) {
  .ft-tab[aria-selected="true"] { forced-color-adjust: none; border-color: Highlight; background: Highlight; color: HighlightText; }
  .ft-segmented__option input:checked + span { forced-color-adjust: none; background: Highlight; color: HighlightText; }
  .ft-switch input { forced-color-adjust: none; border-color: ButtonText; background: Canvas; }
  .ft-switch input::before { background: ButtonText; }
  .ft-switch input:checked { border-color: Highlight; background: Highlight; }
  .ft-switch input:checked::before { background: HighlightText; }
  .ft-switch input:disabled { border-color: GrayText; }
  .ft-switch input:disabled::before { background: GrayText; }
  .ft-btn[aria-pressed="true"]:where(:not(.ft-btn--primary)) { forced-color-adjust: none; border-color: Highlight; background: Highlight; color: HighlightText; }
  /* The select arrow is a gradient, which this mode removes: show the system's own arrow instead. */
  .ft-select, .ft-inputgroup > .ft-select.ft-inputgroup__unit { appearance: auto; padding-right: 0.75rem; background-image: none; }
  .ft-drop:hover .ft-drop__label, .ft-drop.is-dragover .ft-drop__label { border-color: Highlight; }
  .ft-table tr.is-flagged > * { border-bottom: 2px solid Highlight; }
  .ft-steps > li::before { border: 1px solid CanvasText; }
  /* Chart legend keys keep their series colour (it is the only thing they show). */
  .ft-swatch { forced-color-adjust: none; }
  .ft-input:focus-visible, .ft-select:focus-visible, .ft-textarea:focus-visible, .ft-range__input:focus-visible,
  .ft-check input:focus-visible, .ft-switch input:focus-visible, .ft-drop__input:focus-visible + .ft-drop__label,
  .ft-btn:focus-visible, .ft-tablewrap:focus-visible, .ft-tab:focus-visible, .ft-tabpanel:focus-visible,
  .ft-faq__item > summary:focus-visible, .ft-disclosure > summary:focus-visible { outline-color: Highlight; }
  /* A ring that touches a highlighted fill takes the other colour of the pair so it stays visible. */
  .ft-tab[aria-selected="true"]:focus-visible { outline-color: HighlightText; }
  .ft-segmented__option input:focus-visible + span { outline-color: CanvasText; }
  .ft-btn[aria-pressed="true"]:where(:not(.ft-btn--primary)):focus-visible { outline-color: CanvasText; }
}
