/*
  Design: a register, not a brochure. One typeface (Archivo variable) carries hierarchy through its
  width axis rather than a pile of weights; numbers are tabular everywhere because this whole app is
  grades, fees and dates. Status is never colour alone — it also has a left edge mark and a word.
  Provenance is deliberately quiet: the answer is the page, the evidence is one click under it.
*/
:root {
  --paper: #f1f2ee;
  --surface: #fbfbf9;
  --sunken: #e5e7e1;
  /* the student's own column: the one surface that is about them, not the programme */
  --you: #e6e9fb;
  --ink: #101318;
  --quiet: #5f646c;
  --rule: #d3d6ce;
  --rule-strong: #b6bab0;
  --mark: #2b3fe8;
  --mark-soft: #dfe2fb;
  --met: #23703f;
  --met-soft: #dcebdf;
  --bad: #b03624;
  --bad-soft: #f5ddd8;
  --open: #8a6508;
  --open-soft: #f3e7c8;

  --gutter: clamp(1rem, 4vw, 2.5rem);
  --measure: 68ch;
  /* one height and one corner for every control on the page */
  --control-h: 2rem;
  --radius: 3px;
  /* native parts (select lists, date pickers, scrollbars) follow the theme too */
  color-scheme: light dark;
}
option { background: var(--surface); color: var(--ink); }
@media (prefers-color-scheme: dark) {
  :root {
    --paper: #14161b;
    --surface: #1c1f26;
    --sunken: #262a33;
    --you: #1f2440;
    --ink: #f3f2ee;
    --quiet: #9ba1ab;
    --rule: #2b2f38;
    --rule-strong: #444a56;
    --mark: #9aa8ff;
    --mark-soft: #262c52;
    --met: #74d39a;
    --met-soft: #17301f;
    --bad: #f28b7a;
    --bad-soft: #3a1f1b;
    --open: #eab94f;
    --open-soft: #33290f;
  }
}

*, *::before, *::after { box-sizing: border-box; }
/* room for the scrollbar is kept even on short pages, so switching pages never shifts the layout */
html { -webkit-text-size-adjust: 100%; scrollbar-gutter: stable; }
body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: Archivo, system-ui, sans-serif;
  font-size: 16px;
  line-height: 1.5;
  font-variant-numeric: tabular-nums;
}

h1, h2, h3, h4 { margin: 0; font-weight: 600; line-height: 1.15; letter-spacing: -0.01em; }
h1 { font-size: 1rem; font-variation-settings: 'wdth' 88; }
h2 { font-size: 1.4rem; font-variation-settings: 'wdth' 92; }
/* hierarchy comes from size, width and space alone — no rules, no boxes */
h3 { font-size: 2.1rem; font-weight: 700; font-variation-settings: 'wdth' 78; letter-spacing: -0.015em; }
h4 { font-size: 1.1rem; font-weight: 600; font-variation-settings: 'wdth' 90; margin: 1.25rem 0 0.6rem; }
p { margin: 0 0 0.6rem; max-width: var(--measure); }
a { color: var(--mark); text-underline-offset: 2px; }
a.plain { color: inherit; }
:focus-visible { outline: 2px solid var(--mark); outline-offset: 2px; border-radius: 2px; }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.skip { position: absolute; left: -9999px; top: 0; z-index: 30; background: var(--surface); padding: 0.5rem 1rem; border: 1px solid var(--mark); }
.skip:focus { left: 0; }

/* ---------- shell ---------- */
header {
  display: flex; align-items: center; gap: 1.5rem; flex-wrap: wrap;
  padding: 0.45rem var(--gutter);
  background: var(--surface);
  position: sticky; top: 0; z-index: 10;
}
/* The logo file is a monoline drawn in currentColor, which an <img> cannot pass in; used as a
   mask, it takes the text colour and follows light and dark. */
header h1 a { display: flex; color: inherit; text-decoration: none; padding: 0.3rem 0; }
header h1 .logo {
  display: block; height: 1.4rem; aspect-ratio: 220 / 88; background: currentColor;
  mask: url(uni-logo.svg) center / contain no-repeat;
}
/* scoped to the header: the breadcrumb trail is a <nav> too, and must not inherit this padding */
header nav { display: flex; flex-wrap: wrap; gap: 0.25rem; margin-right: auto; }
header nav a { position: relative; padding: 0.2rem 0.55rem; text-decoration: none; color: var(--quiet); }
header nav a:hover { color: var(--ink); }
header nav a.active { color: var(--ink); font-weight: 600; }
/* the underline spans the word, not the padding around it */
header nav a.active::after { content: ''; position: absolute; left: 0.55rem; right: 0.55rem; bottom: -0.1rem; height: 2px; border-radius: 1px; background: var(--mark); }

/* the profile is a companion to every page, not a page of its own */
/* one line: a person outline says whose it is, the summary says what it holds */
.profile-chip {
  display: inline-flex; align-items: center; gap: 0.5rem;
  padding: 0 0.7rem 0 0.55rem; font-size: 0.85rem;
  background: var(--sunken); border: 1px solid transparent; border-radius: 999px;
  cursor: pointer; color: var(--ink); font-variant-numeric: tabular-nums;
}
.profile-chip svg { width: 1rem; height: 1rem; color: var(--quiet); flex: none; }
.profile-chip:hover svg, .profile-chip[aria-expanded='true'] svg { color: var(--mark); }
.profile-chip:hover { border-color: var(--mark); }
a.button.out { border-color: transparent; background: var(--mark-soft); color: var(--mark); border-radius: 8px; font-weight: 600; }
.profile-chip[aria-expanded='true'] { border-color: var(--mark); background: var(--mark-soft); }

main { padding: var(--gutter); max-width: 1320px; margin: 0 auto; }
/* proximity: sections sit far apart, their own heading close to what it introduces */
section { margin-bottom: 5.5rem; }
section > h3 { margin-bottom: 1.75rem; }
.lede { color: var(--quiet); max-width: var(--measure); margin-bottom: 1rem; }
.meta { color: var(--quiet); font-size: 0.85rem; }
.footnote { margin-top: 4rem; max-width: none; }
.inline-label { display: inline-flex; gap: 0.35rem; align-items: center; }

/* ---------- drawer ---------- */
#scrim { position: fixed; inset: 0; background: rgba(0, 0, 0, 0.35); z-index: 15; }
#drawer {
  position: fixed; top: 0; right: 0; bottom: 0; width: min(28rem, 100vw);
  background: var(--paper); border-left: 1px solid var(--rule-strong);
  padding: 1.25rem var(--gutter) 3rem; overflow-y: auto; z-index: 20;
}
#drawer[hidden] { display: none; }
.drawer-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 0.25rem; }

/* ---------- profile form ---------- */
/* Sections are told apart by a heading and generous space above it, not by boxes or rules. */
.profile-form section { margin: 0 0 2.25rem; }
.profile-form h4 { margin: 0 0 0.75rem; }
.profile-form .fields { gap: 1rem 1.25rem; align-items: flex-start; margin-bottom: 1rem; }
.profile-form .field { gap: 0.3rem; }
.field-label { font-size: 0.8rem; color: var(--quiet); }
.field-block { display: flex; flex-direction: column; align-items: flex-start; gap: 0.35rem; margin-bottom: 1rem; }
.hint { font-size: 0.8rem; color: var(--quiet); margin: 0.35rem 0 0; }
/* a hint that introduces a control needs air under it, not just above */
.hint + .add-row, .hint + .chips, .hint + .rows, .hint + .fields { margin-top: 0.7rem; }
.hint code { font-size: 0.95em; background: var(--sunken); padding: 0 0.25rem; border-radius: 2px; }
.profile-form .field > input { width: 6rem; height: 2rem; }
.profile-form .rows input { width: 100%; }

/* every row of pickable values behaves the same way */
.chips { display: flex; flex-wrap: wrap; gap: 0.35rem; align-items: center; }
/* "no restriction" is a state worth showing, and a one-click way back to it */
.choice-any { margin-right: 0.4rem; }
.choice-any:has(input:checked) { background: var(--sunken); border-color: var(--rule-strong); font-weight: 600; }
.segmented { display: inline-flex; }
.segmented .choice { border-radius: 0; margin-left: -1px; }
.segmented .choice:first-child { margin-left: 0; border-radius: var(--radius) 0 0 var(--radius); }
.segmented .choice:last-child { border-radius: 0 var(--radius) var(--radius) 0; }
.choice { padding: 0.3rem 0.6rem; font-size: 0.85rem; line-height: 1.3; white-space: nowrap; }
.choice input[type='radio'], .choice input[type='checkbox'] { margin: 0; }

/* list rows: name, value, and one icon button that never grows */
.rows { list-style: none; margin: 0 0 0.6rem; padding: 0; }
.rows li { display: grid; grid-template-columns: 1fr 4.5rem 1.9rem; gap: 0.5rem; align-items: center; padding: 0.25rem 0; }
.rows .row-name { font-size: 0.9rem; }
/* the average is the whole-picture number, so it leads the list and sits slightly apart */
.rows .row-total { margin-bottom: 0.4rem; }
.rows .row-total .row-name { font-weight: 600; }
.rows .row-value { text-align: right; font-size: 0.9rem; }
.rows input { width: 100%; text-align: right; }
.remove {
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.75rem; height: 1.75rem; padding: 0; line-height: 1; font-size: 0.85rem;
  border-color: transparent; background: none; color: var(--quiet);
}
.remove:hover { border-color: var(--bad); color: var(--bad); }

.picker > summary { font-size: 0.85rem; color: var(--mark); cursor: pointer; padding: 0.25rem 0; }
.picker-body { padding: 0.5rem 0 0; display: grid; gap: 0.75rem; }
.picker-group { display: grid; gap: 0.3rem; }
.add-chip { padding: 0.25rem 0.55rem; font-size: 0.85rem; background: var(--surface); color: var(--ink); }
.add-chip:hover { border-color: var(--mark); color: var(--mark); }

.add-row { display: grid; grid-template-columns: 1fr 4.5rem auto; gap: 0.5rem; align-items: center; }
.add-row input, .add-row select { width: 100%; }
.with-unit { display: inline-flex; align-items: center; gap: 0; border: 1px solid var(--rule); background: var(--surface); }
.with-unit:focus-within { border-color: var(--mark); }
.with-unit .unit { padding: 0 0.15rem 0 0.5rem; color: var(--quiet); }
.with-unit input { border: 0; background: none; }

/* ---------- research tallies ---------- */
.verdict { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-bottom: 1.5rem; }
.verdict .stat {
  display: inline-flex; align-items: baseline; gap: 0.45rem;
  padding: 0.45rem 0.85rem; line-height: 1.2;
  border: 1px solid var(--rule); border-radius: 2rem; background: var(--surface);
}
.verdict .stat .of { color: var(--quiet); font-size: 0.85rem; }
.verdict .stat .count { font-size: 1.4rem; font-weight: 600; font-variation-settings: 'wdth' 85; }
.verdict .stat.v-met { border-left: 4px solid var(--met); }
.verdict .stat.v-unknown { border-left: 4px solid var(--open); }
.verdict .stat.v-all { border-left: 4px solid var(--rule-strong); }

/* ---------- control primitives ----------
   Every interactive control — input, select, button, link-button, choice chip — shares one height,
   one border, one hover and one focus ring, so a row of mixed controls lines up and reads as one
   family. This is the whole "design system": tokens plus these few rules. */
.controls { display: flex; flex-wrap: wrap; gap: 0.6rem; align-items: center; margin-bottom: 1rem; }
input, select, button, textarea { font: inherit; font-variant-numeric: tabular-nums; color: var(--ink); }

input, select, button, .button, .choice {
  height: var(--control-h);
  padding: 0 0.65rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface);
  line-height: calc(var(--control-h) - 2px);
  vertical-align: middle;
}
input:hover, select:hover, button:hover, .button:hover, .choice:hover { border-color: var(--rule-strong); }
input:focus-visible, select:focus-visible, button:focus-visible, .button:focus-visible { outline: 2px solid var(--mark); outline-offset: 1px; }
input::placeholder { color: var(--quiet); opacity: 0.9; }
input[type='number'] { width: 6rem; }
input[type='checkbox'], input[type='radio'] { height: auto; padding: 0; border: 0; background: none; accent-color: var(--mark); }
textarea { padding: 0.4rem 0.65rem; height: auto; line-height: 1.45; }

/* one arrow for every select, instead of each platform's own */
select {
  appearance: none; padding-right: 1.8rem; cursor: pointer;
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%), linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: right 0.85rem center, right 0.6rem center;
  background-size: 0.3rem 0.3rem, 0.3rem 0.3rem;
  background-repeat: no-repeat;
}

button, .button { cursor: pointer; display: inline-flex; align-items: center; gap: 0.35rem; text-decoration: none; white-space: nowrap; }
.primary, a.button.primary { background: var(--mark); border-color: var(--mark); color: #fff; font-weight: 600; }
.primary:hover, a.button.primary:hover { border-color: var(--mark); filter: brightness(1.08); }
button.quiet { border-color: transparent; background: none; color: var(--quiet); padding: 0 0.4rem; }
button.quiet:hover { color: var(--ink); background: var(--sunken); border-color: transparent; }
button.inline {
  height: auto; padding: 0; border: 0; background: none; line-height: inherit;
  color: var(--mark); text-decoration: underline; cursor: pointer; font-size: inherit;
}

label { display: inline-flex; gap: 0.4rem; align-items: center; color: var(--quiet); }
.field { display: inline-flex; flex-direction: column; align-items: flex-start; gap: 0.25rem; font-size: 0.8rem; color: var(--quiet); }
.fields { display: flex; flex-wrap: wrap; gap: 0.75rem 1rem; align-items: flex-end; margin-bottom: 0.75rem; }
fieldset { border: 0; margin: 0.5rem 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 0.4rem; }
legend { padding: 0; font-size: 0.8rem; color: var(--quiet); margin-bottom: 0.3rem; }

/* The chip itself is the checkbox: filled means on. A native box next to it would say the same
   thing twice and put ten small squares on screen for one question. */
.choice { display: inline-flex; align-items: center; gap: 0.4rem; color: var(--ink); cursor: pointer; font-size: 0.85rem; }
.choice input[type='checkbox'], .choice input[type='radio'] {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
}
.choice:has(input:checked) { background: var(--mark-soft); border-color: var(--mark); color: var(--ink); font-weight: 600; }
/* a checked segment must paint over its neighbour's edge, or its border looks clipped */
.choice:has(input:checked), .choice:focus-within { position: relative; z-index: 1; }
.choice:focus-within { outline: 2px solid var(--mark); outline-offset: 1px; }

/* ---------- register ---------- */
.scroll { overflow-x: auto; }
table { border-collapse: collapse; width: 100%; }
th, td { text-align: left; vertical-align: top; padding: 0.55rem 0.7rem; }
th { font-size: 0.75rem; font-weight: 600; color: var(--quiet); font-variation-settings: 'wdth' 82; letter-spacing: 0.02em; border-bottom: 1px solid var(--rule-strong); white-space: nowrap; }
tbody tr { border-bottom: 1px solid var(--rule); }
.where { color: var(--quiet); font-size: 0.85rem; }
.num { text-align: right; }

/* ---------- programme list ----------
   One line of filters, then rows held apart by space rather than rules. The whole row is the
   target, so it lights up as one piece on hover; the verdict is a coloured dot and a word. */
/* Above the table: how many, what narrows them, and search. Filters and sorting are on the
   column headings themselves, so each control sits on the column it acts on. */
.toolbar { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; margin: 1.25rem 0 0.75rem; font-size: 0.85rem; }
.toolbar button, .toolbar input { font-size: 0.85rem; }
.toolbar .count { color: var(--quiet); margin-right: 0.35rem; }
.toolbar-end { display: flex; gap: 1rem; align-items: center; margin-left: auto; }
.toolbar .search { width: 12rem; background-color: transparent; }
.group-toggle { cursor: pointer; white-space: nowrap; }
.group-toggle:hover { color: var(--ink); }
/* an active filter, removable where it is named */
.chip { height: 1.6rem; padding: 0 0.3rem 0 0.6rem; gap: 0.4rem; border-radius: 999px; border-color: var(--mark); background: var(--mark-soft); color: var(--ink); font-weight: 500; }
.chip .x { display: inline-grid; place-items: center; width: 1.1rem; height: 1.1rem; border-radius: 50%; font-size: 0.6rem; line-height: 1; color: var(--quiet); }
.chip .flag.fi { margin-right: 0; }
.chip:hover .x { background: var(--mark); color: var(--surface); }
.chevron { width: 0.35rem; height: 0.35rem; border: solid currentColor; border-width: 0 1.5px 1.5px 0; transform: translateY(-0.1rem) rotate(45deg); opacity: 0.6; }

/* A heading that is a control keeps looking like a heading: same small type, no box until
   hovered. When it filters or sorts the list it turns the accent colour, so the state is read
   off the column itself. */
button.head {
  height: auto; margin: -0.25rem -0.4rem; padding: 0.25rem 0.4rem; gap: 0.4rem;
  border: 0; border-radius: 5px; background: none; line-height: inherit;
  color: inherit; font: inherit; letter-spacing: inherit;
}
button.head:hover { background: var(--sunken); color: var(--ink); }
button.head svg { width: 0.8rem; height: 0.8rem; flex: none; }
button.head.on, button.head.sorted { color: var(--mark); }
button.head.desc svg { transform: rotate(180deg); }
/* the sort arrow is a hint until the column is the one sorted by */
button.head[aria-pressed='false'] svg { opacity: 0; }
button.head[aria-pressed='false']:hover svg { opacity: 0.5; }
.flag-cell button.head svg { width: 0.9rem; height: 0.9rem; }
.head .count { min-width: 1.05rem; height: 1.05rem; padding: 0 0.25rem; border-radius: 999px; background: var(--mark); color: var(--surface); font-size: 0.68rem; font-weight: 700; line-height: 1.05rem; text-align: center; }
/* the list of choices: a popover under its heading, flipped when there is no room */
.menu[popover] {
  inset: auto; margin: 0.3rem 0; position-area: block-end span-inline-end;
  position-try-fallbacks: flip-block, flip-inline;
  min-width: 12rem; max-height: 20rem; overflow-y: auto; padding: 0.3rem;
  background: var(--surface); color: var(--ink); border: 1px solid var(--rule-strong); border-radius: 8px;
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.18); font-size: 0.85rem; font-weight: 400;
  text-align: left; white-space: normal; letter-spacing: 0; font-variation-settings: normal;
}
@supports not (anchor-name: --a) { .menu[popover] { inset: 0; margin: auto; } }
.menu-item { display: flex; align-items: center; gap: 0.6rem; padding: 0.4rem 0.55rem; border-radius: 5px; color: var(--ink); cursor: pointer; }
.menu-item:hover { background: var(--sunken); }
.menu-item > span { display: inline-flex; align-items: center; }
.clear { margin-left: 0.25rem; font-size: 0.8rem; }

/* Rows have side padding for their hover fill; pulling the table out by that much keeps the
   text itself in line with the heading and the controls above. */
.scroll:has(> .register) { margin-inline: -0.75rem; }
.register { border-collapse: separate; border-spacing: 0; font-size: 0.9rem; }
.register th { border-bottom: 0; padding: 0.55rem 0.75rem 0.4rem; }
.register tbody tr { border-bottom: 0; }
.register td { padding: 0.8rem 0.75rem; }
.register .link-row { cursor: pointer; }
.register .link-row:hover td { background: var(--surface); }
.register .link-row td:first-child { border-radius: 8px 0 0 8px; }
.register .link-row td:last-child { border-radius: 0 8px 8px 0; }
.register a.name { display: block; font-size: 1rem; font-weight: 600; color: var(--ink); text-decoration: none; }
.register .link-row:hover a.name { color: var(--mark); }
/* the degree as a short code in its own column: a small outlined tag, one width for all */
.register .degree {
  display: inline-block; min-width: 2.6rem; padding: 0.05rem 0.4rem; border: 1px solid var(--rule-strong); border-radius: 4px;
  font-size: 0.72rem; font-weight: 600; letter-spacing: 0.02em; text-align: center; color: var(--quiet); line-height: 1.4;
}
/* a lone flag, a little larger than in running text, on the row's first line */
.register .flag-cell { width: 1%; padding-right: 0.25rem; }
.register td.flag-cell { padding-top: 1.02rem; }
.register td.flag-cell .flag.fi { width: 1.3rem; height: 0.975rem; margin: 0; display: block; }
.register .where { font-size: 0.8rem; }
.register .where a.plain { text-decoration: none; }
.register .where a.plain:hover { text-decoration: underline; }
.register .star-cell { width: 1%; padding-top: 0.55rem; }
/* a 4:3 flag the height of the capitals, centred on the text beside it */
.flag.fi { width: 1em; height: 0.75em; line-height: 0; flex: none; margin-right: 0.4em; border-radius: 2px; background-size: cover; box-shadow: 0 0 0 1px rgba(127, 127, 127, 0.25); vertical-align: 0; }
/* Archivo's capitals sit above the middle of the line box, so centring alone looks low */
.country .flag.fi, .group-head .flag.fi, .menu-item .flag.fi { position: relative; top: -0.07em; }
.country, .group-head { display: inline-flex; align-items: center; }
.uni-line { display: flex; align-items: center; gap: 0.35rem; }
.group-head { flex-wrap: wrap; }

/* Grouped by university. The university is the parent: a larger heading with its flag, far
   from the group above. Its programmes are children: indented and hung from a line that runs
   down from the heading, so where one group ends and the next begins needs no reading. */
.register .group-row th { padding: 2.25rem 0.75rem 0.35rem; color: var(--ink); white-space: normal; font-variation-settings: normal; letter-spacing: 0; }
.register tbody.group:first-of-type .group-row th { padding-top: 0.5rem; }
.register .group-row .flag { font-size: 1.1rem; }
.register .group-row a.uni { font-size: 1.2rem; font-weight: 700; font-variation-settings: 'wdth' 85; letter-spacing: -0.01em; text-decoration: none; }
.register .group-row a.uni:hover { text-decoration: underline; text-underline-offset: 3px; }
.register .group-row .where { font-size: 0.85rem; font-weight: 400; margin-left: 0.6rem; }
.register.grouped .link-row td { padding-top: 0.6rem; padding-bottom: 0.6rem; }
.register.grouped .link-row td:first-child { position: relative; padding-left: 2.1rem; }
.register.grouped .link-row td:first-child::before {
  content: ''; position: absolute; left: 1.05rem; top: 0; bottom: 0; width: 1px; background: var(--rule-strong);
}
/* the branch meets the programme name, not the middle of a two-line row */
.register.grouped .link-row:last-child td:first-child::before { bottom: auto; height: 1.3rem; }
.register.grouped .link-row td:first-child::after {
  content: ''; position: absolute; left: 1.05rem; top: 1.3rem; width: 0.6rem; height: 1px; background: var(--rule-strong);
}
.register.grouped a.name { font-weight: 550; }
/* grouped, the heading carries the flag; the first cell holds the branch instead */
.register.grouped td.flag-cell .flag { visibility: hidden; }
.register.grouped .link-row td.flag-cell { padding-left: 1.6rem; }
.register.grouped .link-row td.flag-cell::after { width: auto; right: 0.15rem; top: 1.45rem; }
.register.grouped .link-row:last-child td.flag-cell::before { height: 1.45rem; }

.status { display: inline-flex; align-items: center; gap: 0.45rem; white-space: nowrap; font-weight: 500; }
.status::before { content: ''; width: 0.5rem; height: 0.5rem; border-radius: 50%; background: currentColor; flex: none; }
.status.s-met { color: var(--met); }
.status.s-unknown { color: var(--open); }
.status.s-not_met { color: var(--bad); }
.status.s-not_applicable { color: var(--quiet); }
.status.s-researched { color: var(--met); }
.status.s-to_research { color: var(--mark); }
.status.s-skipped { color: var(--quiet); }

/* ---------- research page: the same register, with long text kept quiet and readable ---------- */
.register.research td.rank { color: var(--quiet); width: 1%; }
.register.research td.why { color: var(--quiet); font-size: 0.85rem; line-height: 1.5; max-width: 60ch; }
.register.research td.nowrap { white-space: nowrap; }
.register a.name.out::after { content: ' ↗'; font-weight: 400; font-size: 0.85em; color: var(--quiet); }
.tallies { gap: 1.5rem; margin-top: -0.75rem; margin-bottom: 0.75rem; }
.tallies b { font-weight: 650; }
.scope-countries { display: flex; flex-wrap: wrap; align-items: center; gap: 0.35rem 1rem; max-width: none; margin-bottom: 3rem; font-size: 0.9rem; }
/* on its own in a cell, the country is a line of its own, so it sits on the row's first line */
.register td > .country { display: flex; line-height: 1.5; }
.scope-countries .meta { margin-right: 0.25rem; }

/* ---------- status words ---------- */
.tag { display: inline-block; padding: 0.05rem 0.45rem; margin: 0 0.15rem 0.15rem 0; font-size: 0.78rem; white-space: nowrap; background: var(--sunken); color: var(--quiet); }
.tag.met, .tag.yes { background: var(--met-soft); color: var(--met); }
.tag.not_met, .tag.no { background: var(--bad-soft); color: var(--bad); }
.tag.unknown, .tag.provisional { background: var(--open-soft); color: var(--open); }

/* ---------- "i": one control per answer for everything behind it ----------
   The ring's colour is the confidence meter: green = solid, amber = fairly sure,
   dashed red = shaky, grey = nothing to be sure about (a calculation). */
.info { display: inline; }
.info-button {
  appearance: none; background: none; border: 0; margin: 0; padding: 0.1rem; border-radius: 50%;
  display: inline-flex; cursor: pointer; line-height: 1;
  /* optically centred on the text's x-height rather than sitting on its baseline */
  vertical-align: middle; position: relative; top: -0.08em;
}
.info-button:hover { background: none; }
.info-button:focus-visible { outline: 2px solid var(--mark); outline-offset: 1px; }
.i-mark {
  position: relative; isolation: isolate; display: inline-grid; place-items: center;
  width: 1.05rem; height: 1.05rem; flex: none;
  font: italic 700 0.7rem/1 Georgia, 'Times New Roman', serif; color: var(--quiet);
}
.i-mark::before { content: ''; position: absolute; inset: 0; z-index: -1; border-radius: 50%; border: 1.5px solid var(--rule-strong); }
.i-mark.l-solid { color: var(--met); }
.i-mark.l-solid::before { border-color: var(--met); }
.i-mark.l-partial { color: var(--open); }
.i-mark.l-partial::before { border-color: var(--open); }
.i-mark.l-weak { color: var(--bad); }
.i-mark.l-weak::before { border: 1.5px dashed var(--bad); }
.info-button:hover .i-mark::before, .info-button:has(+ :popover-open) .i-mark::before { background: var(--sunken); }
.footnote .i-mark { vertical-align: middle; position: relative; top: -0.08em; }
/* The panel is a popover in the top layer, tied to its "i" by anchor positioning: below and
   to the right when there is room, flipped up or left when there is not. */
.info-body[popover] {
  inset: auto; margin: 0.35rem 0;
  position-area: block-end span-inline-end;
  position-try-fallbacks: flip-block, flip-inline, flip-block flip-inline;
  /* take the side with more room, and never grow past it */
  position-try-order: most-block-size;
  width: min(30rem, calc(100vw - 2rem)); max-height: min(calc(100% - 0.7rem), 34rem); overflow-y: auto;
  padding: 0.75rem 0.9rem; background: var(--surface); color: var(--ink);
  border: 1px solid var(--rule-strong); border-radius: 8px; box-shadow: 0 6px 24px rgba(0, 0, 0, 0.18);
  /* it inherits from wherever the "i" sits (a heading, a verdict), so reset the text */
  font-size: 0.85rem; font-weight: 400; font-style: normal; font-variation-settings: normal;
  line-height: 1.5; letter-spacing: 0; text-align: left; text-transform: none; white-space: normal;
}
/* without anchor positioning the browser centres the popover, which still works */
@supports not (anchor-name: --a) { .info-body[popover] { inset: 0; margin: auto; } }
.info-body p { margin: 0 0 0.5rem; }
.info-more { margin-bottom: 0.75rem; padding-bottom: 0.6rem; border-bottom: 1px solid var(--rule); }
.info-more:last-child { margin-bottom: 0; padding-bottom: 0; border-bottom: 0; }
.info-body .working { margin: 0; padding-left: 1.1rem; display: grid; gap: 0.35rem; }
.info-body .fees { list-style: none; margin: 0 0 0.6rem; padding: 0; display: grid; gap: 0.45rem; }
.info-body .fees b { font-weight: 600; }
.cert-why { margin-bottom: 0.6rem; }
/* the dot still marks last year's dates in the timeline */
.dot {
  display: inline-block; width: 0.55rem; height: 0.55rem; border-radius: 50%;
  border: 1.5px solid currentColor; vertical-align: -0.02em;
}
.d-solid { color: var(--met); background: currentColor; }
.d-partial { color: var(--open); background: linear-gradient(to right, currentColor 50%, transparent 50%); }
.d-weak { color: var(--bad); background: transparent; }

/* ---------- breadcrumbs and masthead ---------- */
.crumbs { display: flex; align-items: center; gap: 0.45rem; flex-wrap: wrap; font-size: 0.85rem; line-height: 1.6; color: var(--quiet); margin-bottom: 0.9rem; }
.crumbs a { color: var(--quiet); }
.crumbs a:hover { color: var(--ink); }
.crumbs span[aria-hidden] { color: var(--rule-strong); }
/* on a programme page the university is the line above the title and the way up to it */
.pre-title { display: flex; align-items: center; flex-wrap: wrap; gap: 0 0.6rem; font-size: 1rem; line-height: 1.4; margin-bottom: 0.4rem; }
.pre-title .place { display: inline-flex; align-items: center; gap: 0.4rem; }
.pre-title a.uni { font-weight: 600; color: var(--ink); text-decoration: none; }
.pre-title a.uni:hover { text-decoration: underline; text-underline-offset: 3px; }
.pre-title .place { color: var(--quiet); }
.masthead { margin-bottom: 1.75rem; }
.masthead .title-row { display: flex; align-items: flex-start; gap: 1rem 1.5rem; flex-wrap: wrap; }
.masthead .title-row > div:first-child { flex: 1 1 min(20rem, 100%); min-width: 0; }
.masthead h2 { font-size: clamp(2rem, 5.5vw, 3.25rem); font-weight: 750; font-variation-settings: 'wdth' 75; letter-spacing: -0.02em; line-height: 1; }
.masthead .where { margin-top: 0.5rem; font-size: 1.05rem; color: var(--quiet); }
.title-actions { display: flex; align-items: center; gap: 0.5rem; margin-top: 0.3rem; }
.star-button { border-color: transparent; background: none; padding: 0.15rem 0.35rem; line-height: 1; color: var(--quiet); }
.star-button:hover { border-color: var(--rule); color: var(--ink); }
.star-button .star { font-size: 1.5rem; }
.star-button .star.on { color: var(--mark); }
a.out::after { content: ' ↗'; font-size: 0.85em; }
.page-tools { display: flex; justify-content: flex-end; margin: 0 0 1rem; }
.switch { display: inline-flex; align-items: center; gap: 0.5rem; font-size: 0.8rem; color: var(--quiet); cursor: pointer; }
.switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.switch .track {
  width: 1.9rem; height: 1.05rem; border-radius: 1rem; background: var(--sunken);
  border: 1px solid var(--rule-strong); position: relative; flex: none; transition: background 0.12s;
}
.switch .knob {
  position: absolute; top: 1px; left: 1px; width: 0.8rem; height: 0.8rem; border-radius: 50%;
  background: var(--rule-strong); transition: transform 0.12s, background 0.12s;
}
.switch input:checked + .track { background: var(--mark-soft); border-color: var(--mark); }
.switch input:checked + .track .knob { transform: translateX(0.82rem); background: var(--mark); }
.switch input:focus-visible + .track { outline: 2px solid var(--mark); outline-offset: 2px; }
.switch:hover { color: var(--ink); }

.stack { display: grid; gap: 2rem; }
.stack > div > h4:first-child { margin-top: 0; }

/* ---------- the programme: what it is in a few sentences, then one strip of facts ---------- */
.summary { max-width: var(--measure); margin: 0 0 2rem; }
.summary p { margin: 0; font-size: 1.05rem; line-height: 1.55; }
.summary p.meta { margin-top: 0.4rem; font-size: 0.9rem; }
.facts-strip { display: flex; flex-wrap: wrap; gap: 1.75rem 3.5rem; margin: 0 0 2.75rem; }
.fact-value { font-size: 1.6rem; font-weight: 650; font-variation-settings: 'wdth' 80; line-height: 1.1; letter-spacing: -0.01em; }
.fact-value .unit { font-size: 0.95rem; font-weight: 400; color: var(--quiet); letter-spacing: 0; }
.fact-label { font-size: 0.9rem; color: var(--quiet); margin-top: 0.3rem; }
.fact-note { font-size: 0.8rem; color: var(--quiet); margin-top: 0.15rem; max-width: 22ch; }

/* ---------- programme page layout ---------- */
/* The verdict: a quiet neutral panel. The title above is the loudest thing on the page, so only
   the verdict word carries colour. Two columns share one type scale: a 1.1rem line with the
   answer, then 0.875rem lines with what follows from it, their first lines on one baseline. */
.judgement {
  display: flex; flex-wrap: wrap; gap: 0.75rem 3rem; justify-content: space-between; align-items: baseline;
  background: var(--surface); padding: 0.85rem 1.1rem; margin-bottom: 2.75rem; border-radius: 8px;
}
.judgement-main { flex: 1 1 min(22rem, 100%); min-width: 0; }
.judgement-next { flex: 0 1 22rem; }
.judgement .headline { font-size: 1.1rem; font-weight: 650; line-height: 1.4; margin: 0; letter-spacing: -0.005em; }
.judgement .label { font-weight: 400; color: var(--quiet); }
.judgement .headline-row { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.25rem 1rem; }
.judgement .headline-row .tally-link { font-size: 0.875rem; color: var(--quiet); }
.judgement .score { color: var(--quiet); font-size: 0.875rem; line-height: 1.45; margin-top: 0.2rem; max-width: var(--measure); }
.tally-link { color: inherit; text-decoration: none; display: inline-flex; align-items: center; }
.tally-link:hover { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }
.cut-mark { font-weight: 800; margin-right: 0.45rem; }
.cut-above .cut-mark { color: var(--met); }
.cut-below .cut-mark { color: var(--bad); }
.cut-unclear .cut-mark, .cut-equal .cut-mark { color: var(--open); }
.unknown-value { font-size: 1rem; font-weight: 500; color: var(--quiet); }
.judgement.j-met .headline { color: var(--met); }
.judgement.j-unknown .headline { color: var(--open); }
.judgement.j-not_met .headline { color: var(--bad); }
/* the verdict's colour belongs to the verdict, not to the deadline beside it */
.judgement .judgement-next .headline { color: var(--ink); }
/* one tick per requirement: filled when settled, hollow while open */
.tally { display: inline-flex; gap: 0.15rem; margin-right: 0.5rem; }
.tally i { width: 0.6rem; height: 0.25rem; border-radius: 1px; background: var(--rule-strong); }
.tally i.t-met { background: var(--met); }
.tally i.t-not_met { background: var(--bad); }
.tally i.t-unknown { background: var(--sunken); box-shadow: inset 0 0 0 1px var(--rule-strong); }
.judgement .todo { margin-top: 0.6rem; }
.judgement button.inline { font-size: inherit; }

/* ---------- getting in: topic, the programme's answer, what it means for you ----------
   No rules and no column headings. Each row is one line of thought read left to right; the
   evaluation is a small cell on the same row, tinted by what it means (met, open, not met), so it
   belongs to its requirement instead of forming a separate column. Groups are far apart, rows close. */
.qa-group { margin-top: 3.5rem; max-width: 74rem; scroll-margin-top: 5rem; }
.qa-group:first-of-type { margin-top: 0; }
.qa.facts-only > li { grid-template-columns: minmax(8rem, 11rem) minmax(0, 1fr); max-width: 52rem; }
.qa-group > h4 { font-size: 1.35rem; font-weight: 650; font-variation-settings: 'wdth' 82; margin: 0 0 0.9rem; }
.qa { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.35rem; }
.qa > li { display: grid; grid-template-columns: minmax(8rem, 11rem) minmax(0, 1.4fr) minmax(0, 1fr); column-gap: 2rem; align-items: start; padding: 0.55rem 0; border-radius: 10px; }
.qa .q { color: var(--quiet); font-size: 0.92rem; padding-top: 0.2rem; }
.qa .a { font-size: 1.05rem; font-weight: 500; line-height: 1.45; padding-top: 0.1rem; }
.qa .a .detail { color: var(--quiet); font-size: 0.88rem; font-weight: 400; margin-top: 0.3rem; max-width: 56ch; }
.qa .a .steps { margin: 0.4rem 0 0; padding-left: 1.1rem; color: var(--quiet); font-size: 0.88rem; font-weight: 400; }
.qa .a .step + .step, .qa .a .outcome + .outcome { margin-top: 0.6rem; }
.qa .you {
  display: grid; grid-template-columns: 1rem 1fr; gap: 0.5rem; align-content: start;
  padding: 0.45rem 0.8rem; border-radius: 8px; font-size: 0.93rem;
  background: var(--sunken); color: var(--ink);
}
.qa .you .steps { margin: 0.4rem 0 0; padding-left: 1.1rem; color: var(--quiet); font-size: 0.87rem; }
.qa .mark { font-weight: 800; line-height: 1.5; }
.qa .y-met, .qa .y-above { background: var(--met-soft); }
.qa .y-met .mark, .qa .y-above .mark { color: var(--met); }
.qa .y-not_met, .qa .y-below { background: var(--bad-soft); }
.qa .y-not_met .mark, .qa .y-below .mark { color: var(--bad); }
.qa .y-unknown, .qa .y-unclear { background: var(--open-soft); }
.qa .y-unknown .mark, .qa .y-unclear .mark { color: var(--open); }
.qa .y-todo, .qa .y-info { background: var(--mark-soft); }
.qa .y-todo .mark, .qa .y-info .mark { color: var(--mark); }
/* nothing to meet: present so the row is complete, but it should not compete with real verdicts */
.qa .y-not_applicable, .qa .y-equal, .qa .y-not_comparable { background: transparent; color: var(--quiet); }
.qa .y-not_applicable .mark { color: var(--quiet); }
@media (max-width: 760px) {
  .qa > li { grid-template-columns: 1fr; row-gap: 0.25rem; padding: 0.6rem 0; }
  .qa .q { padding-top: 0; }
  .qa .you { margin-top: 0.3rem; }
}

.todo { list-style: none; margin: 0; padding: 0; }
.todo li { padding: 0.3rem 0 0.3rem 1rem; position: relative; font-size: 0.9rem; }
.todo li::before { content: ''; position: absolute; left: 0; top: 0.8rem; width: 0.45rem; height: 1px; background: var(--rule-strong); }

/* ---------- timeline ---------- */
.timeline { list-style: none; margin: 0; padding: 0 0 0 1.4rem; position: relative; max-width: var(--measure); }
.timeline::before { content: ''; position: absolute; left: 0.28rem; top: 0.5rem; bottom: 0.5rem; width: 1px; background: var(--rule); }
.timeline li { position: relative; padding: 0.5rem 0; display: flex; flex-wrap: wrap; gap: 0.25rem 0.9rem; align-items: baseline; }
.timeline li::before { content: ''; position: absolute; left: -1.4rem; top: 0.95rem; width: 0.6rem; height: 0.6rem; border-radius: 50%; background: var(--paper); border: 2px solid var(--rule-strong); }
.timeline li.soon::before { background: var(--open); border-color: var(--open); }
.timeline li.next::before { background: var(--mark); border-color: var(--mark); }
.timeline li.past::before { border-color: var(--rule); }
.timeline .when { font-weight: 600; font-variation-settings: 'wdth' 88; min-width: 6.5rem; }
.timeline li.past .when, .timeline li.past .purpose { color: var(--quiet); text-decoration: line-through; text-decoration-color: var(--rule-strong); }
.timeline .away { color: var(--quiet); font-size: 0.82rem; margin-left: auto; }
.timeline li.old .when, .timeline li.old .purpose { color: var(--quiet); }
.timeline li.old::before { border-style: dashed; }
.timeline li.old .away { display: inline-flex; align-items: center; gap: 0.3rem; }
.timeline + .meta { margin-top: 0.75rem; }
.timeline li.soon .away, .timeline li.next .away { color: var(--open); }

/* ---------- rankings: one line, secondary to the facts above ---------- */
.ranking { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.5rem 2.5rem; }
.ranking > h4 { margin: 0; font-size: 1rem; font-weight: 500; color: var(--quiet); flex-basis: 100%; }
.ranks { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 0.5rem 2.25rem; }
.ranks li { display: flex; align-items: baseline; gap: 0.45rem; }
.ranks .rank { font-size: 1.35rem; font-weight: 650; font-variation-settings: 'wdth' 80; }
.ranks .provider { font-size: 0.9rem; color: var(--quiet); }
.ranking .meta { flex-basis: 100%; max-width: 64ch; margin: 0.35rem 0 0; }

.stats td { padding: 0.35rem 0.7rem 0.35rem 0; }
.programme-list { list-style: none; margin: 0; padding: 0; }
.programme-list li { display: flex; flex-wrap: wrap; gap: 0.75rem; align-items: baseline; padding: 0.6rem 0 0.6rem 0.8rem; border-bottom: 1px solid var(--rule); border-left: 4px solid var(--rule); }
.programme-list li.r-met { border-left-color: var(--met); }
.programme-list li.r-unknown { border-left-color: var(--open); }
.programme-list li.r-not_met { border-left-color: var(--bad); }
.programme-list a { font-weight: 600; }
.programme-list .tag { margin-left: auto; }

/* ---------- evidence, deliberately quiet ---------- */
.source { margin-bottom: 0.6rem; font-size: 0.85rem; }
.quote { border-left: 2px solid var(--rule-strong); padding: 0.1rem 0 0.1rem 0.6rem; margin: 0.25rem 0 0; white-space: pre-wrap; color: var(--quiet); font-size: 0.85rem; }
.more { margin-top: 1.5rem; }
.more > summary { cursor: pointer; color: var(--quiet); font-size: 0.95rem; padding: 0.5rem 0; }
.more > summary:hover { color: var(--ink); }
.facts td:first-child { width: 13rem; color: var(--quiet); }
.value + .value { margin-top: 0.3rem; }

.compare td { min-width: 15rem; }
.compare td:first-child { min-width: 0; width: 11rem; color: var(--quiet); }

.empty { padding: 3rem 1rem; text-align: center; color: var(--quiet); border: 1px dashed var(--rule-strong); max-width: none; }
.empty strong { display: block; color: var(--ink); font-size: 1.05rem; margin-bottom: 0.35rem; }
.star { font-size: 1rem; line-height: 1; }
.star.on { color: var(--mark); }

@media (max-width: 640px) {
  header { gap: 0.5rem 1rem; }
  .facts td:first-child { width: auto; }
  .verdict button { flex: 1 1 8rem; }
  #drawer { padding-bottom: 4rem; }
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}
