/* Familjen Grotesk, self-hosted. A Swiss grotesque with tabular figures by
   default - every digit is the same width with no feature flag, so columns of
   numbers line up in SVG text where font-variant-numeric is unreliable. */
@font-face {
  font-family: "Familjen Grotesk";
  src: url("fonts/familjen-grotesk-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Familjen Grotesk";
  src: url("fonts/familjen-grotesk-500.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Familjen Grotesk";
  src: url("fonts/familjen-grotesk-700.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

:root {
  color-scheme: light;
  --bg: #f6f4ef;
  --ink: #1f2a2e;
  --muted: #5d6868;
  --line: #d8d4c8;
  --panel: #fffdf8;
  --green: #25715f;
  --gold: #b98522;
  --clay: #b45e3d;
  --blue: #3d6f91;

  /* Categorical series palette - muted earth tones, matching the page's brand
     character rather than a bright default set.
     Validated against surface #fffdf8: lightness band PASS, chroma floor PASS,
     CVD separation PASS (worst adjacent dE 8.5 protan, above the 8.0 target),
     normal-vision floor PASS (16.8), contrast PASS (all >= 3:1). No WARNs.
     The earlier hand-picked muted set failed three of those five checks - six of
     its eight colours sat below the chroma floor and read as gray, and two were
     indistinguishable even with full colour vision. These keep the muted feel by
     staying deep in lightness rather than by draining chroma.
     Slot ORDER is the colour-blind-safety mechanism: assign in sequence, never
     reorder or cycle. The brand colours above stay in the page chrome. */
  --series-1: #007a5f;
  --series-2: #b5701f;
  --series-3: #2a6ea8;
  --series-4: #a4453a;
  --series-5: #5f4a9e;
  --series-6: #5f7d2e;
  --series-7: #9c5a86;
  --series-8: #8a6a10;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: "Familjen Grotesk", Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  font-variant-numeric: tabular-nums lining-nums;
}

.shell {
  width: min(1180px, calc(100% - 32px));
  margin: 0 auto;
  padding: 36px 0 48px;
}

.intro {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: 28px;
  align-items: end;
  padding-bottom: 26px;
  border-bottom: 1px solid var(--line);
}

.eyebrow {
  margin: 0 0 10px;
  color: var(--green);
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

h1,
h2,
p {
  margin-top: 0;
}

h1 {
  max-width: 760px;
  margin-bottom: 14px;
  font-size: clamp(2.3rem, 6vw, 5rem);
  line-height: 0.96;
}

h2 {
  margin-bottom: 6px;
  font-size: 1.05rem;
}

.lede {
  max-width: 680px;
  margin-bottom: 0;
  color: var(--muted);
  font-size: 1.08rem;
}

/* Sized to however many figures a row actually has. It was fixed at four, so
   removing one left an empty cell and squeezed the rest into three quarters of
   the width. */
.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 12px;
  margin: 22px 0;
}

.stats article,
.panel,
.takeaway,
.compare,
.synthesis {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 8px;
}

.stats article {
  padding: 16px;
}

.stats span {
  display: block;
  color: var(--muted);
  font-size: 0.84rem;
}

.stats strong {
  display: block;
  margin-top: 6px;
  font-size: 1.5rem;
}

/* A narrower stat row for two figures inline within a panel's narrative,
   rather than the four-figure header row. Falls back to the .stats mobile
   media query below (equal specificity, later in source order) so it still
   stacks to one column on small screens. */
.stats-inline {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  max-width: 460px;
  margin: 16px 0 20px;
}

/* Closing narrative section: same card language as .takeaway and .compare,
   used once to state the report's synthesis before the audience takeaways. */
.synthesis {
  margin-top: 18px;
  padding: 22px;
}

.synthesis h2 {
  margin-bottom: 10px;
  font-size: 1.5rem;
}

.synthesis > p {
  max-width: 78ch;
  color: var(--muted);
  line-height: 1.6;
}

.synthesis .stats {
  margin: 20px 0;
}

.controls {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin-bottom: 12px;
}

/* The page is long, so the one filter that governs it stays reachable while
   scrolling. It is deliberately the only global control on the page. */
#filterBar {
  display: block;   /* overrides .controls flex, which collapsed the fields */
  position: sticky;
  top: 0;
  z-index: 20;
  margin: 0 0 20px;
  padding: 12px 0;
  /* Solid, not translucent: a backdrop-filter blur on a sticky bar spanning a
     page this long is very expensive to composite and froze the renderer. */
  background: var(--bg);
  border-bottom: 1px solid var(--line);
  box-shadow: 0 6px 12px -10px rgba(31, 42, 46, 0.5);
  /* Isolate the sticky bar's paint work: without this every scroll frame
     invalidates a strip across a 7,400px page. */
  contain: layout paint;
}

.controls-inner {
  display: grid;
  gap: 8px;
}

.controls-fields {
  display: flex;
  flex-wrap: wrap;
  align-items: end;
  gap: 14px 20px;
}

.controls-fields label {
  flex: 0 1 260px;
  min-width: 200px;
}

.control-hint {
  color: var(--muted);
  font-size: 0.76rem;
  font-weight: 500;
}

.controls-status {
  margin: 0;
  color: var(--ink);
  font-size: 0.92rem;
  font-weight: 650;
}

.reset-btn {
  align-self: end;
  margin-bottom: 18px;
  padding: 8px 14px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--panel);
  font: inherit;
  font-size: 0.86rem;
  color: var(--ink);
  cursor: pointer;
}

.reset-btn:hover {
  border-color: var(--green);
  color: var(--green);
}

/* Guidance on reading a chart, distinct from the chart's one-line subject. */
.how-to-read {
  margin: 6px 0 0;
  color: var(--muted);
  font-size: 0.88rem;
  line-height: 1.5;
  max-width: 78ch;
}

/* What the active filter is doing to THIS chart. */
.scope-note {
  margin: 8px 0 0;
  padding: 6px 10px;
  border-left: 3px solid var(--green);
  background: color-mix(in srgb, var(--green) 6%, transparent);
  border-radius: 0 5px 5px 0;
  color: var(--ink);
  font-size: 0.84rem;
  max-width: 78ch;
}

.scope-note:empty {
  display: none;
}

.scope-note-standalone {
  border-left-color: var(--gold);
  background: color-mix(in srgb, var(--gold) 8%, transparent);
}

label {
  display: grid;
  gap: 6px;
  min-width: min(100%, 260px);
  color: var(--muted);
  font-size: 0.88rem;
  font-weight: 700;
}

select {
  width: 100%;
  min-width: 0;
  min-height: 42px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--panel);
  color: var(--ink);
  font: inherit;
  font-weight: 500;
  padding: 0 12px;
}

.filter-context {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 12px;
  align-items: baseline;
  margin-bottom: 18px;
  padding: 12px 14px;
  border-left: 4px solid var(--green);
  background: rgba(37, 113, 95, 0.08);
  color: var(--muted);
  line-height: 1.45;
}

.filter-context strong {
  color: var(--ink);
}

.grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 18px;
}

.panel {
  padding: 18px;
}

/* The sector donut sits in a grid row beside the ten-bar business-type chart, so
   its card stretches to the taller neighbour and used to leave a blank block under
   a fixed-height chart. Let this ONE chart claim the leftover height.
   Scoped deliberately: applying it to every .panel forces charts that size
   themselves from their content (the treemap) to overflow their card. */
.panel-fill {
  display: flex;
  flex-direction: column;
}

.panel-fill > .chart {
  flex: 1 1 0;
  min-height: 0;
}

.panel-wide {
  grid-column: 1 / -1;
}

.panel-heading {
  margin-bottom: 12px;
}

.split-heading {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(180px, 280px);
  gap: 16px;
  align-items: end;
}

.panel-filter {
  display: grid;
  gap: 7px;
  width: 100%;
  min-width: 0;
  max-width: 280px;
  justify-self: end;
  color: var(--muted);
  font-size: 0.85rem;
  font-weight: 700;
}

.panel p {
  margin-bottom: 12px;
  color: var(--muted);
  font-size: 0.92rem;
}

.chart {
  min-height: 300px;
}

.bar-label,
.axis text {
  fill: var(--ink);
  font-size: 12px;
}

.leader-line {
  stroke: var(--muted);
  stroke-width: 1.2;
  opacity: 0.82;
}

.donut-label rect {
  fill: #ffffff;
  stroke: var(--line);
}

.donut-label text {
  fill: var(--ink);
  font-size: 12px;
  font-weight: 700;
}

.axis path,
.axis line,
.grid-line {
  stroke: var(--line);
}

.axis-title,
.capital-explain {
  fill: var(--muted);
  font-size: 12px;
}

/* No inner scroll: a nested scroller here swallowed the page wheel across most of
   the page width, so the page appeared frozen while the cursor was over the chart.
   The treemap sizes itself to its content and the page scrolls normally. */
.treemap-chart {
  min-height: 460px;
}

.treemap-label,
.treemap-value {
  fill: #fffdf8;
  font-weight: 750;
  pointer-events: none;
}

.treemap-value {
  opacity: 0.88;
}

.takeaway {
  margin-top: 18px;
  padding: 20px;
}

.compare {
  margin-top: 18px;
  padding: 20px;
}

.compare-heading {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(280px, 0.75fr);
  gap: 18px;
  align-items: end;
  margin-bottom: 16px;
}

.compare-heading h2 {
  margin-bottom: 8px;
  font-size: 1.45rem;
}

.compare-heading p {
  margin-bottom: 0;
  color: var(--muted);
  line-height: 1.5;
}

.compare-controls {
  justify-content: end;
  margin-bottom: 0;
}

.comparison-stats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px;
  margin-bottom: 14px;
}

.comparison-stats article {
  border-top: 3px solid var(--green);
  padding-top: 10px;
}

.comparison-stats article:nth-child(2) {
  border-color: var(--blue);
}

.comparison-stats article:nth-child(3) {
  border-color: var(--gold);
}

.comparison-stats span {
  display: block;
  color: var(--muted);
  font-size: 0.82rem;
}

.comparison-stats strong {
  display: block;
  margin-top: 4px;
  font-size: 1.2rem;
}

.comparison-takeaway {
  margin-bottom: 16px;
  padding: 12px 14px;
  border-left: 4px solid var(--gold);
  color: var(--muted);
  line-height: 1.45;
}

.compact-chart {
  min-height: 190px;
}

.chart-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 18px;
  margin-top: 4px;
  padding-top: 10px;
  border-top: 1px solid var(--line);
  color: var(--ink);
  font-size: 0.88rem;
}

.legend-item {
  display: inline-flex;
  gap: 7px;
  align-items: center;
  max-width: min(100%, 260px);
}

.legend-swatch {
  width: 10px;
  height: 10px;
  flex: 0 0 10px;
  border-radius: 2px;
}

.takeaway-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px;
}

.takeaway p {
  margin-bottom: 0;
  color: var(--muted);
  line-height: 1.5;
}

.takeaway strong {
  color: var(--ink);
}

.tooltip {
  position: fixed;
  pointer-events: none;
  display: none;
  max-width: 260px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--panel);
  color: var(--ink);
  box-shadow: 0 12px 30px rgba(31, 42, 46, 0.14);
  font-size: 0.86rem;
  line-height: 1.35;
  z-index: 10;
}

@media (max-width: 760px) {
  .intro,
  .split-heading,
  .compare-heading,
  .comparison-stats,
  .grid,
  .takeaway-grid,
  .stats {
    grid-template-columns: 1fr;
  }

  .shell {
    width: min(100% - 24px, 1180px);
    padding-top: 24px;
  }

  .stats strong {
    font-size: 1.35rem;
  }

  .panel-filter {
    max-width: none;
    justify-self: stretch;
  }

  /* .panel-fill's chart grows via flex:1 1 0 to match a taller grid neighbor -
     that only works in the desktop two-column grid, where CSS Grid's default
     row stretch gives the card a definite height to grow into. Below 760px the
     grid drops to one column, so panel-fill has no taller neighbor and no
     definite height; flex-basis:0 with nothing to grow into collapses the
     chart to zero height instead of falling back to its content size (the
     donut disappeared entirely). Restore a content floor for that case. */
  .panel-fill > .chart {
    min-height: 380px;
  }
}

/* --- Formality + drilldown views ------------------------------------------ */

.track {
  fill: var(--line);
  opacity: 0.35;
}

/* Ownership and capital: two linear bars per row. The old version of this
   chart put a median dot and an interquartile line on a log axis, which asked
   the reader to decode three conventions before seeing the point. Two plain
   bars on linear scales say it without instruction: the commonest way to
   register is also the way that puts in the least money. */
.own-head {
  fill: var(--muted);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.own-label {
  fill: var(--ink);
  font-size: 13px;
  font-weight: 650;
}

.own-value {
  fill: var(--muted);
  font-size: 11.5px;
  font-variant-numeric: tabular-nums;
}

.own-foot {
  fill: var(--muted);
  font-size: 11px;
}

.axis-note,
.empty-note {
  fill: var(--muted);
  font-size: 0.82rem;
}

/* Breadcrumb for the two drilldowns. Buttons rather than links: this is
   in-page state, not navigation. */
.crumbs {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 4px;
  max-width: 340px;
}

.crumb {
  background: none;
  border: 0;
  padding: 4px 8px;
  border-radius: 6px;
  font: inherit;
  font-size: 0.86rem;
  color: var(--green);
  cursor: pointer;
}

.crumb:hover {
  background: var(--bg);
}

.crumb + .crumb::before {
  content: "›";
  margin-right: 8px;
  color: var(--muted);
}

.crumb-current {
  color: var(--ink);
  font-weight: 650;
  cursor: default;
}

.crumb-current:hover {
  background: none;
}

.dbar-clickable {
  cursor: pointer;
}

.dbar {
  transition: opacity 0.12s ease;
}

.dbar:hover,
.fbar:hover {
  opacity: 0.82;
}

.tt-row {
  display: flex;
  justify-content: space-between;
  gap: 18px;
  margin-top: 3px;
}

.tt-hint {
  margin-top: 7px;
  padding-top: 6px;
  border-top: 1px solid rgba(255, 255, 255, 0.22);
  font-size: 0.8rem;
  opacity: 0.8;
}

.tooltip hr {
  margin: 7px 0 4px;
  border: 0;
  border-top: 1px solid rgba(255, 255, 255, 0.22);
}

/* --- Businesses against capital -------------------------------------------- */

/* The radar stands alone now. Cap its width so it stays a chart rather than
   stretching across a wide panel, and keep the caveat beside it readable. */
/* The 560px cap here was left over from when a dumbbell chart sat beside the
   radar. With the dumbbell gone the radar was a small circle in a half-empty
   panel, so the panel is now two columns: the chart takes the space it was
   wasting, and its note and caveat move alongside instead of underneath. */
.radar-wrap {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(250px, 1fr);
  gap: 4px 36px;
  align-items: start;
}

.radar-wrap > .chart {
  grid-column: 1;
  grid-row: 1;
  /* This chart sizes its own box to the circle inside it, so the page-wide
     300px floor would only reintroduce the empty space. */
  min-height: 0;
}

.radar-aside {
  grid-column: 2;
  grid-row: 1;
  align-self: center;
}

.radar-aside > .chart-notes.is-shown,
.radar-aside > .caveat,
.radar-aside > .why-it-matters {
  margin-top: 0;
  margin-bottom: 16px;
}

.radar-aside > :last-child {
  margin-bottom: 0;
}

.why-it-matters {
  color: var(--muted);
  font-size: 0.88rem;
  line-height: 1.5;
}

/* The figures table belongs under both columns. */
.radar-wrap > .data-table {
  grid-column: 1 / -1;
}

/* One column once the second would be too narrow to read. */
@media (max-width: 900px) {
  .radar-wrap {
    grid-template-columns: 1fr;
  }

  .radar-wrap > .chart,
  .radar-aside,
  .radar-wrap > .data-table {
    grid-column: 1;
    grid-row: auto;
  }

  .radar-aside {
    margin-top: 12px;
  }
}

.dual {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 26px 32px;
  align-items: start;
}

.dual-col {
  min-width: 0;
}

.sub-chart-title {
  margin: 0 0 8px;
  font-size: 0.72rem;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 700;
}

.caveat {
  margin: 12px 0 0;
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--muted);
  max-width: 52ch;
}

.caveat strong {
  color: var(--ink);
}

.radar-grid {
  fill: none;
  stroke: var(--line);
  stroke-width: 1;
}

.radar-spoke {
  stroke: var(--line);
  stroke-width: 1;
}

.radar-axis-label {
  font-size: 11px;
  fill: var(--muted);
}

/* Ring values, sitting on top of the grid and sometimes on top of an outline.
   paint-order puts a stroke of the panel colour behind the glyphs, which keeps
   them readable without a box around each one. */
.radar-ring-label {
  font-size: 10.5px;
  fill: var(--muted);
  font-variant-numeric: tabular-nums;
  paint-order: stroke;
  stroke: var(--panel);
  stroke-width: 3px;
  stroke-linejoin: round;
}

/* Legend for the two series in Businesses Against Capital. Both charts read
   from it, so it sits above them rather than being repeated in each. */
.swatch {
  display: inline-block;
  width: 12px;
  height: 12px;
  border-radius: 3px;
  margin-right: 8px;
  vertical-align: -1px;
}

.swatch-count { background: var(--series-3); }
.swatch-capital { background: var(--series-2); }

#capitalShareLegend {
  margin-top: 12px;
  border-top: 0;
  padding-top: 0;
}

/* --- Keyboard focus ------------------------------------------------------- */

/* Charts are SVG, so focus needs an explicit outline: the browser default is
   invisible on a filled rect. */
:where(a, button, select, summary, [tabindex]):focus-visible {
  outline: 3px solid var(--green);
  outline-offset: 2px;
  border-radius: 3px;
}

svg :where(rect, circle, g)[tabindex]:focus-visible {
  outline: 3px solid var(--ink);
  outline-offset: 1px;
}

/* --- Data tables ---------------------------------------------------------- */

.data-table {
  margin-top: 14px;
  border-top: 1px solid var(--line);
  padding-top: 10px;
}

.data-table > summary {
  cursor: pointer;
  font-size: 0.86rem;
  color: var(--green);
  list-style: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 2px;
}

.data-table > summary::-webkit-details-marker {
  display: none;
}

.data-table > summary::before {
  content: "▸";
  font-size: 0.8em;
  transition: transform 0.15s ease;
}

.data-table[open] > summary::before {
  transform: rotate(90deg);
}

.data-table table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.88rem;
  margin-top: 10px;
}

.data-table caption {
  text-align: left;
  color: var(--muted);
  font-size: 0.82rem;
  padding-bottom: 8px;
}

.data-table th,
.data-table td {
  text-align: left;
  padding: 6px 12px 6px 0;
  border-bottom: 1px solid var(--line);
  font-weight: 400;
}

.data-table thead th {
  color: var(--muted);
  font-size: 0.74rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  border-bottom-color: var(--ink);
}

.data-table .numeric {
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.data-table tbody th {
  font-weight: 600;
  color: var(--ink);
}

@media (prefers-reduced-motion: reduce) {
  .data-table > summary::before { transition: none; }
}

/* --- Annotations ----------------------------------------------------------
   Recessive by construction: the band is a tint of the ink rather than a colour
   of its own, so it never competes with a series, and the leader line is
   thinner than any mark. */
.ann-band {
  fill: var(--ink);
  opacity: 0.05;
}

.ann-band-label {
  fill: var(--muted);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

.ann-lead {
  stroke: var(--muted);
  stroke-width: 1;
  opacity: 0.6;
}

.ann-dot {
  fill: var(--muted);
}

.ann-note {
  fill: var(--ink);
  font-size: 12px;
  font-weight: 500;
}

/* The notes list under a chart. Clipped, not removed, while the notes are drawn
   on the plot: the chart is role="img", so this list is the only form of the
   annotation a screen reader ever reaches. */
.chart-notes {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.chart-notes.is-shown {
  position: static;
  width: auto;
  height: auto;
  margin: 10px 0 0;
  padding: 0 0 0 18px;
  overflow: visible;
  clip-path: none;
  white-space: normal;
  list-style: disc;
  color: var(--muted);
  font-size: 0.86rem;
  line-height: 1.5;
}

.chart-notes.is-shown li {
  margin-bottom: 5px;
}

.chart-notes.is-shown li::marker {
  color: var(--line);
}
