@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=Public+Sans:wght@400;600;700&display=swap');

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
}

/* ── Design tokens ─────────────────────────────────────────────────────────── */

:root {
  /* Core palette — names kept for backward-compat with JS inline-style refs */
  --bg:     #242b3d;
  --border: #1c2030;
  --text:   #e2e5f0;
  /* Contrast floor: must clear 4.5:1 on --bg, --surface AND --surface-raised,
     since muted labels sit on all three. #929292 previously failed on the
     latter two (4.04 / 3.53). */
  --muted:  #a8acba;
  --accent: #ffffff;

  /* Surface hierarchy */
  --surface:        #2d3345;
  --surface-raised: #353c50;
  --surface-hover:  rgba(255,255,255,0.03);
  --surface-active: rgba(255,255,255,0.06);

  /* Border scale — three steps only: hairline (within a card), card (its
     outer edge), strong (emphasis). Kept parallel across both themes. */
  --border-hairline:      rgba(255,255,255,0.06);
  --border-card:          rgba(255,255,255,0.12);
  --border-strong:        rgba(255,255,255,0.20);
  --border-control:       #444b5e;
  --border-control-hover: #6a7090;

  /* Status */
  --color-up:      hsl(49, 84%, 63%);
  --color-down:    hsl(148, 60%, 50%);
  --color-surplus: hsl(148, 58%, 52%);
  --color-error:   hsl(0, 70%, 60%);

  /* Police tab change column only (see .pol-table-wrap override below) - an
     off-white/greenish-gray for a rising figure, muted slate-gray for a
     falling one, in place of the site's default amber/green. >10:1 / ~5.8:1
     against --bg, --surface and --surface-raised. */
  --pol-change-up:   hsl(215, 20%, 90%);
  --pol-change-down: hsl(215, 12%, 65%);

  /* Component-specific */
  --bar-track:        rgba(255,255,255,0.07);
  --tt-underline:     rgba(255,255,255,0.25);

  /* Shadows */
  --shadow-header: 0 4px 20px rgba(0,0,0,0.45);
  --shadow-tabbar: 0 4px 12px rgba(0,0,0,0.35);

  /* Layout — header-height overwritten by JS after measurement */
  --header-height: 60px;
  --tabbar-height: 0px;

  /* Labels — one size/tracking pair for every small label on the site.
     See "Label roles" below for when uppercase applies. */
  --label-size:     0.80rem;
  --label-tracking: 0.08em;
}

/* ── Label roles ────────────────────────────────────────────────────────────
   Two roles, no more:

   SECTION - uppercase, 600. Heads a block of content (section titles, table
             column heads, group dividers, reconciliation steps).
   INLINE  - sentence case, 400. Annotates a value sitting next to it.

   Uppercase is deliberately reserved for the section role. A label beside a
   large figure is an annotation, not a heading, and setting it in tracked
   caps makes it compete with the number it is supposed to be describing.
   Both roles share --label-size / --label-tracking; if a new label needs a
   third size, the answer is almost always that it belongs to one of these. */

:root.theme-light {
  --bg:     #f8f9ff;
  --border: #c3c6cf;
  --text:   #0b1c30;
  --muted:  #43474e;
  --accent: #254870;

  --surface:        #ffffff;
  --surface-raised: #eff4ff;
  --surface-hover:  rgba(0,0,0,0.03);
  --surface-active: rgba(0,0,0,0.06);

  --border-hairline:      rgba(0,0,0,0.08);
  --border-card:          rgba(0,0,0,0.16);
  --border-strong:        rgba(0,0,0,0.28);
  --border-control:       #73777f;
  --border-control-hover: #43474e;

  --color-up:      hsl(38, 75%, 30%);
  --color-down:    hsl(148, 55%, 28%);
  --color-surplus: hsl(148, 55%, 28%);
  --color-error:   hsl(0, 65%, 38%);

  --pol-change-up:   hsl(215, 28%, 25%);
  --pol-change-down: hsl(215, 10%, 45%);

  --bar-track:        rgba(0,0,0,0.07);
  --tt-underline:     rgba(0,0,0,0.28);

  --shadow-header: 0 1px 3px rgba(0,0,0,0.08), 0 2px 12px rgba(0,0,0,0.06);
  --shadow-tabbar: 0 1px 4px rgba(0,0,0,0.05), 0 2px 8px rgba(0,0,0,0.04);
}

/* ── Focus visibility ─────────────────────────────────────────────────────── */

.theme-toggle:focus-visible,
.source-link:focus-visible,
.sel:focus-visible,
.view-btn:focus-visible,
.mob-cmp-sel:focus-visible,
.mob-bar-row:focus-visible,
.pol-row-expand:focus-visible,
.pol-section-head:focus-visible,
[data-tt]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ── Base ──────────────────────────────────────────────────────────────────── */

body {
  background: var(--bg);
  color: var(--text);
  font-family: 'Inter', sans-serif;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
}

@media (min-width: 641px) {
  body { zoom: 1.2; }
}

/* ── Header / nav bar (combined) ────────────────────────────────────────── */

.header-brand {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  min-width: 0;
}
.site-icon-link {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 8px;
  flex-shrink: 0;
  outline: none;
  transition: background 0.12s;
}
.site-icon-link:hover,
.site-icon-link:focus-visible { background: var(--surface-hover); }
.site-icon-mark { width: 18px; height: 18px; display: block; }
.header-brand h1 {
  font-family: 'Public Sans', 'Inter', sans-serif;
  font-size: 1.05rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--text);
  white-space: nowrap;
}
.header-subtitle {
  font-family: 'Inter', sans-serif;
  font-size: 0.75rem;
  color: var(--muted);
  white-space: nowrap;
  letter-spacing: 0.01em;
}
.tab-bar-right {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  justify-self: end;
  flex-shrink: 0;
}
.theme-toggle {
  width: 34px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  border: 1px solid var(--border-control);
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  outline: none;
  transition: border-color 0.12s, color 0.12s, background 0.12s;
  flex-shrink: 0;
}
.theme-toggle:hover {
  border-color: var(--border-control-hover);
  color: var(--text);
  background: var(--surface-hover);
}
.source-link {
  height: 28px;
  display: flex;
  align-items: center;
  padding: 0 0.625rem;
  border-radius: 8px;
  border: 1px solid var(--border-control);
  background: transparent;
  color: var(--muted);
  font-size: 0.75rem;
  font-family: 'Inter', sans-serif;
  letter-spacing: 0.01em;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
  flex-shrink: 0;
  transition: border-color 0.12s, color 0.12s, background 0.12s;
}
.source-link:hover {
  border-color: var(--border-control-hover);
  color: var(--text);
  background: var(--surface-hover);
}
.icon-sun  { display: block; }
.icon-moon { display: none; }
:root.theme-light .icon-sun  { display: none; }
:root.theme-light .icon-moon { display: block; }

/* ── Year select ─────────────────────────────────────────────────────────── */

.sel {
  font-family: 'Inter', sans-serif;
  font-size: 0.8rem;
  letter-spacing: 0.05em;
  padding: 0.3rem;
  line-height: 1.2;
  border-radius: 8px;
  border: 1px solid var(--border-control);
  background: var(--bg);
  color: var(--text);
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  outline: none;
  transition: border-color 0.12s;
}
.sel:hover { border-color: var(--border-control-hover); }
.sel:focus  { border-color: var(--accent); }
#year-select { min-width: 88px; text-align: center; }

/* ── Council select (brand area) ─────────────────────────────────────────── */

.sel--council {
  font-family: 'Public Sans', 'Inter', sans-serif;
  font-size: 1.05rem;
  font-weight: 700;
  letter-spacing: 0;
  padding: 0 4px;
  border-color: transparent;
  background: transparent;
  background-image: none;
  min-width: 0;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sel--council:not(:disabled) {
  padding-right: 20px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='5' viewBox='0 0 8 5'%3E%3Cpath d='M0 0l4 5 4-5z' fill='%23888'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 4px center;
}
.sel--council:not(:disabled):hover { border-color: var(--border-control-hover); }
.sel--council:disabled { opacity: 1; cursor: default; }

.council-combo { position: relative; min-width: 0; }
.council-combo-btn {
  display: flex;
  align-items: center;
  text-align: left;
}
.council-combo-btn span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.council-combo-panel {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  z-index: 200;
  width: 240px;
  max-width: calc(100vw - 32px);
  background: var(--surface-raised);
  border: 1px solid var(--border-control);
  border-radius: 8px;
  box-shadow: var(--shadow-header);
  padding: 8px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.council-combo-panel.hidden { display: none; }

.council-combo-search {
  font-family: 'Inter', sans-serif;
  font-size: 0.8rem;
  padding: 6px 8px;
  border-radius: 8px;
  border: 1px solid var(--border-control);
  background: var(--bg);
  color: var(--text);
  outline: none;
}
.council-combo-search:focus { border-color: var(--accent); }

.council-combo-list {
  list-style: none;
  max-height: 240px;
  overflow-y: auto;
}
.council-combo-option {
  padding: 0;
  border-radius: 8px;
  font-family: 'Inter', sans-serif;
  font-size: 0.8rem;
  color: var(--text);
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* The option's own text now lives in a real <a> (see ui.js) so a crawler can
   follow it - block + inherited color/no-underline makes it fill the same
   footprint the <li> used to own directly, so this is a no-op visually. */
.council-combo-option a {
  display: block;
  padding: 8px;
  color: inherit;
  text-decoration: none;
  white-space: inherit;
  overflow: inherit;
  text-overflow: inherit;
}
.council-combo-option.is-highlighted { background: var(--surface-hover); }
.council-combo-option.is-current { font-weight: 700; }
.council-combo-empty {
  padding: 8px;
  font-family: 'Inter', sans-serif;
  font-size: 0.8rem;
  color: var(--muted);
}

/* ── Tab bar ─────────────────────────────────────────────────────────────── */

.tab-bar {
  position: sticky;
  top: 0;
  z-index: 60;
  background: var(--bg);
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  padding: 0 1.5rem;
  border-bottom: 1px solid var(--border);
  box-shadow: var(--shadow-header);
  flex-shrink: 0;
}
.tab-btns { display: flex; }
.view-toggle-wrap { justify-self: end; }
.tab-btn {
  font-family: 'Inter', sans-serif;
  font-size: 0.78rem;
  font-weight: 500;
  padding: 0.75rem 1rem;
  border: none;
  border-bottom: 2px solid transparent;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  letter-spacing: 0.02em;
  transition: color 0.12s, border-color 0.12s;
  margin-bottom: -1px;
  white-space: nowrap;
}
.tab-btn:hover  { color: var(--text); }
.tab-btn.active { color: var(--text); border-bottom-color: var(--accent); }

/* ── View container ──────────────────────────────────────────────────────── */

#view {
  flex: 1;
  display: flex;
  flex-direction: column;
  position: relative;
}

/* ── Tab panels ──────────────────────────────────────────────────────────── */

.tab-panel {
  display: none;
  flex-direction: column;
  min-height: calc(100dvh - var(--header-height) - var(--tabbar-height));
}
.tab-panel.active { display: flex; }
.tab-placeholder {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.75rem;
  color: var(--muted);
}
.mob-card-placeholder {
  min-height: 120px;
  align-items: center;
  justify-content: center;
}
.mob-card-placeholder .tab-placeholder { flex: none; }

/* ── List view container ─────────────────────────────────────────────────── */

#list-view {
  flex: 1;
  position: relative;
}
#income-view {
  flex: 1;
  position: relative;
}

/* ── Tooltip — always dark for contrast in both modes ───────────────────── */

#tooltip {
  position: fixed;
  background: #21273a;
  border: 1px solid #2a3045;
  color: #dde3f0;
  padding: 0.75rem 1rem;
  border-radius: 4px;
  font-size: 0.72rem;
  pointer-events: none;
  z-index: 999;
  display: none;
  max-width: 260px;
  box-shadow: 0 4px 24px rgba(0,0,0,0.65);
  line-height: 1.45;
}
#tooltip strong { display: block; font-weight: 700; margin-bottom: 4px; font-size: 0.78rem; color: #e2e5f0; }
.tt-val     { font-family: 'Inter', sans-serif; color: #dde3f0; }
.tt-sub     { display: block; color: #8892aa; font-family: 'Inter', sans-serif; font-size: 0.63rem; margin-top: 4px; }
.tt-explain { font-style: italic; border-top: 1px solid rgba(255,255,255,0.10); margin-top: 8px; padding-top: 4px; max-width: 200px; white-space: normal; line-height: 1.4; }

/* ── Status overlay ──────────────────────────────────────────────────────── */

#status-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg);
  z-index: 50;
  font-family: 'Inter', sans-serif;
  font-size: 0.75rem;
  color: var(--muted);
  flex-direction: column;
  gap: 10px;
}
#status-overlay.hidden { display: none; }
.status-error { color: var(--color-error); }

/* ── View toggle ─────────────────────────────────────────────────────────── */

.view-toggle-wrap { display: flex; gap: 4px; justify-self: end; align-self: end; padding-bottom: 0.5rem; }
.view-btn {
  font-family: 'Inter', sans-serif;
  font-size: 0.72rem;
  letter-spacing: 0.05em;
  padding: 8px 12px;
  border-radius: 8px;
  border: 1px solid var(--border-control);
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  outline: none;
  transition: border-color 0.12s, color 0.12s;
}
.view-btn:hover  { border-color: var(--border-control-hover); color: var(--text); }
.view-btn.active { border-color: var(--accent); color: var(--accent); }

/* ── Council Tax tab ─────────────────────────────────────────────────────── */

#tab-council-tax.active { display: block; }

/* ── Council Tax redesigned layout (ct2-*) ───────────────────────────────── */

.ct2-wrap {
  max-width: 860px;
  margin: 0 auto;
  padding: 1.5rem 1.75rem;
  display: flex;
  flex-direction: column;
  gap: 1.75rem;
}
.ct2-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 3rem;
  color: var(--muted);
  font-size: 1rem;
}

/* Hero card. There was a .ct2-hero-split grid holding this card plus a
   .ct2-support-stack column beside it (Net Budget Requirement, then Council Tax
   Requirement). Both of those are gone: NBR was dropped, and the Council Tax
   Requirement moved into this card's top-right corner - it is the same bill
   borough-wide rather than per household, so a separate card left it stranded in
   a mostly empty column. */
.ct2-hero-card {
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: 12px;
  padding: 1.25rem 1.5rem;
  min-width: 0;
}
.ct2-hero-val {
  font-size: 2.2rem;
  font-weight: 700;
  letter-spacing: -0.03em;
  color: var(--text);
}

/* Band D figure left, Council Tax Requirement top-right */
.ct2-hero-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 24px;
}
.ct2-hero-main { min-width: 0; }

/* The aside keeps a border, unlike the nested .ct2-cards-sub rows below, which
   drop theirs. Those are components of the same bill, so a hairline between them
   is enough. This is a different kind of figure - the whole borough's
   requirement, not a slice of one household's bill - and its value would
   otherwise sit in the same right-hand column as the per-household amounts,
   reading as one more row of the same list. --surface-raised puts it at a
   different elevation, which is what stops a box inside a box looking like
   scaffolding. */
.ct2-hero-aside {
  text-align: right;
  flex-shrink: 0;
  background: var(--surface-raised);
  border: 1px solid var(--border-card);
  border-radius: 8px;
  padding: 12px 16px;
}
.ct2-hero-aside .ct2-card-lbl { margin-bottom: 4px; }
.ct2-hero-main[data-tt],
.ct2-hero-aside[data-tt] { cursor: help; }

/* Cards */
.ct2-card {
  background: var(--surface);
  border: 1px solid var(--border-card);
  border-radius: 12px;
  padding: 1rem 1.25rem;
  min-width: 0;
}
.ct2-card[data-tt] { cursor: help; }
/* Label role: INLINE — sentence case; the figure beside it carries the weight */
.ct2-card-lbl {
  font-size: var(--label-size);
  color: var(--muted);
  letter-spacing: 0;
  margin-bottom: 0.5rem;
}
.ct2-card-val {
  font-size: 1.2rem;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--text);
}
.ct2-note-mark {
  font-size: 0.6em;
  font-weight: 400;
  vertical-align: super;
  margin-left: 0.15em;
  opacity: 0.55;
}
.ct2-card-sub { font-size: 0.73rem; margin-top: 4px; color: var(--muted); }
.ct2-lbl-full  { display: none; }
.ct2-lbl-short { display: inline; }
@media (min-width: 721px) {
  .ct2-lbl-full  { display: inline; }
  .ct2-lbl-short { display: none; }
}
.ct2-breakdown-wrap {
  display: flex;
  flex-direction: column;
  gap: 0.625rem;
  margin-top: 1.25rem;
}
.ct2-cards-sub {
  display: flex;
  flex-direction: column;
}
/* Nested inside .ct2-hero-card, so these drop their own border/radius/fill —
   boxes inside boxes at the same elevation read as generated scaffolding.
   A hairline rule between rows does the same structural work more quietly. */
.ct2-cards-sub .ct2-card {
  display: grid;
  grid-template-columns: 1fr auto;
  grid-template-rows: auto auto;
  align-items: center;
  column-gap: 0.75rem;
  padding: 0.75rem 0;
  background: none;
  border: none;
  border-radius: 0;
  border-top: 1px solid var(--border-hairline);
}
.ct2-cards-sub .ct2-card:first-child { border-top: none; }
.ct2-cards-sub .ct2-card-lbl {
  grid-column: 1;
  grid-row: 1 / 3;
  margin-bottom: 0;
  align-self: center;
}
.ct2-cards-sub .ct2-card-val {
  grid-column: 2;
  grid-row: 1;
  font-size: 1.05rem;
  text-align: right;
}
.ct2-cards-sub .ct2-card-sub {
  grid-column: 2;
  grid-row: 2;
  margin-top: 0;
  text-align: right;
}
.ct2-card-solo {
  display: inline-block;
  background: var(--surface);
  border: 1px solid var(--border-card);
  border-radius: 12px;
  padding: 1rem 1.25rem;
}

/* Section wrapper */
.ct2-section {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  background: var(--surface);
  border: 1px solid var(--border-card);
  border-radius: 12px;
  padding: 1.25rem 1.5rem;
}
/* Label role: SECTION */
.ct2-h3 {
  font-family: 'Public Sans', 'Inter', sans-serif;
  font-size: var(--label-size);
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: var(--label-tracking);
  margin: 0;
}

/* Collapsible sections (band table, waterfall) */
.ct2-section.ct2-details { display: block; padding: 0; gap: 0; }
.ct2-details-toggle {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 1.25rem 1.5rem;
  border: none;
  background: none;
  color: var(--text);
  font-family: inherit;
  cursor: pointer;
  text-align: left;
}
.ct2-details-toggle .ct2-h3 { margin: 0; }
.ct2-details-toggle .ct2-explain-icon { font-size: 0.7rem; color: var(--muted); transition: transform 0.15s; flex-shrink: 0; }
.ct2-details-toggle[aria-expanded="true"] .ct2-explain-icon { transform: rotate(180deg); }
.ct2-details-body {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  padding: 0 1.5rem 1.25rem;
}
.ct2-details-body[hidden] { display: none; }

/* Band table */
.ct2-table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.ct2-table { width: 100%; border-collapse: collapse; font-size: 0.84rem; }
/* Label role: SECTION */
.ct2-table thead th {
  font-size: var(--label-size);
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: var(--label-tracking);
  padding: 0.5rem 1rem;
  text-align: right;
  border-bottom: 1px solid var(--border-strong);
  white-space: nowrap;
  cursor: default;
}
/* Every tooltip-bearing header gets the same dotted underline the waterfall
   labels use, instead of an info circle on an arbitrary three of them. One
   affordance, applied consistently, and quieter than three more icons. */
.ct2-table thead th[data-tt] {
  cursor: help;
  text-decoration: underline;
  text-decoration-style: dotted;
  text-underline-offset: 4px;
  text-decoration-color: var(--tt-underline);
}
.ct2-table thead th:first-child { text-align: left; }
.ct2-table tbody td {
  padding: 0.5rem 1rem;
  text-align: right;
  color: var(--text);
  border-bottom: 1px solid var(--border-hairline);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.ct2-table tbody td:first-child { text-align: left; }
/* These tables use <th scope="row"> for the label, so the td:first-child rule
   above does not reach it and the label falls through to the browser's default
   th centring. Every .ct2-table row label is a left-aligned name, so this is
   the correct default rather than a police-only fix. */
.ct2-table tbody th[scope="row"] { text-align: left; font-weight: inherit; }
.ct2-table tbody tr:hover td { background: var(--surface-hover); }
.ct2-band-d td { background: var(--surface-active); font-weight: 600; }
.ct2-muted   { color: var(--muted) !important; }
.ct2-col-sep { border-left: 1px solid var(--border-strong); }

/* A council with more than one special area (Westminster has two) pushes the
   band table past seven columns, which overflowed its own container even on a
   desktop viewport - the wrapper scrolls, so nothing was lost, but a table
   clipped mid-column reads as broken rather than scrollable. Tightening the
   horizontal padding buys back ~56px and is invisible at the narrower counts.
   Applied by council-tax.js when the table has more than 6 columns. */
.ct2-table--compact thead th,
.ct2-table--compact tbody td { padding-left: 0.75rem; padding-right: 0.75rem; }

.ct2-area-link {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  color: var(--muted);
  text-decoration: none;
  opacity: 0.6;
  transition: opacity 0.15s, color 0.15s;
  flex-shrink: 0;
}
.ct2-area-link:hover { opacity: 1; color: var(--text); }
/* .ct2-info-icon removed: every card and table header that carried one is
   itself the tooltip target, so the icon duplicated an affordance already
   signalled by cursor:help (cards) or a dotted underline (headers). The
   remaining icon is .gloss-info-icon, which marks one term inside a longer
   line of text - the case where a target marker genuinely earns its place. */
.ct2-note { font-size: 0.75rem; color: var(--muted); margin: 0; }
.ct2-explainer { font-size: 0.75rem; font-weight: 400; color: var(--muted); line-height: 1.4; margin: 0; }
.ct2-explainer + .ct2-explainer { margin-top: 8px; }
.ct2-explainer-lead {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--text);
  line-height: 1.45;
}
.ct2-explainer-lead + .ct2-explainer { margin-top: 8px; }

/* ── Plain-English landing callout (all tabs) ────────────────────────────── */

/* Normal weight, not 600: these run to several lines on the Reserves and
   Council Tax tabs, and bold body copy at that length reads as shouting
   rather than emphasis - and made the callout heavier than the data below it. */
.plain-summary {
  font-size: 0.9rem;
  font-weight: 400;
  line-height: 1.5;
  color: var(--text);
  background: var(--surface-raised);
  border: 1px solid var(--border-card);
  border-radius: 8px;
  padding: 12px 16px;
}

/* ── Glossary inline tooltips (jargon terms, badges) ─────────────────────── */

.gloss-term {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  cursor: help;
}
.gloss-info-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 1px solid currentColor;
  font-size: 9px;
  font-weight: 600;
  font-family: 'Inter', sans-serif;
  line-height: 1;
  opacity: 0.7;
  flex-shrink: 0;
}

/* ── Reporting-change warning banner (Council Tax tab) ────────────────────── */

.ct2-warning {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 12px 16px;
  margin-bottom: 16px;
  border: 1px solid hsl(4, 70%, 45%);
  border-radius: 8px;
  background: hsl(4, 70%, 45%, 0.12);
  color: hsl(4, 75%, 35%);
  font-size: 0.85rem;
  font-weight: 600;
  line-height: 1.5;
}
:root:not(.theme-light) .ct2-warning {
  border-color: hsl(4, 80%, 60%);
  background: hsl(4, 70%, 45%, 0.18);
  color: hsl(4, 90%, 78%);
}
.ct2-warning-icon { font-size: 1.1rem; flex-shrink: 0; line-height: 1.4; }

/* ── Data notes (reusable, any tab — see js/data-notes.js) ───────────────── */

/* Deliberately quieter than .ct2-warning, which is a red alert for a genuine
   reporting-change artefact on one tab. These sit under the plain-English
   summary on any tab and say what the source does not publish, or what will be
   misread without context. They have to be noticeable enough that nobody
   mistakes a thin tab for a broken one, and quiet enough to sit above real
   content on every visit without becoming noise. */
.data-note-stack { display: flex; flex-direction: column; gap: 8px; }
.data-note {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 12px 16px;
  border-radius: 8px;
  border: 1px solid var(--border-card);
  background: var(--surface-raised);
  font-size: 0.85rem;
  line-height: 1.5;
}
.data-note-icon { font-size: 1rem; flex-shrink: 0; line-height: 1.5; }
.data-note-text { min-width: 0; }
/* Label role: INLINE — annotates the body beneath it, so sentence case at 600,
   not tracked caps. A heading here would compete with the tab's own headings. */
.data-note-title {
  margin: 0 0 4px;
  font-weight: 600;
  color: var(--text);
}
.data-note-body { margin: 0; color: var(--muted); }

/* Amber left edge for the "correct but easily misread" case, so a comparison
   caveat is distinguishable at a glance from a plain missing-data note without
   either shouting. Border-left only: a tinted fill on a block that appears on
   several tabs at once reads as an error state. */
.data-note--caution { border-left: 3px solid hsl(38, 80%, 50%); }
.data-note--caution .data-note-icon { color: hsl(38, 80%, 44%); }
:root:not(.theme-light) .data-note--caution .data-note-icon { color: hsl(38, 85%, 62%); }

.data-note--limitation .data-note-icon { color: var(--muted); }

/* `context` is not a defect notice - it explains a surprising but perfectly
   correct figure. A muted accent marks it as a distinct kind of note without
   borrowing the amber that means "check this before you compare". */
.data-note--context { border-left: 3px solid var(--border-strong); }
.data-note--context .data-note-icon { font-size: 0.7rem; color: var(--muted); line-height: 2.2; }

/* ── "Why did my bill change?" explainer (Council Tax tab) ───────────────── */

.ct2-explain {
  border: 1px solid var(--border-card);
  border-radius: 8px;
  background: var(--surface-hover);
  overflow: hidden;
}
.ct2-explain-toggle {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 12px 16px;
  border: none;
  background: none;
  color: var(--text);
  font-family: inherit;
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
  text-align: left;
}
.ct2-explain-icon { font-size: 0.7rem; transition: transform 0.15s; }
.ct2-explain-toggle[aria-expanded="true"] .ct2-explain-icon { transform: rotate(180deg); }
.ct2-explain-body {
  padding: 0 16px 16px;
  font-size: 0.8rem;
  color: var(--muted);
  line-height: 1.5;
}
.ct2-explain-body p { margin: 0 0 8px; }
.ct2-explain-body p:last-child { margin-bottom: 0; }

/* Change indicators */
.ct-up   { color: var(--color-up); }
.ct-dn   { color: var(--color-down); }
.ct-flat { color: var(--muted); }
.ct-na   { color: var(--muted); font-style: italic; font-size: 0.9em; }

/* ── Mobile bar list (Expenditure, Services, Income) ─────────────────────── */

.mob-list {
  padding: 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  max-width: 700px;
  margin: 0 auto;
  width: 100%;
}
.mob-bar-row { cursor: pointer; }
.mob-bar-row:active { opacity: 0.65; }
.mob-row-top { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.mob-swatch { width: 12px; height: 12px; border-radius: 4px; flex-shrink: 0; }
.mob-name { flex: 1; font-size: 0.87rem; font-weight: 500; color: var(--text); min-width: 0; }
.mob-val  { font-size: 0.8rem; color: var(--text); white-space: nowrap; font-variant-numeric: tabular-nums; }
.mob-pct  { font-size: 0.72rem; color: var(--muted); min-width: 60px; text-align: right; flex-shrink: 0; white-space: normal; line-height: 1.35; }
.mob-bar-track { height: 4px; background: var(--bar-track); border-radius: 999px; margin-left: 20px; }
.mob-bar-fill  { height: 100%; border-radius: 999px; opacity: 0.8; }
.mob-bar-income-fill { height: 100%; border-radius: 999px; opacity: 0.28; }

/* Expenditure + GLA body rows: one track carrying gross, split into net cost
   (solid) and the part grants and fees cover (dim). Built by expBarHtml() in
   helpers.js; see docs/superpowers/specs/2026-07-31-expenditure-bars-design.md.
   Taller than the 4px .mob-bar-track it overrides, which is what carrying two
   segments needs - and free, because it replaced a 4px bar plus a 4px gap plus
   a 2px underbar. The height stays on the -split modifier rather than moving to
   .mob-bar-track, which the Income, Reserves and drill-down rows all still use
   at 4px.
   Radius sits on the track and the bar, never on the segments: rounding the
   segments puts a pinch at the joint and turns a floored 0.8% net segment into
   a dot. overflow:hidden keeps the joint square while the bar's outer ends
   stay rounded. */
.mob-bar-track-split { height: 10px; border-radius: 3px; }
.mob-bar-split-bar   { display: flex; height: 100%; border-radius: 3px; overflow: hidden; }
.mob-bar-split-net   { height: 100%; opacity: 0.8; }
.mob-bar-split-fees  { height: 100%; opacity: 0.45; flex: 1; }

/* Key for the split bar, built by barKeyHtml() in helpers.js. Indented 20px to
   sit under the bars rather than the labels, and wraps to two lines on a narrow
   phone rather than being shortened - the whole point of it is that the wording
   matches the sub-line printed on every row.
   The swatches take their 3px radius from the segments above, not from the 4px
   scale: they are a picture of that bar, and a reader who cannot match them to
   it learns nothing. Neutral --text on purpose, since the hue on a real bar
   means "which service" and nothing here should. */
.mob-bar-key {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 16px;
  margin: 0 0 12px 20px;
  font-size: 0.68rem;
  color: var(--muted);
  line-height: 1.35;
}
.mob-bar-key-item   { display: inline-flex; align-items: center; gap: 8px; }
.mob-bar-key-swatch {
  width: 16px;
  height: 8px;
  border-radius: 3px;
  background: var(--text);
  flex-shrink: 0;
}
/* The dim swatch is 0.55, NOT the bar's 0.45. On a neutral it is the pairing
   that has to read, not the exact value, and 0.45 measured 2.88:1 against the
   light-theme card - under the 3:1 that non-text UI needs. 0.55 gives 4.21:1
   dark and 3.90:1 light while staying plainly the faded one of the two. The
   bar's own segment cannot be fixed this way and is not: it carries a service
   hue, and no opacity lifts those to 3:1 (see the note above .mob-bar-track-split
   and the bars design spec). The difference is that this swatch is neutral, so
   here it costs nothing to clear the threshold. */
.mob-bar-key-net    { opacity: 0.8; }
.mob-bar-key-fees   { opacity: 0.55; }
.mob-income-sub {
  font-size: 0.68rem;
  color: var(--muted);
  margin-left: 20px;
  margin-top: 4px;
  margin-bottom: 4px;
  line-height: 1.35;
}
.mob-income-sub-earn { color: var(--color-surplus); }
.mob-sub-total  { font-size: 0.72rem; color: var(--muted); margin-top: -4px; }
.mob-explainer  { font-size: 0.75rem; color: var(--muted); line-height: 1.4; }
.mob-surplus-val {
  font-size: 0.8rem;
  color: var(--color-surplus);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
/* No badge here by design. A tinted uppercase pill would be the fourth signal
   for a fact the row already carries three ways: the value is green, it is
   prefixed "+", and the line beneath spells out the surplus. The concept
   itself is explained once by the "Net earners" divider note above. */
.mob-surplus-suffix {
  font-size: 0.8rem;
  color: var(--color-surplus);
  white-space: nowrap;
}
.mob-surplus-note { font-size: 0.68rem; color: var(--muted); margin-left: 20px; margin-top: 4px; line-height: 1.4; }
.mob-na { color: var(--muted); font-style: italic; font-size: 0.85rem; padding: 8px 0; }

/* Expenditure rows: one split bar carrying gross (see .mob-bar-track-split) */
.mob-exp-row { position: relative; }
.mob-expand-icon {
  font-size: 0.8rem;
  color: var(--muted);
  flex-shrink: 0;
  width: 16px;
  height: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform 0.15s;
}
.mob-exp-row-open .mob-expand-icon { transform: rotate(45deg); }

/* Service-group drill-down panel */
.mob-detail {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: -4px 0 4px 20px;
  padding: 8px 0 0 12px;
  border-left: 1px solid var(--border-hairline);
}
.mob-detail[hidden] { display: none; }

/* Service-line drill-down (one level deeper than service groups) */
.mob-subline-detail { gap: 4px; }
.mob-subline-row { display: flex; align-items: center; gap: 8px; font-size: 0.78rem; }
.mob-subline-row .mob-swatch { width: 8px; height: 8px; }
.mob-subline-row .mob-name { color: var(--muted); font-weight: 400; }

/* Net Earners section divider */
.mob-divider { margin-top: 4px; padding-top: 12px; border-top: 1px solid var(--border-hairline); }
/* Label role: SECTION */
.mob-divider-label {
  font-family: 'Public Sans', 'Inter', sans-serif;
  font-size: var(--label-size);
  font-weight: 600;
  color: var(--text);
  text-transform: uppercase;
  letter-spacing: var(--label-tracking);
  margin-bottom: 4px;
}
.mob-divider-note { font-size: 0.72rem; color: var(--muted); line-height: 1.4; margin: 0 0 8px; }
.mob-total { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.mob-total > .mob-controls { margin-left: auto; align-self: center; }
.mob-total-val {
  font-family: 'Public Sans', 'Inter', sans-serif;
  font-size: 1.5rem;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--text);
}
/* Label role: INLINE — sentence case; the figure beside it carries the weight */
.mob-total-lbl { font-size: var(--label-size); color: var(--muted); letter-spacing: 0; }
.mob-controls { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.mob-card > .mob-controls:last-child { margin-bottom: -8px; }
.mob-cmp-sel {
  font-family: 'Inter', sans-serif;
  font-size: 0.72rem;
  padding: 8px 8px;
  border-radius: 8px;
  border: 1px solid var(--border-control);
  background: var(--bg);
  color: var(--muted);
  cursor: pointer;
  outline: none;
  margin-left: auto;
  transition: border-color 0.12s, color 0.12s;
}
.mob-cmp-sel:hover  { border-color: var(--border-control-hover); color: var(--text); }
.mob-cmp-sel.active { border-color: hsl(44,80%,56%); color: hsl(44,80%,56%); }
.mob-cmp-sel option { background: var(--surface); color: var(--text); }

/* ── Card containers for tab sections (matches Council Tax .ct2-card) ─────── */

.mob-card {
  padding: 1rem;
  border: 1px solid var(--border-card);
  border-radius: 8px;
  background: var(--surface);
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}
.mob-card-pad-b { padding-bottom: 1.5rem; }
.mob-card .mob-divider:first-child {
  margin-top: 0;
  padding-top: 0;
  border-top: none;
}

/* ── Expenditure header sum (Expenditure tab) ────────────────────────────── */
/* Lines of visible arithmetic. Values sit in their own right-aligned column so
   they line up like a sum on paper - that alignment is what makes it read as
   arithmetic rather than a stack of unrelated stats.
   The header itself is two lines (total spend, council tax share); the full
   deduction chain lives in .exp-chain below and reuses the same grid. */

.exp-sum {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: baseline;
  column-gap: 12px;
  row-gap: 4px;
}
.exp-sum-row {
  display: contents;
}
.exp-sum-val {
  font-family: 'Public Sans', 'Inter', sans-serif;
  font-size: 1.05rem;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--muted);
  text-align: right;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
/* Flex, so the running balance can be pushed to the right edge. The label text
   needs its own child (.exp-sum-lbl-txt) - as a bare flex parent this element
   would turn each word into a flex item and destroy normal text wrapping. */
.exp-sum-lbl {
  font-size: var(--label-size);
  color: var(--muted);
  line-height: 1.35;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  column-gap: 12px;
}
.exp-sum-lbl-txt { flex: 1 1 12rem; }
/* These labels wrap at narrow widths. .gloss-term is inline-flex by default,
   which strands the icon at the end of the first line instead of letting it
   follow the last word; inline makes it flow with the text. */
.exp-sum-lbl .gloss-term { display: inline; }

/* Running balance after each step of a funding chain, so nobody has to carry a
   number down four rows in their head. margin-left:auto right-aligns every one
   of them to the card edge, which forms a clean column at wide widths; the
   wrap on .exp-sum-lbl drops it onto its own line on narrow screens rather
   than crushing the label to ~130px.
   Deliberately muted and smaller than .exp-sum-val: this is an annotation on
   the arithmetic, not one of its terms. Styled to compete with the operand
   column, the chain reads as having two value columns and stops being a sum. */
.exp-sum-bal {
  margin-left: auto;
  font-size: 0.72rem;
  color: var(--muted);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
/* The result is the figure the rows below sum to, so it carries the weight */
.exp-sum-result .exp-sum-val {
  font-size: 1.5rem;
  color: var(--text);
}
.exp-sum-result .exp-sum-lbl { color: var(--text); }
.exp-sum-result .exp-sum-val,
.exp-sum-result .exp-sum-lbl {
  border-top: 1px solid var(--border-card);
  padding-top: 8px;
  margin-top: 4px;
}

/* Percentage beside the council tax share - an annotation on the label, so it
   stays muted even on the result row where the label goes full contrast. */
.exp-sum-pct { color: var(--muted); white-space: nowrap; }

/* ── Funding chain (Expenditure tab) ──────────────────────────────────────── */
/* The tab's main statement: gross cost down to council tax, all three
   deductions shown. It was briefly a collapsed disclosure under a two-line
   summary; the summary restated figures the chain already ends on, so the
   chain was promoted and the summary and toggle both went. */

.exp-chain { display: flex; flex-direction: column; gap: 16px; }

.exp-chain-detail { display: flex; flex-direction: column; gap: 4px; }
.exp-chain-item {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  font-size: 0.78rem;
}
.exp-chain-item-name { color: var(--muted); min-width: 0; }
.exp-chain-item-val {
  color: var(--text);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.exp-chain-note {
  font-size: 0.72rem;
  color: var(--muted);
  line-height: 1.5;
  margin: 0;
}

/* The itemised list under a figure, reused from the Expenditure funding chain.
   .exp-chain-detail sits inside .exp-chain there, which supplies a 16px gap;
   standing alone in a card it needs its own top margin. Grep the JS before
   deleting either class - they are now used by two tabs. */
.debt-detail { margin-top: 12px; }

/* Net-cost subtotal heading on the service list */
.mob-divider-total {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}
.mob-divider-total .mob-divider-label { margin-bottom: 0; }
.mob-divider-total-val {
  font-family: 'Public Sans', 'Inter', sans-serif;
  font-size: 1.05rem;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ── Closing card (GLA tab) ──────────────────────────────────────────────── */
/* Card shell comes from .mob-card; this is just the prose inside it. */

.gla-closing p {
  font-size: 0.85rem;
  color: var(--text);
  line-height: 1.5;
  margin: 0;
}
/* .gla-closing-note went with the closing card's second paragraph: the card now
   opens on the precept and lists the per-body split beneath, so there is no
   trailing muted note to style. */

/* ── Ring-fenced callout (Expenditure tab) ───────────────────────────────── */

/* Footnote, not a peer card: this covers spending that appears in none of the
   figures above it, and it now sits after the tab's closing handoff. A plain
   hairline rule and no fill say "aside" where a bordered card said "section". */
.mob-rf-box {
  margin-top: 8px;
  padding: 1rem 0 0;
  border: none;
  border-top: 1px solid var(--border-card);
  border-radius: 0;
  background: none;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.mob-rf-title { font-size: 0.78rem; font-weight: 600; color: var(--muted); }
.mob-rf-row   { display: flex; align-items: center; gap: 8px; }
/* No ring-fenced badge: the box is already titled "What about Schools and
   Housing?" and the note below says these are self-financing, so a pill
   repeating it mid-row only forced the service name to wrap on mobile.
   The glossary definition now hangs off "self-financing" in that note. */
.mob-rf-name  { flex: 1; font-size: 0.82rem; color: var(--muted); min-width: 0; }
.mob-rf-val   { font-size: 0.8rem; color: var(--muted); white-space: nowrap; font-variant-numeric: tabular-nums; }
.mob-rf-note { font-size: 0.72rem; color: var(--muted); line-height: 1.45; margin: 0; }

/* ── Tablet ──────────────────────────────────────────────────────────────── */

@media (max-width: 720px) {
  .ct2-wrap { padding: 1rem 1.25rem; gap: 1.5rem; }
  .ct2-muted { display: none; }
}

/* ── Mobile ──────────────────────────────────────────────────────────────── */

@media (max-width: 600px) {
  :root {
    --header-height: 88px;
    --tabbar-height: 0px;
  }

  .header-subtitle { display: none; }
  .sel--council { font-size: 0.9rem; }
  .tab-bar { grid-template-columns: 1fr auto; grid-template-rows: auto auto; padding: 0; }
  .header-brand { padding: 0.5rem 1rem 0; }
  .tab-bar-right { grid-row: 1; grid-column: 2; padding: 0.5rem 1rem 0; }
  .tab-btns { grid-column: 1 / -1; overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none; padding: 0 8px; border-top: 1px solid var(--border-hairline); }
  .tab-btns::-webkit-scrollbar { display: none; }
  .tab-btn { padding: 0.5rem 0.75rem; font-size: 0.72rem; white-space: nowrap; }
  .view-btn { font-size: 0.65rem; padding: 8px 8px; }

  .ct2-wrap { padding: 0.75rem 1rem; gap: 1.25rem; }
  .ct2-hero-val { font-size: 1.8rem; }
  /* The Band D figure and the requirement cannot sit side by side at this width
     without colliding - both are large and nowrap - so the requirement drops
     below and returns to left alignment with everything else. */
  .ct2-hero-top { flex-direction: column; gap: 16px; }
  .ct2-hero-aside { text-align: left; }
  .ct2-card-val { font-size: 1.05rem; }
  .ct2-cards-sub .ct2-card-val { font-size: 0.95rem; }
  .ct2-table-wrap { scrollbar-width: none; }
  .ct2-table-wrap::-webkit-scrollbar { display: none; }
}

/* ── Landing overlay ─────────────────────────────────────────────────────── */

.landing-overlay {
  position: fixed;
  inset: 0;
  z-index: 9000;
  background: rgba(0, 0, 0, 0.72);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
}
.landing-overlay.hidden { display: none; }

.landing-card {
  background: var(--surface-raised);
  border: 1px solid var(--border-strong);
  border-radius: 12px;
  padding: 32px;
  max-width: 480px;
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 20px;
  box-shadow: 0 8px 40px rgba(0, 0, 0, 0.55);
}

.landing-logo {
  display: flex;
  align-items: baseline;
  gap: 8px;
}
.landing-logo-name {
  font-size: 1.35rem;
  font-weight: 800;
  color: var(--text);
  letter-spacing: -0.02em;
}
.landing-intro {
  font-size: 0.88rem;
  color: var(--muted);
  line-height: 1.6;
}

.landing-warn {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 14px 16px;
  border-radius: 8px;
  border: 1px solid hsl(38, 70%, 45%);
  background: hsla(38, 70%, 45%, 0.12);
  color: var(--color-up);
  font-size: 0.83rem;
  line-height: 1.55;
}
:root.theme-light .landing-warn {
  border-color: hsl(38, 65%, 38%);
  background: hsla(38, 80%, 50%, 0.10);
  color: hsl(38, 75%, 30%);
}
.landing-warn-icon {
  font-size: 1rem;
  flex-shrink: 0;
  line-height: 1.55;
}
.landing-warn strong { font-weight: 700; }
.landing-warn-link {
  color: inherit;
  text-underline-offset: 2px;
}
.landing-warn-link:hover { opacity: 0.8; }

.landing-btn {
  appearance: none;
  border: none;
  cursor: pointer;
  font-family: 'Inter', sans-serif;
  font-size: 0.88rem;
  font-weight: 600;
  padding: 12px 20px;
  border-radius: 8px;
  background: var(--accent);
  color: var(--bg);
  align-self: flex-end;
  transition: opacity 0.15s;
}
.landing-btn:hover { opacity: 0.88; }
.landing-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

@media (max-width: 480px) {
  .landing-card { padding: 24px 20px; gap: 16px; }
  .landing-btn { align-self: stretch; text-align: center; }
}

/* ── Site footer ─────────────────────────────────────────────────────────── */

.site-footer {
  text-align: center;
  font-size: 12px;
  color: var(--muted);
  padding: 16px 16px 24px;
  opacity: 0.6;
}

/* ── Police tab ────────────────────────────────────────────────────────────── */

/* The source prints these for itself, and they form a hierarchy, not one
   flat "weighted row" style: a subtotal or an intermediate total (Staff
   costs total, Total gross expenditure, Total gross income - see
   _polSubjectiveDivider() in police-budget.js) is CLOSING the group above
   it, so it reads quieter than that group's own divider heading; the
   table's actual bottom line (.pol-row-final, always the last row - Net
   expenditure, or the equivalent Net MPS/MOPAC/VRU service expenditure) is
   the answer the whole table was building to, so it gets the most
   separation of any row. */
.pol-row-subtotal,
.pol-row-total:not(.pol-row-final) {
  font-weight: 500;
}
.pol-row-subtotal th, .pol-row-subtotal td,
.pol-row-total:not(.pol-row-final) th, .pol-row-total:not(.pol-row-final) td {
  color: var(--muted);
}
.pol-row-total { border-top: 1px solid var(--border-card); }
.pol-row-final { border-top: 2px solid var(--border-strong); }
.pol-row-final th, .pol-row-final td {
  font-weight: 700;
  color: var(--text);
  padding-top: 14px;
  padding-bottom: 14px;
}

/* These four tables carry five value columns beside a long row label and
   overflow their container at every viewport measured, so - unlike
   council-tax.js's tables, which also use ct2-table-wrap but fit most
   viewports - both the fact that they scroll and where that scroll starts
   need deliberate handling. Everything below is scoped to .pol-table-wrap
   (added alongside ct2-table-wrap only here) so council-tax.js is untouched. */

/* The row label is the reader's anchor: pin it during horizontal scroll so
   landing on the budget-year column doesn't also scroll the label itself out
   of view. Needs its own opaque background, not the default transparent one,
   since value columns now scroll underneath it. */
.pol-table-wrap th[scope="row"],
.pol-table-wrap thead th:first-child {
  position: sticky;
  left: 0;
  z-index: 1;
  background: var(--surface);
}

/* The sticky label column needs its own opaque background, so the generic
   .ct2-table tbody tr:hover td rule cannot reach it - the column a reader is
   most likely tracking across a wide scroll was the one place hover did not
   light. --surface-hover is a translucent overlay, so it is layered as a
   background-image over the opaque background-color rather than replacing it.
   hover: hover keeps it off touch, where it would stick after a tap. */
@media (hover: hover) {
  .pol-table-wrap tbody tr:hover th[scope="row"] {
    background-image: linear-gradient(var(--surface-hover), var(--surface-hover));
  }
}

/* Long MOPAC priority names ("Building safer, more confident communities")
   wrapped to five lines in the column width the table gave them. */
.pol-table-wrap th[scope="row"] { min-width: 168px; }

/* Column headers wrap instead of forcing their own width - "2026/27 budget"
   at the base .ct2-table nowrap rule was wider than the money value beneath
   it, which is what actually needs the space. Wrapping it onto two lines
   lets the column shrink to the value's width instead. */
.pol-table-wrap thead th { white-space: normal; }

/* Even with one value column plus Change, the label column alone (168px)
   is over half of a 360-390px phone's available width - measured overflow
   of 77-107px before this rule. Narrowing the label column here trades
   taller wrapped labels on the two priority tables for a table that fits
   without scrolling on an ordinary phone; every wider viewport keeps the
   full 168px, which most rows never need anyway. */
@media (max-width: 460px) {
  .pol-table-wrap th[scope="row"] { min-width: 112px; }
  .pol-table-wrap thead th,
  .pol-table-wrap tbody td { padding-left: 0.5rem; padding-right: 0.5rem; }
}

/* Group divider inside "What the money is spent on" only (_polSubjectiveDivider
   in police-budget.js) - marks where staff costs end and other spending
   starts, and where spending ends and income starts. Deliberately louder
   than the site's usual SECTION label role (bigger, heavier, full --text
   rather than --muted): it has to outrank the subdued group-closing
   subtotal/total rows below it (see .pol-row-subtotal/.pol-row-total above)
   as well as read as a heading over ordinary data rows, which the standard
   label size does for the ordinary case but not against a row this quiet. A
   top border plus extra top padding on the label itself (not the row)
   separates it from the block above without adding a second border on the
   row that follows. */
.pol-row-divider td {
  padding: 28px 1rem 10px;
  font-family: 'Public Sans', 'Inter', sans-serif;
  font-size: 0.95rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--text);
  border-top: 1px solid var(--border-strong);
  border-bottom: none;
}
.pol-row-divider:first-child td { border-top: none; padding-top: 4px; }

/* A zero the source actually printed, muted so the eye skips it. An absent or
   null value stays an empty cell - the source printing nothing is a different
   fact from the source printing zero, and they must not collapse into one
   glyph. */
.pol-zero { color: var(--muted); }

/* Change-column colours on this tab only. _chgSpan() (mobile.js, shared
   site-wide) emits the same .ct-up/.ct-dn classes every tab uses; these two
   rules override just the colour, just inside a Police table, rather than
   touching .ct-up/.ct-dn themselves - every other tab and every other
   council keeps the site's default amber (rising) / green (falling). */
.pol-table-wrap .ct-up { color: var(--pol-change-up); }
.pol-table-wrap .ct-dn { color: var(--pol-change-down); }

/* Scroll affordance, two parts.
   1) ct2-table-wrap hides the scrollbar below 600px everywhere else
      (council-tax's tables normally fit there), but these tables still
      overflow at that width, so losing the only visual cue that more columns
      exist would make the missing scrollbar read as the table's own edge
      rather than as "more to see". Restored here only. */
@media (max-width: 600px) {
  .pol-table-wrap--scroll { scrollbar-width: thin; }
  .pol-table-wrap--scroll::-webkit-scrollbar { display: block; height: 4px; }
  .pol-table-wrap--scroll::-webkit-scrollbar-track { background: transparent; }
  .pol-table-wrap--scroll::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 4px; }
}
/* 2) A right-edge fade, visible at every width (a native scrollbar can be an
   overlay that only appears while actively scrolling, which is not a
   deliberate cue by itself). Sits above the table, below the sticky label
   column (z-index between them), fading the card's own background to
   transparent so it reads as "content continues" rather than as a stray line.
   pointer-events: none so it never intercepts the scroll/keyboard input it
   is only there to advertise. */
.pol-table-wrap { position: relative; }
.pol-table-wrap--scroll::after {
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 24px;
  z-index: 2;
  pointer-events: none;
  background: linear-gradient(to right, transparent, var(--surface));
}

/* A row's label doubling as its own expand control, for the years beside the
   two shown columns - see _polColumns()/the row loop in _polSection() in
   police-budget.js. Replaces an earlier whole-tab "show all years" toggle
   that widened every table to 5-6 columns: that forced horizontal scrolling
   on every viewport with no comfortable fix, so the years moved into each
   row instead of the table growing wider. Reset to a plain button so it
   reads as the row label it visually replaces, not as a button.
   justify-content: flex-start (not space-between) keeps the chevron and the
   label clustered together at the start of the cell, matching the section
   headers below rather than pushing the chevron to the cell's far edge. */
.pol-row-expand {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 8px;
  width: 100%;
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}
/* Slightly larger than the site-wide 0.7rem chevron - this one sits right
   beside a row label rather than trailing a whole card's title, so it reads
   better a touch bigger. Scoped here rather than raising the shared
   .ct2-details-toggle/.ct2-explain-icon rule, which council-tax.js's band
   toggle also uses and was not asked to change. */
/* Right-pointing while collapsed, rotated to point down once expanded - the
   base .ct2-explain-icon rule carries no rotation at all outside
   .ct2-details-toggle, so both states are set here. */
.pol-row-expand .ct2-explain-icon {
  flex-shrink: 0;
  color: var(--muted);
  font-size: 0.82rem;
  transition: transform 0.15s;
}
.pol-row-expand[aria-expanded="true"] .ct2-explain-icon { transform: rotate(90deg); }

/* The extra-years detail row. Sits on the raised surface, like a nested
   drill-down elsewhere on the site, so it reads as subordinate to the row
   above it rather than as one more row of the table. */
.pol-row-extra > td { background: var(--surface-raised); padding: 8px 12px; }
.pol-row-extra[hidden] { display: none; }
.pol-extra-years { display: flex; flex-direction: column; gap: 4px; }
.pol-extra-year {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  font-size: 0.78rem;
}
.pol-extra-label { color: var(--muted); }
.pol-extra-val { font-variant-numeric: tabular-nums; }

/* .ct2-details-toggle supplies the layout; these adjust it for a card that is
   already padded (unlike .ct2-section.ct2-details, which zeroes its own) and
   add the headline figure. */
.pol-section-head { padding: 0; }
.pol-section-body { padding: 0; gap: 8px; }
.pol-section-head .ct2-h3 { flex: 1; text-align: left; }
/* Slightly larger than the shared 0.7rem, and moved to sit right before the
   title (see the markup order in _polSection()) rather than trailing the
   headline total - scoped here so council-tax.js's band toggle, which also
   uses .ct2-details-toggle, is unaffected. Right-pointing while collapsed,
   rotated to point down once expanded, overriding the shared
   .ct2-details-toggle[aria-expanded="true"] rule's 180deg (up/down toggle,
   what council-tax.js's own band toggle still uses) with 90deg (right/down)
   - equal specificity, so this later rule wins for .pol-section-head only. */
.pol-section-head .ct2-explain-icon { font-size: 0.82rem; }
.pol-section-head[aria-expanded="true"] .ct2-explain-icon { transform: rotate(90deg); }
/* The section's own budget-year total, so four headline figures are readable
   with every table shut. */
.pol-section-total {
  font-size: 0.84rem;
  font-weight: 600;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
