/* Chart kit — the look of every chart: cards, keys, bars, rings, lines,
   maps, tables and tooltips. The report and the gallery (chart-kit/charts.html)
   both load this file after their own stylesheet, and neither restyles a
   chart itself, so a change here reaches every chart on both.

   Scope: every rule sits under #report, the container the charts are drawn
   in. Site tokens (--ink, --mute, --surface, --line-soft, --mono, --display,
   --body, --r, --sp-*) come from the page's stylesheet.

   Split out of style.css; rules keep their original order and comments. */

/* ── Tokens ────────────────────────────────────────────────────────────
   The whole chart palette. charts-core.js reads these when it loads (as
   TP.C and TP.RAMPS), so a colour changed here changes every chart on every
   page that loads the kit. tokens.json is generated from this block for
   anyone rendering the charts outside a browser: node chart-kit/export-tokens.mjs */
:root{
  /* series colours, by role */
  --chart-accent: #064d90;
  --chart-mint:   #008cff;
  --chart-sand:   #62aee0;
  --chart-deep:   #051c23;
  --chart-warn:   #0a3a66;
  --chart-hot:    #ff7a00;
  --chart-dim:    #051c23;
  /* the categorical order bars cycle through, a colour per row */
  --chart-series: #064d90, #008cff, #62aee0, #0a3a66, #ff7a00, #2f76a9;
  /* furniture */
  --chart-ink:    #051c23;               /* a ring's centre figure */
  --chart-off:    #e3e7ea;               /* a series or area greyed out by a key */
  --chart-nodata: #ffffff;               /* a map area with no value */
  --chart-water:  #c9c9c9;
  --chart-ground: #dfe6ea;               /* the tracts under a dot map */
  --chart-field:  rgba(5,28,35,.04);     /* the tinted field behind bars */

  /* Choropleth ramps, five steps each, light to heavy. Every ramp is ONE
     hue. Two maps side by side take primary (blue, left) and secondary
     (orange, right): roles, not new colours. */
  --ramp-blue:    #e0ecf6, #aecde4, #6ea6c9, #2f76a9, #064d90;
  --ramp-mint:    #e0f2ff, #b0dcff, #74bdfa, #2f9bef, #008cff;
  --ramp-sand:    #ffe3c2, #ffc27a, #ffa03c, #ff7a00, #cc5f00;
  --ramp-heat:    #fff0de, #ffc27a, #ff9a33, #ff7a00, #b35300;
  /* a dark reading of the blue, for a second blue map in a chapter */
  --ramp-deep:    #d5dee6, #9db5c6, #5d7f9b, #26455f, #051c23;
  /* weighted on the middle class, for a measure whose interesting band is
     mid-range */
  --ramp-deepmid: #cdeeff, #74bdfa, #051c23, #96a5ad, #e8ebed;
  --ramp-parcel:  #e0ecf6, #c3daec, #9cc2de, #6ea6c9, #3f86b8, #1f649a, #064d90;
  --ramp-underuse: #b35300, #ff7a00, #ffc27a, #ffe3c2;
}

/* Two charts abreast inside one full-width card, on the module's own gutter. */
#report .chartpair{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  gap:var(--sp-s) 34px}
@media (max-width:767px){#report .chartpair{grid-template-columns:minmax(0,1fr)}}
/* No card surface — but only when the card really holds a map. The class is
   applied to whichever card opens a section, and in Economy that is a line
   chart, which needs its white card like any other. */
/* Not scoped to .statmod: the gallery page draws the same card outside the
   report's module wrapper and must get the same bare treatment. */
#report .secmap:has(.mapwrap){background:none;border-color:transparent;
  box-shadow:none;padding:0}
/* The "?" belongs beside the title it explains, not pinned to the far edge
   of a card that no longer has an edge. */
/* Only a real map: on a map the title floats on the page, so the "?" belongs
   beside it rather than out at an edge the card no longer has. A chart card
   still has its edge, and the "?" stays in the top-right corner. */
#report .secmap:has(.mapwrap) .cardhead{justify-content:flex-start}
#report .secmap:has(.mapwrap) .cardhead h3{flex:0 1 auto}
/* The "?" and the download sit as a pair beside the title, not spread across
   the head, and both carry the card's white so they read as controls on the
   page's grey ground. */
#report .secmap:has(.mapwrap) .cardhead{gap:5px}
/* Half again the size of the ones on a chart card: on a map there is no card
   edge to hold them, so they carry more weight. The "?" keeps its place on
   the title's x-height midline, which at 27px means half the extra height
   comes off the top margin. */
#report .secmap:has(.mapwrap) .cardhead .capq{
  margin-left:6px;margin-top:-.5px;width:27px;height:27px;font-size:14px}
/* Half the width — at full width the key was a longer line than the title. */
#report .secmap .scale{max-width:50%}
/* The stepped key: a label over one swatch per value, rather than a ramp
   between two end labels. */
#report .scale.steps{display:block;max-width:none;margin:0 0 18px}
#report .scale.steps:has(.spread){display:flex;align-items:flex-start}
#report .steps-lab{display:block;font:600 11px/1 var(--display);
  letter-spacing:.1em;text-transform:uppercase;color:var(--dim);margin:0 0 9px}
#report .steps-row{display:flex;gap:10px}
/* A scale rather than a list of categories: the bands share the width. */
#report .steps-row.spread{gap:4px;flex:1}
#report .steps-row.spread .step{width:auto;flex:1;min-width:34px}
/* packed (see fitKeys): the bands sit left, each the width of the longest
   label, rather than stretching across the card. */
#report .steps-row.spread.packed{justify-content:flex-start;flex:none}
#report .steps-row.spread.packed .step{flex:none}
#report .steps-row.spread.packed .step span{white-space:nowrap}
/* A range is a longer label than a single value, so it is set smaller and
   allowed to wrap rather than being clipped by its band. */
#report .steps-row.spread .step span{text-align:left;font-size:11px;
  line-height:1.3;white-space:normal;overflow-wrap:anywhere}
#report .step{display:flex;flex-direction:column;gap:6px;width:56px;
  cursor:pointer;transition:opacity .15s}
/* The steps not being hovered take the same grey the map areas take, so the
   key shows the same state the map is in rather than just fading.
   --chart-off is the grey the map areas take; !important because the
   swatch colour is an inline style set when the key is built. */
#report .map-key.focused .step:not(.on) i{background:var(--chart-off)!important}
#report .map-key.focused .step:not(.on) span{opacity:.5}
#report .step:focus-visible{outline:2px solid var(--mint);outline-offset:3px;
  border-radius:4px}
#report .secmap svg path{transition:fill .15s}
/* A hairline inside the swatch. The palest class in a ramp is lighter than
   the page it sits on, so without it the first band reads as an empty gap —
   the map's own colours are left alone, because the key has to be the same
   colours the map paints. */
#report .step i{display:block;height:9px;border-radius:5px;
  box-shadow:inset 0 0 0 1px rgba(5,28,35,.14)}
#report .step span{font:500 12px var(--mono);color:var(--mute);text-align:center}
#report .map-context-keys{flex-wrap:wrap;gap:12px 20px}
#report .step.map-context{width:max-content;max-width:100%;flex-direction:row;align-items:center;gap:8px}
#report .step.map-context i{width:32px;flex-shrink:0}
#report .step.map-context span{text-align:left}
/* The map itself, two thirds bigger. The cap it overrides is an inline
   style on the <svg> (max-height:400px), so this needs !important. */
#report .secmap .mapwrap svg{max-height:667px!important}
/* The entries not being hovered take the same grey the slices take.
   --chart-off, the grey the other shapes take. */
#report .legend span{cursor:pointer;transition:opacity .15s}
#report .legend-on .legend span:not(.on) i{background:var(--chart-off)!important}
#report .legend-on .legend span:not(.on){opacity:.65}
#report .legend span:focus-visible{outline:2px solid var(--mint);
  outline-offset:3px;border-radius:4px}
/* A half ring has no bottom half to balance its top, so left in the flow it
   hangs below the key with a band of empty card above it. Lifted by the head
   (one line of h3, 25px, plus its 15px margin) it starts level with the title
   and ends level with the key. */
/* Gallery: the key stacked flush left with the chart beside it, so the ring
   gets the rest of the card's width instead of sitting under the key. */
/* The key's last line sits on the chart's own bottom, which keyToBaseline in
   charts-gallery.js finds from the drawn shape, not from the svg box. */
#report .card .lleft{display:flex;align-items:flex-end;gap:24px}
#report .card .lleft{min-height:0}
/* rule 3: a card with room to spare centres the key on the ring */
#report .card .lleft.ringmid{align-items:center}
#report .card .lleft > .legend{order:-1;flex:0 0 auto;flex-direction:column;
  align-items:flex-start;gap:9px;margin:0}
#report .card .lleft > svg{flex:1;min-width:0}
/* The vertical version of the same pair: the key above the chart, one line
   per series, and the ring on the card's full width under it. */
#report .card .ltop{display:flex;flex-direction:column}
#report .card .ltop > .legend{flex-direction:row;flex-wrap:wrap;
  align-items:center;gap:8px 18px;margin:0 0 14px}
#report .card .ltop > svg{width:100%}

/* Mid widths keep the two-column shape and only even up the ratio. The
   other chart rows go back to auto-fit; they have no placement to keep. */
@media (max-width:1023px){
  #report .secmap .scale{max-width:none}

}
#report .card{background:var(--surface);border:1px solid var(--line-soft);
  border-radius:var(--r);padding:19px 20px 15px;min-width:0;
  display:flex;flex-direction:column;box-shadow:0 1px 2px rgba(5,28,35,.05)}
#report .card h3{font-size:15px;font-weight:600;letter-spacing:-.01em}
#report .card .cap{color:var(--mute);font-size:13.5px;margin:5px 0 15px;line-height:1.55;
  max-width:65ch}
#report .card svg{display:block;width:100%;height:auto;overflow:visible}
#report .mapwrap svg{overflow:hidden}
#report .axis{font:500 12px var(--mono);fill:var(--mute)}
#report .vlab{font:600 12px var(--mono);fill:var(--dim)}
/* Gallery: row labels read as quiet type, not as headings. */
#report svg.barsh .vlab{font-weight:400}
/* Row rules in an svg chart, matching the criteria table's. */
#report .rowrule{stroke:var(--ink);stroke-opacity:.12;stroke-width:1}
/* The rules run edge to edge inside the card: the svg bleeds into the card's
   20px side padding and the bars are inset back by the same amount in
   viewBox units (see fitBars in charts-core.js). */
#report .card > svg.barsh,#report .card > svg.barsv-bleed{
  margin:0 -20px -15px;width:calc(100% + 40px);max-width:none}
/* Column titles and the rules between categories. The rule is the same 35%
   ink as the map's keylines, so the two read as one family. */
#report .colhead{font:600 10.5px var(--mono);fill:var(--mute);
  letter-spacing:.09em;text-transform:uppercase}
/* ── criteria table ───────────────────────────────────────────────────
   Four columns: the criteria, the band, its count, and the population. HTML,
   not svg, so the type is the size it says it is at every card width.
   The rows' rules run to the card's edges — the negative margin is the
   card's own 20px padding — so they read as a table, not as a stack of
   boxes inset from it. */
#report .critab{display:flex;flex-direction:column}
/* The card ends where the table ends: no band of white under the last row's
   tint. :has, so only the card that actually holds this table loses its
   bottom padding. */
#report .card:has(> div > .critab){padding-bottom:0}

#report .critab-head,#report .critab-row{
  display:grid;
  /* The criteria track does not shrink: at minmax(0,150px) it collapsed on a
     narrow card and "Minority, income and English isolation" went to four
     lines, which is what made the rows different heights. */
  /* 146, not 150: the tint starts at this track's edge, so narrowing it by
     4 moves the grey left. The criteria text does not move with it — its
     right padding drops by the same 4 — and the gaps either side of the tint
     come out equal at 16. */
  grid-template-columns:146px minmax(36px,1fr) 44px 52px;
  /* No column gap: the spacing is padding on the cells instead, so the tint
     behind the band and its count is one continuous strip rather than two
     with a stripe of card showing between them. */
  column-gap:0;align-items:center;margin:0 -20px;padding:0 20px}
/* The gap under the head is padding on its CELLS, not on the row: a cell's
   background covers its own padding, so the tint reaches the keyline while
   the text still sits clear of it. On the row it left the tint stopping
   short and the heads sitting above the rule at different heights. */
#report .critab-head{
  letter-spacing:.06em;text-transform:uppercase;align-items:end}
#report .critab-head .c1,#report .critab-head .c4{padding-bottom:9px}
/* The head has three cells in a four-column grid, so auto-placement put
   "Pop." in the count's column. Both are placed explicitly: the band's title
   spans the band and its count — it names both — and Pop. sits over its own
   column, which also stops "Block groups" wrapping into two lines. */
/* No nowrap: on a narrow card the spanned columns are shorter than "BLOCK
   GROUPS" and it ran straight over POP. It wraps instead; the head row is
   the one place where that costs nothing. */
/* The same 9px above the title as below it. The head cells are bottom
   aligned, so the top padding grows the tint upward and leaves the text
   where it is. */
#report .critab-head .c2{text-align:left;grid-column:2/4;line-height:1.2;
  padding:9px 12px}
#report .critab-head .c4{grid-column:4}
/* One height for every row, whether its label takes one line or two. */
#report .critab-row{height:54px;border-top:1px solid rgba(5,28,35,.12)}
/* padding-right, not a narrower track: the text is right-aligned, so this
   moves the whole column 10px left and widens the gap to the bands without
   changing where the bands start. */
#report .critab .c1{text-align:right;font:400 13px var(--body);
  color:var(--ink);line-height:1.3;padding-right:16px}
/* Stretched, so the tint is the full height of the row: grid items are only
   as tall as their content when the row centres them, which made the band a
   floating strip around the bar instead of a column. The cells centre their
   own content instead. */
#report .critab .c2,#report .critab .c3{align-self:stretch;
  display:flex;align-items:center}
#report .critab .c2{padding-left:12px;padding-right:8px}
#report .critab .c3{padding-right:12px;justify-content:flex-end}
#report .critab .c4{padding-left:16px}
/* The block-groups column reads as one field: the band and the count it
   belongs to, tinted away from the card. The heading sits above the field
   rather than inside it, so it takes no tint. */
#report .critab-row .c2,#report .critab-row .c3{background:rgba(5,28,35,.04)}
/* The criteria and the population either side take a lighter tint of the
   same ink, so the three fields read as columns without the middle one
   losing its emphasis. Body rows only — the headings sit above the fields. */
#report .critab-row .c1,#report .critab-row .c4{background:rgba(5,28,35,.02)}
/* Gallery: the label column carries no tint — only the measured columns do. */
#report .critab-row .c1{background:none}
/* Gallery criteria table:
   — a wider gap between the criteria and the band it labels;
   — no fourth track when the rows carry no Pop. cell, so the tint runs to
     the card's edge instead of stopping 52px short of it;
   — and the card ends where the table does (the report's rule looks for
     `> div > .critab`; here the table is the card's own child). */
#report .critab .c1{padding-right:44px}
/* Column titles set as the data table's are: mono, 12px, quiet, wider
   tracking. */
#report .critab-head .c1,
#report .critab-head .c2,
#report .critab-head .c4{font:600 12px var(--mono);letter-spacing:.09em;
  color:var(--mute)}
#report .critab:not(:has(.c4)) .critab-head,
#report .critab:not(:has(.c4)) .critab-row{
  grid-template-columns:210px minmax(36px,1fr) 44px}
#report .card:has(> .critab){padding-bottom:0}
/* The row's own right padding is what kept the tint 20px short of the card:
   it is dropped and the count carries the inset itself. */
#report .critab-head,#report .critab-row{padding-right:0}
#report .critab .c3{padding-right:20px}
/* The figures column of a data table reads as one field, like the band in
   the criteria table: head and cells share the tint. */
/* The tint is the field, not the heading: the head stays on the card and the
   band starts under it, reaching left of the figures the way the block-groups
   band does — the extra width is padding, so the figures do not move. */
/* The figures column is the second one — the last in a two-column table, the
   middle one where there are three. */
#report .card > table td:nth-child(2),
#report .card > div > table td:nth-child(2){background:rgba(5,28,35,.04);
  padding-left:12px}
#report .card > table th:nth-child(2),
#report .card > div > table th:nth-child(2){padding-left:12px}
/* and the column after it clears the tint by the same 12px its own column
   leaves inside it */
#report .card > table td:nth-child(3),#report .card > table th:nth-child(3),
#report .card > div > table td:nth-child(3),
#report .card > div > table th:nth-child(3){padding-left:12px}
/* and, as in the criteria table, the card ends where the table ends, so the
   tint runs to the bottom edge instead of stopping above a white band. The
   corners are kept by clipping the card, which has nothing overflowing it. */
#report .card:has(> table),#report .card:has(> div > table){
  padding-bottom:0;overflow:hidden}
/* Gallery cards are plain white fields: no border, no shadow. The border is
   removed, not made transparent: a transparent 1px border still shows the
   card's white under it, so a tinted field bled to the edge (fill:true bars)
   carried a white keyline round it. */
#report .card{border:0;box-shadow:none}
#report .critab .c2 i{display:block;height:10px;border-radius:5px;flex:none}
#report .critab .c3,#report .critab .c4{
  font:500 11.5px var(--mono);color:var(--mute);white-space:nowrap}
/* Left-aligned, so the header sits directly over the first digit of the
   numbers rather than over their ragged right edge. */
#report .critab .c4{text-align:left}
/* The three column titles are one set, in the body face rather than two of
   them in the numbers' mono. Set 1.5px under the criteria they head: the
   titles are uppercase, and uppercase at the same point size reads a size
   larger than the mixed-case rows beneath it. */
#report .critab-head .c1,
#report .critab-head .c2,
#report .critab-head .c4{font:600 11.5px var(--body);color:var(--ink)}
#report .critab-head .c4{text-align:left}
/* Isolating a series on hover swaps colours on the shapes; without this it
   snapped. A short cross-dissolve on fill, stroke and opacity covers every
   chart at once — bars, rings, lines and the gradient areas, which fade
   their opacity instead because a gradient fill cannot be tweened. */
#report .card svg path,#report .card svg rect,#report .card svg circle{
  transition:fill .22s ease,stroke .22s ease,opacity .22s ease}
/* ── charts arrive as you scroll ──────────────────────────────────────
   The observer in planning.js adds .in on first crossing; everything else
   is here. transform-box:fill-box so an svg rect scales from its own edge
   rather than from the svg's origin. */
@media (prefers-reduced-motion:no-preference){
  #report rect.hbar,#report rect.vbar,#report .critab .c2 i{
    transform-box:fill-box;
    transition:transform .55s cubic-bezier(.22,1,.36,1),
               fill .22s ease,stroke .22s ease,opacity .22s ease}
  #report rect.hbar{transform-origin:left center;transform:scaleX(0)}
  #report rect.hbar-l{transform-origin:right center}
  #report rect.vbar{transform-origin:center bottom;transform:scaleY(0)}
  #report .critab .c2 i{transform-origin:left center;transform:scaleX(0);
    transition-duration:.5s}
  #report .card.in rect.hbar,#report .card.in rect.vbar,
  #report .critab.in .c2 i{transform:none}
  /* Row by row rather than all at once. */
  #report .card rect.hbar:nth-of-type(2){transition-delay:.05s}
  #report .card rect.hbar:nth-of-type(3){transition-delay:.1s}
  #report .card rect.hbar:nth-of-type(4){transition-delay:.15s}
  #report .card rect.hbar:nth-of-type(5){transition-delay:.2s}
  #report .card rect.hbar:nth-of-type(n+6){transition-delay:.25s}
  #report .critab-row:nth-child(3) .c2 i{transition-delay:.05s}
  #report .critab-row:nth-child(4) .c2 i{transition-delay:.1s}
  #report .critab-row:nth-child(5) .c2 i{transition-delay:.15s}
  #report .critab-row:nth-child(n+6) .c2 i{transition-delay:.2s}
  /* The fill under the line arrives just behind it, and the markers last —
     the shape is read before the points on it. A gradient fill cannot be
     tweened, so this is opacity, which is also what the key's isolation
     uses on these paths (as an inline style, which outranks this). */
  #report .card svg path[fill^="url("]{opacity:0;
    transition:opacity .6s ease .2s}
  #report .card.in svg path[fill^="url("]{opacity:1}
  #report .card svg circle{opacity:0;transition:opacity .4s ease .55s}
  #report .card.in svg circle{opacity:1}
  /* The line draws itself; pathLength:1 makes the dash maths unit-length. */
  #report .linepath{stroke-dasharray:1;stroke-dashoffset:1;
    transition:stroke-dashoffset 1.1s ease}
  #report .card.in .linepath{stroke-dashoffset:0}
  /* Donut slices and the maps just arrive. */
  #report .card svg path.bar{opacity:0;
    transition:opacity .5s ease,fill .22s ease}
  #report .card.in svg path.bar{opacity:1}
  #report .mapwrap{opacity:0;transform:translateY(6px);
    transition:opacity .6s ease,transform .6s cubic-bezier(.22,1,.36,1)}
  #report .mapwrap.in{opacity:1;transform:none}

}
#report .gl{stroke:var(--line-soft);stroke-width:1}
#report .bar{transition:opacity .15s}
#report .bar:hover{opacity:.75}
/* A key that sits above its chart carries the gap below it instead. */
#report .legend.legend-top{margin:0 0 var(--sp-s)}
#report .legend{display:flex;flex-wrap:wrap;gap:14px;margin-top:13px;
  font:500 12px var(--mono);color:var(--mute)}
#report .legend i{width:10px;height:10px;border-radius:3px;display:inline-block;
  margin-right:6px;vertical-align:-1px}
/* Gallery: round key swatches, no keyline — a dot reads as a series marker
   where a rounded square reads as a chip. */
#report .legend i{border-radius:50%;border:0;
  box-shadow:none}
#report .mapwrap{position:relative}
#report .small-map-note{margin:0 0 18px;padding:16px;background:var(--surface,#fff);
  border:1px solid var(--line-soft,#d9dfe3);border-radius:10px;color:var(--ink);
  font:400 14px/1.5 var(--body);overflow-wrap:anywhere}
#report .small-map-note p{margin:0 0 12px}
#report .small-map-note button{width:auto;max-width:100%;white-space:normal;text-align:left}
/* The dividers between areas match the city outline: same ink, same 35% —
   stroke-opacity rather than opacity, because opacity would fade the fill
   with it and wash the whole map out. */
#report .mapwrap svg path{stroke:var(--ink);stroke-opacity:.35;
  stroke-width:.5;transition:.12s}
#report .mapwrap svg path:hover{stroke:var(--ink);stroke-opacity:1;
  stroke-width:1.1}
#report .mapwrap svg path.outline{fill:none;stroke:var(--ink);stroke-width:1.2;
  opacity:.35;pointer-events:none}
/* No fill here: it is set as an attribute so the stepped key can dim the
   base along with the areas. A fill in CSS would override that attribute. */
#report .mapwrap svg path.mapbase{stroke:none;pointer-events:auto}
#report .mapwrap svg path.mapwater{stroke:none}
#report .parcelmap svg{width:100%;height:auto;max-height:667px}
#report .parcelmap svg path{stroke:none}
#report .parcelmap svg path:hover{stroke:var(--ink);stroke-opacity:1;stroke-width:1}
#report .parcelmap .parcel-switch{display:flex;gap:6px;margin:0 0 10px}
#report .parcelmap .parcel-switch button{font:500 12px var(--mono);padding:4px 10px;
  border:1px solid var(--line-soft,#d9dfe3);border-radius:999px;background:var(--surface,#fff);
  color:var(--ink);cursor:pointer}
#report .parcelmap .parcel-switch button[aria-pressed="true"]{background:var(--ink);color:#fff}
#report .parcelmap .parcel-note{margin:8px 0 0;font:400 12px/1.4 var(--mono);color:var(--mute)}
#report .scale{display:flex;align-items:center;gap:9px;margin:0 0 12px;
  font:500 12px var(--mono);color:var(--mute)}
#report .tip{position:absolute;pointer-events:none;background:#051c23;
  border:1px solid #0b3a5e;border-radius:8px;padding:7px 10px;
  font:500 12px var(--mono);color:#ffffff;opacity:0;transition:opacity .12s;
  z-index:9;white-space:nowrap;box-shadow:0 6px 20px rgba(5,28,35,.28)}
#report td.n{font-family:var(--mono);color:var(--accent)}
/* The row rules run to the card's edges rather than stopping at its padding,
   so a table reads as a table and not as a stack of rows inset from the box.
   The negative margin is the card's own 20px side padding, given back to the
   first and last cells so the text still lines up with the title above it.
   .critab-look sets its own version of this below. */
#report .card > table,#report .card > div > table{
  margin:0 -20px;width:calc(100% + 40px)}
#report .card > table th:first-child,#report .card > table td:first-child,
#report .card > div > table th:first-child,
#report .card > div > table td:first-child{padding-left:20px}
#report .card > table th:last-child,#report .card > table td:last-child,
#report .card > div > table th:last-child,
#report .card > div > table td:last-child{padding-right:20px}
/* ── a table presented like the criteria table ────────────────────────
   Same heads, same full-bleed row rules, same quiet numbers. The rules run
   to the card's edges — the negative margin is the card's own 20px padding —
   so it reads as a table rather than a stack of rows inset from it. */
#report .critab-look table{margin:0 -20px;width:calc(100% + 40px)}
#report .critab-look th{font:600 11.5px var(--body);letter-spacing:.06em;
  text-transform:uppercase;color:var(--ink);border-bottom:0;
  padding:0 12px 9px 0}
#report .critab-look thead tr{border-bottom:1px solid rgba(5,28,35,.12)}
#report .critab-look td{border-bottom:0;border-top:1px solid rgba(5,28,35,.12);
  height:54px;padding:0 12px 0 0}
#report .critab-look th:first-child,
#report .critab-look td:first-child{padding-left:20px}
#report .critab-look th:last-child,
#report .critab-look td:last-child{padding-right:20px}
#report .critab-look td.n{font:500 11.5px var(--mono);color:var(--mute)}
#report .critab-look td:first-child{font:400 13px var(--body);color:var(--ink)}
/* …except a card table, which is deliberately wider than its content box so
   its row rules reach the card's edges. max-width:100% above resolves
   against that content box and was clamping the width:calc() back. */
#report .card > table,#report .card > div > table{max-width:none}
/* Gallery: the row rules run the card's full width. `display:block` (the
   mobile scroll shim) makes the table shrink-wrap its cells, so width:100%
   never reaches the edges — these tables fit, so they stay real tables. */
#report .card > table,#report .card > div > table{display:table;
  /* the rows share out a stretched card, so the tinted column reaches the
     card's bottom edge instead of stopping above a white band */
  height:100%}

/* ── wave 5: empty states and first-use glosses ──────────────────────── */
/* E4: a panel with nothing to draw used to render as a bare caption,
   indistinguishable from one still loading. */
#report .empty {
  border: 1px dashed var(--line-soft); border-radius: var(--r);
  padding: 20px; color: var(--mute); font-size: 13.5px;
  text-align: center; line-height: 1.55;
}
#report .card .cap{ position: relative; }

/* ── FN9: card captions become a hoverable question mark ─────────────── */
#report .cardhead {
  display: flex; align-items: flex-start; gap: 9px;
  position: relative; margin-bottom: 15px;
}
#report .cardhead h3 { flex: 1; min-width: 0; }
/* The dot sits on the title's x-height midline, not on the top of its box:
   the head aligns to flex-start, so the 4px the two centres were apart is
   taken off here. */
#report .capq {
  flex: none; width: 18px; height: 18px; padding: 0; border-radius: 50%;
  border: 1px solid var(--line-soft); background: none; color: var(--mute);
  font: 600 12px/1 var(--body); cursor: help; margin-top: 4px;
}
#report .secmap:has(.mapwrap) .capq{background:#fff}
#report .capq:hover { color: var(--ink); border-color: var(--mute); }
#report .capq:focus-visible {
  outline: 2px solid var(--brand-line); outline-offset: 2px;
}
/* anchored to the card head's RIGHT edge, so a long caption opens inwards
   and can never push the page sideways the way the first gloss tooltip did */
#report .capq::after {
  content: attr(data-cap); display: none; position: absolute; right: 0;
  top: calc(100% + 7px); z-index: 30; width: max-content;
  max-width: min(320px, calc(100vw - 32px)); text-align: left;
  background: var(--brand-deep); color: #ffffff;
  font: 400 12px/1.45 var(--body); padding: 8px 10px; border-radius: 7px;
  box-shadow: 0 4px 16px rgba(5, 28, 35, .32); pointer-events: none;
}
#report .capq:hover::after,
#report .capq:focus-visible::after { display: block; }

/* ── chart tooltip ────────────────────────────────────────────────────
   One element for the whole report (see planning.js). Fixed, so it is not
   clipped by a card's overflow, and pointer-events:none so it never steals
   the hover from the shape that summoned it. */
#report .charttip{
  position:fixed;left:0;top:0;z-index:60;pointer-events:none;
  max-width:22rem;padding:7px 10px;border-radius:8px;
  background:rgba(5,28,35,.94);color:#fff;
  font:500 12px/1.35 var(--mono);white-space:nowrap;
  box-shadow:0 6px 20px rgba(5,28,35,.22);
  opacity:0;transform:translateY(3px);
  transition:opacity .12s ease,transform .12s ease;
}
#report .charttip.on{opacity:1;transform:none}
@media (prefers-reduced-motion:reduce){
  #report .charttip{transition:none}
}

/* ── phone ─────────────────────────────────────────────────────────────
   Checked at 375: two cards abreast left the bar labels rendering at 2.7px
   and squeezed the ring's chart to nothing, because a key-beside-chart row
   keeps its flex direction however narrow it gets. Below 768 every paired
   row stacks and the key goes back above its chart. */
@media (max-width:767px){
  #report .card .lleft{flex-direction:column;align-items:stretch;gap:14px}
  #report .card .lleft > .legend{order:-1;margin:0 !important}
  #report .card .lleft > svg{width:100%;height:auto !important;
    margin-top:0 !important;margin-bottom:0 !important}
  #report .secmap:has(.mapwrap) .mapwrap{width:100%;margin:0}

}
