/* ==========================================================================
   Rankings das Escolas | Styles
   ==========================================================================

   CONTENTS
   1. Theme ............ every colour, font, size, radius and space. Change
                         the look here: the rest only uses these variables.
   2. Base ............. reset, helpers, page container
   3. Components ....... reusable pieces, used by every page:
                         buttons, form fields, tabs, chips, view toggle,
                         filter panel, cards, stats, bars, data tables, the
                         exam vs. internal grade chart, legends, trends,
                         help "i" and tooltip, loader
   4. Page intro and footer
   5. Rankings page .... results bar, list layout, municipality map card,
                         ranking table, "Mostrar mais", map view
   6. School shapes and markers (tables, legends, Leaflet map)
   7. Info panel ....... school details drawer
   8. Provas Moda and Ensino Profissional pages
   9. Chatbot page
   10. Coming soon page (before the rankings are published)

   Breakpoints (min-width unless noted):
     480px  phones (max-width 479px rules)
     768px  tablets
     1024px desktop: map card next to the list

   Every rule starts with .rankings-page: only that div goes to the
   newspaper's back office, and nothing here may restyle the rest of the
   newspaper's page. Class names never start with "icon-" or "i-" (publico.pt
   gives those its icon font) nor reuse the newspaper's (.btn, .content…).
   ========================================================================== */


/* ==========================================================================
   1. THEME
   ========================================================================== */

/* The two weights of PÚBLICO the titles use, bold and light (the second line
   of the page title), from the newspaper's CDN (which allows any origin), so
   they load on any page. Same family name and files as publico.pt's own
   rules, so on the site they are the same fonts. The only rules not under
   .rankings-page. */
@font-face {
  font-family: "Publico";
  src: url("https://static.publicocdn.com/files/site/assets/fonts/publico-bold.woff2") format("woff2"),
       url("https://static.publicocdn.com/files/site/assets/fonts/publico-bold.woff") format("woff");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Publico";
  src: url("https://static.publicocdn.com/files/site/assets/fonts/publico-light.woff2") format("woff2"),
       url("https://static.publicocdn.com/files/site/assets/fonts/publico-light.woff") format("woff");
  font-weight: 300;
  font-style: normal;
  font-display: swap;
}

.rankings-page {

  /* --- Text and surfaces ------------------------------------------------ */
  --color-text: #1a1a1a;
  --color-text-soft: #444;          /* body text of the panel, notes */
  --color-muted: #6b6b6b;           /* labels, meta lines, captions */
  --color-faint: #9a9a9a;           /* page footer, chart ticks */
  --color-background: #fff;
  --color-surface: #f6f6f4;         /* table heads, mini cards */
  --color-border: #e5e5e1;
  --color-border-strong: #cfcfca;

  /* --- Accent (blue, the base colour of the rankings) -------------------- */
  --color-accent: #363e96;          /* links, active chips */
  --color-accent-strong: #2a3078;   /* leading numbers: superação positions */
  --color-accent-fill: #363e96;     /* view toggle, active context, bars, exam dots */
  --color-accent-soft: #f1f2fa;     /* filter panel, summary box, notes */
  --color-accent-line: #d3d6ee;     /* borders on accent-soft areas */
  --color-on-accent: #fff;          /* text on accent-fill */

  /* --- Other meaning colours -------------------------------------------- */
  --color-dark: #1a1a1a;            /* dark buttons, retention bars */
  --color-internal: #e07b39;        /* internal grades (dots of the charts), apart from the exam dots */
  --color-up: #2f8550;              /* trend up: green, as down is red */
  --color-down: #c0392b;
  --color-same: var(--color-muted);
  --color-down-soft: #fbeeec;       /* message when a data file fails to load */
  --color-link: var(--color-accent);

  /* --- Tiers (maps, legends, markers) ----------------------------------- */
  /* DEFAULTS ONLY: js/shared.js copies tierColors from js/config.js here at
     load time, so change the palette there. 0 is the best tier, 4 "no data". */
  --color-tier-0: #2a2c29;
  --color-tier-1: #4a57a5;
  --color-tier-2: #3fc4cb;
  --color-tier-3: #edce50;
  --color-tier-4: #bec1c3;

  /* --- School shapes (schoolShapes in js/config.js) --------------------- */
  --color-shape-neutral: #bcbec0;   /* shapes without a tier (legends, Moda) */
  --color-shape-edge: #fff;

  /* --- Tooltips, overlays, maps ----------------------------------------- */
  --color-tooltip-bg: #1a1a1a;
  --color-tooltip-text: #fff;
  --color-overlay: rgba(255, 255, 255, 0.72);
  --color-overlay-loading: rgba(255, 255, 255, 0.9);
  --color-map-stroke: #fff;         /* municipality outlines */
  --color-map-dimmed: #eeeeee;      /* municipalities outside the district */
  --color-map-district: #cbcbcb;    /* district hover and inner lines */
  --color-marker-shadow: rgba(0, 0, 0, 0.3);

  /* --- Chatbot daily usage bar (thresholds in js/chatbot.js) ------------- */
  --color-usage-track: var(--color-border);
  --color-usage-ok: var(--color-accent-fill);
  --color-usage-warning: #debf24;
  --color-usage-high: var(--color-down);

  /* --- Typography ------------------------------------------------------- */
  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;   /* publico.pt's system font stack */
  --font-title: "Publico", Georgia, "Times New Roman", Times, serif;   /* PÚBLICO (bold, light; @font-face above): titles, school names of the panel, leading positions */
  --font-size-base: 16px;
  --font-size-small: 14px;
  --font-size-xsmall: 12px;
  --font-size-label: 10px;          /* uppercase labels of the filters */
  --font-size-title: 30px;          /* page title on phones */
  --font-size-title-large: 40px;    /* page title from 768px */
  --font-size-rank: 22px;           /* superação position in the table */
  --font-size-stat: 22px;           /* values of the info panel */
  --font-size-stat-big: 34px;       /* the two rankings of the info panel */

  /* --- Shape ------------------------------------------------------------ */
  --radius-small: 2px;
  --radius: 4px;                    /* fields, buttons of a group, cards */
  --radius-large: 4px;              /* panels: filters, map card, table */
  --radius-pill: 999px;
  --control-height: 40px;           /* fields and buttons */
  --shadow-panel: -2px 0 12px rgba(0, 0, 0, 0.12);

  /* --- Spacing ---------------------------------------------------------- */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;

  /* --- Icons and markers ------------------------------------------------ */
  --icon-school-type: 16px;         /* school shape inside a line of text (Moda tabs) */
  --icon-school-table: 24px;        /* school shape next to the name (Moda, Profissional) */
  --icon-school-legend: 22px;       /* school shapes of the type legend */
  --icon-help: 13px;                /* the "i" tooltip button */
  --icon-text-centre: 0.35em;       /* icons in text: centre above the baseline */
  --marker-size: 26px;              /* school markers on the Leaflet map */
  --cluster-count-top: 0%;          /* moves the count of a cluster down from the centre of its shape */
  --cluster-count-left: 0%;         /* and to the right */
  --cluster-size-small: 34px;       /* school clusters on the Leaflet map */
  --cluster-size-medium: 42px;
  --cluster-size-large: 52px;
  --legend-swatch-height: 10px;     /* colour bars of the tier legends */
  --bar-height: 8px;                /* bars of the info panel */
  --dot-size: 11px;                 /* dots of the exam vs. internal chart */

  /* --- Layout ----------------------------------------------------------- */
  --container-width: 1288px;
  --container-gutter: 16px;
  --intro-width: 680px;
  --map-card-width: 300px;
  --info-panel-width: 600px;
  --info-panel-width-wide: 100%;    /* the panel while comparing schools: the whole screen */
}


/* ==========================================================================
   2. BASE
   ========================================================================== */

/* The div is its own container (max-width 1288px, centred), so it can be
   pasted as is into a full-width page. The gutter keeps the content off the
   edges of small screens. */
.rankings-page {
  width: 100%;
  max-width: var(--container-width);
  margin: 0 auto;
  padding-left: var(--container-gutter);
  padding-right: var(--container-gutter);
  color: var(--color-text);
  font-family: var(--font);
  font-size: var(--font-size-base);
  line-height: 1.5;
}

.rankings-page,
.rankings-page *,
.rankings-page *::before,
.rankings-page *::after {
  box-sizing: border-box;
}

.rankings-page a {
  color: var(--color-link);
}

.rankings-page button,
.rankings-page select,
.rankings-page input {
  font: inherit;
}

/* Undo publico.pt's generic label, table and heading styles; components set
   their own. */
.rankings-page label {
  margin: 0;
  color: inherit;
  font-size: inherit;
  font-weight: inherit;
  line-height: inherit;
}

.rankings-page table {
  margin: 0;
  border-radius: 0;
}

.rankings-page h1,
.rankings-page h2,
.rankings-page h3,
.rankings-page p {
  margin-top: 0;
}

/* publico.pt sets every heading in Times ("h1, h2, h3… { font-family }"):
   ours use the page font, unless a component sets the title font. */
.rankings-page h1,
.rankings-page h2,
.rankings-page h3,
.rankings-page h4 {
  font-family: var(--font);
}

.rankings-page .hidden {
  display: none !important;
}

/* Text for screen readers only. */
.rankings-page .visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Copy of the page wrapper at the end of <body> that holds the panel, its
   overlay and the tooltip (getRankingsLayer in js/shared.js), above the
   newspaper's header and ads. It takes no room; its children are fixed. */
.rankings-page.rankings-layer {
  position: fixed;
  z-index: 2147483000;
  top: 0;
  left: 0;
  width: 0;
  max-width: none;
  height: 0;
  margin: 0;
  padding: 0;
}


/* ==========================================================================
   3. COMPONENTS
   ========================================================================== */

/* --- Buttons ------------------------------------------------------------ */
/* Not ".btn": publico.pt has its own .btn. Every property its button rules
   touch is set here too, so the newspaper's styles cannot change the look.
     .rankings-btn            outlined, rectangular
     .rankings-btn--pill      rounded ends
     .rankings-btn--dark      filled dark
     .rankings-btn--small     smaller */
.rankings-page .rankings-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: var(--control-height);
  margin: 0;
  padding: 0 var(--space-4);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius);
  background: var(--color-background);
  box-shadow: none;
  color: var(--color-text);
  font-family: var(--font);
  font-size: var(--font-size-small);
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: normal;
  text-align: center;
  text-transform: none;
  text-decoration: none;
  vertical-align: middle;
  -webkit-appearance: none;
  appearance: none;
  cursor: pointer;
  transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.rankings-page .rankings-btn:hover {
  border-color: var(--color-text);
}

.rankings-page .rankings-btn:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

.rankings-page .rankings-btn[disabled] {
  opacity: 0.45;
  pointer-events: none;
}

.rankings-page .rankings-btn--pill {
  border-radius: var(--radius-pill);
}

.rankings-page .rankings-btn--dark {
  background: var(--color-dark);
  border-color: var(--color-dark);
  color: var(--color-background);
}

.rankings-page .rankings-btn--dark:hover {
  background: var(--color-text-soft);
  border-color: var(--color-text-soft);
}

.rankings-page .rankings-btn--small {
  min-height: 30px;
  padding: 0 var(--space-3);
  font-size: var(--font-size-xsmall);
}

/* --- Form fields --------------------------------------------------------- */
/* publico.pt styles every select and input (Foundation forms): bottom
   margin, inset shadow, its own arrow, line height. Each of those is set
   here too; selects draw their own arrow (below). */
.rankings-page select,
.rankings-page input[type="search"],
.rankings-page input[type="text"] {
  width: 100%;
  height: var(--control-height);
  margin: 0;
  padding: 0 var(--space-3);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius);
  background: var(--color-background);
  box-shadow: none;
  color: var(--color-text);
  font-family: var(--font);
  font-size: var(--font-size-small);
  font-weight: 400;
  line-height: normal;
  -webkit-appearance: auto;
  appearance: auto;
}

/* The arrow of the selects: the same chevron in every browser, 12px from the
   edge (the browsers' own sits against it), with room for the text. Every
   background property is set, over publico.pt's arrow. */
.rankings-page select {
  padding-right: 36px;
  background-color: var(--color-background);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5l5 5 5-5' fill='none' stroke='%236b6b6b' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 12px 8px;
  background-origin: padding-box;
  -webkit-appearance: none;
  appearance: none;
}

.rankings-page select:focus-visible,
.rankings-page input:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 0;
  border-color: var(--color-accent);
}

.rankings-page select[disabled] {
  background-color: var(--color-surface);
  color: var(--color-faint);
}

/* A labelled field: uppercase label over the control. */
.rankings-page .filter-field {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 0;
}

.rankings-page .filter-label {
  font-size: var(--font-size-label);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-muted);
}

/* Search field with a magnifier inside. */
.rankings-page .search-box {
  position: relative;
  display: block;
}

.rankings-page .search-box__icon {
  position: absolute;
  top: 50%;
  left: var(--space-3);
  width: 15px;
  height: 15px;
  transform: translateY(-50%);
  color: var(--color-muted);
  pointer-events: none;
}

.rankings-page .search-box input {
  padding-left: 34px;
}

/* --- Tabs ---------------------------------------------------------------- */
/* A row of text tabs over a dark rule; the active one is bold and
   underlined. Used for the grades and the Moda sectors. */
.rankings-page .grade-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-5);
  margin: 0 0 var(--space-4);
  border-bottom: 2px solid var(--color-dark);
}

.rankings-page .grade-tabs button {
  position: relative;
  margin: 0;
  padding: var(--space-2) 0 var(--space-3);
  border: 0;
  background: transparent;
  color: var(--color-text);
  font-size: var(--font-size-small);
  font-weight: 400;
  text-transform: none;
  cursor: pointer;
}

.rankings-page .grade-tabs button.active {
  font-weight: 700;
}

.rankings-page .grade-tabs button.active::after {
  content: "";
  position: absolute;
  bottom: -2px;
  left: 0;
  width: 100%;
  height: 4px;
  background: var(--color-dark);
}

/* --- Chips --------------------------------------------------------------- */
/* Pills to pick one option; the chosen one is outlined in the accent with a
   tick, the others carry a "+". */
.rankings-page .chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.rankings-page .chips button {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 34px;
  margin: 0;
  padding: 0 var(--space-3) 0 var(--space-4);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-pill);
  background: var(--color-background);
  color: var(--color-text);
  font-size: var(--font-size-small);
  cursor: pointer;
}

.rankings-page .chips button::after {
  content: "+";
  font-size: 15px;
  line-height: 1;
  color: var(--color-muted);
}

.rankings-page .chips button.active {
  border-color: var(--color-accent);
  box-shadow: inset 0 0 0 1px var(--color-accent);
  background: var(--color-accent-soft);
  color: var(--color-accent-strong);
}

.rankings-page .chips button.active::after {
  content: "✓";
  color: var(--color-accent);
}

/* --- View toggle (segmented buttons) ----------------------------------- */
/* One accent block split by a thin line; the button on screen is bold. */
.rankings-page .view-toggle {
  display: inline-flex;
  overflow: hidden;
  border: 1px solid var(--color-accent-fill);
  border-radius: var(--radius-small);
  background: var(--color-accent-fill);
}

.rankings-page .view-toggle button {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 36px;
  margin: 0;
  padding: 0 var(--space-4);
  border: 0;
  border-radius: 0;
  background: transparent;
  color: var(--color-on-accent);
  font-size: var(--font-size-small);
  font-weight: 400;
  cursor: pointer;
}

.rankings-page .view-toggle button + button {
  border-left: 1px solid var(--color-border-strong);
}

.rankings-page .view-toggle svg {
  width: 15px;
  height: 15px;
}

.rankings-page .view-toggle button:hover {
  background: rgba(255, 255, 255, 0.2);
}

.rankings-page .view-toggle button.active {
  font-weight: 700;
}

/* --- Filter panel -------------------------------------------------------- */
/* A tinted box holding the filters, in rows that wrap. */
.rankings-page .filter-panel {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  margin: 0 0 var(--space-4);
  padding: var(--space-4);
  border-radius: var(--radius-large);
  background: var(--color-accent-soft);
}

.rankings-page .filter-panel__row {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--space-3) var(--space-4);
}

.rankings-page .filter-panel__row > .filter-field {
  flex: 1 1 180px;
}

.rankings-page .filter-panel__row > .filter-field--search {
  flex: 1 1 320px;
}

/* As wide as their buttons, but never wider than the row (the chips wrap). */
.rankings-page .filter-panel__row > .filter-field--view,
.rankings-page .filter-panel__row > .filter-field--type {
  flex: 0 1 auto;
}

/* The map view filters by school and place only, as last year's map (the
   type, context and subject change nothing on a map of all the schools). */
.rankings-page.view--mapa .filter-field--list-only {
  display: none;
}

/* Alone on the second row there, the municipality keeps the width it has in
   the list (about 290px on computers) instead of filling the row. The first
   row (search and view) stays as it is. */
@media (min-width: 600px) {
  .rankings-page.view--mapa .filter-panel__row + .filter-panel__row > .filter-field {
    flex: 0 1 290px;
  }
}

@media (min-width: 768px) {
  .rankings-page .filter-panel {
    padding: var(--space-4) var(--space-5) var(--space-5);
  }
}

/* --- Cards and stats ----------------------------------------------------- */
/* .stat: a small label over a big value. .stat-grid lays them two by two
   (three with --3); .stat-card is a bordered card; .mini-card a smaller one. */
.rankings-page .stat__label,
.rankings-page .stat-card__label {
  margin: 0 0 var(--space-1);
  font-size: var(--font-size-small);
  line-height: 1.35;
  color: var(--color-muted);
}

.rankings-page .stat__value {
  margin: 0;
  font-size: var(--font-size-stat);
  font-weight: 700;
  line-height: 1.2;
}

.rankings-page .stat-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-4) var(--space-5);
  margin: var(--space-4) 0;
}

.rankings-page .stat .trend {
  margin-top: var(--space-1);
}

.rankings-page .stat-cards {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-3);
  margin: var(--space-4) 0;
}

.rankings-page .stat-card {
  padding: var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-large);
}

/* "▲ 9 lugares face a 2024 (33.º)" wraps inside the narrow cards of phones. */
.rankings-page .stat-card .trend {
  white-space: normal;
}

.rankings-page .stat-card__value {
  margin: var(--space-1) 0;
  font-family: var(--font-title);
  font-size: var(--font-size-stat-big);
  font-weight: 700;
  line-height: 1.1;
}

.rankings-page .stat-card__note {
  margin: 0;
  font-size: var(--font-size-xsmall);
  color: var(--color-muted);
}

.rankings-page .mini-cards {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-3);
  margin: var(--space-2) 0 var(--space-4);
}

.rankings-page .mini-card {
  padding: var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
}

.rankings-page .mini-card .stat__value {
  margin-bottom: var(--space-2);
}

@media (max-width: 479px) {
  .rankings-page .mini-cards {
    gap: var(--space-2);
  }

  .rankings-page .mini-card {
    padding: var(--space-2);
  }
}

/* --- Bars ---------------------------------------------------------------- */
/* .bar: a track with a fill (width set inline). .bar-row: label, bar and
   value on one line; .bar-chart stacks them. */
.rankings-page .bar {
  display: block;
  height: var(--bar-height);
  overflow: hidden;
  border-radius: var(--radius-pill);
  background: var(--color-border);
}

.rankings-page .bar__fill {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: var(--color-accent-fill);
}

.rankings-page .bar__fill--muted { background: var(--color-accent-fill); opacity: 0.55; }
.rankings-page .bar__fill--accent { background: var(--color-accent-fill); }
.rankings-page .bar__fill--dark { background: var(--color-dark); }
.rankings-page .bar__fill--internal { background: var(--color-internal); }

.rankings-page .bar-chart {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin: var(--space-3) 0;
}

.rankings-page .bar-row {
  display: grid;
  grid-template-columns: minmax(110px, 38%) 1fr auto;
  align-items: center;
  gap: var(--space-3);
  font-size: var(--font-size-small);
}

.rankings-page .bar-row__value {
  min-width: 52px;
  font-weight: 700;
  text-align: right;
}

/* --- Data tables --------------------------------------------------------- */
/* A rounded, bordered table with a tinted head. Number cells: .num (right
   aligned), .num--strong (bold), .num--muted (grey). */
.rankings-page .data-table-wrap {
  overflow-x: auto;
  margin: var(--space-3) 0;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-large);
}

.rankings-page .data-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--font-size-small);
}

.rankings-page .data-table th,
.rankings-page .data-table td {
  padding: 10px var(--space-3);
  text-align: left;
  vertical-align: middle;
  white-space: nowrap;
}

.rankings-page .data-table thead th,
.rankings-page .data-table thead td {
  background: var(--color-surface);
  font-size: var(--font-size-label);
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--color-muted);
}

.rankings-page .data-table tbody tr + tr th,
.rankings-page .data-table tbody tr + tr td {
  border-top: 1px solid var(--color-border);
}

.rankings-page .data-table tbody th {
  font-weight: 400;
  /* Long row names ("História e Geografia de Portugal") wrap. */
  white-space: normal;
}

.rankings-page .data-table tfoot td {
  border-top: 1px solid var(--color-border);
  background: var(--color-surface);
  font-size: var(--font-size-label);
  color: var(--color-muted);
}

.rankings-page .data-table .num {
  text-align: right;
}

.rankings-page .data-table .num--strong {
  font-weight: 700;
}

.rankings-page .data-table .num--muted {
  color: var(--color-muted);
}

/* --- Exam vs. internal grade chart ("dumbbell") --------------------------- */
/* Two dots on a scale (left set inline, in %) joined by a line. */
.rankings-page .chart-cell {
  width: 34%;
  min-width: 120px;
}

.rankings-page .dumbbell {
  position: relative;
  display: block;
  height: var(--dot-size);
  margin: 0 calc(var(--dot-size) / 2);
}

.rankings-page .dumbbell::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--color-border);
}

.rankings-page .dumbbell--empty::before {
  display: none;
}

.rankings-page .dumbbell__line {
  position: absolute;
  top: 50%;
  height: 2px;
  margin-top: -1px;
  background: var(--color-muted);
}

.rankings-page .dumbbell__dot {
  position: absolute;
  top: 0;
  width: var(--dot-size);
  height: var(--dot-size);
  margin-left: calc(var(--dot-size) / -2);
  border-radius: 50%;
}

.rankings-page .dumbbell__dot--exam {
  background: var(--color-accent-fill);
}

.rankings-page .dumbbell__dot--internal {
  background: var(--color-internal);
}

.rankings-page .dumbbell-scale {
  position: relative;
  display: block;
  height: 14px;
  margin: 0 calc(var(--dot-size) / 2);
}

.rankings-page .dumbbell-scale span {
  position: absolute;
  transform: translateX(-50%);
}

/* --- Dots and their legend ---------------------------------------------- */
.rankings-page .dot {
  display: inline-block;
  width: 9px;
  height: 9px;
  margin-right: 6px;
  border-radius: 50%;
  vertical-align: 0.05em;
}

.rankings-page .dot--exam { background: var(--color-accent-fill); }
.rankings-page .dot--internal { background: var(--color-internal); }

.rankings-page .dot-legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  margin: var(--space-3) 0;
  padding: 0;
  list-style: none;
  font-size: var(--font-size-small);
}

/* --- Tier legend --------------------------------------------------------- */
/* A row of colour bars with the range under each one, generated from
   rankingTiers by renderTierLegend (js/shared.js). */
.rankings-page .map-legend {
  display: flex;
  margin: 0 0 var(--space-3);
  padding: 0;
  list-style: none;
  font-size: var(--font-size-label);
  color: var(--color-muted);
}

.rankings-page .map-legend li {
  flex: 1 1 0;
  padding: 0 1px;
  text-align: center;
  white-space: nowrap;
}

.rankings-page .map-legend .map-legend-title {
  display: none;
}

.rankings-page .map-legend-icon {
  display: block;
  height: var(--legend-swatch-height);
  margin-bottom: var(--space-1);
  border-radius: 2px;
  /* No background here: each swatch carries a "tier-N" class (see below). */
}

.rankings-page .tier-0 { background: var(--color-tier-0); }
.rankings-page .tier-1 { background: var(--color-tier-1); }
.rankings-page .tier-2 { background: var(--color-tier-2); }
.rankings-page .tier-3 { background: var(--color-tier-3); }
.rankings-page .tier-4 { background: var(--color-tier-4); }

/* School type legend: a shape before each label. */
.rankings-page .type-legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: var(--font-size-xsmall);
  color: var(--color-muted);
}

.rankings-page .type-legend li {
  display: flex;
  align-items: center;
  gap: 6px;
}

/* --- Trends ("▲ 3 face a 2024") ----------------------------------------- */
.rankings-page .trend {
  display: block;
  margin: 0;
  font-size: var(--font-size-xsmall);
  font-weight: 600;
  line-height: 1.3;
  white-space: nowrap;
}

.rankings-page .trend--up { color: var(--color-up); }
.rankings-page .trend--down { color: var(--color-down); }
.rankings-page .trend--same,
.rankings-page .trend--none { color: var(--color-same); font-weight: 400; }

/* --- Positions ----------------------------------------------------------- */
/* .rank: a position ("50.º"); .rank--lead: the leading one (superação), in
   the title font and the accent. */
.rankings-page .rank {
  font-weight: 700;
}

.rankings-page .rank--lead {
  font-family: var(--font-title);
  font-size: var(--font-size-rank);
  color: var(--color-accent-strong);
}

.rankings-page .stat-card__value.rank--lead {
  font-size: var(--font-size-stat-big);
}

/* --- Help "i" and its tooltip ------------------------------------------- */
/* Centred on the text: the bottom of the box is its baseline (overflow:
   hidden) and vertical-align raises its centre --icon-text-centre above the
   text baseline, in em so it follows each label. The tooltip is one element
   in the layer (initTooltips in js/shared.js), with the text of data-tip. */
.rankings-page .help {
  display: inline-block;
  box-sizing: border-box;
  overflow: hidden;
  width: var(--icon-help);
  height: var(--icon-help);
  border: 1px solid currentColor;
  border-radius: 50%;
  color: var(--color-muted);
  vertical-align: calc(var(--icon-text-centre) - var(--icon-help) / 2);
  cursor: help;
}

.rankings-page .help::before {
  content: "i";
  display: block;
  font-size: 9px;
  font-weight: 700;
  line-height: calc(var(--icon-help) - 2px);
  text-align: center;
}

.rankings-page .help:hover {
  color: var(--color-accent);
}

.rankings-page .help:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 1px;
}

/* Last word of a label and its "i" (renderLabelWithHelp): never split. */
.rankings-page .label-end {
  white-space: nowrap;
}

.rankings-page .tooltip {
  position: fixed;
  z-index: 9500;
  max-width: 280px;
  padding: var(--space-2) 10px;
  border-radius: var(--radius-small);
  background: var(--color-tooltip-bg);
  color: var(--color-tooltip-text);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.25);
  font-size: var(--font-size-xsmall);
  font-weight: 400;
  line-height: 1.4;
  text-align: left;
  text-transform: none;
  letter-spacing: normal;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity 0.15s ease;
}

.rankings-page .tooltip.is-visible {
  opacity: 1;
  visibility: visible;
}

/* --- Loader -------------------------------------------------------------- */
.rankings-page .infographic {
  position: relative;
  padding-bottom: var(--space-4);
}

.rankings-page .loader {
  display: none;
  position: absolute;
  z-index: 10;
  inset: 0;
  background: var(--color-overlay-loading);
  cursor: wait;
}

.rankings-page .infographic.is-loading .loader {
  display: block;
}

.rankings-page .loader__spinner {
  width: 24px;
  height: 24px;
  margin: 136px auto 0;
  border: 3px solid rgba(50, 50, 50, 0.64);
  border-bottom-color: rgba(50, 50, 50, 0.2);
  border-radius: 50%;
  animation: rankings-spin 0.7s linear infinite;
}

@keyframes rankings-spin {
  to {
    transform: rotate(360deg);
  }
}


/* ==========================================================================
   4. PAGE INTRO AND FOOTER
   ========================================================================== */

/* Every page: aligned with the content, on the left. */
.rankings-page .page-intro {
  max-width: var(--intro-width);
  margin: var(--space-6) 0 var(--space-5);
}

.rankings-page .page-title {
  margin: 0 0 var(--space-3);
  font-family: var(--font-title);
  font-size: var(--font-size-title);
  font-weight: 700;
  line-height: 1.12;
}

/* Second line of the title: the same PÚBLICO family, light. */
.rankings-page .page-title__light {
  display: block;
  margin-top: var(--space-1);
  font-family: var(--font-title);
  font-weight: 300;
}

@media (min-width: 768px) {
  .rankings-page .page-title {
    font-size: var(--font-size-title-large);
  }
}

.rankings-page .page-blurb {
  margin: 0 0 var(--space-3);
  font-size: var(--font-size-small);
  line-height: 1.55;
  color: var(--color-text-soft);
}

/* "Edições anteriores 2024 2023 …" on one line. */
.rankings-page .past-versions {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2) var(--space-4);
  font-size: var(--font-size-xsmall);
}

.rankings-page .past-versions p {
  margin: 0;
  color: var(--color-muted);
}

.rankings-page .past-versions ul {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin: 0;
  padding: 0;
  list-style: none;
}

.rankings-page .past-versions a {
  color: var(--color-accent);
  text-underline-offset: 2px;
}

/* Methodology note before the credits, one per grade: the grade class on
   #rankings-page (set by js/lists.js) shows the right one. */
.rankings-page .grade-notes {
  margin: var(--space-2) 0 var(--space-4);
  padding-top: var(--space-4);
  border-top: 1px solid var(--color-border);
}

.rankings-page .grade-note {
  margin: 0;
  font-size: var(--font-size-xsmall);
  line-height: 1.5;
  color: var(--color-muted);
}

.rankings-page.grade--9ano .grade-note--sec,
.rankings-page.grade--sec .grade-note--9ano {
  display: none;
}

.rankings-page .page-footer {
  margin-top: var(--space-2);
  padding: var(--space-5) 0 var(--space-2);
  border-top: 1px solid var(--color-border);
  font-size: var(--font-size-xsmall);
  line-height: 18px;
  color: var(--color-faint);
  text-align: center;
}

.rankings-page .page-footer p {
  margin: 0 0 var(--space-2);
}

.rankings-page .page-footer strong {
  font-size: 11px;
  text-transform: uppercase;
}


/* ==========================================================================
   5. RANKINGS PAGE
   ========================================================================== */

/* --- Results bar, hint ---------------------------------------------------- */
.rankings-page .results-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2) var(--space-4);
  margin: var(--space-4) 0 var(--space-2);
}

.rankings-page .results-bar > .rankings-btn {
  margin-left: auto;
}

.rankings-page .results-count {
  margin: 0;
  font-size: var(--font-size-small);
  color: var(--color-muted);
}

.rankings-page .results-count strong {
  color: var(--color-text);
}

.rankings-page .results-hint {
  margin: 0 0 var(--space-4);
  font-size: var(--font-size-xsmall);
  color: var(--color-muted);
}

.rankings-page .results-hint__icon {
  display: inline-block;
  width: 13px;
  height: 13px;
  margin-right: 6px;
  border: 1px solid var(--color-accent);
  border-radius: 50%;
  color: var(--color-accent);
  font-size: 9px;
  font-weight: 700;
  line-height: 11px;
  text-align: center;
  vertical-align: 0;
}

.rankings-page .help--inline {
  cursor: default;
}

/* --- Layout: map card on the left, table on the right ---------------------- */
.rankings-page .rankings-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-5);
  align-items: start;
}

@media (min-width: 1024px) {
  .rankings-page .rankings-layout {
    grid-template-columns: var(--map-card-width) minmax(0, 1fr);
  }
}

.rankings-page .rankings-layout__table {
  min-width: 0;
}

/* --- Municipality map card ------------------------------------------------ */
/* Follows the page while the table scrolls (sticky). Phones and tablets use
   the map view instead. */
.rankings-page .map-card {
  display: none;
  padding: var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-large);
  background: var(--color-background);
}

@media (min-width: 1024px) {
  .rankings-page .map-card {
    display: block;
    position: sticky;
    top: var(--space-4);
  }
}

.rankings-page .map-card__title {
  margin: 0 0 var(--space-3);
  font-family: var(--font-title);
  font-size: 17px;
  font-weight: 700;
  line-height: 1.25;
}

.rankings-page .map-card__note {
  margin: 0 0 var(--space-3);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius);
  background: var(--color-accent-soft);
  color: var(--color-accent-strong);
  font-size: var(--font-size-xsmall);
  line-height: 1.4;
}

.rankings-page .map-card__foot {
  margin: var(--space-3) 0 0;
  font-size: var(--font-size-label);
  color: var(--color-muted);
}

.rankings-page .map-actions {
  display: flex;
  justify-content: center;
  gap: var(--space-2);
}

.rankings-page .map-actions:has(.rankings-btn:not(.hidden)) {
  margin-bottom: var(--space-3);
}

/* The SVG map (paths from data/ptPt.json, fills set by js/lists.js). Only
   ".map-svg": a bare ".map-canvas svg" would also hit Leaflet's SVGs. */
.rankings-page .map-svg {
  display: block;
  width: 100%;
  height: auto;
}

.rankings-page .map-municipality {
  stroke: var(--color-map-stroke);
  stroke-width: 0;
  cursor: pointer;
  transition: fill 0.25s ease;
}

.rankings-page .map-municipality:hover {
  fill-opacity: 0.8;
}

.rankings-page .map-municipality.is-dimmed {
  fill: var(--color-map-dimmed);
  pointer-events: none;
}

.rankings-page .map-municipality.is-selected {
  stroke-width: 4;
}

.rankings-page .map-district {
  fill: var(--color-map-district);
  fill-opacity: 0;
  stroke: var(--color-map-stroke);
  stroke-width: 1;
  cursor: pointer;
}

.rankings-page .map-district:hover {
  fill-opacity: 0.2;
}

.rankings-page .map-district.is-hidden {
  opacity: 0;
  pointer-events: none;
}

.rankings-page .map-lines {
  fill: none;
  stroke: var(--color-map-district);
  stroke-width: 0.5;
}

/* --- Ranking table --------------------------------------------------------- */
/* Columns: superação | school (name and meta line) | average | face ao
   esperado | exam ranking with the change since the previous edition.
   Also used, with their own columns, by the Moda and Profissional pages. */
.rankings-page .ranking-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-large);
  font-size: var(--font-size-small);
  overflow: hidden;
}

.rankings-page .ranking-table th,
.rankings-page .ranking-table td {
  padding: var(--space-3);
  text-align: left;
  vertical-align: middle;
}

.rankings-page .ranking-table thead th {
  background: var(--color-surface);
  font-size: var(--font-size-label);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: none;
  color: var(--color-muted);
  white-space: nowrap;
}

.rankings-page .ranking-table th[data-sort] {
  cursor: pointer;
  user-select: none;
}

.rankings-page .ranking-table th[data-sort]:hover,
.rankings-page .ranking-table th.sorted-asc,
.rankings-page .ranking-table th.sorted-desc {
  color: var(--color-text);
}

.rankings-page .ranking-table th.sorted-asc::after {
  content: " ↓";
}

.rankings-page .ranking-table th.sorted-desc::after {
  content: " ↑";
}

.rankings-page .ranking-table tbody td {
  border-top: 1px solid var(--color-border);
}

.rankings-page .ranking-table tbody tr {
  cursor: pointer;
}

.rankings-page .ranking-table tbody tr:hover td {
  background: var(--color-surface);
}

.rankings-page .ranking-table tbody tr:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: -2px;
}

.rankings-page .ranking-table tbody tr.empty {
  cursor: default;
}

.rankings-page .ranking-table .col-superacao {
  width: 1%;
  white-space: nowrap;
}

.rankings-page .ranking-table .col-mean,
.rankings-page .ranking-table .col-expected,
.rankings-page .ranking-table .col-ranking {
  text-align: right;
  white-space: nowrap;
}

.rankings-page .ranking-table thead .col-mean,
.rankings-page .ranking-table thead .col-expected,
.rankings-page .ranking-table thead .col-ranking {
  text-align: right;
}

.rankings-page .ranking-table .col-expected {
  font-weight: 700;
}

.rankings-page .ranking-table .col-ranking .rank {
  display: block;
}

.rankings-page .school-cell__name {
  display: block;
  font-weight: 700;
  line-height: 1.3;
}

.rankings-page .school-cell__meta {
  display: block;
  margin-top: 2px;
  font-size: var(--font-size-label);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-muted);
}

/* Header labels with a full and a short version (Moda, Profissional). */
.rankings-page .ranking-table .label-short {
  display: none;
}

/* Phones: superação, school and exam ranking; the average and the
   difference move under the school name (the meta line shows the type and
   municipality). */
@media (max-width: 599px) {
  .rankings-page .ranking-table th,
  .rankings-page .ranking-table td {
    padding: 10px var(--space-2);
  }

  .rankings-page .ranking-table .col-mean,
  .rankings-page .ranking-table .col-expected {
    display: none;
  }

  .rankings-page .ranking-table thead .help {
    display: none;
  }

  .rankings-page .ranking-table .label-full {
    display: none;
  }

  .rankings-page .ranking-table .label-short {
    display: inline;
  }

  .rankings-page .rank--lead {
    font-size: 18px;
  }
}

/* --- Rankings list on phones: help, tap note and one card per school ------ */
/* Computers read the columns with the "i" of the head (hover); phones open
   "Como ler este ranking" instead, and get a card per school (the col-card
   cell holds its values; it is hidden on computers). */
.rankings-page .results-hint__toggle {
  display: none;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: var(--color-link);
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}

.rankings-page .results-hint__separator,
.rankings-page .results-tap,
.rankings-page .sort-field,
.rankings-page .ranking-table .col-card {
  display: none;
}

.rankings-page .results-help {
  margin: calc(var(--space-2) * -1) 0 var(--space-4);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--color-accent-line);
  border-radius: var(--radius);
  background: var(--color-accent-soft);
  font-size: var(--font-size-xsmall);
  line-height: 1.45;
}

.rankings-page .results-help dt {
  font-weight: 700;
}

.rankings-page .results-help dd {
  margin: 0 0 var(--space-2);
}

.rankings-page .results-help dd:last-child {
  margin-bottom: 0;
}

@media (min-width: 600px) {
  .rankings-page .results-help {
    display: none !important;
  }
}

@media (max-width: 599px) {
  .rankings-page .results-hint__desktop {
    display: none;
  }

  .rankings-page .results-hint__toggle,
  .rankings-page .results-hint__separator {
    display: inline;
  }

  .rankings-page .results-tap {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin: 0 0 var(--space-4);
    padding: 10px var(--space-3);
    border-radius: var(--radius);
    background: var(--color-accent-soft);
    color: var(--color-accent-strong);
    font-size: var(--font-size-small);
  }

  .rankings-page .results-tap svg {
    flex: none;
    width: 20px;
    height: 20px;
    color: var(--color-accent);
  }

  /* "Tocar": the cursor comes in and presses, the rays light up around its
     tip, then a pause. Still for readers who ask for less motion. */
  .rankings-page .tap-icon__cursor,
  .rankings-page .tap-icon__burst {
    transform-box: fill-box;
  }

  .rankings-page .tap-icon__cursor {
    transform-origin: 0 0;
    animation: rankings-tap-cursor 1.7s ease-in-out infinite;
  }

  .rankings-page .tap-icon__burst {
    transform-origin: 100% 100%;
    animation: rankings-tap-burst 1.7s ease-out infinite;
  }

  @media (prefers-reduced-motion: reduce) {
    .rankings-page .tap-icon__cursor,
    .rankings-page .tap-icon__burst {
      animation: none;
    }
  }

  /* "Ordenar por": the cards hide the table head, which sorts on computers. */
  .rankings-page .sort-field {
    display: flex;
    margin: 0 0 var(--space-3);
  }

  /* Cards: position, school and an arrow; under them, the three values. */
  .rankings-page .ranking-table--cards,
  .rankings-page .ranking-table--cards tbody {
    display: block;
    border: 0;
    border-radius: 0;
    overflow: visible;
  }

  .rankings-page .ranking-table--cards thead {
    display: none;
  }

  .rankings-page .ranking-table--cards tbody tr {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    column-gap: var(--space-3);
    margin-bottom: var(--space-2);
    padding: var(--space-4);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-large);
    background: var(--color-background);
  }

  .rankings-page .ranking-table--cards tbody tr::after {
    content: "›";
    grid-row: 1;
    grid-column: 3;
    font-size: 24px;
    line-height: 1;
    color: var(--color-muted);
  }

  .rankings-page .ranking-table--cards tbody tr.empty {
    display: block;
  }

  .rankings-page .ranking-table--cards tbody tr.empty::after {
    content: none;
  }

  .rankings-page .ranking-table--cards tbody td {
    padding: 0;
    border-top: 0;
    background: none;
  }

  .rankings-page .ranking-table--cards tbody tr:hover {
    background: var(--color-surface);
  }

  .rankings-page .ranking-table--cards tbody tr:hover td {
    background: none;
  }

  .rankings-page .ranking-table--cards .col-superacao {
    grid-row: 1;
    grid-column: 1;
  }

  .rankings-page .ranking-table--cards .col-name {
    grid-row: 1;
    grid-column: 2;
  }

  .rankings-page .ranking-table--cards .col-mean,
  .rankings-page .ranking-table--cards .col-expected,
  .rankings-page .ranking-table--cards .col-ranking {
    display: none;
  }

  .rankings-page .ranking-table--cards .col-card {
    display: grid;
    grid-column: 1 / -1;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    grid-template-rows: auto auto;
    gap: 2px var(--space-2);
    margin-top: var(--space-3);
    padding-top: var(--space-3);
    border-top: 1px solid var(--color-border);
  }

  /* Label and value on the card's two rows, so the values line up even when
     a label takes two lines on small phones. */
  .rankings-page .card-stat {
    display: grid;
    grid-row: span 2;
    grid-template-rows: subgrid;
    align-items: end;
  }

  .rankings-page .card-stat__value {
    align-self: start;
  }

  .rankings-page .card-stat__label {
    display: block;
    margin-bottom: 2px;
    font-size: var(--font-size-xsmall);
    color: var(--color-muted);
  }

  .rankings-page .card-stat__value {
    display: block;
    font-weight: 700;
  }

  .rankings-page .card-stat__value .rank {
    display: block;
  }

  .rankings-page .card-stat__value .trend {
    font-weight: 600;
  }

  .rankings-page .ranking-table--cards .rank--lead {
    font-size: var(--font-size-rank);
  }
}

/* Keyframes of the tap icon (.tap-icon above). Their names carry the
   "rankings-" prefix: keyframes are global, outside .rankings-page. */
@keyframes rankings-tap-cursor {
  0%, 15% { transform: translate(3px, 3px); }
  35% { transform: translate(0, 0) scale(1); }
  42% { transform: translate(0, 0) scale(0.88); }
  50%, 75% { transform: translate(0, 0) scale(1); }
  100% { transform: translate(3px, 3px); }
}

@keyframes rankings-tap-burst {
  0%, 38% { opacity: 0; transform: scale(0.5); }
  48% { opacity: 1; transform: scale(1); }
  70% { opacity: 1; transform: scale(1.05); }
  85%, 100% { opacity: 0; transform: scale(1.05); }
}

/* --- "Mostrar mais" -------------------------------------------------------- */
.rankings-page .table-more {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  margin: var(--space-5) 0 var(--space-2);
}

.rankings-page .table-info {
  margin: 0;
  font-size: var(--font-size-xsmall);
  color: var(--color-muted);
}

/* --- Map view (Leaflet) ------------------------------------------------- */
.rankings-page .map-view__bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3) var(--space-5);
  margin-bottom: var(--space-3);
}

.rankings-page .map-legend--inline {
  flex: 1 1 280px;
  max-width: 420px;
  margin: 0;
}

.rankings-page .map-holder {
  position: relative;
  overflow: hidden;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-large);
}

.rankings-page .map-holder .map-canvas {
  height: calc(100vh - 220px);
  min-height: 420px;
}

/* OpenStreetMap tiles in light grey, so the school colours stand out. */
.rankings-page .map-holder .leaflet-tile-pane {
  filter: grayscale(1) contrast(0.85) brightness(1.08);
  opacity: 0.75;
}

/* "Ver todo o país", visible once the map is zoomed in. */
.rankings-page .map-holder .btn-map-reset {
  position: absolute;
  z-index: 500;
  top: 10px;
  right: 10px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s ease;
}

.rankings-page .map-holder.zoomed .btn-map-reset {
  opacity: 1;
  pointer-events: auto;
}

/* Overlay while the browser looks up the reader's position. */
.rankings-page .map-holder.is-locating::after {
  content: "";
  position: absolute;
  z-index: 600;
  inset: 0;
  background: rgba(255, 255, 255, 0.6);
  cursor: wait;
}


/* ==========================================================================
   6. SCHOOL SHAPES AND MARKERS
   School shapes (public, private, cluster) are SVG files set in js/config.js
   ("schoolShapes"), drawn inline and painted here in the tier colour (or
   grey without one). If the files fail, they are drawn as circles.
   ========================================================================== */

.rankings-page .school-shape {
  display: inline-block;
  flex: 0 0 auto;
  width: var(--icon-school-type);
  height: var(--icon-school-type);
  margin-right: var(--space-1);
  color: var(--color-shape-neutral);
  vertical-align: calc(var(--icon-text-centre) - var(--icon-school-type) / 2);
}

.rankings-page .school-shape__svg {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
}

.rankings-page .school-shape__svg * {
  fill: currentColor;
  stroke: var(--color-shape-edge);
  stroke-width: 2px;
  stroke-linecap: square;
  stroke-linejoin: round;
}

.rankings-page .school-shape--tier-0 { color: var(--color-tier-0); }
.rankings-page .school-shape--tier-1 { color: var(--color-tier-1); }
.rankings-page .school-shape--tier-2 { color: var(--color-tier-2); }
.rankings-page .school-shape--tier-3 { color: var(--color-tier-3); }
.rankings-page .school-shape--tier-4 { color: var(--color-tier-4); }

.rankings-page.school-shapes-failed .school-shape:empty {
  border-radius: 50%;
  background: currentColor;
}

.rankings-page .school-shape--legend {
  width: var(--icon-school-legend);
  height: var(--icon-school-legend);
  margin-right: 0;
  vertical-align: middle;
}

/* Icon and school name in a table (Moda, Profissional): a flex row so the
   icon stays centred on a name of two lines. */
/* Leaflet markers: the school shape in its tier colour, with a shadow that
   follows its outline. No "position": Leaflet places markers absolutely. */
.rankings-page .school-marker {
  background: transparent;
  border: 0;
  filter: drop-shadow(0 0 1px var(--color-marker-shadow));
  transition: opacity 0.25s ease;
}

.rankings-page .school-marker:hover {
  opacity: 0.8;
}

.rankings-page .school-marker .school-shape {
  display: block;
  width: 100%;
  height: 100%;
  margin: 0;
}

/* Clusters: the cluster shape in the dominant tier, with the count on it. */
.rankings-page .school-cluster {
  display: flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  padding-top: var(--cluster-count-top);
  padding-left: var(--cluster-count-left);
  color: #fff;
  font-weight: 700;
  line-height: 1;
  filter: drop-shadow(0 1px 2px var(--color-marker-shadow));
  transition: opacity 0.25s ease;
}

.rankings-page .school-cluster:hover {
  opacity: 0.85;
}

.rankings-page .school-cluster--small { font-size: 12px; }
.rankings-page .school-cluster--medium { font-size: 13px; }
.rankings-page .school-cluster--large { font-size: 14px; }

.rankings-page .school-cluster .school-shape {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  margin: 0;
}

/* No inner edges on clusters, so the count never crosses a line. */
.rankings-page .school-cluster .school-shape__svg *,
.rankings-page .school-shape--silhouette .school-shape__svg * {
  stroke: currentColor;
}

.rankings-page .school-cluster__count {
  position: relative;
  text-shadow: 0 0 3px rgba(0, 0, 0, 0.6);
}

.rankings-page.school-shapes-failed .school-cluster {
  padding-top: 0;
  padding-left: 0;
}


/* ==========================================================================
   7. INFO PANEL (school details drawer)
   Built by renderInfoPanel (js/shared.js) and, for Provas Moda, by
   js/moda.js. Uses the components of section 3.
   ========================================================================== */

.rankings-page .info-overlay {
  display: none;
  position: fixed;
  z-index: 9000;
  inset: 0;
  background: var(--color-overlay);
}

/* Set by js/shared.js and js/moda.js while the info panel is open. */
.rankings-page.is-panel-open .info-overlay {
  display: block;
}

.rankings-page .info-panel {
  position: fixed;
  z-index: 9001;
  top: 0;
  right: 0;
  bottom: 0;
  width: var(--info-panel-width);
  max-width: 100%;
  background: var(--color-background);
  box-shadow: var(--shadow-panel);
  transform: translateX(110%);
  /* The width eases between the ficha and the comparison (.info-panel--wide). */
  transition: transform 0.35s ease-out, width 0.35s ease-out;
}

.rankings-page .info-panel.open {
  transform: translateX(0);
}

/* Set by showPanelContent (js/shared.js) when the open panel goes from the
   ficha to the comparison or back: the new content fades in once the panel
   has changed width, so it reads as the same panel growing, not a new page. */
.rankings-page .info-panel__inner--enter {
  animation: rankings-panel-enter 0.3s ease-out 0.2s backwards;
}

@keyframes rankings-panel-enter {
  from {
    opacity: 0;
    transform: translateY(12px);
  }
}

@media (prefers-reduced-motion: reduce) {
  .rankings-page .info-panel {
    transition: none;
  }

  .rankings-page .info-panel__inner--enter {
    animation: none;
  }
}

.rankings-page .info-panel--wide {
  width: var(--info-panel-width-wide);
}

/* On a wide screen the comparison stays at the width of the page
   (--container-width), centred: the side padding grows. Phones keep theirs. */
@media (min-width: 768px) {
  .rankings-page .info-panel--wide .info-panel__inner {
    --panel-padding: max(var(--space-5), calc((100vw - var(--container-width)) / 2));
  }
}

.rankings-page .info-panel__inner {
  position: absolute;
  inset: 0;
  overflow-y: auto;
  /* Scrolling past the end of the panel does not scroll the page behind it. */
  overscroll-behavior: contain;
  --panel-padding: var(--space-5);
  padding: 0 var(--panel-padding) var(--space-6);
  /* Tables of the panel adapt to its width (@container info-panel). */
  container: info-panel / inline-size;
}

@media (max-width: 479px) {
  .rankings-page .info-panel__inner {
    --panel-padding: var(--space-4);
  }
}

/* Top bar: previous and next school, and the close button. Stays on top
   while the panel scrolls. */
.rankings-page .info-topbar {
  position: sticky;
  z-index: 2;
  top: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 52px;
  margin: 0 calc(var(--panel-padding) * -1);
  padding: 0 var(--space-3) 0 var(--panel-padding);
  border-bottom: 1px solid var(--color-border);
  background: var(--color-background);
}

.rankings-page .info-nav {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--font-size-xsmall);
  color: var(--color-muted);
}

.rankings-page .info-nav__button {
  margin: 0;
  padding: var(--space-1) var(--space-2);
  border: 0;
  border-radius: var(--radius-small);
  background: transparent;
  color: var(--color-accent);
  font-size: var(--font-size-xsmall);
  font-weight: 600;
  cursor: pointer;
}

.rankings-page .info-nav__button[disabled] {
  color: var(--color-faint);
  cursor: default;
}

.rankings-page .info-nav__status {
  padding: 0 var(--space-2);
  border-left: 1px solid var(--color-border);
  border-right: 1px solid var(--color-border);
}

/* Close button: also the one of the Moda panel (.info-panel__close). */
.rankings-page .info-panel__close {
  margin: 0 0 0 auto;
  width: 40px;
  height: 40px;
  border: 0;
  background: transparent;
  color: var(--color-text);
  font-size: 30px;
  line-height: 1;
  cursor: pointer;
}

/* The Moda panel has its close button outside the content. */
.rankings-page .info-panel > .info-panel__close {
  position: absolute;
  z-index: 3;
  top: var(--space-1);
  right: var(--space-2);
}

.rankings-page .info-header {
  padding-top: var(--space-5);
}

.rankings-page .info-name {
  margin: 0 0 var(--space-2);
  font-family: var(--font-title);
  font-size: 28px;
  font-weight: 700;
  line-height: 1.15;
}

.rankings-page .info-meta {
  margin: 0;
  font-size: var(--font-size-xsmall);
  color: var(--color-muted);
}

.rankings-page .info-meta__type {
  margin-right: var(--space-2);
  font-size: var(--font-size-label);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-text);
}

/* "Superou o esperado em 2,60 valores" box, the same colours whatever the
   result, with the change of the average since the previous edition. */
.rankings-page .info-summary {
  margin: var(--space-5) 0 0;
  padding: var(--space-4);
  border: 1px solid var(--color-accent-line);
  border-radius: var(--radius-large);
  background: var(--color-accent-soft);
}

.rankings-page .info-summary__change {
  margin-top: var(--space-2);
}
.rankings-page .info-summary__title {
  margin: 0 0 var(--space-2);
  font-size: 17px;
  font-weight: 700;
  line-height: 1.3;
}

.rankings-page .info-section {
  margin-top: var(--space-6);
  padding-top: var(--space-5);
  border-top: 1px solid var(--color-border);
}

.rankings-page .info-section-title {
  margin: 0 0 var(--space-3);
  font-size: 18px;
  font-weight: 700;
  line-height: 1.3;
}

.rankings-page .info-subtitle {
  margin: var(--space-4) 0 var(--space-2);
  font-size: 15px;
  font-weight: 500;
}

.rankings-page .info-text {
  margin: 0 0 var(--space-3);
  font-size: var(--font-size-small);
  line-height: 1.5;
  color: var(--color-text-soft);
}

.rankings-page .info-text--muted {
  color: var(--color-muted);
}

.rankings-page .info-footnote {
  margin: var(--space-2) 0 0;
  font-size: var(--font-size-xsmall);
  line-height: 1.45;
  color: var(--color-muted);
}
/* The possible contexts; the school's own is marked with aria-current and a
   hidden text, so it does not depend on colour alone. */
.rankings-page .info-context {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 0 0 var(--space-3);
  padding: 0;
  list-style: none;
}

.rankings-page .context-block {
  margin: 0;
  padding: 6px 10px;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-small);
  font-size: var(--font-size-xsmall);
  line-height: 1.2;
  color: var(--color-text-soft);
}

.rankings-page .context-block--active {
  border-color: var(--color-accent-fill);
  background: var(--color-accent-fill);
  color: var(--color-on-accent);
  font-weight: 700;
}

/* Exam subjects table. Secondary (--chart): exam and internal grade, three
   columns each under a group head, then the chart. The "Exame" / "Interna"
   cells and the short head (phone-head) are for phones only. */
.rankings-page .subject-table__caption {
  text-transform: none;
  letter-spacing: normal;
}

.rankings-page .subject-table tbody th {
  white-space: normal;
}

.rankings-page .subject-table__group,
.rankings-page .subject-table__phone-head {
  display: none;
}

/* Fixed column widths (the colgroup of renderSubjectTable): the table can
   never be wider than the panel, whatever the font. The subject takes what
   is left. */
.rankings-page .subject-table--chart {
  table-layout: fixed;
}

.rankings-page .subject-table__count { width: 47px; }
.rankings-page .subject-table__average { width: 47px; }
.rankings-page .subject-table__position { width: 54px; }
.rankings-page .subject-table__chart { width: 20%; }

/* The colgroup sets the width: not the generic chart cell's. */
.rankings-page .subject-table--chart .chart-cell {
  width: auto;
  min-width: 0;
}

.rankings-page .subject-table--chart th,
.rankings-page .subject-table--chart td {
  padding-right: 5px;
  padding-left: 5px;
}

/* Every column label on the second head line, at the bottom of it, even when
   "Exame vs. interna" takes two lines. */
.rankings-page .subject-table--chart thead th,
.rankings-page .subject-table--chart thead td {
  vertical-align: bottom;
  letter-spacing: 0.02em;
  white-space: normal;
}

/* A long subject name wraps, its "i" with it, inside its own column. */
.rankings-page .subject-table--chart tbody th {
  overflow-wrap: break-word;
}

.rankings-page .subject-table--chart .subject-table__group-head {
  border-bottom: 1px solid var(--color-border-strong);
  text-align: center;
}

.rankings-page .subject-table--chart .subject-table__groups th,
.rankings-page .subject-table--chart .subject-table__groups td {
  padding-bottom: 4px;
}

.rankings-page .subject-table--chart .subject-table__columns th {
  padding-top: 4px;
}

/* A narrow panel (phones, small tablets and windows; a container query, so
   it follows the panel and not the screen): each subject is a grid of fixed
   columns (the numbers line up from subject to subject): its name, then a
   line for the exam and one for the internal grade (number, average,
   position), then the chart, full width. The full table needs about 520px. */
@container info-panel (max-width: 539px) {
  .rankings-page .subject-table--chart {
    table-layout: auto;
    font-size: 13px;
  }

  .rankings-page .subject-table--chart colgroup {
    display: none;
  }

  .rankings-page .subject-table--chart tr {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 46px 54px 60px;
    align-items: center;
  }

  .rankings-page .subject-table--chart th,
  .rankings-page .subject-table--chart td {
    box-sizing: border-box;
  }

  .rankings-page .subject-table--chart tbody th {
    grid-column: 1 / -1;
    padding-bottom: 0;
    font-weight: 700;
  }

  .rankings-page .subject-table--chart .subject-table__group {
    display: block;
    color: var(--color-muted);
  }

  .rankings-page .subject-table--chart tbody td {
    padding-top: 4px;
    padding-bottom: 4px;
  }

  .rankings-page .subject-table__groups,
  .rankings-page .subject-table__columns {
    display: none !important;
  }

  .rankings-page .subject-table--chart .subject-table__phone-head {
    display: grid;
  }

  /* The rule between subjects belongs to the row: the cells of a row are
     on several lines, so their own rules would not meet. */
  .rankings-page .subject-table--chart tbody tr + tr th,
  .rankings-page .subject-table--chart tbody tr + tr td {
    border-top: 0;
  }

  .rankings-page .subject-table--chart tbody tr + tr {
    border-top: 1px solid var(--color-border);
  }

  .rankings-page .subject-table--chart .chart-cell {
    grid-column: 1 / -1;
    width: auto;
    min-width: 0;
    padding-top: var(--space-2);
    padding-bottom: var(--space-3);
  }

  /* A subject without both grades has no chart: no empty line under it. */
  .rankings-page .subject-table--chart tbody .chart-cell:has(.dumbbell--empty) {
    display: none;
  }

  .rankings-page .subject-table--chart tfoot td:not(.chart-cell) {
    display: none;
  }
}
/* Radar chart of the positions by subject (data/radar/<eid>.svg). */
.rankings-page .radar-img {
  display: block;
  width: 100%;
  max-width: 480px;
  height: auto;
  margin: var(--space-3) auto;
}

.rankings-page .info-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-top: var(--space-6);
  padding-top: var(--space-5);
  border-top: 1px solid var(--color-border);
}

/* --- Comparison of schools (in the info panel) ---------------------------- */
/* Opened from a school's page, up to compareMaxSchools schools. Computers: a
   table, labels on the left, a column per school. Phones: the schools as
   cards on top, then each row's label over its values. The best value of
   some rows sits in an accent-soft pill. */
.rankings-page .compare-add {
  gap: var(--space-2);
  margin: var(--space-4) 0 var(--space-5);
}

.rankings-page .compare-add__count {
  margin: 0;
  font-size: var(--font-size-xsmall);
  color: var(--color-muted);
}

/* Wide panel: the count beside the search box, the results under it. */
@container info-panel (min-width: 600px) {
  .rankings-page .compare-add {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    column-gap: var(--space-4);
  }

  .rankings-page .compare-add__count {
    align-self: end;
    padding-bottom: 14px;   /* on the line of the text of the search box */
  }

  .rankings-page .compare-results {
    grid-column: 1;
  }
}

.rankings-page .compare-results {
  margin: 0;
  padding: 0;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-background);
  list-style: none;
}

.rankings-page .compare-results:empty {
  display: none;
}

.rankings-page .compare-results button {
  display: block;
  width: 100%;
  padding: 10px var(--space-3);
  border: 0;
  border-bottom: 1px solid var(--color-border);
  background: none;
  font: inherit;
  text-align: left;
  color: inherit;
  cursor: pointer;
}

.rankings-page .compare-results li:last-child button {
  border-bottom: 0;
}

.rankings-page .compare-results button:hover,
.rankings-page .compare-results button:focus-visible {
  background: var(--color-surface);
}

.rankings-page .compare-results__name {
  display: block;
  font-weight: 700;
}

.rankings-page .compare-results__meta,
.rankings-page .compare-school__meta {
  display: block;
  margin-top: 2px;
  font-size: var(--font-size-label);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-muted);
}

/* The table (computers). */
.rankings-page .compare-table-wrap {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-large);
  overflow: hidden;
}

.rankings-page .compare-table {
  width: 100%;
  border-collapse: collapse;
  table-layout: fixed;
  font-size: var(--font-size-small);
}

.rankings-page .compare-table th,
.rankings-page .compare-table td {
  padding: var(--space-3) var(--space-4);
  border-top: 1px solid var(--color-border);
  text-align: left;
  vertical-align: top;
  /* Long words hyphenate (the page is in Portuguese) instead of being cut. */
  hyphens: auto;
}

.rankings-page .compare-table thead th {
  border-top: 0;
}

.rankings-page .compare-table tbody th {
  font-weight: 400;
  color: var(--color-text-soft);
}

.rankings-page .compare-table__corner {
  width: 24%;
}

.rankings-page .compare-school__name {
  display: block;
  font-weight: 700;
  line-height: 1.3;
}

.rankings-page .compare-school__short {
  display: none;
}

.rankings-page .compare-link,
.rankings-page .compare-remove {
  display: block;
  margin: var(--space-1) 0 0;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  font-size: var(--font-size-xsmall);
  font-weight: 400;
  text-align: left;
  cursor: pointer;
}

.rankings-page .compare-link {
  margin: 0;
  color: var(--color-link);
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* "Remover": an outlined pill under the school (only "×" on phones). */
.rankings-page .compare-remove {
  margin-top: var(--space-2);
  padding: 3px var(--space-3);
  border: 1px solid var(--color-text);
  border-radius: 999px;
  color: var(--color-text);
}

.rankings-page .compare-remove:hover,
.rankings-page .compare-remove:focus-visible {
  background: var(--color-surface);
}

.rankings-page .compare-remove__icon {
  display: none;
}

.rankings-page .compare-table__empty .compare-school__meta {
  font-size: var(--font-size-xsmall);
  font-weight: 400;
  letter-spacing: normal;
  text-transform: none;
}

/* Group rows ("Resultados nos exames"). */
.rankings-page .compare-table .compare-table__group th {
  padding-top: var(--space-2);
  padding-bottom: var(--space-2);
  background: var(--color-surface);
  font-size: var(--font-size-label);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-muted);
}

/* A value and its note, with the padding of the pill, so best and other
   values line up. */
.rankings-page .compare-cell {
  display: block;
  margin: calc(var(--space-1) * -1) calc(var(--space-2) * -1);
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius);
}

.rankings-page .compare-table .is-best .compare-cell {
  background: var(--color-accent-soft);
}

.rankings-page .compare-table .is-best .compare-value {
  color: var(--color-accent-strong);
}

.rankings-page .compare-value {
  display: block;
  font-weight: 700;
  line-height: 1.35;
  font-variant-numeric: tabular-nums;
}

.rankings-page .compare-note {
  display: block;
  margin-top: 2px;
  font-size: var(--font-size-xsmall);
  font-weight: 400;
  color: var(--color-muted);
}

.rankings-page .compare-note .trend {
  font-size: inherit;
}

.rankings-page .compare-cell--empty .compare-value {
  font-weight: 400;
  color: var(--color-faint);
}

.rankings-page .compare-legend {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: var(--space-3) 0 var(--space-6);
  font-size: var(--font-size-xsmall);
  color: var(--color-muted);
}

.rankings-page .compare-legend__swatch {
  width: 14px;
  height: 14px;
  border: 1px solid var(--color-accent-line);
  border-radius: var(--radius-small);
  background: var(--color-accent-soft);
}

/* Phones and small tablets: cards and stacked rows. */
@media (max-width: 767px) {
  .rankings-page .compare-table-wrap {
    border: 0;
    border-radius: 0;
    overflow: visible;
  }

  .rankings-page .compare-table,
  .rankings-page .compare-table thead,
  .rankings-page .compare-table tbody {
    display: block;
  }

  .rankings-page .compare-table tr {
    display: grid;
    grid-template-columns: repeat(var(--compare-columns), minmax(0, 1fr));
    column-gap: var(--space-2);
  }

  .rankings-page .compare-table--1 { --compare-columns: 1; }
  .rankings-page .compare-table--2 { --compare-columns: 2; }
  .rankings-page .compare-table--3 { --compare-columns: 3; }

  .rankings-page .compare-table th,
  .rankings-page .compare-table td {
    display: block;
    padding: 0;
    border: 0;
  }

  /* The schools: one card each, with "×" in the corner. */
  .rankings-page .compare-table thead tr {
    margin-bottom: var(--space-3);
  }

  .rankings-page .compare-table__corner {
    display: none !important;
  }

  .rankings-page .compare-table thead th:not(.compare-table__corner) {
    position: relative;
    padding: var(--space-2);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
  }

  .rankings-page .compare-table thead .compare-table__empty {
    border-style: dashed;
  }

  /* Room for the "×" (not on the first school, which cannot be removed). */
  .rankings-page .compare-table thead .compare-school--removable {
    padding-right: var(--space-5);
  }

  .rankings-page .compare-school__place,
  .rankings-page .compare-remove__label {
    display: none;
  }

  /* The full name stays for screen readers; the short one, at most four
     lines ("Escola Artística do Conservatório de Música…"), is on screen. */
  .rankings-page .compare-school__name {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
  }

  .rankings-page .compare-school__short {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 4;
    overflow: hidden;
    overflow-wrap: break-word;   /* only a word wider than the card */
    font-size: var(--font-size-xsmall);
    font-weight: 700;
    line-height: 1.3;
  }

  .rankings-page .compare-remove {
    position: absolute;
    top: var(--space-1);
    right: var(--space-1);
    margin: 0;
    padding: var(--space-1);
    border: 0;
    border-radius: var(--radius-small);
    font-size: 16px;
    line-height: 1;
    color: var(--color-text-soft);
  }

  .rankings-page .compare-remove__icon {
    display: inline;
  }

  /* "▲ 3": the year only for screen readers. */
  .rankings-page .compare-table .trend__since {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
  }

  /* The rows, in one box: the label on a line of its own, then the values. */
  .rankings-page .compare-table tbody {
    border: 1px solid var(--color-border);
    border-radius: var(--radius-large);
    overflow: hidden;
  }

  .rankings-page .compare-table tbody tr {
    padding: var(--space-3);
    border-top: 1px solid var(--color-border);
  }

  .rankings-page .compare-table tbody tr:first-child {
    border-top: 0;
  }

  .rankings-page .compare-table tbody th {
    grid-column: 1 / -1;
    margin-bottom: var(--space-2);
  }

  .rankings-page .compare-table .compare-table__group {
    background: var(--color-surface);
  }

  .rankings-page .compare-table .compare-table__group th {
    margin: 0;
    padding: 0;
    color: var(--color-text);
  }

  /* Values start at the column edge; the highlight of the best one bleeds a
     little into the gap between columns. */
  .rankings-page .compare-cell {
    margin: 0 calc(var(--space-1) * -1);
    padding: var(--space-1);
  }

  .rankings-page .compare-value {
    font-weight: 500;
  }

  /* Words ("Desfavorável", "Privados sem contrato de associação") fit the
     three columns of a 320px phone, smaller. */
  .rankings-page .compare-cell--text {
    font-size: var(--font-size-small);
  }
}

/* ==========================================================================
   8. PROVAS MODA AND ENSINO PROFISSIONAL PAGES
   Same components as the rankings page; only what differs is here.
   ========================================================================== */

/* Message when a data file fails to load. */
.rankings-page .load-error {
  padding: var(--space-4);
  border-radius: var(--radius);
  background: var(--color-down-soft);
  color: var(--color-down);
}

/* Profissional: number columns right aligned; the difference in bold. */
.rankings-page .ranking-table .col-number {
  text-align: right;
  white-space: nowrap;
}

.rankings-page .ranking-table .col-difference {
  font-weight: 700;
}

.rankings-page .ranking-table.profissional-table tbody tr {
  cursor: default;
}

/* Profissional on small screens: only the position and the school show;
   a row opens to list the other columns (js/profissional.js). */
.rankings-page .ranking-table.profissional-table .col-details {
  display: none;
}

.rankings-page .profissional-details {
  margin: 0;
  padding: 0;
  list-style: none;
}

.rankings-page .profissional-details li {
  display: flex;
  justify-content: space-between;
  gap: var(--space-3);
  padding: 6px 0;
}

.rankings-page .profissional-details li + li {
  border-top: 1px solid var(--color-border);
}

.rankings-page .profissional-details__label {
  color: var(--color-muted);
}

.rankings-page .profissional-details__value {
  font-weight: 700;
  text-align: right;
  white-space: nowrap;
}

@media (max-width: 767px) {
  .rankings-page .ranking-table.profissional-table thead tr,
  .rankings-page .ranking-table.profissional-table tbody tr {
    display: flex;
    flex-flow: row wrap;
    align-items: stretch;
  }

  .rankings-page .ranking-table.profissional-table th,
  .rankings-page .ranking-table.profissional-table td {
    display: flex;
    align-items: center;
    white-space: normal;
  }

  .rankings-page .ranking-table.profissional-table .col-number {
    display: none;
  }

  .rankings-page .ranking-table.profissional-table .col-superacao {
    flex: 0 0 64px;
  }

  /* Name over the municipality, as on the other tables. */
  .rankings-page .ranking-table.profissional-table .col-name {
    flex: 1 1 0;
    flex-direction: column;
    align-items: flex-start;
    justify-content: center;
    min-width: 0;
  }

  .rankings-page .ranking-table.profissional-table tbody tr {
    cursor: pointer;
  }

  .rankings-page .ranking-table.profissional-table tbody .col-name {
    position: relative;
    padding-right: var(--space-6);
  }

  .rankings-page .ranking-table.profissional-table tbody .col-name::after {
    content: "+";
    position: absolute;
    top: 50%;
    right: 10px;
    transform: translateY(-50%);
    font-size: 18px;
    font-weight: 700;
    color: var(--color-accent);
  }

  .rankings-page .ranking-table.profissional-table tbody tr.is-open .col-superacao,
  .rankings-page .ranking-table.profissional-table tbody tr.is-open .col-name {
    background: var(--color-accent-soft);
    font-weight: 700;
  }

  .rankings-page .ranking-table.profissional-table tbody tr.is-open .col-name::after {
    content: "\2212";
  }

  .rankings-page .ranking-table.profissional-table tbody tr.is-open .col-details {
    display: block;
    flex: 1 1 100%;
    padding: var(--space-1) 10px var(--space-1) 72px;
    border-top: 0;
    background: var(--color-surface);
  }
}


/* ==========================================================================
   9. CHATBOT PAGE ("Pergunte aos rankings")
   Conversation built by js/chatbot.js. Replies may hold small tables.
   ========================================================================== */

/* Full width of the container, as the other pages. */
.rankings-page .chatbot {
  margin: 0 0 var(--space-6);
}

/* Warning under the intro: the answers come from a language model. */
.rankings-page .chatbot__notice {
  margin: 0 0 var(--space-4);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--color-accent-line);
  border-radius: var(--radius);
  background: var(--color-accent-soft);
  font-size: var(--font-size-small);
  line-height: 1.5;
}

.rankings-page .chatbot__thread {
  max-height: 60vh;
  overflow-y: auto;
  margin-bottom: var(--space-3);
}

.rankings-page .chatbot__thread:not(:empty) {
  padding: var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-large);
}

.rankings-page .chatbot__message {
  max-width: 90%;
  margin-bottom: var(--space-3);
  font-size: 15px;
  overflow-wrap: break-word;
}

.rankings-page .chatbot__message--user {
  width: fit-content;
  margin-left: auto;
  padding: 6px var(--space-3);
  border-radius: var(--radius);
  background: var(--color-accent-soft);
}

.rankings-page .chatbot__message p,
.rankings-page .chatbot__message ul,
.rankings-page .chatbot__message ol {
  margin: 0 0 var(--space-2);
}

.rankings-page .chatbot__thinking {
  color: var(--color-muted);
  font-style: italic;
}

.rankings-page .chatbot__error {
  color: var(--color-down);
}

.rankings-page .chatbot__table {
  overflow-x: auto;
  margin: var(--space-2) 0;
}

.rankings-page .chatbot__table table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}

.rankings-page .chatbot__table th,
.rankings-page .chatbot__table td {
  padding: 6px var(--space-2);
  border-bottom: 1px solid var(--color-border);
  text-align: left;
}

.rankings-page .chatbot__table thead {
  background: var(--color-surface);
}

/* The question form sits in a .filter-panel, like the filters of the other
   pages; the textarea looks like their fields. */
.rankings-page .chatbot__form {
  gap: var(--space-2);
}

.rankings-page .chatbot textarea {
  display: block;
  width: 100%;
  margin: 0;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius);
  background: var(--color-background);
  box-shadow: none;
  font: inherit;
  font-size: 15px;
  resize: vertical;
}

.rankings-page .chatbot textarea:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 0;
  border-color: var(--color-accent);
}

/* While an answer is on its way (setChatbotBusy in js/chatbot.js). */
.rankings-page .chatbot textarea:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.rankings-page .chatbot__actions {
  display: flex;
  gap: var(--space-2);
  margin-top: var(--space-2);
}

.rankings-page .chatbot__subscribe {
  margin-top: var(--space-1);
}

/* Daily usage: an empty track that fills in the accent colour, then yellow and red. */
.rankings-page .chatbot__usage {
  margin-top: var(--space-4);
}

.rankings-page .chatbot__usage[hidden] {
  display: none;
}

.rankings-page .chatbot__usage-bar {
  height: 6px;
  overflow: hidden;
  border-radius: var(--radius-pill);
  background: var(--color-usage-track);
}

.rankings-page .chatbot__usage-fill {
  display: block;
  width: 0;
  height: 100%;
  background: var(--color-usage-ok);
  transition: width 0.4s ease, background-color 0.4s ease;
}

.rankings-page .chatbot__usage--warning .chatbot__usage-fill {
  background: var(--color-usage-warning);
}

.rankings-page .chatbot__usage--high .chatbot__usage-fill {
  background: var(--color-usage-high);
}


/* ==========================================================================
   10. COMING SOON PAGE (brevemente.html)
   Shown before the rankings are published: a clock and the time they open.
   ========================================================================== */

/* Full width of the container, as the infographics of the other pages. */
.rankings-page .coming-soon {
  margin: 0 0 var(--space-6);
  padding: var(--space-6) var(--space-5);
  border: 1px solid var(--color-accent-line);
  border-radius: var(--radius-large);
  background: var(--color-accent-soft);
  text-align: center;
}

.rankings-page .coming-soon__icon {
  display: block;
  width: 48px;
  height: 48px;
  margin: 0 auto var(--space-3);
  color: var(--color-accent);
}

.rankings-page .coming-soon__time {
  margin: 0 0 var(--space-2);
  font-family: var(--font-title);
  font-size: 22px;
  font-weight: 300;
  line-height: 1.3;
}

.rankings-page .coming-soon__time strong {
  font-weight: 700;
}

.rankings-page .coming-soon__text {
  margin: 0;
  font-size: var(--font-size-small);
  line-height: 1.55;
  color: var(--color-text-soft);
}

.rankings-page .coming-soon a {
  color: var(--color-link);
}
