/* Compact setup, with detailed controls available on demand. */
.mp__presets { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding-bottom: 18px; border-bottom: 1px solid var(--line); }
.mp__presets > .mp__qLabel { flex-basis: 100%; margin-bottom: 2px; }
.mp__presets .mp__opt { border-radius: 999px; }
.mp__qs > .mp__q { grid-template-columns: minmax(0, 1fr); gap: 9px; }
.mp__qs { gap: 22px; }
.mp__qs > .mp__q .mp__qHead { padding-top: 0; }
.mp__qs > .mp__q .mp__opt { padding: 10px 14px; }
.mp__qs > .mp__q:nth-of-type(5) .mp__opt { border-radius: 999px; padding: 7px 12px; }
.mp__inference { margin: -8px 0 0; max-width: 80ch; color: var(--ink-3); font-size: .78rem; line-height: 1.6; }
.mp__advGrid { grid-template-columns: repeat(auto-fit, minmax(min(290px, 100%), 1fr)); }
.mp__opts { min-width: 0; }
@media (max-width: 560px) {
  .mp__qs > .mp__q .mp__opt { flex: 1 1 140px; text-align: left; }
  .mp__presets .mp__opt { flex: 1 1 145px; }
}

/* Three shares of one ranking, drawn as one whole. Two grips sit on the boundaries; the third boundary is
   twelve o'clock and does not move, so the arithmetic is the same pair of numbers the bar used. Colours are
   a categorical set validated all-pairs in both modes. */
.mp__pieWrap { position: relative; width: min(186px, 100%); margin: -6px auto -8px; aspect-ratio: 1; touch-action: none; user-select: none; cursor: grab; }
.mp__pieWrap:active { cursor: grabbing; }
.mp__pie { display: block; width: 100%; height: 100%; overflow: visible; }
.mp__wedge { stroke: var(--toc-bg); stroke-width: 1.2; }
/* One colour per measure, named once here. The pie sets them, and anything else that names quality, cost
   or speed takes them from the same place so the two pictures cannot drift apart. */
:root { --m-quality: #57458f; --m-cost: #3a7d2c; --m-speed: #00829e; }
/* --line is a hairline between rows; --rule outlines a box — a tab, a panel, an axis — and has to hold
   its own against the surface rather than disappear into it. */
:root { --rule: #c2c9d2; }
.mp__wedge.is-q { fill: var(--m-quality); }
.mp__wedge.is-c { fill: var(--m-cost); }
.mp__wedge.is-s { fill: var(--m-speed); }
.mp__wedgeLabel { fill: #fff; pointer-events: none; }
.mp__wedgeName { font-size: 5px; font-weight: 600; letter-spacing: .08em; }
.mp__wedgeVal { font-size: 9px; font-weight: 700; }
.mp__pieGrip { position: absolute; width: 15px; height: 15px; margin: -7.5px 0 0 -7.5px; padding: 0; border: 2px solid var(--toc-bg); border-radius: 50%; background: var(--ink); box-shadow: 0 1px 3px #0004; cursor: grab; touch-action: none; }
.mp__pieGrip::before { content: ''; position: absolute; inset: -9px; border-radius: 50%; }
.mp__pieGrip:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.mp__pieKey { display: flex; flex-wrap: wrap; justify-content: center; gap: 4px 14px; margin-top: 2px; font-size: .78rem; color: var(--ink-2); }
.mp__pieKey[hidden] { display: none; }
.mp__pieKeyItem { display: inline-flex; align-items: center; gap: 6px; }
.mp__pieKeyItem::before { content: ''; width: 9px; height: 9px; border-radius: 2px; }
.mp__pieKeyItem.is-q::before { background: var(--m-quality); }
.mp__pieKeyItem.is-c::before { background: var(--m-cost); }
.mp__pieKeyItem.is-s::before { background: var(--m-speed); }
.mp__pieKeyItem b { color: var(--ink); font-variant-numeric: tabular-nums; }
/* the named balance as a shape, in the picker that sets it: the seam takes the surface it sits on */
.mp__miniPie { flex: none; width: 15px; height: 15px; margin-right: 7px; vertical-align: -3px; }
.mp__miniPie .mp__wedge { stroke: var(--surface); stroke-width: 2.5; }
.mp__pickVal .mp__miniPie { margin-right: 6px; }
@media (prefers-color-scheme: dark) {
  :root { --m-quality: #9a77ec; --m-cost: #5fbb45; --m-speed: #00a5ac; --rule: #434d59; }
  .mp__wedgeLabel { fill: #10151b; }
}

/* the two shortcut bars, above the chart */
.mp__presetRow { margin: 0 0 16px; padding: 12px 13px 13px; border: 1px solid var(--line); border-radius: 12px; }
.mp__presetLabel { display: block; margin-bottom: 8px; font-size: .72rem; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--ink-3); }
.mp__presetBars { display: flex; flex-wrap: wrap; gap: 10px 14px; }
.mp__seg--wrap { flex-wrap: wrap; }
/* The scenarios are not one control with six positions, which is what a welded bar says: they are six ways
   in, and only one of them is ever lit. Separate cards, sized to share the row, each with the name of the
   way in and under it the model it lands on. A named chip rather than the chart's ringed dot — the dot
   says "first" to someone already reading the plot, while a card read cold has to say which model that is. */
/* a grid, so a card that wraps to the next row keeps its column rather than stretching across it */
.mp__presetSet { display: grid; grid-template-columns: repeat(auto-fit, minmax(138px, 1fr)); gap: 6px; width: 100%; }
.mp__presetBtn { display: inline-flex; flex-direction: column; align-items: center; gap: 2px; min-width: 0; padding: 8px 10px; border: 1px solid transparent; border-radius: 9px; background: var(--toc-bg); color: var(--ink-2); font: inherit; font-size: .78rem; cursor: pointer; }
.mp__presetName { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
.mp__presetBtn:hover { border-color: var(--accent); color: var(--accent); }
.mp__presetBtn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.mp__presetBtn.is-on { border-color: var(--accent); background: var(--accent-wash); color: var(--accent); }
/* the model sits under the name as a second line of the label, not as a thing of its own: it is what the
   card resolves to, and a bordered pill made it look like a control inside a control */
/* a grid item's floor is its content unless it is told otherwise, which is what let a long model name
   push past the card instead of ellipsing inside it */
.mp__presetWin { display: grid; place-items: center; min-height: 20px; min-width: 0; max-width: 100%; }
.mp__presetWin.is-waiting::after { content: ''; width: 76px; height: 9px; border-radius: 999px; background: var(--line); opacity: .7; }
@media (prefers-reduced-motion: no-preference) {
  .mp__presetWin.is-waiting::after { animation: mp-wait 1.1s ease-in-out infinite; }
  @keyframes mp-wait { 0%, 100% { opacity: .35; } 50% { opacity: .8; } }
}
.mp__winName { display: inline-flex; align-items: center; min-width: 0; max-width: 100%; color: var(--ink-3); font-size: .72rem; font-weight: 500; }
.mp__winName b { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 500; }
/* the glyph rides on the card rather than in a badge: the badge exists to keep logos a uniform size in a
   dense list, and on a card with one model there is nothing to line it up with */
.mp__winName .mp__mark.mp__mark { width: 19px; min-width: 19px; max-width: 19px; height: 19px; min-height: 19px; flex: 0 0 19px; margin-right: 5px; border-radius: 0; background: none; }
.mp__winName .mp__mark.mp__mark svg { width: 16px; height: 16px; }
.mp__winName .mp__mark.mp__mark--mono { font-size: 9px; }
/* a preset that exists but has nothing behind it yet: readable, obviously off, and it says why on hover */
.mp__presetBtn.is-soon { position: relative; border-style: dashed; border-color: var(--line); background: none; color: var(--ink-3); cursor: not-allowed; }
.mp__presetBtn.is-soon > .mp__presetName { opacity: .55; }
.mp__winNone { font-size: .72rem; font-style: normal; font-weight: 500; color: var(--ink-3); opacity: .75; }
.mp__presetBtn.is-soon:hover { border-color: var(--line); color: var(--ink-3); }
.mp__presetBtn.is-soon:hover .mp__pop, .mp__presetBtn.is-soon:focus-visible .mp__pop { display: block; }

/* Same footprint in results, top pick, runners-up, and the details dialog. */
.mp__mark.mp__mark {
  box-sizing: border-box;
  display: inline-grid;
  place-items: center;
  width: 24px;
  min-width: 24px;
  max-width: 24px;
  height: 24px;
  min-height: 24px;
  flex: 0 0 24px;
  padding: 0;
  margin-right: 7px;
  border-radius: 6px;
  vertical-align: -5px;
  overflow: hidden;
}
.mp__mark.mp__mark svg { display: block; width: 15px; height: 15px; }
.mp__mark.mp__mark--mono { font-size: 9px; line-height: 1; letter-spacing: 0; white-space: nowrap; }

.mp__chart { margin: 0 0 18px; padding: 2px 0 10px; }
.mp__chart[hidden] { display: none; }
.mp__chartTitle { margin: 0 0 7px; font-size: 1.1rem; }
.mp__chartNote { margin: 8px 0 0; color: var(--ink-3); font-size: .76rem; line-height: 1.6; }
.mp__plotFrame { position: relative; padding: 14px 16px 26px 56px; margin-top: 2px; }
.mp__plotAxes { position: absolute; inset: 0; pointer-events: none; }
.mp__plot { position: relative; height: 285px; border-left: 1px solid var(--rule); border-bottom: 1px solid var(--rule); }
.mp__plotGrid { position: absolute; left: 0; right: 0; border-top: 1px dashed color-mix(in srgb, var(--line) 55%, var(--rule)); pointer-events: none; }
/* the bottom gridline would be drawn on top of the axis itself */
.mp__plotGrid.is-base { border-top: 0; }
.mp__plotGrid span { position: absolute; right: calc(100% + 9px); transform: translateY(-50%); font-size: .75rem; font-weight: 500; color: var(--ink-2); }
.mp__plotTick { position: absolute; top: calc(100% + 10px); transform: translateX(-50%); white-space: nowrap; font-size: .75rem; font-weight: 500; color: var(--ink-2); }
.mp__plotY { position: absolute; left: 0; top: 50%; writing-mode: vertical-rl; transform: translateY(-50%) rotate(180deg); white-space: nowrap; font-size: .84rem; font-weight: 600; color: var(--ink-2); }
.mp__axisScale { font-weight: 400; color: var(--ink-3); }
.mp__chartBottom { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 6px 14px; margin: 4px 0 0; }
.mp__chartBottom[hidden] { display: none; }
.mp__plotX { grid-column: 2; text-align: center; font-size: .84rem; font-weight: 600; color: var(--ink-2); margin: 0; }
.mp__chartBottom .mp__frontierKey { grid-column: 3; justify-self: end; font-size: .75rem; }
.mp__frontierKey[hidden] { display: none; }
@media (max-width: 760px) {
  .mp__chartBottom { grid-template-columns: minmax(0, 1fr); }
  .mp__plotX, .mp__chartBottom .mp__frontierKey { grid-column: 1; justify-self: center; }
}
/* The dot is the vendor's mark on a disc filled with the response-time colour. Marks are monochrome and
   inherit `color`, and --surface flips with the theme, so the glyph clears the whole ramp either way. */
/* Placed by a transform in pixels rather than by left/bottom, so a change of weighting or of axes is one
   compositor-driven move instead of twenty-five relayouts. --x/--y come from the layout pass; --nx/--ny are
   the overlap nudge; the -50% centres the dot on its own point. */
.mp__plotDot { position: absolute; left: 0; top: 0; display: grid; place-items: center; width: 31px; height: 31px; padding: 0; transform: translate(calc(var(--x, 0px) - 50% + var(--nx, 0px)), calc(var(--y, 0px) - 50% + var(--ny, 0px))) scale(var(--pop, 1)); border-radius: 50%; border: 2px solid var(--surface); background: var(--dot-color, var(--accent)); color: var(--surface); cursor: pointer; }
@media (prefers-reduced-motion: no-preference) {
  .mp__plotDot { transition: transform .52s cubic-bezier(.22, .61, .36, 1), background-color .35s ease, opacity .25s ease, width .25s ease, height .25s ease; }
}
/* a dot drawn for the first time is put in place before it is allowed to move, so it does not fly in */
.mp__plotDot.is-fresh { transition: none; }
.mp__plotGlyph { width: 17px; height: 17px; fill: currentColor; pointer-events: none; }
b.mp__plotGlyph { display: block; width: auto; height: auto; font-size: 10px; font-weight: 700; line-height: 1; letter-spacing: 0; }
/* The badge hangs outside the dot's circle, so it needs to be hit-testable in its own right: with
   pointer-events off, the part of it beyond the circle was dead space that neither hovered nor clicked the
   dot it belongs to. As a child of the button it inherits both. */
/* the medal is the badge: no disc behind it, and a ring of the page colour so it reads over any dot */
.mp__plotRank { position: absolute; top: -11px; right: -13px; display: block; font-size: 22px; font-style: normal; line-height: 1; text-shadow: 0 0 3px var(--surface), 0 0 3px var(--surface); cursor: pointer; }
/* a medalled dot sits above the plain ones, so nothing without a medal can cover one */
.mp__plotDot.is-top { z-index: 3; }
.mp__plotDot:hover, .mp__plotDot:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; z-index: 2; }
.mp__chartCards { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(230px, 100%), 1fr)); gap: 12px; margin-top: 18px; }
.mp__chartCard { display: flex; flex-direction: column; align-items: flex-start; gap: 9px; padding: 18px; color: var(--ink); background: var(--paper, transparent); border: 1px solid var(--line); border-radius: 9px; text-align: left; cursor: pointer; font: inherit; }
.mp__chartCard > span { font-size: .76rem; }
.mp__chartCard .mp__chartCardName { display: flex; align-items: center; font-size: .95rem; font-weight: 600; }
.mp__chartCard strong { font-size: 1.9rem; letter-spacing: -.04em; }
.mp__chartCard:hover, .mp__chartCard:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.mp__chartLink { color: var(--accent); }
@media (max-width: 560px) {
  .mp__chart { padding: 2px 0 8px; }
  .mp__plotFrame { padding-left: 46px; padding-right: 10px; }
  .mp__plot { height: 245px; }
}

.mp__resultScope { display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap; font-size: .8rem; color: var(--ink-3); }
.mp__resultScope[hidden] { display: none; }
.mp__plotDot:hover, .mp__plotDot:focus-visible { z-index: 5; }
.mp__plotTooltip { --tip-px: 13px; --tip-py: 12px; --tip-r: 9px; display: none; position: absolute; bottom: 100%; left: 50%; transform: translateX(-50%); width: 246px; max-width: 70vw; box-sizing: border-box; padding: var(--tip-py) var(--tip-px); text-align: left; background: var(--surface); color: var(--ink); border: 1px solid var(--line); border-radius: var(--tip-r); box-shadow: 0 8px 26px #00000026; font-size: 12px; line-height: 1.5; font-weight: 400; cursor: default; }
.mp__plotDot.is-left .mp__plotTooltip { left: 0; transform: none; }
.mp__plotDot.is-right .mp__plotTooltip { left: auto; right: 0; transform: none; }
.mp__plotDot:not(.is-dismissed):hover .mp__plotTooltip, .mp__plotDot:not(.is-dismissed):focus-visible .mp__plotTooltip { display: grid; gap: 5px; }
.mp__tipHead > strong { display: block; font-size: 14px; }
.mp__tipHead > span { display: block; color: var(--ink-3); }
.mp__plotTooltip > span { color: var(--ink-2); }
.mp__plotTooltip b { color: var(--ink); }
.mp__tooltipFacts { display: grid; gap: 4px; margin: 5px 0; }
.mp__tooltipFacts > span { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
/* how much of the quality score was measured, qualifying the score rather than standing beside it */
.mp__tooltipFacts > span > span { white-space: nowrap; }
.mp__tipCover { margin-right: 6px; color: var(--ink-3); font-style: normal; font-size: 11px; }
.mp__plotDot.is-below .mp__plotTooltip { bottom: auto; top: 100%; }

/* Two segmented bars, one line: which pair the plot draws, and how much of the ranking it covers. */
.mp__chartBars { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px; }
.mp__chartBars[hidden] { display: none; }
.mp__seg { display: inline-flex; border: 1px solid var(--line); border-radius: 999px; background: var(--surface); }
.mp__seg[hidden] { display: none; }
/* The ends are rounded on the buttons themselves rather than clipped by the bar. Clipping also cropped the
   focus ring, which is drawn inside the button and so ran straight into the bar's rounded corner. */
.mp__segBtn { padding: 6px 14px; border: 0; border-left: 1px solid var(--line); background: transparent; color: var(--ink-2); font: inherit; font-size: .78rem; white-space: nowrap; cursor: pointer; }
.mp__segBtn:first-child { border-left: 0; border-radius: 999px 0 0 999px; }
.mp__segBtn:last-child { border-radius: 0 999px 999px 0; }
.mp__segBtn:only-child { border-radius: 999px; }
.mp__segBtn:hover { color: var(--accent); }
.mp__segBtn.is-on { background: var(--accent-wash); color: var(--accent); font-weight: 600; }
.mp__segBtn:focus-visible { outline: 2px solid var(--accent); outline-offset: -3px; z-index: 1; }
/* each figure in the colour its measure wears in the pie, so the two pictures read as one page */
.mp__tooltipFacts > span.is-m-quality b { color: var(--m-quality); }
.mp__tooltipFacts > span.is-m-cost b { color: var(--m-cost); }
.mp__tooltipFacts > span.is-m-speed b { color: var(--m-speed); }
.mp__tooltipFacts > span.is-axis { font-weight: 500; }

.mp__speedLegend[hidden], .mp__plotFrame[hidden], .mp__plotX[hidden], .mp__chartCards[hidden] { display: none; }
/* The colour scale is the third axis, so it is named above the plot where an axis title belongs; the
   Pareto key is a different kind of thing and sits out of its way on the right. */
.mp__speedLegend { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 6px 14px; margin: 10px 0 0; font-size: .75rem; font-weight: 500; color: var(--ink-2); }
.mp__speedLegend[hidden] { display: none; }
.mp__speedLegend { grid-template-columns: minmax(0, 1fr); justify-items: center; }
.mp__legendMain { grid-column: 1; display: inline-flex; align-items: center; flex-wrap: wrap; justify-content: center; gap: 6px 12px; }
@media (max-width: 760px) {
  .mp__speedLegend { grid-template-columns: minmax(0, 1fr); }
  .mp__legendMain { grid-column: 1; justify-self: start; }
}
.mp__legendAxis { font-size: .84rem; font-weight: 600; color: var(--ink-2); }
.mp__frontierKey, .mp__speedUnknown { font-weight: 400; color: var(--ink-3); }
.mp__speedScale { display: flex; align-items: center; gap: 8px; }
.mp__speedRamp { display: inline-flex; }
.mp__speedStep { display: block; width: 19px; height: 10px; background: var(--dot-color); }
.mp__speedStep:first-of-type { border-radius: 3px 0 0 3px; }
.mp__speedStep:last-of-type { border-radius: 0 3px 3px 0; }

/* One hue in five steps for the third measure, each paired with the glyph colour measured to clear it: no step
   drops below 4:1 for the mark it carries, and the two themes are stepped separately against their own
   chart surface rather than flipped. Validated as an ordinal ramp (monotone lightness, single hue, pale end
   clear of the surface) before it shipped. */
.mp__plotDot.is-t1, .mp__speedStep.is-t1 { --dot-color: #ac9ad8; }
.mp__plotDot.is-t2, .mp__speedStep.is-t2 { --dot-color: #927bc7; }
.mp__plotDot.is-t3, .mp__speedStep.is-t3 { --dot-color: #7961ab; }
.mp__plotDot.is-t4, .mp__speedStep.is-t4 { --dot-color: #604c89; }
.mp__plotDot.is-t5, .mp__speedStep.is-t5 { --dot-color: #463765; }
/* The third measure keeps the colour it wears in the priorities pie, so "more purple" and "more quality"
   are the same fact on both pictures. Each ramp is the same five lightness steps at that measure's hue,
   with the chroma held near the others' so none of the three shouts louder; every step clears 4.4:1 for
   the mark it carries. The unclassed ramp above is quality's, which is what the plot colours by default. */
.is-hue-cost :is(.mp__plotDot, .mp__speedStep).is-t1 { --dot-color: #86c473; }
.is-hue-cost :is(.mp__plotDot, .mp__speedStep).is-t2 { --dot-color: #5fa94b; }
.is-hue-cost :is(.mp__plotDot, .mp__speedStep).is-t3 { --dot-color: #3a7d2c; }
.is-hue-cost :is(.mp__plotDot, .mp__speedStep).is-t4 { --dot-color: #2c6221; }
.is-hue-cost :is(.mp__plotDot, .mp__speedStep).is-t5 { --dot-color: #1e4718; }
.is-hue-speed :is(.mp__plotDot, .mp__speedStep).is-t1 { --dot-color: #6ab4be; }
.is-hue-speed :is(.mp__plotDot, .mp__speedStep).is-t2 { --dot-color: #319ba8; }
.is-hue-speed :is(.mp__plotDot, .mp__speedStep).is-t3 { --dot-color: #00808f; }
.is-hue-speed :is(.mp__plotDot, .mp__speedStep).is-t4 { --dot-color: #006573; }
.is-hue-speed :is(.mp__plotDot, .mp__speedStep).is-t5 { --dot-color: #004a54; }
@media (prefers-color-scheme: dark) {
  .is-hue-cost :is(.mp__plotDot, .mp__speedStep).is-t1 { --dot-color: #235a1a; }
  .is-hue-cost :is(.mp__plotDot, .mp__speedStep).is-t2 { --dot-color: #337d26; }
  .is-hue-cost :is(.mp__plotDot, .mp__speedStep).is-t3 { --dot-color: #46a034; }
  .is-hue-cost :is(.mp__plotDot, .mp__speedStep).is-t4 { --dot-color: #6ec257; }
  .is-hue-cost :is(.mp__plotDot, .mp__speedStep).is-t5 { --dot-color: #93da7d; }
  .is-hue-speed :is(.mp__plotDot, .mp__speedStep).is-t1 { --dot-color: #00666c; }
  .is-hue-speed :is(.mp__plotDot, .mp__speedStep).is-t2 { --dot-color: #00848b; }
  .is-hue-speed :is(.mp__plotDot, .mp__speedStep).is-t3 { --dot-color: #1ea2aa; }
  .is-hue-speed :is(.mp__plotDot, .mp__speedStep).is-t4 { --dot-color: #51bfc7; }
  .is-hue-speed :is(.mp__plotDot, .mp__speedStep).is-t5 { --dot-color: #84dce2; }
}

/* Each theme steps away from its own surface as the measure grows: the extreme end is the darkest mark on
   a light page and the brightest on a dark one, so "more of it" is the more present mark either way. Both
   directions land on the same two glyph colours, which is why this rule needs no theme of its own. */
@media (prefers-color-scheme: dark) {
  .mp__plotDot.is-t1, .mp__speedStep.is-t1 { --dot-color: #5f4d87; }
  .mp__plotDot.is-t2, .mp__speedStep.is-t2 { --dot-color: #7b64ae; }
  .mp__plotDot.is-t3, .mp__speedStep.is-t3 { --dot-color: #987ed3; }
  .mp__plotDot.is-t4, .mp__speedStep.is-t4 { --dot-color: #b49cef; }
  .mp__plotDot.is-t5, .mp__speedStep.is-t5 { --dot-color: #d1bfff; }
}
.mp__plotDot.is-t1, .mp__plotDot.is-t2 { color: var(--ink); }
.mp__plotDot.is-t3, .mp__plotDot.is-t4, .mp__plotDot.is-t5 { color: var(--surface); }
.mp__speedUnknown { display: inline-flex; align-items: center; gap: 5px; }
.mp__speedUnknown::before { content: ''; width: 9px; height: 9px; border: 1px dashed var(--ink-3); border-radius: 50%; }
.mp__plotDot.is-speed-unknown { background: var(--toc-bg); border-color: var(--ink-3); border-style: dashed; color: var(--ink-2); }

/* The Pareto frontier. A ring, not a colour: colour already carries response time, and the frontier is a
   yes/no, so it gets the one channel left that reads as a boundary rather than a quantity. */
.mp__plotDot.is-frontier { box-shadow: 0 0 0 2px var(--ink); }
.mp__plotDot.is-beaten { width: 25px; height: 25px; opacity: .72; }
.mp__plotDot.is-beaten .mp__plotGlyph { width: 14px; height: 14px; }

/* Enter and exit. These come after .is-beaten deliberately: same specificity, so source order is what lets
   a fading dot reach zero rather than settling at the faded opacity. */
.mp__plotDot.is-entering, .mp__plotDot.is-leaving { opacity: 0; --pop: .5; }
.mp__plotDot.is-leaving { pointer-events: none; }
@media (prefers-reduced-motion: no-preference) {
  .mp__plotDot.is-leaving { transition-duration: .3s; }
}
.mp__plotDot.is-beaten:hover, .mp__plotDot.is-beaten:focus-visible { opacity: 1; }
.mp__frontierKey { display: inline-flex; align-items: center; gap: 6px; }
.mp__frontierKey::before { content: ''; width: 10px; height: 10px; border-radius: 50%; background: transparent; box-shadow: 0 0 0 2px var(--ink); margin-right: 3px; }
.mp__tipFrontier { padding-top: 5px; border-top: 1px solid var(--line); }

/* ---------- the rail is the control panel ---------- */
/* The questions moved into the sticky column, so it scrolls on its own and the body keeps the answer. */
.anRail:has(.mp__inputs) { padding: 18px 14px; }
/* no rule under the questions: the one button below them is separation enough */
.mp__inputs { padding-bottom: 6px; margin-bottom: 4px; }
.anRail .mp__qs { gap: 16px; }
.anRail .mp__presets { gap: 6px; padding-bottom: 14px; }
.anRail .mp__opt { padding: 6px 10px; font-size: .78rem; }
.anRail .mp__qs > .mp__q .mp__opt { flex: 1 1 auto; padding: 7px 10px; }
.anRail .mp__qLabel { font-size: .82rem; }
.anRail .mp__wbar { height: 40px; }
.anRail .mp__wsegName { font-size: .55rem; letter-spacing: .05em; }
.anRail .mp__wsegVal { font-size: .78rem; }
.anRail .mp__advGrid { grid-template-columns: minmax(0, 1fr); }
.anRail__inline .mp__inputs { border-bottom: 0; }

/* ---------- result tabs ---------- */
.mp__tabs { display: flex; flex-wrap: wrap; gap: 4px; margin: 26px 0 0; }
.mp__tab { display: inline-flex; align-items: center; gap: 7px; padding: 9px 14px; margin-bottom: -1px; border: 1px solid transparent; border-bottom: 0; border-radius: 8px 8px 0 0; background: transparent; color: var(--ink-3); font: inherit; font-size: .85rem; cursor: pointer; }
.mp__tab[hidden] { display: none; }
.mp__tab:hover { color: var(--accent); }
.mp__tab.is-on { position: relative; z-index: 1; border-color: var(--line); background: var(--toc-bg); color: var(--ink); font-weight: 600; }
.mp__tab:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.mp__tabN { padding: 1px 7px; border-radius: 999px; background: var(--line); color: var(--ink-2); font-size: .72rem; font-weight: 600; font-variant-numeric: tabular-nums; }
.mp__tab.is-on .mp__tabN { background: var(--accent); color: var(--surface); }
.mp__panel { padding-top: 18px; }
.mp__panel[hidden] { display: none; }
.mp__panel:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }
.mp__panelMore { margin: 14px 0 0; color: var(--ink-3); font-size: .78rem; }

/* ---------- what does not apply, and why ---------- */
.mp__outGroup { margin-top: 20px; }
.mp__outH { margin: 0 0 9px; font-size: .84rem; font-weight: 600; color: var(--ink-2); }
.mp__outChips { display: flex; flex-wrap: wrap; gap: 6px; }
.mp__outChip { display: inline-flex; align-items: center; padding: 4px 10px 4px 5px; border: 1px solid var(--line); border-radius: 999px; color: var(--ink-3); font-size: .76rem; }
.mp__outChip .mp__mark { width: 18px; min-width: 18px; max-width: 18px; height: 18px; flex-basis: 18px; margin-right: 6px; border-radius: 5px; vertical-align: -4px; }
.mp__outChip .mp__mark svg { width: 11px; height: 11px; }
.mp__outChip--more { border-style: dashed; padding-left: 10px; }

/* ---------- results table ---------- */
/* One header for the whole list instead of a label beside every number, which is what makes two rows
   comparable at a glance and what makes sorting mean anything. The row is the control: clicking it opens
   the evidence, so there is no button competing with it for the same intent. */
/* Sticky headers. A box that scrolls in any direction captures `position: sticky`, and these wrappers
   scroll sideways only to rescue narrow screens — so above that width they do not scroll at all and the
   header can stick to the page instead of to a box the height of its own table. */
.mp__tableWrap { overflow-x: visible; }
@media (max-width: 900px) { .mp__tableWrap { overflow-x: auto; } }
.mp__table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: .84rem; }
.mp__table th { position: relative; padding: 0 0 8px; border-bottom: 1px solid var(--line); text-align: left; font-weight: 600; white-space: nowrap; }
.mp__thIn { display: inline-flex; align-items: center; gap: 1px; }
.mp__table th.is-num .mp__thIn { flex-direction: row-reverse; }
/* the header's own note, anchored under it and inside the table's scroll box; the last two columns open
   it leftwards so it does not run off the end */
.mp__table th > .mp__pop { position: fixed; top: 0; left: 0; right: auto; width: 250px; max-width: 250px; transform: none; font-weight: 400; letter-spacing: normal; text-transform: none; }
.mp__table th:hover > .mp__pop, .mp__table th:focus-within > .mp__pop { display: block; }
.mp__table th.is-num, .mp__table td.is-num { text-align: right; }
/* One width per column, so the same column is the same width whichever tab you are on: the tables are
   separate elements and auto layout would otherwise size each one to its own contents. The model name
   takes whatever is left. */
.mp__table th.mp__c-rank, .mp__table td.mp__c-rank { text-align: right; width: 4.2rem; }
.mp__table th.mp__c-ctx, .mp__table td.mp__c-ctx { width: 5.4rem; }
.mp__table th.mp__c-quality, .mp__table td.mp__c-quality { width: 5.4rem; }
.mp__table th.mp__c-time, .mp__table td.mp__c-time { width: 5.4rem; }
.mp__table th.mp__c-cost, .mp__table td.mp__c-cost { width: 6.4rem; }
.mp__table th.mp__c-pricein, .mp__table td.mp__c-pricein,
.mp__table th.mp__c-priceout, .mp__table td.mp__c-priceout { width: 6rem; }
.mp__table th.mp__c-reason, .mp__table td.mp__c-reason { width: 30%; }
/* the medal sits on the left of the cell, the number stays where the eye reads down the column */
/* the medal is the rank for the first three, standing where the number would have been */
.mp__medal { display: block; margin: -11px -9px; font-style: normal; font-size: 2rem; line-height: 1; }
/* the rank belongs to the row's first line, not to the middle of a cell two lines deep */
.mp__table td.mp__c-rank { vertical-align: top; padding-top: 11px; color: var(--ink-3); }
.mp__sort { display: inline-flex; align-items: center; gap: 4px; padding: 4px 6px; border: 0; border-radius: 6px; background: transparent; color: var(--ink-3); font: inherit; font-size: .74rem; font-weight: 600; letter-spacing: .03em; text-transform: uppercase; cursor: pointer; }
.mp__table th.is-num .mp__sort { flex-direction: row-reverse; }
.mp__sort:hover { color: var(--accent); }
.mp__sort:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.mp__sort.is-on { color: var(--ink); }
.mp__sortArrow { width: 0; height: 0; border-left: 3.5px solid transparent; border-right: 3.5px solid transparent; border-bottom: 5px solid currentColor; opacity: 0; }
.mp__sort.is-on .mp__sortArrow { opacity: 1; }
.mp__sort.is-on.is-desc .mp__sortArrow { transform: rotate(180deg); }
.mp__tr { border-bottom: 1px solid var(--line); cursor: pointer; }
.mp__tr:last-child { border-bottom: 0; }
.mp__tr:hover { background: var(--toc-bg); }
.mp__tr:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.mp__table td { padding: 9px 8px; vertical-align: middle; font-variant-numeric: tabular-nums; white-space: nowrap; }
/* the figures are a size down from the model they belong to: the name is what you scan, the numbers are
   what you compare once you have found the row */
.mp__table td.is-num { font-size: .78rem; }
.mp__table td.mp__c-name { font-variant-numeric: normal; min-width: 15rem; white-space: normal; }
.mp__cellName { display: flex; align-items: center; font-size: .92rem; }
.mp__cellName b { font-weight: 600; }
.mp__cellSub { display: block; margin-top: 2px; padding-left: 31px; color: var(--ink-3); font-size: .72rem; }
.mp__cellSub code { font-size: .95em; }
/* One hue, its strength standing for how good the number is within its own column. The wash is drawn on
   the figure rather than on the cell holding it: a full-bleed cell turned the table into a grid of blocks
   you read before the numbers, where a chip the width of the figure keeps the number the thing you see and
   still lets the eye run down a column to its good end. */
.mp__heat { display: inline-block; padding: 2px 7px; margin: -2px -3px; border-radius: 5px; background: color-mix(in srgb, var(--accent) calc(var(--heat, 0) * 24%), transparent); }
/* The top pick, marked the way the handbook marks an anecdote: the story wash with a 3px bar down its
   left edge. Its figures wash toward the same hue rather than the chart's teal — teal over a warm wash
   reads as neither — so the row keeps its own colour and still shows which of its numbers are the good
   ones. */
.mp__tr.is-win { background: var(--story-wash); }
.mp__tr.is-win .mp__heat { background: color-mix(in srgb, var(--story) calc(var(--heat, 0) * 26%), transparent); }
.mp__tr.is-win td:first-child { box-shadow: inset 3px 0 0 var(--story); }
.mp__tr.is-win .mp__cellName b { color: var(--story); }
.mp__placeNone { color: var(--ink-3); }
@media (max-width: 1100px) {
  .mp__table th.mp__c-priceout, .mp__table td.mp__c-priceout { display: none; }
}
@media (max-width: 900px) {
  .mp__table th.mp__c-pricein, .mp__table td.mp__c-pricein { display: none; }
}
@media (max-width: 720px) {
  .mp__table th.mp__c-ctx, .mp__table td.mp__c-ctx { display: none; }
}

/* The chart is the answer, so it sits as close to the byline as the type allows. */
.page--tearsheet .tsSec#picker { margin-top: 20px; }
.page--tearsheet .tsHead { margin-bottom: 0; }

/* The open tab and the table header it belongs to are one surface: the header moved up against the tab bar
   and took its background, so the selected tab reads as the lid of the table rather than a chip above it. */
/* The tab is the lid of a box, so the panel draws the other three sides and the table sits inside it —
   the same frame the sources table has, which is what makes the tab read as a tab rather than a chip
   floating over a list. */
.mp__panel { position: relative; padding-top: 0; border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); }
/* the corner under the open tab is square, because the tab is sitting on it; every other one is round.
   The first tab covers the left corner, so only that case loses it. */
.mp__panels.is-firstTab > .mp__panel { border-top-left-radius: 0; }
/* no inset on the wrapper: 2px of padding here showed the panel's white fill either side of the header
   band, which read as a hairline gap inside the border */
.mp__panel > .mp__tableWrap { padding: 0; }
/* the header band has to reach into the panel's rounded corners, or the fill stops short and the curve
   shows through as a white nick either side */
.mp__panel .mp__table thead th:first-child { border-top-left-radius: var(--radius); }
.mp__panel .mp__table thead th:last-child { border-top-right-radius: var(--radius); }
.mp__panels.is-firstTab .mp__table thead th:first-child { border-top-left-radius: 0; }
.mp__table thead th:first-child { padding-left: 14px; }
.mp__table thead th:last-child { padding-right: 14px; }
.mp__table td:first-child { padding-left: 14px; }
.mp__table td:last-child { padding-right: 14px; }
.mp__table tbody tr:last-child td { border-bottom: 0; }
.mp__panelMore { margin: 0; padding: 12px 14px; border-top: 1px solid var(--line); color: var(--ink-3); font-size: .8rem; }
.mp__empty { margin: 0; padding: 16px 14px; }
/* The tab explains itself on hover, above the strip so it does not cover the table it is describing. */
.mp__tab { position: relative; cursor: pointer; }
.mp__tab .mp__pop { top: auto; bottom: calc(100% + 8px); cursor: default; }
.mp__tab:hover .mp__pop, .mp__tab:focus-visible .mp__pop { display: block; }
@media (max-width: 560px) { .mp__tab .mp__pop { left: 0; transform: none; } }
/* The tab strip pins along with the header it labels. A header band on its own, halfway down a long list,
   does not say which list it belongs to; the tab does. The strip stacks above the header, and the header
   drops by the strip's measured height (--mp-tabH, set from JS because the tabs wrap on narrow screens)
   so the two sit flush instead of overlapping. */
.mp__tabs { position: sticky; top: 0; z-index: 7; background: var(--surface); }
.mp__table thead th { position: sticky; top: var(--mp-tabH, 40px); z-index: 6; background: var(--toc-bg); padding: 11px 8px; border-bottom: 1px solid var(--line); }
.mp__table thead th:first-child, .mp__table thead th:last-child { border-radius: 0; }
.mp__tableWrap { padding-bottom: 2px; }

/* The sources table: the row tint is the hit target's feedback, so it runs the full width of the card
   rather than stopping at the cells. The card's side padding moves onto the outer cells to get there. */
/* the shared rule pairs overflow-x: auto with overflow-y: hidden, and either one turns this into a scroll
   container that would swallow the sticky header; both have to go */
.scoreWrap--flush { padding-left: 0; padding-right: 0; overflow-x: visible; overflow-y: visible; }
@media (max-width: 900px) { .scoreWrap--flush { overflow-x: auto; overflow-y: hidden; } }
.scoreWrap--flush .score--src th:first-child, .scoreWrap--flush .score--src td:first-child { padding-left: 18px; }
.scoreWrap--flush .score--src th:last-child, .scoreWrap--flush .score--src td:last-child { padding-right: 18px; }

/* the byline stamp is a link down to those sources */
/* the shared rule indents this badge because elsewhere it sits beside a byline; here it is the first
   thing on its line, and the indent held it 10px off the left edge everything else lines up on */
.tsHead .hbHead__stamp .tsHead__upd { margin-left: 0; }
a.tsHead__upd { text-decoration: none; }
a.tsHead__upd:hover { background: var(--accent); color: var(--surface); }
a.tsHead__upd:hover b { color: var(--surface); }
a.tsHead__upd:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ---------- the control panel ---------- */
/* Every control has the same shape: a bold label, the control under it. One line per question whatever the
   option list is, which is what makes showing all of them possible. */
/* min-width:0 the whole way down. The value inside a picker is white-space:nowrap, so its min-content
   width is the entire string; every grid item above it defaults to min-width:auto and so refuses to shrink
   below that, and the column grows instead of the text ellipsising. */
.mp__inputs, .mp__qs > *, .mp__f, .mp__pick, .mp__pickBtn { min-width: 0; }
/* the one field you type at rather than pick from: same shell, a caret instead of a chevron */
.mp__pickInput { width: 100%; box-sizing: border-box; font: inherit; color: var(--ink); cursor: text; }
.mp__pickInput::placeholder { color: var(--ink-3); }
/* when the placeholder is the answer rather than a prompt, it reads like one */
.mp__pickInput.has-pick::placeholder { color: var(--ink); }
.mp__pickMenu.is-empty::after { content: 'No vendor by that name'; display: block; padding: 8px 12px; color: var(--ink-3); font-size: .78rem; }
.mp__f { display: block; margin-bottom: 11px; }
/* a field that was changed for you, saying so for a moment */
@media (prefers-reduced-motion: no-preference) {
  .mp__f.is-flash { animation: mp-flash 1.5s ease-out; border-radius: 8px; }
  /* the handbook's anecdote wash, which is the page's colour for "look here" */
  @keyframes mp-flash {
    0%, 25% { background: var(--story-wash); box-shadow: 0 0 0 6px var(--story-wash); }
    100% { background: transparent; box-shadow: 0 0 0 6px transparent; }
  }
}
.mp__fWrap[hidden], .mp__f[hidden] { display: none; }
.mp__fHead { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 3px; }
.mp__fLabel { display: block; margin-bottom: 3px; font-size: .78rem; font-weight: 700; color: var(--ink); }
.mp__fHead .mp__fLabel { margin-bottom: 0; }
/* the tip belongs to the name, so it sits against it rather than out at the column's far edge */
.mp__fHead--tip { justify-content: flex-start; gap: 5px; }
.mp__fTip { display: inline-grid; place-items: center; width: 18px; height: 18px; padding: 0; border: 0; border-radius: 50%; background: none; color: var(--ink-3); cursor: help; }
.mp__fTip:hover { color: var(--accent); }
.mp__fTip .act__icon { width: 14px; height: 14px; }
.mp__fTip:hover .mp__pop, .mp__fTip:focus-visible .mp__pop { display: block; }
/* The rail is a scroll container, so a popover anchored to the icon is clipped by its right edge rather
   than floating over the page. It measures against the label row instead, which is the field's own width:
   inside the rail whatever the rail can show, and never off the side of it. */
.mp__fHead { position: relative; }
.mp__fTip .mp__pop { top: calc(100% + 6px); left: 0; right: 0; width: auto; max-width: none; transform: none; }
.mp__popList { margin: 0 0 9px; padding: 0; list-style: none; display: grid; gap: 7px; }
.mp__popList:last-child { margin-bottom: 0; }
.mp__popList b { color: var(--ink); }
.mp__fNote { margin: 3px 0 0; font-size: .71rem; line-height: 1.5; color: var(--ink-3); }
/* One dropdown for every choice. The value is allowed to run out of room and ellipsis: a long multiple
   selection must not be able to widen the column it sits in. min-width:0 is what lets it — a flex item
   will not shrink below its content without it, and the ellipsis never fires. */
.mp__pick { position: relative; }
.mp__pickBtn { display: flex; align-items: center; justify-content: space-between; gap: 8px; width: 100%; padding: 7px 9px; border: 1px solid var(--line); border-radius: 7px; background: var(--surface); color: var(--ink); font: inherit; font-size: .8rem; text-align: left; cursor: pointer; }
.mp__pickBtn:hover { border-color: var(--accent); }
.mp__pickBtn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.mp__pickVal { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mp__pickBtn .act__icon { flex: 0 0 auto; width: 13px; height: 13px; transform: rotate(90deg); color: var(--ink-3); }
.mp__pick.is-open .mp__pickBtn { border-color: var(--accent); }
.mp__pick.is-open .mp__pickBtn .act__icon { transform: rotate(-90deg); }
.mp__pickMenu { display: none; position: absolute; z-index: 9; top: calc(100% + 4px); left: 0; right: 0; max-height: 280px; overflow-y: auto; overscroll-behavior: contain; padding: 5px; background: var(--surface); border: 1px solid var(--line); border-radius: 8px; box-shadow: 0 8px 26px #00000026; }
.mp__pick.is-open .mp__pickMenu { display: block; }
/* flipped when the field sits near the bottom of the scrolling panel */
.mp__pick.is-up .mp__pickMenu { top: auto; bottom: calc(100% + 4px); }
.mp__pickRow { display: flex; align-items: flex-start; gap: 7px; padding: 6px 7px; border-radius: 5px; font-size: .78rem; cursor: pointer; }
/* `display: flex` above beats the browser's own [hidden] rule, so the type-ahead's hidden rows kept
   showing: the property was set and nothing moved. */
.mp__pickRow[hidden] { display: none; }
/* the arrow keys' marker: the caret stays in the box, so the list needs its own sense of "here" */
.mp__pickRow.is-active { background: var(--toc-bg); }
.mp__pickRow.is-active.is-on { background: var(--accent-wash); }
/* an answer the catalog cannot give, present so its absence is on the record */
.mp__pickRow.is-off { color: var(--ink-3); cursor: not-allowed; }
.mp__pickRow.is-off:hover { background: none; }
.mp__pickRow.is-off .mp__pickTick { visibility: hidden; }
.mp__pickRow:hover { background: var(--toc-bg); }
.mp__pickRow:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.mp__pickRow.is-on { color: var(--accent); font-weight: 600; }
.mp__pickTick { flex: 0 0 auto; width: 13px; height: 13px; margin-top: 2px; opacity: 0; }
.mp__pickRow.is-on .mp__pickTick { opacity: 1; }
.mp__pickTick svg { width: 13px; height: 13px; fill: none; stroke: var(--accent); stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.mp__pickText { min-width: 0; }
.mp__pickHint { display: block; color: var(--ink-3); font-weight: 400; font-size: .7rem; }
/* the pie's preset picker shares the widget but not its width */
.mp__pickHost { max-width: 58%; }
.mp__pickHost .mp__pickBtn { padding: 3px 7px; font-size: .72rem; color: var(--ink-2); }
.mp__pickHost .mp__pickMenu { left: auto; right: 0; width: max-content; min-width: 100%; }

.mp__sliderRow { display: flex; align-items: center; gap: 10px; }
.mp__sliderRow .mp__range { flex: 1 1 auto; }
.mp__sliderOut { flex: 0 0 auto; min-width: 5.2rem; text-align: right; font-size: .75rem; font-weight: 600; font-variant-numeric: tabular-nums; color: var(--ink); }
.mp__range { -webkit-appearance: none; appearance: none; width: 100%; height: 18px; margin: 0; background: transparent; cursor: pointer; }
.mp__range::-webkit-slider-runnable-track { height: 5px; border-radius: 999px; background: linear-gradient(to right, var(--accent) var(--fill, 0%), var(--line) var(--fill, 0%)); }
.mp__range::-moz-range-track { height: 5px; border-radius: 999px; background: linear-gradient(to right, var(--accent) var(--fill, 0%), var(--line) var(--fill, 0%)); }
.mp__range::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 14px; height: 14px; margin-top: -4.5px; border-radius: 50%; background: var(--accent); border: 2px solid var(--surface); box-shadow: 0 1px 3px #0003; }
.mp__range::-moz-range-thumb { width: 14px; height: 14px; border-radius: 50%; background: var(--accent); border: 2px solid var(--surface); box-shadow: 0 1px 3px #0003; }
.mp__range:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 999px; }

/* the shared popover, used by the tab info tip and by a preset that is switched off */
.mp__pop { display: none; position: absolute; z-index: 8; top: calc(100% + 8px); left: 50%; transform: translateX(-50%); width: 290px; max-width: min(290px, 78vw); padding: 12px 14px; box-sizing: border-box; text-align: left; font-size: .76rem; font-weight: 400; line-height: 1.6; color: var(--ink-2); background: var(--surface); border: 1px solid var(--line); border-radius: 9px; box-shadow: 0 8px 26px #00000026; white-space: normal; cursor: default; }


/* The headline is set to the measure of the body column, not folded at 20ch: over a full-width table a
   two-line title just reads as a wrap in the wrong place. */
.tsHead h1 { max-width: none; }

/* ---------- the settings drawer ---------- */
/* Under the rail's breakpoint the controls move behind a hamburger rather than stacking above the answer:
   twenty fields is a screen and a half of scrolling before the first result. Sticky, not fixed — see the
   handbook's contents for why a fixed anchor ratchets the page wider on mobile. */
.mp__drawer[hidden] { display: none; }
.mp__drawer { position: sticky; top: 10px; z-index: 50; width: 44px; height: 44px; margin: 0 0 4px auto; }
.mp__drawerBtn { display: flex; align-items: center; justify-content: center; width: 44px; height: 44px; border: 1px solid var(--line); border-radius: 50%; background: var(--surface); color: var(--ink); box-shadow: 0 2px 12px rgb(0 0 0 / 10%); cursor: pointer; list-style: none; position: relative; z-index: 1; }
.mp__drawerBtn::-webkit-details-marker { display: none; }
.mp__drawer .burger { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; }
.mp__drawer .burger--close, .mp__drawer[open] .burger { display: none; }
.mp__drawer[open] .burger--close { display: block; }
.mp__drawerBody { position: absolute; top: -10px; right: -12px; width: min(86vw, 340px); height: 100vh; height: 100dvh; overflow-y: auto; overscroll-behavior: contain; padding: 60px 14px 28px; background: var(--surface); border-left: 1px solid var(--line); box-shadow: -14px 0 34px rgb(0 0 0 / 16%); }
.mp__drawerBody .rail { padding: 0; background: none; }
.mp__drawerBody .anRail { position: static; max-height: none; }

/* Reset and Share sit on the stamp line, sized to it rather than to the panel they came from. */
/* the stamp names the moment the answer was built; the two buttons that act on the whole answer ride
   the same line, pushed to its far edge */
.tsHead .hbHead__stamp { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.mp__headBtns { display: flex; gap: 8px; margin-left: auto; }
.mp__headBtns .sim__btn { padding: 3px 11px; border-radius: 999px; font-size: .72rem; font-weight: 600; letter-spacing: 0; text-transform: none; }
@media (max-width: 640px) { .mp__headBtns { margin: 8px 0 0; } }

/* Model explanation: verdict first, exact arithmetic and sources on demand. */
.mp__exDialog { width: min(920px, calc(100vw - 24px)); padding: 16px 26px 26px; font-size: .84rem; }
.mp__exDialog .rail__howBody { margin: 6px -26px 0; padding: 0 26px 2px; }
.mp__exHeader { padding-right: 58px; }
.mp__exHeader h2 { display: flex; align-items: center; gap: 5px; margin: 0 0 8px; font-size: 1.65rem; letter-spacing: -.035em; color: var(--ink); }
.mp__exHeader p { margin: 0; font-size: .82rem; color: var(--ink-3); }
.mp__exHeader .mp__exEyebrow { font-size: .7rem; text-transform: uppercase; letter-spacing: .08em; font-weight: 700; color: var(--accent); }
.mp__exVerdict { line-height: 1.7; margin: 20px 0; color: var(--ink); }
.mp__exSection { border-top: 1px solid var(--line); padding-top: 22px; margin-top: 24px; }
.mp__exSection h3 { margin: 0 0 9px; color: var(--ink); font-size: .98rem; letter-spacing: -.02em; }
.mp__exSection p { line-height: 1.65; }
.mp__exDialog .mp__exNote { color: var(--ink-2); line-height: 1.65; }
.mp__exParts { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin-top: 16px; }
.mp__exPart { --ex-color: var(--m-quality); padding: 14px; border: 1px solid var(--line); border-top: 3px solid var(--ex-color); border-radius: 9px; }
.mp__exPart.is-c { --ex-color: var(--m-cost); }
.mp__exPart.is-s { --ex-color: var(--m-speed); }
.mp__exPart > div { display: flex; justify-content: space-between; gap: 8px; flex-wrap: wrap; align-items: baseline; }
.mp__exPart h4 { margin: 0; font-size: .82rem; color: var(--ink); }
.mp__exPart span { font-size: .72rem; }
.mp__exPart > b { display: block; margin: 12px 0; font-size: 1.35rem; color: var(--ink); }
.mp__exPart small { font-size: .7rem; font-weight: 400; color: var(--ink-3); }
.mp__exPart .mp__bar { display: block; width: 100%; }
.mp__exPart .mp__bar i { background: var(--ex-color); }
.mp__exPart p { margin: 8px 0 0; font-size: .7rem; color: var(--ink-3); }
.mp__exEquation { text-align: center; font-variant-numeric: tabular-nums; }
.mp__exEquation span { display: block; font-size: .7rem; color: var(--ink-3); }
.mp__exDeltas { display: flex; flex-wrap: wrap; gap: 8px 20px; font-size: .78rem; }
.mp__exDeltas b { margin-left: 5px; font-variant-numeric: tabular-nums; }
/* One grid for the whole list rather than one per row: a row of its own sized its columns to its own
   text, so "0% measured" and "100% measured" pulled their bars to different lengths. */
.mp__exAxes { display: grid; grid-template-columns: 1.2fr 1fr auto; gap: 13px 15px; align-items: center; margin: 18px 0; }
.mp__exAxes > div { display: contents; }
.mp__exAxes > div > div { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px; }
.mp__exAxes span { color: var(--ink-2); }
.mp__exAxes .mp__bar { width: 100%; }
.mp__benchTable { min-width: 560px; }
.mp__benchTable td, .mp__benchTable th { padding: 10px 16px 10px 0; font-size: .8rem; line-height: 1.6; vertical-align: top; }
.mp__benchTable tbody th { width: 30%; white-space: normal; font-weight: 600; }
.mp__benchTable tbody th a { color: var(--ink); }
.mp__benchMeta { display: block; margin-top: 3px; font-size: .7rem; font-weight: 400; line-height: 1.55; color: var(--ink-3); }
.mp__benchTable .is-num { text-align: right; white-space: nowrap; font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
.mp__benchTable tbody tr { transition: background-color .12s ease; }
.mp__benchTable tbody tr:hover { background: var(--toc-bg); }
.mp__benchTable tr.is-gap th a, .mp__benchTable tr.is-gap td { color: var(--ink-3); }
.mp__benchGap { display: inline-flex; align-items: center; gap: 6px; font-weight: 500; color: var(--ink-3); }
.mp__benchGap .mark { width: 17px; height: 17px; padding: 3px; }
.mp__exFacts { margin: 8px 0; }
.mp__exFacts > div { display: grid; grid-template-columns: 1fr 1fr; gap: 15px; padding: 10px 0; border-bottom: 1px solid var(--line); }
.mp__exFacts > div:last-child { border-bottom: 0; }
.mp__exFacts dd { margin: 0; color: var(--ink); overflow-wrap: anywhere; }
.mp__exTable { overflow-x: auto; }
.mp__exEvidence .mp__exTable { margin-top: 22px; }
.mp__exAlert { padding: 12px; border-left: 3px solid var(--no); background: var(--no-wash); }
@media (max-width: 600px) {
  .mp__exDialog { padding: 18px 15px; }
  .mp__exDialog .rail__howBody { margin-left: -15px; margin-right: -15px; padding-left: 15px; padding-right: 15px; }
  .mp__exHeader h2 { font-size: 1.35rem; }
  .mp__exParts { grid-template-columns: minmax(0, 1fr); }
  .mp__exAxes { grid-template-columns: minmax(0, 1fr); gap: 16px; }
  .mp__exAxes > div { display: grid; grid-template-columns: 1fr auto; gap: 4px 12px; align-items: center; }
  .mp__exAxes .mp__bar { grid-row: 2; grid-column: 1 / -1; }
}

/* Keep rank, dismissal, and model navigation visible while the explanation scrolls. */
.mp__exTop { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex: 0 0 auto; }
.mp__exTop .rail__dialogClose { position: static; }
.mp__exTop .mp__exEyebrow { color: var(--accent); font-size: .78rem; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; }
.mp__exHeader { padding: 0 0 18px; border-bottom: 1px solid var(--line); }
.mp__exHeader h2 { gap: 12px; margin: 0 0 14px; }
.mp__exHeader .mp__mark.mp__mark { width: 44px; min-width: 44px; max-width: 44px; height: 44px; min-height: 44px; flex-basis: 44px; border-radius: 11px; margin: 0; font-size: 15px; }
.mp__exHeader .mp__mark.mp__mark svg { width: 29px; height: 29px; }
.mp__exSubtitle { display: flex; flex-wrap: wrap; gap: 12px 32px; margin: 0; }
.mp__exSubtitle > div { display: grid; gap: 4px; }
.mp__exSubtitle dt { text-transform: uppercase; letter-spacing: .05em; color: var(--ink-3); }
.mp__exSubtitle dd { margin: 0; color: var(--ink); }
.mp__exTabs { display: flex; gap: 4px; margin-top: 22px; }
.mp__exTabs button { flex: 1; position: relative; z-index: 1; margin-bottom: -1px; padding: 10px 8px 11px; background: transparent; border: 1px solid var(--rule); border-radius: 11px 11px 0 0; font: inherit; font-weight: 600; color: var(--ink-3); cursor: pointer; }
.mp__exTabs button span { display: block; font-weight: 400; margin-top: 3px; }
.mp__exTabs button:hover { color: var(--ink); }
.mp__exTabs button:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.mp__exDialog [role="tabpanel"][hidden] { display: none; }
/* the open tab and its panel are one shape: same tint, same border, and no line between them */
.mp__exDialog [role="tabpanel"] { border: 1px solid var(--rule); border-radius: 0 0 12px 12px; padding: 18px; background: var(--surface); }
.mp__exDialog [role="tabpanel"] > .mp__exSection:first-child { margin-top: 0; border-top: 0; padding-top: 0; }
.mp__exDialog [role="tabpanel"] > :first-child { margin-top: 0; }
.mp__exNav { flex: 0 0 auto; display: flex; justify-content: space-between; align-items: center; gap: 10px; border-top: 1px solid var(--line); margin-top: 18px; padding-top: 14px; }
.mp__exNav > span { color: var(--ink-3); font-size: .7rem; text-align: center; }
.mp__exNav button { margin: 0; white-space: nowrap; }
.mp__exNav button:disabled { opacity: .4; cursor: default; }
@media (max-width: 600px) {
  .mp__exNav { gap: 6px; }
  .mp__exNav button { padding: 8px; font-size: .74rem; }
  .mp__exTabs button { font-size: .78rem; }
}

/* Compact header and four factor-specific panels. */
.mp__exTop { gap: 12px; }
.mp__exTop .mp__exNav { margin: 0 0 0 auto; padding: 0; border: 0; gap: 6px; }
/* Previous, Next and Close are one row of controls, so they are one size and one height */
.mp__exTop .mp__exNav button, .mp__exTop .rail__dialogClose { padding: 6px 12px; border-radius: 8px; font-size: .84rem; font-weight: 600; line-height: 1.5; }
.mp__exHeader { margin-left: -26px; margin-right: -26px; padding-left: 26px; padding-right: 26px; padding-bottom: 14px; }
.mp__exHeader h2 { margin-bottom: 10px; }
.mp__exSubtitle { gap: 8px 24px; }
.mp__exSubtitle > div { display: flex; align-items: baseline; gap: 7px; }
.mp__exSubtitle dt { text-transform: none; letter-spacing: 0; font-size: .76rem; white-space: nowrap; }
.mp__exSubtitle dt::after { content: ':'; }
.mp__exTabs [data-part="q"] { --factor-color: var(--m-quality); }
.mp__exTabs [data-part="c"] { --factor-color: var(--m-cost); }
.mp__exTabs [data-part="s"] { --factor-color: var(--m-speed); }
.mp__exTabs [data-part="info"]::before { display: none; }
/* The measure's colour is a straight bar inside the top edge, not a coloured border: a border follows the
   rounded corner and bleeds the colour down both sides, which is not what a wedge of the pie looks like.
   Same three values the pie fills its wedges with, so the tab and the wedge are recognisably one measure. */
.mp__exTabs button { padding: 10px 6px 11px; overflow: hidden; }
.mp__exTabs button::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 4px; background: var(--factor-color); opacity: .6; }
.mp__exTabs button[aria-selected="true"]::before { opacity: 1; }
.mp__exTabs button[aria-selected="true"] { color: var(--ink); background: var(--surface); border-bottom-color: var(--surface); }
/* the tab carries the standing on this factor; the weight rides beside the name */
.mp__exTabName { font-size: .84rem; font-weight: 500; }
.mp__exTabs button[aria-selected="true"] .mp__exTabName { font-weight: 700; }
.mp__exTabName small { font-size: .76rem; font-weight: 500; opacity: .85; }
.mp__exTabs button > span + span { margin-top: 3px; font-weight: 400; font-size: .78rem; }
.mp__exSubhead { margin: 22px 0 8px; font-size: .92rem; }
/* three lists side by side: inputs, outputs, and everything else a model either does or does not do */
.mp__capGroups { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 4px 22px; }
.mp__capGroups > p { grid-column: 1 / -1; }
.mp__capGroups h3, .mp__exInfo h3 { font-size: .92rem; margin: 18px 0 10px; color: var(--ink); }
.mp__capGroups h3 { margin-top: 0; }   /* the three lists start level; nothing sits above them any more */
.mp__capList { display: grid; gap: 1px; padding: 0; margin: 0; list-style: none; }
.mp__capList li { display: grid; grid-template-columns: 21px 1fr; gap: 9px; align-items: start; padding: 4px 8px; margin: 0 -8px; border-radius: 6px; color: var(--ink-2); }
.mp__capList .mark { width: 21px; height: 21px; padding: 4px; margin-top: .05em; }
.mp__capList li.is-required { background: var(--story-wash); }
.mp__capList li.is-required .txt { font-weight: 700; }
/* providers: price, endpoint and uptime on one row, with the money right-aligned so a column reads down */
.mp__whyProv td, .mp__whyProv th { padding: 9px 14px 9px 0; font-size: .8rem; }
.mp__whyProv tbody th { width: 26%; white-space: normal; font-weight: 600; }
.mp__whyProv tbody th .mp__tag { margin-left: 5px; vertical-align: middle; }
.mp__provHq { display: block; margin-top: 2px; font-size: .7rem; font-weight: 400; color: var(--ink-3); }
.mp__whyProv .is-num { text-align: right; padding-left: 14px; font-variant-numeric: tabular-nums; }
.mp__whyProv tbody tr { transition: background-color .12s ease; }
.mp__whyProv tbody tr:hover { background: var(--toc-bg); }
.mp__hostUp { white-space: nowrap; padding-left: 12px; }
.mp__hostUp .src__bar { display: inline-block; width: 68px; margin: 0 8px 0 0; vertical-align: middle; }
.mp__hostUp b { font-size: .76rem; font-variant-numeric: tabular-nums; }
@media (max-width: 600px) {
  .mp__exTop { flex-wrap: wrap; }
  .mp__exTop .mp__exEyebrow { flex: 1; }
  .mp__exTop .rail__dialogClose { order: 1; }
  .mp__exTop .mp__exNav { order: 2; flex-basis: 100%; justify-content: flex-end; }
  .mp__exHeader { margin-left: -15px; margin-right: -15px; padding-left: 15px; padding-right: 15px; }
  .mp__exTabs { gap: 2px; }
  .mp__exTabs button { font-size: .72rem; padding-left: 3px; padding-right: 3px; }
  .mp__exTabs button { border-radius: 8px 8px 0 0; }
  .mp__exTabName { font-size: .76rem; }
  .mp__exTabName small { font-size: .68rem; }
  .mp__exTabs button > span + span { font-size: .7rem; }
  .mp__exDialog [role="tabpanel"] { padding: 14px; }
  .mp__capGroups { grid-template-columns: minmax(0, 1fr); }
  .mp__dimensionStanding { flex-wrap: wrap; gap: 5px; }
}

/* each source says when it last ran and how far into this catalog it reaches, in its own column */
.score--src th.src__whenHead, .score--src td.src__when { width: 9.5rem; }
.src__stat { display: block; font-size: .74rem; font-weight: 400; line-height: 1.5; color: var(--ink-3); }
.src__stat span { display: block; }
.src__stat b { display: block; color: var(--ink); font-weight: 700; font-size: .8rem; }
.src__stat time { border-bottom: 1px dotted var(--line); cursor: help; }
/* how much of the catalog this source reaches, as a share rather than a count */
.src__bar { height: 5px; margin: 7px 0 5px; border-radius: 999px; background: var(--line); overflow: hidden; }
.src__bar i { display: block; height: 100%; border-radius: 999px; background: var(--accent); }
/* the do/don't pair the handbook uses, at table density */
.src__points { margin: 0; gap: 8px; max-width: none; }
.src__points li { grid-template-columns: 19px 1fr; gap: 9px; }
.src__points .mark { width: 19px; height: 19px; padding: 3.5px; }
/* the benchmarks that were considered and left out, in their own table */
.score--unused tbody th { white-space: normal; width: 18%; min-width: 13ch; }
.score--src th[scope="row"] > a { display: inline-flex; align-items: center; gap: 4px; color: var(--ink); }
/* the prose measurements, beside the same counts over human writing */
.mp__exProse h3 a { margin-left: 8px; font-size: .8rem; font-weight: 500; white-space: nowrap; letter-spacing: 0; }
.mp__slop { display: grid; grid-template-columns: auto 1fr auto; gap: 14px 16px; align-items: center; margin-top: 18px; }
.mp__slopRow { display: contents; }
.mp__slopName b { display: block; color: var(--ink); font-weight: 600; }
.mp__slopName span { display: block; margin-top: 2px; font-size: .74rem; color: var(--ink-3); }
.mp__slopBar { position: relative; height: 7px; border-radius: 4px; background: var(--line); }
.mp__slopBar i { display: block; height: 100%; border-radius: 4px; background: var(--ink-3); }
.mp__slopRow.is-good .mp__slopBar i { background: var(--st-good); }
.mp__slopRow.is-bad .mp__slopBar i { background: var(--st-bad); }
/* where a person lands on the same scale */
.mp__slopBar u { position: absolute; top: -4px; bottom: -4px; width: 2px; margin-left: -1px; border-radius: 1px; background: var(--ink); opacity: .55; }
.mp__slopVal { text-align: right; white-space: nowrap; }
.mp__slopVal b { display: block; color: var(--ink); font-variant-numeric: tabular-nums; }
.mp__slopVal b small { font-weight: 400; color: var(--ink-3); }
.mp__slopVal span { display: block; margin-top: 2px; font-size: .74rem; color: var(--ink-3); font-variant-numeric: tabular-nums; }
@media (max-width: 600px) {
  /* one grid per row again: three cells flowing through one shared grid interleaves the rows */
  .mp__slop { grid-template-columns: minmax(0, 1fr); gap: 16px; }
  .mp__slopRow { display: grid; grid-template-columns: 1fr auto; gap: 7px 12px; align-items: center; }
  .mp__slopName { grid-area: 1 / 1; }
  .mp__slopVal { grid-area: 1 / 2; }
  .mp__slopBar { grid-area: 2 / 1 / 3 / -1; }
}

/* the sources table keeps its heading in view the same way; it needs a fill of its own to do it */
.score--src thead th { position: sticky; top: 0; z-index: 6; padding-top: 12px; background: var(--surface); }
