@charset "UTF-8";

/* ═══════════════════════════════════════════════════════════════════════
   UniRank Observatory — design system
   ───────────────────────────────────────────────────────────────────────
   A measurement instrument for university web performance. The visual
   language borrows from academic heraldry and printed statistical annexes:
   navy structure, a crimson seal accent, brass for distinction, hairline
   rules instead of card shadows, and figures set in a reading serif with
   tabular numerals so columns of scores align like a printed table.

   Sections
     1  Tokens (colour, type, space, radius, elevation, motion)
     2  Dark theme
     3  Reset and base elements
     4  Typography and the figure treatment
     5  Layout primitives — shell, section, panel, rule
     6  Navigation and mobile menu
     7  Buttons
     8  Forms
     9  Tables and the ranking ledger
    10  Badges, chips, meters, deltas
    11  Feedback — alerts, toasts, modals, tooltips
    12  Empty states, skeletons, pagination
    13  Home / landing
    14  Motion
    15  Utilities
    16  Print and reduced motion
   ═══════════════════════════════════════════════════════════════════════ */

/* ── 1 · TOKENS ──────────────────────────────────────────────────────── */
:root {
  /* Structure — a chromatic navy, not a tinted black */
  --ink-900: #0c1a2e;
  --ink-800: #16243d;
  --ink-700: #22344f;
  --ink-600: #3c4f6b;
  --ink-500: #4a5c76;
  --ink-400: #556880;

  /* Grounds */
  --paper: #e9ecf1;
  --surface: #ffffff;
  --surface-2: #f4f6f9;
  --surface-3: #eceff4;
  --surface-inset: #f7f9fb;

  /* Hairlines carry structure here; shadows are reserved for floating UI */
  --rule: #d3dae4;
  --rule-soft: #e6eaf0;
  --rule-strong: #b9c4d2;

  /* Accents drawn from academic regalia */
  --seal: #8e2434;        /* crimson — primary action, section marks */
  --seal-strong: #741d2a;
  --seal-soft: #f7eaec;
  --seal-line: #e3c2c7;

  --brass: #8a611a;       /* gilt — distinction, first rank */
  --brass-soft: #faf2e2;
  --brass-line: #e6d2a8;

  --verdigris: #17635c;   /* oxidised copper — gains, confirmations */
  --verdigris-soft: #e4f1ef;
  --verdigris-line: #b4d8d3;

  /* Text roles */
  --text: var(--ink-900);
  --text-secondary: var(--ink-600);
  --text-muted: var(--ink-400);
  --text-inverse: #ffffff;
  --text-on-ink: #c9d4e4;
  --text-on-ink-muted: #a8b7cd;

  /* Score bands — printed-ink ramp, all AA on white and legible reversed */
  --band-critical: #a1232b;
  --band-low: #96550f;
  --band-mid: #8a6a12;
  --band-upper: #2b5e8f;
  --band-high: #176b4d;
  --band-none: #8494a8;

  --band-critical-soft: #fbeaeb;
  --band-low-soft: #fbf0e3;
  --band-mid-soft: #f9f3df;
  --band-upper-soft: #e9f0f8;
  --band-high-soft: #e3f2ec;
  --band-none-soft: #eef1f5;

  /* The four index dimensions each carry one colour, used identically in the
     composition plate, the dimension cards, the source matrix and the leader
     profile — so a reader learns the code once and it holds across the page. */
  --dim-webometrics: #16243d;
  --dim-research: #8e2434;
  --dim-technical: #8a611a;
  --dim-presence: #17635c;

  /* The same four as type rather than as a fill. On the light theme a colour
     that carries white type also reads as type on paper, so the two sets are
     identical here and part ways only under the dark theme. */
  --dim-webometrics-ink: var(--dim-webometrics);
  --dim-research-ink: var(--dim-research);
  --dim-technical-ink: var(--dim-technical);
  --dim-presence-ink: var(--dim-presence);

  /* Code blocks stay dark-on-light-page and dark-on-dark-page alike. */
  --code-bg: #0c1a2e;

  /* Semantic roles map onto the same ramp so the palette stays closed */
  --success: var(--verdigris);
  --success-soft: var(--verdigris-soft);
  --danger: var(--band-critical);
  --danger-soft: var(--band-critical-soft);
  --warning: var(--band-low);
  --warning-soft: var(--band-low-soft);
  --info: var(--band-upper);
  --info-soft: var(--band-upper-soft);

  /* Type */
  --font-text: "IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --font-display: "Source Serif 4", "Source Serif Pro", Georgia, "Times New Roman", serif;
  --font-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, "Cascadia Mono", Consolas, monospace;

  /* A modular scale at 1.2 from a 16px body, rounded to sane pixels */
  --t-3xs: 0.6875rem;   /* 11 */
  --t-2xs: 0.75rem;     /* 12 */
  --t-xs: 0.8125rem;    /* 13 */
  --t-sm: 0.875rem;     /* 14 */
  --t-base: 1rem;       /* 16 */
  --t-md: 1.125rem;     /* 18 */
  --t-lg: 1.3125rem;    /* 21 */
  --t-xl: 1.5625rem;    /* 25 */
  --t-2xl: 1.875rem;    /* 30 */
  --t-3xl: 2.25rem;     /* 36 */
  --t-4xl: 2.75rem;     /* 44 */
  --t-5xl: 3.5rem;      /* 56 */
  --t-6xl: 4.25rem;     /* 68 */

  --leading-tight: 1.15;
  --leading-snug: 1.3;
  --leading-normal: 1.55;
  --leading-relaxed: 1.7;

  --track-tight: -0.018em;
  --track-normal: 0;
  --track-loose: 0.01em;

  --measure: 68ch;      /* body copy line length */
  --measure-narrow: 46ch;

  /* Space — a 4px base with a doubling rhythm */
  --s-1: 0.25rem;
  --s-2: 0.5rem;
  --s-3: 0.75rem;
  --s-4: 1rem;
  --s-5: 1.5rem;
  --s-6: 2rem;
  --s-7: 3rem;
  --s-8: 4rem;
  --s-9: 6rem;

  --gutter: 1.25rem;
  --shell-max: 1240px;
  --shell-wide: 1480px;

  /* Radius — restrained; this is a ledger, not a card kit */
  --r-xs: 2px;
  --r-sm: 4px;
  --r-md: 6px;
  --r-lg: 10px;
  --r-pill: 999px;

  /* Elevation — only for things that genuinely float */
  --shadow-raised: 0 1px 2px rgba(12, 26, 46, 0.06);
  --shadow-float: 0 6px 16px -4px rgba(12, 26, 46, 0.14), 0 2px 4px rgba(12, 26, 46, 0.06);
  --shadow-overlay: 0 24px 48px -12px rgba(12, 26, 46, 0.28), 0 4px 12px rgba(12, 26, 46, 0.1);

  /* Motion */
  --ease-out: cubic-bezier(0.22, 0.61, 0.36, 1);
  --ease-in-out: cubic-bezier(0.45, 0.05, 0.55, 0.95);
  --ease-spring: cubic-bezier(0.34, 1.4, 0.64, 1);
  --dur-1: 90ms;
  --dur-2: 160ms;
  --dur-3: 260ms;
  --dur-4: 420ms;

  --focus-ring: 0 0 0 2px var(--surface), 0 0 0 4px var(--seal);
  --focus-ring-ink: 0 0 0 2px var(--ink-800), 0 0 0 4px #e2c98a;

  /* Bootstrap bridge — retheme the framework from our own tokens so stock
     markup inherits the identity instead of Bootstrap's defaults. */
  --bs-body-font-family: var(--font-text);
  --bs-body-font-size: var(--t-base);
  --bs-body-color: var(--text);
  --bs-body-bg: var(--paper);
  --bs-emphasis-color: var(--text);
  --bs-secondary-color: var(--text-secondary);
  --bs-border-color: var(--rule);
  --bs-border-color-translucent: var(--rule);
  --bs-border-radius: var(--r-sm);
  --bs-border-radius-sm: var(--r-xs);
  --bs-border-radius-lg: var(--r-md);
  --bs-border-radius-xl: var(--r-lg);
  --bs-primary: var(--seal);
  --bs-primary-rgb: 142, 36, 52;
  --bs-link-color: var(--seal);
  --bs-link-color-rgb: 142, 36, 52;
  --bs-link-hover-color: var(--seal-strong);
  --bs-success: var(--verdigris);
  --bs-danger: var(--band-critical);
  --bs-warning: var(--band-low);
  --bs-info: var(--band-upper);
  --bs-heading-color: var(--text);
  --bs-code-color: var(--seal);
  --bs-focus-ring-color: rgba(142, 36, 52, 0.35);
  color-scheme: light;
}

/* ── 2 · DARK THEME ──────────────────────────────────────────────────── */
[data-bs-theme="dark"] {
  --ink-900: #e5eaf2;
  --ink-800: #d3dbe8;
  --ink-700: #b7c3d4;
  --ink-600: #9aaac2;
  --ink-500: #8b9bb4;
  --ink-400: #8b9bb4;

  --paper: #0b1320;
  --surface: #141f30;
  --surface-2: #1b2940;
  --surface-3: #22314a;
  --surface-inset: #101a29;

  --rule: #2b3b55;
  --rule-soft: #223047;
  --rule-strong: #3b4d6b;

  --seal: #d9636f;
  --seal-strong: #e8808a;
  --seal-soft: #2a1a20;
  --seal-line: #4a2730;

  --brass: #d9ab56;
  --brass-soft: #2a2317;
  --brass-line: #4a3d22;

  --verdigris: #59c0ae;
  --verdigris-soft: #142b28;
  --verdigris-line: #22463f;

  --text: #e5eaf2;
  --text-secondary: #b7c3d4;
  --text-muted: #9aaac2;
  --text-inverse: #0b1320;
  --text-on-ink: #c9d4e4;
  --text-on-ink-muted: #a8b7cd;

  --band-critical: #e8707a;
  --band-low: #e0954b;
  --band-mid: #d4a93c;
  --band-upper: #74aee0;
  --band-high: #4fc08d;
  --band-none: #8b9bb4;

  --band-critical-soft: #2c1a1d;
  --band-low-soft: #2c2118;
  --band-mid-soft: #2b2617;
  --band-upper-soft: #16283a;
  --band-high-soft: #142b24;
  --band-none-soft: #1b2940;

  /* Dimension colours lift on the dark ground; white type on each still
     clears 4.5:1 (5.14, 6.03, 4.93, 4.83 respectively). */
  --dim-webometrics: #4a6ea8;
  --dim-research: #ab3c4c;
  --dim-technical: #8f6a2a;
  --dim-presence: #1f7f75;

  /* As type on a dark surface the fills are far too dark, so the ink set is
     lifted until each clears 4.5:1 on --surface, --surface-2 and --paper. */
  --dim-webometrics-ink: #7fa0d2;
  --dim-research-ink: #d87f8b;
  --dim-technical-ink: #d2a65a;
  --dim-presence-ink: #5fbdb1;

  --code-bg: #060d17;

  --shadow-raised: 0 1px 2px rgba(0, 0, 0, 0.4);
  --shadow-float: 0 6px 16px -4px rgba(0, 0, 0, 0.6), 0 2px 4px rgba(0, 0, 0, 0.4);
  --shadow-overlay: 0 24px 48px -12px rgba(0, 0, 0, 0.75), 0 4px 12px rgba(0, 0, 0, 0.5);

  --focus-ring: 0 0 0 2px var(--surface), 0 0 0 4px var(--seal);

  --bs-body-bg: var(--paper);
  --bs-body-color: var(--text);
  --bs-border-color: var(--rule);
  --bs-border-color-translucent: var(--rule);
  --bs-primary: var(--seal);
  --bs-primary-rgb: 217, 99, 111;
  --bs-link-color: var(--seal);
  --bs-link-color-rgb: 217, 99, 111;
  --bs-link-hover-color: var(--seal-strong);
  --bs-focus-ring-color: rgba(217, 99, 111, 0.4);
  color-scheme: dark;
}

/* ── 3 · RESET AND BASE ──────────────────────────────────────────────── */
*,
*::before,
*::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 5.5rem;
  /* Set on both html and body: with overflow only on body the value
     propagates to the viewport and body itself reverts to visible, which let
     off-canvas panels widen the document.
     clip rather than hidden: hidden creates a scroll container that can still
     be panned programmatically and that breaks position:sticky inside it,
     while clip simply refuses the overflow. hidden stays as the fallback. */
  overflow-x: hidden;
  overflow-x: clip;
}

body {
  margin: 0;
  min-height: 100vh;
  background-color: var(--paper);
  color: var(--text);
  font-family: var(--font-text);
  font-size: var(--t-base);
  line-height: var(--leading-normal);
  font-feature-settings: "kern" 1, "liga" 1, "calt" 1;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* Never allow a stray wide child to scroll the whole document sideways. */
  overflow-x: hidden;
  overflow-x: clip;
}

img,
svg,
canvas { max-width: 100%; }

img { height: auto; }

hr {
  border: 0;
  border-top: 1px solid var(--rule);
  opacity: 1;
  margin: var(--s-5) 0;
}

::selection {
  background: var(--seal);
  color: #fff;
}

/* One visible focus treatment for the whole app. */
:focus-visible {
  outline: 2px solid var(--seal);
  outline-offset: 2px;
  border-radius: var(--r-xs);
}

.on-ink :focus-visible,
.site-header :focus-visible,
.hero :focus-visible {
  outline-color: #e2c98a;
}

/* The skip link is the first thing keyboard users reach. */
.skip-link {
  position: fixed;
  top: 0;
  left: 50%;
  transform: translate(-50%, -110%);
  z-index: 2000;
  padding: var(--s-3) var(--s-5);
  background: var(--seal);
  color: #fff;
  font-weight: 600;
  font-size: var(--t-sm);
  border-radius: 0 0 var(--r-md) var(--r-md);
  text-decoration: none;
  transition: transform var(--dur-2) var(--ease-out);
}
.skip-link:focus {
  transform: translate(-50%, 0);
  color: #fff;
}

/* ── 4 · TYPOGRAPHY ──────────────────────────────────────────────────── */
h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6 {
  font-family: var(--font-display);
  font-weight: 600;
  color: var(--text);
  letter-spacing: var(--track-tight);
  line-height: var(--leading-snug);
  margin: 0 0 var(--s-3);
  text-wrap: balance;
}

h1, .h1 {
  font-size: clamp(2rem, 1.25rem + 3.1vw, 3.25rem);
  line-height: 1.06;
  letter-spacing: -0.024em;
}
h2, .h2 {
  font-size: clamp(1.625rem, 1.12rem + 2.1vw, 2.625rem);
  line-height: 1.1;
  letter-spacing: -0.022em;
}
h3, .h3 { font-size: clamp(1.3125rem, 1.1rem + 0.85vw, 1.6875rem); }
/* A second-rank heading used where a section is one of a pair rather than
   the page's own subject. */
.h-sub { font-size: clamp(1.25rem, 1.05rem + 0.8vw, 1.625rem); line-height: 1.15; }
h4, .h4 { font-size: var(--t-lg); }
h5, .h5 { font-size: var(--t-md); }
h6, .h6 { font-size: var(--t-base); }

p { margin: 0 0 var(--s-4); }

.lede {
  font-size: var(--t-md);
  line-height: var(--leading-relaxed);
  color: var(--text-secondary);
  max-width: var(--measure);
}

.prose { max-width: var(--measure); }
.prose p,
.prose li { line-height: var(--leading-relaxed); }
.prose h2 { margin-top: var(--s-7); }
.prose h3 { margin-top: var(--s-6); }

a {
  color: var(--seal);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.16em;
  transition: color var(--dur-1) var(--ease-out);
}
a:hover { color: var(--seal-strong); }

small, .small { font-size: var(--t-sm); }

code, kbd, pre, samp { font-family: var(--font-mono); }

code {
  font-size: 0.9em;
  background: var(--surface-2);
  border: 1px solid var(--rule-soft);
  border-radius: var(--r-xs);
  padding: 0.08em 0.36em;
  color: var(--seal);
}

/* Code blocks keep a dark ground in both themes: --ink-900 inverts under the
   dark theme, which left pale type on a pale block. */
pre {
  background: var(--code-bg);
  color: #dbe3ef;
  padding: var(--s-4);
  border-radius: var(--r-md);
  overflow-x: auto;
  font-size: var(--t-xs);
  line-height: 1.6;
}
pre code {
  background: none;
  border: 0;
  padding: 0;
  color: inherit;
}

kbd {
  font-family: var(--font-text);
  font-size: var(--t-2xs);
  font-weight: 600;
  padding: 0.15em 0.45em;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-bottom-width: 2px;
  border-radius: var(--r-sm);
  color: var(--text-secondary);
  box-shadow: none;
}

/* — The figure treatment —
   Every measured number in the product is set in the reading serif with
   tabular lining numerals, so columns of scores line up exactly and a score
   reads as a printed measurement rather than as UI chrome. */
.fig,
.figure-lg,
.figure-xl,
.rank-no,
.stat-value,
td.num,
th.num {
  font-family: var(--font-display);
  font-variant-numeric: tabular-nums lining-nums;
  font-feature-settings: "tnum" 1, "lnum" 1;
  letter-spacing: var(--track-tight);
}

.fig { font-weight: 600; }

.figure-xl {
  font-size: clamp(2.75rem, 2rem + 3.4vw, 4rem);
  font-weight: 600;
  line-height: 0.95;
  display: block;
}

.figure-lg {
  font-size: clamp(1.875rem, 1.5rem + 1.6vw, 2.5rem);
  font-weight: 600;
  line-height: 1;
  display: block;
}

.figure-unit {
  font-family: var(--font-text);
  font-size: 0.42em;
  font-weight: 500;
  letter-spacing: 0;
  color: var(--text-muted);
  margin-left: 0.12em;
  vertical-align: 0.5em;
}

.stat-label {
  display: block;
  font-size: var(--t-xs);
  font-weight: 500;
  color: var(--text-muted);
  line-height: 1.35;
  margin-top: var(--s-2);
}

/* Section heading with a crimson mark: the rule says "a section starts
   here", it is not ornament. */
.section-head {
  position: relative;
  padding-left: var(--s-4);
  margin-bottom: var(--s-5);
}
.section-head::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.24em;
  bottom: 0.24em;
  width: 3px;
  background: var(--seal);
  border-radius: 1px;
}
.section-head > :last-child { margin-bottom: 0; }
.section-head p {
  color: var(--text-secondary);
  max-width: var(--measure);
  margin-bottom: 0;
}

/* Where a section opens a full-width plate, the heading and its lede sit side
   by side on one baseline rather than stacking into a narrow left column —
   the head then measures the same width as the figure beneath it. */
.section-head-wide {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
  gap: var(--s-4) clamp(2rem, 5vw, 5.5rem);
  align-items: end;
  margin-bottom: var(--s-6);
}
.section-head-wide h2 { margin-bottom: 0; }
.section-head-wide p {
  font-size: var(--t-md);
  line-height: var(--leading-relaxed);
  max-width: 56ch;
}

@media (max-width: 899.98px) {
  .section-head-wide {
    grid-template-columns: minmax(0, 1fr);
    align-items: start;
    gap: var(--s-3);
  }
  .section-head-wide p { font-size: var(--t-base); }
}

/* Anything linked to by fragment clears the sticky header. */
.anchor-target { scroll-margin-top: 5rem; }

/* ── 5 · LAYOUT PRIMITIVES ───────────────────────────────────────────── */
.shell,
.container,
.container-fluid,
.container-lg,
.container-xl {
  width: 100%;
  max-width: var(--shell-max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.shell-wide { max-width: var(--shell-wide); }

.section { padding-block: clamp(3rem, 1.6rem + 5.4vw, 6rem); }
.section-tight { padding-block: clamp(1.75rem, 1.2rem + 2vw, 2.75rem); }
.section-alt { background: var(--surface-2); border-block: 1px solid var(--rule-soft); }

main { display: block; }

/* Panel — the workhorse container. Flat, ruled, no shadow. */
.panel {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  padding: var(--s-5);
}
.panel-flush { padding: 0; }
.panel-tight { padding: var(--s-4); }

.panel-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-3);
  flex-wrap: wrap;
  padding: var(--s-4) var(--s-5);
  border-bottom: 1px solid var(--rule);
  background: var(--surface-2);
  border-radius: var(--r-md) var(--r-md) 0 0;
}
.panel-head h2,
.panel-head h3,
.panel-head h4 {
  font-size: var(--t-md);
  margin: 0;
}
.panel-head .panel-note {
  font-size: var(--t-xs);
  color: var(--text-muted);
  margin: 0;
}

.panel-body { padding: var(--s-5); }
.panel-foot {
  padding: var(--s-3) var(--s-5);
  border-top: 1px solid var(--rule);
  background: var(--surface-2);
  border-radius: 0 0 var(--r-md) var(--r-md);
  font-size: var(--t-sm);
  color: var(--text-muted);
}

/* Bootstrap's card, retuned to the same language. */
.card {
  --bs-card-bg: var(--surface);
  --bs-card-border-color: var(--rule);
  --bs-card-border-radius: var(--r-md);
  --bs-card-inner-border-radius: var(--r-sm);
  --bs-card-cap-bg: var(--surface-2);
  --bs-card-color: var(--text);
  box-shadow: none;
}
.card-header {
  border-bottom-color: var(--rule);
  font-weight: 600;
  color: var(--text);
}

/* A figure panel: for the one or two numbers that matter most on a page. */
.figure-panel {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-top: 3px solid var(--seal);
  border-radius: var(--r-md);
  padding: var(--s-5);
}
.figure-panel .figure-xl,
.figure-panel .figure-lg { color: var(--text); }

/* Stat row: several small figures sharing one ruled strip. */
.stat-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  overflow: hidden;
}
.stat-cell {
  padding: var(--s-4) var(--s-5);
  border-right: 1px solid var(--rule-soft);
  border-bottom: 1px solid var(--rule-soft);
  min-width: 0;
}
.stat-cell:last-child { border-right: 0; }
.stat-value {
  font-size: var(--t-2xl);
  font-weight: 600;
  line-height: 1.05;
  display: block;
  color: var(--text);
  word-break: break-word;
}

/* Definition grid for "key: figure" pairs. */
.data-list {
  margin: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 0;
}
.data-list dt,
.data-list dd {
  padding: var(--s-3) 0;
  border-bottom: 1px solid var(--rule-soft);
  margin: 0;
  min-width: 0;
}
.data-list dt {
  font-size: var(--t-sm);
  color: var(--text-secondary);
  padding-right: var(--s-4);
}
.data-list dd {
  font-family: var(--font-display);
  font-variant-numeric: tabular-nums lining-nums;
  font-weight: 600;
  text-align: right;
  color: var(--text);
  white-space: nowrap;
}
.data-list > :nth-last-child(1),
.data-list > :nth-last-child(2) { border-bottom: 0; }

/* ── 6 · NAVIGATION ──────────────────────────────────────────────────── */
.site-header {
  position: sticky;
  top: 0;
  z-index: 1030;
  background: var(--ink-800);
  border-bottom: 1px solid rgba(255, 255, 255, 0.09);
  color: var(--text-on-ink);
}
[data-bs-theme="dark"] .site-header {
  background: #0e1726;
  border-bottom-color: var(--rule);
}

.site-header-inner {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  min-height: 62px;
  padding-block: var(--s-2);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  color: #fff;
  text-decoration: none;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--t-md);
  letter-spacing: var(--track-tight);
  white-space: nowrap;
  flex-shrink: 0;
}
.brand:hover { color: #fff; }
.brand-mark {
  width: 30px;
  height: 30px;
  flex: 0 0 30px;
  display: grid;
  place-items: center;
  border-radius: var(--r-sm);
  background: var(--seal);
  color: #fff;
  font-size: 1rem;
}
.brand-name { line-height: 1.05; }
.brand-name small {
  display: block;
  font-family: var(--font-text);
  font-size: var(--t-3xs);
  font-weight: 500;
  color: var(--text-on-ink-muted);
  letter-spacing: 0.02em;
}

.nav-main {
  display: flex;
  align-items: center;
  gap: var(--s-1);
  margin: 0 0 0 auto;
  padding: 0;
  list-style: none;
}

.nav-link-top {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.5rem 0.7rem;
  border-radius: var(--r-sm);
  color: var(--text-on-ink);
  text-decoration: none;
  font-size: var(--t-sm);
  font-weight: 500;
  white-space: nowrap;
  background: none;
  border: 0;
  position: relative;
  transition: color var(--dur-1) var(--ease-out), background-color var(--dur-1) var(--ease-out);
}
.nav-link-top:hover,
.nav-link-top:focus-visible { color: #fff; background: rgba(255, 255, 255, 0.08); }
.nav-link-top[aria-current="page"] { color: #fff; }
.nav-link-top[aria-current="page"]::after {
  content: "";
  position: absolute;
  left: 0.7rem;
  right: 0.7rem;
  bottom: 0.1rem;
  height: 2px;
  background: var(--brass, #d9ab56);
  border-radius: 1px;
}
[data-bs-theme="light"] .nav-link-top[aria-current="page"]::after { background: #d9ab56; }

/* Header search */
.header-search {
  position: relative;
  flex: 1 1 210px;
  min-width: 0;
  max-width: 300px;
}
.header-search input {
  width: 100%;
  padding: 0.45rem 2rem 0.45rem 0.7rem;
  font-size: var(--t-sm);
  font-family: inherit;
  color: #fff;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: var(--r-sm);
  transition: background-color var(--dur-2) var(--ease-out), border-color var(--dur-2) var(--ease-out);
}
.header-search input::placeholder { color: rgba(255, 255, 255, 0.55); }
.header-search input:focus {
  background: rgba(255, 255, 255, 0.14);
  border-color: rgba(255, 255, 255, 0.4);
  outline: 2px solid #e2c98a;
  outline-offset: 1px;
}
.header-search .search-icon {
  position: absolute;
  right: 0.6rem;
  top: 50%;
  transform: translateY(-50%);
  color: rgba(255, 255, 255, 0.5);
  pointer-events: none;
  font-size: 0.9rem;
}

.search-results {
  position: absolute;
  inset-inline: 0;
  top: calc(100% + 6px);
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-overlay);
  overflow: hidden;
  z-index: 40;
  max-height: 60vh;
  overflow-y: auto;
}
.search-result {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: 0.55rem 0.75rem;
  text-decoration: none;
  color: var(--text);
  border-bottom: 1px solid var(--rule-soft);
  transition: background-color var(--dur-1) var(--ease-out);
}
.search-result:last-child { border-bottom: 0; }
.search-result:hover,
.search-result:focus-visible { background: var(--surface-2); color: var(--text); }
.search-result-name { font-weight: 600; font-size: var(--t-sm); line-height: 1.25; }
.search-result-meta { font-size: var(--t-2xs); color: var(--text-muted); }
.search-empty {
  padding: 0.8rem 0.75rem;
  font-size: var(--t-sm);
  color: var(--text-muted);
}

/* Dropdown */
.dropdown-menu {
  --bs-dropdown-bg: var(--surface);
  --bs-dropdown-border-color: var(--rule);
  --bs-dropdown-border-radius: var(--r-md);
  --bs-dropdown-link-color: var(--text-secondary);
  --bs-dropdown-link-hover-bg: var(--surface-2);
  --bs-dropdown-link-hover-color: var(--text);
  --bs-dropdown-link-active-bg: var(--seal-soft);
  --bs-dropdown-link-active-color: var(--seal);
  --bs-dropdown-divider-bg: var(--rule-soft);
  --bs-dropdown-font-size: var(--t-sm);
  box-shadow: var(--shadow-overlay);
  padding-block: var(--s-1);
}
.dropdown-item {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.45rem 0.9rem;
}
.dropdown-header {
  font-size: var(--t-2xs);
  font-weight: 600;
  color: var(--text-muted);
  padding: 0.5rem 0.9rem 0.25rem;
}

/* Icon button used in the header rail */
.icon-btn {
  display: inline-grid;
  place-items: center;
  width: 34px;
  height: 34px;
  flex: 0 0 34px;
  border-radius: var(--r-sm);
  border: 1px solid rgba(255, 255, 255, 0.16);
  background: rgba(255, 255, 255, 0.06);
  color: var(--text-on-ink);
  cursor: pointer;
  transition: background-color var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}
.icon-btn:hover { background: rgba(255, 255, 255, 0.14); color: #fff; }

/* Mobile menu */
.nav-toggle { display: none; }

.mobile-nav {
  position: fixed;
  inset: 0 0 0 auto;
  width: min(340px, 88vw);
  background: var(--surface);
  border-left: 1px solid var(--rule);
  box-shadow: var(--shadow-overlay);
  z-index: 1080;
  transform: translateX(100%);
  transition: transform var(--dur-3) var(--ease-out);
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.mobile-nav[data-open="true"] { transform: translateX(0); }

.mobile-nav[hidden],
.nav-scrim[hidden] { display: none !important; }

.mobile-nav-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  padding: var(--s-4) var(--s-5);
  border-bottom: 1px solid var(--rule);
  background: var(--surface-2);
  position: sticky;
  top: 0;
}
.mobile-nav-body { padding: var(--s-3) 0 var(--s-6); }
.mobile-nav-group {
  padding: var(--s-3) var(--s-5) var(--s-1);
  font-size: var(--t-2xs);
  font-weight: 600;
  color: var(--text-muted);
}
.mobile-nav a,
.mobile-nav button.mobile-nav-item {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  width: 100%;
  padding: 0.7rem var(--s-5);
  color: var(--text);
  text-decoration: none;
  font-size: var(--t-sm);
  font-weight: 500;
  border: 0;
  background: none;
  text-align: left;
  border-left: 3px solid transparent;
  transition: background-color var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out);
}
.mobile-nav a:hover,
.mobile-nav a:focus-visible,
.mobile-nav button.mobile-nav-item:hover { background: var(--surface-2); border-left-color: var(--rule-strong); }
.mobile-nav a[aria-current="page"] {
  border-left-color: var(--seal);
  background: var(--seal-soft);
  color: var(--seal);
}

.nav-scrim {
  position: fixed;
  inset: 0;
  background: rgba(12, 26, 46, 0.5);
  z-index: 1070;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-3) var(--ease-out);
}
.nav-scrim[data-open="true"] { opacity: 1; pointer-events: auto; }

/* Breadcrumbs */
.crumbs {
  background: var(--surface);
  border-bottom: 1px solid var(--rule);
}
.crumbs ol {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem 0.5rem;
  list-style: none;
  margin: 0;
  padding-block: 0.6rem;
  font-size: var(--t-xs);
}
.crumbs li { display: flex; align-items: center; gap: 0.5rem; color: var(--text-muted); }
.crumbs li + li::before { content: "/"; color: var(--rule-strong); }
.crumbs a { color: var(--text-secondary); text-decoration: none; }
.crumbs a:hover { color: var(--seal); text-decoration: underline; }
.crumbs [aria-current="page"] { color: var(--text); font-weight: 600; }

/* Local tab bar (dashboard sections) */
.tabbar {
  display: flex;
  gap: 0;
  overflow-x: auto;
  border-bottom: 1px solid var(--rule);
  background: var(--surface);
  scrollbar-width: thin;
  -webkit-overflow-scrolling: touch;
}
.tabbar a {
  flex: 0 0 auto;
  padding: 0.7rem 1rem;
  font-size: var(--t-sm);
  font-weight: 500;
  color: var(--text-secondary);
  text-decoration: none;
  border-bottom: 2px solid transparent;
  white-space: nowrap;
  transition: color var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out);
}
.tabbar a:hover { color: var(--text); border-bottom-color: var(--rule-strong); }
.tabbar a[aria-current="page"] { color: var(--seal); border-bottom-color: var(--seal); font-weight: 600; }

/* ── 7 · BUTTONS ─────────────────────────────────────────────────────── */
.btn {
  --bs-btn-border-radius: var(--r-sm);
  --bs-btn-font-family: var(--font-text);
  --bs-btn-font-size: var(--t-sm);
  --bs-btn-font-weight: 600;
  --bs-btn-padding-y: 0.5rem;
  --bs-btn-padding-x: 1rem;
  --bs-btn-line-height: 1.4;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.45rem;
  letter-spacing: var(--track-loose);
  border-width: 1px;
  box-shadow: none;
  transition:
    background-color var(--dur-1) var(--ease-out),
    border-color var(--dur-1) var(--ease-out),
    color var(--dur-1) var(--ease-out),
    transform var(--dur-1) var(--ease-out);
}
.btn:active { transform: translateY(1px); }
.btn:focus-visible { box-shadow: var(--focus-ring); outline: none; }
.btn:disabled,
.btn.disabled { opacity: 0.5; cursor: not-allowed; transform: none; }

.btn-primary,
.btn-seal {
  --bs-btn-color: #fff;
  --bs-btn-bg: var(--seal);
  --bs-btn-border-color: var(--seal);
  --bs-btn-hover-color: #fff;
  --bs-btn-hover-bg: var(--seal-strong);
  --bs-btn-hover-border-color: var(--seal-strong);
  --bs-btn-active-bg: var(--seal-strong);
  --bs-btn-active-border-color: var(--seal-strong);
  --bs-btn-disabled-bg: var(--seal);
  --bs-btn-disabled-border-color: var(--seal);
  --bs-btn-disabled-color: #fff;
  color: #fff;
  background: var(--seal);
  border-color: var(--seal);
}
[data-bs-theme="dark"] .btn-primary,
[data-bs-theme="dark"] .btn-seal {
  --bs-btn-color: #1a0d10;
  --bs-btn-hover-color: #1a0d10;
  color: #1a0d10;
}

.btn-ink {
  color: #fff;
  background: var(--ink-800);
  border-color: var(--ink-800);
}
.btn-ink:hover { color: #fff; background: var(--ink-700); border-color: var(--ink-700); }
[data-bs-theme="dark"] .btn-ink { color: var(--paper); background: var(--ink-700); border-color: var(--ink-600); }

.btn-secondary,
.btn-outline-secondary,
.btn-outline-primary,
.btn-quiet {
  --bs-btn-color: var(--text-secondary);
  --bs-btn-bg: var(--surface);
  --bs-btn-border-color: var(--rule);
  --bs-btn-hover-color: var(--text);
  --bs-btn-hover-bg: var(--surface-2);
  --bs-btn-hover-border-color: var(--rule-strong);
  --bs-btn-active-color: var(--text);
  --bs-btn-active-bg: var(--surface-3);
  --bs-btn-active-border-color: var(--rule-strong);
  color: var(--text-secondary);
  background: var(--surface);
  border-color: var(--rule);
}
.btn-outline-primary {
  --bs-btn-color: var(--seal);
  --bs-btn-border-color: var(--seal-line);
  --bs-btn-hover-bg: var(--seal-soft);
  --bs-btn-hover-color: var(--seal-strong);
  --bs-btn-hover-border-color: var(--seal);
  color: var(--seal);
  border-color: var(--seal-line);
}

.btn-danger,
.btn-outline-danger {
  --bs-btn-color: #fff;
  --bs-btn-bg: var(--band-critical);
  --bs-btn-border-color: var(--band-critical);
  --bs-btn-hover-bg: #8a1c24;
  --bs-btn-hover-border-color: #8a1c24;
  --bs-btn-hover-color: #fff;
}
.btn-outline-danger {
  --bs-btn-color: var(--band-critical);
  --bs-btn-bg: transparent;
  --bs-btn-hover-color: #fff;
  color: var(--band-critical);
  background: transparent;
}

.btn-success {
  --bs-btn-color: #fff;
  --bs-btn-bg: var(--verdigris);
  --bs-btn-border-color: var(--verdigris);
  --bs-btn-hover-bg: #114f4a;
  --bs-btn-hover-border-color: #114f4a;
  --bs-btn-hover-color: #fff;
}

.btn-link {
  --bs-btn-color: var(--seal);
  --bs-btn-hover-color: var(--seal-strong);
  text-decoration: none;
  padding-inline: 0.25rem;
}
.btn-link:hover { text-decoration: underline; }

.btn-lg {
  --bs-btn-font-size: var(--t-base);
  --bs-btn-padding-y: 0.7rem;
  --bs-btn-padding-x: 1.4rem;
}
.btn-sm {
  --bs-btn-font-size: var(--t-xs);
  --bs-btn-padding-y: 0.32rem;
  --bs-btn-padding-x: 0.7rem;
}

/* Busy state: the label stays put, the spinner replaces the icon. */
.btn[data-busy="true"] {
  pointer-events: none;
  opacity: 0.75;
}
.btn[data-busy="true"] .btn-icon { display: none; }
.btn[data-busy="true"]::before {
  content: "";
  width: 0.85em;
  height: 0.85em;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  animation: spin 620ms linear infinite;
}

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

/* ── 8 · FORMS ───────────────────────────────────────────────────────── */
.field { margin-bottom: var(--s-4); }

.form-label,
.field > label {
  display: block;
  font-size: var(--t-sm);
  font-weight: 600;
  color: var(--text);
  margin-bottom: 0.35rem;
}

.form-hint,
.form-text {
  display: block;
  font-size: var(--t-xs);
  color: var(--text-muted);
  margin-top: 0.3rem;
}

.form-control,
.form-select {
  width: 100%;
  padding: 0.55rem 0.75rem;
  font-family: var(--font-text);
  font-size: var(--t-sm);
  line-height: 1.45;
  color: var(--text);
  background-color: var(--surface);
  border: 1px solid var(--rule-strong);
  border-radius: var(--r-sm);
  box-shadow: none;
  transition: border-color var(--dur-1) var(--ease-out), box-shadow var(--dur-1) var(--ease-out);
}
.form-control::placeholder { color: var(--text-muted); opacity: 1; }
.form-control:focus,
.form-select:focus {
  border-color: var(--seal);
  box-shadow: 0 0 0 3px rgba(142, 36, 52, 0.14);
  outline: none;
  background-color: var(--surface);
  color: var(--text);
}
[data-bs-theme="dark"] .form-control:focus,
[data-bs-theme="dark"] .form-select:focus { box-shadow: 0 0 0 3px rgba(217, 99, 111, 0.22); }

.form-control:disabled,
.form-select:disabled {
  background-color: var(--surface-3);
  color: var(--text-muted);
  cursor: not-allowed;
}

.form-control-lg {
  padding: 0.8rem 1rem;
  font-size: var(--t-base);
}

textarea.form-control { min-height: 7rem; resize: vertical; }

.form-select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%234a5c76' stroke-width='1.6' stroke-linecap='round'%3E%3Cpath d='M4 6.5 8 10.5 12 6.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.6rem center;
  background-size: 15px;
  padding-right: 2.1rem;
  appearance: none;
}
[data-bs-theme="dark"] .form-select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%239aaac2' stroke-width='1.6' stroke-linecap='round'%3E%3Cpath d='M4 6.5 8 10.5 12 6.5'/%3E%3C/svg%3E");
}

.form-check-input {
  border-color: var(--rule-strong);
  background-color: var(--surface);
}
.form-check-input:checked {
  background-color: var(--seal);
  border-color: var(--seal);
}
.form-check-input:focus {
  border-color: var(--seal);
  box-shadow: 0 0 0 3px rgba(142, 36, 52, 0.16);
}
.form-check-label { font-size: var(--t-sm); color: var(--text-secondary); }

.input-group > .form-control { border-radius: var(--r-sm) 0 0 var(--r-sm); }
.input-group > .btn { border-radius: 0 var(--r-sm) var(--r-sm) 0; }
.input-group-text {
  background: var(--surface-2);
  border-color: var(--rule-strong);
  color: var(--text-muted);
  font-size: var(--t-sm);
}

/* Validation */
.form-control[aria-invalid="true"],
.form-control.is-invalid {
  border-color: var(--band-critical);
  background-image: none;
}
.field-error,
.invalid-feedback {
  display: block;
  font-size: var(--t-xs);
  font-weight: 500;
  color: var(--band-critical);
  margin-top: 0.3rem;
}
.field-error:empty,
.invalid-feedback:empty { display: none; }

/* Filter bar above a table */
.filter-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--s-3);
  padding: var(--s-4) var(--s-5);
  background: var(--surface-2);
  border: 1px solid var(--rule);
  border-bottom: 0;
  border-radius: var(--r-md) var(--r-md) 0 0;
}
.filter-bar .field { margin-bottom: 0; flex: 1 1 170px; min-width: 0; }
.filter-bar .filter-actions { display: flex; gap: var(--s-2); flex-wrap: wrap; }

/* ── 9 · TABLES — THE RANKING LEDGER ─────────────────────────────────── */
.table-frame {
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  background: var(--surface);
  overflow: hidden;
}
.filter-bar + .table-frame { border-radius: 0 0 var(--r-md) var(--r-md); }

/* Horizontal scroll is confined to this wrapper, never the page. */
.table-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
}

table.ledger,
.table {
  width: 100%;
  margin: 0;
  border-collapse: collapse;
  font-size: var(--t-sm);
  color: var(--text);
  background: var(--surface);
}

table.ledger thead th,
.table > thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--surface-2);
  color: var(--text-secondary);
  font-size: var(--t-2xs);
  font-weight: 600;
  letter-spacing: 0.02em;
  text-align: left;
  padding: 0.6rem 0.75rem;
  border-bottom: 1px solid var(--rule-strong);
  white-space: nowrap;
}

table.ledger tbody td,
.table > tbody td {
  padding: 0.6rem 0.75rem;
  border-bottom: 1px solid var(--rule-soft);
  vertical-align: middle;
  background: transparent;
}

table.ledger tbody tr,
.table > tbody tr { transition: background-color var(--dur-1) var(--ease-out); }
table.ledger tbody tr:hover,
.table > tbody tr:hover { background: var(--surface-2); }
table.ledger tbody tr:last-child td,
.table > tbody tr:last-child td { border-bottom: 0; }

/* Numeric columns: right-aligned, tabular, never wrapping. */
.ledger .num,
.table .num,
td.num,
th.num {
  text-align: right;
  white-space: nowrap;
  font-variant-numeric: tabular-nums lining-nums;
}

/* Rank column: the serif numeral is the signature of the ledger. */
.rank-no {
  font-size: var(--t-md);
  font-weight: 600;
  color: var(--text-secondary);
  text-align: right;
  width: 1%;
  white-space: nowrap;
}
.rank-no[data-medal="1"] { color: var(--brass); }
.rank-no[data-medal="2"],
.rank-no[data-medal="3"] { color: var(--text); }

.ledger-institution { min-width: 200px; }
.ledger-institution .name {
  font-weight: 600;
  color: var(--text);
  text-decoration: none;
  display: block;
  line-height: 1.3;
}
.ledger-institution .name:hover { color: var(--seal); text-decoration: underline; }
.ledger-institution .domain {
  font-size: var(--t-2xs);
  color: var(--text-muted);
  display: block;
  word-break: break-all;
}

/* Sortable headers */
th.sortable { padding: 0; }
th.sortable > a,
th.sortable > button {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  width: 100%;
  padding: 0.6rem 0.75rem;
  color: inherit;
  font: inherit;
  text-decoration: none;
  background: none;
  border: 0;
  cursor: pointer;
  transition: color var(--dur-1) var(--ease-out), background-color var(--dur-1) var(--ease-out);
}
th.sortable.num > a,
th.sortable.num > button { justify-content: flex-end; }
th.sortable > a:hover,
th.sortable > button:hover { color: var(--text); background: var(--surface-3); }
th.sortable .sort-mark { opacity: 0.35; font-size: 0.8em; transition: opacity var(--dur-1) var(--ease-out); }
th[aria-sort="ascending"] .sort-mark,
th[aria-sort="descending"] .sort-mark { opacity: 1; color: var(--seal); }
th[aria-sort] > a,
th[aria-sort] > button { color: var(--text); }

.table-caption,
caption {
  caption-side: top;
  padding: var(--s-3) var(--s-4);
  font-size: var(--t-xs);
  color: var(--text-muted);
  text-align: left;
}

/* A table used purely as the accessible alternative to a chart. */
.visually-hidden-table { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* ── 10 · BADGES, CHIPS, METERS ──────────────────────────────────────── */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.12rem 0.5rem;
  border-radius: var(--r-sm);
  font-size: var(--t-2xs);
  font-weight: 600;
  line-height: 1.55;
  border: 1px solid transparent;
  white-space: nowrap;
}
.chip-neutral { background: var(--surface-3); color: var(--text-secondary); border-color: var(--rule); }
.chip-seal { background: var(--seal-soft); color: var(--seal); border-color: var(--seal-line); }
.chip-brass { background: var(--brass-soft); color: var(--brass); border-color: var(--brass-line); }
.chip-good { background: var(--verdigris-soft); color: var(--verdigris); border-color: var(--verdigris-line); }
.chip-warn { background: var(--band-low-soft); color: var(--band-low); border-color: var(--band-low); }
.chip-bad { background: var(--band-critical-soft); color: var(--band-critical); border-color: var(--band-critical); }

.badge {
  --bs-badge-border-radius: var(--r-sm);
  --bs-badge-font-size: var(--t-2xs);
  --bs-badge-font-weight: 600;
  --bs-badge-padding-x: 0.5rem;
  --bs-badge-padding-y: 0.22rem;
}

/* Score band colouring, driven by data-band so PHP and JS agree. */
[data-band="high"] { --band: var(--band-high); --band-soft: var(--band-high-soft); }
[data-band="upper"] { --band: var(--band-upper); --band-soft: var(--band-upper-soft); }
[data-band="mid"] { --band: var(--band-mid); --band-soft: var(--band-mid-soft); }
[data-band="low"] { --band: var(--band-low); --band-soft: var(--band-low-soft); }
[data-band="critical"] { --band: var(--band-critical); --band-soft: var(--band-critical-soft); }
[data-band="none"] { --band: var(--band-none); --band-soft: var(--band-none-soft); }

.score-figure {
  font-family: var(--font-display);
  font-variant-numeric: tabular-nums lining-nums;
  font-weight: 600;
  color: var(--band, var(--text));
}

.score-chip {
  display: inline-flex;
  align-items: baseline;
  gap: 0.15rem;
  padding: 0.1rem 0.45rem;
  border-radius: var(--r-sm);
  background: var(--band-soft, var(--surface-3));
  color: var(--band, var(--text-secondary));
  border: 1px solid currentColor;
  font-family: var(--font-display);
  font-variant-numeric: tabular-nums lining-nums;
  font-weight: 600;
  font-size: var(--t-sm);
  white-space: nowrap;
}

/* The measure bar: a thin horizontal rule showing a 0-100 value in place. */
.measure {
  position: relative;
  height: 5px;
  background: var(--surface-3);
  border-radius: var(--r-pill);
  overflow: hidden;
  min-width: 48px;
}
/* The bar's value is carried by --target, set on the element by whatever
   renders it. Setting it in the markup means the bar is drawn correctly with
   no script at all; the draw animation is only how it arrives, never whether
   it arrives. Bars built at runtime leave --target unset and are painted by
   script, which is why the transition stays. */
.measure > span {
  display: block;
  height: 100%;
  background: var(--band, var(--ink-600));
  border-radius: inherit;
  width: var(--target, 0);
  transform-origin: left center;
  transition: width var(--dur-4) var(--ease-out);
  animation: track-draw var(--dur-4) var(--ease-out) both;
}
.measure-lg { height: 8px; }

.measure-row {
  display: flex;
  align-items: center;
  gap: var(--s-3);
}
.measure-row .measure { flex: 1 1 auto; }
.measure-row .score-figure { flex: 0 0 auto; min-width: 3.2rem; text-align: right; }

/* Delta: direction is carried by the arrow glyph as well as the colour, so
   it does not rely on colour alone. */
.delta {
  font-family: var(--font-display);
  font-variant-numeric: tabular-nums lining-nums;
  font-weight: 600;
  font-size: var(--t-xs);
  white-space: nowrap;
}
.delta-up { color: var(--verdigris); }
.delta-down { color: var(--band-critical); }
.delta-flat { color: var(--text-muted); }

/* Grade seal: a small struck disc, used once per report. */
.grade-seal {
  display: inline-grid;
  place-items: center;
  width: 3.4rem;
  height: 3.4rem;
  border-radius: 50%;
  border: 2px solid var(--band, var(--rule-strong));
  background: var(--band-soft, var(--surface-2));
  color: var(--band, var(--text));
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--t-lg);
  line-height: 1;
  flex: 0 0 auto;
}
.grade-seal-lg { width: 5rem; height: 5rem; font-size: var(--t-2xl); border-width: 3px; }

/* ── 11 · FEEDBACK ───────────────────────────────────────────────────── */
.alert {
  --bs-alert-border-radius: var(--r-md);
  display: flex;
  align-items: flex-start;
  gap: 0.65rem;
  padding: var(--s-3) var(--s-4);
  font-size: var(--t-sm);
  border: 1px solid;
  border-left-width: 3px;
  margin-bottom: var(--s-3);
  color: var(--text);
  background: var(--surface);
}
.alert > .alert-icon { flex: 0 0 auto; margin-top: 0.1em; }
.alert > .alert-body { flex: 1 1 auto; min-width: 0; }
.alert p:last-child { margin-bottom: 0; }

.alert-success { background: var(--verdigris-soft); border-color: var(--verdigris); color: var(--text); }
.alert-danger { background: var(--band-critical-soft); border-color: var(--band-critical); }
.alert-warning { background: var(--band-low-soft); border-color: var(--band-low); }
.alert-info { background: var(--band-upper-soft); border-color: var(--band-upper); }
.alert-success .alert-icon { color: var(--verdigris); }
.alert-danger .alert-icon { color: var(--band-critical); }
.alert-warning .alert-icon { color: var(--band-low); }
.alert-info .alert-icon { color: var(--band-upper); }

.btn-close {
  --bs-btn-close-color: var(--text);
  opacity: 0.45;
  transition: opacity var(--dur-1) var(--ease-out);
}
.btn-close:hover { opacity: 1; }
[data-bs-theme="dark"] .btn-close { filter: invert(1) grayscale(1) brightness(2); }

/* Toasts */
.toast-stack {
  position: fixed;
  right: var(--s-4);
  bottom: var(--s-4);
  z-index: 1090;
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  width: min(360px, calc(100vw - 2rem));
  pointer-events: none;
}
.toast-item {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  padding: 0.7rem 0.85rem;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-left: 3px solid var(--rule-strong);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-overlay);
  font-size: var(--t-sm);
  color: var(--text);
  pointer-events: auto;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity var(--dur-3) var(--ease-out), transform var(--dur-3) var(--ease-out);
}
.toast-item[data-visible="true"] { opacity: 1; transform: translateY(0); }
.toast-item[data-tone="success"] { border-left-color: var(--verdigris); }
.toast-item[data-tone="error"] { border-left-color: var(--band-critical); }
.toast-item[data-tone="warning"] { border-left-color: var(--band-low); }
.toast-item[data-tone="info"] { border-left-color: var(--band-upper); }
.toast-item .toast-close {
  margin-left: auto;
  border: 0;
  background: none;
  color: var(--text-muted);
  cursor: pointer;
  padding: 0 0.2rem;
  line-height: 1;
  font-size: 1.1rem;
}
.toast-item .toast-close:hover { color: var(--text); }

/* Modals */
.modal-content {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-overlay);
  color: var(--text);
}
.modal-header {
  border-bottom: 1px solid var(--rule);
  padding: var(--s-4) var(--s-5);
}
.modal-title { font-size: var(--t-md); margin: 0; }
.modal-body { padding: var(--s-5); }
.modal-footer {
  border-top: 1px solid var(--rule);
  padding: var(--s-3) var(--s-5);
  gap: var(--s-2);
}
.modal-backdrop { --bs-backdrop-bg: #0c1a2e; --bs-backdrop-opacity: 0.55; }

.tooltip-inner {
  background: var(--ink-900);
  color: #fff;
  font-size: var(--t-2xs);
  border-radius: var(--r-sm);
  padding: 0.35rem 0.55rem;
  max-width: 260px;
}
.tooltip .tooltip-arrow::before { border-top-color: var(--ink-900); }

/* ── 12 · EMPTY STATES, SKELETONS, PAGINATION ────────────────────────── */
.empty-state {
  text-align: center;
  padding: var(--s-7) var(--s-5);
  max-width: 42ch;
  margin-inline: auto;
}
.empty-state .empty-mark {
  display: inline-grid;
  place-items: center;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  border: 1px solid var(--rule);
  background: var(--surface-2);
  color: var(--text-muted);
  font-size: 1.3rem;
  margin-bottom: var(--s-4);
}
.empty-state h3 { font-size: var(--t-md); margin-bottom: var(--s-2); }
.empty-state p { color: var(--text-muted); font-size: var(--t-sm); margin-bottom: var(--s-4); }
.empty-state > :last-child { margin-bottom: 0; }

.skeleton {
  background: linear-gradient(
    90deg,
    var(--surface-3) 0%,
    var(--surface-2) 40%,
    var(--surface-3) 80%
  );
  background-size: 300% 100%;
  border-radius: var(--r-sm);
  animation: skeleton-sweep 1.4s ease-in-out infinite;
  color: transparent;
  user-select: none;
}
.skeleton-line { height: 0.75rem; margin-bottom: 0.5rem; }
.skeleton-line:last-child { margin-bottom: 0; width: 65%; }
.skeleton-row { height: 2.6rem; margin-bottom: 1px; border-radius: 0; }
.skeleton-figure { height: 2.4rem; width: 4.5rem; }

@keyframes skeleton-sweep {
  0% { background-position: 100% 0; }
  100% { background-position: 0 0; }
}

.pagination {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem;
  list-style: none;
  margin: var(--s-5) 0 0;
  padding: 0;
}
.pagination li { display: flex; }
.pagination a,
.pagination span {
  display: inline-grid;
  place-items: center;
  min-width: 2.15rem;
  height: 2.15rem;
  padding-inline: 0.5rem;
  border: 1px solid var(--rule);
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--text-secondary);
  font-size: var(--t-sm);
  font-variant-numeric: tabular-nums;
  text-decoration: none;
  transition: background-color var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}
.pagination a:hover { background: var(--surface-2); border-color: var(--rule-strong); color: var(--text); }
.pagination [aria-current="page"] {
  background: var(--seal);
  border-color: var(--seal);
  color: #fff;
  font-weight: 600;
}
[data-bs-theme="dark"] .pagination [aria-current="page"] { color: #1a0d10; }
.pagination .gap { border: 0; background: none; color: var(--text-muted); min-width: 1.4rem; }
.pagination .disabled span { opacity: 0.4; cursor: not-allowed; }

.pagination-meta {
  font-size: var(--t-xs);
  color: var(--text-muted);
  margin-top: var(--s-3);
}

/* Progress */
.progress {
  --bs-progress-bg: var(--surface-3);
  --bs-progress-border-radius: var(--r-pill);
  --bs-progress-bar-bg: var(--seal);
  height: 8px;
}

/* ── 13 · HOME / LANDING ─────────────────────────────────────────────── */
.hero {
  position: relative;
  background: var(--ink-800);
  color: var(--text-on-ink);
  overflow: hidden;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}
[data-bs-theme="dark"] .hero { background: #0e1726; }

/* A plotted grid, as on graph paper — the ground an index is drawn on. */
.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.045) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.045) 1px, transparent 1px);
  background-size: 56px 56px;
  mask-image: radial-gradient(120% 90% at 15% 0%, #000 20%, transparent 75%);
  -webkit-mask-image: radial-gradient(120% 90% at 15% 0%, #000 20%, transparent 75%);
  pointer-events: none;
}

.hero-inner {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1.06fr) minmax(0, 0.94fr);
  gap: clamp(2rem, 4vw, 4.5rem);
  align-items: start;
  padding-block: clamp(2.75rem, 1.5rem + 5.5vw, 5.5rem);
}
/* The lead column keeps its own rhythm so the form sits at the optical centre
   of the hero rather than floating at its top. */
.hero-lead { display: flex; flex-direction: column; }

.hero-rule {
  width: 56px;
  height: 3px;
  background: var(--seal);
  border-radius: 2px;
  margin-bottom: var(--s-4);
  transform-origin: left center;
}
[data-bs-theme="dark"] .hero-rule { background: #d9636f; }

.hero h1 {
  color: #fff;
  font-size: clamp(2.125rem, 1.2rem + 4vw, 3.9rem);
  line-height: 1.02;
  letter-spacing: -0.03em;
  margin-bottom: var(--s-4);
  max-width: 17ch;
  text-wrap: balance;
}
.hero-lede {
  color: var(--text-on-ink);
  font-size: clamp(1.0625rem, 0.98rem + 0.42vw, 1.25rem);
  line-height: 1.62;
  max-width: 50ch;
  margin-bottom: var(--s-5);
}

.hero-form { max-width: 36rem; }
.hero-form .input-group { box-shadow: 0 8px 24px -10px rgba(0, 0, 0, 0.5); border-radius: var(--r-md); }
.hero-form .form-control {
  border: 1px solid transparent;
  border-radius: var(--r-md) 0 0 var(--r-md);
  padding: 0.85rem 1rem;
  font-size: var(--t-base);
  background: #fff;
  color: var(--ink-900);
}
.hero-form .form-control::placeholder { color: #6b7c94; }
.hero-form .form-control:focus {
  box-shadow: none;
  border-color: #e2c98a;
  outline: 2px solid #e2c98a;
  outline-offset: -2px;
}
.hero-form .btn {
  border-radius: 0 var(--r-md) var(--r-md) 0;
  padding-inline: 1.25rem;
  font-size: var(--t-base);
}
.hero-note {
  font-size: var(--t-xs);
  color: var(--text-on-ink-muted);
  margin-top: var(--s-3);
  margin-bottom: 0;
}
.hero-note a { color: #e2c98a; }
.hero-note a:hover { color: #f0dcac; }

/* The running totals, set as a graduated strip: hairline dividers between the
   figures make them read as one instrument panel rather than four stray stats. */
.hero-figures {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  margin-top: auto;
  padding-top: var(--s-5);
  border-top: 1px solid rgba(255, 255, 255, 0.16);
}
.hero-figure {
  padding-right: var(--s-4);
  border-right: 1px solid rgba(255, 255, 255, 0.1);
  min-width: 0;
}
.hero-figure + .hero-figure { padding-left: var(--s-4); }
.hero-figure:last-child { border-right: 0; padding-right: 0; }
.hero-figure .figure-lg {
  color: #fff;
  font-size: clamp(1.75rem, 1.2rem + 1.6vw, 2.625rem);
}
.hero-figure .stat-label { color: var(--text-on-ink-muted); }

/* The leaderboard shown in the hero: live data, not an illustration. */
.hero-board {
  background: rgba(255, 255, 255, 0.045);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: var(--r-md);
  overflow: hidden;
  backdrop-filter: blur(2px);
}
.hero-board-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-3);
  padding: 0.7rem 0.9rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.14);
  font-size: var(--t-2xs);
  color: var(--text-on-ink-muted);
  font-weight: 600;
}
.hero-board-list {
  list-style: none;
  margin: 0;
  padding: 0;
}
.hero-board-row {
  display: grid;
  grid-template-columns: 2rem minmax(0, 1fr) auto;
  align-items: center;
  gap: 0.75rem;
  padding: 0.7rem 1rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  color: var(--text-on-ink);
  text-decoration: none;
  transition:
    background-color var(--dur-2) var(--ease-out),
    padding-left var(--dur-2) var(--ease-out);
}
.hero-board-list li:last-child .hero-board-row { border-bottom: 0; }
.hero-board-row:hover,
.hero-board-row:focus-visible {
  background: rgba(255, 255, 255, 0.09);
  color: #fff;
  padding-left: 1.35rem;
}
.hero-board-row:focus-visible { outline: 2px solid #e2c98a; outline-offset: -2px; }
.hero-board-row:hover .hero-board-track > span,
.hero-board-row:focus-visible .hero-board-track > span { background: #e2c98a; }

/* A hairline under each name showing where that index sits on 0–100. It is the
   same scale as everything else on the page, so rows compare at a glance. */
.hero-board-track {
  display: block;
  height: 2px;
  margin-top: 0.4rem;
  background: rgba(255, 255, 255, 0.14);
  border-radius: var(--r-pill);
  overflow: hidden;
}
.hero-board-track > span {
  display: block;
  height: 100%;
  width: var(--v, 0%);
  background: rgba(255, 255, 255, 0.55);
  border-radius: inherit;
  transform-origin: left center;
  animation: track-draw var(--dur-4) var(--ease-out) both;
  animation-delay: 420ms;
  transition: background-color var(--dur-2) var(--ease-out);
}
@keyframes track-draw {
  from { transform: scaleX(0); }
  to { transform: scaleX(1); }
}
.hero-board-rank {
  font-family: var(--font-display);
  font-variant-numeric: tabular-nums lining-nums;
  font-weight: 600;
  font-size: var(--t-base);
  color: var(--text-on-ink-muted);
  text-align: right;
}
.hero-board-list li:first-child .hero-board-rank { color: #e2c98a; }
.hero-board-name {
  font-size: var(--t-sm);
  font-weight: 500;
  min-width: 0;
}
.hero-board-label,
.hero-board-name small {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.hero-board-name small {
  font-size: var(--t-3xs);
  color: var(--text-on-ink-muted);
  margin-top: 0.1rem;
}
.hero-board-score {
  font-family: var(--font-display);
  font-variant-numeric: tabular-nums lining-nums;
  font-weight: 600;
  font-size: var(--t-lg);
  color: #fff;
}
.hero-board-foot {
  padding: 0.75rem 1rem;
  border-top: 1px solid rgba(255, 255, 255, 0.14);
  font-size: var(--t-xs);
}
.hero-board-foot a { color: #e2c98a; text-decoration: none; font-weight: 600; }
.hero-board-foot a:hover { color: #f0dcac; text-decoration: underline; }

/* Nothing measured yet: four ruled slots stand ready rather than a shrug. The
   slots are the shape the table will take, so the empty state is a promise. */
.hero-board-empty { padding: var(--s-5) 1rem var(--s-6); }
.hero-board-empty-plate {
  display: grid;
  gap: 0.65rem;
  margin-bottom: var(--s-5);
}
.hero-board-empty-plate span {
  display: block;
  height: 2px;
  background: rgba(255, 255, 255, 0.14);
  border-radius: var(--r-pill);
}
.hero-board-empty-plate span:nth-child(1) { width: 82%; }
.hero-board-empty-plate span:nth-child(2) { width: 64%; }
.hero-board-empty-plate span:nth-child(3) { width: 51%; }
.hero-board-empty-plate span:nth-child(4) { width: 38%; }
.hero-board-empty p {
  font-size: var(--t-sm);
  color: var(--text-on-ink-muted);
  margin: 0;
  line-height: var(--leading-relaxed);
}

/* ── The leader's dimension profile, inside the hero plate ─────────────── */
.profile-plate {
  padding: var(--s-5) 1rem var(--s-4);
  border-top: 1px solid rgba(255, 255, 255, 0.14);
  background: rgba(0, 0, 0, 0.12);
}
.profile-title {
  font-family: var(--font-text);
  font-size: var(--t-2xs);
  font-weight: 600;
  color: var(--text-on-ink-muted);
  letter-spacing: 0.01em;
  margin: 0 0 var(--s-4);
  display: flex;
  flex-wrap: wrap;
  gap: 0.15rem 0.5rem;
}
.profile-title span {
  font-family: var(--font-display);
  font-size: var(--t-sm);
  font-weight: 600;
  color: #fff;
  letter-spacing: var(--track-tight);
}
.profile-bars { margin: 0; display: grid; gap: 0.7rem; }
.profile-bar { display: grid; grid-template-columns: minmax(0, 1fr); gap: 0.3rem; }
.profile-bar dt {
  font-size: var(--t-2xs);
  color: var(--text-on-ink);
  font-weight: 500;
}
.profile-bar dd {
  margin: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 2.9rem;
  align-items: center;
  gap: 0.6rem;
}
.profile-track {
  display: block;
  height: 9px;
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 2px;
  overflow: hidden;
}
.profile-track > span {
  display: block;
  height: 100%;
  width: var(--v, 0%);
  background: var(--dim, rgba(255, 255, 255, 0.7));
  transform-origin: left center;
  animation: track-draw 620ms var(--ease-out) both;
  animation-delay: calc(480ms + var(--i, 0) * 70ms);
}
.profile-bar:nth-child(1) .profile-track > span { --i: 0; }
.profile-bar:nth-child(2) .profile-track > span { --i: 1; }
.profile-bar:nth-child(3) .profile-track > span { --i: 2; }
.profile-bar:nth-child(4) .profile-track > span { --i: 3; }
.profile-bar b {
  font-family: var(--font-display);
  font-variant-numeric: tabular-nums lining-nums;
  font-size: var(--t-sm);
  font-weight: 600;
  color: #fff;
  text-align: right;
}
.profile-axis {
  display: flex;
  justify-content: space-between;
  margin-top: var(--s-3);
  padding-top: 0.4rem;
  border-top: 1px solid rgba(255, 255, 255, 0.12);
  font-family: var(--font-display);
  font-variant-numeric: tabular-nums lining-nums;
  font-size: var(--t-3xs);
  color: var(--text-on-ink-muted);
}
/* The axis labels stop short of the figure column so they line up with the
   track they measure. */
.profile-axis { padding-right: 3.5rem; }

/* On the hero's dark ground the dimension colours are lifted once, here, so
   the four bars stay legible against navy. */
.profile-bar[data-dim="webometrics"] { --dim: #7fa0d2; }
.profile-bar[data-dim="research"] { --dim: #d87f8b; }
.profile-bar[data-dim="technical"] { --dim: #d2a65a; }
.profile-bar[data-dim="presence"] { --dim: #5fbdb1; }

/* ── The composition plate ─────────────────────────────────────────────
   One hundred units of index, divided exactly as the scoring config divides
   them. Width is the only encoding; height is uniform, so nothing is
   double-counted. */
.weight-plate { margin: 0 0 var(--s-7); }

.weight-band {
  display: flex;
  gap: 3px;
  height: clamp(6.5rem, 4rem + 7vw, 9.5rem);
}
.weight-seg {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  flex-basis: 0;
  min-width: 0;
  padding: var(--s-4) var(--s-4) var(--s-3);
  background: var(--dim);
  color: #fff;
  text-decoration: none;
  border-radius: var(--r-xs);
  border: 1px solid rgba(255, 255, 255, 0.16);
  overflow: hidden;
  transition:
    transform var(--dur-3) var(--ease-out),
    box-shadow var(--dur-3) var(--ease-out),
    filter var(--dur-3) var(--ease-out);
}
.weight-seg[data-dim="webometrics"] { --dim: var(--dim-webometrics); }
.weight-seg[data-dim="research"] { --dim: var(--dim-research); }
.weight-seg[data-dim="technical"] { --dim: var(--dim-technical); }
.weight-seg[data-dim="presence"] { --dim: var(--dim-presence); }

.weight-seg:hover,
.weight-seg:focus-visible {
  transform: translateY(-4px);
  filter: saturate(1.12) brightness(1.08);
  box-shadow: 0 10px 22px -12px rgba(12, 26, 46, 0.55);
}
.weight-seg:focus-visible { outline: 2px solid var(--text); outline-offset: 3px; }

.weight-seg-pct {
  position: relative;
  font-family: var(--font-display);
  font-variant-numeric: tabular-nums lining-nums;
  font-size: clamp(1.75rem, 1.1rem + 2.2vw, 3rem);
  font-weight: 600;
  line-height: 0.92;
  letter-spacing: -0.03em;
}
.weight-seg-pct i {
  font-style: normal;
  font-size: 0.42em;
  font-weight: 600;
  margin-left: 0.06em;
  vertical-align: 0.75em;
  opacity: 0.8;
}
.weight-seg-name,
.weight-seg-short {
  position: relative;
  font-size: var(--t-sm);
  font-weight: 600;
  line-height: 1.25;
  overflow-wrap: anywhere;
}
.weight-seg-short { display: none; }

/* The narrowest segment cannot hold its full name; it shows the short form
   instead of overflowing or shrinking the type below legibility. */
.weight-seg[data-dim="presence"] .weight-seg-name,
.weight-seg[data-dim="technical"] .weight-seg-name { font-size: var(--t-xs); }

/* The axis is the only graduated thing on the plate, and it spans exactly the
   hundred units — so every tick on it means five index points. Minor ticks go
   here rather than inside the blocks, where they would measure nothing. */
.weight-axis {
  position: relative;
  height: 1.9rem;
  margin-top: 0.55rem;
  border-top: 1px solid var(--rule-strong);
}
.weight-axis::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 4px;
  background-image: repeating-linear-gradient(
    90deg,
    var(--rule-strong) 0 1px,
    transparent 1px 5%
  );
}
.weight-mark {
  position: absolute;
  top: 0;
  transform: translateX(-50%);
  padding-top: 0.45rem;
  font-family: var(--font-display);
  font-variant-numeric: tabular-nums lining-nums;
  font-size: var(--t-2xs);
  color: var(--text-muted);
}
.weight-mark::before {
  content: "";
  position: absolute;
  top: 0;
  left: 50%;
  width: 1px;
  height: 6px;
  background: var(--rule-strong);
}
.weight-mark.is-first { transform: none; }
.weight-mark.is-first::before { left: 0; }
.weight-mark.is-last { transform: translateX(-100%); }
.weight-mark.is-last::before { left: auto; right: 0; }

.weight-plate figcaption {
  margin-top: var(--s-3);
  font-size: var(--t-xs);
  color: var(--text-muted);
  max-width: 74ch;
}

/* ── The four dimensions, as a two-by-two plate ────────────────────────── */
.dimension-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  overflow: hidden;
}
.dimension {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  padding: var(--s-6) var(--s-5) var(--s-5);
  transition: background-color var(--dur-2) var(--ease-out);
}
.dimension[data-dim="webometrics"] { --dim: var(--dim-webometrics); --dim-ink: var(--dim-webometrics-ink); }
.dimension[data-dim="research"] { --dim: var(--dim-research); --dim-ink: var(--dim-research-ink); }
.dimension[data-dim="technical"] { --dim: var(--dim-technical); --dim-ink: var(--dim-technical-ink); }
.dimension[data-dim="presence"] { --dim: var(--dim-presence); --dim-ink: var(--dim-presence-ink); }
.dimension:hover { background: var(--surface-inset); }

/* Each cell repeats its own share along its top edge, so the four cells are a
   second reading of the plate above. */
.dimension-rule {
  position: absolute;
  top: 0;
  left: 0;
  height: 3px;
  width: var(--w, 0%);
  background: var(--dim-ink, var(--seal));
  transform-origin: left center;
  transition: filter var(--dur-2) var(--ease-out);
}
.dimension:hover .dimension-rule { filter: brightness(1.15); }

.dimension-weight {
  font-family: var(--font-display);
  font-variant-numeric: tabular-nums lining-nums;
  font-size: clamp(1.75rem, 1.4rem + 1.1vw, 2.375rem);
  font-weight: 600;
  color: var(--dim-ink, var(--seal));
  line-height: 1;
  letter-spacing: -0.03em;
  margin-bottom: var(--s-4);
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
}
.dimension-weight i {
  font-style: normal;
  font-size: 0.46em;
  vertical-align: 0.6em;
  margin-left: -0.35rem;
}
.dimension-weight small {
  font-family: var(--font-text);
  font-size: var(--t-2xs);
  font-weight: 500;
  color: var(--text-muted);
  letter-spacing: 0.01em;
}
.dimension h3 { font-size: var(--t-lg); margin-bottom: 0.5rem; }
.dimension-body {
  color: var(--text-secondary);
  font-size: var(--t-base);
  line-height: var(--leading-normal);
  margin-bottom: var(--s-4);
  max-width: 54ch;
}
/* The provenance line sits on the cell floor, so the four rules line up across
   a row however unevenly the descriptions run. */
.dimension .sources {
  font-size: var(--t-xs);
  color: var(--text-muted);
  margin: auto 0 0;
  padding-top: var(--s-3);
  border-top: 1px solid var(--rule-soft);
}

/* ── Distribution and activity, side by side ───────────────────────────── */
.split-plate {
  display: grid;
  grid-template-columns: minmax(0, 1.22fr) minmax(0, 1fr);
  gap: clamp(2rem, 4vw, 4rem);
  align-items: start;
}

.dist-plate { margin: 0 0 var(--s-5); }
.dist-chart {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}
.dist-grid line { stroke: var(--rule-soft); stroke-width: 1; }
.dist-grid line.dist-base { stroke: var(--rule-strong); }
.dist-grid text {
  fill: var(--text-muted);
  font-family: var(--font-display);
  font-size: 13px;
  font-variant-numeric: tabular-nums lining-nums;
}
.dist-col[data-band="critical"] { --band: var(--band-critical); }
.dist-col[data-band="low"] { --band: var(--band-low); }
.dist-col[data-band="mid"] { --band: var(--band-mid); }
.dist-col[data-band="upper"] { --band: var(--band-upper); }
.dist-col[data-band="high"] { --band: var(--band-high); }
.dist-bar {
  fill: var(--band, var(--ink-600));
  transform-box: view-box;
  animation: bar-rise 620ms var(--ease-out) both;
  animation-delay: calc(120ms + var(--i, 0) * 70ms);
}
@keyframes bar-rise {
  from { transform: scaleY(0); }
  to { transform: scaleY(1); }
}
.dist-ghost {
  fill: none;
  stroke: var(--rule-strong);
  stroke-width: 1;
  stroke-dasharray: 3 3;
}
.dist-count {
  fill: var(--text);
  font-family: var(--font-display);
  font-variant-numeric: tabular-nums lining-nums;
  font-weight: 600;
  font-size: 17px;
}
.dist-col.is-empty .dist-count { fill: var(--text-muted); font-weight: 400; }
.dist-range {
  fill: var(--text-secondary);
  font-family: var(--font-display);
  font-variant-numeric: tabular-nums lining-nums;
  font-size: 14px;
}
.dist-share {
  fill: var(--text-muted);
  font-family: var(--font-text);
  font-size: 12px;
}
.dist-plate figcaption {
  margin-top: var(--s-3);
  font-size: var(--t-xs);
  color: var(--text-muted);
}
.dist-table .dist-band-name { font-weight: 500; }
.dist-table tbody tr td:last-child,
.dist-table tbody tr th { transition: color var(--dur-1) var(--ease-out); }
.dist-table tbody tr:hover th { color: var(--band, var(--text)); }

.ledger-date { color: var(--text-muted); font-size: var(--t-xs); white-space: nowrap; }

/* ── Source provenance, as a ruled matrix ──────────────────────────────── */
.source-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1px;
  background: var(--rule-soft);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  overflow: hidden;
}
.source-item {
  position: relative;
  background: var(--surface);
  padding: var(--s-5) var(--s-4);
  transition: background-color var(--dur-2) var(--ease-out);
}
.source-item[data-dim="webometrics"] { --dim-ink: var(--dim-webometrics-ink); }
.source-item[data-dim="research"] { --dim-ink: var(--dim-research-ink); }
.source-item[data-dim="technical"] { --dim-ink: var(--dim-technical-ink); }
.source-item[data-dim="presence"] { --dim-ink: var(--dim-presence-ink); }
.source-item::before {
  /* Which dimension this source feeds, shown as a mark that only fills on
     attention — quiet until asked. */
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 3px;
  background: var(--dim-ink, var(--rule));
  transform: scaleY(0);
  transform-origin: top center;
  transition: transform var(--dur-3) var(--ease-out);
}
.source-item:hover { background: var(--surface-inset); }
.source-item:hover::before { transform: scaleY(1); }
.source-item .source-name {
  font-weight: 600;
  font-size: var(--t-base);
  display: block;
  margin-bottom: 0.2rem;
  letter-spacing: var(--track-tight);
}
.source-item .source-what {
  font-size: var(--t-xs);
  color: var(--text-muted);
  line-height: 1.45;
  display: block;
}

/* ── Methodology: commentary beside the figures ────────────────────────── */
.method-split {
  display: grid;
  grid-template-columns: minmax(0, 4fr) minmax(0, 7fr);
  gap: var(--s-6) clamp(2rem, 4vw, 4.5rem);
  align-items: start;
}
.method-split-text { align-items: start; }
.method-split-text .prose { max-width: none; }
.method-split-text .prose p { max-width: 66ch; }

.method-aside .section-head { margin-bottom: var(--s-5); }
.method-aside .section-head p { font-size: var(--t-base); }

/* Each dimension keeps the colour it has on the landing plate, so the two
   pages describe the same four things in the same terms. */
section[data-dim="webometrics"] { --dim: var(--dim-webometrics); --dim-ink: var(--dim-webometrics-ink); }
section[data-dim="research"] { --dim: var(--dim-research); --dim-ink: var(--dim-research-ink); }
section[data-dim="technical"] { --dim: var(--dim-technical); --dim-ink: var(--dim-technical-ink); }
section[data-dim="presence"] { --dim: var(--dim-presence); --dim-ink: var(--dim-presence-ink); }
section[data-dim] .section-head::before { background: var(--dim-ink, var(--seal)); }

.method-share {
  display: flex;
  align-items: baseline;
  gap: 0.55rem;
  margin: 0 0 0.5rem;
}
.method-share b {
  font-family: var(--font-display);
  font-variant-numeric: tabular-nums lining-nums;
  font-size: clamp(2rem, 1.5rem + 1.6vw, 2.75rem);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.03em;
  color: var(--dim-ink, var(--seal));
}
.method-share b i {
  font-style: normal;
  font-size: 0.44em;
  vertical-align: 0.65em;
  margin-left: 0.04em;
}
.method-share span {
  font-size: var(--t-xs);
  color: var(--text-muted);
}
.method-share-rule {
  display: block;
  height: 3px;
  width: 100%;
  background: var(--rule);
  border-radius: var(--r-pill);
  overflow: hidden;
  position: relative;
}
.method-share-rule::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: var(--w, 0%);
  background: var(--dim-ink, var(--seal));
  border-radius: inherit;
}
.method-count {
  margin: var(--s-3) 0 0;
  font-size: var(--t-xs);
  color: var(--text-muted);
}

@media (max-width: 899.98px) {
  .method-split { grid-template-columns: minmax(0, 1fr); }
}

/* ── Closing band ─────────────────────────────────────────────────────── */
.closing-band {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4) var(--s-6);
  margin-top: var(--s-7);
  padding-top: var(--s-5);
  border-top: 2px solid var(--ink-800);
}
.closing-band p {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--t-lg);
  line-height: 1.35;
  color: var(--text);
  max-width: 44ch;
}
.closing-band .cluster { gap: var(--s-3); }

/* Footer */
.site-footer {
  background: var(--ink-900);
  color: var(--text-on-ink);
  border-top: 3px solid var(--seal);
  margin-top: var(--s-8);
}
[data-bs-theme="dark"] .site-footer { background: #080f1a; }
.site-footer a { color: var(--text-on-ink); text-decoration: none; }
.site-footer a:hover { color: #fff; text-decoration: underline; }
.footer-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: var(--s-6);
  padding-block: var(--s-7) var(--s-6);
}
.footer-col h2 {
  font-family: var(--font-text);
  font-size: var(--t-2xs);
  font-weight: 600;
  color: var(--text-on-ink-muted);
  margin-bottom: var(--s-3);
}
.footer-col ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.5rem; font-size: var(--t-sm); }
.footer-bottom {
  border-top: 1px solid rgba(255, 255, 255, 0.12);
  padding-block: var(--s-4);
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--s-3);
  font-size: var(--t-xs);
  color: var(--text-on-ink-muted);
}

/* ── 14 · MOTION ─────────────────────────────────────────────────────── */
/* One orchestrated entrance on the landing page. Everything else in the
   product responds to an action rather than to scrolling. */
.enter {
  opacity: 0;
  transform: translateY(10px);
  animation: enter-up var(--dur-4) var(--ease-out) forwards;
  animation-delay: calc(var(--enter-step, 0) * 70ms);
}
@keyframes enter-up {
  to { opacity: 1; transform: translateY(0); }
}

.enter-rule {
  animation: rule-draw 520ms var(--ease-out) forwards;
  transform: scaleX(0);
}
@keyframes rule-draw {
  to { transform: scaleX(1); }
}

/* Reveal on scroll, applied sparingly and only where a section genuinely
   benefits from being introduced.

   The hidden state is gated behind .js-reveal, which only a working script
   puts on <html>. With scripting off, with the observer never firing, or if
   app.js fails to load, the class is absent or removed again and the content
   is simply visible — a reveal must never be the thing that decides whether
   a page has content. */
.js-reveal .reveal {
  opacity: 0;
  transform: translateY(12px);
  transition: opacity var(--dur-4) var(--ease-out), transform var(--dur-4) var(--ease-out);
}
.js-reveal .reveal.is-visible { opacity: 1; transform: none; }

/* Reserve space for async figures so nothing shifts when they arrive. */
.chart-box {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  min-height: 180px;
}
.chart-box > canvas { position: absolute; inset: 0; width: 100% !important; height: 100% !important; }
.chart-box-tall { aspect-ratio: 4 / 3; }

/* ── 15 · UTILITIES ──────────────────────────────────────────────────── */
.text-muted { color: var(--text-muted) !important; }
.text-secondary { color: var(--text-secondary) !important; }
.text-seal { color: var(--seal) !important; }
.text-brass { color: var(--brass) !important; }
.text-good { color: var(--verdigris) !important; }
.text-bad { color: var(--band-critical) !important; }

.bg-surface { background: var(--surface) !important; }
.bg-surface-2 { background: var(--surface-2) !important; }

.rule-top { border-top: 1px solid var(--rule); }
.rule-bottom { border-bottom: 1px solid var(--rule); }

.tabular { font-variant-numeric: tabular-nums lining-nums; }
.serif { font-family: var(--font-display); }

.stack > * + * { margin-top: var(--s-4); }
.stack-sm > * + * { margin-top: var(--s-2); }
.stack-lg > * + * { margin-top: var(--s-6); }

.cluster {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-2);
}

.grid-auto {
  display: grid;
  gap: var(--s-4);
  grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr));
}
.grid-2 {
  display: grid;
  gap: var(--s-5);
  grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
  /* Panels size to their own content rather than stretching to match the
     tallest sibling, which otherwise leaves large empty wells. */
  align-items: start;
}

.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.break-word { word-break: break-word; overflow-wrap: anywhere; }

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

/* Bootstrap's own dark-mode background helpers should follow our surfaces. */
.bg-body,
.bg-white { background-color: var(--surface) !important; }
.bg-body-tertiary,
.bg-light { background-color: var(--surface-2) !important; }
.border { border-color: var(--rule) !important; }
.list-group-item {
  background: var(--surface);
  border-color: var(--rule);
  color: var(--text);
}
.list-group-item.active {
  background: var(--seal);
  border-color: var(--seal);
  color: #fff;
}
[data-bs-theme="dark"] .list-group-item.active { color: #1a0d10; }
.nav-tabs {
  --bs-nav-tabs-border-color: var(--rule);
  --bs-nav-tabs-link-active-bg: var(--surface);
  --bs-nav-tabs-link-active-color: var(--seal);
  --bs-nav-tabs-link-active-border-color: var(--rule) var(--rule) var(--surface);
}
.accordion {
  --bs-accordion-bg: var(--surface);
  --bs-accordion-border-color: var(--rule);
  --bs-accordion-btn-color: var(--text);
  --bs-accordion-active-bg: var(--seal-soft);
  --bs-accordion-active-color: var(--seal);
  --bs-accordion-border-radius: var(--r-md);
}

/* ── 16 · RESPONSIVE ─────────────────────────────────────────────────── */
@media (max-width: 1199.98px) {
  :root { --shell-max: 1100px; }
}

@media (max-width: 1099.98px) {
  .split-plate { grid-template-columns: minmax(0, 1fr); }
  .source-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* Below this the ten-point slice is too narrow to hold a word, so the plate
   turns on its side: height now carries the proportion, full width carries
   the label, and the reading is unchanged. */
@media (max-width: 959.98px) {
  .weight-band {
    flex-direction: column;
    height: auto;
    min-height: 22rem;
    gap: 2px;
  }
  .weight-seg {
    flex-direction: row;
    align-items: center;
    justify-content: flex-start;
    gap: var(--s-4);
    padding: var(--s-3) var(--s-4);
  }
  .weight-seg-pct { font-size: clamp(1.5rem, 1rem + 2vw, 2.25rem); min-width: 3.4rem; }
  .weight-seg-name { font-size: var(--t-sm); }
  .weight-seg[data-dim="presence"] .weight-seg-name,
  .weight-seg[data-dim="technical"] .weight-seg-name { font-size: var(--t-sm); }
  .weight-seg:hover,
  .weight-seg:focus-visible { transform: translateX(4px); }
  .weight-axis { display: none; }
  .dimension-grid { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 991.98px) {
  .hero-inner { grid-template-columns: minmax(0, 1fr); }
  .hero-board { max-width: 38rem; }
  .hero-figures { margin-top: var(--s-6); }
  .nav-main { display: none; }
  .nav-toggle {
    display: inline-grid;
    margin-left: auto;
  }
  .header-search { max-width: none; flex: 1 1 auto; }
}

@media (max-width: 767.98px) {
  :root { --gutter: 1rem; }
  .header-search { display: none; }
  .site-header-inner { min-height: 56px; }
  .hero h1 { max-width: none; }
  .hero-figures { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-4) 0; }
  .hero-figure:nth-child(2n) { border-right: 0; padding-right: 0; }
  .hero-figure:nth-child(2n + 1) { padding-left: 0; }
  .dimension { padding: var(--s-5) var(--s-4) var(--s-4); }
  .dimension-body { font-size: var(--t-sm); }
  .source-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .source-item { padding: var(--s-4) var(--s-3); }
  .closing-band { align-items: flex-start; }
  .closing-band p { font-size: var(--t-md); }
  .stat-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .stat-cell:nth-child(2n) { border-right: 0; }
  .panel { padding: var(--s-4); }
  .panel-head,
  .panel-body,
  .filter-bar { padding: var(--s-4); }
  .toast-stack { left: var(--s-3); right: var(--s-3); width: auto; }
  .modal-body { padding: var(--s-4); }
}

@media (max-width: 575.98px) {
  .hero-form .input-group { flex-wrap: nowrap; }
  .hero-form .form-control { font-size: var(--t-sm); padding: 0.7rem 0.8rem; }
  .hero-form .btn { padding-inline: 0.9rem; font-size: var(--t-sm); }
  .hero-figure .figure-lg { font-size: var(--t-2xl); }
  .source-grid { grid-template-columns: minmax(0, 1fr); }
  .weight-band { min-height: 19rem; }
  .weight-seg-name { display: none; }
  .weight-seg-short { display: block; }
  .stat-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .stat-value { font-size: var(--t-xl); }
  table.ledger thead th,
  .table > thead th,
  table.ledger tbody td,
  .table > tbody td { padding: 0.5rem 0.55rem; }
  .grade-seal-lg { width: 4rem; height: 4rem; font-size: var(--t-xl); }
  .figure-panel { padding: var(--s-4); }
}

/* Sticky first column keeps the institution visible while a wide ranking
   table is scrolled sideways on a phone. */
@media (max-width: 767.98px) {
  .ledger-sticky thead th:first-child,
  .ledger-sticky tbody td:first-child {
    position: sticky;
    left: 0;
    z-index: 1;
    background: var(--surface);
    box-shadow: 1px 0 0 var(--rule-soft);
  }
  .ledger-sticky thead th:first-child { z-index: 3; background: var(--surface-2); }
  .ledger-sticky tbody tr:hover td:first-child { background: var(--surface-2); }
}

/* ── 17 · PRINT AND REDUCED MOTION ───────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  .enter,
  .reveal,
  .hero-board-track > span,
  .profile-track > span,
  .measure > span,
  .dist-bar {
    opacity: 1 !important;
    transform: none !important;
    animation: none !important;
  }
  .enter-rule { transform: scaleX(1) !important; }
  .weight-seg:hover,
  .weight-seg:focus-visible { transform: none; }
  .skeleton { animation: none; }
}

@media print {
  .site-header,
  .site-footer,
  .mobile-nav,
  .nav-scrim,
  .toast-stack,
  .crumbs,
  .no-print { display: none !important; }
  body { background: #fff; color: #000; }
  .panel,
  .table-frame { border-color: #999; break-inside: avoid; }

  /* Printing never scrolls, so nothing may depend on a scroll to appear. */
  .reveal,
  .enter,
  .hero-board-track > span,
  .profile-track > span,
  .measure > span,
  .dist-bar {
    opacity: 1 !important;
    transform: none !important;
    animation: none !important;
  }
  .weight-plate,
  .dist-plate,
  .dimension-grid,
  .source-grid { break-inside: avoid; }
}

/* ═══════════════════════════════════════════════════════════════════════
   18 · LEGACY BRIDGE
   ───────────────────────────────────────────────────────────────────────
   Views and the dashboard stylesheet still name a handful of tokens and
   component classes from the previous design. Rather than leave two visual
   languages in the product, those names are re-pointed at the new system
   here, so every page inherits the identity from one place.
   ═══════════════════════════════════════════════════════════════════════ */
:root {
  --bg-primary: var(--paper);
  --bg-secondary: var(--surface-2);
  --bg-tertiary: var(--surface-3);
  --bg-card: var(--surface);
  --bg-card-hover: var(--surface-2);

  --text-primary: var(--text);
  --border-color: var(--rule);
  --border-light: var(--rule-soft);

  --primary: var(--seal);
  --primary-dark: var(--seal-strong);
  --primary-light: var(--seal-soft);
  --accent: var(--brass);
  --success: var(--verdigris);
  --danger: var(--band-critical);
  --warning: var(--band-low);
  --info: var(--band-upper);

  --font-xs: var(--t-2xs);
  --font-sm: var(--t-xs);
  --font-base: var(--t-sm);
  --font-lg: var(--t-base);
  --font-xl: var(--t-md);
  --font-2xl: var(--t-lg);
  --font-3xl: var(--t-xl);

  --radius-xs: var(--r-xs);
  --radius-sm: var(--r-sm);
  --radius-md: var(--r-md);
  --radius-lg: var(--r-md);
  --radius-xl: var(--r-lg);
  --radius-full: var(--r-pill);

  --shadow-xs: var(--shadow-raised);
  --shadow-sm: var(--shadow-raised);
  --shadow-md: var(--shadow-float);
  --shadow-lg: var(--shadow-float);
  --shadow-xl: var(--shadow-overlay);
  --shadow-2xl: var(--shadow-overlay);

  --transition-fast: var(--dur-1) var(--ease-out);
  --transition-base: var(--dur-2) var(--ease-out);
  --transition-slow: var(--dur-3) var(--ease-out);
}

/* The old glass card becomes the flat ruled panel. */
.glass-card {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  box-shadow: none;
  backdrop-filter: none;
  color: var(--text);
}
.glass-card > .card-header,
.glass-card > .panel-head { border-bottom: 1px solid var(--rule); }

/* Lift on hover is reduced to a rule change: this is a reference product,
   and every panel floating on hover reads as decoration. */
.hover-lift { transition: border-color var(--dur-2) var(--ease-out); }
.hover-lift:hover { border-color: var(--rule-strong); }

/* A label/figure pair inside a panel. */
.metric-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-3);
  padding: 0.5rem 0;
  border-bottom: 1px solid var(--rule-soft);
}
.metric-row:last-child { border-bottom: 0; }
.metric-label {
  font-size: var(--t-sm);
  color: var(--text-secondary);
  min-width: 0;
}
.metric-value {
  font-family: var(--font-display);
  font-variant-numeric: tabular-nums lining-nums;
  font-weight: 600;
  font-size: var(--t-md);
  color: var(--text);
  text-align: right;
  white-space: nowrap;
}

/* Charts keep a reserved box so their arrival never shifts the layout. */
.chart-container {
  position: relative;
  width: 100%;
  min-height: 200px;
}
.chart-container > canvas { max-width: 100%; }

/* Bootstrap progress bars adopt the score ramp. */
.progress-bar { background-color: var(--band, var(--seal)); }

/* Legacy gradient headings become plain display type — the identity now
   comes from the typeface, not from a colour wash. */
.gradient-text-hero,
.gradient-text-primary {
  background: none;
  -webkit-background-clip: initial;
  -webkit-text-fill-color: currentColor;
  color: inherit;
}

/* Anything still asking for the old page chrome is simply not rendered. */
.page-loader,
.scroll-progress,
.fab-scan,
.hero-floating-shapes,
.floating-shape { display: none !important; }


/* Embeddable snippets on the badge page: long unbroken URLs. */
.embed-code-box {
  display: block;
  background: var(--surface-inset);
  border: 1px solid var(--rule);
  border-radius: var(--r-sm);
  padding: var(--s-3);
  font-family: var(--font-mono);
  font-size: var(--t-2xs);
  line-height: 1.6;
  color: var(--text-secondary);
  overflow-wrap: anywhere;
  word-break: break-all;
  white-space: pre-wrap;
  max-width: 100%;
}

.badge-preview-container {
  display: flex;
  justify-content: center;
  padding: var(--s-5);
  background: var(--surface-2);
  border: 1px solid var(--rule);
  border-radius: var(--r-sm);
  overflow-x: auto;
}

/* ═══════════════════════════════════════════════════════════════════════
   19 · THE LEDGER ON A PHONE
   ───────────────────────────────────────────────────────────────────────
   Ten columns cannot be read on a 360px screen, and asking someone to pan
   sideways through them is not "responsive". Below the tablet breakpoint the
   table keeps rank, institution and the overall index, and the four
   dimension figures move into a compact digest under the institution name.
   Nothing is lost: the full table returns at 768px and every figure is in
   the JSON export.
   ═══════════════════════════════════════════════════════════════════════ */
.row-digest { display: none; }

@media (max-width: 767.98px) {
  .ledger .col-dimension,
  .ledger .col-change,
  .ledger .col-country,
  /* The "Report" button was clipped at the right edge on phones; the
     institution name above is already the link to the same report. */
  .ledger .col-actions { display: none; }

  .row-digest {
    display: flex;
    flex-wrap: wrap;
    gap: 0.15rem 0.6rem;
    margin-top: 0.3rem;
    font-size: var(--t-3xs);
    color: var(--text-muted);
  }
  .row-digest b {
    font-family: var(--font-display);
    font-variant-numeric: tabular-nums lining-nums;
    font-weight: 600;
    color: var(--band, var(--text-secondary));
  }

  .ledger-institution { min-width: 0; }

  /* With fewer columns the table fits, so the sticky column is unnecessary
     and would only add a seam. */
  .ledger-sticky thead th:first-child,
  .ledger-sticky tbody td:first-child {
    position: static;
    box-shadow: none;
  }
}
