/* ---------------------------------------------------------------------------
   Wood speeds and feeds calculator, app layer.

   Loads after lt-tokens.css and lt-components.css. Every colour, size, space
   and radius here reads a --lt-* token. Nothing in this file declares a
   literal, and conformance.py fails the build if one appears.

   SURFACES decide the rest of this file. <body> is the page surface and
   follows the colour scheme. <main> is a panel and is light in BOTH schemes,
   which is why controls sit inside it. The header and the footer sit on the
   page.

   THERE IS NO DARK-MODE BLOCK HERE, deliberately. lt-tokens.css owns
   prefers-color-scheme and re-declares its surfaces, its ink and its
   color-scheme together. A second dark-mode system running beside it is two
   sources of truth that drift, and the drift shows up as light ink on a light
   card months later.
   --------------------------------------------------------------------------- */

:root {
  font-family: var(--lt-font-sans);
}

body {
  margin: 0 auto;
  padding: var(--lt-space-5);
  max-width: 44rem;
  background: var(--lt-surface-page);
  color: var(--lt-text-primary);
  font-size: var(--lt-text-md);
  line-height: var(--lt-leading-md);
}

header h1 {
  font-size: var(--lt-text-2xl);
  line-height: var(--lt-leading-2xl);
  margin: var(--lt-space-2) 0;
}
.tagline {
  color: var(--lt-text-secondary);
  margin-top: 0;
  font-size: var(--lt-text-base);
  line-height: var(--lt-leading-base);
}

/* Scoped, not a bare h2. A bare element selector reaches inside any component
   that generates its own heading, which is how a gallery once gave every
   lt-dialog title a 64px top margin and a rule under it. */
#diagnostics h2 {
  font-size: var(--lt-text-lg);
  line-height: var(--lt-leading-lg);
  margin: var(--lt-space-6) 0 var(--lt-space-3);
}

/* The panel paints its own background through .lt-panel. This adds only the
   geometry, never a background: a later single-class rule setting one would
   beat the surface class and leave the ink saying the opposite. */
main {
  padding: var(--lt-space-5);
  border: var(--lt-border-width-thin) solid var(--lt-border-subtle);
  border-radius: var(--lt-radius-lg);
}

/* The tool-type picker keeps its card grid, and the card is layout only: the
   control inside every card is a real .lt-check radio. The old card hid its
   radio with opacity, so a keyboard user had no focus ring to follow. */
.tool-grid { display: grid; gap: var(--lt-space-3); grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr)); }

.tool-card {
  padding: var(--lt-space-4);
  background: var(--lt-field-bg);
  border: var(--lt-border-width-thin) solid var(--lt-field-border);
  border-radius: var(--lt-radius-md);
}
.tool-card:has(input:checked) {
  border-color: var(--lt-action-bg);
  outline: var(--lt-border-width-medium) solid var(--lt-action-bg);
}
.tool-body { display: grid; gap: var(--lt-space-1); }
.tool-name { font-weight: var(--lt-weight-semibold); }
.tool-hint { font-size: var(--lt-text-xs); color: var(--lt-text-secondary); }

/* The button group is inline-flex by default. The profile picker spans the
   field, and its three options share the width evenly. */
.profile-group { display: flex; }
.profile-group > .lt-btn { flex: 1; }

/* Every bounded block on the panel pads the same: space-4 block, space-5
   inline. .out-card is the one exception and states its reason there. The
   details blocks were on space-4 all round, so they sat 4px narrower inside
   than the notes and the ladder beside them. */
details#advanced, details.defects {
  margin: var(--lt-space-5) 0;
  border: var(--lt-border-width-thin) solid var(--lt-border-subtle);
  border-radius: var(--lt-radius-md);
  background: var(--lt-surface-subtle);
  padding: var(--lt-space-4) var(--lt-space-5);
}
details summary { cursor: pointer; font-weight: var(--lt-weight-semibold); }

#advanced-fields { margin-top: var(--lt-space-4); }

/* The limit line, the warnings, the notes, the refusal and the block are all
   .lt-alert banners now, and the diagnostic chips are .lt-badge. The results
   section spaces them; the components carry no outer margin of their own. */
#results { display: grid; gap: var(--lt-space-4); margin-block: var(--lt-space-5); }

/* Provenance notes, not banners. One cut can produce nine of them, because
   most published charts hold no value at a 3.175 mm tool, and nine banners
   bury the feedrates they sit under. */
.notes {
  border: var(--lt-border-width-thin) solid var(--lt-border-subtle);
  border-radius: var(--lt-radius-md);
  background: var(--lt-surface-subtle);
  padding: var(--lt-space-4) var(--lt-space-5);
  color: var(--lt-text-secondary);
  font-size: var(--lt-text-sm);
  line-height: var(--lt-leading-sm);
}
.notes-title {
  font-size: var(--lt-text-xs);
  font-weight: var(--lt-weight-semibold);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--lt-text-primary);
  margin-bottom: var(--lt-space-3);
}
.notes ul { padding-inline-start: var(--lt-space-5); }
.notes li { margin-block: var(--lt-space-2); }

/* The output rows stay bespoke. .lt-specs is the nearest component and it is
   not an equivalent: it left-aligns its values in a second column, and a
   column of feedrates a machinist transcribes needs its digits right-aligned
   and its imperial conversion under each one. Tokens only, no literals. */
.out-card {
  border: var(--lt-border-width-thin) solid var(--lt-border-subtle);
  border-radius: var(--lt-radius-md);
  padding: var(--lt-space-2) var(--lt-space-5);
}
.out-row {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: baseline;
  gap: var(--lt-space-1) var(--lt-space-3);
  padding: var(--lt-space-3) 0;
  border-bottom: var(--lt-border-width-thin) solid var(--lt-border-subtle);
}
.out-row:last-child { border-bottom: 0; }
.out-row.secondary .out-label, .out-row.secondary .metric { color: var(--lt-text-secondary); font-weight: var(--lt-weight-regular); }
.out-label { font-weight: var(--lt-weight-semibold); }
.out-vals { text-align: right; }
.metric { font-weight: var(--lt-weight-bold); font-variant-numeric: tabular-nums; }
.imperial { display: block; font-size: var(--lt-text-xs); color: var(--lt-text-secondary); font-variant-numeric: tabular-nums; }
.row-note {
  grid-column: 1 / -1;
  font-size: var(--lt-text-sm);
  color: var(--lt-text-secondary);
  padding-top: var(--lt-space-2);
}

/* THE TWO CHARTS BELOW ARE BESPOKE ON PURPOSE. The capacity cascade and the
   chip-load ladder are bar and range visualisations, and the system has no
   component for either. It does own the chart tokens: the track, the marks
   and the series slots all live in tokens/lt-tokens.css, with the system's
   measurements above them.

   Both are EMPHASIS charts: grey the rest, highlight the one that matters.
   Neither cycles hues, and neither leans on colour alone -- the serving and
   binding rows carry bold weight too.

   The highlighted bar carries .lt-chart-emphasis in the markup and that class
   owns its paint: the emphasis colour normally, Highlight in forced colours,
   where every other fill collapses to one tone. The :not() below is what
   keeps that working. This file loads last, so a plain .casc-fill background
   would beat the class on source order and pin the bar to a colour forced
   colours cannot see. The neutral rules therefore step aside by name.

   Neither uses opacity to separate a live mark from a context one. An opacity
   cannot be contrast-checked and is discarded under forced colours, so the
   difference is carried by two different tokens.

   Marks follow the fixed specs: capped thin bars, a 4px rounded data-end with
   the baseline end left square, a 2px surface gap between touching bars, and a
   hairline recessive track. No border is ever drawn around a mark to separate
   it -- the gap does that work. */
.cascade { margin-top: var(--lt-space-4); }
.casc-row {
  display: flex;
  align-items: center;
  gap: var(--lt-space-3);
  /* half the 2px surface gap on each side of a touching neighbour */
  padding-block: 1px;
  min-block-size: var(--lt-target-min);
  font-size: var(--lt-text-sm);
}
.casc-label { flex: 0 1 7rem; min-width: 0; }
/* Both charts run the same geometry: a 16px track carrying a 12px mark, so
   the leftover band is air rather than more ink. The cascade used to be a
   12px track with the fill painted edge to edge, which made the same kind of
   bar read heavier here than in the ladder below it. */
.casc-bar {
  position: relative;
  flex: 1 1 3rem;
  min-width: 2rem;
  block-size: var(--lt-space-5);
  background: var(--lt-chart-track);
  border-radius: var(--lt-radius-sm);
}
/* Square at the baseline it grows from, rounded at the data end. */
.casc-fill {
  position: absolute;
  inset-block: var(--lt-space-1);
  inset-inline-start: 0;
  border-start-end-radius: var(--lt-radius-md);
  border-end-end-radius: var(--lt-radius-md);
}
.casc-fill:not(.lt-chart-emphasis) { background: var(--lt-chart-mark); }
.casc-row.is-bind { font-weight: var(--lt-weight-bold); }
/* A cap so far above the served feed that it cannot bind. Dimmed with a
   real ink token rather than opacity: at 0.45 the label dropped under the
   contrast floor and nothing could measure it. */
.casc-row.na { color: var(--lt-text-placeholder); }
.casc-row.na .casc-fill { background: var(--lt-chart-mark-context); }
.casc-val { flex: 0 1 auto; text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }

.ladder {
  border: var(--lt-border-width-thin) solid var(--lt-border-subtle);
  border-radius: var(--lt-radius-md);
  padding: var(--lt-space-4) var(--lt-space-5);
  margin: var(--lt-space-4) 0;
}
.ladder-head { display: flex; justify-content: space-between; align-items: baseline; gap: var(--lt-space-3); }
.ladder-head h2 { margin: 0 0 var(--lt-space-3); font-size: var(--lt-text-lg); line-height: var(--lt-leading-lg); }
.ladder-units { font-size: var(--lt-text-xs); color: var(--lt-text-secondary); white-space: nowrap; }
.ladder-row {
  display: grid;
  grid-template-columns: minmax(7rem, 15rem) 1fr auto;
  gap: var(--lt-space-1) var(--lt-space-3);
  align-items: center;
  padding: var(--lt-space-1) 0;
  font-size: var(--lt-text-xs);
}
.ladder-label { color: var(--lt-text-secondary); line-height: var(--lt-leading-xs); overflow-wrap: break-word; }
.ladder-row.is-serving .ladder-label { color: var(--lt-text-primary); font-weight: var(--lt-weight-bold); }
.ladder-tag {
  font-style: normal;
  font-size: var(--lt-text-2xs);
  border: var(--lt-border-width-thin) solid var(--lt-border-subtle);
  border-radius: var(--lt-radius-pill);
  padding: 0 var(--lt-space-2);
  color: var(--lt-text-secondary);
  white-space: nowrap;
}
.ladder-track {
  position: relative;
  block-size: var(--lt-space-5);
  background: var(--lt-chart-track);
  border-radius: var(--lt-radius-sm);
}
/* A range bar, so BOTH ends are data ends and both round. */
.ladder-bar {
  position: absolute;
  top: var(--lt-space-1);
  bottom: var(--lt-space-1);
  border-radius: var(--lt-radius-md);
}
.ladder-bar:not(.lt-chart-emphasis) { background: var(--lt-chart-mark-context); }
/* The served feed per tooth, marked in every row against the shared scale.
   Dotted stays: this is a threshold reference line, which is the one case
   the anti-pattern on dashed rules explicitly carves out. It is not a grid. */
.ladder-mark {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 0;
  border-left: var(--lt-border-width-medium) dotted var(--lt-chart-mark-context);
}
.ladder-row.is-serving .ladder-mark { border-left-color: var(--lt-text-primary); }
.ladder-range {
  color: var(--lt-text-secondary);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  font-size: var(--lt-text-2xs);
}
.ladder-legend { margin: var(--lt-space-3) 0 0; font-size: var(--lt-text-xs); color: var(--lt-text-secondary); }

/* THE HOVER LAYER. Each chart is one tab stop with a roving tabindex, so the
   focus ring lands on a row and the arrow keys walk the rest. The hovered or
   focused row lifts with a ring in the surface colour rather than a border
   drawn on the mark, which would add ink that is not data. */
.casc-row, .ladder-row {
  border-radius: var(--lt-radius-sm);
  outline-offset: calc(var(--lt-border-width-medium) * -1);
}
.casc-row:hover, .ladder-row:hover {
  background: var(--lt-chart-track);
}
.casc-row:focus-visible, .ladder-row:focus-visible {
  outline: var(--lt-focus-ring-width) solid var(--lt-focus-ring-color);
  outline-offset: var(--lt-focus-ring-gap);
}
.ladder-row { min-block-size: var(--lt-target-min); }

.chart-tip {
  position: fixed;
  /* An anchored floating layer, dismissed like one, and it must sit under the
     overlay, modal and toast levels. There is no --lt-z-tooltip. */
  z-index: var(--lt-z-dropdown);
  display: grid;
  gap: var(--lt-space-1);
  max-inline-size: 22rem;
  padding: var(--lt-space-3) var(--lt-space-4);
  border: var(--lt-border-width-thin) solid var(--lt-border-default);
  border-radius: var(--lt-radius-md);
  box-shadow: var(--lt-shadow-overlay);
  pointer-events: none;
}
.chart-tip[hidden] { display: none; }
/* Values lead, labels follow: the reader already has the row and wants the
   number, which is the legend's hierarchy inverted. */
.chart-tip__value {
  font-size: var(--lt-text-md);
  font-weight: var(--lt-weight-semibold);
  font-variant-numeric: tabular-nums;
  color: var(--lt-text-primary);
}
.chart-tip__label { font-size: var(--lt-text-xs); color: var(--lt-text-secondary); }
.chart-tip__note { font-size: var(--lt-text-xs); color: var(--lt-text-primary); }

.table-twin { margin-top: var(--lt-space-4); }
.table-twin > summary {
  cursor: pointer;
  font-size: var(--lt-text-xs);
  font-weight: var(--lt-weight-semibold);
  color: var(--lt-text-secondary);
}
.table-twin .lt-table-wrap { margin-top: var(--lt-space-3); }
@media (max-width: 480px) {
  .ladder-row { grid-template-columns: 1fr auto; }
  .ladder-label { grid-column: 1 / -1; }
}

.defects dt { font-weight: var(--lt-weight-semibold); margin-top: var(--lt-space-3); }
.defects dd { margin: 0 0 var(--lt-space-2); color: var(--lt-text-secondary); }

footer { margin: var(--lt-space-8) 0 var(--lt-space-5); font-size: var(--lt-text-sm); color: var(--lt-text-secondary); }
