/* Version-aware Trend detail, using the formal Measurement Detail tokens. */

/* Rhythm ladder. The page used to run 24 / 16 / 12 / 12 — ratios 1.50 / 1.33 / 1.00 — so the bottom two
   levels were perceptually identical and space could not say "this boundary is bigger than that one". The
   only mechanism left was line weight, which is exactly what the code reached for (--detail-line-strong
   against --detail-line, one rung apart). At 40 / 20 / 8 / 4 the ratios are 2.0 / 2.5 / 2.0, every level is
   unmistakable, and the rules that were standing in for hierarchy can go. All four are existing --mf-space-*
   steps; this is a redistribution, not an inflation — it nets roughly -15px per module against the old set. */
body.trend-detail-enhanced #detail {
  --tdi-rhythm-section: var(--mf-space-10, 40px);
  --tdi-rhythm-block: var(--mf-space-5, 20px);
  --tdi-rhythm-group: var(--mf-space-2, 8px);
  --tdi-rhythm-item: var(--mf-space-1, 4px);
}

body.trend-detail-enhanced #detail .nav-content {
  gap: var(--tdi-rhythm-section);
}

body.trend-detail-enhanced #detail .nav-analysis-grid {
  grid-template-columns: minmax(0, 1fr) clamp(320px, 27vw, 390px);
  gap: clamp(28px, 3.4vw, 52px);
  align-items: stretch;
  margin-top: 4px;
}

body.trend-detail-enhanced #detail .nav-chart-panel {
  border-bottom: 0;
}

/* Keep the primary detail-module titles on one deliberate typographic rung.
   "Factors Breakdown" is deliberately NOT one of them: it is the twin of the selected-Factor h3 opposite it,
   and the two are declared together below. Listing it here only forced a counter-override that had to undo
   it, and the pair then drifted apart in weight when the shared rule was normalised. */
body.trend-detail-enhanced #detail #nav-chart-title,
body.trend-detail-enhanced #detail #nav-direction-title {
  color: var(--detail-graphite);
  font-family: var(--detail-sans);
  /* 24px, was 18px. An 18px head is 1.29x the 14px body — too close to open a region on its own, which is
     why a rule kept getting drawn beside or under it. At 24px the head does the work and the rule is free
     to go. 24 rather than 26 so the composition heads (23px) move by a single step onto the same rung
     instead of the whole page shifting into an editorial register. */
  font-size: 24px;
  font-weight: 600;
  letter-spacing: -0.025em;
  line-height: 1.15;
}

.tdi-epoch-rail-host,
.tdi-workbench-host {
  min-width: 0;
  color: var(--detail-ink);
  font-family: var(--detail-sans);
  font-size: 14px;
  line-height: 1.55;
}

.tdi-epoch-rail-host {
  align-self: stretch;
  min-height: 0;
  overflow: hidden;
}

/* The global app button is a large mono CTA. These are detail-page controls. */
body.trend-detail-enhanced #detail :where(.tdi-epoch-rail-host, .tdi-workbench-host) button {
  width: auto;
  min-width: 0;
  height: auto;
  min-height: 0;
  margin: 0;
  font-family: var(--detail-sans);
  font-size: inherit;
  letter-spacing: 0;
  line-height: 1.25;
  text-transform: none;
}

body.trend-detail-enhanced #detail :where(.tdi-epoch-rail-host, .tdi-workbench-host) :where(button, select, input) {
  font-family: var(--detail-sans);
}

body.trend-detail-enhanced #detail :where(.tdi-epoch-rail-host, .tdi-workbench-host) button:active:not(:disabled) {
  transform: translateY(1px);
}

body.trend-detail-enhanced #detail :where(.tdi-epoch-rail-host, .tdi-workbench-host) :where(button, select, input, summary, a):focus-visible {
  outline: 2px solid #35aebb;
  outline-offset: 2px;
}

body.trend-detail-enhanced #detail .chart :where(.vline, .dot) {
  pointer-events: none;
}

.tdi-trade-context {
  display: block;
  margin-top: 9px;
  color: var(--detail-muted);
  font-size: 12.5px;
  line-height: 1.45;
  text-align: center;
}

.tdi-epoch-rail-host {
  position: relative;
  width: 100%;
  margin: 0;
  padding: 0;
  overflow: hidden;
  /* No border: the panel now sits ΔL* 3.09 above the page ground, and a value step plus a stroke at the same
     edge is one boundary stated twice. Restored under forced-colors in styles.css, where ground is discarded
     and the stroke is the only channel left. */
  border: 0;
  border-radius: var(--mf-radius-md);
  background: var(--mf-surface-panel);
  box-shadow: none;
  font-family: var(--mf-font-sans);
}

.tdi-epoch-rail {
  display: grid;
  grid-template-columns: calc(var(--tdi-driver-index-width) + var(--tdi-driver-workspace-gap) - var(--mf-rule-width)) minmax(0, 1fr);
  align-items: stretch;
  gap: 0;
  height: auto;
  min-height: 64px;
  padding: 0;
  overflow: visible;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
}

.tdi-version-select {
  display: grid;
  align-items: center;
  width: 100%;
  min-width: 0;
  padding: var(--mf-space-3);
  border-right: var(--mf-rule-width) solid var(--mf-border-subtle);
  background: transparent;
  color: var(--mf-text-secondary);
  font-size: var(--mf-font-size-label);
}

.tdi-version-select select {
  width: 100%;
  min-width: 0;
  height: var(--mf-control-height-default);
  padding: 0 30px 0 0;
  border: 0;
  border-radius: var(--mf-radius-xs, 4px);
  background-color: transparent;
  box-shadow: none;
  color: var(--mf-text-strong);
  font-family: var(--mf-font-sans) !important;
  font-size: var(--mf-font-size-label);
  font-variant-numeric: tabular-nums;
  font-weight: var(--mf-font-weight-semibold);
  cursor: pointer;
  transition:
    background-color var(--mf-duration-standard) var(--mf-ease-standard),
    border-color var(--mf-duration-standard) var(--mf-ease-standard);
}

@media (hover: hover) and (pointer: fine) {
  .tdi-version-select select:hover { background-color: color-mix(in srgb, var(--mf-text-primary) 4%, transparent); }
}

.tdi-adjustment-panel {
  display: contents;
  min-height: 0;
}

.tdi-adjustment-summary {
  display: grid;
  align-items: center;
  min-width: 0;
  padding: var(--mf-space-3) var(--mf-space-4);
  overflow: hidden;
  border: 0;
  border-radius: 0;
  background: var(--mf-surface-panel);
  box-shadow: none;
}

.tdi-adjustment-summary > header {
  display: grid;
  align-content: center;
  gap: var(--mf-space-0-5);
  min-width: 0;
  min-height: var(--mf-control-height-default);
  padding: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
}

.tdi-adjustment-kicker {
  color: var(--mf-text-secondary);
  font-size: var(--mf-font-size-meta);
  font-weight: var(--mf-font-weight-medium);
  line-height: var(--mf-line-height-title);
}
.tdi-adjustment-kicker small { color: var(--mf-signal-accent-ink); font: inherit; font-weight: var(--mf-font-weight-semibold); }
/* No ellipsis. This is the headline fact of the version rail — "2 added · 1 removed · 3 re-homed · 4 weights
   reweighted" — and nowrap+ellipsis was cutting the last clause off on narrow viewports rather than wrapping
   it. The row is sized by min-height (.tdi-epoch-rail, .tdi-adjustment-summary > header), not a fixed height,
   so a second line grows the row instead of being clipped. */
.tdi-adjustment-summary > header > strong {
  color: var(--mf-text-strong);
  font-size: var(--mf-font-size-body-sm);
  font-variant-numeric: tabular-nums;
  font-weight: var(--mf-font-weight-semibold);
  line-height: var(--mf-line-height-title);
}

.tdi-version-status {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Driver master-detail workspace */
.tdi-workbench {
  --tdi-driver-index-width: clamp(320px, 27vw, 370px);
  --tdi-driver-workspace-gap: var(--tdi-rhythm-section);
  display: grid;
  gap: var(--tdi-rhythm-block);
  padding-top: 24px;
  border-top: 0;
}

.tdi-composition-context {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-items: start;
  gap: 0;
  /* No underline: at 24px the head opens the section by itself, and the 40px rhythm above it already
     states the boundary. The rule was compensating for a head that was too small to do either. */
  padding: 0 0 var(--tdi-rhythm-block);
  border-bottom: 0;
}

body.trend-detail-enhanced #detail .tdi-composition-context h2 { margin: 0; color: var(--detail-graphite); font-size: 27px; font-weight: 600; letter-spacing: -0.035em; line-height: 1.1; }

.tdi-driver-workspace {
  display: grid;
  grid-template-columns: var(--tdi-driver-index-width) minmax(0, 1fr);
  align-items: start;
  gap: var(--tdi-driver-workspace-gap);
  min-width: 0;
}

.tdi-driver-workspace > * { min-width: 0; }

/* Driver ladder: the only driver selector. */
.tdi-driver-breakdown {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--tdi-rhythm-group);
  min-width: 0;
  padding: 0;
  border: 0;
}

.tdi-factor-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  min-width: 0;
  max-width: 100%;
}

.tdi-factor-controls { display: none; align-items: center; gap: 8px; color: var(--detail-muted); font-family: var(--detail-mono); font-size: 12px; font-weight: 600; }
.tdi-factor-controls button { width: 36px; height: 36px; padding: 0; border: 1px solid var(--detail-line-strong); border-radius: 8px; background: color-mix(in srgb, var(--detail-cyan) 12%, var(--detail-panel)); color: var(--detail-graphite); font-size: 25px; font-weight: 600; line-height: 1; box-shadow: 0 2px 8px rgba(17, 19, 22, 0.08); }
.tdi-factor-controls button:disabled { opacity: 0.35; }

.tdi-factor-head > span {
  flex: none;
  color: var(--detail-muted);
  font-size: 12.5px;
  font-weight: 500;
  white-space: nowrap;
}
/* overflow-wrap: the selected-Factor heading echoes the Factor name, so a name with no break opportunity
   pushed the whole page wider than the viewport (measured 514px against a 375px viewport) rather than
   wrapping — DESIGN.md §9 forbids horizontal page overflow at 320px and up. Same guard the Factor row
   carries. 600, not 620: Inter's shipped axis stops at 700 and the ladder is 400/500/600/700. */
.tdi-driver-breakdown h3,
.tdi-driver-detail-head h3 {
  margin: 0;
  overflow-wrap: anywhere;
  color: var(--detail-graphite);
  font-size: 24px;
  font-weight: 600;
  letter-spacing: -0.025em;
  line-height: 1.2;
}

.tdi-driver-detail-head > div > p {
  max-width: 62ch;
  margin: 1px 0 0;
  color: var(--detail-muted);
  font-size: 14px;
  line-height: 1.55;
}

.tdi-composition-bar {
  display: grid;
  gap: 0;
  width: 100%;
  max-width: 100%;
  min-width: 0;
  overflow: hidden;
  /* Border-left only. The share wash is `inset: 0 auto 0 0` and the row carries no left padding, so the wash
     runs flush to this edge — with no stroke there the darkest rows bleed straight into the ground and the
     list loses its left boundary. Every other edge is carried by the ΔL* step. */
  border: 0;
  border-left: 1px solid var(--detail-line);
  border-radius: var(--mf-radius-xs, 4px);
  background: var(--detail-panel);
}

.tdi-composition-segment {
  --tdi-color: var(--detail-cyan);
  position: relative;
  display: grid;
  grid-template-columns: 4px minmax(0, 1fr) 76px;
  align-items: center;
  gap: 12px;
  width: 100% !important;
  min-height: 64px !important;
  /* height:auto is load-bearing, not redundant. This row is a <button>, and a button does not propagate its
     intrinsic content height to the grid track the way a div does — proven by swapping the tag with every
     other style identical: the div grew to 68px, the button stayed pinned at 64px. Without this the track
     collapsed to min-height and `overflow: hidden` silently cut the "N markets included" line off any Factor
     whose name wrapped to two lines (measured: 18px lost on two lines, 37px on three). min-height still holds
     the row rhythm at every breakpoint; this only lets a long name push past it. */
  height: auto;
  padding: 10px 12px 12px 0;
  overflow: hidden;
  border: 0;
  border-bottom: 1px solid var(--detail-line);
  border-radius: 0;
  background: var(--detail-panel);
  box-shadow: none;
  color: var(--detail-ink);
  text-align: left;
  cursor: pointer;
  transition: background var(--mf-duration-standard) var(--mf-ease-standard), border-color var(--mf-duration-standard) var(--mf-ease-standard), box-shadow var(--mf-duration-standard) var(--mf-ease-standard);
}

.tdi-composition-segment:last-child { border-bottom: 0; }
/* Was a full-height 4px bar in the Factor's hashed hue. It now paints nothing at all except a single dot on
   the selected row — the only mark of colour left in the module, and it marks a state rather than decorating
   a category. It keeps the 4px gutter column so the cap row's geometry still matches (see the shared
   grid-template-columns above). */
.tdi-driver-rail {
  justify-self: center;
  align-self: start;
  margin-top: 8px;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: transparent;
  transition: background var(--mf-duration-fast) var(--mf-ease-standard);
}
.tdi-composition-segment.is-active .tdi-driver-rail { background: var(--mf-signal-accent, #74deeb); }
/* styles.css sets `button { font-family: var(--mono) }` globally, and this row is a button — so the Factor
   name and its market count were rendering in mono while the market-card title, the price and the section
   heading beside them all render in Inter. DESIGN.md reserves mono for figures; a Factor name is a label.
   The percentage in <strong> keeps mono, because that one IS a figure. */
.tdi-composition-segment > span { display: grid; gap: 4px; min-width: 0; font-family: var(--detail-sans, var(--mf-font-sans)); }
/* A Factor name with no spaces would otherwise run straight under the weight column (measured: 179px of
   overlap) rather than wrapping. */
.tdi-composition-segment > span b { overflow-wrap: anywhere; color: var(--detail-graphite); font-size: 14.5px; font-weight: 600; line-height: 1.3; }
.tdi-composition-segment > span small { color: var(--detail-muted); font-size: 12.5px; font-weight: 400; line-height: 1.4; }
.tdi-composition-segment > strong { display: grid; justify-items: end; gap: 2px; min-width: 72px; }
/* font-weight is explicit because <b> resolves the browser's `bolder` against the parent and lands on 900,
   outside DESIGN.md 4.3's 400/500/600/700 ladder. */
/* The figure is the anchor of the row now that the coloured marks are gone: 17px mono against a 14.5px label
   and a 12.5px count gives the row a reading order it did not have when all three were the same size. */
.tdi-composition-segment > strong b { color: var(--detail-graphite); font-family: var(--detail-mono); font-size: 17px; font-weight: 600; font-variant-numeric: tabular-nums; letter-spacing: -0.02em; line-height: 1.1; }
.tdi-composition-segment > strong small { color: var(--detail-muted); font-size: 12px; font-weight: 500; }
/* The share used to be a 3px bar pinned to the bottom edge, on top of a coloured rail, on top of the
   percentage, on top of the card weight track — the same quantity encoded four ways. It is now the row's own
   ground: a hue-less ink wash running full height out to the Factor's share. Proportion stops being an added
   object and becomes the row itself, so the at-a-glance ranking survives with no decorative marks at all.
   z-index pairs with the content below: <em> is last in the DOM, so without an explicit order it would paint
   over the label it is meant to sit behind. */
.tdi-composition-segment > em {
  position: absolute;
  z-index: 0;
  inset: 0 auto 0 0;
  width: var(--tdi-share);
  max-width: 100%;
  background: color-mix(in srgb, var(--detail-ink) 5.5%, transparent);
  pointer-events: none;
  transition: background var(--mf-duration-standard) var(--mf-ease-standard);
}
.tdi-composition-segment > span,
.tdi-composition-segment > strong,
.tdi-composition-segment > .tdi-driver-rail { position: relative; z-index: 1; }

@media (hover: hover) and (pointer: fine) {
  .tdi-composition-segment:hover { border-color: var(--detail-line-strong); background: transparent; box-shadow: none; transform: none; }
  .tdi-composition-segment:hover > em { background: color-mix(in srgb, var(--detail-ink) 8%, transparent); }
}
/* Selected reads through three channels at once — deeper ground, stronger ink, and the cyan dot — so colour
   is never the only signal. */
.tdi-composition-segment.is-active { background: transparent; box-shadow: none; }
.tdi-composition-segment.is-active > em { background: color-mix(in srgb, var(--detail-ink) 9%, transparent); }
.tdi-composition-segment.is-active > span b,
.tdi-composition-segment.is-active > strong b { color: var(--detail-graphite); }
.tdi-composition-segment.is-active :where(.tdi-driver-rail, em) { opacity: 1; }
.tdi-composition-segment:focus-visible { z-index: 1; outline-offset: -3px !important; }

/* Rulebook exposure cap: an advisory disclosure, not a basket row. It sits OUTSIDE .tdi-composition-bar because
   the bar states the index basket a purchase actually executes, and this figure is the composition rulebook's
   own budget — mixing the two denominators inside one bordered group would read as one arithmetic. It reuses
   .tdi-composition-segment's grid so the row geometry is identical, and the modifier strips every affordance
   that would imply the <div> is pressable. */
.tdi-composition-cap {
  display: grid;
  gap: 0;
  width: 100%;
  max-width: 100%;
  min-width: 0;
  overflow: hidden;
  border: 1px dashed var(--detail-line-strong);
  border-radius: 8px;
  background: color-mix(in srgb, var(--detail-muted) 4%, var(--detail-panel));
}

.tdi-composition-segment.is-cap {
  --tdi-color: var(--detail-muted);
  border-bottom: 0;
  background: transparent;
  cursor: default;
  transition: none;
}

.tdi-composition-segment.is-cap:hover { border-color: transparent; background: transparent; box-shadow: none; }
.tdi-composition-segment.is-cap > span b { color: var(--detail-muted); }
.tdi-composition-segment.is-cap > strong b { color: var(--detail-muted); }
.tdi-composition-segment.is-cap .tdi-driver-rail { opacity: 0.3; }
/* NO proportional underline on this row, ever. The facet rows above use --tdi-share to draw a bottom rail whose
   LENGTH encodes the share; this figure has a different denominator, so a rail at the same pixel scale would
   invite reading 60% / 40% / 41.2% as one allocation summing to 141%. The markup emits no <em>; this rule makes
   the ban structural rather than a property of the current template. Column geometry is untouched — the rail is
   absolutely positioned, so removing it shifts nothing. */
.tdi-composition-segment.is-cap > em { display: none; }

.tdi-composition-cap-note {
  margin: 0;
  padding: 0 12px 12px 16px;
  color: var(--detail-faint);
  font-size: 12.5px;
  line-height: 1.5;
}

/* Selected driver and market inspection */
.tdi-driver-detail {
  display: grid;
  gap: 16px;
  padding: 12px 0 0 26px;
  border-top: 1px solid var(--detail-line);
  border-left: 1px solid var(--detail-line-strong);
}

.tdi-driver-detail-head {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-items: start;
  gap: 10px;
}

.tdi-driver-detail-head > div { display: grid; align-content: center; gap: 5px; min-width: 0; }

/* One framed surface with hairline-divided cells, exactly like the Factor list opposite — instead of a
   scatter of individually bordered cards. Both halves of the workspace now read as the same object: a single
   ruled panel. Gap stays 0 and the dividers are drawn with box-shadow so an odd number of markets cannot
   leave an empty grid cell painting as a solid block; the container's overflow clips the trailing edges. */
.tdi-market-card-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0;
  min-width: 0;
  overflow: hidden;
  /* No border: the panel now sits ΔL* 3.09 above the page ground, and a value step plus a stroke at the same
     edge is one boundary stated twice. Restored under forced-colors in styles.css, where ground is discarded
     and the stroke is the only channel left. */
  border: 0;
  border-radius: var(--mf-radius-xs, 4px);
  background: var(--detail-panel);
}

.tdi-market-card {
  display: grid;
  gap: 12px;
  width: 100% !important;
  padding: 15px 16px 16px;
  border: 0;
  border-radius: 0;
  background: var(--detail-panel);
  box-shadow: 1px 0 0 var(--detail-line), 0 1px 0 var(--detail-line);
  color: var(--detail-ink);
  text-align: left;
  text-decoration: none;
  transition: background var(--mf-duration-standard) var(--mf-ease-standard), box-shadow var(--mf-duration-standard) var(--mf-ease-standard), border-color var(--mf-duration-standard) var(--mf-ease-standard), transform var(--mf-duration-standard) var(--mf-ease-standard);
}

a.tdi-market-card { cursor: pointer; }
/* Hover is a ground shift, not a lift: a cell inside a ruled panel has nowhere to rise to, and the shadow it
   used to cast was invisible on the warm ground anyway. Gated so a tap cannot leave it stuck. */
@media (hover: hover) and (pointer: fine) {
  a.tdi-market-card:hover { background: color-mix(in srgb, var(--detail-ink) 2.5%, var(--detail-panel)); }
}

.tdi-market-card:focus-visible {
  z-index: 1;
  outline: 2px solid #258895 !important;
  outline-offset: 2px !important;
}

.tdi-market-card-head {
  display: grid;
  grid-template-columns: 38px minmax(0, 1fr) auto;
  align-items: center;
  gap: 10px;
}

.tdi-market-thumb {
  position: relative;
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  overflow: hidden;
  border: 1px solid var(--detail-line);
  border-radius: 8px;
  background: #f1f5f3;
  color: #819095;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.7);
}

.tdi-market-thumb-fallback {
  display: grid;
  place-items: center;
  width: 100%;
  height: 100%;
  transition: opacity var(--mf-duration-standard) var(--mf-ease-standard);
}

.tdi-market-thumb-fallback svg { width: 17px; height: 17px; }

.tdi-market-thumb img {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity var(--mf-duration-standard) var(--mf-ease-standard);
}

.tdi-market-thumb.has-image img { opacity: 1; }
.tdi-market-thumb.has-image .tdi-market-thumb-fallback { opacity: 0; }

.tdi-market-card-id { display: grid; gap: 4px; min-width: 0; }
.tdi-market-card-id > b { display: -webkit-box; overflow: hidden; color: var(--detail-graphite); font-size: 14px; font-weight: 600; line-height: 1.4; -webkit-box-orient: vertical; -webkit-line-clamp: 2; }

.tdi-market-card-link {
  display: inline-block;
  margin-left: 5px;
  color: var(--detail-faint);
  font-family: var(--detail-mono);
  font-size: 11px;
  font-style: normal;
  transform: translateY(-1px);
  transition: color var(--mf-duration-standard) var(--mf-ease-standard);
}

a.tdi-market-card:hover .tdi-market-card-link,
a.tdi-market-card:focus-visible .tdi-market-card-link { color: #247f8b; }

.tdi-market-card-price-block {
  display: grid;
  gap: 8px;
}

.tdi-market-card-stat {
  display: grid;
  gap: 1px;
}

/* --detail-faint measured 2.53:1 on the card ground — under WCAG AA's 4.5:1 for text this size. --detail-muted
   measures 5.01:1. This is the caption on the largest figure in the card, not an unavailability notice, so it
   should read as a label. 650 is off DESIGN.md 4.3's 400/500/600/700 ladder and renders as 700 regardless. */
.tdi-market-card-stat-label {
  color: var(--detail-muted);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

.tdi-market-card-stat-value {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 8px;
}

/* The largest figure in the card, so it anchors the card the way the share percentage anchors a Factor row —
   and it is a FIGURE, which the type contract reserves the mono face for. It was set in the sans face at 550,
   which the ladder sweep would have taken to 500: lighter than the label above it and lighter than the share
   opposite. Mono also makes a column of prices align on the decimal, which is the point of reading them. */
.tdi-market-card-price {
  color: var(--detail-graphite);
  font-family: var(--detail-mono);
  font-size: 22px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}

.tdi-market-card-change {
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
  color: var(--detail-muted);
  font-family: var(--detail-mono);
  font-size: 12.5px;
  font-weight: 600;
}

.tdi-market-card-change.is-up { color: var(--detail-pos); }
.tdi-market-card-change.is-down { color: var(--detail-neg); }
/* muted, not faint (2.53:1 -> 5.01:1). This variant also carries "Not held on Jul 29", which is a fact about
   the prior composition rather than an unavailability, so it has to be readable. */
.tdi-market-card-change.is-unavailable { color: var(--detail-muted); font-family: var(--detail-sans); font-size: 12px; font-weight: 500; }
.tdi-market-card-change small { color: inherit; font-family: inherit; font-weight: 500; opacity: 0.7; }

.tdi-market-card-foot {
  display: grid;
  gap: 7px;
  padding-top: 10px;
  border-top: 1px solid var(--detail-line);
}

.tdi-market-card-weight-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
}

.tdi-market-card-foot-label { color: var(--detail-muted); font-size: 10.5px; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; }

.tdi-market-card-weight { display: inline-flex; align-items: baseline; gap: 6px; }
.tdi-market-card-weight > b { color: var(--detail-graphite); font-family: var(--detail-mono); font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums; letter-spacing: -0.005em; }



.tdi-market-card-spark { display: block; width: 100%; height: 30px; }
.tdi-market-card-spark-line { fill: none; stroke: var(--detail-muted); stroke-linecap: round; stroke-linejoin: round; stroke-width: 1.6; vector-effect: non-scaling-stroke; }
.tdi-market-card-spark-fill { stroke: none; fill: var(--detail-muted); opacity: 0.08; }
.tdi-market-card-spark.is-up .tdi-market-card-spark-line { stroke: var(--detail-pos); }
.tdi-market-card-spark.is-up .tdi-market-card-spark-fill { fill: var(--detail-pos); }
.tdi-market-card-spark.is-down .tdi-market-card-spark-line { stroke: var(--detail-neg); }
.tdi-market-card-spark.is-down .tdi-market-card-spark-fill { fill: var(--detail-neg); }

.tdi-market-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 5px 7px;
  min-width: 0;
}

.tdi-market-status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  width: max-content;
  color: #247f8b;
  font-size: 12px;
  font-weight: 600;
  line-height: 1.3;
}

.tdi-market-status::before {
  width: 6px;
  height: 6px;
  border: 1px solid currentColor;
  border-radius: 50%;
  content: "";
}

.tdi-market-inclusion {
  display: inline-flex;
  align-items: center;
  width: max-content;
  max-width: 100%;
  padding: 2px 6px;
  border: 1px solid rgba(53, 174, 187, 0.34);
  border-radius: 3px;
  background: rgba(116, 222, 235, 0.07);
  color: #247f8b;
  font-size: 11px;
  font-weight: 700;
  line-height: 1.25;
}

.tdi-market-inclusion.is-returning {
  border-color: var(--detail-line-strong);
  background: var(--detail-paper);
  color: var(--detail-muted);
}

.tdi-market-weight-delta {
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
  color: #287f89;
  font-family: var(--detail-mono);
  font-size: 11.5px;
  font-weight: 600;
  line-height: 1.25;
  white-space: nowrap;
}

.tdi-market-weight-delta > b { color: inherit; font: inherit; }
.tdi-market-weight-delta > small { color: var(--detail-muted); font-family: inherit; font-size: 10.5px; font-weight: 500; }
.tdi-side {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 28px;
  padding: 0 7px;
  border: 1px solid var(--detail-line);
  border-radius: 3px;
  background: var(--detail-paper);
  color: var(--detail-muted);
  /* "Yes"/"No" is an outcome LABEL, not a figure — the same contract line that puts the Factor name in Inter.
     750 is off the 400/500/600/700 ladder and renders as 700 anyway, since both shipped faces stop at bold.
     The badge keeps its border and tint, so the side is still signalled by more than colour. */
  font-family: var(--detail-sans);
  font-size: 12px;
  font-style: normal;
  font-weight: 700;
  text-transform: uppercase;
}

/* YES was green and NO was red. That paints a position SIDE as good or bad, which DESIGN.md §6.5 forbids —
   "a View name is not positive or negative; performance colour follows the numeric move, not the thesis
   label". A NO leg can be the profitable one. The word already says which side this is, so the hue was
   redundant as well as wrong; both sides now read in ink and the only green/red left in the module is the
   price change, where it does track the numeric move. */
.tdi-side.is-yes,
.tdi-side.is-no { border-color: var(--detail-line-strong); background: color-mix(in srgb, var(--detail-ink) 3%, transparent); color: var(--detail-graphite); }

.tdi-market-toggle {
  justify-self: start;
  min-height: 38px !important;
  padding: 0 16px;
  border: 1px solid var(--detail-line) !important;
  border-radius: 8px;
  background: var(--detail-paper);
  box-shadow: none;
  color: #247f8b;
  font-size: 13.5px !important;
  font-weight: 600;
  cursor: pointer;
}

.tdi-market-toggle:hover { background: rgba(116, 222, 235, 0.08); box-shadow: none; transform: none; }

.tdi-empty {
  padding: 28px 20px;
  color: var(--detail-muted);
  font-size: 14px;
  text-align: center;
}

.tdi-historical-trade-note {
  overflow: hidden;
  border: 1px solid rgba(169, 109, 32, 0.24);
  border-radius: 7px;
  background: rgba(169, 109, 32, 0.05);
}

.tdi-historical-trade-note { margin: 0; padding: 13px 15px; color: var(--detail-muted); font-size: 13.5px; line-height: 1.55; }
.tdi-historical-trade-note b { color: #825215; }

@media (max-width: 1024px) {
  body.trend-detail-enhanced #detail .nav-analysis-grid { grid-template-columns: minmax(0, 1fr); gap: 24px; }
  .tdi-epoch-rail-host { overflow: hidden; }
  .tdi-epoch-rail {
    grid-template-columns: calc(var(--tdi-driver-index-width) + var(--tdi-driver-workspace-gap) - var(--mf-rule-width)) minmax(0, 1fr);
  }
}

/* Detail copy uses sentence case throughout; status labels remain differentiated by color and weight. */
body.trend-detail-enhanced #detail :where(*) { text-transform: none; }


@media (max-width: 1180px) and (min-width: 861px) {
  .tdi-workbench {
    --tdi-driver-index-width: clamp(280px, 34vw, 320px);
    --tdi-driver-workspace-gap: 18px;
  }
  .tdi-driver-detail { padding-left: 18px; }
}

@media (max-width: 860px) {
  .tdi-composition-context { grid-template-columns: 1fr; align-items: start; gap: 16px; }
  .tdi-epoch-rail { grid-template-columns: minmax(240px, 0.82fr) minmax(0, 2fr); }
  .tdi-driver-workspace { grid-template-columns: 1fr; gap: 24px; }
  .tdi-driver-detail { padding: 22px 0 0; border-top: 1px solid var(--detail-line); border-left: 0; }
}

@media (max-width: 780px) {
  body.trend-detail-enhanced #detail .nav-content { gap: 20px; }
  .tdi-epoch-rail-host,
  .tdi-workbench-host { font-size: 14px; }

  .tdi-version-select { border-right: 0; border-bottom: var(--mf-rule-width) solid var(--mf-border-subtle); }
  .tdi-version-select select { height: var(--mf-control-height-touch); font-size: var(--mf-font-size-label); }
  .tdi-epoch-rail { grid-template-columns: 1fr; gap: 0; }

  .tdi-workbench { gap: 18px; padding-top: 22px; }
  .tdi-driver-breakdown { gap: 14px; }
  .tdi-composition-segment { min-height: 72px !important; padding: 12px 14px 14px 0; gap: 11px; }
  .tdi-composition-segment > span b { font-size: 14px; }
  .tdi-composition-segment > strong { min-width: 78px; }

  .tdi-driver-detail { padding-top: 22px; }
  .tdi-market-card { padding: 12px; gap: 10px; }
  .tdi-market-card-price { font-size: 20px; }

}

@media (max-width: 620px) {
  .tdi-epoch-rail-host { padding: 0; border-radius: var(--mf-radius-md); }
  .tdi-epoch-rail { grid-template-columns: 1fr; padding: 0; border-radius: 0; }
  .tdi-adjustment-summary { padding: var(--mf-space-3); }
  .tdi-composition-bar {
    grid-auto-flow: column;
    grid-auto-columns: minmax(220px, 78vw);
    gap: 8px;
    overflow-x: auto;
    border: 0;
    border-radius: 0;
    background: transparent;
    scroll-snap-type: x proximity;
    scrollbar-width: none;
  }
  .tdi-factor-head { flex-wrap: wrap; }
  .tdi-composition-bar::-webkit-scrollbar { display: none; }
  .tdi-factor-controls { display: inline-flex; }
  .tdi-factor-controls button { cursor: pointer; touch-action: manipulation; }
  .tdi-factor-controls button:active { background: color-mix(in srgb, var(--detail-cyan) 22%, var(--detail-panel)); transform: translateY(1px); }
  .tdi-composition-segment { min-height: 76px !important; border: 1px solid var(--detail-line); border-radius: 7px; scroll-snap-align: start; }
  .tdi-composition-segment:last-child { border-bottom: 1px solid var(--detail-line); }
  .tdi-driver-breakdown h3,
  .tdi-driver-detail-head h3 { font-size: 21px; }
  .tdi-composition-segment { grid-template-columns: 4px minmax(0, 1fr) 76px; }
  .tdi-composition-segment > span small { font-size: 12px; }
  /* The bar turns into a horizontal scroll rail here; the exposure cap is a separate stacked block, so it must
     not inherit the rail's per-card border or snap geometry. */
  .tdi-composition-segment.is-cap { min-height: 64px !important; border: 0; border-radius: 0; }
}

@media (max-width: 480px) {
  .tdi-market-card-grid { grid-template-columns: 1fr; }
}

@media (max-width: 420px) {
  .tdi-market-card-head { grid-template-columns: 34px minmax(0, 1fr) auto; gap: 8px; }
  .tdi-market-thumb { width: 34px; height: 34px; }
  .tdi-market-card-price { font-size: 19px; }
}

@media (prefers-reduced-motion: reduce) {
  body.trend-detail-enhanced #detail :where(.tdi-composition-segment, .tdi-market-card) {
    transition: none;
  }
}

/* RESERVED CASH — a Factor of the basket that holds no market (navCashFactor.ts). Rendered inert: no hover
   lift, no active state, no pointer affordance, because unlike every other segment it filters nothing. It
   keeps the proportional underline: it IS a share of the same ΣW = 1 basket, unlike .is-cap above (a rulebook
   verdict against a different denominator), which is why that one suppresses the bar and this one must not. */
.tdi-composition-segment.is-cash {
  background: color-mix(in srgb, var(--mf-status-warning, #96631c) 6%, var(--detail-panel));
  cursor: default;
}
.tdi-composition-segment.is-cash:hover {
  border-color: var(--detail-line);
  background: color-mix(in srgb, var(--mf-status-warning, #96631c) 6%, var(--detail-panel));
}
.tdi-composition-segment.is-cash > .tdi-driver-rail,
.tdi-composition-segment.is-cash > em {
  opacity: 0.72;
}

/* Touch synthesizes a :hover on tap that sticks until the next tap elsewhere; drop the lift so a tapped
   market card doesn't stay raised. See the matching block at the end of styles.css. */
@media (hover: none) {
  a.tdi-market-card:hover {
    transform: none;
  }
}
