/* Rankings: the reader's page (templates/rankings/*.html, core/views_rankings.py).
   One entity-first page - a section tab chooses what is being counted, the shared rail selects it,
   and the panes show it. Classes are prefixed .rk-; colour and type come from app.css tokens.
   docs/ui-redesign.md is the specification this draws. */

/* ── The page and its tabs ────────────────────────────────────────────── */
/* The page fills the window: the rail and the panes have more to hold than a centred column allows. */
main.rk-page { background: var(--white); width: 100%; max-width: none; padding: 0;
               --rk-bar: 47px;      /* the one bar */
               --rk-head: 47px;     /* what is sticky above the page: the bar alone */
               --rk-rail: 216px;    /* the filter column, and the pane switch that sits over it */
               --rk-pad: 16px;      /* the page's own side padding */
               /* The chrome the bar and the filter column share: a light blue-grey, so the two
                  read as one surface around the white the figures are drawn on. */
               --rk-chrome: #eef2f8; }
.rk-in { width: 100%; max-width: none; margin: 0; padding: 0 var(--rk-pad); }
/* The bar and the page below it are laid out on the SAME two tracks: the filter column, and the sheet. The
   tabs therefore begin on the sheet's own left edge by construction, with no offsets to keep in step. */
.rk-grid { display: grid; grid-template-columns: var(--rk-rail) minmax(0, 1fr); gap: 0; align-items: end; }

/* The one row of navigation, drawn as tabs on a strip: the current one is a sheet of the page below it, its
   bottom edge open onto the pane it names; the others sit back on the strip. */
/* The one bar stays at the top of the window: it is the site's whole navigation, and a tab that scrolls out of
   reach is no tab. Everything below scrolls under it. */
.rk-tabs { position: sticky; top: 0; z-index: 30; background: var(--rk-chrome);
           border-bottom: 1px solid var(--rule); padding: 9px var(--rk-pad) 0; }
.rk-topbar { padding: 0; }
/* The site's name, on the filter column's track: the one thing in the bar that is about the site and not
   about the query. It sits on the tabs' own baseline so the row reads as one line. */
.rk-mark { display: block; padding: 0 16px 11px 0; white-space: nowrap; font-size: 15px; font-weight: 600;
           letter-spacing: -.01em; color: var(--ink); text-decoration: none; align-self: end; }
.rk-mark:hover { color: var(--accent); }
.rk-menus { margin-left: auto; padding-bottom: 8px; display: flex; gap: 14px; align-items: center; flex: none; }

/* The tabs and the "?" on one line: the bar's grid has two tracks, so they share the second one rather than
   the "?" becoming a third child and wrapping to a row of its own. */
.rk-navrow { display: flex; align-items: flex-end; justify-content: space-between; gap: 12px; min-width: 0; }

/* "What this is", at the end of the bar. A circle because it is one small question and not a menu; muted
   until asked for, so it is available without competing with the section tabs beside it. */
.rk-help { align-self: end; margin-bottom: 7px; flex: none;
           width: 20px; height: 20px; padding: 0; border-radius: 50%; cursor: pointer;
           border: 1px solid var(--rule-strong); background: var(--white);
           font: 500 12px/1 var(--mono); color: var(--muted); }
.rk-help:hover { border-color: var(--ink); color: var(--ink); background: var(--fill); }
.rk-help:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.rk-tabrow { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0 3px; margin-bottom: -1px; }
.rk-tab { display: flex; align-items: baseline; gap: 7px; padding: 9px 16px 8px; font-size: 13px;
          color: var(--ink-2); text-decoration: none; border: 1px solid transparent; border-bottom: 0;
          border-radius: 9px 9px 0 0; position: relative; }
.rk-tab:hover { background: var(--fill-hover); color: var(--ink); }
.rk-tab[aria-current="page"] { background: var(--white); color: var(--ink); font-weight: 500;
                               border-color: var(--rule); padding-bottom: 9px; }
/* The strip's bottom rule stops at the open tab: this covers it, two pixels deep so no half-pixel of it
   survives rounding and shows as a hairline across the tab's foot. */
.rk-tab[aria-current="page"]::after { content: ""; position: absolute; left: 0; right: 0; bottom: -2px;
                                      height: 3px; background: var(--white); }
.rk-tab .n { font-size: 11px; color: var(--muted-2); font-variant-numeric: tabular-nums; }
.rk-tab[aria-current="page"] .n { color: var(--muted); }
.rk-tab.is-away { margin-left: auto; color: var(--muted); }
.rk-tab.is-away:hover { color: var(--ink); }
/* The tabs are pulled left by exactly one border, so the first tab's own left border IS the rail's right
   border rather than a second line beside it.

   Both rules are 1px of `--rule`, and both were being drawn: the rail's right border ended on the grid
   track and the tab's left border began there, so the two sat edge to edge as a 2px double line, the open
   tab's white body started a pixel late, and its label - 1px border plus 16px padding - landed a pixel right
   of the pane's own contents, which `.rk-main` pads 16px from the same track. Taking the border's width off
   the row puts the line, the sheet's edge and the label all on the track: the tab's border occupies the
   track's own pixel, and its label falls at 16px from it like everything below. Stated as 1px, the declared
   width, so it holds at any zoom - the used value is 0.8px at 80%, and both borders scale together. */
.rk-tabrow { margin-left: -1px; }

/* ── Shell: rail beside main ──────────────────────────────────────────── */
/* The rail is a column of short statements, so it needs the width of its longest value and no more. */
.rk-shell { align-items: start; }
/* The sheet's own edge stays on the grid track (that is what the tabs align to); its contents sit inside
   it, so no figure is printed against the filter column's rule. */
.rk-main { padding: 0 18px 64px 16px; min-width: 0; }
/* The rail is the same sheet as the pane's own strip: it starts on the line the Analytics and Database tabs
   sit on, in the same grey, so the filters read as part of the pane they are filtering and not as furniture
   beside it. */
/* The column runs from the bar to the foot of the window and out to the window's own edge: nothing white
   above it, below it or beside it. It carries the bar's own grey, so the bar and the column are one surface
   the controls sit on. It breaks out of the page's side padding and puts that padding inside. */
.rk-rail { position: sticky; top: var(--rk-bar); height: calc(100vh - var(--rk-bar));
           overflow-y: auto; overscroll-behavior: contain; background: var(--rk-chrome);
           border-right: 1px solid var(--rule); box-sizing: border-box;
           margin-left: calc(-1 * var(--rk-pad)); width: calc(var(--rk-rail) + var(--rk-pad));
           padding: 12px 11px 24px var(--rk-pad); }
.rk-rail-head { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 8px; }
.rk-rail-head-2 { margin-top: 20px; padding-top: 14px; border-top: 1px solid var(--rule); }
.rk-rail h2 { font-size: 10.5px; font-family: var(--mono); text-transform: uppercase; letter-spacing: .07em;
              color: var(--muted-2); font-weight: 400; margin: 0; }
.rk-reset { font-size: 12px; color: var(--accent); }

/* One row per filter: closed it states what it selects, open it shows the choices. `name="rail"` makes the
   rows one accordion, so the column is a short list of statements rather than a wall of chips. */
.rk-f { border-bottom: 1px solid var(--rule-2); }
.rk-f > summary { display: flex; justify-content: space-between; align-items: baseline; gap: 8px;
                  padding: 7px 14px 7px 1px; cursor: pointer; list-style: none; position: relative; }
.rk-f > summary::-webkit-details-marker { display: none; }
.rk-f > summary::after { content: ""; position: absolute; right: 2px; top: 12px; width: 6px; height: 6px;
                         border-right: 1.5px solid var(--muted-2); border-bottom: 1.5px solid var(--muted-2);
                         transform: rotate(45deg); transition: transform .12s ease; }
.rk-f[open] > summary::after { transform: rotate(-135deg); top: 14px; }
.rk-f > summary:hover { background: var(--white); }
.rk-f > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.rk-f-name { font-size: 12.5px; font-weight: 500; color: var(--ink); white-space: nowrap; }
.rk-f-value { font-size: 11.5px; color: var(--muted); text-align: right; overflow: hidden;
              text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.rk-f[open] .rk-f-value { color: var(--ink-2); }
/* A row that is actually narrowing the selection says so in its own figure, which goes dark and bold. There
   was an accent rule down the row's left edge as well, saying the same thing a second time; in a column of
   eight rows it read as a border the panel did not otherwise have. The figure carries it alone. */
.rk-f.is-set .rk-f-value { color: var(--ink); font-weight: 500; }
.rk-f-body { padding: 2px 2px 12px; }
.rk-f-empty { font-size: 12px; color: var(--muted); margin: 0; }

/* "All" and any groups beside it, on one wrapping line above the choices. */
.rk-groups { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 6px; }

/* "All" leads a row of choices: one statement about the whole row, so it is a link and not another tick. */
.rk-all { display: inline-block; padding: 2px 8px; font-size: 11.5px; text-decoration: none;
          border: 1px solid var(--rule-strong); border-radius: 3px; background: var(--white); color: var(--muted); }
.rk-all:hover { background: var(--fill-hover); color: var(--ink); }
.rk-all.is-on { background: var(--fill); border-color: var(--ink); color: var(--ink); font-weight: 500; }

/* The two bar buttons: what the site is, and what this section draws. */
.rk-bar-buttons { display: flex; align-items: flex-end; gap: 6px; flex: none; }
.rk-help svg { display: block; margin: auto; }

/* ── The chart guide ────────────────────────────────────── */
/* Every graph the site draws, from core/chart_registry.py: the record the code reads, shown to the reader.
   Dense on purpose (the author's rule, 2026-09-17): all 28 charts in one look, not a scroll. `dialog.gd` and
   not `.gd`, so it outranks `dialog.dialog`'s own width. */
dialog.gd { width: min(1340px, calc(100vw - 32px)); max-width: none; padding: 20px 22px 22px; }
.gd-lead { margin: 0 0 4px; color: var(--ink-2); }
.gd .dialog-body { margin-top: 10px; }
/* Multi-column, not a grid: the sections are different lengths, and a grid would leave the short ones'
   space empty while the long ones ran on. Columns flow, so the whole set packs to the shortest height it
   fits in. `break-inside: avoid` keeps a section whole - a heading at the foot of one column with its
   charts at the head of the next is worse than an uneven column. */
.gd-cols { column-count: 4; column-gap: 26px; }
@media (max-width: 1100px) { .gd-cols { column-count: 3; } }
@media (max-width: 820px)  { .gd-cols { column-count: 2; } }
@media (max-width: 560px)  { .gd-cols { column-count: 1; } }
.gd-sec { break-inside: avoid; margin: 0 0 14px; }
.gd-sec-name { display: flex; align-items: baseline; gap: 7px; margin: 0 0 1px;
               padding-bottom: 4px; border-bottom: 1px solid var(--rule);
               font: 500 11px/1.3 var(--mono); letter-spacing: .05em; text-transform: uppercase;
               color: var(--ink); }
/* Which of the five the reader is on. Its links are jumps down this page; the rest are pages to load. */
.gd-here { font: 400 10px/1.3 var(--mono); letter-spacing: .02em; text-transform: none; color: var(--muted-2); }
.gd-list { list-style: none; margin: 0; padding: 0; }
.gd-item { padding: 7px 0; border-top: 1px solid var(--rule-2); }
.gd-item:first-child { border-top: 0; }
/* The name carries the chart's one-sentence caption on its `title`: what a reader wants about ONE chart,
   where printing all 28 of them is what made this a scroll. */
.gd-name { display: block; font-size: 12.5px; font-weight: 500; line-height: 1.35;
           color: var(--ink); text-decoration: none; }
.gd-name:hover { color: var(--accent); text-decoration: underline; }
/* The kind of drawing, under the name: it is what the chart IS, not what it is called. */
.gd-kind { display: block; font: 400 10px/1.4 var(--mono); color: var(--muted-2); }
.gd-opts { margin: 4px 0 0; padding: 0; list-style: none; display: flex; flex-wrap: wrap; gap: 3px 4px; }
.gd-opts li { font-size: 10px; line-height: 1.45; color: var(--muted); border: 1px solid var(--rule-2);
              border-radius: 3px; padding: 0 4px; background: var(--white); }

/* ── The search popout ──────────────────────────────────── */
/* One query across every section (core/find.py), one column per section, so the five answers stand side by
   side. `dialog.fd`, not `.fd`, so it outranks `dialog.dialog`'s own width. */
dialog.fd { width: min(1340px, calc(100vw - 32px)); max-width: none; padding: 20px 22px 22px; }
/* Near the top, not centred (the author's rule, 2026-09-17). A modal <dialog> centres itself, which is right
   for a panel whose size is settled and wrong for this one: it opens almost empty, grows as the reader types,
   and a centred box grows from BOTH edges - so the search field slides upward under the cursor while
   somebody is still typing into it. Pinned at the top, the field stays put and the results fill downward.

   Guarded to the wide layout: under 640px app.css makes every dialog a bottom sheet (`margin: auto 0 0`),
   which is the right shape on a phone and which this would otherwise override - rankings.css loads after
   app.css, so on equal specificity this file wins. */
@media (min-width: 641px) { dialog.fd { margin-block: 6vh auto; } }
.fd-form { display: flex; gap: 8px; align-items: center; margin: 0; }
.fd-q { flex: 1; min-width: 0; height: 38px; padding: 0 11px; font-size: 14px; color: var(--ink);
        background: var(--white); border: 1px solid var(--rule-strong); border-radius: 4px; }
.fd-q:focus { outline: 2px solid var(--accent); outline-offset: -1px; }
/* The results scroll, not the dialog, so the box the reader is typing in never leaves the screen. */
.fd-out { max-height: min(64vh, 640px); overflow: auto; margin-top: 14px; }
.fd-empty { margin: 0; padding: 18px 0; font-size: 13px; color: var(--muted); line-height: 1.6; }
/* A real grid and not `column-count`: multi-column would flow ONE section across several columns, and the
   whole point is that a column IS a section. `auto-fit` so four sections fill the width when the fifth has
   no answer, and a floor of 200px so a narrow window wraps to two rows instead of five unreadable slivers. */
.fd-cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 0 24px;
           align-items: start; }
.fd-sec { min-width: 0; }
.fd-sec-name { display: flex; align-items: baseline; gap: 7px; margin: 0 0 1px; padding-bottom: 4px;
               border-bottom: 1px solid var(--rule); font: 500 11px/1.3 var(--mono); letter-spacing: .05em;
               text-transform: uppercase; color: var(--ink); }
/* How many the section holds in all, so a column of eight never reads as the whole answer. */
.fd-n { font: 400 11px/1.3 var(--mono); letter-spacing: 0; color: var(--muted-2); }
/* The reason a whole column is here, said once instead of on all eight rows. */
.fd-sec-note { margin: 4px 0 0; font-size: 11px; font-style: italic; color: var(--muted); }
.fd-list { list-style: none; margin: 0; padding: 0; }
.fd-item { padding: 7px 0; border-top: 1px solid var(--rule-2); }
.fd-item:first-child { border-top: 0; }
/* Up to two lines. A column is 250px and a title is long: clipping one at 30 characters names nothing, and
   letting it run names one result per screen. Two lines is the compromise, and `word-break` keeps a single
   long token (a DOI, a hyphen-free German title) inside the column instead of widening it. */
.fd-link { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
           font-size: 12.5px; line-height: 1.35; color: var(--ink); text-decoration: none;
           overflow-wrap: anywhere; }
.fd-link:hover { color: var(--accent); text-decoration: underline; }
/* Year and venue on one line under the name. The year never gives way - a year clipped to "2..." is not a
   year - so it is fixed and the venue is what truncates. */
.fd-sub { display: flex; align-items: baseline; gap: 6px; margin: 2px 0 0; min-width: 0; }
.fd-meta { flex: none; font: 400 10.5px/1.4 var(--mono); color: var(--muted-2); }
.fd-tail { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
           font: 400 10.5px/1.4 var(--mono); color: var(--muted-2); }
/* Why this row is here, where the rows of the column differ. */
.fd-note { margin: 2px 0 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
           font-size: 10.5px; font-style: italic; color: var(--muted); }
.fd-more { margin: 7px 0 0; font-size: 11px; }
.fd-more a { color: var(--muted); }
/* ── A line chart's crosshair ─────────────────────────────────────────── */
/* Hold the cursor over a line chart and it names every series at that year, highest first. The rule and the
   readout are drawn by the server (core/charts.py) and only shown and positioned by the script, so the
   ranking, the numbers and the colours are the chart's own and cannot drift from the lines above them. */
.cl-plot { position: relative; }
.cl-rule { stroke: var(--ink); stroke-width: 1px; opacity: 0; pointer-events: none; }
.cl-plot.is-reading .cl-rule { opacity: .35; }
.cl-reads { position: absolute; inset: 0; pointer-events: none; }
.cl-read { position: absolute; top: 0; min-width: 132px; max-width: 230px; padding: 7px 9px;
           background: var(--white); border: 1px solid var(--rule-strong); border-radius: 4px;
           box-shadow: 0 2px 10px rgb(16 18 22 / .10); font-size: 11.5px; line-height: 1.5; }
.cl-read-head { margin: 0 0 4px; font: 500 11px/1 var(--mono); color: var(--muted-2); }
/* One row per series: its colour, its short name, its value. The name is the short one the chart was given -
   a department's university - because fifteen rows of "Harvard Government · Political Science" is a
   paragraph, and the field is the same on every row of a chart that is inside one field anyway. */
/* The swatch is `ch-key<n>`'s own ::before, from app.css, so this list and the key under the chart take
   their colours from one place. */
.cl-r { display: flex; align-items: baseline; gap: 0; white-space: nowrap; color: var(--ink-2);
        padding: 0; font-size: 11.5px; }
.cl-r::before { width: 8px; height: 8px; margin-right: 6px; flex: none; align-self: center; }
.cl-r b { margin-left: auto; padding-left: 10px; font-weight: 500; color: var(--ink);
          font-variant-numeric: tabular-nums; }

/* The quick links: one row naming everything on the page, each jumping to it. An Analytics pane runs to a
   leaderboard and up to seven charts, which is several screens, so this is the page's own table of contents.
   Quiet - it is a way to get somewhere, not a thing to read - and it wraps rather than scrolling, because a
   list of eight short names is not worth a scrollbar. `scroll-margin-top` on the targets keeps a heading clear
   of the bar that stays at the top of the window. */
.rk-jump { display: flex; flex-wrap: wrap; gap: 4px 14px; margin: 0 0 14px; font-size: 12px; }
.rk-jump a { color: var(--muted); text-decoration: none; white-space: nowrap; }
.rk-jump a:hover { color: var(--ink); text-decoration: underline; }
.rk-board, .rk-sec { scroll-margin-top: 60px; }

/* The choices inside a row: one to a line, ticked in place, so a long list reads down instead of wrapping. */
.rk-opts { display: flex; flex-direction: column; gap: 1px; max-height: 260px; overflow-y: auto; }
.rk-opt { display: flex; align-items: center; gap: 7px; padding: 3px 4px; font-size: 12px;
          color: var(--ink-2); cursor: pointer; border-radius: 3px; }
.rk-opt:hover { background: var(--white); color: var(--ink); }
.rk-opt input { margin: 0; accent-color: var(--ink); }
.rk-opt:has(input:checked) { color: var(--ink); font-weight: 500; }

.rk-chips { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 8px; }
.rk-chip { display: inline-block; border: 1px solid var(--rule-strong); border-radius: 3px; padding: 2px 7px;
           font-size: 12px; color: var(--muted); background: var(--white); text-decoration: none; }
.rk-chip:hover { background: var(--fill-hover); color: var(--ink); }
.rk-chip.is-on { background: var(--fill); border-color: var(--ink); color: var(--ink); }
.rk-years { display: flex; gap: 6px; align-items: center; }
.rk-years input { width: 58px; font-family: var(--mono); font-size: 12px; padding: 3px 6px;
                  border: 1px solid var(--control); border-radius: var(--r-control); background: var(--white); color: var(--ink); }
.rk-years span { font-size: 11px; color: var(--muted-2); }
.rk-weightline { font-size: 12px; color: var(--muted); line-height: 1.5; margin: 12px 0 0; }
.rk-weightline b { font-weight: 500; color: var(--ink-2); }
.rk-rail noscript button { margin-top: 10px; }

/* ── Panes and the view, at the head of the rail ──────────────────────── */
/* Which pane, then what the pane is about, then what it is about it: the whole of the reader's control is one
   column, and the pane itself opens straight into its figures. */
/* The switch sits on the bar's own colour, and the open pane is the one lit in white: no block of white in
   the bar for the pane nobody is in. */
/* The switch lives in the filter column's track and stops short of its edge, so it clears the first tab
   without moving it. */
/* The switch now heads the filter column instead of the bar, so it runs the column's width and sits above
   the rows it governs. */
.rk-panes { display: flex; margin: 0 0 12px; border: 1px solid var(--control);
            border-radius: var(--r-control); overflow: hidden; background: transparent; }
.rk-panes a { flex: 1 1 0; text-align: center; padding: 4px 6px; font-size: 12px; color: var(--muted);
              text-decoration: none; border-right: 1px solid var(--control);
              overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rk-panes a:last-child { border-right: 0; }
.rk-panes a:hover { color: var(--ink); background: rgb(255 255 255 / .55); }
.rk-panes a[aria-current="page"] { background: var(--white); color: var(--ink); font-weight: 500; }
.rk-panes.is-empty { border-color: transparent; }
.rk-f-view { border-top: 1px solid var(--rule-2); }
.rk-f-note { font-size: 11.5px; line-height: 1.5; color: var(--muted); margin: 8px 0 0; }
.rk-pick { display: flex; flex-direction: column; gap: 3px; font-size: 11.5px; color: var(--muted); margin-top: 8px; }
.rk-pick select { width: 100%; font-size: 12px; padding: 3px 5px; border: 1px solid var(--control);
                  border-radius: var(--r-control); background: var(--white); color: var(--ink); }

/* ── Segmented controls ───────────────────────────────────────────────── */
/* A real radio inside each label, hidden, so the control is a set of radios to everything but the eye. */
.rk-lab { font-family: var(--mono); font-size: 10px; text-transform: uppercase; letter-spacing: .07em;
          color: var(--muted-2); }
.rk-seg { display: inline-flex; border: 1px solid var(--control); border-radius: var(--r-control);
          overflow: hidden; background: var(--white); }
.rk-seg label { padding: 3px 11px; font-size: 12.5px; color: var(--muted); cursor: pointer;
                border-right: 1px solid var(--rule-3); }
.rk-seg label:last-child { border-right: 0; }
.rk-seg input { position: absolute; opacity: 0; pointer-events: none; }
.rk-seg label:has(input:checked) { background: var(--fill); color: var(--ink); font-weight: 500; }
.rk-seg label:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: -2px; }

/* ── The y-axis control ───────────────────────────────────────────────── */
/* One of these sits over the list and over every chart: the same control, wherever the reader is reading.
   It is white, like the tab above it and the page around it, so the open tab runs straight into the sheet
   instead of stepping onto a panel of another colour. */
.rk-axis { display: flex; gap: 14px; align-items: center; flex-wrap: wrap; padding: 7px 10px;
           background: var(--white); border-bottom: 1px solid var(--rule); margin: 0; }
.rk-sec .rk-axis { margin: 10px 0 0; border-top: 1px solid var(--rule); }
.rk-axis .rk-grp { display: flex; gap: 7px; align-items: center; }
.rk-axis .rk-note { font-size: 11.5px; color: var(--muted-2); }

/* ── The leaderboard ──────────────────────────────────────────────────── */
.rk-board { border: 1px solid var(--rule); margin-bottom: 20px; }
.rk-board-head { display: flex; justify-content: space-between; gap: 12px; align-items: baseline;
                 padding: 9px 12px; border-bottom: 1px solid var(--ink); }
.rk-board-head h2 { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .07em; margin: 0; }
.rk-board-cap { font-size: 12px; color: var(--muted); }
.rk-row { display: grid; grid-template-columns: 26px minmax(130px, 1.5fr) minmax(0, 2fr) 92px;
          gap: 12px; align-items: center; padding: 7px 12px; border-bottom: 1px solid var(--rule-2); font-size: 13px; }
.rk-row:last-child { border-bottom: 0; }
.rk-row:hover { background: var(--fill-hover); }
.rk-row.is-me { background: var(--fill-me); }
.rk-row .rk-rank { font-family: var(--mono); font-size: 11px; color: var(--muted-2); }
.rk-row .rk-who { min-width: 0; }
.rk-row .rk-who a { color: var(--ink); text-decoration: none; }
.rk-row .rk-who a:hover { text-decoration: underline; }
/* The margin is the separator. `.rk-who` is a flex row with no gap, so the name and this ran together -
   "Harvard Government41 academics". It was hidden while this text began with the university and a middot,
   which read as punctuation between the two; with the university gone it is a digit against a letter. */
.rk-row .rk-sub { display: block; margin-left: 9px; font-size: 11.5px; color: var(--muted);
                  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rk-bar { height: 8px; background: var(--rule-2); }
.rk-bar i { display: block; height: 100%; background: var(--ink); }
.rk-row.is-me .rk-bar i { background: var(--accent); }
.rk-row .rk-val { font-family: var(--mono); font-size: 12.5px; text-align: right; }
.rk-empty { padding: 12px; font-size: 13px; color: var(--muted); }

.rk-cover { font-size: 12.5px; line-height: 1.6; color: var(--muted); margin: 0 0 22px; max-width: 78ch; }
.rk-cover b { color: var(--ink); font-weight: 500; }
.rk-chip.is-on { background: var(--fill); border-color: var(--ink); color: var(--ink); }
.rk-chip { text-decoration: none; }

/* ── Chart sections ───────────────────────────────────────────────────── */
.rk-secs { display: grid; gap: 26px; }
.rk-sec-head { display: flex; justify-content: space-between; gap: 12px; align-items: baseline;
               border-bottom: 1px solid var(--ink); padding-bottom: 6px; }
.rk-sec-head h2 { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .07em; margin: 0; }
.rk-sec-cap { font-size: 12px; color: var(--muted); }
.rk-sec > .rk-hint { font-size: 12px; color: var(--muted); line-height: 1.6; margin: 8px 0 0; }
.rk-sec .ch, .rk-sec .cl { margin-top: 14px; }
/* The key under a chart. Everything it draws is app.css's `.ch-legend` / `.ch-key<n>`, shared with the Compare page,
   so only its place in this section is set here: a block rather than the inline-flex the tag lists use, because a
   key of eight departments wraps onto three rows and has to keep the section's left edge while it does. */
.rk-sec .ch-legend { display: flex; margin-top: 10px; }

/* ── The Database pane ────────────────────────────────────────────────── */
.rk-dbbar { display: flex; justify-content: space-between; gap: 12px; align-items: center; flex-wrap: wrap; margin-bottom: 10px; }
.rk-dbbar .rk-tools { display: flex; gap: 8px; align-items: center; }
.rk-list { border: 1px solid var(--rule); min-width: 0; }
.rk-table-wrap { overflow-x: auto; }
table.rk-table { border-collapse: collapse; width: 100%; font-size: 13px; }
.rk-table th, .rk-table td { text-align: left; padding: 7px 11px; border-bottom: 1px solid var(--rule-2); white-space: nowrap; }
.rk-table thead th { font-size: 10.5px; font-family: var(--mono); text-transform: uppercase; letter-spacing: .06em;
                     color: var(--muted-2); font-weight: 400; border-bottom: 1px solid var(--ink); background: var(--white); }
.rk-table th a { color: inherit; text-decoration: none; }
.rk-table th a:hover { color: var(--ink); text-decoration: underline; }
.rk-table td.r, .rk-table th.r { text-align: right; font-family: var(--mono); font-size: 12.5px; }
.rk-table tbody tr:hover { background: var(--fill-hover); }
.rk-table tbody tr[aria-current="true"] { background: var(--fill-me); }
.rk-table tbody tr[aria-current="true"] td:first-child { box-shadow: inset 2px 0 0 var(--ink); }
.rk-table .rk-title { white-space: normal; max-width: 460px; }
.rk-pager { display: flex; justify-content: space-between; gap: 12px; align-items: center;
            padding: 8px 11px; font-size: 12px; color: var(--muted); border-top: 1px solid var(--rule); }

/* The columns, sized by what they hold rather than equally. A fixed layout is the point: left to itself the
   browser gives a venue the width of its longest name and squeezes a title, which is the wrong way round -
   the title is what the row is, the venue is a fact about it. `data-col` comes from the section's own column
   list (views_rankings._sorted), so one rule serves five tables. */
.rk-db { table-layout: fixed; }
.rk-db th, .rk-db td { overflow: hidden; text-overflow: ellipsis; }
.rk-db [data-col="title"], .rk-db [data-col="name"], .rk-db [data-col="department"],
.rk-db [data-col="journal"] { width: 34%; }
.rk-db [data-col="academics"]:not(.r) { width: 20%; }
.rk-db [data-col="venue"] { width: 19%; }
.rk-db [data-col="university"], .rk-db [data-col="field"], .rk-db [data-col="rank"] { width: 12%; }
.rk-db [data-col="year"], .rk-db [data-col="kind"], .rk-db [data-col="tier"] { width: 74px; }
.rk-db td.r, .rk-db th.r { width: 96px; }
/* The title wraps rather than being cut: it is the one column where the whole value has to be readable. */
.rk-db td[data-col="title"], .rk-db td[data-col="name"], .rk-db td[data-col="department"],
.rk-db td[data-col="journal"] { white-space: normal; max-width: none; }
.rk-db td[data-col="academics"]:not(.r), .rk-db td[data-col="venue"] { white-space: normal; }
.rk-db td[data-col="venue"] { color: var(--muted); font-size: 12px; }

/* A row is the control, so it looks like one and opens on a click anywhere along it. */
.rk-db tr.rk-r { cursor: pointer; }
.rk-db tr.rk-r > td:first-child { position: relative; }
.rk-db tr.rk-r[aria-expanded="true"] { background: var(--fill-me); }
.rk-db tr.rk-r[aria-expanded="true"] > td { border-bottom-color: transparent; }
.rk-db tr.rk-r[aria-expanded="true"] > td:first-child { box-shadow: inset 2px 0 0 var(--ink); }
.rk-db tr.rk-r a { color: inherit; text-decoration: none; }
.rk-db tr.rk-r:hover .rk-title a, .rk-db tr.rk-r a:focus-visible { text-decoration: underline; }

/* The record, folded out under the row it belongs to. */
.rk-db tr.rk-fold > td { padding: 0; background: var(--rail); border-bottom: 1px solid var(--ink);
                         white-space: normal; }
.rk-db tr.rk-fold[aria-busy="true"] .rk-fold-body { opacity: .45; }
.rk-fold-body { min-height: 2px; }
/* The fold is as wide as the table, so the groups run in columns rather than one long ladder with the key at
   one edge of the screen and its value at the other. */
.rk-fold-body .rk-rec-head { padding: 10px 12px; border-bottom: 1px solid var(--rule); }
.rk-fold-body .rk-rec-grp { padding: 10px 12px; border-bottom: 0; break-inside: avoid; }
.rk-fold-body > .rk-rec-grp { display: inline-block; vertical-align: top; width: 100%; box-sizing: border-box; }
@supports (columns: 2) {
  .rk-fold-body { columns: 2; column-gap: 0; }
  .rk-fold-body > .rk-rec-head { column-span: all; }
}
.rk-fold-body .rk-rec-lines > div { max-width: 46ch; }

/* the record itself, now folded under its row rather than parked in a panel beside the list */
.rk-rec-head { display: flex; justify-content: space-between; gap: 10px; align-items: baseline;
               padding: 10px 12px; border-bottom: 1px solid var(--ink); }
.rk-rec-head h2 { font-size: 14.5px; font-weight: 600; margin: 0; line-height: 1.3; }
.rk-rec-kind { font-family: var(--mono); font-size: 10.5px; text-transform: uppercase; letter-spacing: .06em; color: var(--muted-2); }
.rk-rec-grp { padding: 10px 12px; border-bottom: 1px solid var(--rule-2); }
.rk-rec-grp:last-child { border-bottom: 0; }
.rk-rec-grp > h3 { font-family: var(--mono); font-size: 10px; text-transform: uppercase; letter-spacing: .07em;
                   color: var(--muted-2); font-weight: 400; margin: 0 0 6px; }
.rk-rec-lines { margin: 0; font-size: 12.5px; }
.rk-rec-lines > div { display: flex; justify-content: space-between; gap: 12px; padding: 2px 0; }
.rk-rec-lines .k { color: var(--muted); }
.rk-rec-lines .v { text-align: right; }
.rk-rec-lines .v.n { font-family: var(--mono); font-size: 12px; }
.rk-rec-empty { padding: 14px 12px; font-size: 12.5px; color: var(--muted); }
.rk-fold-body a { color: var(--accent); }

/* ── The citation weight pane ─────────────────────────────────────────── */
.rk-input { font-size: 12.5px; padding: 3px 6px; border: 1px solid var(--control); border-radius: var(--r-control);
            background: var(--white); color: var(--ink); }
.rk-input.n { font-family: var(--mono); }
.rk-weight { width: 72px; text-align: right; }
.rk-input:disabled { background: var(--fill); color: var(--muted-2); }
.rk-table .meta { font-family: var(--mono); font-size: 10.5px; color: var(--muted-2); }

.rk-weight-eq { font-family: var(--mono); font-size: 13px; padding: 10px 12px; background: var(--rail);
                border: 1px solid var(--rule); margin-bottom: 14px; }
.rk-weight-vars { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 10px 18px;
                  font-size: 12px; color: var(--muted); margin-bottom: 16px; }
.rk-weight-vars b { color: var(--ink); font-weight: 500; }

/* ── The Department formula section ───────────────────────────────────── */
/* An equation is read, not skimmed, so it gets the mono face and room to breathe; the ready-made ones are
   cards because the reader is choosing between whole statements, not picking a word out of a list. */
.rk-eq { width: min(340px, 100%); }
.rk-eq-bad { font-size: 12.5px; color: var(--bad, #a1231b); margin: 0 0 14px; }
.rk-eq-presets { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 1px;
                 background: var(--rule); border: 1px solid var(--rule); margin-bottom: 26px; }
.rk-eq-preset { display: grid; gap: 4px; padding: 12px 14px; background: var(--white); text-decoration: none;
                color: inherit; align-content: start; }
.rk-eq-preset:hover { background: var(--rail); }
.rk-eq-preset.is-on { background: var(--fill); }
.rk-eq-preset b { font-family: var(--mono); font-size: 12.5px; font-weight: 500; color: var(--ink); }
.rk-eq-title { font-size: 12.5px; color: var(--ink-2); }
.rk-eq-note { font-size: 11.5px; line-height: 1.5; color: var(--muted); }
.rk-eq-table { margin-bottom: 14px; }
.rk-eq-table .rk-sub { color: var(--muted); font-size: 11.5px; }

@media (max-width: 1000px) {
  /* Narrow: the columns stop being a grid and the table scrolls sideways instead of crushing the title. */
  .rk-db { table-layout: auto; }
  .rk-db td[data-col="title"], .rk-db td[data-col="name"] { min-width: 260px; }
  .rk-fold-body { grid-template-columns: 1fr; }
}
@media (max-width: 880px) {
  .rk-shell { grid-template-columns: 1fr; gap: 0; }
  .rk-rail { position: static; max-height: none; border-right: 0; border-bottom: 1px solid var(--rule);
             padding-right: 0; padding-bottom: 16px; margin-bottom: 18px; }
}

/* ── A record on the whole sheet (Academics, Departments, Journals) ────── */
/* Its own page, not a panel: the reading runs the width of the sheet and the list is one link behind. */
.rk-recpage { padding-bottom: 48px; }
.rk-back { display: inline-block; margin-bottom: 12px; font-size: 12.5px; color: var(--accent);
           text-decoration: none; }
.rk-back:hover { text-decoration: underline; }
.rk-back::before { content: "\2190"; margin-right: 6px; }
.rk-recpage .rk-rec-head { display: flex; justify-content: space-between; gap: 12px; align-items: baseline;
                           padding: 0 0 10px; border-bottom: 1px solid var(--ink); margin-bottom: 16px; }
.rk-recpage .rk-rec-head h2 { font-size: 22px; line-height: 1.2; }
/* The groups sit in a grid rather than a column: on a wide sheet a single column of short lists is mostly
   whitespace, and the reader has to scroll past facts to reach the charts. */
.rk-recpage .rk-rec-grp { padding: 0 0 18px; border-bottom: 0; break-inside: avoid; }
.rk-recpage > .rk-rec-grp, .rk-recpage .rk-rec-grp { margin-bottom: 0; }
@supports (display: grid) {
  .rk-recpage { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 0 28px;
                align-items: start; }
  .rk-recpage > .rk-back, .rk-recpage > .rk-rec-head { grid-column: 1 / -1; }
  /* A group holding a drawing or a long list takes the full width; short fact lists share the columns. */
  .rk-recpage > .rk-rec-grp.is-wide { grid-column: 1 / -1; }
}
.rk-recpage .rk-rec-lines > div { max-width: 52ch; }

/* A record's own table: every publication, the roster, the works in a venue. Compact, because it sits inside
   a record rather than being the page's own list. */
.rk-rec-tablewrap { overflow-x: auto; max-height: 420px; overflow-y: auto; border: 1px solid var(--rule-2); }
table.rk-rec-table { border-collapse: collapse; width: 100%; font-size: 12.5px; }
.rk-rec-table th, .rk-rec-table td { text-align: left; padding: 5px 9px; border-bottom: 1px solid var(--rule-2); }
.rk-rec-table thead th { position: sticky; top: 0; background: var(--white); z-index: 1;
                         font-family: var(--mono); font-size: 10px; text-transform: uppercase;
                         letter-spacing: .06em; color: var(--muted-2); font-weight: 400;
                         border-bottom: 1px solid var(--rule-strong); }
.rk-rec-table td.r, .rk-rec-table th.r { text-align: right; font-family: var(--mono); font-size: 12px;
                                         white-space: nowrap; }
.rk-rec-table tbody tr:hover { background: var(--fill-hover); }
.rk-rec-n { font-family: var(--mono); font-size: 10px; color: var(--muted-2); letter-spacing: 0; }
.rk-rec-more { font-size: 11.5px; color: var(--muted); margin: 6px 0 0; }

/* The depth box on a ranked chart: a number the reader types, not a set of guesses at one. */
.rk-depth { width: 62px; text-align: right; }

/* ── The university mark ──────────────────────────────────────────────── */
/* Three letters in the university's own colour, in front of a department's name and big at the head of its
   record. A solid block rather than an outline: at 16px an outlined chip is mostly border. */
.uni-mark { display: inline-flex; align-items: center; justify-content: center; flex: none;
            min-width: 30px; height: 16px; padding: 0 4px; border-radius: 2px;
            background: var(--mark, var(--muted-2)); color: #fff;
            font-family: var(--mono); font-size: 9.5px; font-weight: 600; letter-spacing: .04em;
            vertical-align: 1px; }
.uni-mark.is-big { min-width: 62px; height: 40px; border-radius: 4px; font-size: 20px; letter-spacing: .02em;
                   vertical-align: 0; }
/* In a table cell and a leaderboard row the mark leads the name on one line. */
.rk-db td .uni-mark, .rk-who .uni-mark, .rk-rec-table td .uni-mark { margin-right: 7px; }
.rk-who { display: flex; align-items: baseline; gap: 0; flex-wrap: wrap; }
.rk-recpage .rk-rec-head .uni-mark { margin-right: 12px; }
.rk-rec-name { display: flex; align-items: center; gap: 0; min-width: 0; }
/* The university's own logo, where its site published one. Contained rather than cropped: these are fifteen
   different shapes - a shield, a tree, a letter - and only `contain` keeps each one whole at one size. */
.uni-logo { width: 18px; height: 18px; object-fit: contain; flex: none; vertical-align: -3px; }
.uni-logo.is-big { width: 44px; height: 44px; }
.rk-db td .uni-logo, .rk-who .uni-logo, .rk-rec-table td .uni-logo { margin-right: 7px; }
.rk-recpage .rk-rec-head .uni-logo { margin-right: 14px; }

/* ── Sorting a Database column ────────────────────────────────────────── */
/* The heading is the control, so it carries the arrow rather than the cell beside it. A numeric column is
   right-aligned, so its arrow goes on the left of the label and the two still read as one word. */
.rk-sort { display: inline-flex; align-items: baseline; gap: 4px; color: inherit; text-decoration: none; }
.rk-sort:hover { color: var(--ink); }
.rk-db th.r .rk-sort { flex-direction: row-reverse; }
.rk-arrow { font-size: 10px; line-height: 1; color: var(--muted-2); opacity: .32; transition: opacity .12s ease; }
.rk-sort:hover .rk-arrow, .rk-sort:focus-visible .rk-arrow { opacity: 1; }
/* The column actually in force: its arrow is the answer, not an offer, so it is dark and always full strength. */
.rk-sort.is-on { color: var(--ink); font-weight: 500; }
.rk-sort.is-on .rk-arrow { opacity: 1; color: var(--accent); font-size: 11px; }
/* A heading on a list that cannot be reordered (the grouped Fields list). It carries no arrow and does not
   light up under the pointer, because there is nothing to click: an affordance here would be a lie. */
.rk-sort.is-fixed, .rk-sort.is-fixed:hover { color: inherit; cursor: default; }

/* ── The collaboration matrix ─────────────────────────────────────────── */
/* A square of shared works. The column heads are turned on their side: fourteen names across the top would
   otherwise set the column width and make the grid wider than the sheet. */
.rk-grid-matrix { table-layout: auto; }
.rk-grid-matrix th[scope="row"] { text-align: left; white-space: nowrap; font-weight: 400; color: var(--ink-2);
                                  position: sticky; left: 0; background: var(--white); z-index: 1; }
.rk-grid-matrix .rk-diag { height: 104px; vertical-align: bottom; padding: 0 0 6px; width: 26px; }
.rk-grid-matrix .rk-diag span { display: inline-block; transform: rotate(-60deg); transform-origin: left bottom;
                                white-space: nowrap; font-family: var(--mono); font-size: 10px;
                                letter-spacing: 0; text-transform: none; color: var(--muted); }
.rk-cell { text-align: center; font-family: var(--mono); font-size: 11.5px; color: var(--muted-2);
           width: 26px; padding: 4px 2px; }
/* The count sits on a wash of the accent, so a dense corner reads as a shape before it reads as numbers. */
.rk-cell.is-on { background: color-mix(in srgb, var(--accent) calc(var(--heat) * 62%), transparent);
                 color: var(--ink); font-weight: 500; }
.rk-cell.is-self { background: var(--fill); }

/* ── The welcome dialog ───────────────────────────────────────────────── */
/* Wider than a confirm dialog, because it is a page of reading rather than a question, and it scrolls on a
   short window instead of pushing its own button off the screen. */
dialog.wc { width: min(680px, calc(100vw - 32px)); max-height: min(88vh, 900px); overflow-y: auto; }
.wc-mark { font-size: 11px; font-family: var(--mono); text-transform: uppercase; letter-spacing: .1em;
           color: var(--muted-2); margin: 0; }
.wc-lead { font-size: 15.5px; line-height: 1.55; color: var(--ink); font-weight: 500; }
.wc-sub { margin-bottom: .4em !important; }
/* The two claims lead their paragraphs, so they read as headings without being one. */
.wc-point { color: var(--ink); font-weight: 600; }
.wc-units { margin: 0 0 1.2em; padding-left: 18px; font-size: 13.5px; line-height: 1.6; }
.wc-units li { margin-bottom: 3px; }
.wc-units b { font-weight: 600; color: var(--ink); }
.wc .dialog-actions { position: sticky; bottom: -24px; background: var(--white); padding-top: 14px;
                      margin-top: 22px; border-top: 1px solid var(--rule-2); }
.wc .dialog-actions form { margin: 0; }

/* ── The evidence table under a graph ─────────────────────────────────── */
/* What these filters select, one line per mark (core/rankings_coverage.py). Shown rather than folded away:
   the rows that explain a quiet graph are sorted to the top, and a reason behind a disclosure is a reason
   nobody reads. `.rk-cov` and not `.rk-cover`, which is the board's own sentence and a different thing. */
.rk-cov { margin-top: 16px; padding-top: 12px; border-top: 1px solid var(--rule-2); }
/* The summary line: it names what is behind the fold, so the table is closed without being a mystery. */
.rk-cov-head { display: flex; align-items: baseline; gap: 8px; margin: 0; padding: 2px 0; cursor: pointer;
               font: 500 10.5px/1.3 var(--mono); letter-spacing: .06em; text-transform: uppercase;
               color: var(--muted-2); list-style: none; }
.rk-cov-head::-webkit-details-marker { display: none; }
/* The disclosure's own arrow, drawn with borders rather than set as a character: the line is monospaced and
   IBM Plex Mono has no triangle, so a glyph here renders as a replacement box. */
.rk-cov-head::before { content: ""; flex: none; align-self: center; width: 0; height: 0; margin-right: 3px;
                       border: 4px solid transparent; border-left-color: currentColor; border-right-width: 0;
                       transition: transform .12s ease; }
.rk-cov[open] > .rk-cov-head::before { transform: rotate(90deg); }
.rk-cov-head:hover { color: var(--ink-2); }
.rk-cov[open] > .rk-cov-head { margin-bottom: 7px; }
/* The half of the heading that stops the table being read as the graph's denominator. */
.rk-cov-note { font: 400 10.5px/1.3 var(--mono); letter-spacing: .02em; text-transform: none;
               color: var(--muted-2); font-style: italic; }
/* A department-level table is a dozen rows; an academic-level one on a wide page is hundreds, so it scrolls
   in place. A scroll box is visible where a <details> is hidden. */
.rk-cov-wrap { max-height: 280px; overflow: auto; }
/* `.rk-table` sets `white-space: nowrap` on every cell, which is right for the figures and wrong for a name
   that can be "Johns Hopkins Political Science". */
.rk-cov-name { white-space: normal; max-width: 320px; }
.rk-cov-share { color: var(--muted-2); }
/* A row the filters found no work for: kept, first, and dimmed so the eye reads it as an absence. */
.rk-cov .is-quiet td { color: var(--muted); }
.rk-cov-notes { margin: 8px 0 0; padding: 0 0 0 16px; font-size: 11.5px; line-height: 1.55;
                color: var(--muted); }
