/* ParlaVis — design tokens and layout.
 *
 * The house style is Dihur's (dihur.inz.si, Inštitut za novejšo zgodovino):
 * coral #ED6A59 against warm neutrals, Antonio condensed for display, Libre
 * Franklin for text, and square corners throughout. Those values are taken
 * from the Dihur stylesheet rather than sampled by eye, so the two sites
 * agree exactly rather than approximately.
 *
 * What is *not* taken from Dihur is its spacing. That site is a public
 * homepage built out of large hero cards; this is a working instrument for
 * reading half a million sentences, and a researcher scanning results needs
 * density. The identity is adopted, the airiness is not.
 *
 * The subject is a text corpus, so reading is the primary act: transcript and
 * snippet text is set for a comfortable measure, while the interface chrome
 * stays compact so it recedes.
 *
 * Colour does one structural job beyond the accent: each corpus has its own hue,
 * carried as an edge stripe on result cards. Results from the two parliaments
 * interleave constantly and the eye needs to separate them without reading.
 *
 * Fonts are vendored, not fetched: the app ships no runtime network dependency.
 * Both Dihur faces are Latin-only — 0 Cyrillic glyphs, verified — and this
 * corpus is 59% Cyrillic in yu1Parl, so `--reading` deliberately keeps a
 * Cyrillic-capable stack for corpus text and the @font-face rules carry a
 * `unicode-range` so the browser falls back cleanly per character instead of
 * rendering Serbian in tofu.
 */

/* Latin + Latin Extended + punctuation. Beyond this range the browser skips
   these faces entirely, which is what routes Cyrillic to the fallback. */
@font-face {
  font-family: "Libre Franklin"; font-style: normal; font-weight: 400;
  font-display: swap;
  src: url("/static/fonts/libre-franklin-v19-latin-ext-regular.woff2") format("woff2");
  unicode-range: U+0000-024F, U+0259, U+1E00-1EFF, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Libre Franklin"; font-style: italic; font-weight: 400;
  font-display: swap;
  src: url("/static/fonts/libre-franklin-v19-latin-ext-italic.woff2") format("woff2");
  unicode-range: U+0000-024F, U+0259, U+1E00-1EFF, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Libre Franklin"; font-style: normal; font-weight: 700;
  font-display: swap;
  src: url("/static/fonts/libre-franklin-v19-latin-ext-700.woff2") format("woff2");
  unicode-range: U+0000-024F, U+0259, U+1E00-1EFF, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Antonio"; font-style: normal; font-weight: 400;
  font-display: swap;
  src: url("/static/fonts/antonio-v21-latin-ext-regular.woff2") format("woff2");
  unicode-range: U+0000-024F, U+0259, U+1E00-1EFF, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  /* Dihur's own values. --paper is its white; --surface-2 its light grey. */
  --paper: #ffffff;
  --surface: #ffffff;
  --surface-2: #EEECEB;
  --ink: #4C4547;          /* charcoal, warm-biased — Dihur uses it for body */
  --ink-2: #5f595b;       /* 6.85:1 */
  --ink-3: #767676;       /* Dihur grey, 4.54:1 — the floor for 11px text */
  --rule: #EEECEB;
  --rule-strong: #d9d5d3;

  --accent: #ED6A59;       /* Dihur primary */
  --accent-soft: #FFE0D6;  /* Dihur light-peach */
  --accent-ink: #000000;   /* Dihur --color-on-primary */
  --accent-text: #B4503F;  /* the coral, darkened to pass AA as text */
  /* The selected-language chip: white on coral, which only works on the deep
     coral. White on the primary #ED6A59 is 3.09:1 and the chip is 11.5px type;
     on #B4503F it is 5.05:1 and clears AA. */
  --chip: #B4503F;
  --chip-ink: #FFFFFF;

  /* Charts do not use the accent.
   *
   * Coral earns its loudness by being rare — a live tab, a selected chip, the
   * one button that costs money. A stacked area chart is a field of large
   * filled shapes, and painting those in the brand colour spends the emphasis
   * everywhere at once, so nothing on the page reads as marked any more. Data
   * gets its own blue instead — the same blue that leads the categorical
   * palette, so a bar chart and the first band of a stacked one are not two
   * different blues — and coral returns only where a chart shows a
   * *selection*, which is the same thing it means elsewhere. */
  --chart-ink: #4477AA;    /* the first band colour, so one blue means one thing */
  --chart-ink-soft: #DCE5E7;

  --good: #2f6f4f;
  --bad: #d63e4e;          /* Dihur red */

  /* The two corpora keep distinct hues, pulled toward the house palette: one
     warm and adjacent to the coral, one cool enough to separate at a glance
     without competing with it. */
  --kranjska: #B4503F;
  --kranjska-soft: #FBE7E1;
  --yu1parl: #3F6F78;
  --yu1parl-soft: #E2EDEF;

  --mark: #FFE0D6;
  --mark-ink: #7a2d1e;
  --warn: #B4503F;

  --ent-per: #c0397f;
  --ent-loc: #2a7d6a;
  --ent-per-soft: #fbe4f0;
  --ent-loc-soft: #ddf2ec;

  --sans: "Libre Franklin", Inter, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --display: Antonio, "Arial Narrow", Helvetica, Arial, sans-serif;
  /* Corpus text. Libre Franklin covers the Latin; the faces after it are
     there for Serbian Cyrillic, which Libre Franklin does not contain. */
  --reading: "Libre Franklin", "Segoe UI", Roboto, "Noto Sans", "DejaVu Sans", system-ui, sans-serif;
  --serif: var(--reading);
  --mono: Consolas, Menlo, ui-monospace, SFMono-Regular, "Liberation Mono", monospace;

  /* Type sizes as tokens: the sizes that carry content are defined once, so
     Search, Semantic and Ask cannot drift apart.
     Fixed, not fluid: a large display is handled with the browser's own zoom,
     which scales the whole page coherently — including the things a type
     scale leaves behind, like padding, icons and rules. */
  --fs-ui: 14px;         /* interface chrome */
  --fs-result: 12.5px;   /* snippets and retrieved passages */
  --fs-answer: 13.5px;   /* the generated answer, a step above the evidence */
  --fs-meta: 10.5px;     /* provenance lines, counts, timings */
  --fs-opt: 13px;        /* filter rail options */
  --fs-chip: 12px;

  /* How wide a line of corpus text is allowed to get.
     Search and Semantic show the same kind of thing and had drifted to 94ch
     and 98ch; one token, so they cannot drift again. Wider than the 45-90
     characters typography usually recommends, because these are scanned for a
     match as much as read in sequence — but still capped: on a 1480px pane an
     uncapped line runs past 170 characters, and the eye loses its place coming
     back to the left margin. */
  --measure: 124ch;

  --rail: 292px;
  --header: 56px;
  --radius: 0px;           /* Dihur --button-radius: 0 */
  --shadow: none;
  /* Flat is the house style, and it is right for every surface that sits in
     the page. A popover does not: it covers content, and without elevation its
     text tangles with whatever it is over. This is the one exception. */
  --pop-shadow: 0 2px 4px rgba(0, 0, 0, .10), 0 10px 28px -12px rgba(0, 0, 0, .28);
}

/* Dihur publishes no dark theme, so this is an extrapolation rather than a
   quotation: the coral is lifted just enough to stay legible on a dark ground
   (it fails contrast at #ED6A59 on near-black), and the warm neutral bias is
   preserved so the two themes read as one family. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --paper: #1a1718;
    --surface: #221e20;
    --surface-2: #2b2628;
    --ink: #EEECEB;
    --ink-2: #b3acae;
    --ink-3: #8a8385;
    --rule: #352f31;
    --rule-strong: #4C4547;

    --accent: #F4907F;
    --accent-soft: #432824;
    --accent-ink: #1a1718;
    --accent-text: #F4907F;
    /* Inverted: the dark theme's coral is a *light* colour, so it takes
       dark ink — white on it is 2.30:1. */
    --chip: #F4907F;
    --chip-ink: #1a1718;
    --chart-ink: #77AADD;
    --chart-ink-soft: #2A3B40;

    --good: #7cbf9c;
    --bad: #e86b78;

    --kranjska: #E08A76;
    --kranjska-soft: #3a2721;
    --yu1parl: #7FB3BC;
    --yu1parl-soft: #1e2e31;

    --mark: #5e3327;
    --mark-ink: #FFE0D6;
    --warn: #E08A76;

    --ent-per: #f07ab4;
    --ent-loc: #5fc9ae;
    --ent-per-soft: #3a1c2c;
    --ent-loc-soft: #14302a;
    --shadow: none;
    --pop-shadow: 0 2px 6px rgba(0, 0, 0, .5), 0 12px 32px -12px rgba(0, 0, 0, .8);
  }
}

:root[data-theme="dark"] {
  --paper: #1a1718; --surface: #221e20; --surface-2: #2b2628;
  --ink: #EEECEB; --ink-2: #b3acae; --ink-3: #8a8385;
  --rule: #352f31; --rule-strong: #4C4547;
  --accent: #F4907F; --accent-soft: #432824; --accent-ink: #1a1718;
  --accent-text: #F4907F;
  /* Inverted: the dark theme's coral is a *light* colour, so dark ink. */
  --chip: #F4907F; --chip-ink: #1a1718;
  --chart-ink: #77AADD; --chart-ink-soft: #2A3B40;
  --good: #7cbf9c; --bad: #e86b78;
  --kranjska: #E08A76; --kranjska-soft: #3a2721;
  --yu1parl: #7FB3BC; --yu1parl-soft: #1e2e31;
  --mark: #5e3327; --mark-ink: #FFE0D6; --warn: #E08A76;
  --ent-per: #f07ab4; --ent-loc: #5fc9ae;
  --ent-per-soft: #3a1c2c; --ent-loc-soft: #14302a;
  --shadow: none;
  --pop-shadow: 0 2px 6px rgba(0, 0, 0, .5), 0 12px 32px -12px rgba(0, 0, 0, .8);
}

/* The chip's key text is coral-on-peach in light and would vanish on the dark
   ground, where the same chip is peach-on-brown. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .chip .k,
  :root:not([data-theme="light"]) .chip button { color: var(--accent-text); }
  :root:not([data-theme="light"]) .chip .v { color: var(--ink); }
}
:root[data-theme="dark"] .chip .k,
:root[data-theme="dark"] .chip button { color: var(--accent-text); }
:root[data-theme="dark"] .chip .v { color: var(--ink); }

* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
}

body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: var(--fs-ui);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

button, input, select, textarea { font: inherit; color: inherit; }
a { color: var(--accent-text); text-underline-offset: 2px; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; border-radius: 0; }
@media (prefers-reduced-motion: reduce) { * { animation: none !important; transition: none !important; } }

/* ---------- app shell ---------- */

#app { min-height: 100%; display: flex; flex-direction: column; }

.masthead {
  height: var(--header);
  font-family: var(--sans);
  flex: none;
  display: flex;
  align-items: center;
  gap: 20px;
  padding: 0 16px;
  border-bottom: 1px solid var(--rule);
  background: var(--surface);
  position: sticky;
  top: 0;
  z-index: 40;
}

.brand {
  font-family: var(--display);
  font-size: 27px;
  font-weight: 400;
  line-height: 1;
  letter-spacing: .01em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--ink);
  white-space: nowrap;
}
/* Dihur sets its wordmark entirely in the coral; here only the second half is,
   so the name still reads as one word at a glance. */
.brand span { color: var(--accent-text); }

/* The tabs are the only part of the masthead allowed to run out of room.
 * Adding About and the Speakers icon pushed the Slovenian row to ~700px, and
 * with nothing here able to shrink it was the *right-hand* controls that went
 * past the edge — Settings and the language switch simply vanished. The tabs
 * scroll instead, and the controls below are pinned. */
.tabs {
  display: flex; gap: 2px; align-self: stretch; align-items: stretch;
  min-width: 0; overflow-x: auto;
  scrollbar-width: none; -ms-overflow-style: none;
}
.tabs::-webkit-scrollbar { display: none; }
/* Never shrink, never be pushed out: these are how the reader changes language
 * and reaches the retrieval settings. */
.masthead > .settings, .masthead > .locale, .masthead > .brand { flex: none; }
/* Three stages, not one breakpoint. The Slovenian row needs ~944px at full
 * padding: first the spacing tightens, then the hints' icons go (the label is
 * what navigates; the sentence is still in the collapsed menu), and only then
 * does the row give way to a burger. */
@media (max-width: 1150px) {
  .masthead { gap: 12px; }
  .tabs > button, .tabs .tabwrap > button { padding: 0 9px; }
  .tabs .about > button { padding-right: 9px; }
}
@media (max-width: 1000px) {
  .tabs .tabwrap > .infotip { display: none; }
  .tabs .tabwrap > button { padding-right: 9px; }
}
@media (max-width: 820px) {
  .masthead > .tabs { display: none; }
  /* Qualified, not bare: `.burger { display: none }` comes later in the file
     and at equal specificity it won, so on a phone the tabs vanished and the
     burger never replaced them, which left no navigation at all. */
  .masthead > .burger { display: inline-flex; }
  /* The brand alone is 27px of Antonio; at this width it is the only thing
     between the edge and the controls, so it may shrink before they do. */
  .brand { font-size: 23px; }
}

/* ---------- collapsed navigation ---------- */
.burger {
  display: none;                 /* shown by the breakpoint above */
  align-items: center; justify-content: center;
  width: 30px; height: 30px; padding: 5px;
  background: none; border: 1px solid transparent; border-radius: var(--radius);
  color: var(--ink-2); cursor: pointer;
}
.burger:hover { color: var(--ink); border-color: var(--rule-strong); }
.burger[aria-expanded="true"] { color: var(--accent-text); border-color: var(--rule-strong); }
.burger svg { width: 100%; height: 100%; display: block; }

.menuback { position: fixed; inset: 0; z-index: 79; background: rgb(0 0 0 / 28%); }
/* Drops from under the header across the full width, the way a phone menu is
 * expected to: a right-aligned card at this size would leave the labels in a
 * narrow column with the hints wrapping to three lines each. */
.menupop {
  position: fixed; z-index: 80; top: var(--header); left: 0; right: 0;
  max-height: calc(100vh - var(--header)); max-height: calc(100dvh - var(--header));
  overflow-y: auto;
  background: var(--paper); border-bottom: 1px solid var(--rule-strong);
  box-shadow: var(--pop-shadow);
  display: flex; flex-direction: column; padding: 4px 0;
}
/* The About component wraps its trigger in a span it needs for the dialog;
   `contents` lets the button itself be the flex item, so it lines up with the
   five generated ones instead of sitting in a box of its own. */
.menupop .aboutitem { display: contents; }
.menupop button {
  display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
  width: 100%; text-align: left; cursor: pointer;
  background: none; border: 0; border-left: 3px solid transparent;
  padding: 11px 18px;
}
.menupop button:hover { background: var(--surface); }
.menupop button.on { border-left-color: var(--accent); }
.menupop button .k {
  font-family: var(--display); font-size: 18px; letter-spacing: .03em;
  text-transform: uppercase; color: var(--ink);
}
.menupop button.on .k { color: var(--accent-text); }
.menupop button .d { font-size: 12px; line-height: 1.45; color: var(--ink-3); }
/* Scoped to the tabs themselves. `.tabs button` also matched the info button
   inside a tab — and beat `.infobtn` on specificity — so that icon was being
   given a tab's 13px side padding, a tab's transparent 3px underline and a
   tab's 17px uppercase Antonio. It is an icon, not a tab. */
.tabs > button,
.tabs .tabwrap > button {
  background: none;
  border: 0;
  border-bottom: 3px solid transparent;
  padding: 0 13px;
  color: var(--ink-2);
  cursor: pointer;
  font-family: var(--display);
  font-size: 17px;
  letter-spacing: .03em;
  text-transform: uppercase;
  transition: color .12s, border-color .12s;
}
.tabs > button:hover,
.tabs .tabwrap > button:hover { color: var(--ink); border-bottom-color: var(--rule-strong); }
/* A coral rule under the live tab. Dihur marks state with the primary colour
   rather than a filled pill, and a rule keeps the header height honest. */
.tabs > button.on,
.tabs .tabwrap > button.on { color: var(--ink); border-bottom-color: var(--accent); }

.masthead .spacer { flex: 1; }

.locale { display: flex; border: 1px solid var(--rule-strong); border-radius: var(--radius); overflow: hidden; }
.locale button {
  background: none; border: 0; padding: 4px 9px; cursor: pointer;
  font-size: 11.5px; font-family: var(--mono); color: var(--ink-2);
}
.locale button.on { background: var(--chip); color: var(--chip-ink); }

/* ---------- search layout ---------- */

.search-layout { display: grid; grid-template-columns: var(--rail) minmax(0, 1fr); flex: 1; min-height: 0; }

.rail {
  border-right: 1px solid var(--rule);
  background: var(--surface);
  padding: 14px;
  overflow-y: auto;
  position: sticky;
  top: var(--header);
  height: calc(100vh - var(--header));
  height: calc(100dvh - var(--header));
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.results { padding: 16px 20px 64px; min-width: 0; }

/* Very wide screens.
 *
 * The pane was never narrow — it fills the grid column. What looked narrow was
 * the measure: result text caps at ~95 characters because a line of 300 is
 * unreadable, so on a 4K display the copy hugged the left with a void beside
 * it. Two changes, rather than letting lines run: the column is centred once
 * it outgrows what a measure can fill, and the lexical result list — the one
 * meant for browsing rather than reading in rank order — goes multi-column, so
 * the extra width buys more results on screen instead of longer lines.
 */
@media (min-width: 1700px) {
  /* `width: 100%` is load-bearing, not decoration.
     `.results` is a grid item, and auto inline margins suppress the default
     stretch — which leaves `width: auto` resolving to shrink-to-fit. Search
     survived that because its snippets have a large max-content width, but
     Explore's charts are `width: 100%`, and a percentage contributes nothing
     to max-content: the whole view collapsed to about 440px. A definite width
     is what the auto margins then centre. */
  .results { width: 100%; max-width: 1560px; margin-inline: auto; padding-inline: 32px; }
}
@media (min-width: 2500px) {
  .results { max-width: 2200px; }
}

/* The facets' disclosure, on narrow screens only (see the breakpoint below). */
.railtoggle, .raildone { display: none; }

/* Narrow screens: the rail stacks above the results instead of beside them.
 *
 * It used to turn into a fixed full-screen layer. That hid the query box,
 * which lives in the rail, behind a "Filters" button, and once open the layer
 * covered the button that opened it, so there was no way back to the results.
 * Now the query box is always in the page and only the facets fold, opening
 * in place: the toggle stays where it was tapped, and a button at the foot
 * closes them again for whoever has scrolled down to it. */
@media (max-width: 900px) {
  .search-layout { grid-template-columns: minmax(0, 1fr); }
  .rail {
    position: static; height: auto; overflow: visible;
    border-right: 0; border-bottom: 1px solid var(--rule);
    padding: 12px 16px; gap: 10px;
  }
  .rail > .railbody { display: none; }
  .rail.open > .railbody { display: flex; flex-direction: column; gap: 12px; }
  .railtoggle {
    display: flex; align-items: center; gap: 6px; width: 100%;
    background: none; border: 0; padding: 2px 0; cursor: pointer; text-align: left;
    font-family: var(--display); font-size: 14px; letter-spacing: .06em;
    text-transform: uppercase; color: var(--ink);
  }
  .railtoggle .caret { font-size: 9px; color: var(--ink-3); }
  .railtoggle .count {
    font-family: var(--mono); font-size: 10.5px; letter-spacing: 0;
    background: var(--chip); color: var(--chip-ink); padding: 0 6px;
  }
  .railfoot { display: flex; gap: 8px; }
  .railfoot .btn-reset { flex: 1; }
  .raildone {
    display: block; flex: 1; padding: 6px; cursor: pointer; font-size: 12.5px;
    background: var(--ink); color: var(--paper);
    border: 1px solid var(--ink); border-radius: var(--radius);
  }
  .results { padding: 12px 16px 48px; }
  /* Its reserved height steadies the desktop layout; here an empty row is
     just a gap between the query and the results. Vue's placeholders are
     comments, which `:empty` ignores. */
  .chips:empty { display: none; }
}

/* ---------- query box ---------- */

.querybox { display: flex; flex-direction: column; gap: 7px; }
.querybox .field {
  display: flex; align-items: center; gap: 7px;
  border: 1px solid var(--rule-strong); border-radius: var(--radius);
  background: var(--paper); padding: 0 9px;
}
.querybox .field:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.querybox input {
  flex: 1; border: 0; background: none; padding: 8px 0; min-width: 0;
  font-size: 14px;
}
.querybox input:focus { outline: none; }
.querybox .glyph { color: var(--ink-3); font-size: 13px; }

.modes { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 3px; }
.modes button {
  border: 1px solid var(--rule); background: var(--paper); color: var(--ink-2);
  border-radius: var(--radius); padding: 4px 2px; font-size: 11.5px; cursor: pointer;
}
.modes button:hover { border-color: var(--rule-strong); color: var(--ink); }
.modes button.on { background: var(--ink); border-color: var(--ink); color: var(--paper); font-weight: 600; }

/* ---------- facets ---------- */

.facet { border-top: 1px solid var(--rule); padding-top: 10px; }
.facet > h3 {
  margin: 0 0 7px; font-family: var(--display); font-size: 14px; font-weight: 400;
  letter-spacing: .06em; text-transform: uppercase;
  color: var(--ink); display: flex; align-items: center; gap: 6px;
  cursor: pointer; user-select: none;
}
.facet > h3 .count { margin-left: auto; font-family: var(--mono); font-size: 10.5px; color: var(--ink-3); font-weight: 400; }
.facet > h3 .caret { font-size: 9px; color: var(--ink-3); }

.opt {
  display: flex; align-items: baseline; gap: 7px; padding: 1.5px 0;
  cursor: pointer; font-size: var(--fs-opt); line-height: 1.4; color: var(--ink-2);
}
.opt:hover { color: var(--ink); }
.opt input { margin: 0; accent-color: var(--accent); flex: none; position: relative; top: 1px; }
.opt .label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.opt .n { font-family: var(--mono); font-size: 10.5px; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.opt.checked { color: var(--ink); font-weight: 600; }

.facethint { margin: 5px 0 0; font-size: 11px; line-height: 1.4; color: var(--ink-3); }
/* A facet row with a standing note beside it. */
.optrow { display: flex; align-items: center; gap: 2px; }
.optrow > .opt { flex: 1; min-width: 0; }

.facet .more {
  background: none; border: 0; padding: 3px 0; color: var(--accent-text);
  font-size: 12px; cursor: pointer;
}

.relgrid { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 4px; }
.relword {
  display: inline-flex; align-items: baseline; gap: 5px;
  border: 1px solid var(--rule-strong); background: var(--paper);
  border-radius: 0; padding: 2px 9px; font-size: 12px; cursor: pointer; color: var(--ink-2);
}
.relword:hover { border-color: var(--accent); color: var(--accent-text); }
.relword.on { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); font-weight: 500; }
.relword .n { font-family: var(--mono); font-size: 9.5px; opacity: .65; }

/* One disclosure per language.

   The corpus is four languages and a suggestion is only usable in one of them,
   so the language is part of the suggestion. All shut to begin with: four
   languages of neighbours is a long list in a narrow rail, and the reader picks
   a language before they pick a word. A group holding a word already added to
   the query opens itself, so nothing selected is ever hidden. */
.relgroup + .relgroup { margin-top: 5px; }
.rellang {
  display: flex; align-items: baseline; gap: 6px; width: 100%;
  margin: 4px 0 0; padding: 3px 2px; border: 0; background: none;
  font-size: 11px; font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; color: var(--ink-3); cursor: pointer; text-align: left;
}
.rellang:hover { color: var(--ink-2); }
.rellang.open { color: var(--ink-2); }
.rellang .caret { font-size: 8px; width: 8px; color: var(--ink-3); }
.rellang .n {
  font-family: var(--mono); font-size: 9.5px; font-weight: 500;
  letter-spacing: 0; text-transform: none;
  background: var(--surface-2); border-radius: 0; padding: 0 5px;
}
/* The form the neighbours were found under, which is not always what was
   typed: a translated term, or the other script. */
.rellang .src {
  margin-left: auto; font-family: var(--mono); font-size: 9.5px; font-weight: 400;
  letter-spacing: 0; text-transform: none; opacity: .75;
}

.yearrow { display: flex; align-items: center; gap: 6px; }
.yearrow input {
  width: 100%; border: 1px solid var(--rule-strong); border-radius: var(--radius);
  padding: 4px 6px; background: var(--paper); font-family: var(--mono); font-size: 12px;
}
.yearrow span { color: var(--ink-3); font-size: 12px; }

.typeahead { position: relative; }
.typeahead > input {
  width: 100%; border: 1px solid var(--rule-strong); border-radius: var(--radius);
  padding: 5px 7px; background: var(--paper); font-size: 12.5px;
}
.typeahead .drop {
  position: absolute; left: 0; right: 0; top: 100%; z-index: 20;
  background: var(--surface); border: 1px solid var(--rule-strong); border-radius: var(--radius);
  box-shadow: var(--pop-shadow); max-height: 260px; overflow-y: auto; margin-top: 3px;
}
.typeahead .drop button {
  display: block; width: 100%; text-align: left; background: none; border: 0;
  padding: 6px 8px; cursor: pointer; font-size: 12.5px; color: var(--ink);
  border-bottom: 1px solid var(--rule);
}
.typeahead .drop button:last-child { border-bottom: 0; }
.typeahead .drop button:hover { background: var(--accent-soft); }
.typeahead .drop .meta { display: block; font-size: 10.5px; color: var(--ink-3); font-family: var(--mono); }

.topictree { max-height: 320px; overflow-y: auto; margin: 0 -4px; padding: 0 4px; }
.topictree .major { display: flex; align-items: center; gap: 5px; }
.topictree .expand {
  background: none; border: 0; cursor: pointer; color: var(--ink-3);
  font-size: 10px; padding: 0 2px; width: 14px; flex: none;
}
.topictree .picked {
  font-family: var(--mono); font-size: 10px; line-height: 1.6;
  background: var(--accent); color: var(--accent-ink);
  border-radius: 0; padding: 0 5px; flex: none;
}

.topictree .minors { margin-left: 18px; border-left: 1px solid var(--rule); padding-left: 8px; }

/* Only a wrapper for the narrow-screen fold; on a wide screen its children are
   the rail's own flex items, so the gaps and the pinned foot are unchanged. */
.railbody { display: contents; }

.railfoot { margin-top: auto; padding-top: 12px; border-top: 1px solid var(--rule); }
.btn-reset {
  width: 100%; background: var(--paper); border: 1px solid var(--rule-strong);
  border-radius: var(--radius); padding: 6px; cursor: pointer; color: var(--ink-2); font-size: 12.5px;
}
.btn-reset:hover { border-color: var(--warn); color: var(--warn); }

/* ---------- chips & result header ---------- */

.chips { display: flex; flex-wrap: wrap; gap: 5px; align-items: center; margin-bottom: 10px; min-height: 24px; }
.chip {
  display: inline-flex; align-items: center; gap: 6px;
  border: 1px solid var(--accent); border-radius: 0;
  padding: 2px 5px 2px 9px; background: var(--accent-soft); font-size: var(--fs-chip);
  color: var(--accent-ink);
}
.chip .k { color: #7a4034; font-size: 10px; font-family: var(--display);
           text-transform: uppercase; letter-spacing: .07em; }
.chip .v { color: var(--accent-ink); font-weight: 500; }
.chip button {
  border: 0; background: none; cursor: pointer; color: #7a4034;
  padding: 0 3px; font-size: 14px; line-height: 1; border-radius: 0;
}
.chip button:hover { color: var(--bad); }
.chips .clear { border: 0; background: none; color: var(--accent-text); cursor: pointer; font-size: 12px; }

.resulthead {
  display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;
  padding-bottom: 8px; border-bottom: 1px solid var(--rule); margin-bottom: 4px;
}
.resulthead .total { font-size: 14px; }
.resulthead .total b { font-variant-numeric: tabular-nums; }
.resulthead .took { font-family: var(--mono); font-size: 11px; color: var(--ink-3); }
.resulthead .spacer { flex: 1; }
.resulthead select {
  border: 1px solid var(--rule-strong); border-radius: var(--radius);
  background: var(--surface); padding: 3px 6px; font-size: 12.5px;
}


/* Answering language, in the rail under the query box.
 *
 * It sits where the search modes sit on the lexical tab, because it is the
 * same kind of control: something that shapes the request being typed above
 * it, not something that annotates the result. Ask has no submit button —
 * Enter in that box is the request, as in Search and Semantic — so the
 * controls belonging to the question all live with the question. */
.querybox .answerlang {
  display: flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--ink-2);
}
.querybox .answerlang select {
  flex: 1; min-width: 0; font: inherit; color: var(--ink); background: var(--paper);
  border: 1px solid var(--rule); border-radius: var(--radius); padding: 4px 6px;
}
.querybox .answerlang select:hover { border-color: var(--rule-strong); }
/* The language the answer actually came out in, reported only when the
 * setting above is on automatic. Mono because it is a machine's reading of
 * the question, not a label the reader chose. */
.ask .detected { font-family: var(--mono); font-size: 11px; color: var(--ink-3); }

/* ---------- search settings ---------- */

/* The instrument, not the evidence: which retriever runs and whether its order
 * is corrected. Sits with the language chooser because it holds across tabs,
 * unlike a filter, which describes one result set. */
.settings { position: relative; display: inline-flex; }
.settingsbtn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; padding: 5px; margin-right: 6px;
  border: 1px solid transparent; background: none; color: var(--ink-2);
  border-radius: var(--radius); cursor: pointer;
}
.settingsbtn:hover { color: var(--ink); border-color: var(--rule-strong); }
.settingsbtn svg { width: 100%; height: 100%; display: block; }
.settingsbtn[aria-expanded="true"] { color: var(--accent-text); border-color: var(--rule-strong); }

/* A click anywhere else closes the panel. Transparent rather than dimmed: this
 * is a two-control popover, not a modal that should darken the page behind it. */
.settingsback { position: fixed; inset: 0; z-index: 59; }
.settingspop {
  position: fixed; z-index: 60; width: 300px; max-width: calc(100vw - 16px);
  background: var(--paper); border: 1px solid var(--rule-strong);
  border-radius: var(--radius); box-shadow: var(--pop-shadow);
  padding: 14px 16px; display: flex; flex-direction: column; gap: 12px;
}
.settingspop .setting { display: flex; align-items: center; gap: 10px; font-size: 12.5px; }
.settingspop .setting .k { color: var(--ink-2); flex: 0 0 auto; }
.settingspop .setting select {
  flex: 1; min-width: 0; font: inherit; color: var(--ink); background: var(--surface);
  border: 1px solid var(--rule-strong); border-radius: var(--radius); padding: 4px 6px;
}
.settingspop .note {
  margin: 0; font-size: 11.5px; line-height: 1.45; color: var(--ink-3);
  border-top: 1px solid var(--rule); padding-top: 10px;
}

/* ---------- about ---------- */
/* A centred dialog rather than a popover anchored to its button: it carries two
 * paragraphs and four institutional marks, which is more than a bubble should
 * hold, and it is read once rather than consulted while working. */
/* About is a tab, so it takes `tabwrap` and inherits the tab rules exactly.
 * The one thing it must not inherit is the 3px right padding, which exists to
 * pull an info icon up against its label — About has no icon, so it keeps a
 * tab's own padding and sits evenly beside Speakers. */
.tabs .about > button { padding-right: 13px; }

.aboutback { position: fixed; inset: 0; z-index: 69; background: rgb(0 0 0 / 28%); }
.aboutpop {
  position: fixed; z-index: 70;
  left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: 600px; max-width: calc(100vw - 32px); max-height: calc(100vh - 48px);
  overflow-y: auto;
  background: var(--paper); border: 1px solid var(--rule-strong);
  border-radius: var(--radius); box-shadow: var(--pop-shadow);
  padding: 26px 30px 22px;
}
.aboutclose {
  position: absolute; top: 10px; right: 10px;
  width: 26px; height: 26px; padding: 0; display: grid; place-items: center;
  background: none; border: 0; border-radius: var(--radius);
  color: var(--ink-3); cursor: pointer;
}
.aboutclose:hover { color: var(--accent-text); background: var(--accent-soft); }
.aboutclose svg { width: 15px; height: 15px; }

/* Takes `.brand` for the typeface, casing and the coral second half; only the
 * size differs, because the dialog is not a 48px header bar. */
.aboutpop .abouttitle { font-size: 34px; margin: 0; }
.aboutpop .aboutsub {
  margin: 4px 0 16px; font-size: 13px; color: var(--ink-3);
  /* Reads as a standing subtitle, not a sentence of the body text. */
  font-family: var(--display); letter-spacing: .02em;
}
.aboutpop .aboutbody {
  margin: 0 0 12px; font-size: 13px; line-height: 1.62; color: var(--ink-2);
}
.aboutpop .aboutbody a { color: var(--accent-text); }

/* One line, which is what the four marks are for — they read as a funder strip,
 * not as a gallery. They fit because the compact LGM mark is used rather than
 * the 6.7:1 wordmark; the lab's full name is in the body text above. Summed at
 * 36px they come to 449px against 540px of inner width, so the row has slack
 * and still wraps rather than overflowing if a mark is ever replaced. */
.aboutlogos {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
  gap: 16px 20px;
  margin-top: 20px; padding-top: 18px; border-top: 1px solid var(--rule);
}
.aboutlogos a { display: block; line-height: 0; }
/* An explicit height, not max-height. Two of these files carry only a viewBox,
 * and an <img> whose source has no intrinsic width cannot resolve `width: auto`
 * against a *maximum* — those two collapsed and the dialog showed two marks of
 * four. The files now carry width and height as well; this is the second half
 * of that fix, and the half that survives someone dropping in a bare export. */
.aboutlogos img { height: 36px; width: auto; max-width: 100%; display: block; }
/* The marks are supplied as dark artwork. On the dark theme they would vanish
 * into the panel, so they sit on their own light plate rather than being
 * inverted, which would misrender any coloured mark. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .aboutlogos a {
    background: #fff; border-radius: var(--radius); padding: 5px 8px;
  }
}
:root[data-theme="dark"] .aboutlogos a {
  background: #fff; border-radius: var(--radius); padding: 5px 8px;
}

/* ---------- charts ---------- */
.plot { width: 100%; }
/* Plotly paints its own mode bar; keep it out of the way until hovered. */
.plot .modebar { opacity: 0; transition: opacity .12s; }
.plot:hover .modebar { opacity: 1; }
.plot .modebar-btn path { fill: var(--ink-3); }
.plot .modebar-btn:hover path { fill: var(--accent); }
.plot .cursor-pointer, .plot .points path, .plot .legend { cursor: pointer; }
/* Plotly leaves its own dashed rectangle behind after a select drag. That is
   four lines across the plot, and this app already marks the selection its own
   way — one coral band, drawn from the actual filter rather than from the
   gesture, so it survives a redraw and matches the Period chip. Two marks for
   one thing, one of which is a box, is what made the drag look broken. */
.plot .select-outline, .plot .zoombox-corners { display: none !important; }

/* A chart card, which is not a result card.
 *
 * These were `.card` too, and silently inherited the lexical result card's
 * `display: grid; grid-template-columns: 44px minmax(0, 1fr)` — so every
 * chart heading and caption was laid out in a 44px column beside the plot
 * rather than above it. That is why "drag to select a period" wrapped to four
 * lines, why "Vertical axis:" wrapped to two, and why the info icon appeared
 * to sit inside the chart. Its own name, so the two cannot collide again. */
.chartcard {
  display: block;
  background: var(--surface); border: 1px solid var(--rule);
  border-radius: var(--radius); padding: 12px 14px 8px; margin: 0 0 14px;
}
.chartcard > h3 {
  display: flex; align-items: center; gap: 4px; margin: 0 0 8px;
  font: 400 15px/1.2 var(--display); letter-spacing: .04em; text-transform: uppercase;
  color: var(--ink);
}
.chartcard > h3 .spacer { flex: 1; }
.chartcard .empty { color: var(--ink-3); font-size: 13px; margin: 8px 0 14px; }
.speakercharts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
                 gap: 14px; margin-top: 18px; }
/* The profile heading doubles as the control that searches this speaker, so
   it has to read as a heading and behave as a link. */
.speakername { margin: 0 0 4px; }
.speakername button {
  font-family: var(--serif); font-size: inherit; font-weight: inherit;
  color: var(--ink); background: none; border: 0; padding: 0; cursor: pointer;
  text-align: left; text-decoration: underline;
  text-decoration-color: var(--rule-strong); text-underline-offset: 4px;
}
.speakername button:hover {
  color: var(--accent-text); text-decoration-color: var(--accent);
}

.speakercharts > .chartcard { margin: 0; }

.listcount {
  color: var(--ink-3); font-family: var(--mono); font-size: 11px;
  white-space: nowrap; font-variant-numeric: tabular-nums;
}
/* Zero height: it exists to be observed, not seen. */
.sentinel { height: 1px; }
.loadmore { width: auto; margin: 10px auto 0; display: block; padding: 6px 18px; }
.charthint {
  margin: 4px 0 0; font-size: 10.5px; color: var(--ink-3);
  text-transform: none; letter-spacing: 0; font-family: var(--mono);
  display: flex; align-items: baseline; gap: 6px;
}
.charthint b { color: var(--ink-2); font-weight: 500; }
.charthint .linkish {
  background: none; border: 0; padding: 0; cursor: pointer;
  font: inherit; color: var(--accent-text); text-decoration: underline;
}

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

.explore .cardrow { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
.explore .cardrow > .chartcard { margin-bottom: 14px; }
@media (max-width: 900px) { .explore .cardrow { grid-template-columns: minmax(0, 1fr); } }

/* A chart's unit switch, built like the locale switch in the masthead: one
   bordered group with the live half filled, rather than two loose buttons.
   As two `.mini` buttons it read as stray UI dropped into the heading —
   and, sitting inside an Antonio heading, it also inherited the uppercase and
   letter-spacing that the `font` shorthand does not reset. */
.seg {
  display: inline-flex; border: 1px solid var(--rule-strong);
  border-radius: var(--radius); overflow: hidden; flex: none;
}
.seg button {
  background: var(--surface); border: 0; padding: 3px 9px; cursor: pointer;
  font: 400 10.5px/1.5 var(--mono); color: var(--ink-3);
  text-transform: none; letter-spacing: 0;
}
.seg button + button { border-left: 1px solid var(--rule-strong); }
.seg button:hover { color: var(--ink); }
.seg button.on { background: var(--accent-soft); color: var(--accent-text); }

.histogram .hint button.linkish {
  background: none; border: 0; padding: 0 0 0 6px; cursor: pointer;
  font: inherit; color: var(--accent-text); text-decoration: underline;
}

/* ---------- histogram ---------- */

.histogram { margin: 12px 0 14px; user-select: none; }
.histogram .hint { font-family: var(--mono); font-size: 10px; color: var(--ink-3); display: flex; gap: 10px; }
.histogram .hint b { color: var(--ink-2); font-weight: 500; }

/* ---------- result cards ---------- */

/* One column at every width.
 *
 * A wide screen was briefly spent on two and then three columns of results.
 * That is the wrong trade for a ranked list: the reader is working down it in
 * order, and columns break that reading — the eye has to jump back up to the
 * top of the next column, and rank 1 and rank 11 end up side by side. Semantic
 * and Ask were always single-column for the same reason; Search now matches
 * them. The extra width goes to the line length instead, which the measures
 * cap at a readable 94 characters. */
.cards { display: flex; flex-direction: column; gap: 5px; }


.card {
  position: relative;
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr);
  gap: 10px;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-left: 3px solid var(--corpus, var(--rule-strong));
  border-radius: var(--radius);
  padding: 7px 11px 7px 10px;
}
.card { transition: background-color .1s, border-color .1s; }
.card:hover {
  border-color: var(--rule-strong);
  border-left-color: var(--corpus, var(--rule-strong));
  border-left-width: 5px;
  padding-left: 8px;
  background: var(--surface-2);
}
.card[data-corpus="Kranjska"] { --corpus: var(--kranjska); }
.card[data-corpus="yu1Parl"] { --corpus: var(--yu1parl); }

.card .thumb {
  width: 44px; height: 59px; object-fit: cover; object-position: top;
  border: 1px solid var(--rule); border-radius: 0; background: var(--surface-2);
  cursor: pointer; display: block;
}
.card .body { min-width: 0; }

/* The provenance line above every result, in all three views. One rule, so
   they cannot drift apart the way the hand-rolled versions did. */
.hitmeta {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px;
  font-family: var(--mono); font-size: var(--fs-meta); line-height: 1.4;
  color: var(--ink-3); margin-bottom: 2px;
}
.hitmeta .date { color: var(--ink-2); }
/* The same corpus must look the same in every view. It was `var(--corpus)`,
   which only the lexical card ever sets — so Kranjska was rust in Search and
   plain ink in Semantic. The per-corpus hues still separate the two
   parliaments where it matters, on the card's edge stripe. */
.hitmeta .corpus { color: var(--accent-text); font-weight: 500; }
/* Set in the sans so a name is readable, but only a little larger than the
   line around it: at 12px/600 it read as a heading and pulled the eye away
   from the passage, which is the thing being scanned. */
.hitmeta .speaker {
  font-family: var(--sans); font-size: 11px; font-weight: 500; color: var(--ink-2);
  cursor: pointer; border: 0; background: none; padding: 0; line-height: 1.4;
}
.hitmeta .speaker:hover { color: var(--accent-text); }
/* Already filtered to this speaker: the control is still live — clicking
   removes the filter — so it is marked rather than disabled. */
.hitmeta .speaker.on { color: var(--accent-text); font-weight: 600; }
.hitmeta .lang { color: var(--ink-3); }
.hitmeta .spacer { flex: 1; }
.hitmeta .page.approx { cursor: help; }

.card .snippet {
  font-family: var(--reading); font-size: var(--fs-result); line-height: 1.4;
  color: var(--ink); margin: 0 0 4px; max-width: var(--measure);
}
.card .snippet mark { background: var(--mark); color: var(--mark-ink); padding: 0 1px; border-radius: 0; }
/* The server already caps the preview; this keeps cards a uniform height on a
   wide screen, where 280 characters can still run to four or five lines. */
.card .snippet.clamp {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3;
  overflow: hidden;
}

.card .foot { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; }
.topicchip {
  font-size: 10.5px; line-height: 1.55; border-radius: 0; padding: 0 5px;
  background: var(--surface-2); color: var(--ink-2); border: 1px solid var(--rule);
  cursor: pointer;
}
.topicchip:hover { border-color: var(--accent); color: var(--accent-text); }
/* Marks the topic that put this result in the set, when a topic filter is the
   only thing narrowing it and there is no text match to highlight. */
.topicchip.matched {
  background: var(--accent-soft); color: var(--accent-text);
  border-color: var(--accent); font-weight: 600;
}
.card .foot .grow { flex: 1; }
.card .snippet .ellipsis { color: var(--ink-3); }

.card .page {
  font-family: var(--mono); font-size: 11px; color: var(--ink-3); white-space: nowrap;
}
.card .page.approx { color: var(--warn); }
.card .actions { display: flex; gap: 4px; }
.card .actions button {
  border: 1px solid var(--rule-strong); background: var(--paper); border-radius: 0;
  padding: 2px 8px; font-size: 11.5px; cursor: pointer; color: var(--ink-2);
}
.card .actions button:hover { border-color: var(--accent); color: var(--accent-text); }

.pager { display: flex; justify-content: center; align-items: center; gap: 10px; padding: 20px 0; }
.pager button {
  border: 1px solid var(--rule-strong); background: var(--surface); border-radius: var(--radius);
  padding: 5px 12px; cursor: pointer; font-size: 13px;
}
.pager button:disabled { opacity: .4; cursor: default; }
.pager .pos { font-family: var(--mono); font-size: 12px; color: var(--ink-3); }

.empty, .loading {
  text-align: center; padding: 56px 20px; color: var(--ink-3);
}
.empty h3 { font-family: var(--serif); font-size: 19px; color: var(--ink-2); margin: 0 0 6px; font-weight: 500; }

/* ---------- reader ---------- */

/* The rows must be bounded explicitly. With the default `auto` rows the content
   row grew to the height of the whole transcript, so the panes had no definite
   height: their internal overflow never engaged, the page itself scrolled, and
   the viewer measured a viewport far taller than the screen when fitting a page. */
.reader {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  grid-template-rows: auto minmax(0, 1fr);
  height: calc(100vh - var(--header));
  /* A phone's toolbars come and go and `vh` counts the space under them, so
     the panes ran past the bottom of the screen. `dvh` is the visible part;
     a browser without it drops this line and keeps the one above. */
  height: calc(100dvh - var(--header));
  min-height: 0;
}
.reader.text-only { grid-template-columns: minmax(0, 1fr); }


.reader-head {
  grid-column: 1 / -1;
  display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;
  padding: 10px 18px; border-bottom: 1px solid var(--rule); background: var(--surface);
}
.reader-head h2 { font-family: var(--serif); font-size: 16px; margin: 0; font-weight: 600; }
.reader-head .meta { font-family: var(--mono); font-size: 11.5px; color: var(--ink-3); }
.reader-head .spacer { flex: 1; }
.reader-head button, .reader-head select {
  border: 1px solid var(--rule-strong); background: var(--paper); border-radius: var(--radius);
  padding: 3px 9px; font-size: 12.5px; cursor: pointer;
}
.reader-head button.on { background: var(--accent-soft); border-color: var(--accent); color: var(--accent-text); }

.transcript { overflow-y: auto; min-height: 0; padding: 18px 22px 80px; border-right: 1px solid var(--rule); }
.reader.text-only .transcript { border-right: 0; }

.turn { display: grid; grid-template-columns: 148px minmax(0, 1fr); gap: 16px; margin-bottom: 16px; scroll-margin-top: 20px; }
.turn .who { text-align: right; }
.turn .who .name {
  font-size: 12.5px; font-weight: 600; color: var(--ink); background: none; border: 0;
  padding: 0; cursor: pointer; text-align: right; line-height: 1.35;
}
.turn .who .name:hover { color: var(--accent-text); text-decoration: underline; }
.turn .who .sub { font-family: var(--mono); font-size: 10.5px; color: var(--ink-3); display: block; margin-top: 2px; }
.turn.prose .who .name { color: var(--ink-3); font-weight: 400; font-style: italic; }
.turn .said { font-family: var(--serif); font-size: 15.5px; line-height: 1.62; max-width: 70ch; }
.turn .said .s { cursor: pointer; }
.turn .said .s:hover { background: var(--surface-2); }
/* A segment-level match tints the whole segment; the sentence that was linked
   to stays strongest, so both facts are visible at once. */
/* Machine-translated text is set apart, so it is never mistaken for the record. */
.turn .said .s.mt { font-style: italic; color: var(--ink-2); }
.mtnote {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .04em;
  color: var(--warn); border: 1px solid var(--warn); border-radius: 0; padding: 1px 6px;
}
.card .snippet .mt { font-style: italic; color: var(--ink-2); }
.card .snippet .mt::after {
  content: attr(data-lang); font-family: var(--mono); font-size: 9px;
  vertical-align: super; color: var(--warn); margin-left: 2px; font-style: normal;
}

.turn .said .s.inseg { background: var(--accent-soft); }
.turn .said .s.active { background: var(--mark); color: var(--mark-ink); }
/* text-decoration rather than border-bottom: it tracks the text baseline, can be
   offset clear of descenders, and skip-ink is switched off so the run stays
   continuous instead of breaking under every g and j. */
.turn .said .ent {
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
  text-decoration-skip-ink: none;
  text-decoration-color: var(--rule-strong);
  border-radius: 0;
}
.turn .said .ent.PER { text-decoration-color: var(--ent-per); }
.turn .said .ent.LOC { text-decoration-color: var(--ent-loc); }
.turn .said .ent.ORG { text-decoration-color: var(--brass); text-decoration-style: dashed; }
/* Hovering tints the span, so the exact extent of an entity is legible even
   where two abut. */
.turn .said .ent.PER:hover { background: var(--ent-per-soft); }
.turn .said .ent.LOC:hover { background: var(--ent-loc-soft); }

.entlegend { display: flex; gap: 12px; align-items: center; font-size: 11.5px; color: var(--ink-3); }
.entlegend span { display: inline-flex; align-items: center; gap: 5px; }
.entlegend i { width: 16px; height: 2px; background: currentColor; border-radius: 0; display: inline-block; }
.entlegend .per { color: var(--ent-per); }
.entlegend .loc { color: var(--ent-loc); }
.turn .topics { display: flex; gap: 4px; flex-wrap: wrap; margin-top: 5px; }

/* ---------- pdf pane ---------- */

.pdfpane { display: flex; flex-direction: column; min-width: 0; min-height: 0; background: var(--surface-2); }
.pdfbar {
  display: flex; align-items: center; gap: 8px; padding: 6px 10px;
  border-bottom: 1px solid var(--rule); background: var(--surface); flex: none;
}
.pdfbar button {
  border: 1px solid var(--rule-strong); background: var(--paper); border-radius: 0;
  padding: 2px 8px; cursor: pointer; font-size: 12px;
}
.pdfbar button:disabled { opacity: .4; cursor: default; }
.pdfbar .pos { font-family: var(--mono); font-size: 12px; color: var(--ink-2); }
.pdfbar .spacer { flex: 1; }
.pdfbar .marked { display: flex; align-items: center; gap: 4px; font-size: 11.5px; color: var(--ink-3); }
.pdfbar .pagechip {
  border: 1px solid var(--rule-strong); background: var(--paper); border-radius: 0;
  padding: 1px 6px; font-family: var(--mono); font-size: 11px; cursor: pointer;
}
.pdfbar .pagechip.on { background: var(--mark); border-color: var(--mark); color: var(--mark-ink); font-weight: 600; }
.pdfscroll { flex: 1; min-height: 0; overflow: auto; padding: 14px; display: flex; justify-content: center; align-items: flex-start; }
.pdfstage { position: relative; box-shadow: var(--shadow); background: #fff; }
.pdfstage canvas { display: block; }
.pdfstage .hl {
  position: absolute; background: var(--mark); mix-blend-mode: multiply;
  opacity: .55; border-radius: 0; pointer-events: none;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .pdfstage .hl { mix-blend-mode: normal; opacity: .4; }
}
.pdfstage .hl.focus { opacity: .9; outline: 1px solid var(--warn); }

/* Narrow screens: the scan goes under the text rather than beside it.
 *
 * Side by side at phone width gave each pane about 190px; the transcript ran
 * one word per line beside the 148px speaker margin, and the scan was too
 * small to read. Stacked, the text keeps the full width and the page scan
 * takes the lower part of the screen. */
@media (max-width: 900px) {
  .reader {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto minmax(0, 3fr) minmax(0, 2fr);
  }
  .reader.text-only { grid-template-rows: auto minmax(0, 1fr); }
  .reader-head { padding: 8px 16px; gap: 6px 10px; }
  .reader-head h2 { font-size: 14.5px; flex-basis: 100%; }
  .reader-head .spacer { display: none; }
  /* The title already names the assembly and the date. */
  .reader-head .meta { display: none; }
  .transcript { padding: 12px 16px 40px; border-right: 0; border-bottom: 1px solid var(--rule); }
  /* The speaker moves from the margin to a line above what they said. */
  .turn { grid-template-columns: minmax(0, 1fr); gap: 2px; margin-bottom: 14px; }
  .turn .who { text-align: left; display: flex; align-items: baseline; gap: 8px; }
  .turn .who .name { text-align: left; }
  .turn .who .sub { margin-top: 0; }
  .turn .said { font-size: 15px; line-height: 1.55; }
  .pdfbar { flex-wrap: wrap; gap: 6px; }
  .pdfscroll { padding: 8px; }
}

/* ---------- speakers ---------- */

.speakers { padding: 18px 22px 64px; }
.speakers .toolbar { display: flex; gap: 10px; align-items: center; margin-bottom: 14px; flex-wrap: wrap; }
.speakers .toolbar input {
  border: 1px solid var(--rule-strong); border-radius: var(--radius); padding: 6px 9px;
  background: var(--surface); min-width: 220px;
}
.speakergrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 8px; }
.speakercard {
  border: 1px solid var(--rule); border-left: 3px solid var(--corpus, var(--rule-strong));
  border-radius: var(--radius); background: var(--surface); padding: 9px 11px; cursor: pointer;
  text-align: left;
}
.speakercard[data-corpus="Kranjska"] { --corpus: var(--kranjska); }
.speakercard[data-corpus="yu1Parl"] { --corpus: var(--yu1parl); }
.speakercard:hover { border-color: var(--rule-strong); border-left-color: var(--corpus); }
.speakercard .nm { font-weight: 600; font-size: 13.5px; }
.speakercard .alt { font-family: var(--mono); font-size: 10.5px; color: var(--ink-3); }
.speakercard .facts { font-size: 11.5px; color: var(--ink-2); margin-top: 4px; display: flex; gap: 8px; flex-wrap: wrap; }
.speakercard .facts .n { font-family: var(--mono); font-variant-numeric: tabular-nums; }

.profile { display: grid; grid-template-columns: minmax(0, 320px) minmax(0, 1fr); gap: 24px; }
@media (max-width: 780px) { .profile { grid-template-columns: minmax(0, 1fr); } }
.profile dl { margin: 0; display: grid; grid-template-columns: auto minmax(0, 1fr);
              gap: 3px 12px; font-size: 13px; }
.profile dt { color: var(--ink-3); font-size: 11.5px; text-transform: uppercase; letter-spacing: .05em; padding-top: 2px; }
.profile dd { margin: 0; }
.termtable { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.termtable th, .termtable td { text-align: left; padding: 5px 8px; border-bottom: 1px solid var(--rule); }
.termtable th { font-family: var(--mono); font-size: 10.5px; text-transform: uppercase; letter-spacing: .07em; color: var(--ink-3); font-weight: 500; }

.notice {
  border-left: 2px solid var(--warn); background: var(--surface-2);
  padding: 8px 12px; font-size: 12.5px; color: var(--ink-2); border-radius: 0;
}

.skeleton {
  background: linear-gradient(90deg, var(--surface-2) 25%, var(--rule) 50%, var(--surface-2) 75%);
  background-size: 200% 100%; animation: sk 1.4s infinite; border-radius: 0;
}
@keyframes sk { to { background-position: -200% 0; } }

/* ---------------------------------------------------------------------------
   Semantic search and Ask.

   Passages are set wider and quieter than result cards: they are read, not
   scanned. Ask keeps its answer visually subordinate to the sources below it —
   the prose is a reading aid over the evidence, never the finding itself.
   --------------------------------------------------------------------------- */

.results .hint {
  margin: 0 0 14px; max-width: 68ch; color: var(--ink-3);
  font-size: 12.5px; line-height: 1.5;
}
.results .empty, .results .loading { color: var(--ink-3); font-size: 13px; }
.results .error { color: var(--bad); font-size: 13px; }

/* One line, not a panel. The terms themselves live in the tip beside it —
   at twenty-odd words the inline list stood taller than the first result. */
/* Normal text flow, not flex. As a flex row the icon and the switch were
   separate items that wrapped onto their own line when the column narrowed,
   so a sentence reading "…and translations (i). Turn off translations." broke
   into pieces that looked unrelated. This is one sentence and should wrap like
   one. */
.expansion {
  margin: 0 0 12px; font-size: 12px; color: var(--ink-3); line-height: 1.7;
}
.expansion b { color: var(--ink-2); font-weight: 600; }
/* The icon sits on the text baseline rather than floating above it. */
.expansion .infotip { vertical-align: -2px; }
/* The switch, inside the sentence that reports what it changed — the two or
   three words that name the action, and nothing else. It carried `btn-reset`
   at first, which is the style for the full-width "reset filters" button:
   `width: 100%` made it a block of its own and it read as a stray centred
   control rather than as part of the line. Everything here is stated
   explicitly for that reason. */
.expansion .trlink { display: inline; width: auto; border: 0; background: none;
  cursor: pointer; padding: 0; margin: 0 0 0 3px; font: inherit;
  color: var(--accent-text); text-decoration: underline; }
.expansion .trlink:hover { color: var(--accent-ink); }
.expansion .trlink:focus-visible { outline: 2px solid var(--accent);
  outline-offset: 2px; border-radius: 2px; }

.infopop .expnote { display: block; margin-bottom: 8px; }
.infopop .expgroup {
  display: block; margin-top: 7px; padding-top: 7px;
  border-top: 1px solid var(--rule);
}
.infopop .expgroup:first-of-type { border-top: 0; padding-top: 0; }
.infopop .expgroup em {
  display: block; font-style: normal; font-family: var(--display);
  font-size: 11px; letter-spacing: .06em; text-transform: uppercase;
  color: var(--ink-3); margin-bottom: 4px;
}
.infopop .expword {
  display: inline-block; margin: 0 3px 3px 0;
  border: 1px solid var(--rule-strong); border-radius: 0;
  padding: 0 6px; background: var(--paper); color: var(--ink-2);
  font-size: 11.5px; line-height: 1.7;
}

.passage {
  border: 1px solid var(--rule); border-radius: var(--radius);
  background: var(--paper); padding: 8px 11px; margin-bottom: 5px; cursor: pointer;
}
.passage:hover { border-color: var(--accent); }
.passage .rank {
  font-family: var(--mono); font-size: 11px; font-weight: 600;
  color: var(--accent-ink); background: var(--accent);
  border-radius: 0; padding: 0 6px; min-width: 18px; text-align: center;
}
.passage .unused { font-family: var(--mono); font-size: 10.5px; }
/* The number the list is sorted by, so it reads as a measurement rather than
   a label: monospaced, tabular, and aligned down the right edge. */
.passage .score {
  font-family: var(--mono); font-size: 10.5px; color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}
.results > .meta .spacer { flex: 1; }
.results > .meta { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.passage .text {
  margin: 0; font-size: var(--fs-result); line-height: 1.45; color: var(--ink);
  max-width: var(--measure);
}
.passage.uncited { opacity: .62; }
.passage.uncited .rank { background: var(--rule-strong); color: var(--ink-2); }

.answer {
  border-left: 3px solid var(--accent); background: var(--surface-2);
  border-radius: 0 var(--radius) var(--radius) 0;
  padding: 10px 13px; margin-bottom: 15px;
}
.answer .body { margin: 0; font-size: var(--fs-answer); line-height: 1.5; max-width: 88ch; }
.answer .cite {
  border: 0; background: var(--accent); color: var(--accent-ink);
  border-radius: 0; font-family: var(--mono); font-size: 10px;
  padding: 0 4px; margin: 0 2px; cursor: pointer; vertical-align: super;
}
.answer .grounding { margin: 7px 0 0; font-size: 11px; color: var(--good); }
.answer .grounding.bad { color: var(--bad); }
.answer .disclaimer { margin: 3px 0 0; font-size: 10.5px; color: var(--ink-3); }
.passagehead {
  margin: 0 0 6px; font-size: 11px; text-transform: uppercase;
  letter-spacing: .05em; color: var(--ink-3); font-weight: 600;
}

/* Clearing the query is a frequent action and was only reachable through
   "clear all", which also discards every filter — two quite different
   intentions behind one control. The field is already a flex row, so this
   sits in it like the search glyph rather than floating over the text. */
.clearq {
  flex: 0 0 auto; border: 0; background: none; color: var(--ink-3);
  cursor: pointer; font-size: 17px; line-height: 1; padding: 2px 4px;
  border-radius: 0; margin-right: -4px;
}
.clearq:hover { color: var(--ink); background: var(--surface-2); }
.clearq:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* Shown when the best passage scored below the confidence floor: the results
   are what the corpus offered, not what the question asked for. Marked in the
   warn tone rather than the accent — it is a caveat on the list, not a
   selection in it. This had no rule at all and inherited body text, so the one
   line telling a reader not to trust the results looked like the results. */
.weakmatch {
  margin: 0 0 8px; padding: 5px 9px; font-size: 11.5px; line-height: 1.4;
  color: var(--warn); background: var(--accent-soft);
  border-left: 3px solid var(--warn);
}

.passage .foot {
  display: flex; flex-wrap: wrap; align-items: center; gap: 4px; margin-top: 4px;
}


/* The information icon and the sentence it reveals.

   Used where an explanation is worth having once and tiresome to be shown every
   time: what a retrieval mode does, why the expansion caption says what it
   says. Both used to be standing paragraphs, read on the first visit and
   occupying a line forever after. */
.tabwrap { position: relative; display: inline-flex; align-items: center; }
/* A tab with an info icon is still a tab. Wrapped in a centred inline-flex it
   stopped stretching to the header's full height, so its coral underline sat
   just below the text while the bare tabs' sat on the header's bottom edge —
   the three tabs with icons were underlined at a different height from the two
   without. */
.tabs .tabwrap { align-self: stretch; align-items: stretch; }
.tabs .tabwrap > button { padding-right: 3px; }
/* The icon is a flex item beside the label; centring it vertically and pulling
   the row's padding off its left is what puts it next to the word rather than
   a tab's width away from it. */
.tabs .tabwrap > .infotip { align-self: center; margin: 0 8px 0 0; }
.tabs .infobtn { padding: 5px; }
.infotip { position: relative; display: inline-flex; align-items: center; }
.infobtn {
  display: inline-flex; align-items: center; justify-content: center;
  padding: 3px; border: 0; background: none; color: var(--ink-3);
  border-radius: 0; cursor: pointer;
}
/* An inline SVG rather than a glyph: ⓘ and ℹ fall back unpredictably across
   platforms and can arrive as colour emoji, at the wrong size and hue. */
.infobtn svg { width: 13px; height: 13px; display: block; }
.infobtn:hover { background: var(--surface-2); color: var(--accent-text); }
.infobtn[aria-expanded="true"] { color: var(--accent-text); background: var(--surface-2); }

.infopop {
  /* Fixed, not absolute: the filter rail scrolls, and a scroll container clips
     its absolutely-positioned descendants on both axes — the note was being
     cut off at the rail's right edge. The coordinates come from the icon's
     rectangle, computed when it opens. */
  position: fixed; z-index: 60;
  width: 290px; padding: 9px 11px; cursor: pointer;
  background: var(--surface); color: var(--ink-2);
  border: 1px solid var(--rule-strong); border-radius: var(--radius);
  box-shadow: var(--pop-shadow); font-size: 12.5px; line-height: 1.5;
  font-weight: 400; text-align: left; white-space: normal;
  /* A tip can sit inside an Antonio heading, and the `font` shorthand does not
     reset text-transform or letter-spacing while nothing at all reset the
     family — so the Explore tips were rendering condensed and uppercased. */
  font-family: var(--sans); text-transform: none; letter-spacing: 0;
}
.infopop.wide { width: 360px; max-height: 50vh; overflow-y: auto; }
@media (max-width: 640px) {
  /* Tight on a phone: the placement already clamps to the viewport, so only
     the width needs to give. */
  .infopop { width: min(290px, 78vw); }
  .infopop.wide { width: min(360px, 86vw); }
}

/* The translated term itself, at the head of a group reached through it. Marked
   because it is a different kind of suggestion from the rest: not a word the
   corpus uses near yours, but the word your query becomes in that language. */
.relword.anchor { border-style: dashed; font-weight: 600; }
.relword.anchor.on { border-style: solid; }

/* The count-and-timing line above a passage list. Small, because it is a
   caption on the results rather than one of them. */
.results > .meta {
  margin: 0 0 6px; font-family: var(--mono); font-size: 10.5px; color: var(--ink-3);
}

/* ---- the words/meaning balance ---- */
.setting.balance { display: flex; align-items: baseline; justify-content: space-between; }
.setting.balance .mix { font-variant-numeric: tabular-nums; font-size: 12.5px;
  color: var(--ink-2); font-weight: 600; }
.settingspop .dial { width: 100%; margin: 2px 0 0; accent-color: var(--accent, #ED6A59); }
.settingspop .dialends { display: flex; justify-content: space-between;
  font-size: 11px; color: var(--ink-3); margin-bottom: 10px;
  text-transform: lowercase; letter-spacing: 0.02em; }

/* Run the search again — for the tabs that wait to be asked. Paired with the
   clear button rather than floated on its own, so the field keeps one cluster
   of controls at its right edge instead of two. */
.querybox .goq { display: inline-flex; align-items: center; justify-content: center;
  border: 0; background: none; cursor: pointer; padding: 0 2px; color: var(--ink-3); }
.querybox .goq:hover { color: var(--accent, #ED6A59); }
.querybox .goq svg { width: 15px; height: 15px; display: block; }
.querybox .goq:focus-visible { outline: 2px solid var(--accent, #ED6A59);
  outline-offset: 2px; border-radius: 3px; }

