/* datasets-demo.nodejavascript.com
   Theme colour  #0891b2   — untaken (register read 20 Sep 2026)
   Background    #041218   — untaken
   Drawing       a stepped block field: two conic-gradient layers at different
                 pitches, masked so it dissolves. Not a neighbour's shape.
   Gradient signature: 3 radial + 2 linear + a repeating stepped texture, masked.
*/

:root {
  --accent: #0891b2;
  --accent-soft: #22d3ee;
  --bg: #041218;
  --ink: #e8f6f9;
  --muted: #8fb3bd;
  --hairline: rgba(34, 211, 238, .16);
  --card: rgba(8, 30, 38, .55);
  --consent-height: 0px;
}

/* part 2 · a class that declares display beats the [hidden] attribute, so the
   attribute is stated to win, once, plainly. */
[hidden] { display: none !important; }

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 16px/1.6 ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  /* the bar's space is reserved HERE, after everything, so the footer's own
     bottom edge clears it. */
  padding-bottom: var(--consent-height);
}

/* ---- the base wash: three soft glows and two slow sweeps, every stop fading ---- */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(60rem 40rem at 12% -10%, rgba(8, 145, 178, .22), transparent 70%),
    radial-gradient(48rem 34rem at 92% 8%, rgba(34, 211, 238, .13), transparent 72%),
    radial-gradient(70rem 50rem at 50% 118%, rgba(8, 145, 178, .16), transparent 74%),
    linear-gradient(178deg, rgba(4, 18, 24, 0) 0%, rgba(6, 40, 52, .55) 55%, rgba(4, 18, 24, 0) 100%),
    linear-gradient(96deg, rgba(34, 211, 238, .05) 0%, rgba(4, 18, 24, 0) 60%);
}

/* ---- part 5d-ii · THIS SITE'S DRAWING -------------------------------------------------
   A ruled ledger: a fine rule every 18px with a heavier rule every 90px, the
   field a printed data table is made of. Hard-edged, not a wash — but the whole
   layer is masked with a single soft gradient so it dissolves towards the foot of
   the page rather than stopping at a visible line.

   The first attempt at this was two conic layers, and it read as a soft wash with
   faint verticals the moment it was looked at in a browser. That is the fault part
   5d-ii exists to catch, so the geometry was changed, not the shade.

   Only horizontal rules, deliberately: `word-cloud` already owns vertical bars. */
.dvs-pattern {
  position: fixed;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  opacity: .85;
  background-image:
    /* the fine rule */
    repeating-linear-gradient(0deg,
      rgba(34, 211, 238, .17) 0 1px, rgba(0, 0, 0, 0) 1px 18px),
    /* every fifth rule, heavier — the group break on a printed table */
    repeating-linear-gradient(0deg,
      rgba(8, 145, 178, .30) 0 2px, rgba(0, 0, 0, 0) 2px 90px),
    /* a faint column tick, so the field is a grid of rules and not just lines */
    repeating-linear-gradient(90deg,
      rgba(34, 211, 238, .07) 0 1px, rgba(0, 0, 0, 0) 1px 120px);
  background-repeat: repeat, repeat, repeat;
  -webkit-mask-image: linear-gradient(180deg,
    rgba(0, 0, 0, .95) 0%, rgba(0, 0, 0, .75) 40%, rgba(0, 0, 0, .35) 74%, rgba(0, 0, 0, 0) 100%);
  mask-image: linear-gradient(180deg,
    rgba(0, 0, 0, .95) 0%, rgba(0, 0, 0, .75) 40%, rgba(0, 0, 0, .35) 74%, rgba(0, 0, 0, 0) 100%);
}

/* ---- part 3 · the header bar ---- */
.top {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 12px 20px;
  background: rgba(4, 18, 24, .82);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--hairline);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: var(--ink);
  text-decoration: none;
}

.brand .mark,
.footer-brand .mark { color: var(--accent-soft); display: inline-flex; }

.brand b {
  display: block;
  font-size: 15px;
  font-weight: 650;
  letter-spacing: .2px;
  line-height: 1.1;      /* keeps the bar at 60px */
}

.brand small {
  display: block;
  font-size: 11.5px;
  color: var(--muted);
  letter-spacing: .4px;
  text-transform: uppercase;
  line-height: 1.1;
}

/* ---- the page ---- */
main {
  position: relative;
  z-index: 2;
  max-width: 960px;
  margin: 0 auto;
  padding: 40px 20px 72px;
}

h1 {
  font-size: clamp(1.9rem, 4.6vw, 2.9rem);
  line-height: 1.15;
  margin: 0 0 18px;
  letter-spacing: -.4px;
}

h2 { font-size: 1.28rem; line-height: 1.3; margin: 0 0 10px; }

.lede { font-size: 1.06rem; color: #cfe9ee; max-width: 62ch; margin: 0 0 34px; }
.noteLine { display: block; margin-top: 10px; color: var(--muted); font-size: .92rem; }

.room {
  margin: 0 0 46px;
  padding: 22px 22px 18px;
  background: var(--card);
  border: 1px solid var(--hairline);
  /* The header is STICKY, so jumping to a room (or opening a #link) put the room's
     own heading underneath it -- the kicker was sliced in half on arrival, which
     reads as a broken page rather than a scrolled one. An anchor offset fixes it
     for every room at once. */
  scroll-margin-top: 74px;
  border-radius: 14px;
}

.eyebrow {
  margin: 0 0 6px;
  font-size: .74rem;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--accent-soft);
}

.promise { color: #cfe9ee; margin: 0 0 18px; font-size: 1.02rem; }

.method {
  margin: 16px 0 0;
  padding-top: 12px;
  border-top: 1px solid var(--hairline);
  color: var(--muted);
  font-size: .87rem;
  line-height: 1.65;
}

.figure { margin: 0; }

/* ---- the drawings ---- */
.bars { display: grid; gap: 6px; }

.barRow {
  display: grid;
  grid-template-columns: minmax(104px, 230px) 1fr auto;
  align-items: start;
  gap: 10px;
  font-size: .86rem;
}

/* WRAP THE LABEL. DO NOT TRUNCATE IT.
   These labels are the finding. `C/A — The rest - codes the Board does not name`
   needs 373px and was being cut to 132, so NINETEEN labels on this page read as
   fragments: `L — Landlord appli...`, `L2 — the landlord'...`. An ellipsis on a
   label is a promise to say a thing and then not saying it. */
.barLabel {
  color: #cfe9ee;
  white-space: normal;
  overflow-wrap: anywhere;
  line-height: 1.3;
  padding-top: 1px;
}

.barTrack {
  position: relative;
  height: 16px;
  margin-top: 2px;
  background: rgba(255, 255, 255, .05);
  border-radius: 3px;
  overflow: hidden;
}

.barFill {
  position: absolute;
  inset: 0 auto 0 0;
  background: linear-gradient(90deg, var(--accent), var(--accent-soft));
  border-radius: 3px;
}

.barValue { color: var(--muted); font-variant-numeric: tabular-nums; padding-top: 1px; }

/* ---- read against a base rate ----
   The split says how private and company divide; the line says whether that
   division is a preference or just the room. Without it, "+10.1" is a number with
   nothing to compare to, and 74% looks like a finding when the base is 63.9%.

   The marker lives in a WRAPPER, not in the track: `.stackTrack` clips its children
   for the rounded ends, and a marker inside it was clipped away -- while without
   position: relative it escaped and drew a white line the full height of the page. */
.stackHolder { position: relative; display: block; min-width: 0; }
.stackBaseMark {
  position: absolute;
  top: -3px;
  bottom: -3px;
  width: 2px;
  background: #f8fafc;
  opacity: .9;
  z-index: 3;
  pointer-events: none;
}

/* ---- the paired comparison ----
   The renoviction question is "compared with what", so the two numbers that answer
   it sit under one heading instead of on two long separate rows. */
.groupRow { margin-bottom: 14px; }
.groupRow:last-child { margin-bottom: 0; }
.groupHead {
  margin: 0 0 5px;
  color: var(--ink);
  font-size: .87rem;
  font-weight: 600;
  line-height: 1.3;
}
.groupNote { color: var(--muted); font-weight: 400; font-variant-numeric: tabular-nums; }
.groupBar {
  display: grid;
  grid-template-columns: minmax(96px, 148px) 1fr 58px;
  align-items: center;
  gap: 10px;
  font-size: .82rem;
  margin-bottom: 3px;
}
.groupBarLabel { color: var(--muted); }
.groupBar.isStrong .groupBarLabel { color: #cfe9ee; }
.groupBar .barTrack { margin-top: 0; height: 14px; }
.groupBar .barValue { padding-top: 0; }
.groupBar.isStrong .barValue { color: var(--ink); }

.donut { display: flex; align-items: center; gap: 26px; flex-wrap: wrap; }
.donutRing {
  width: 168px;
  height: 168px;
  border-radius: 50%;
  /* set from the data in app.js */
  background: conic-gradient(var(--accent) 0 var(--pct), rgba(255, 255, 255, .07) 0);
  display: grid;
  place-items: center;
}
.donutHole {
  width: 112px; height: 112px; border-radius: 50%;
  background: #05161d;
  display: grid; place-items: center; text-align: center;
}
.donutHole b { display: block; font-size: 1.7rem; letter-spacing: -.5px; }
.donutHole span { font-size: .72rem; color: var(--muted); }

.lorenz svg { width: 100%; height: auto; display: block; }
.lorenz .axis { stroke: rgba(255, 255, 255, .2); stroke-width: 1; }
.lorenz .line { fill: none; stroke: var(--accent-soft); stroke-width: 2; }
.lorenz .area { fill: rgba(8, 145, 178, .18); }
.lorenz text { fill: var(--muted); font-size: 11px; }

/* ---- a room is a sequence of figures, not one ---- */
.sub {
  margin: 34px 0 0;
  padding-top: 26px;
  border-top: 1px solid var(--hairline);
}
.sub h3 {
  margin: 0 0 8px;
  font-size: 1.06rem;
  letter-spacing: -.2px;
  line-height: 1.3;
}
.sub .figure { margin-top: 16px; }

/* ---- a scatter: does size explain the rate? ---- */
.scatter svg,
.monthly svg,
.curve svg { width: 100%; height: auto; display: block; }

.scatter .axis,
.curve .axis,
.monthly .axis { stroke: rgba(255, 255, 255, .2); stroke-width: 1; }
.scatter .mean,
.curve .mean {
  stroke: rgba(255, 255, 255, .34);
  stroke-width: 1;
  stroke-dasharray: 5 5;
}
.scatter text,
.curve text,
.monthly text { fill: var(--muted); font-size: 11px; }
.scatter circle { fill: var(--accent-soft); }
.scatter .ptLabel { fill: #dff7fb; font-size: 10.5px; }
.scatter .grid { stroke: rgba(255, 255, 255, .08); stroke-width: 1; }
.scatter .axisName { fill: #cfe9ee; font-size: 11px; }
.scatter .leader {
  stroke: rgba(34, 211, 238, .45);
  stroke-width: 1;
}

/* ---- the monthly line: two series, and a flat line is the finding ---- */
.monthly .grid { stroke: rgba(255, 255, 255, .08); stroke-width: 1; }
.monthly .lineA { fill: none; stroke: var(--accent-soft); stroke-width: 2; }
.monthly .lineB { fill: none; stroke: #f59e0b; stroke-width: 2; }
.monthly circle.lineA { fill: var(--accent-soft); }
.monthly circle.lineB { fill: #f59e0b; }

/* ---- a cumulative curve ---- */
.curve .area { fill: rgba(8, 145, 178, .18); }
.curve .line { fill: none; stroke: var(--accent-soft); stroke-width: 2; }
.curve circle { fill: var(--accent-soft); }
.curve + .method { margin-top: 10px; padding-top: 0; border-top: none; font-size: .82rem; }

/* ---- two halves of one fact, in two stacked bars ---- */
.stackRow {
  display: grid;
  grid-template-columns: minmax(84px, 132px) 1fr auto;
  align-items: center;
  gap: 10px;
  font-size: .86rem;
}
.stackRow + .stackRow { margin-top: 10px; }
.stackLabel { color: #cfe9ee; }
.stackTrack {
  display: flex;
  height: 20px;
  border-radius: 5px;
  overflow: hidden;
  background: rgba(255, 255, 255, .05);
}
.stackA,
.stackB {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: .68rem;
  white-space: nowrap;
}
.stackA { background: var(--accent-soft); color: #04141a; }
.stackB { background: rgba(34, 211, 238, .26); color: #dff7fb; }

/* every figure has a table behind it: the page is readable with no JavaScript,
   and a reader who wants the numbers can copy them. */
/* THE NUMBERS, FOLDED AWAY.
   A fallback table is what a reader gets when the DRAWING did not happen. It was
   instead sitting beside every drawing as well, twelve times over, so each room
   read as a wall of numbers with the picture somewhere above it -- which is what
   made the forward-sortation-area room look like it had no graphics at all. The
   table is now folded behind a toggle: still in the DOM, still readable and still
   printable, but not competing with the chart it backs up. */
.numbers { margin-top: 14px; }
.numbers > summary {
  cursor: pointer;
  color: var(--muted);
  font-size: .84rem;
  padding: 6px 0;
  list-style: none;
}
.numbers > summary::-webkit-details-marker { display: none; }
.numbers > summary::before { content: "\203A"; display: inline-block; margin-right: 7px; transition: transform .15s; }
.numbers[open] > summary::before { transform: rotate(90deg); }
.numbers > summary:hover { color: var(--ink); }
.numbers .fallback { margin-top: 4px; }

.fallback {
  width: 100%;
  border-collapse: collapse;
  margin-top: 18px;
  font-size: .84rem;
}
.fallback caption { text-align: left; color: var(--muted); padding-bottom: 8px; }
.fallback th, .fallback td {
  text-align: left;
  padding: 5px 8px;
  border-bottom: 1px solid rgba(255, 255, 255, .06);
}
.fallback td:last-child, .fallback th:last-child { text-align: right; font-variant-numeric: tabular-nums; }
.fallback.open td:first-child { color: var(--muted); width: 34%; }

.policy ul { padding-left: 20px; }
.policy li { margin: 0 0 9px; }

a { color: var(--accent-soft); }

/* ---- part 4 · the footer ---- */
.site-footer {
  position: relative;
  z-index: 2;
  max-width: 960px;
  margin: 0 auto;
  padding: 26px 20px 34px;
  border-top: 1px solid var(--hairline);
  color: var(--muted);
  font-size: .88rem;
}

.footer-brand { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.footer-brand b { color: var(--ink); font-weight: 650; }
.footer-links { margin: 0 0 10px; }
.footer-copy { margin: 0; font-size: .82rem; }

.linkish {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: var(--accent-soft);
  cursor: pointer;
  text-decoration: underline;
}

/* ---- part 2 · the consent bar. Accept all and Reject all are equal: same
   class, same size, same weight, same distance, no ring on either. ---- */
.consent {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 20;
  background: rgba(3, 14, 19, .97);
  border-top: 1px solid var(--hairline);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  padding: 16px 20px;
  max-height: 78vh;
  overflow: auto;
}

.consentAsk, .consentPrefs { max-width: 960px; margin: 0 auto; }
.consentTitle { font-size: 1rem; margin: 0 0 6px; }
.consentText { margin: 0 0 14px; color: #cfe9ee; font-size: .9rem; }
.consentButtons { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }

.btn {
  font: inherit;
  font-size: .88rem;
  padding: 9px 16px;
  border-radius: 8px;
  border: 1px solid var(--hairline);
  background: rgba(255, 255, 255, .05);
  color: var(--ink);
  cursor: pointer;
}
.btn.primary { background: var(--accent); border-color: var(--accent); color: #032028; font-weight: 650; }

.consentHead { display: flex; align-items: center; justify-content: space-between; }
.consentClose {
  background: none; border: 0; color: var(--muted); font-size: 1.4rem;
  line-height: 1; cursor: pointer;
}
.consentList { list-style: none; margin: 8px 0 14px; padding: 0; }
.consentRow {
  display: flex; gap: 14px; align-items: center; justify-content: space-between;
  padding: 12px 0; border-top: 1px solid rgba(255, 255, 255, .06);
}
.consentRowName { margin: 0; font-weight: 600; font-size: .9rem; }
.consentRowWhy { margin: 3px 0 0; color: var(--muted); font-size: .8rem; max-width: 62ch; }
.switch {
  font: inherit; font-size: .8rem; min-width: 62px;
  padding: 7px 12px; border-radius: 999px;
  border: 1px solid var(--hairline);
  background: rgba(255, 255, 255, .06);
  color: var(--ink); cursor: pointer;
}
.switch[aria-checked="true"] { background: var(--accent); border-color: var(--accent); color: #032028; }
.consentFoot { margin: 0; }

@media (max-width: 620px) {
  .barRow { grid-template-columns: minmax(84px, 150px) 1fr auto; font-size: .8rem; }
  .donut { gap: 18px; }
}

/* ---- the standout, at the top of the page -------------------------------
   This is the one panel that is allowed to shout. It sits above every room and
   carries the comparison the rest of the page unpacks, so it gets its own card,
   an accent edge, and the largest body type on the page. Everything else here is
   a chart; this is the reason to read one. */
.standout {
  position: relative;
  margin: 0 0 34px;
  padding: 26px 28px 22px 30px;
  border: 1px solid var(--hairline);
  border-left: 5px solid var(--accent);
  border-radius: 14px;
  /* THE SAME DARK CARD AS EVERY ROOM, with the accent only as light: a tint of it
     bleeding in from the left edge and a faint glow behind the whole panel. The
     first version used --accent-soft as the FILL and produced a saturated cyan slab
     with muted text on top of it -- the definition and every bar note were
     unreadable. On a dark page an accent is an EDGE, never a surface. */
  background:
    linear-gradient(90deg, rgba(8, 145, 178, .16), rgba(8, 145, 178, 0) 62%),
    var(--card);
  box-shadow: 0 0 0 1px rgba(34, 211, 238, .06), 0 18px 46px -30px rgba(34, 211, 238, .5);
}
.standout[hidden] { display: none; }
.standoutTag {
  margin: 0 0 10px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--accent-soft);
}
.standout h2 {
  margin: 0 0 16px;
  font-size: clamp(24px, 3.1vw, 36px);
  line-height: 1.18;
  letter-spacing: -.015em;
  max-width: 30ch;
}
.standoutDef,
.standoutBody {
  margin: 0 0 14px;
  max-width: 74ch;
  font-size: 16.5px;
  line-height: 1.62;
}
/* The definition is the quiet half of the panel; the body is the argument. */
.standoutDef { color: var(--muted); }
.standoutBody { font-size: 17px; }
.standoutBars {
  margin: 22px 0 6px;
  padding-top: 20px;
  border-top: 1px solid var(--hairline);
}
/* Do NOT restyle the bars. .barRow already lays out label | track | note as a
   three-column grid; overriding the label column collapsed it and pushed every
   note into a cramped third column where it was cut off. This panel borrows the
   shared bar idiom rather than inventing a second one. */
.standoutJump {
  margin: 18px 0 0;
  font-weight: 600;
}

@media (max-width: 700px) {
  .standout { padding: 20px 18px 18px 20px; }
  .standoutDef, .standoutBody { font-size: 15.5px; }
}
