/* graficnolan.cat — one stylesheet, cascade layers, no build step. */
@layer reset, tokens, base, layout, components, utilities;

/* ---------------------------------------------------------------------------
   Tokens
   --------------------------------------------------------------------------- */
@layer tokens {
  :root {
    color-scheme: light dark;
    --paper: #f6f3ec;
    --ink: #15171a;
    --muted: #4a4d52;
    --rule: #d6d1c6;
    --accent: #7a5c3a;
    --tint: color-mix(in oklab, var(--ink) 4%, var(--paper));
    --font-serif: 'Newsreader', Georgia, serif;
    --font-sans: 'Libre Franklin', system-ui, sans-serif;
    --font-mono: 'JetBrains Mono', ui-monospace, monospace;
    --space-1: 4px;
    --space-2: 8px;
    --space-3: 12px;
    --space-4: 16px;
    --space-5: 24px;
    --space-6: 32px;
    --space-7: 48px;
    --space-8: 64px;
    --measure: 68ch;
    --radius: 2px;
    --duration: 160ms;
  }

  :root[data-theme='light'] {
    color-scheme: light;
  }

  @media (prefers-color-scheme: dark) {
    :root:not([data-theme='light']) {
      --paper: #141311;
      --ink: #ece8df;
      --muted: #b3ada2;
      --rule: #3a3731;
      --accent: #c9a27a;
    }
  }

  :root[data-theme='dark'] {
    color-scheme: dark;
    --paper: #141311;
    --ink: #ece8df;
    --muted: #b3ada2;
    --rule: #3a3731;
    --accent: #c9a27a;
  }

  @media (prefers-contrast: more) {
    :root {
      --rule: var(--ink);
      --muted: var(--ink);
    }
  }
}

/* ---------------------------------------------------------------------------
   Reset
   --------------------------------------------------------------------------- */
@layer reset {
  *,
  *::before,
  *::after {
    box-sizing: border-box;
  }

  body,
  h1,
  h2,
  h3,
  p,
  ul,
  ol,
  figure,
  blockquote,
  dl,
  dd {
    margin: 0;
  }

  ul[role='list'],
  ol[role='list'] {
    list-style: none;
    padding: 0;
  }

  img,
  svg {
    max-inline-size: 100%;
    display: block;
  }

  button,
  input {
    font: inherit;
    color: inherit;
  }

  fieldset {
    border: 0;
    padding: 0;
    margin: 0;
    min-inline-size: 0;
  }

  legend {
    padding: 0;
  }
}

/* ---------------------------------------------------------------------------
   Base: fonts, document, typography
   --------------------------------------------------------------------------- */
@layer base {
  @font-face {
    font-family: 'Newsreader';
    src: url('../fonts/newsreader-400.woff2') format('woff2');
    font-weight: 400;
    font-display: swap;
  }
  @font-face {
    font-family: 'Newsreader';
    src: url('../fonts/newsreader-400i.woff2') format('woff2');
    font-weight: 400;
    font-style: italic;
    font-display: swap;
  }
  @font-face {
    font-family: 'Newsreader';
    src: url('../fonts/newsreader-600.woff2') format('woff2');
    font-weight: 600;
    font-display: swap;
  }
  @font-face {
    font-family: 'Libre Franklin';
    src: url('../fonts/libre-franklin-400.woff2') format('woff2');
    font-weight: 400;
    font-display: swap;
  }
  @font-face {
    font-family: 'Libre Franklin';
    src: url('../fonts/libre-franklin-500.woff2') format('woff2');
    font-weight: 500;
    font-display: swap;
  }
  @font-face {
    font-family: 'Libre Franklin';
    src: url('../fonts/libre-franklin-600.woff2') format('woff2');
    font-weight: 600;
    font-display: swap;
  }
  @font-face {
    font-family: 'JetBrains Mono';
    src: url('../fonts/jetbrains-mono-400.woff2') format('woff2');
    font-weight: 400;
    font-display: swap;
  }
  @font-face {
    font-family: 'JetBrains Mono';
    src: url('../fonts/jetbrains-mono-500.woff2') format('woff2');
    font-weight: 500;
    font-display: swap;
  }

  html {
    background: var(--paper);
    color: var(--ink);
    font-family: var(--font-sans);
    line-height: 1.5;
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
    overflow-x: clip;
  }

  body {
    min-block-size: 100dvh;
    display: flex;
    flex-direction: column;
  }

  main {
    flex: 1;
  }

  h1,
  h2,
  h3 {
    font-family: var(--font-serif);
    font-weight: 600;
    line-height: 1.15;
    text-wrap: balance;
  }

  h1 {
    font-size: clamp(2rem, 1.2rem + 3.5vw, 3.5rem);
  }

  h2 {
    font-size: clamp(1.5rem, 1.1rem + 1.5vw, 2.125rem);
  }

  h3 {
    font-size: 1.25rem;
  }

  a {
    color: inherit;
    text-decoration-thickness: 1px;
    text-underline-offset: 0.15em;

    &:hover {
      color: var(--accent);
    }
  }

  :focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
  }

  .num,
  td.num,
  th.num {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
  }

  ::selection {
    background: var(--accent);
    color: var(--paper);
  }

  hr {
    border: 0;
    border-block-start: 1px solid var(--rule);
    margin-block: var(--space-6);
  }

  /* Quiz steps swap under document.startViewTransition; keep it within budget. */
  ::view-transition-old(root),
  ::view-transition-new(root) {
    animation-duration: var(--duration);
  }
}

/* ---------------------------------------------------------------------------
   Layout: container, grids, sections, header, footer
   --------------------------------------------------------------------------- */
@layer layout {
  .container {
    max-inline-size: 72rem;
    margin-inline: auto;
    padding-inline: var(--space-4);
    inline-size: 100%;
  }

  .grid-2 {
    display: grid;
    gap: var(--space-6);
    align-items: start;

    @media (min-width: 60rem) {
      grid-template-columns: 1fr 1fr;
      gap: var(--space-8);
    }
  }

  .section {
    padding-block: var(--space-7);
    border-block-start: 1px solid var(--rule);

    & > h2 {
      margin-block-end: var(--space-5);
    }
  }

  .hero {
    /* Bottom spacing as margin, not padding, so the sticky chart stays until the hero's edge. */
    padding-block-start: var(--space-7);
    margin-block-end: var(--space-7);

    /* Wide: copy and story stack in the left column; the chart spans both rows on the
       right and stays pinned while the story scrolls past it. */
    @media (min-width: 60rem) {
      grid-template-rows: auto 1fr;
      row-gap: var(--space-6);

      & > .hero-copy {
        grid-column: 1;
        grid-row: 1;
      }

      & > .hero-chart {
        grid-column: 2;
        grid-row: 1 / span 2;
      }

      & > .story {
        grid-column: 1;
        grid-row: 2;
      }
    }
  }

  .site-header {
    position: sticky;
    inset-block-start: 0;
    z-index: 10;
    background: var(--paper);
    border-block-end: 1px solid var(--rule);

    & > .container {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--space-4);
      flex-wrap: wrap;
      min-block-size: 56px;
    }

    & .brand {
      font-family: var(--font-serif);
      font-weight: 600;
      font-size: 1.125rem;
      text-decoration: none;
      display: inline-flex;
      align-items: center;
      min-block-size: 44px;
    }

    & nav ul {
      display: flex;
      gap: var(--space-2);
      list-style: none;
      margin: 0;
      padding: 0;
    }

    & nav a {
      display: inline-flex;
      align-items: center;
      min-block-size: 44px;
      padding-inline: var(--space-2);
      font-size: 0.9375rem;
      font-weight: 500;
      text-decoration: none;
      transition: color var(--duration);

      &[aria-current='page'] {
        text-decoration: underline;
        text-decoration-color: var(--accent);
        text-decoration-thickness: 2px;
        text-underline-offset: 0.4em;
      }
    }

    /* Narrow phones: brand and nav share one row; targets stay >= 44 px tall. */
    @media (max-width: 30rem) {
      & > .container {
        flex-wrap: nowrap;
        gap: var(--space-2);
      }

      & .brand {
        font-size: 1rem;
        white-space: nowrap;
      }

      & nav ul {
        gap: 0;
      }

      & nav a {
        font-size: 0.875rem;
      }
    }
  }

  /* Pages without a hero: room between the sticky header and the title. */
  main > .prose,
  main > .party-page,
  main > .method-page {
    padding-block-start: var(--space-7);
  }

  /* Footer: an ink rule closes the page, then one compact band (statement and two link
     groups) and a last line with version and date. The header already carries
     the site navigation, so it is not repeated here. */
  .site-footer {
    margin-block-start: var(--space-8);
    border-block-start: 1px solid var(--ink);
    padding-block: var(--space-6) var(--space-4);
    font-size: 0.875rem;
    color: var(--muted);

    & ul {
      list-style: none;
      margin: 0;
      padding: 0;
    }

    & a:not(.button) {
      display: inline-flex;
      align-items: center;
      min-block-size: 44px;
      color: var(--ink);
      /* A list of links under a label reads as links without the rule; it comes back on hover and focus. */
      text-decoration: none;

      &:is(:hover, :focus-visible) {
        color: var(--accent);
        text-decoration: underline;
      }
    }

    & .num {
      color: var(--ink);
    }
  }

  .footer-top {
    display: grid;
    gap: var(--space-5);

    @media (min-width: 60rem) {
      grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
      gap: var(--space-8);
      align-items: start;
    }
  }

  .footer-statement {
    font-family: var(--font-serif);
    font-size: clamp(1.125rem, 1.05rem + 0.35vw, 1.3125rem);
    line-height: 1.35;
    color: var(--ink);
    max-inline-size: 28ch;
    text-wrap: balance;
    margin-block-end: var(--space-4);
  }

  .footer-nav {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-5);

    @media (min-width: 40rem) {
      grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
    }

    /* Each group hangs from its own hairline, like columns in a printed index. */
    & > div {
      border-block-start: 1px solid var(--rule);
      padding-block-start: var(--space-2);
    }
  }

  /* Four links read better as two short columns than as one tall one. */
  .footer-links-pair {
    @media (min-width: 40rem) {
      display: grid;
      grid-template-columns: repeat(2, minmax(0, 1fr));
      column-gap: var(--space-5);
    }
  }

  .footer-label {
    font-size: 0.8125rem;
    color: var(--muted);
  }

  .footer-colophon {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: var(--space-1) var(--space-6);
    margin-block-start: var(--space-5);
    border-block-start: 1px solid var(--rule);
    padding-block-start: var(--space-3);
    font-size: 0.8125rem;
  }

  .footer-disclaimer {
    color: var(--ink);
  }
}

/* ---------------------------------------------------------------------------
   Components
   --------------------------------------------------------------------------- */
@layer components {
  /* Skip link: visually hidden until focused. */
  .skip-link {
    position: absolute;
    inset-block-start: var(--space-2);
    inset-inline-start: var(--space-2);
    z-index: 20;
    padding: var(--space-3) var(--space-4);
    background: var(--ink);
    color: var(--paper);
    font-weight: 500;
    text-decoration: none;
    translate: 0 -200%;
    transition: translate var(--duration);

    &:focus-visible {
      translate: 0 0;
      outline-color: var(--paper);
      outline-offset: -4px;
    }
  }

  /* Reading column. */
  .prose {
    max-inline-size: var(--measure);
    font-family: var(--font-serif);
    font-size: clamp(1.0625rem, 1rem + 0.3vw, 1.1875rem);
    line-height: 1.6;

    & > * + * {
      margin-block-start: var(--space-4);
    }

    & > h2,
    & > h3 {
      margin-block-start: var(--space-6);
    }

    & > h1 + p,
    & > h2 + p,
    & > h3 + p {
      margin-block-start: var(--space-3);
    }

    & > .button {
      margin-block-start: var(--space-5);
    }

    & ul,
    & ol {
      padding-inline-start: 1.25em;
    }

    & li + li {
      margin-block-start: var(--space-2);
    }

    & em {
      font-style: italic;
    }

    & blockquote {
      border-inline-start: 1px solid var(--accent);
      padding-inline-start: var(--space-4);
      color: var(--muted);
    }

    & .caption,
    & .rule-list,
    & .button {
      font-family: var(--font-sans);
    }
  }

  /* Buttons: ink on paper; hover inverts. */
  .button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    min-block-size: 44px;
    padding: var(--space-2) var(--space-5);
    border: 1px solid var(--ink);
    border-radius: var(--radius);
    background: var(--paper);
    color: var(--ink);
    font-family: var(--font-sans);
    font-size: 1rem;
    font-weight: 500;
    line-height: 1.2;
    text-decoration: none;
    cursor: pointer;
    transition:
      background-color var(--duration),
      color var(--duration),
      border-color var(--duration);

    &:hover {
      background: var(--ink);
      color: var(--paper);
    }

    &:disabled,
    &[aria-disabled='true'] {
      opacity: 0.5;
      cursor: not-allowed;
      background: var(--paper);
      color: var(--ink);
    }
  }

  .button--primary {
    background: var(--ink);
    color: var(--paper);

    &:hover {
      background: var(--paper);
      color: var(--ink);
    }

    &:disabled,
    &[aria-disabled='true'] {
      background: var(--ink);
      color: var(--paper);
    }
  }

  /* Small source line under charts, meta text. */
  .caption {
    font-family: var(--font-sans);
    font-size: 0.8125rem;
    line-height: 1.45;
    color: var(--muted);

    & a {
      color: inherit;
    }

    & a:hover {
      color: var(--accent);
    }
  }

  /* Rows separated by 1 px rules. */
  .rule-list {
    list-style: none;
    margin: 0;
    padding: 0;
    border-block-start: 1px solid var(--rule);

    & > li {
      border-block-end: 1px solid var(--rule);
      padding-block: var(--space-3);
    }
  }

  /* Party page heading: colour swatch inline before the name. */
  .party-title {
    display: flex;
    align-items: start;
    gap: var(--space-3);

    /* Centred on the first line even when the name wraps: (line-height − swatch) / 2. */
    & .swatch {
      flex: none;
      inline-size: 0.45em;
      block-size: 0.45em;
      margin-block-start: calc((1.15em - 0.45em) / 2);
    }
  }

  /* Party page: header and reading column on the left, sticky chart on the right
     from 60rem. Below that, the chart sits between the header and the text. */
  .party-page {
    --header-offset: 57px; /* sticky site header: 56 px row + 1 px rule */
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    row-gap: var(--space-6);

    & > .party-header,
    & > .party-body {
      max-inline-size: var(--measure);
    }

    & > .party-chart {
      inline-size: 100%;
      max-inline-size: 36rem;
    }

    @media (min-width: 60rem) {
      /* Text takes what is left; the chart column stays between 20 and 30 rem. */
      grid-template-columns: minmax(0, 1fr) clamp(20rem, 38%, 30rem);
      column-gap: var(--space-7);
      row-gap: var(--space-5);
      align-items: start;

      & > .party-chart {
        grid-column: 2;
        grid-row: 1 / span 2;
        position: sticky;
        inset-block-start: calc(var(--header-offset) + var(--space-5));
        max-inline-size: none;
      }
    }
  }

  .party-header {
    & > .party-nav + .party-title {
      margin-block-start: var(--space-2);
    }

    & > .party-title + .party-quadrant {
      margin-block-start: var(--space-3);
    }

    & > .party-quadrant + .party-coords {
      margin-block-start: var(--space-2);
    }
  }

  /* Previous / next party: two quiet links, 44 px tall, one at each end. */
  .party-nav {
    display: flex;
    justify-content: space-between;
    gap: var(--space-4);

    & a {
      display: inline-flex;
      align-items: center;
      gap: var(--space-1);
      min-block-size: 44px;
      text-decoration: none;

      &:hover,
      &:focus-visible {
        text-decoration: underline;
      }
    }
  }

  /* Quadrant name as an editorial subtitle. */
  .party-quadrant {
    font-family: var(--font-serif);
    font-style: italic;
    font-size: clamp(1.25rem, 1rem + 1vw, 1.5rem);
    line-height: 1.3;
  }

  /* Lede: slightly larger than the running text. */
  .party-intro {
    font-size: 1.1em;
    line-height: 1.55;
    text-wrap: pretty;
  }

  /* Footnote reference at the end of a claim. Inline in a sentence, so the target
     grows through a pseudo-element instead of the line box (WCAG 2.5.8 inline case). */
  .fn-ref {
    font-size: 0.7em;
    line-height: 0;
    vertical-align: super;

    & a {
      position: relative;
      font-family: var(--font-sans);
      font-weight: 500;
      text-decoration: none;
      padding-inline: 1px;

      &::after {
        content: '';
        position: absolute;
        inset: -14px -10px;
      }

      &:hover,
      &:focus-visible {
        color: var(--accent);
      }
    }
  }

  /* Topic scores: five rows plus the mean, which is the coordinate. */
  .topic-scores {
    inline-size: 100%;
    border-collapse: collapse;
    font-family: var(--font-sans);
    font-size: 0.9375rem;

    & th,
    & td {
      padding: var(--space-2) var(--space-3);
      text-align: start;
      border-block-end: 1px solid var(--rule);
    }

    & th:first-child,
    & td:first-child {
      padding-inline-start: 0;
    }

    & th:last-child,
    & td:last-child {
      padding-inline-end: 0;
    }

    & thead th {
      font-size: 0.8125rem;
      font-weight: 600;
      color: var(--muted);
      border-block-end: 1px solid var(--ink);
    }

    & tbody th {
      font-weight: 400;
    }

    & th.num,
    & td.num {
      text-align: end;
      inline-size: 6.5rem;
      white-space: nowrap;
    }

    & tfoot th,
    & tfoot td {
      font-weight: 600;
      border-block-start: 1px solid var(--ink);
      border-block-end: 0;
    }
  }

  .party-status strong {
    font-weight: 600;
    color: var(--ink);
  }

  /* Facts sheet: leader, web, social, programme. Rows ruled, labels muted. */
  .party-facts {
    margin-block-start: var(--space-6);
    font-family: var(--font-sans);
    font-size: 0.9375rem;
    border-block-start: 1px solid var(--rule);

    & > div {
      display: grid;
      grid-template-columns: 5.5rem minmax(0, 1fr);
      column-gap: var(--space-4);
      align-items: baseline;
      padding-block: var(--space-1);
      border-block-end: 1px solid var(--rule);
    }

    & dt {
      font-size: 0.8125rem;
      color: var(--muted);
    }

    & dd {
      margin: 0;
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      gap: 0 var(--space-4);
    }

    & a {
      display: inline-flex;
      align-items: center;
      min-block-size: 44px;
    }

    & .leader-name {
      font-weight: 500;
    }
  }

  /* Sources as numbered notes: the number hangs in a narrow first column. */
  ol.footnotes {
    list-style: none;
    padding-inline-start: 0;
    counter-reset: footnote;
    font-family: var(--font-sans);
    font-size: 0.9375rem;
    border-block-start: 1px solid var(--rule);

    & > li {
      counter-increment: footnote;
      display: grid;
      grid-template-columns: 1.5rem minmax(0, 1fr);
      column-gap: var(--space-3);
      align-items: baseline;
      padding-block: var(--space-1);
      border-block-end: 1px solid var(--rule);
      scroll-margin-block-start: calc(57px + var(--space-4));

      &::before {
        content: counter(footnote);
        font-family: var(--font-mono);
        font-size: 0.8125rem;
        color: var(--muted);
      }

      &:target {
        background: var(--tint);
      }
    }

    & > li + li {
      margin-block-start: 0;
    }

    /* Title link and host share a row and wrap together on narrow screens. */
    & .fn-body {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      column-gap: var(--space-3);
      min-inline-size: 0;
    }

    & a {
      display: inline-flex;
      align-items: center;
      min-block-size: 44px;
      min-inline-size: 0;
    }
  }

  /* Nolan chart figure. The SVG has viewBox 0 0 500 500. */
  .nolan-chart {
    container-type: inline-size;
    inline-size: 100%;
    max-inline-size: 560px;
    margin-inline: auto;

    & svg {
      inline-size: 100%;
      block-size: auto;
      aspect-ratio: 1;
      overflow: visible;
      font-family: var(--font-sans);
    }

    & figcaption {
      margin-block-start: var(--space-3);
    }

    /* Two opposite quadrants carry a 5 % ink tint; the other two are bare paper. */
    & .chart-tint {
      fill: color-mix(in oklab, var(--ink) 5%, var(--paper));
    }

    & .chart-grid {
      stroke: var(--rule);
      stroke-width: 1;
    }

    & .chart-axis {
      stroke: var(--ink);
      stroke-width: 1;
    }

    & .chart-label {
      font-size: 12px;
      font-weight: 400;
      fill: var(--muted);
    }

    & a {
      text-decoration: none;
      outline-offset: 4px;
    }

    & .party {
      & circle {
        stroke: var(--paper);
        stroke-width: 1;
        transition:
          stroke var(--duration),
          stroke-width var(--duration);
      }

      /* Invisible touch target under the dot: catches taps, never drawn. */
      & circle.hit {
        fill: transparent;
        stroke: none;
      }

      & text {
        font-size: 12px;
        font-weight: 500;
        fill: var(--ink);
        paint-order: stroke;
        stroke: var(--paper);
        stroke-width: 3px;
        stroke-linejoin: round;
      }

      &.is-current circle:not(.hit),
      &.is-highlight circle:not(.hit) {
        stroke: var(--ink);
        stroke-width: 2;
      }

      &.is-current text,
      &.is-highlight text {
        font-weight: 600;
      }
    }

    /* Story highlight: the SVG dims every party except the ones the current step names. */
    & .party {
      transition: opacity var(--duration);
    }

    & svg.is-dim .party:not(.is-highlight) {
      opacity: 0.35;
    }

    & a:hover .party circle:not(.hit),
    & a:focus-visible .party circle:not(.hit) {
      stroke: var(--ink);
      stroke-width: 2;
    }

    & a:hover .party text,
    & a:focus-visible .party text {
      text-decoration: underline;
    }

    /* The visitor: 2 px ink ring, accent centre, name inside an ink chip. */
    & .user-point {
      /* Entry tween scales around the ring, not the SVG origin. */
      transform-box: fill-box;
      transform-origin: center;

      & .user-ring {
        fill: var(--paper);
        stroke: var(--ink);
        stroke-width: 2;
      }

      & .user-dot {
        fill: var(--accent);
      }

      & .user-chip rect {
        fill: var(--ink);
      }

      & .user-chip text {
        font-size: 12px;
        font-weight: 500;
        fill: var(--paper);
      }
    }

    /* Chart narrower than 30rem: SVG text is in user units, so scale it up. */
    @container (inline-size < 30rem) {
      & .chart-label,
      & .party text,
      & .user-chip text {
        font-size: 15px;
      }
    }
  }

  /* Hover / focus tooltip for a party dot: HTML box outside the SVG, moved with a held animation. */
  .nolan-chart {
    position: relative;
  }

  .chart-tip {
    position: absolute;
    inset-block-start: 0;
    inset-inline-start: 0;
    z-index: 2;
    display: grid;
    gap: 2px;
    max-inline-size: 16rem;
    padding: var(--space-2) var(--space-3);
    border: 1px solid var(--ink);
    border-radius: var(--radius);
    background: var(--paper);
    color: var(--ink);
    font-family: var(--font-sans);
    font-size: 0.8125rem;
    line-height: 1.35;
    white-space: nowrap;
    pointer-events: none;
    transform: translate(-50%, -100%);

    &[hidden] {
      display: none;
    }

    &.is-below {
      transform: translate(-50%, 0);
    }

    & strong {
      font-weight: 600;
    }

    & .num {
      font-size: 0.75rem;
    }

    & > span:last-child {
      color: var(--muted);
    }
  }

  /* Two-button period switch. */
  .time-toggle {
    display: inline-flex;
    border: 1px solid var(--ink);
    border-radius: var(--radius);

    & button {
      min-block-size: 44px;
      padding-inline: var(--space-4);
      border: 0;
      background: transparent;
      color: var(--ink);
      font-family: var(--font-mono);
      font-size: 0.875rem;
      font-variant-numeric: tabular-nums;
      cursor: pointer;
      transition:
        background-color var(--duration),
        color var(--duration);

      & + button {
        border-inline-start: 1px solid var(--ink);
      }

      &:hover {
        background: var(--tint);
      }

      &[aria-pressed='true'] {
        background: var(--ink);
        color: var(--paper);
      }

      &:focus-visible {
        outline-offset: -3px;
        outline-color: var(--paper);
      }

      &:focus-visible:not([aria-pressed='true']) {
        outline-color: var(--accent);
      }
    }
  }

  /* Single axis bar: SVG track + marker, labels left and right. */
  .axis-bar {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-1) var(--space-3);

    /* Label with the value, above the track (party pages). */
    & > .axis-label {
      grid-column: 1 / -1;
      display: flex;
      align-items: baseline;
      gap: var(--space-3);
      font-family: var(--font-sans);
      font-size: 0.9375rem;
      font-weight: 500;
    }

    & svg {
      grid-column: 1 / -1;
      inline-size: 100%;
      block-size: 24px;
      overflow: visible;
    }

    & rect {
      fill: var(--rule);
    }

    & line {
      stroke: var(--muted);
      stroke-width: 1;
    }

    /* Marker: the party colour when the markup sets fill, the accent otherwise (quiz). */
    & circle {
      stroke: var(--paper);
      stroke-width: 1;
    }

    & circle:not([fill]) {
      fill: var(--accent);
    }

    & .caption:last-of-type {
      text-align: end;
    }

    & + .axis-bar {
      margin-block-start: var(--space-4);
    }
  }

  /* Quiz. One step = progress line, question block and the Anterior / Següent bar. */
  .quiz-step {
    max-inline-size: var(--measure);

    /* Room for the fixed navigation bar on narrow screens (see .quiz-nav). */
    @media (width < 60rem) {
      padding-block-end: calc(88px + env(safe-area-inset-bottom, 0px));
    }

    /* Wide screens: the question sits in the middle of the viewport, not glued to the top. */
    @media (width >= 60rem) {
      display: grid;
      align-content: center;
      min-block-size: 60dvh;
    }
  }

  /* Progress text on the left, "Tornar al resultat" (when there is one) on the right. */
  .quiz-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    margin-block-end: var(--space-2);

    & .caption {
      font-variant-numeric: tabular-nums;
    }

    & .quiz-back {
      min-block-size: 32px;
      font-size: 0.875rem;
    }

    & .quiz-back[hidden] {
      display: none;
    }
  }

  .quiz-question {
    display: block;
    font-family: var(--font-serif);
    font-weight: 600;
    font-size: clamp(1.5rem, 1.2rem + 1.5vw, 2.25rem);
    line-height: 1.25;
    text-wrap: balance;
    margin-block: var(--space-5);
  }

  .quiz-answers {
    display: grid;
    gap: var(--space-2);

    &:has([aria-pressed='true']) .quiz-answer:not([aria-pressed='true']) {
      color: var(--muted);
    }
  }

  /* Answer: key marker (1-4) · text · tick. Selected = 2 px accent border; the padding drops
     by 1 px on every side so the box keeps its size and the list does not jump. */
  .quiz-answer {
    display: grid;
    grid-template-columns: auto 1fr 12px;
    align-items: center;
    gap: var(--space-3);
    inline-size: 100%;
    min-block-size: 44px;
    padding: var(--space-4);
    /* Control boundary at >= 3:1 (WCAG 1.4.11); --rule is for decorative dividers only. */
    border: 1px solid var(--muted);
    border-radius: var(--radius);
    background: var(--paper);
    color: var(--ink);
    font-family: var(--font-sans);
    font-size: 1rem;
    line-height: 1.4;
    text-align: start;
    cursor: pointer;
    transition:
      background-color var(--duration),
      border-color var(--duration),
      color var(--duration);

    & .quiz-answer-key {
      align-self: start;
      min-inline-size: 1.5em;
      padding-block-start: 0.1em;
      font-size: 0.8125rem;
      color: var(--muted);
      transition: color var(--duration);
    }

    & .quiz-answer-check {
      inline-size: 12px;
      block-size: 12px;
      opacity: 0;
      transition: opacity var(--duration);
    }

    &:hover {
      border-color: var(--ink);

      & .quiz-answer-key {
        color: var(--ink);
      }
    }

    &[aria-pressed='true'] {
      padding: calc(var(--space-4) - 1px);
      border: 2px solid var(--accent);
      background: var(--tint);
      color: var(--ink);

      & .quiz-answer-key {
        color: var(--accent);
        font-weight: 500;
      }

      & .quiz-answer-check {
        opacity: 1;
        color: var(--accent);
      }
    }
  }

  .quiz-skip {
    margin-block-start: var(--space-4);
    border-style: dashed;
    border-color: var(--muted);
    background: transparent;
    color: var(--muted);
    font-size: 0.875rem;
    font-weight: 400;

    &:hover {
      border-color: var(--ink);
      background: var(--tint);
      color: var(--ink);
    }

    &[aria-pressed='true'] {
      border-style: solid;
      border-color: var(--ink);
      background: var(--tint);
      color: var(--ink);
    }
  }

  .quiz-nav {
    display: flex;
    justify-content: space-between;
    gap: var(--space-3);
    margin-block-start: var(--space-6);
    padding-block-start: var(--space-4);
    border-block-start: 1px solid var(--rule);

    /* Narrow screens: a fixed bar in the thumb zone, two equal columns, 48 px targets. */
    @media (width < 60rem) {
      position: fixed;
      inset-inline: 0;
      inset-block-end: 0;
      z-index: 5;
      display: grid;
      grid-template-columns: 1fr 1fr;
      margin: 0;
      padding: var(--space-3) var(--space-4) calc(var(--space-3) + env(safe-area-inset-bottom, 0px));
      background: var(--paper);

      & .button {
        inline-size: 100%;
        min-block-size: 48px;
      }
    }
  }

  /* Shortcut hint: only where there is a keyboard to speak of. */
  .quiz-keys {
    display: none;
    margin-block-start: var(--space-3);

    @media (pointer: fine) and (width >= 60rem) {
      display: block;
    }
  }

  /* The fixed bar would cover the footer's last line on the quiz steps. */
  @media (width < 60rem) {
    body:has(.quiz-step) .site-footer {
      padding-block-end: calc(var(--space-6) + 88px + env(safe-area-inset-bottom, 0px));
    }
  }

  progress {
    display: block;
    appearance: none;
    inline-size: 100%;
    block-size: 4px;
    border: 0;
    border-radius: 0;
    background: var(--rule);
    color: var(--accent);
    accent-color: var(--accent);

    &::-webkit-progress-bar {
      background: var(--rule);
      border-radius: 0;
    }

    &::-webkit-progress-value {
      background: var(--accent);
      border-radius: 0;
      transition: inline-size var(--duration);
    }

    &::-moz-progress-bar {
      background: var(--accent);
      border-radius: 0;
    }
  }

  /* Result. The three axis figures share one row at every width; the national bar sits under. */
  .result-axes {
    border-block: 1px solid var(--rule);
    padding-block: var(--space-4);
  }

  .result-numbers {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-1) var(--space-3);

    & > div {
      display: grid;
      gap: var(--space-1);
    }

    & dt {
      font-family: var(--font-sans);
      font-size: 0.8125rem;
      line-height: 1.45;
      color: var(--muted);
    }

    & dd {
      font-family: var(--font-mono);
      font-variant-numeric: tabular-nums;
      font-size: 1.75rem;
      line-height: 1.1;
    }
  }

  .result-national {
    margin-block-start: var(--space-4);
    padding-block-start: var(--space-4);
    border-block-start: 1px solid var(--rule);
  }

  .result-quadrant {
    font-family: var(--font-serif);
    font-weight: 600;
    font-size: clamp(1.75rem, 1.2rem + 2vw, 2.75rem);
    line-height: 1.1;
    text-wrap: balance;
  }

  .proximity-row {
    display: grid;
    grid-template-columns: 12px 1fr auto;
    column-gap: var(--space-3);
    align-items: center;
    padding-block: var(--space-3);
    border-block-end: 1px solid var(--rule);

    &:first-child {
      border-block-start: 1px solid var(--rule);
    }

    & .swatch {
      inline-size: 12px;
      block-size: 12px;
    }

    & a {
      display: inline-flex;
      align-items: center;
      min-block-size: 44px;
      font-weight: 500;
      text-decoration: none;
    }

    & .num {
      justify-self: end;
      font-size: 1.125rem;
    }

    & .caption {
      grid-column: 2 / -1;
      margin-block-start: var(--space-1);
    }

    &:has(a:hover) .num,
    &:has(a:focus-visible) .num {
      color: var(--accent);
    }
  }

  /* Quiz page shell: intro, stage and result share one column. */
  .quiz {
    padding-block: var(--space-7) var(--space-8);
  }

  /* Legend margins do not apply inside a fieldset; space the question from the progress bar here. */
  .quiz-body > fieldset {
    padding-block-start: var(--space-3);
  }

  /* Intro as a cover: what you get, the caveat, one big call to action. */
  .quiz-intro {
    & .quiz-intro-label {
      margin-block-start: var(--space-6);
      font-weight: 500;
      letter-spacing: 0.02em;
      text-transform: uppercase;
      font-size: 0.75rem;
    }

    & .quiz-gets {
      margin-block-start: var(--space-2);
      font-family: var(--font-sans);
      font-size: 1rem;

      & > li {
        display: grid;
        grid-template-columns: 1.5em 1fr;
        gap: var(--space-3);
        padding-block: var(--space-3);
      }

      & > li::before {
        content: counter(gets, decimal-leading-zero);
        counter-increment: gets;
        font-family: var(--font-mono);
        font-size: 0.8125rem;
        line-height: 1.6;
        color: var(--muted);
      }
    }

    & .quiz-gets {
      counter-reset: gets;
    }

    & .quiz-gets + p {
      margin-block-start: var(--space-5);
    }

    & .quiz-cta {
      display: grid;
      justify-items: start;
      gap: var(--space-3);
      margin-block-start: var(--space-6);
      font-family: var(--font-sans);
    }

    & .quiz-resume {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      gap: var(--space-3) var(--space-5);
    }

    & .quiz-resume[hidden],
    & .quiz-last[hidden],
    & [data-start][hidden] {
      display: none;
    }

    & .quiz-last {
      margin: 0;
    }

    & .quiz-meta {
      margin-block-start: var(--space-3);
    }
  }

  /* Result: stacked blocks in the reading column; the chart sits flush left. */
  .result {
    max-inline-size: var(--measure);

    & > * + * {
      margin-block-start: var(--space-6);
    }

    & h3 {
      margin-block-end: var(--space-3);
    }

    & .nolan-chart {
      margin-inline: 0;
    }

    @media (width >= 60rem) {
      & .nolan-chart {
        max-inline-size: 640px;
      }
    }
  }

  .result-national > .caption {
    margin-block-start: var(--space-2);
  }

  /* Percentage plus its qualifier, right-aligned in the proximity row. */
  .proximity-value {
    justify-self: end;
    display: grid;
    justify-items: end;
    text-align: end;

    & .num {
      font-size: 1.125rem;
    }
  }

  /* "Les teves respostes": question, chosen answer and a "Canvia" button per row. */
  .result-review {
    font-family: var(--font-sans);

    & > summary {
      font-weight: 500;
    }

    & > .caption {
      margin-block-end: var(--space-3);
    }
  }

  /* Disclosure rows: a flex summary drops the native marker, so draw a 1 px chevron. */
  .result-review > summary,
  .result-preview > summary {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    min-block-size: 44px;
    list-style: none;
    cursor: pointer;

    &::-webkit-details-marker {
      display: none;
    }

    &::before {
      content: '';
      flex: none;
      inline-size: 7px;
      block-size: 7px;
      margin-inline-start: 2px;
      border-inline-end: 1px solid currentColor;
      border-block-end: 1px solid currentColor;
      transform: rotate(-45deg);
      transition: transform var(--duration);
    }

    &:hover {
      color: var(--accent);
    }
  }

  .result-review[open] > summary::before,
  .result-preview[open] > summary::before {
    transform: rotate(45deg);
  }

  .answer-review > li {
    display: grid;
    grid-template-columns: 1fr auto;
    grid-template-areas:
      'question change'
      'answer change';
    gap: var(--space-1) var(--space-4);
    align-items: center;
    font-size: 0.9375rem;

    & > .caption {
      grid-area: question;
    }

    & > [data-answer-text] {
      grid-area: answer;
    }

    & > [data-change] {
      grid-area: change;
      font-size: 0.9375rem;
    }
  }

  /* Card preview under the share buttons. */
  .result-preview {
    & > summary {
      font-size: 0.9375rem;
    }

    & img {
      inline-size: 100%;
      block-size: auto;
      margin-block-start: var(--space-2);
      border: 1px solid var(--rule);
    }
  }

  /* Name field, copy button and restart link under the result. */
  .result-share {
    display: grid;
    gap: var(--space-3);
    padding-block-start: var(--space-5);
    border-block-start: 1px solid var(--rule);
    font-family: var(--font-sans);

    & label {
      font-size: 0.9375rem;
      font-weight: 500;
    }

    & .field {
      display: flex;
      flex-wrap: wrap;
      gap: var(--space-2);
    }

    & input {
      flex: 1 1 14rem;
      min-block-size: 44px;
      padding-inline: var(--space-3);
      border: 1px solid var(--ink);
      border-radius: var(--radius);
      background: var(--paper);
      font-family: var(--font-sans);
      font-size: 1rem;
    }

    & .result-actions {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      gap: var(--space-3) var(--space-5);
      margin-block-start: var(--space-2);
    }

    & [data-restart] {
      display: inline-flex;
      align-items: center;
      min-block-size: 44px;
    }
  }

  /* Scores table, scrolls horizontally inside its wrapper only. */
  .table-wrap {
    /* Containing block for .visually-hidden cells, so they cannot widen the page. */
    position: relative;
    container-type: inline-size;
    inline-size: 100%;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scrollbar-width: thin;
    border-block-end: 1px solid var(--rule);
  }

  .scores-table {
    inline-size: 100%;
    border-collapse: collapse;
    font-family: var(--font-sans);
    font-size: 0.875rem;

    & caption {
      caption-side: top;
      text-align: start;
      padding-block: var(--space-3);
      color: var(--muted);
      font-size: 0.8125rem;
      /* The caption box is as wide as the table; pin it to the wrapper's width
         and keep it in view while the table scrolls sideways. */
      position: sticky;
      inset-inline-start: 0;
      inline-size: 100cqi;
      white-space: normal;
      text-wrap: pretty;
    }

    & th,
    & td {
      padding: var(--space-2) var(--space-3);
      text-align: start;
      vertical-align: top;
      white-space: nowrap;
      border-block-end: 1px solid var(--rule);
    }

    & thead th {
      font-weight: 600;
      font-size: 0.8125rem;
      color: var(--muted);
      border-block-end: 1px solid var(--ink);
    }

    & th:first-child,
    & td:first-child {
      position: sticky;
      inset-inline-start: 0;
      background: var(--paper);
      border-inline-end: 1px solid var(--rule);
      font-weight: 500;
    }

    & td,
    & th.num {
      font-variant-numeric: tabular-nums;
    }

    & td.num,
    & th.num {
      text-align: end;
    }

    & tbody tr:hover td {
      background: var(--tint);
    }

    & a {
      text-decoration: none;
    }

    /* Mean column: the coordinate, set apart by a rule, with two inline bars
       (economic above, social below) drawn from zero in the party colour. */
    & thead th:last-child,
    & td.mean {
      border-inline-start: 1px solid var(--rule);
    }

    & td.mean {
      font-weight: 500;

      & > span {
        margin-inline-end: var(--space-2);
      }
    }

    & .mean-bars {
      display: inline-block;
      vertical-align: middle;
      overflow: visible;

      & .zero {
        stroke: var(--rule);
        stroke-width: 1;
      }
    }
  }

  /* Methodology page, laid out like a working paper: contents on the left from 60rem,
     a 68ch reading column, margin notes in a third column from 75rem. */
  .method-page {
    --header-offset: 57px; /* sticky site header: 56 px row + 1 px rule */
    --subnav-offset: 45px; /* contents strip under the header on narrow screens: 44 px + 1 px rule */
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    row-gap: var(--space-6);
    padding-block: var(--space-4) var(--space-7);
    hanging-punctuation: first last;

    /* Anchor targets clear the sticky header (and the contents strip when it is there). */
    & [id] {
      scroll-margin-block-start: calc(var(--header-offset) + var(--subnav-offset) + var(--space-4));
    }

    & p {
      text-wrap: pretty;
    }

    & .section > * + * {
      margin-block-start: var(--space-5);
    }

    & .prose h4 {
      font-family: var(--font-serif);
      font-weight: 600;
      font-size: 1.125rem;
      line-height: 1.2;
    }

    @media (min-width: 60rem) {
      --subnav-offset: 0px;
      grid-template-columns: 11rem minmax(0, 1fr);
      column-gap: var(--space-7);
      align-items: start;
      padding-block-start: var(--space-7);
    }
  }

  .method-body {
    min-inline-size: 0;
  }

  /* "En aquesta pàgina": numbered contents. Side rail with a 2 px accent marker on the
     current item from 60rem; below that, a sticky strip under the header that scrolls
     sideways, with the marker under the item. */
  .page-nav {
    font-family: var(--font-sans);

    & .page-nav-title {
      font-size: 0.8125rem;
      font-weight: 600;
      line-height: 1.4;
      color: var(--muted);
      margin-block-end: var(--space-2);
    }

    & ol {
      list-style: none;
      margin: 0;
      padding: 0;
      counter-reset: contents;
    }

    & li {
      counter-increment: contents;
    }

    & a {
      display: flex;
      align-items: center;
      gap: var(--space-2);
      min-block-size: 44px;
      font-size: 0.9375rem;
      font-weight: 500;
      color: var(--muted);
      text-decoration: none;
      transition:
        color var(--duration),
        border-color var(--duration);

      &::before {
        content: counter(contents, decimal-leading-zero);
        font-family: var(--font-mono);
        font-size: 0.75rem;
        color: var(--muted);
        transition: color var(--duration);
      }

      &:hover {
        color: var(--accent);
      }

      &[aria-current='true'] {
        color: var(--ink);
        border-color: var(--accent);

        &::before {
          color: var(--accent);
        }
      }
    }

    @media (max-width: 59.99rem) {
      position: sticky;
      inset-block-start: var(--header-offset);
      z-index: 9;
      background: var(--paper);
      border-block-end: 1px solid var(--rule);
      /* Full bleed inside .container so the strip runs edge to edge. */
      margin-inline: calc(-1 * var(--space-4));
      padding-inline: var(--space-4);

      & .page-nav-title {
        position: absolute;
        inline-size: 1px;
        block-size: 1px;
        margin: -1px;
        overflow: hidden;
        clip-path: inset(50%);
        white-space: nowrap;
      }

      & ol {
        display: flex;
        gap: var(--space-4);
        overflow-x: auto;
        overscroll-behavior-x: contain;
        scrollbar-width: none;
      }

      & a {
        white-space: nowrap;
        border-block-end: 2px solid transparent;
      }
    }

    @media (min-width: 60rem) {
      position: sticky;
      inset-block-start: calc(var(--header-offset) + var(--space-5));

      & ol {
        border-inline-start: 1px solid var(--rule);
      }

      & a {
        margin-inline-start: -1px;
        padding-inline-start: var(--space-3);
        border-inline-start: 2px solid transparent;
      }
    }
  }

  /* Page head: title, dek, version line, abstract, then the note on objectivity. */
  .method-head {
    padding-block-end: var(--space-3);

    & > h1 + .method-dek {
      margin-block-start: var(--space-3);
    }

    & .method-dek {
      max-inline-size: var(--measure);
      font-family: var(--font-serif);
      font-size: clamp(1.125rem, 1rem + 0.6vw, 1.375rem);
      line-height: 1.4;
      color: var(--muted);
    }

    & .method-meta {
      margin-block-start: var(--space-4);
    }

    & .method-abstract,
    & .method-intro {
      margin-block-start: var(--space-6);
    }
  }

  /* Abstract: ink rule on top, a small label and four ruled term / text rows. */
  .method-abstract {
    max-inline-size: var(--measure);
    border-block-start: 1px solid var(--ink);
    padding-block-start: var(--space-3);

    & > h2 {
      font-family: var(--font-sans);
      font-size: 0.8125rem;
      font-weight: 600;
      line-height: 1.4;
      color: var(--muted);
    }

    & dl {
      margin-block-start: var(--space-2);
      border-block-start: 1px solid var(--rule);
    }

    & dl > div {
      display: grid;
      gap: var(--space-1) var(--space-5);
      padding-block: var(--space-3);
      border-block-end: 1px solid var(--rule);
    }

    & dt {
      font-family: var(--font-sans);
      font-size: 0.9375rem;
      font-weight: 500;
    }

    & dd {
      font-family: var(--font-serif);
      font-size: 1.0625rem;
      line-height: 1.5;
      color: var(--muted);
    }

    @media (min-width: 40rem) {
      & dl > div {
        grid-template-columns: minmax(11rem, 1fr) 2fr;
      }
    }
  }

  /* Margin notes: one figure already stated in the paragraph beside it. Inline as a ruled
     line below 75rem; in a third column next to the block they annotate from 75rem. */
  .margin-note {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--space-1) var(--space-2);
    border-inline-start: 1px solid var(--accent);
    padding-inline-start: var(--space-3);
    font-family: var(--font-sans);
    font-size: 0.8125rem;
    line-height: 1.45;
    color: var(--muted);

    & > .num {
      font-size: 1.5rem;
      font-weight: 500;
      line-height: 1;
      color: var(--ink);
    }
  }

  @media (min-width: 75rem) {
    .method-page .prose {
      max-inline-size: none;
      display: grid;
      grid-template-columns: minmax(0, var(--measure)) minmax(8rem, 11rem);
      column-gap: var(--space-6);
      row-gap: var(--space-4);
      align-items: start;

      & > * {
        grid-column: 1;
        margin-block-start: 0;
      }

      & > h2,
      & > h3 {
        padding-block-start: var(--space-3);
      }

      & > :first-child {
        padding-block-start: 0;
      }

      & > .margin-note {
        grid-column: 2;
        display: block;
        border-inline-start: 0;
        border-block-start: 1px solid var(--accent);
        padding-inline-start: 0;
        padding-block-start: var(--space-2);

        & > .num {
          display: block;
          font-size: 2rem;
          margin-block-end: var(--space-1);
        }
      }
    }
  }

  /* Numbered steps (definition list with a counter, same marker style as summaries). */
  .steps {
    counter-reset: step;

    & > div + div {
      margin-block-start: var(--space-4);
    }

    & dt {
      display: flex;
      gap: var(--space-3);
      font-weight: 600;

      &::before {
        counter-increment: step;
        content: counter(step);
        flex: none;
        inline-size: 1.25rem;
        text-align: center;
        font-family: var(--font-mono);
        font-weight: 400;
        color: var(--accent);
      }
    }

    & dd {
      margin-block-start: var(--space-1);
      padding-inline-start: calc(1.25rem + var(--space-3));
    }
  }

  /* Sample calculation: one column per axis, ruled rows of topic values. */
  .sample-calc {
    display: grid;
    gap: var(--space-5);

    & dt {
      font-weight: 600;
      margin-block-end: var(--space-2);
    }

    & .rule-list > li {
      display: flex;
      justify-content: space-between;
      gap: var(--space-3);
      padding-block: var(--space-2);
      font-size: 0.9375rem;
    }

    & dd > p {
      margin-block-start: var(--space-2);
      font-family: var(--font-sans);
      font-size: 0.9375rem;
    }

    @media (min-width: 40rem) {
      grid-template-columns: 1fr 1fr;
    }
  }

  /* Dated versions as a vertical timeline: a 1 px rail, a square marker per entry
     (the newest in accent), date · version on one line and the note below. */
  .changelog {
    list-style: none;
    margin: 0;
    padding: 0;
    max-inline-size: var(--measure);
    border-inline-start: 1px solid var(--rule);

    & > li {
      position: relative;
      padding-inline-start: var(--space-5);
      padding-block-end: var(--space-5);

      &::before {
        content: '';
        position: absolute;
        inset-inline-start: -4px;
        inset-block-start: 5px;
        inline-size: 7px;
        block-size: 7px;
        background: var(--paper);
        border: 1px solid var(--ink);
      }

      &:first-child::before {
        background: var(--accent);
        border-color: var(--accent);
      }

      &:last-child {
        padding-block-end: 0;
      }
    }

    & .changelog-meta {
      display: flex;
      gap: var(--space-3);
      font-family: var(--font-sans);
      font-size: 0.875rem;
      line-height: 1.2;
      color: var(--muted);
    }

    & .changelog-meta + p {
      margin-block-start: var(--space-1);
      font-family: var(--font-serif);
      font-size: 1.0625rem;
      line-height: 1.5;
    }
  }

  /* Home call to action: taller, wider, with two caption lines under it. */
  .button--lg {
    min-block-size: 56px;
    padding-inline: var(--space-6);
    font-size: 1.0625rem;
  }

  /* Chart column: figure plus the period toggle, so the toggle stays under the chart
     however tall the copy column (with the party panel open) gets. */
  .hero-chart {
    display: grid;
    gap: var(--space-5);
    justify-items: start;
    /* Stays in view while the story (and the party panel) scrolls past, until the hero ends. */
    position: sticky;
    align-self: start;

    /* Phones: pinned under the header, compact enough to leave room for the text below.
       Caption, gap and toggle take about 7.75rem; the drawing gets what is left of 46dvh.
       The figure keeps its full width so the caption wraps in two lines, not three. */
    @media (width < 60rem) {
      inset-block-start: 57px;
      z-index: 5;
      gap: var(--space-3);
      padding-block: var(--space-2);
      justify-items: center;
      background: var(--paper);

      & .nolan-chart svg {
        inline-size: min(100%, max(14rem, calc(46dvh - 7.75rem)));
        margin-inline: auto;
      }

      /* Smaller drawing: party labels grow, axis labels stay out of their way. */
      & .nolan-chart .party text,
      & .nolan-chart .user-chip text {
        font-size: 17px;
      }

      & .nolan-chart .chart-label {
        font-size: 14px;
      }
    }

    @media (min-width: 60rem) {
      justify-items: center;
      inset-block-start: calc(57px + var(--space-5));
    }
  }

  .hero-copy {
    display: grid;
    gap: var(--space-6);
    align-content: start;

    & .prose > .button + .caption {
      margin-block-start: var(--space-3);
    }

    & .prose > .caption + .caption {
      margin-block-start: var(--space-1);
    }

    & .prose > .dateline + h1 {
      margin-block-start: var(--space-3);
    }
  }

  /* Newspaper dateline above the h1: place, date, version. */
  .dateline {
    letter-spacing: 0.01em;

    & time {
      color: var(--ink);
    }
  }

  /* Guided reading of the chart: three steps under the intro. Only the step at least half
     on screen reads in ink and carries the accent rule; the others sit back in muted. */
  .story {
    max-inline-size: var(--measure);
    border-block-start: 1px solid var(--rule);
    padding-block-start: var(--space-5);

    & .story-end {
      margin-block-start: var(--space-6);
      max-inline-size: 40ch;
    }

    /* Room under the last step so the pinned chart is still beside it when it is read. */
    @media (min-width: 60rem) {
      padding-block-end: 14dvh;
    }
  }

  .story-step {
    min-block-size: 38dvh;
    padding-block: var(--space-4) var(--space-6);
    padding-inline-start: var(--space-4);
    border-inline-start: 2px solid transparent;
    color: var(--muted);
    transition:
      color var(--duration),
      border-color var(--duration);

    & h2 {
      font-size: clamp(1.375rem, 1.15rem + 0.9vw, 1.75rem);
      max-inline-size: 26ch;
      color: inherit;
    }

    & p {
      margin-block-start: var(--space-3);
      max-inline-size: 52ch;
      font-family: var(--font-serif);
      font-size: 1.125rem;
      line-height: 1.6;
    }

    & .num {
      font-size: 0.9375rem;
    }

    &[aria-current='true'] {
      color: var(--ink);
      border-color: var(--accent);
    }

    @media (min-width: 60rem) {
      min-block-size: 46dvh;
      /* The accent rule hangs in the gutter so the text keeps the column's left edge. */
      margin-inline-start: calc(-1 * var(--space-4) - 2px);
    }
  }

  /* Nine party links in one row: swatch and short name, ruled border, hover inverts. */
  .party-strip {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-3) var(--space-5);
    border-block-start: 1px solid var(--rule);
    padding-block: var(--space-5);

    & > .caption {
      flex: none;
    }

    & ul {
      display: flex;
      flex-wrap: wrap;
      gap: var(--space-2);
      min-inline-size: 0;
    }

    & a {
      display: inline-flex;
      align-items: center;
      gap: var(--space-2);
      min-block-size: 44px;
      padding-inline: var(--space-3) var(--space-4);
      border: 1px solid var(--rule);
      border-radius: var(--radius);
      font-size: 0.9375rem;
      font-weight: 500;
      white-space: nowrap;
      text-decoration: none;
      transition:
        background-color var(--duration),
        border-color var(--duration),
        color var(--duration);

      &:hover {
        background: var(--ink);
        border-color: var(--ink);
        color: var(--paper);
      }
    }

    & .swatch {
      flex: none;
      inline-size: 10px;
      block-size: 10px;
    }

    /* Phones: one scrolling row, edge to edge, that snaps on the links. */
    @media (width < 60rem) {
      & ul {
        flex: 1 1 100%;
        flex-wrap: nowrap;
        overflow-x: auto;
        scroll-snap-type: x proximity;
        scrollbar-width: thin;
        margin-inline: calc(-1 * var(--space-4));
        padding-inline: var(--space-4);
        padding-block-end: var(--space-2);
      }

      & li {
        scroll-snap-align: start;
      }
    }
  }

  /* End of "Com es calcula": the methodology link and a quiet second call to the test. */
  .method-links {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-3) var(--space-5);
    font-family: var(--font-sans);

    & > a:not(.button) {
      display: inline-flex;
      align-items: center;
      min-block-size: 44px;
    }
  }

  /* Party panel: opens beside the chart on a plain click, under the hero copy at >= 60rem. */
  .party-panel {
    border-block-start: 1px solid var(--ink);
    padding-block-start: var(--space-4);
    font-family: var(--font-sans);

    &[hidden] {
      display: none;
    }
  }

  /* Same content as a bottom sheet on narrow screens. */
  .party-sheet {
    inline-size: 100%;
    max-inline-size: none;
    max-block-size: 88dvh;
    margin: auto 0 0;
    padding: var(--space-4) var(--space-4) var(--space-6);
    border: 0;
    border-block-start: 1px solid var(--ink);
    border-radius: var(--radius) var(--radius) 0 0;
    background: var(--paper);
    color: var(--ink);
    font-family: var(--font-sans);
    overflow: auto;

    &::backdrop {
      background: rgb(21 23 26 / 0.55);
    }
  }

  .party-panel,
  .party-sheet {
    & .panel-head {
      display: flex;
      align-items: flex-start;
      justify-content: space-between;
      gap: var(--space-3);
    }

    & .panel-title {
      display: flex;
      align-items: center;
      gap: var(--space-3);
      font-family: var(--font-serif);
      font-weight: 600;
      font-size: clamp(1.375rem, 1.1rem + 1vw, 1.75rem);
      line-height: 1.2;
      outline-offset: 4px;

      & .swatch {
        flex: none;
        inline-size: 14px;
        block-size: 14px;
      }
    }

    & .panel-close {
      flex: none;
      min-inline-size: 44px;
      padding-inline: var(--space-3);
    }

    & .panel-meta {
      margin-block-start: var(--space-1);

      & .num {
        font-size: 0.8125rem;
      }
    }

    & .panel-intro {
      margin-block-start: var(--space-4);
      font-family: var(--font-serif);
      font-size: 1.0625rem;
      line-height: 1.55;
    }

    & .panel-why {
      margin-block-start: var(--space-4);

      & h3 {
        font-family: var(--font-sans);
        font-size: 0.8125rem;
        font-weight: 600;
        letter-spacing: 0.02em;
        text-transform: uppercase;
        color: var(--muted);
        margin-block-end: var(--space-2);
      }

      & ul {
        display: grid;
        gap: var(--space-2);
        padding-inline-start: 1.1em;
        margin: 0;
        font-size: 0.9375rem;
        line-height: 1.5;
      }
    }

    & .panel-link {
      display: inline-flex;
      align-items: center;
      min-block-size: 44px;
      margin-block-start: var(--space-3);
      font-weight: 500;
    }
  }

  /* Dimension caption above each quiz question. */
  .quiz-dimension {
    margin-block-start: var(--space-4);
    font-weight: 500;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    font-size: 0.75rem;
  }

  /* Text-styled button (copy link) with a 44 px hit area. */
  .link-button {
    display: inline-flex;
    align-items: center;
    min-block-size: 44px;
    padding: 0;
    border: 0;
    background: none;
    color: var(--ink);
    font-family: var(--font-sans);
    font-size: 1rem;
    text-decoration: underline;
    text-underline-offset: 0.15em;
    cursor: pointer;

    &:hover {
      color: var(--accent);
    }
  }

  /* Share block sits right under the quadrant; the numbers block below draws the next rule. */
  .result-share {
    padding-block-end: var(--space-2);
  }

  .result-restart {
    display: inline-flex;
    align-items: center;
    min-block-size: 44px;
  }

  /* Proximity scale line ("71 % vol dir…") under the three parties. */
  .proximity-scale {
    margin-block-start: var(--space-3);
  }

  /* Light ink over dark paper reads fainter at the same mix; lift the quadrant tint a little. */
  @media (prefers-color-scheme: dark) {
    :root:not([data-theme='light']) .nolan-chart .chart-tint {
      fill: color-mix(in oklab, var(--ink) 8%, var(--paper));
    }
  }

  :root[data-theme='dark'] .nolan-chart .chart-tint {
    fill: color-mix(in oklab, var(--ink) 8%, var(--paper));
  }
}

/* ---------------------------------------------------------------------------
   Utilities
   --------------------------------------------------------------------------- */
@layer utilities {
  .visually-hidden {
    position: absolute;
    inline-size: 1px;
    block-size: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }
}

/* ---------------------------------------------------------------------------
   Reduced motion: the only permitted !important block. Keep it last.
   --------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation: none !important;
    transition: none !important;
    scroll-behavior: auto !important;
  }
}
