/* ============================================================
   serbian.fyi design system
   Flexoki paper/ink palette, mobile-first charts.
   Source Serif 4 = specimen voice (Serbian, headings),
   Source Sans 3 = apparatus voice (labels, captions, UI).
   ============================================================ */

@font-face {
  font-family: 'Source Sans 3';
  font-style: normal;
  font-weight: 200 900;
  font-display: swap;
  src: url('fonts/source-sans-3-normal-cyrillic.woff2') format('woff2');
  unicode-range: U+0300-0301, U+0304, U+0306, U+0308, U+030F, U+0311, U+0400-045F, U+0490-0491, U+04B0-04B1, U+04C1-04C2, U+04D0-04D3, U+04D6-04D7, U+04DC-04DF, U+04E2-04E7, U+04EC-04F1, U+04F4-04F5, U+04F8-04F9, U+2116;
}
@font-face {
  font-family: 'Source Sans 3';
  font-style: normal;
  font-weight: 200 900;
  font-display: swap;
  src: url('fonts/source-sans-3-normal-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Source Sans 3';
  font-style: normal;
  font-weight: 200 900;
  font-display: swap;
  src: url('fonts/source-sans-3-normal-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Source Sans 3';
  font-style: italic;
  font-weight: 200 900;
  font-display: swap;
  src: url('fonts/source-sans-3-italic-cyrillic.woff2') format('woff2');
  unicode-range: U+0300-0301, U+0304, U+0306, U+0308, U+030F, U+0311, U+0400-045F, U+0490-0491, U+04B0-04B1, U+04C1-04C2, U+04D0-04D3, U+04D6-04D7, U+04DC-04DF, U+04E2-04E7, U+04EC-04F1, U+04F4-04F5, U+04F8-04F9, U+2116;
}
@font-face {
  font-family: 'Source Sans 3';
  font-style: italic;
  font-weight: 200 900;
  font-display: swap;
  src: url('fonts/source-sans-3-italic-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Source Sans 3';
  font-style: italic;
  font-weight: 200 900;
  font-display: swap;
  src: url('fonts/source-sans-3-italic-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Source Serif 4';
  font-style: normal;
  font-weight: 200 900;
  font-display: swap;
  src: url('fonts/source-serif-4-normal-cyrillic.woff2') format('woff2');
  unicode-range: U+0300-0301, U+0304, U+0306, U+0308, U+030F, U+0311, U+0400-045F, U+0490-0491, U+04B0-04B1, U+04C1-04C2, U+04D0-04D3, U+04D6-04D7, U+04DC-04DF, U+04E2-04E7, U+04EC-04F1, U+04F4-04F5, U+04F8-04F9, U+2116;
}
@font-face {
  font-family: 'Source Serif 4';
  font-style: normal;
  font-weight: 200 900;
  font-display: swap;
  src: url('fonts/source-serif-4-normal-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Source Serif 4';
  font-style: normal;
  font-weight: 200 900;
  font-display: swap;
  src: url('fonts/source-serif-4-normal-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Source Serif 4';
  font-style: italic;
  font-weight: 200 900;
  font-display: swap;
  src: url('fonts/source-serif-4-italic-cyrillic.woff2') format('woff2');
  unicode-range: U+0300-0301, U+0304, U+0306, U+0308, U+030F, U+0311, U+0400-045F, U+0490-0491, U+04B0-04B1, U+04C1-04C2, U+04D0-04D3, U+04D6-04D7, U+04DC-04DF, U+04E2-04E7, U+04EC-04F1, U+04F4-04F5, U+04F8-04F9, U+2116;
}
@font-face {
  font-family: 'Source Serif 4';
  font-style: italic;
  font-weight: 200 900;
  font-display: swap;
  src: url('fonts/source-serif-4-italic-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Source Serif 4';
  font-style: italic;
  font-weight: 200 900;
  font-display: swap;
  src: url('fonts/source-serif-4-italic-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* -----------------------------------------------------------
   Tokens
   ----------------------------------------------------------- */

:root {
  color-scheme:   light dark;

  --fx-black:       #100F0F;
  --fx-paper:       #FFFCF0;
  --fx-50:          #F2F0E5;
  --fx-100:         #E6E4D9;
  --fx-150:         #DAD8CE;
  --fx-200:         #CECDC3;
  --fx-300:         #B7B5AC;
  --fx-400:         #9F9D96;
  --fx-500:         #878580;
  --fx-600:         #6F6E69;
  --fx-700:         #575653;
  --fx-800:         #403E3C;
  --fx-850:         #343331;
  --fx-900:         #282726;
  --fx-950:         #1C1B1A;

  --fx-red-400:     #D14D41;
  --fx-red-600:     #AF3029;
  --fx-orange-400:  #DA702C;
  --fx-orange-600:  #BC5215;
  --fx-yellow-400:  #D0A215;
  --fx-yellow-600:  #AD8301;
  --fx-green-400:   #879A39;
  --fx-green-600:   #66800B;
  --fx-cyan-400:    #3AA99F;
  --fx-cyan-600:    #24837B;
  --fx-blue-400:    #4385BE;
  --fx-blue-600:    #205EA6;
  --fx-purple-400:  #8B7EC8;
  --fx-purple-600:  #5E409D;
  --fx-magenta-400: #CE5D97;
  --fx-magenta-600: #A02F6F;

  --paper:          light-dark(var(--fx-paper), var(--fx-black));
  --paper-deep:     light-dark(var(--fx-50), var(--fx-950));
  --paper-mark:     light-dark(var(--fx-100), var(--fx-900));
  --ink:            light-dark(var(--fx-black), var(--fx-50));
  --ink-soft:       light-dark(var(--fx-700), var(--fx-100));
  --ink-muted:      light-dark(var(--fx-600), var(--fx-300));
  --ink-faint:      light-dark(#74736E, var(--fx-500)); /* fx-500 #878580 = 3.59:1 on cream (sub-AA); #74736E = 4.62:1, still faintest tier below ink-muted */
  --accent:         light-dark(var(--fx-orange-600), var(--fx-orange-400));
  --hairline:       light-dark(var(--fx-150), var(--fx-850));
  --hairline-soft:  light-dark(var(--fx-100), var(--fx-900));
  --shadow:         light-dark(rgba(16,15,15,.08), rgba(16,15,15,.46));

  --tone-red:       light-dark(var(--fx-red-600), #D25247); /* dark: red-400 #D14D41 = 4.42:1 as text; #D25247 = 4.61:1 */
  --tone-orange:    light-dark(var(--fx-orange-600), var(--fx-orange-400));
  --tone-yellow:    light-dark(#916E01, var(--fx-yellow-400)); /* light: yellow-600 #AD8301 = 3.39:1 as text; #916E01 = 4.60:1 */
  --tone-green:     light-dark(#637C0B, var(--fx-green-400)); /* light: green-600 #66800B = 4.39:1 as text; #637C0B = 4.60:1 */
  --tone-cyan:      light-dark(#238078, var(--fx-cyan-400)); /* light: cyan-600 #24837B = 4.43:1 as text; #238078 = 4.60:1 */
  --tone-blue:      light-dark(var(--fx-blue-600), var(--fx-blue-400));
  --tone-purple:    light-dark(var(--fx-purple-600), var(--fx-purple-400));
  --tone-magenta:   light-dark(var(--fx-magenta-600), var(--fx-magenta-400)); /* unassigned — reserve for a future cross-chart axis */

  /* Tier 2 — facets. Chroma names the axis, hue names the value within it:
     tier-1 accents run C .085–.165 and own the case axis alone; facets run
     C .050 and own gender. The GAP is the encoding — a facet must never read
     as a faded case. Solved in OKLCH at C .050, L fitted per hue and per
     ground to 4.61–4.63:1 on --fx-paper and --fx-black alike. Do not
     hand-edit: if a hue moves, re-solve L for the same target, or the band
     stops being a band. */
  --facet-m:        light-dark(#5D7A63, #66846B); /* L .550/.583  C .0488/.0511  h 151/150 */
  --facet-n:        light-dark(#717091, #7A7A9A); /* L .558/.591  C .0508/.0486  h 286/285 */
  --facet-f:        light-dark(#8B6D58, #967661); /* L .559/.591  C .0493/.0507  h  57/ 55 */

  /* Two voices: serif carries the language (Serbian specimens, headings),
     sans carries the apparatus (labels, captions, UI, prose around the data). */
  --ff-display:   'Source Serif 4', Georgia, serif;
  --ff-body:      'Source Sans 3', system-ui, sans-serif;

  /* Fixed rem per role. All viewport fluidity lives in ONE place — the root
     font-size clamp on `html`. Tokens must never carry their own vw terms. */
  --fs-label:     .76rem;
  --fs-caption:   .9rem;
  --fs-body:      1.12rem;
  --fs-lead:      1.28rem;
  --fs-title:     1.5rem;
  --fs-head:      2.1rem;

  --track-label:    .075em;
  --track-display: -.02em;

  --lh-snug:  1.3;
  --lh-prose: 1.55;

  /* Canonical column: one layout per chart, sized like a sheet of paper.
     The sheet (body) caps at --max-w and grows physically with the root
     scale — desktop gets the same sheet, larger, never a different layout. */
  --pad-x:        1.1rem;
  --max-w:        28rem;

  --rad:          2px;
}

:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"]  { color-scheme: dark; }

/* -----------------------------------------------------------
   Reset & base
   ----------------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }
html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* The desk behind the sheet — visible only when the viewport outgrows
     --max-w, so no media query is needed. */
  background: var(--paper-deep);
  /* The single viewport-responsive rule on the site. Phones stay at the
     user's default (1rem); wider viewports scale the whole sheet up —
     type, spacing, and column width together — capped at 1.35rem.
     rem-based terms keep user font-size preferences intact. */
  font-size: clamp(1rem, .9rem + .33vw, 1.35rem);
}
body {
  margin: 0 auto;
  max-width: var(--max-w);
  min-height: 100svh;
  border-inline: 1px solid var(--hairline);
  font-family: var(--ff-body);
  font-size: var(--fs-body);
  line-height: var(--lh-prose);
  color: var(--ink);
  background: var(--paper);
  font-feature-settings: "kern", "liga", "onum";
  font-language-override: "SRB";
  font-optical-sizing: auto;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
  /* Long unbreakable tokens wrap instead of forcing a horizontal scroll at
     narrow widths (base safety net for prose, glosses, and translations). */
  overflow-wrap: break-word;
}

/* Translation glosses are NOT Serbian. body pins font-language-override:"SRB"
   for Serbian italic alternates (п → ū-form, т → ш̄-form); an italic Russian
   gloss inherits it and renders "Идём в театр." with Serbian letterforms. Reset
   the override wherever a gloss carries the reader's language — harmless on EN
   pages, where the same glosses are Latin-script. */
.chart-example .tr,
.letter .example .tr,
.ex .tr,
.wrinkle-list .gloss,
.case-head-title h3 em {
  font-language-override: normal;
}

::selection { background: var(--accent); color: var(--paper); }

a {
  color: inherit;
  text-decoration: underline;
  text-decoration-color: color-mix(in oklab, currentColor 40%, transparent);
  text-decoration-thickness: 1px;
  text-underline-offset: .2em;
}
.brand, .chart-card { text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; padding: 0; }

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

h1, h2, h3, h4, h5 {
  font-family: var(--ff-display);
  font-weight: 300;
  letter-spacing: var(--track-display);
  line-height: 1.05;
  margin: 0;
  color: var(--ink);
}
h1, h2 {
  font-size: var(--fs-head);
  font-variation-settings: "opsz" 60;
}
h3     { font-size: var(--fs-title); }
h4     { font-size: var(--fs-lead); }

p { margin: 0 0 1.15em; }

/* <i> marks inline Serbian tokens in foreign-language prose so the script
   converter can find them. It's a structural marker, not visual emphasis —
   but the token itself is a specimen, so it renders in the serif voice. */
i { font-style: inherit; font-family: var(--ff-display); }

/* ── Alphabet switch ───────────────────────────────────────────────────
   Every Serbian string ships in BOTH alphabets and CSS picks one. Toggling is
   one attribute on <html>; nothing rewrites text, so copy/paste and screen
   readers stay correct (display:none removes the hidden twin from both).

   Deliberately `.s`, not `.sr` — `.sr` is a live block-level specimen class
   (.chart-example .sr, .ex .sr), and these wrappers nest inside translations.

   The rules are ASYMMETRIC on purpose: a symmetric pair would render
   `žena жена` on any document without data-script. Latin wins by default,
   matching the pre-rewrite client; the [data-script="cyr"] block flips it. */
.s { display: contents; }
[data-s="cyr"] { display: none; }
[data-script="cyr"] [data-s="lat"] { display: none; }
[data-script="cyr"] [data-s="cyr"] { display: inline; }

/* Serbian specimens and their glosses sit in rigid grid/flex example tracks.
   `break-word` alone won't shrink a track — the longest word still sets the
   column's min-content. `anywhere` lets an over-long unbreakable token break
   AND collapse its min-content contribution, so the track shrinks to fit
   instead of forcing the page body to scroll sideways at 320px. */
.sr,
.tr,
.chart-form {
  overflow-wrap: anywhere;
}

/* -----------------------------------------------------------
   Layout primitives
   ----------------------------------------------------------- */

/* The sheet (body) owns the column width; shells only pad. */
.shell {
  width: 100%;
  margin: 0 auto;
  padding-inline: var(--pad-x);
}

section { position: relative; }

/* -----------------------------------------------------------
   Top navigation
   ----------------------------------------------------------- */

.nav {
  position: sticky; top: 0; z-index: 1100;
  background: var(--paper);
  border-bottom: 1px solid var(--hairline-soft);
  padding-top: env(safe-area-inset-top);
  isolation: isolate;
  transform: translateZ(0);
}
.nav::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: env(safe-area-inset-top);
  background: var(--paper);
  pointer-events: none;
  z-index: 0;
}
.nav-inner {
  display: flex; align-items: center; gap: .75rem;
  padding-block: 1.1rem;
  position: relative;
  z-index: 1;
}
.nav-actions {
  display: inline-flex; align-items: center; gap: .4rem;
  margin-left: auto;
}
.brand {
  display: inline-flex; align-items: baseline; gap: .55rem;
  font-family: var(--ff-display);
  font-weight: 400;
  font-size: var(--fs-lead);
  letter-spacing: -.01em;
  font-feature-settings: "ss01";
}
.brand-tld { color: var(--accent); }
.nav-controls {
  display: inline-flex; align-items: center; gap: .25rem;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  padding: 3px;
}
.chip {
  font-family: var(--ff-body);
  font-size: var(--fs-label);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  line-height: 1;
  /* 44px tap target (phone in hand); horizontal padding trimmed so the
     no-JS chip fallback fits the column down to 320px. */
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 44px;
  padding: 0 .7rem;
  border-radius: 999px;
  color: var(--ink-muted);
  transition: background .25s, color .25s;
}
/* The language chips are real links (they navigate to the counterpart
   route), so they mark the current choice with aria-current; the script and
   theme chips are toggles and use aria-pressed. Same treatment either way. */
.chip[aria-pressed="true"],
.chip[aria-current="true"] { background: var(--ink); color: var(--paper); }

/* Keyboard focus — the house solid-accent ring, applied to the primary
   controls that previously fell back to the unstyled UA default. */
.brand:focus-visible,
.chip:focus-visible,
.foot-charts-list a:focus-visible,
.settings-btn:focus-visible,
.chart-card:focus-visible,
.case-strip-cell a:focus-visible,
.foot a:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}


/* -----------------------------------------------------------
   Chart index
   ----------------------------------------------------------- */

.home {
  padding-block: 1.8rem 3rem;
}
.chart-grid {
  display: grid;
  grid-template-columns: 1fr;
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--hairline);
  border-left: 1px solid var(--hairline);
}
.chart-grid li { min-width: 0; }

/* One layout: a compact row per chart — name only. The old hero-card
   grid (glyph + note, 2/3-col) was desktop-only duplication. */
.chart-card {
  position: relative;
  display: flex;
  align-items: center;
  gap: 1.4rem;
  padding: .95rem 1.2rem;
  background: var(--paper);
  border-right: 1px solid var(--hairline);
  border-bottom: 1px solid var(--hairline);
  transition: background .25s;
}

.chart-glyph { display: none; }

.chart-meta { display: flex; flex-direction: column; gap: .3rem; flex: 1 1 auto; min-width: 0; }
.chart-card h2 {
  font-size: var(--fs-title);
  line-height: var(--lh-snug);
}
.chart-note { display: none; }

:root:not([lang="ru"]) [data-lang-only="ru"] {
  display: none;
}

/* -----------------------------------------------------------
   Footer
   ----------------------------------------------------------- */

/* Keyboard-only route past the masthead. Off-canvas until focused, then it
   parks over the sheet's top-left corner. */
.skip-link {
  position: absolute;
  left: .75rem; top: -4rem;
  z-index: 1300;
  padding: .7rem 1rem;
  border: 1px solid var(--hairline);
  border-radius: .4rem;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--ff-body);
  font-size: var(--fs-label);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  line-height: 1;
  transition: top .18s;
}
.skip-link:focus-visible {
  top: .75rem;
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* With JS off the popovers and the alphabet toggle are inert; everything else
   is already in the served bytes. One line, then out of the way. */
.noscript-note {
  margin: 0 0 1.2rem;
  padding: .7rem 0;
  border-bottom: 1px dashed var(--hairline-soft);
  font-family: var(--ff-body);
  font-size: var(--fs-caption);
  line-height: var(--lh-prose);
  color: var(--ink-muted);
  text-transform: none;
}

.foot {
  padding-block: 3rem 4rem;
  border-top: 1px solid var(--hairline);
  font-family: var(--ff-body);
  font-size: var(--fs-label);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-muted);
  display: flex; flex-direction: column; gap: 2.4rem;
}
.foot-meta {
  display: flex; flex-direction: column; gap: .6rem;
  text-align: right; line-height: var(--lh-snug);
  align-self: flex-end;
}

/* Chart-to-chart navigation. A cheat sheet is flipped between, not read
   through — before this the only route from cases to verbs was
   wordmark -> home -> card. */
.foot-charts {
  display: flex; flex-direction: column; gap: .8rem;
}
.foot-charts-label { color: var(--ink-soft); }
.foot-charts-list {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: .5rem 1.1rem;
  line-height: 1;
}
.foot-charts-list a {
  display: inline-block;
  padding-block: .5rem;
  color: var(--ink-muted);
}
.foot-charts-list a[aria-current="page"] { color: var(--ink); }
@media (hover: hover) and (pointer: fine) {
  .foot-charts-list a:hover { color: var(--accent); }
  .chip:hover { color: var(--ink); }
  .chip[aria-pressed="true"]:hover,
  .chip[aria-current="true"]:hover { color: var(--paper); }
  .chart-card:hover { background: var(--paper-deep); }
  .foot a:hover { color: var(--accent); }
  .tip-chip:hover {
    color: var(--ink);
    border-color: var(--ink-muted);
  }
  .tip-pop-close:hover { color: var(--ink); background: var(--paper-deep); }
  .case-strip-cell:hover {
    background: color-mix(in oklab, var(--tone, var(--accent)) 8%, transparent);
  }
}

/* -----------------------------------------------------------
   Chart pages — shared

   One table vocabulary for every chart page (alphabet and cases
   keep their genuinely unique grids):

   .chart-section / .chart-layout    page scaffold
   .chart-label                      ALL-CAPS apparatus label
   .chart-form                       Serbian specimen voice (data cell)
   .chart-group / .chart-group-head  titled block
   .chart-table / .chart-row /
   .chart-cell                       stacked table: one labelled fact
                                     per line (no header row — per-cell
                                     data-labels carry the axis)
   .chart-pairs / .chart-pair        label + form paradigm rows
   .chart-example                    Serbian sentence over its gloss
   .chart-sep                        connector glyph in a specimen run
   .chart-tiles / .chart-tile        stacked card rows
   .chart-panel-grid / .chart-panel  bordered panel mosaic with a tone
                                     strip (pronouns, verbs)
   .chart-pop / .chart-tip           `?` popover card body
   ----------------------------------------------------------- */

.chart-section {
  padding-block: 2rem 3rem;
}
.chart-layout {
  display: grid;
  align-items: start;
  gap: 1.6rem;
}

.chart-label {
  font-family: var(--ff-body);
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: var(--track-label);
  line-height: 1;
  text-transform: uppercase;
  color: var(--ink-muted);
}

.chart-form {
  font-family: var(--ff-display);
  font-size: var(--fs-lead);
  font-weight: 400;
  line-height: var(--lh-snug);
  letter-spacing: 0;
  min-width: 0;
}

.chart-group {
  border-top: 1px solid var(--hairline);
}
.chart-group-head {
  padding-block: 1rem .85rem;
  border-bottom: 1px solid var(--hairline);
}
.chart-group-head h3 {
  font-size: var(--fs-title);
  line-height: var(--lh-snug);
  color: var(--tone, var(--ink));
}

.chart-table {
  display: grid;
}
.chart-row {
  display: grid;
  gap: .75rem;
  padding: 1.05rem 0 1.15rem;
  border-bottom: 1px solid var(--hairline-soft);
}
.chart-row:last-child {
  border-bottom-color: var(--hairline);
}
.chart-row > * {
  min-width: 0;
}
.chart-row h4 {
  margin: 0;
  display: flex;
  align-items: center;
  gap: .55rem;
  flex-wrap: wrap;
  font-family: var(--ff-body);
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: var(--track-label);
  line-height: 1;
  text-transform: uppercase;
  color: var(--ink-muted);
}
.chart-row p {
  margin: 0;
  font-size: var(--fs-body);
  line-height: var(--lh-prose);
  color: var(--ink-muted);
}
.chart-cell {
  display: grid;
  gap: .3rem;
  min-width: 0;
}
.chart-cell[data-label]::before,
.chart-example[data-label]::before {
  content: attr(data-label);
  font-family: var(--ff-body);
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: var(--track-label);
  line-height: 1;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.chart-pairs {
  display: grid;
  border-top: 1px solid var(--hairline-soft);
}
.chart-pair {
  display: grid;
  grid-template-columns: minmax(5.8rem, .8fr) minmax(0, 1fr);
  align-items: baseline;
  gap: .8rem;
  padding: .72rem 0;
  border-bottom: 1px dashed var(--hairline-soft);
}
.chart-pair:last-child {
  border-bottom: 0;
}

.chart-example {
  display: grid;
  gap: .12rem;
  min-width: 0;
}
.chart-example .sr {
  font-family: var(--ff-display);
  font-size: var(--fs-lead);
  font-weight: 400;
  line-height: var(--lh-snug);
  color: var(--ink);
}
.chart-example .tr {
  font-family: var(--ff-body);
  font-style: italic;
  font-weight: 500;
  font-size: var(--fs-caption);
  line-height: var(--lh-snug);
  color: var(--ink-muted);
}

/* Connector glyph inside a specimen run (sto + jedan, pisati -> napisati) */
.chart-sep {
  font-family: var(--ff-body);
  font-size: var(--fs-caption);
  color: var(--ink-faint);
}

.chart-tiles {
  display: grid;
}
.chart-tile {
  display: grid;
  gap: .75rem;
  padding: 1.05rem 0 1.15rem;
  border-bottom: 1px solid var(--hairline-soft);
}
.chart-tile:last-child {
  border-bottom-color: var(--hairline);
}

.chart-panel-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0;
  border-top: 1px solid var(--hairline);
  border-left: 1px solid var(--hairline);
  position: relative;
}
.chart-panel-grid::before,
.chart-panel-grid::after {
  content: "";
  position: absolute;
  background: var(--hairline);
  pointer-events: none;
}
.chart-panel-grid::before { left: 0; right: 0; bottom: 0; height: 1px; }
.chart-panel-grid::after { top: 0; bottom: 0; right: 0; width: 1px; }

.chart-panel {
  min-width: 0;
  border-right: 1px solid var(--hairline);
  border-bottom: 1px solid var(--hairline);
  background: var(--paper);
  padding: 1.25rem 1.05rem 1.35rem;
  display: grid;
  align-content: start;
  gap: 1.15rem;
}
.chart-panel::before {
  content: "";
  display: block;
  height: 3px;
  background: var(--tone, var(--ink-soft));
  margin: -1.25rem -1.05rem .05rem;
}
.chart-panel-head {
  display: grid;
  gap: .45rem;
}
.chart-panel-head h3 {
  font-size: var(--fs-title);
  line-height: var(--lh-snug);
  color: var(--tone, var(--ink-soft));
}

.chart-pop .tip-pop-card {
  border-left: 2px solid var(--accent);
}
.chart-tip {
  display: grid;
  gap: .65rem;
}
.chart-tip h4 {
  margin: 0;
  font-size: var(--fs-body);
  line-height: var(--lh-snug);
}
.chart-tip p {
  margin: 0;
  font-size: var(--fs-body);
  line-height: var(--lh-prose);
  color: var(--ink-muted);
}


/* -----------------------------------------------------------
   Alphabet grid
   ----------------------------------------------------------- */

.alph-section {
  padding-block: 2.5rem;
}

.alph-legend {
  display: flex; gap: 1.4rem; flex-wrap: wrap;
  font-family: var(--ff-body);
  font-size: var(--fs-label);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-muted);
  padding-bottom: 2rem;
}
.alph-mark {
  display: inline-grid;
  place-items: center;
  width: 2.35rem;
  height: 1.35rem;
  margin-right: .55rem;
  border: 1px solid var(--hairline);
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: 0;
  line-height: 1;
  color: var(--ink-soft);
  vertical-align: middle;
}
.alph-mark.diff {
  border-style: dashed;
}

.alph-grid {
  display: grid;
  grid-template-columns: 1fr;
  border-top: 1px solid var(--hairline);
  border-left: 1px solid var(--hairline);
  position: relative;
}
.alph-grid::before,
.alph-grid::after {
  content: "";
  position: absolute;
  background: var(--hairline);
  pointer-events: none;
}
.alph-grid::before { left: 0; right: 0; bottom: 0; height: 1px; }
.alph-grid::after  { top: 0; bottom: 0; right: 0; width: 1px; }

/* Compact row: glyph pair over IPA on the left, example on the right. */
.letter {
  position: relative;
  padding: .85rem 1.15rem .95rem;
  border-right: 1px solid var(--hairline);
  border-bottom: 1px solid var(--hairline);
  display: grid;
  grid-template-columns: minmax(8rem, auto) minmax(0, 1fr);
  grid-template-areas:
    "glyphs example"
    "ipa    example";
  column-gap: 1.1rem;
  row-gap: .45rem;
  align-content: center;
  background: var(--paper);
  overflow: hidden;
}
.letter .glyphs { grid-area: glyphs; }
.letter .example { grid-area: example; align-self: center; }
.letter[data-kind="unique"],
.letter[data-kind="diff"] {
  padding-right: 3.7rem;
}

.letter .glyphs {
  display: flex; align-items: baseline; gap: .45rem;
  font-family: var(--ff-display);
  font-weight: 400;
  font-size: var(--fs-title);
  line-height: 1;
  letter-spacing: -.025em;
  white-space: nowrap;
}
.letter .cyr { color: var(--ink); }
.letter .sep { color: var(--ink-faint); font-size: var(--fs-caption); padding-bottom: .3em; }
.letter .lat { color: var(--ink); }

.letter .ipa-row {
  grid-area: ipa;
  display: flex;
  align-items: center;
  gap: .7rem;
  flex-wrap: wrap;
}
.letter .ipa {
  font-family: var(--ff-body);
  font-size: var(--fs-caption);
  font-weight: 400;
  line-height: 1;
  color: var(--ink-muted);
}

.letter .example {
  font-family: var(--ff-body);
  line-height: var(--lh-snug);
}
.letter .example .word {
  font-family: var(--ff-display);
  font-size: var(--fs-body);
  font-weight: 500;
  display: inline-flex;
  align-items: baseline;
  gap: .35rem;
  flex-wrap: wrap;
  line-height: var(--lh-snug);
}
.letter .example .word-cyr { color: var(--ink); }
.letter .example .word-sep { color: var(--ink-faint); }
.letter .example .word-lat { color: var(--ink); font-style: normal; }
.letter .example .tr {
  font-style: italic;
  color: var(--ink-muted);
  display: block;
  font-size: var(--fs-caption);
  margin-top: .35rem;
  line-height: var(--lh-snug);
}

.letter::after {
  content: "";
  position: absolute;
  top: 1.15rem;
  right: 1.15rem;
  display: none;
  place-items: center;
  width: 2.35rem;
  height: 1.35rem;
  border: 1px solid var(--hairline);
  font-family: var(--ff-body);
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: 0;
  line-height: 1;
  color: var(--ink-soft);
}
.letter[data-kind="unique"]::after {
  content: "SR";
  display: grid;
}
.letter[data-kind="diff"]::after {
  content: "!=";
  display: grid;
  border-style: dashed;
}

/* Small `?` glyph used by alphabet and case-note popovers */
.tip-chip {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.15rem; height: 1.15rem;
  padding: 0;
  background: transparent;
  border: 1px solid var(--hairline);
  border-radius: 50%;
  font-family: var(--ff-body);
  font-size: var(--fs-label);
  font-weight: 500;
  line-height: 1;
  color: var(--ink-muted);
  cursor: pointer;
  transition: color .15s, border-color .15s;
  vertical-align: baseline;
}
/* Grow the tap target to a comfortable ≥44px (WCAG 2.5.8) without moving the
   visible glyph — a centered, transparent overlay that catches the pointer.
   Absolutely positioned so it never shifts surrounding layout. */
.tip-chip::after {
  content: "";
  position: absolute;
  top: 50%; left: 50%;
  width: 44px; height: 44px;
  min-width: 100%; min-height: 100%;
  transform: translate(-50%, -50%);
}
.tip-chip:focus-visible,
.tip-chip[aria-expanded="true"] {
  color: var(--ink);
  border-color: var(--ink-muted);
}
.tip-chip:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Pronunciation tip — popover */
.tip-pop {
  position: absolute;
  z-index: 50;
  width: min(20rem, calc(100vw - 24px));
  opacity: 0;
  transform: none;
  pointer-events: none;
}
.tip-pop.is-open {
  opacity: 1;
  pointer-events: auto;
}
.tip-pop[data-placement="above"] {
  transform: none;
}
.tip-pop-card {
  position: relative;
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: var(--rad);
  padding: .95rem 2.2rem .95rem 1.1rem;
  box-shadow: 0 18px 38px -22px var(--shadow), 0 8px 18px -16px var(--shadow);
}
.tip-pop-body {
  margin: 0;
  font-family: var(--ff-body);
  font-size: var(--fs-body);
  line-height: var(--lh-prose);
  color: var(--ink-soft);
}
.tip-pop-body strong { color: var(--ink); font-weight: 500; }
.tip-pop-body em { color: var(--accent); font-style: normal; font-family: var(--ff-display); font-weight: 500; }
.tip-pop-close {
  position: absolute;
  top: .35rem; right: .55rem;
  width: 1.6rem; height: 1.6rem;
  background: transparent;
  border: 0;
  color: var(--ink-faint);
  font-size: var(--fs-lead);
  line-height: 1;
  cursor: pointer;
  border-radius: 50%;
  transition: color .15s, background .15s;
}
.tip-pop-close:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Cases page — note popover. Same .tip-pop shell, richer body. */
.case-pop .tip-pop-card {
  border-left: 2px solid var(--tone, var(--accent));
}
.case-pop .tip-pop-body {
  display: grid;
  gap: .7rem;
}

/* -----------------------------------------------------------
   Cases (declension)
   ----------------------------------------------------------- */

.cases-section {
  padding-block: 2rem 3rem;
}

/* Baseline for any [data-tone]: ink-soft. Charts that don't carry
   grammatical meaning in color (pronouns, numbers, aspect) inherit this
   neutral tone; chart-specific overrides come below. :where() keeps the
   baseline at 0 specificity so even un-qualified case rules trivially win. */
:where([data-tone]) { --tone: var(--ink-soft); }

/* Per-case tone colors. One hue per case; orange is brand/marker ink and
   never a case. NOM is unmarked — the dictionary form — so it takes an
   ink-tone rather than an accent, distinguishing it visually from the
   inflected cases. */
[data-tone="nom"] { --tone: var(--ink-soft); }
[data-tone="gen"] { --tone: var(--tone-purple); }
[data-tone="dat"] { --tone: var(--tone-yellow); }
/* AKU holds cyan, and the pairing is load-bearing, not aesthetic: blue and
   purple are indistinguishable to a protanope on the dark ground, and AKU|INS
   is the most-compared case pair on the site by more than 2x. Purple on AKU
   put the palette's worst hue pair on its heaviest case pair. */
[data-tone="aku"] { --tone: var(--tone-cyan); }
[data-tone="vok"] { --tone: var(--tone-red); }
[data-tone="ins"] { --tone: var(--tone-blue); }
[data-tone="lok"] { --tone: var(--tone-green); }

/* Case-toned spans inside the pronouns chart's case-axis headers — the
   personal table's column heads and the who/what row heads (combined labels
   like "ACC/GEN", "DAT/LOC" tone each half by case). */
.pron-table thead [data-tone],
.pron-kw-row [data-tone] { color: var(--tone); }
.pron-slash { color: var(--ink-faint); margin: 0 .15em; }

/* -----------------------------------------------------------
   Case strip — colour-coded sticky nav.
   All seven cells fit the column (no scroll); abbreviations only.
   ----------------------------------------------------------- */
.case-strip {
  position: sticky;
  top: var(--nav-height, calc(68px + env(safe-area-inset-top)));
  z-index: 20;
  background: var(--paper);
  border-bottom: 1px solid var(--hairline);
  padding-inline: 0;
  transition: transform .28s ease, opacity .2s ease;
  will-change: transform;
}
.case-strip.is-hidden {
  opacity: 0;
  pointer-events: none;
  transform: translateY(calc(-100% - 1px));
}
.case-strip-list {
  list-style: none; margin: 0; padding: 0;
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 0;
}

.case-strip-cell {
  position: relative;
  border-right: 1px solid var(--hairline-soft);
  background: transparent;
  transition: background .35s;
  min-width: 0;
}
.case-strip-cell:last-child { border-right: 0; }
.case-strip-cell::before {
  content: "";
  position: absolute;
  top: 0; left: 0; right: 0; height: 3px;
  background: var(--tone, var(--ink-soft));
  opacity: .85;
}
.case-strip-cell a {
  display: grid;
  align-content: center;
  justify-items: center;
  text-align: center;
  gap: .15rem;
  padding: .65rem .2rem .65rem;
  min-height: 52px;
  min-width: 0;
  text-decoration: none;
}
.case-strip-cell.is-current {
  background: color-mix(in oklab, var(--tone, var(--ink-soft)) 14%, transparent);
}
.case-strip-cell.is-current::before { height: 4px; opacity: 1; }

/* Abbreviations only — all seven cells fit the column at every width. */
.strip-abbr {
  font-family: var(--ff-body);
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--tone, var(--ink-soft));
  line-height: 1;
}


/* -----------------------------------------------------------
   Case list — one row per case; endings pair SG | PL per gender.
   ----------------------------------------------------------- */
.case-list {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0;
}

/* Two bands of ending units — SINGULAR, then PLURAL. Number is a band
   heading; gender is a field inside the unit. Each band is a WRAPPING run,
   not three fixed tracks: a merged unit covers two genders and has no
   per-gender column to sit in. The grid still spans three columns for the
   head, example and preposition rows. */
.case-row {
  scroll-margin-top: calc(var(--sticky-offset, 120px) + .5rem);
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  grid-template-areas:
    "head  head  head"
    "sg-l  sg-l  sg-l"
    "sg    sg    sg"
    "pl-l  pl-l  pl-l"
    "pl    pl    pl"
    "ex    ex    ex"
    "preps preps preps";
  gap: .55rem;
  padding: 2.2rem 0;
  border-bottom: 1px solid var(--hairline);
  position: relative;
}
.case-row .case-cell-head { margin-bottom: .65rem; }
.case-row .case-cell-preps { margin-top: .65rem; }
.case-row::before {
  content: "";
  position: absolute;
  top: 0; left: calc(-1 * var(--pad-x));
  width: calc(100% + 2 * var(--pad-x));
  height: 3px;
  background: var(--tone, var(--ink-soft));
  opacity: .85;
}

.case-row-head { display: none; }

.case-cell { min-width: 0; }
.case-cell-preps.is-empty { display: none; }

.case-cell-head    { grid-area: head; }
.case-cell-band[data-band="sg"] { grid-area: sg-l; }
.case-cell-band[data-band="pl"] { grid-area: pl-l; }
/* A band is one run now, not three fixed columns: a merged unit spans two
   genders, so there is no per-gender track for it to sit in. */
.case-cell-end[data-band="sg"] { grid-area: sg; }
.case-cell-end[data-band="pl"] { grid-area: pl; }
.case-cell-ex      { grid-area: ex; }
.case-cell-preps   { grid-area: preps; }
.case-row .case-cell-ex { margin-top: .65rem; }

.case-cell-head { position: relative; }
.case-cell-head .case-head { display: block; }
/* Case name (Serbian) leads as the h3; the chip rides at its top-right. */
.case-head-title {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: .5rem .75rem;
}
.case-head-title h3 { flex: 1 1 auto; min-width: 0; }
.case-head-title .case-tag { flex: 0 0 auto; }
/* Case badge chip — the abbr in a tone-tinted pill. Shared by the detailed
   head and the basic word-grid row labels. */
.case-tag {
  display: inline-block;
  font-family: var(--ff-body);
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--tone, var(--ink-soft));
  background: color-mix(in oklab, var(--tone, var(--ink-soft)) 10%, transparent);
  padding: .35rem .75rem;
  line-height: 1;
}
/* -----------------------------------------------------------
   The ending unit — where tier 2 meets tier 1.

   ONE segmented object, up to three FIELDS: gender · form · source. Not a
   chip inside a chip — gender does not contain case, and nesting one badge in
   another asserts a containment that is not true. Detaching the source
   instead is worse: it loses which ending it annotates the moment a run wraps.

   align-items: stretch is what puts every field on one vertical rule. The old
   construction was an inline-flex box in an align-items: baseline row, which
   produced both shipped bugs at once — an inline-flex box aligns on the
   baseline of its own first line, already displaced by its own top padding,
   so the letter, the ending and the source chip each sat on a different line.
   Equal height BETWEEN units comes from the run (a flex container at the
   default stretch), never from these paddings.

   A case-tag is tone-coloured text on a tint of its own tone; a gender field
   is the inverse — a solid facet fill with the letter KNOCKED OUT of it.

   The knockout is not a style preference. A facet-coloured letter on a 16%
   facet tint measures 4.03:1 light and 2.92:1 dark against its own cell, and
   re-solving L cannot save it: on a 16% tint the CEILING is 4.90:1 on dark
   ground, and only for a pure-white letter — no hue reaches it. Every
   --tone-* token above carries a hand-fit comment proving 4.5:1 is the house
   bar, so the tint recipe is a regression against this project's own
   standard. Inverting costs nothing: knockout-on-fill is the same colour
   pair as fill-on-ground, so the solved lightnesses hold at 4.61-4.63:1 on
   both grounds. Do not "simplify" this back to a tint.

   Colour is the fast path; the letter is the guarantee. Under deuteranopia
   M and F converge, so every facet-coloured mark prints its abbreviation —
   permanently, via endingUnit() in src/render/chart.ts.

   Selectors are scoped to .eu-gender, never a bare [data-gender="m"].
   data-gender marks the facet AXIS, and the axis is carried by things that
   are not fields (the glossary knows a gender for every noun) — an unscoped
   rule would hand them a --facet they have no use for.
   ----------------------------------------------------------- */
.ending-unit {
  display: inline-flex;
  align-items: stretch;
  min-width: 0;
  border: 1px solid var(--ink-muted);
  border-radius: var(--rad);
}
.ending-unit > * { display: inline-flex; align-items: center; line-height: 1; }
/* The corner is cut on the END FIELDS, never with overflow: hidden on the
   unit. A `?` note trigger lives inside .eu-form, and its 44x44 ::after hit
   area and its focus ring both extend past the ~26px unit box — a clipping
   box here would crop the tap target to about 31x26 and slice the focus ring
   top and bottom, to buy a 2px radius. */
.ending-unit > :first-child {
  border-start-start-radius: var(--rad);
  border-end-start-radius: var(--rad);
}
.ending-unit > :last-child {
  border-start-end-radius: var(--rad);
  border-end-end-radius: var(--rad);
}
/* Only the form field may shrink. The letter is the guarantee — under
   deuteranopia it is the ONLY carrier left — so it must never be clipped by
   the unit's overflow: hidden. */
.eu-gender, .eu-source { flex: 0 0 auto; }
.eu-gender {
  font-family: var(--ff-body);
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  padding: .3rem .46rem;
  color: var(--paper);
  background: var(--facet, var(--ink-muted));
}
/* A merged unit's second gender field: divided by a knockout hairline, never
   a gap — a gap would read as two units.

   A BORDER, not an inset box-shadow. forced-colors forces box-shadow to none
   while flattening both fields to one system ground, which would leave the
   seven merged units reading `M N` as a single token — the exact failure the
   sr-only comma fixes for screen readers. Borders survive HCM. */
.eu-gender + .eu-gender {
  border-left: 1px solid color-mix(in oklab, var(--paper) 55%, transparent);
}
/* The specimen is body ink, never case-hued: inside a facet-filled unit a
   case tone would be a second colour on one small object, and two hues on one
   object read as a gradient rather than as two axes. The case is already
   stated by the section the unit sits in; the gender fields state the gender. */
.eu-form {
  font-family: var(--ff-display);
  font-style: normal;
  font-weight: 400;
  font-size: var(--fs-lead);
  color: var(--ink);
  letter-spacing: -.01em;
  padding: .24rem .55rem;
  white-space: nowrap;
  min-width: 0;
}
/* An ending that merely repeats a shape an earlier case introduced recedes to
   ink-faint; the .eu-source field names the case it came from. */
.eu-form.is-echo { color: var(--ink-faint); }
/* Deliberately NEUTRAL. Tone text on a 12% tint of its own tone is the recipe
   .case-tag already fails on — 4/7 tones in light, 6/7 in dark — so writing it
   here would only create a second site to migrate. The field names its case in
   text; the hue was redundant. --ink-soft on --paper-mark measures 5.75:1
   light and 11.69:1 dark. */
.eu-source {
  font-family: var(--ff-body);
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  padding: .3rem .5rem;
  color: var(--ink-soft);
  background: var(--paper-mark);
  border-left: 1px solid var(--hairline);
  white-space: nowrap;
}

/* A wrapping run of chips — what replaced the three gender columns. */
.gender-run {
  display: flex;
  flex-wrap: wrap;
  gap: .4rem .5rem;
  min-width: 0;
}
/* A run under its own number heading. Number is a band, never a chip. */
.gender-band {
  display: grid;
  gap: .4rem;
}
/* The one caveat a one-letter chip cannot carry: the past M plural is
   M-or-mixed. It rides beside the band instead. */
.gender-band-note {
  margin: 0;
  font-family: var(--ff-body);
  font-size: var(--fs-caption);
  line-height: var(--lh-prose);
  color: var(--ink-muted);
}

/* The facet map. --facet is assigned NOWHERE else site-wide: delete these and
   every unit drops to the --ink-muted fallback and turns tier 2 grey
   silently, because the fallback is a valid value. data-gender belongs on the
   FIELD, not the unit — one attribute on .ending-unit cannot feed two
   differently-coloured gender fields in a merged unit. */
.eu-gender[data-gender="m"] { --facet: var(--facet-m); }
.eu-gender[data-gender="n"] { --facet: var(--facet-n); }
.eu-gender[data-gender="f"] { --facet: var(--facet-f); }

.case-head-title h3 {
  font-family: var(--ff-display);
  font-weight: 300;
  text-transform: none;
  font-size: var(--fs-head);
  color: var(--ink);
  letter-spacing: -.025em;
  line-height: .98;
}
/* The i18n case name is a gloss of the Serbian h3 — apparatus, so it takes
   the sans voice, not the serif it would inherit from the heading. */
.case-head-title h3 em {
  font-family: var(--ff-body);
  font-style: italic;
  font-weight: 400;
  color: var(--ink-soft);
  display: block;
  font-size: var(--fs-caption);
  margin-top: .5em;
  letter-spacing: 0;
}
/* The question line pairs a Serbian specimen with its gloss: the <strong>
   question words keep the serif voice, the "— meaning" gloss is apparatus sans. */
.case-cell-head .q {
  font-family: var(--ff-body);
  font-style: italic;
  color: var(--ink-soft);
  font-size: var(--fs-lead);
  margin: .9rem 0 0;
  line-height: var(--lh-prose);
  max-width: 34ch;
}
.case-cell-head .q strong { font-family: var(--ff-display); font-style: normal; font-weight: 500; color: var(--tone, var(--ink-soft)); }

/* The cell is a grid slot, nothing more: the units inside carry the frame,
   and a framed cell around a framed unit is a box in a box. */
.case-cell-end { min-width: 0; }
/* Band heading over its run of units. */
.case-cell-band {
  margin-top: .35rem;
  padding-bottom: .15rem;
}
.cell-axis {
  font-family: var(--ff-body);
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-faint);
  line-height: 1;
}
.case-cell-ex .cell-axis,
.case-cell-preps .cell-axis {
  display: block;
  padding-bottom: .7rem;
  margin-bottom: 1rem;
  border-bottom: 1px solid var(--hairline);
  color: var(--ink-muted);
}
.case-cell-ex .examples,
.case-cell-preps .prep-list { max-width: 60ch; }

.cell-note {
  margin-left: .22rem;
}
/* The connector in an inline alternation (`-e¹ / -u²`). One statement, one
   form field — never a second flex row inside the unit. */
.cell-sep {
  font-family: var(--ff-display);
  font-style: normal;
  font-weight: 400;
  font-size: var(--fs-lead);
  color: var(--ink-faint);
  line-height: 1;
  margin: 0 .15em;
}
/* Syncretic split (AKU animacy): the two endings reuse DIFFERENT cases, so
   they cannot share one provenance field — they stack as two whole units,
   the alive/thing criterion deferred to the ? note. */
.eu-stack {
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  gap: .4rem;
  min-width: 0;
}

/* ── Settings menu ─────────────────────────────────────────────────────
   One masthead button opens a small floating panel with every site toggle.
   Non-modal; scales/fades up from the trigger (reduced-motion reset applies). */
.settings-btn {
  width: 42px; height: 42px;
  display: inline-grid; place-items: center;
  border-radius: 50%;
  border: 1px solid var(--hairline);
  color: var(--ink-soft);
  transition: background .25s, color .25s;
}
.settings-btn svg { width: 19px; height: 19px; }
.settings-btn svg circle { fill: var(--paper); }
.settings-btn[aria-expanded="true"] { background: var(--paper-deep); color: var(--ink); }

.settings-menu {
  position: fixed;
  z-index: 1200;
  opacity: 0;
  transform: scale(.97) translateY(-6px);
  transform-origin: top right;
  transition: opacity .16s ease, transform .16s ease;
  pointer-events: none;
}
.settings-menu.is-open {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}
.settings-menu-card {
  width: min(17.5rem, calc(100vw - 24px));
  background: var(--paper-deep);
  border: 1px solid var(--hairline);
  border-radius: 12px;
  box-shadow: 0 18px 38px -22px var(--shadow), 0 8px 18px -16px var(--shadow);
  padding: .35rem .65rem;
}
/* Each setting stacks: name (an eyebrow label) over its control, both left-
   aligned. A divider sits between settings. */
.settings-row {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: .55rem;
  padding: .8rem .15rem;
  border-top: 1px solid var(--hairline-soft);
}
.settings-menu-card > .settings-row:first-child { border-top: 0; }
.settings-label {
  font-family: var(--ff-body);
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-muted);
  line-height: 1;
}
/* Compact chips inside the panel; a too-wide group wraps within its capsule. */
.settings-menu .nav-controls { flex-wrap: wrap; gap: .15rem; }
.settings-menu .chip { padding: 0 .7rem; }

.note-title {
  font-style: italic;
  font-weight: 400;
  letter-spacing: -.012em;
  line-height: var(--lh-snug);
  margin: 0 0 .6rem;
}
.note-body {
  font-family: var(--ff-body);
  font-size: var(--fs-body);
  line-height: var(--lh-prose);
  color: var(--ink-soft);
  margin: 0;
  max-width: 56ch;
}
.note-pairs {
  list-style: none; padding: 0;
  margin: .95rem 0 0;
  display: flex; flex-wrap: wrap;
  gap: .35rem 1.4rem;
}
.note-pairs li {
  display: inline-flex;
  align-items: baseline;
  gap: .4rem;
  font-family: var(--ff-display);
  font-style: italic;
  font-size: var(--fs-body);
  line-height: var(--lh-snug);
}
.note-pairs .from { color: var(--ink-muted); }
.note-pairs .arrow {
  font-family: var(--ff-body);
  font-style: normal;
  font-size: var(--fs-caption);
  color: var(--ink-faint);
}
.note-pairs .to { color: var(--ink-muted); }
/* Spotlight on the changed letters — the whole point of the pair. */
.note-pairs .lit {
  font-style: italic;
  font-weight: 500;
  color: var(--tone, var(--ink-soft));
  background: color-mix(in oklab, var(--tone, var(--ink-soft)) 14%, transparent);
  padding: 0 .14em;
  border-radius: 2px;
}
/* Extra-table changed letters: colored regular serif, no tint, no italic —
   the hue alone marks the change (inherits serif/normal/400 from .from/.to). */
.wrinkle-list .lit { color: var(--tone, var(--ink-soft)); }

/* Examples + prepositions — used inside per-case cells */
.examples {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0;
}
.ex {
  display: grid;
  grid-template-columns: 1fr;
  gap: .2rem;
  padding: 1rem 0;
  border-bottom: 1px solid var(--hairline-soft);
}
.ex:first-child { padding-top: 0; }
.ex:last-child { border-bottom: 0; }
.ex .sr {
  font-family: var(--ff-display);
  font-size: var(--fs-lead);
  font-weight: 400;
  color: var(--ink);
  line-height: var(--lh-prose);
}
/* Example focus word: colored regular serif, no highlight box, no italic —
   the hue alone lifts it from the sentence (overrides the UA mark default). */
.ex .sr mark {
  background: transparent;
  color: var(--tone, var(--ink-soft));
}
.ex .tr {
  font-family: var(--ff-body);
  font-style: italic;
  font-weight: 500;
  color: var(--ink-muted);
  font-size: var(--fs-caption);
  line-height: var(--lh-prose);
}
.ex .tr em {
  font-style: normal;
  font-family: var(--ff-body);
  font-size: var(--fs-label);
  color: var(--ink-faint);
  letter-spacing: .04em;
  display: inline-block;
  margin-left: .35em;
}

/* Preposition list — tone-colored inline run; meanings live on the
   future Prepositions chart, so this side stays a quick name index. */
.prep-list {
  font-family: var(--ff-display);
  font-weight: 400;
  font-size: var(--fs-lead);
  color: var(--tone, var(--ink-soft));
  letter-spacing: -.005em;
  line-height: var(--lh-prose);
  margin: 0;
}

/* -----------------------------------------------------------
   Off-paradigm pack — i-declension + five wrinkles, stacked.
   ----------------------------------------------------------- */
.case-extra {
  padding-top: 3rem;
}

.extra-pack {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0;
  border-top: 1px solid var(--hairline);
  border-left: 1px solid var(--hairline);
}

.extra-panel {
  border-right: 1px solid var(--hairline);
  border-bottom: 1px solid var(--hairline);
  padding: 1.4rem 1.4rem 1.6rem;
  background: var(--paper);
  display: flex; flex-direction: column;
  min-width: 0;
}

.extra-panel-head { margin: 0 0 1rem; }
.extra-panel-title {
  font-weight: 400;
  letter-spacing: -.012em;
  line-height: var(--lh-snug);
}
.extra-panel-title .lit { white-space: nowrap; }
.extra-panel-sub {
  display: block;
  margin-top: .35rem;
  font-family: var(--ff-body);
  font-size: var(--fs-label);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-muted);
}
.extra-panel-sub em {
  font-family: var(--ff-display);
  font-style: normal;
  font-weight: 400;
  text-transform: none;
  letter-spacing: -.005em;
  font-size: var(--fs-body);
  color: var(--ink);
  margin-right: .25em;
}
.extra-panel-body { min-width: 0; }

/* i-declension paradigm — Sg / Pl table */
.i-decl {
  width: 100%;
  border-collapse: collapse;
}
.i-decl thead th {
  font-family: var(--ff-body);
  font-size: var(--fs-label);
  font-weight: 400;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-muted);
  text-align: left;
  padding: .2rem .6rem .6rem 0;
  border-bottom: 1px solid var(--hairline);
}
.i-decl tbody th.num {
  font-family: var(--ff-body);
  font-size: var(--fs-label);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-faint);
  font-weight: 400;
  text-align: left;
  width: 1%;
  white-space: nowrap;
  padding: .7rem 1rem .7rem 0;
  border-bottom: 1px dashed var(--hairline-soft);
}
.i-decl tbody td {
  padding: .7rem .6rem .7rem 0;
  border-bottom: 1px dashed var(--hairline-soft);
}
.i-decl tbody td .end {
  font-family: var(--ff-display);
  font-style: normal;
  font-weight: 400;
  font-size: var(--fs-lead);
  color: var(--ink);
  letter-spacing: -.005em;
}
.i-decl tbody tr:last-child th,
.i-decl tbody tr:last-child td { border-bottom: 0; }

/* Wrinkle list — from → to · gloss */
.wrinkle-list {
  list-style: none;
  padding: 0; margin: 0;
  display: grid;
  grid-template-columns: 1fr;
  gap: 0;
}
.wrinkle-list li {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: .55rem;
  padding: .6rem 0;
  border-bottom: 1px dashed var(--hairline-soft);
}
.wrinkle-list li:last-child { border-bottom: 0; }

.wrinkle-list .from,
.wrinkle-list .to {
  font-family: var(--ff-display);
  font-style: normal;
  font-weight: 400;
  font-size: var(--fs-body);
  color: var(--ink-muted);
  letter-spacing: -.005em;
}
.wrinkle-list .arrow {
  font-family: var(--ff-body);
  font-size: var(--fs-caption);
  color: var(--ink-faint);
}
.wrinkle-list .gloss {
  font-family: var(--ff-body);
  font-style: italic;
  font-size: var(--fs-caption);
  color: var(--ink-muted);
  line-height: var(--lh-prose);
  width: 100%;
}

/* -----------------------------------------------------------
   Pronouns
   ----------------------------------------------------------- */

/* Person × case is truly 2D — a real table in a horizontal scroll pane
   (the honest answer per the Layout rulebook). The person column sticks
   so orientation survives the scroll; case headers carry their tones. */
.pron-table-wrap {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
.pron-table {
  width: 100%;
  min-width: 28rem;
  border-collapse: collapse;
}
.pron-table th,
.pron-table td {
  padding: .6rem .9rem .6rem 0;
  border-top: 1px dashed var(--hairline-soft);
  text-align: left;
  vertical-align: baseline;
}
.pron-table thead th {
  border-top: 0;
  border-bottom: 1px solid var(--hairline);
  padding-top: 0;
  white-space: nowrap;
}
.pron-table tbody tr:first-child th,
.pron-table tbody tr:first-child td { border-top: 0; }
.pron-table th[scope="row"],
.pron-table thead th:first-child {
  position: sticky;
  left: 0;
  z-index: 1;
  background: var(--paper);
}
.pron-table th[scope="row"] .chart-label {
  display: block;
  margin-bottom: .3rem;
}
.pron-subject,
.pron-long,
.pron-kw-row > span:not(:first-child) {
  color: var(--tone, var(--ink-soft));
}
/* Short (clitic) forms step down one ink tone — position after the comma
   plus the legend carry the long/short axis; no hue (purple would read GEN). */
.pron-short,
.pron-comma,
.pron-dash {
  color: var(--ink-muted);
}
/* One grid item per cell on mobile — keeps "long, short" pairs together
   instead of letting each span take its own grid track. */
.pron-pair {
  min-width: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: .2rem .45rem;
}

/* An ARIA table wrapper that must not become a layout box — the head and its
   rowgroup are laid out by the section's own grid. */
.pron-subtable { display: contents; }

.pron-rule-row {
  display: grid;
  gap: .65rem;
  padding-top: 1rem;
  border-top: 1px solid var(--hairline);
}
.pron-rule-row p,
.pron-poss-card p {
  margin: 0;
  font-size: var(--fs-caption);
  line-height: var(--lh-prose);
  color: var(--ink-muted);
}
.pron-rule-row strong {
  color: var(--ink);
  font-weight: 500;
}

.pron-card-grid,
.pron-demo-pack,
.pron-question-pack {
  display: grid;
  gap: 1.1rem;
}
.pron-poss-card {
  display: grid;
  gap: .45rem;
  padding-bottom: .85rem;
  border-bottom: 1px dashed var(--hairline-soft);
}
.pron-poss-card:last-child { border-bottom: 0; padding-bottom: 0; }
.pron-demo-group,
.pron-question-block {
  display: grid;
  gap: .65rem;
}
/* Label over chips, not label beside three tracks: each chip now carries its
   own gender, so the row needs one column and the run wraps inside it. */
.pron-matrix-row {
  grid-template-columns: minmax(0, 1fr);
  align-items: start;
  gap: .45rem;
}

.pron-kw-table {
  display: grid;
  border-top: 1px solid var(--hairline-soft);
}
.pron-kw-head,
.pron-kw-row {
  grid-template-columns: minmax(7.5rem, 1fr) repeat(2, minmax(0, .8fr));
  gap: .6rem;
}
.pron-kw-head {
  display: grid;
  align-items: baseline;
  padding: 0 0 .5rem;
  border-bottom: 1px solid var(--hairline-soft);
}
.pron-kw-head span:not(:first-child) {
  color: var(--tone, var(--ink-soft));
}

/* -----------------------------------------------------------
   Verbs (conjugation)
   ----------------------------------------------------------- */

/* Present forms (all four conjugation buckets + irregulars) share the
   brand marker orange — chrome ink, not a grammatical hue. Past and
   future fall through to the ink-soft baseline. */
[data-tone="im"],
[data-tone="am"],
[data-tone="em"],
[data-tone="jem"],
[data-tone="irr"] { --tone: var(--tone-orange); }

/* h4s that hold a Serbian lemma (raditi, biti, se) speak in the specimen
   voice, not the caps-label apparatus voice. */
.verb-col .sr-head {
  font-family: var(--ff-display);
  font-size: var(--fs-body);
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink-muted);
}
/* Serbian pronoun labels (ja, ti, on/ona/ono) — specimen voice, lowercase. */
.verb-pron {
  font-family: var(--ff-display);
  font-style: italic;
  font-size: var(--fs-caption);
  line-height: var(--lh-snug);
  color: var(--ink-faint);
}
.verb-form {
  color: var(--tone, var(--ink-soft));
}

.verb-block {
  display: grid;
  gap: .65rem;
}
.verb-patterns {
  display: flex;
  flex-wrap: wrap;
  gap: .45rem;
}
.verb-pattern {
  display: inline-flex;
  align-items: center;
  min-height: 2.2rem;
  padding: .42rem .62rem;
  border: 1px solid var(--hairline-soft);
  font-family: var(--ff-display);
  font-size: var(--fs-body);
  font-weight: 400;
  letter-spacing: 0;
  line-height: 1;
  color: var(--tone, var(--ink-soft));
  background: color-mix(in oklab, var(--tone, var(--ink-soft)) 8%, transparent);
}
.verb-list,
.verb-formula,
.verb-note,
.verb-negative p {
  margin: 0;
  color: var(--ink);
  line-height: var(--lh-prose);
}
.verb-list,
.verb-formula {
  font-family: var(--ff-display);
  font-size: var(--fs-lead);
  font-weight: 400;
  letter-spacing: 0;
}
.verb-list-glossed {
  list-style: none;
  padding: 0;
  display: grid;
  gap: 0.35rem;
}
.verb-list-glossed li {
  display: flex;
  align-items: baseline;
  gap: 0.6em;
  flex-wrap: wrap;
}
.verb-list-glossed .verb-lemma {
  font-family: var(--ff-display);
  font-size: var(--fs-lead);
  color: var(--ink);
}
/* The 1sg present. The stem mutation is the only hard part of a bucket
   (pisati -> pišem, not *pisem), so it sits in the specimen voice beside the
   lemma, with the arrow as apparatus. */
.verb-list-glossed .verb-stem {
  font-family: var(--ff-display);
  font-size: var(--fs-body);
  color: var(--ink-soft);
}
.verb-list-glossed .verb-stem::before {
  content: "→";
  margin-inline-end: .4em;
  font-family: var(--ff-body);
  color: var(--ink-muted);
}
.verb-list-glossed .verb-gloss {
  font-size: var(--fs-caption);
  color: var(--ink-soft);
}
.verb-note,
.verb-negative p {
  font-size: var(--fs-body);
}
/* Negative paradigm (nisam, nisi…) is Serbian data, not prose. */
.verb-negative p {
  font-family: var(--ff-display);
}
.verb-formula {
  color: var(--tone, var(--ink-soft));
}
/* Apparatus inside the formula — the grammatical term naming what the Serbian
   run combines with. Sans voice, caption size; the specimen keeps the serif. */
.verb-formula .verb-term {
  font-family: var(--ff-body);
  font-size: var(--fs-caption);
}

.verb-mini-list {
  display: grid;
  gap: 0;
  border-top: 1px solid var(--hairline-soft);
}
.verb-mini {
  padding: 1rem 0;
  border-bottom: 1px solid var(--hairline-soft);
  display: grid;
  gap: .75rem;
}
.verb-mini:last-child { border-bottom: 0; padding-bottom: 0; }
/* One lemma-head treatment page-wide: an apparatus label (or a tip chip)
   beside the lemma, the lemma itself in the panel's tone. Without the label the
   example lemma read as a glossless item of the COMMON VERBS list above it. */
.verb-lemma-head {
  display: flex;
  align-items: baseline;
  gap: .55rem;
}
.verb-lemma-head .sr-head {
  color: var(--tone, var(--ink-soft));
}
.verb-negative {
  display: grid;
  gap: .35rem;
}

.verb-examples {
  display: grid;
  gap: 0;
  border-top: 1px solid var(--hairline-soft);
}
.verb-example {
  padding: .72rem 0;
  border-bottom: 1px dashed var(--hairline-soft);
}
.verb-example:last-child { border-bottom: 0; }

/* SG | PL paired paradigms — six cells reading as three rows.
   DOM order is ja,mi / ti,vi / on,oni (PAIR_ORDER in verbs.js). */
.verb-pair-grid {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: 1.1rem;
}
.verb-pair-grid .chart-pair {
  grid-template-columns: auto minmax(0, 1fr);
  gap: .55rem;
}
.verb-pair-grid .chart-pair:nth-last-child(-n+2) {
  border-bottom: 0;
}


/* -----------------------------------------------------------
   Numbers
   ----------------------------------------------------------- */

/* Cardinal groups: one fluid rule at every width. auto-fit grows the grid
   from two columns on a phone to a full single row on a wide screen — column
   count tracks the viewport with no per-breakpoint steps and no side-by-side
   panel split. Rows separate with a hairline, columns with a gap; no vertical
   rules to appear and vanish across breakpoints. */
/* Cardinals — one continuous table on the alphabet-chart playbook: a single
   auto-fit grid framed like .alph-grid (container top+left borders + pseudo
   edges close the right and bottom, so a partial last row can't open the
   frame), with cells carrying the inner dividers. Columns follow the viewport
   from two on a phone up to a full row on a wide screen. */
.num-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  border-top: 1px solid var(--hairline);
  border-left: 1px solid var(--hairline);
  position: relative;
}
.num-grid::before,
.num-grid::after {
  content: "";
  position: absolute;
  background: var(--hairline);
  pointer-events: none;
}
.num-grid::before { left: 0; right: 0; bottom: 0; height: 1px; }
.num-grid::after { top: 0; bottom: 0; right: 0; width: 1px; }

.num-cell {
  display: grid;
  gap: .25rem;
  align-content: start;
  padding: .85rem .6rem;
  border-right: 1px solid var(--hairline);
  border-bottom: 1px solid var(--hairline);
}
/* Each order of magnitude gets its own neutral background shade, deepening
   with magnitude, standing in for the old per-range headers. Shades are
   ink-tones, not hues — magnitude isn't a grammatical category. Every step is
   ≥ AA for the number text (ink stays ≥6.4:1) and every step skips fx-150 /
   fx-850, the hairline colour, so the cell dividers never vanish into a band.
   Ones (0–9) keep plain paper: the base is unmarked. */
.num-cell[data-band="teens"]     { background: light-dark(var(--fx-50),  var(--fx-950)); }
.num-cell[data-band="tens"]      { background: light-dark(var(--fx-100), var(--fx-900)); }
.num-cell[data-band="hundreds"]  { background: light-dark(var(--fx-200), var(--fx-800)); }
.num-cell[data-band="thousands"] { background: light-dark(var(--fx-300), var(--fx-700)); }

/* Notable endings — the trailing -a of dvesta/trista, the count-driven
   -u / -e of hiljadu / hiljade. The letters stay ink (AA on every band); the
   brand orange rides an underline as marker ink, so contrast never depends on
   the orange itself. */
.num-end {
  font-weight: 500;
  text-decoration: underline;
  text-decoration-color: var(--accent);
  text-decoration-thickness: .11em;
  text-underline-offset: .17em;
  text-decoration-skip-ink: none;
}
/* Keep number words whole: the fixed-min track already blocks page-level
   overflow, so the .chart-form `anywhere` net isn't needed here — and it
   would split "sedamnaest" mid-word. Two-word thousands still wrap at the
   space. */
.num-word {
  overflow-wrap: normal;
}

/* The digit is the index key, not apparatus: you read the number first,
   then the Serbian form. Sits on the title tier, one step above the
   specimen (--fs-lead), in full ink. */
.num-value {
  font-family: var(--ff-display);
  font-size: var(--fs-title);
  font-weight: 500;
  line-height: var(--lh-snug);
  color: var(--ink);
  font-feature-settings: "tnum";
}

.num-built {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: .35rem;
}

.num-pattern {
  font-size: var(--fs-body);
  line-height: var(--lh-prose);
  color: var(--ink-muted);
}

.num-examples {
  display: grid;
  gap: .35rem;
}

/* -----------------------------------------------------------
   Verb aspect pairs
   ----------------------------------------------------------- */


/* Time behavior: imp | perf side by side under the tense head —
   the forms are short; stacking them wasted half the column. */
.aspect-time .chart-row {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: 1.1rem;
}
.aspect-time .chart-row h4 { grid-column: 1 / -1; }

.aspect-side {
  display: grid;
  gap: .45rem;
  padding-top: .75rem;
  border-top: 1px dashed var(--hairline-soft);
}

/* The verb pair IS the section's data — full ink, like every other specimen.
   Aspect carries no categorical hue, so there is no tone to pull through. */
.aspect-form,
.aspect-prefix-head h4 {
  color: var(--ink);
}

.aspect-prefix {
  align-content: start;
}

.aspect-prefix-head {
  display: flex;
  align-items: center;
  gap: .55rem;
}

.aspect-prefix ul {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: .45rem;
}

/* One inline imp -> perf specimen run — the shape the prefix map already
   uses; the axis is in the arrow, so no per-cell labels are needed. */
.aspect-prefix li,
.aspect-pair {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: .45rem;
}

/* -----------------------------------------------------------
   Pitch & stress
   ----------------------------------------------------------- */

/* Alphabet-style row: mark glyph in a fixed left cell, one inline meta
   line (length · contour · pattern) over the examples on the right. */
.pitch-accent-card {
  grid-template-columns: minmax(2.6rem, auto) minmax(0, 1fr);
  column-gap: 1.1rem;
}

/* The mark glyph is this chart's core data, so it speaks in the specimen voice
   like the examples beside it. Orange is brand chrome; on a grammatical
   specimen it would read as UI. */
.pitch-mark {
  font-family: var(--ff-display);
  font-size: var(--fs-head);
  font-weight: 300;
  line-height: 1;
  color: var(--ink);
}

.pitch-accent-body {
  display: grid;
  gap: .55rem;
  min-width: 0;
}

.pitch-accent-meta {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: .4rem .55rem;
}

.pitch-length {
  font-family: var(--ff-body);
  font-size: var(--fs-caption);
  line-height: 1;
  color: var(--ink-muted);
}

.pitch-contour {
  color: var(--ink);
  padding-bottom: .18rem;
  border-bottom: 2px solid var(--ink);
}

.pitch-accent-card[data-contour="rising"] .pitch-contour {
  border-bottom-style: dashed;
}

.pitch-pattern {
  color: var(--ink);
}

.pitch-examples,
.pitch-sr-list {
  display: flex;
  flex-wrap: wrap;
  gap: .65rem 1rem;
}

/* One 3-col mini-grid: case labels down the side, one column per word. */
.pitch-paradigm-row {
  grid-template-columns: minmax(4.2rem, .55fr) repeat(2, minmax(0, 1fr));
  gap: .8rem;
}

.pitch-paradigm-words { border-bottom: 1px solid var(--hairline); }

.pitch-paradigm-head {
  display: inline-flex;
  align-items: baseline;
  gap: .45rem;
  flex-wrap: wrap;
}

.pitch-paradigm-head .chart-form { color: var(--ink); }

/* One numbered-advice row, shared by Learner priority and Reading order: rank
   badge in an auto column, text in the second. Reading order used to reuse
   .chart-pair, whose 5.8rem paradigm-label column is sized for "NOM SG", not
   for a single digit — half the row went to the number. */
.pitch-advice-row {
  grid-template-columns: auto minmax(0, 1fr);
  align-items: baseline;
}

.pitch-advice-row h4 {
  display: flex;
  align-items: center;
  gap: .55rem;
  flex-wrap: wrap;
  margin: 0;
}

.pitch-advice-row p {
  margin: 0;
  grid-column: 2;
  font-size: var(--fs-body);
  line-height: var(--lh-prose);
  color: var(--ink-muted);
}

.pitch-rank {
  color: var(--paper);
  background: var(--ink);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 2rem;
  block-size: 2rem;
  font-feature-settings: "tnum";
}

.pitch-advice-list {
  list-style: none;
  padding: 0;
  margin: 0;
}

/* -----------------------------------------------------------
   Prepositions
   ----------------------------------------------------------- */

/* The lemma is a compact row header over its uses — one column, because each
   use already spends a column on its own icon. */
.prep-row {
  gap: .5rem;
}

/* The dot is the case marker: its hue comes from the cell's own data-tone
   (chart) or the card use it sits in — never a second case→hue map. */
.prep-icon-cell {
  display: block;
  --prep-dot: var(--tone, var(--ink-soft));
}

.prep-icon {
  width: 4.4rem;
  height: auto;
  color: var(--ink-muted);
  overflow: visible;
}

.prep-icon-object,
.prep-icon-line,
.prep-icon-dash {
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  vector-effect: non-scaling-stroke;
}

.prep-icon-dash {
  stroke-dasharray: 3 4;
}

.prep-icon-dot {
  fill: var(--prep-dot);
  stroke: var(--paper);
  stroke-width: 2;
  vector-effect: non-scaling-stroke;
}

.prep-icon-arrow {
  fill: none;
  stroke: var(--ink);
  stroke-width: 3;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}

/* The row name stays neutral ink — a dual-case prep (pod/pred/nad…) carries one
   row tone, so colouring the name would read as a single phantom case. Case
   colour lives on the per-use icon dots and chips instead. */
.prep-name {
  font-family: var(--ff-display);
  font-size: var(--fs-head);
  font-weight: 400;
  line-height: 1;
  color: var(--ink);
}

.prep-uses {
  display: grid;
}

/* Shared by the chart row and the popover card: icon | chip + meaning +
   example. The icon column is fixed so every use in a group aligns. */
.prep-use {
  display: grid;
  grid-template-columns: 4.4rem minmax(0, 1fr);
  align-items: start;
  column-gap: .9rem;
  padding-top: .85rem;
  border-top: 1px dashed var(--hairline-soft);
}

.prep-use:first-child {
  padding-top: 0;
  border-top: 0;
}

.prep-use .prep-icon-cell {
  padding-top: .1rem;
}

.prep-use-text {
  display: grid;
  gap: .35rem;
  min-width: 0;
}

.prep-use-head {
  display: flex;
  align-items: baseline;
  gap: .55rem;
  flex-wrap: wrap;
}

.prep-case {
  display: inline-flex;
  align-items: center;
  color: var(--tone, var(--ink-soft));
  background: color-mix(in oklab, var(--tone, var(--ink-soft)) 12%, transparent);
  padding: .36rem .52rem .34rem;
}

.prep-meaning {
  font-family: var(--ff-body);
  font-size: var(--fs-caption);
  font-weight: 400;
  line-height: var(--lh-snug);
  color: var(--ink-muted);
}

/* Inline preposition trigger — a clickable token in a case's prep list that
   opens the shared preposition card. Keeps the list's case tone; a dashed
   underline signals it's live, strengthening on hover / while open. */
.prep-trigger {
  font: inherit;
  color: inherit;
  cursor: pointer;
  background: none;
  border: 0;
  /* Vertical padding grows the tap target to ≥24px (WCAG 2.5.8); the equal
     negative block-margin cancels the added height so line flow is unchanged. */
  display: inline-block;
  padding: .35em .06em;
  margin-block: -.35em;
  border-radius: 3px;
  text-decoration: underline dashed color-mix(in oklab, currentColor 40%, transparent);
  text-underline-offset: .22em;
  text-decoration-thickness: 1px;
  transition: background .15s, text-decoration-color .15s;
}
.prep-trigger:hover,
.prep-trigger[aria-expanded="true"] {
  background: color-mix(in oklab, var(--tone, var(--accent)) 12%, transparent);
  text-decoration-color: currentColor;
}

/* Preposition card — the shared popover's prep variant. One entry per lemma;
   every use stacked and tinted by its own case (gen/dat/aku/ins/lok). */
/* Widen the shell itself (not just the card) so position()'s clamp — which
   measures the .tip-pop wrapper — keeps the card on-screen near an edge. */
.prep-pop { width: min(22.5rem, calc(100vw - 24px)); }
.prep-pop .tip-pop-card {
  max-height: min(72vh, 540px);
  overflow-y: auto;
}
.prep-card { display: grid; gap: .9rem; }
.prep-card-name {
  font-family: var(--ff-display);
  font-weight: 400;
  font-size: var(--fs-head);
  line-height: 1;
  color: var(--ink);
}
/* The card's uses ARE .prep-use rows — same grid as the chart, no second
   per-use layout to keep in sync. */
.prep-card-uses { display: grid; }

/* -----------------------------------------------------------
   False friends
   ----------------------------------------------------------- */

/* Headword and its Russian meaning share one baseline row — the serif
   specimen against the sans gloss carries the axis, so the entry needs no
   per-cell labels. */
.false-head {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: .25rem .7rem;
}

.false-word {
  font-family: var(--ff-display);
  font-size: var(--fs-head);
  font-weight: 400;
  line-height: 1;
  letter-spacing: var(--track-display);
  color: var(--ink);
}

.false-means {
  font-size: var(--fs-lead);
  line-height: var(--lh-snug);
}

.false-trap {
  font-size: var(--fs-body);
  line-height: var(--lh-prose);
  display: flex;
  align-items: baseline;
  gap: .45rem .55rem;
  flex-wrap: wrap;
  color: var(--ink-muted);
}

.false-not {
  display: inline-flex;
  align-items: center;
  color: var(--ink);
  background: var(--paper-mark);
  padding: .34rem .48rem .32rem;
}

/* The Russian look-alike word is language-as-object — specimen voice.
   Its gloss (<small>) stays in the sans apparatus voice. */
.false-trap > span:not(.false-not) {
  font-family: var(--ff-display);
  font-size: var(--fs-lead);
  line-height: var(--lh-snug);
  color: var(--ink);
}
.false-trap small {
  flex-basis: 100%;
  font-size: var(--fs-caption);
  line-height: var(--lh-snug);
  color: var(--ink-muted);
}

/* Cross-document transitions, native — no client router, no framework. A
   cheat-sheet site is flipped between, and the flip should not flash white. */
@view-transition { navigation: auto; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    transition-duration: .01ms !important;
  }
  /* The blanket rule above does not reach the view-transition pseudos, which
     animate on their own timeline. Turn the navigation animation off outright
     rather than making it very fast. */
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) {
    animation: none !important;
  }
}

/* -----------------------------------------------------------
   Forced colors (Windows High Contrast Mode)

   The OS swaps every author color for a small system palette, so two
   colour-only codes lose their signal: the alphabet's solid-vs-dashed
   badge (both cyr/lat share one border color) and the six case hues
   (all --tone accents map to one system color). We restore each with a
   channel forced-colors keeps.
   ----------------------------------------------------------- */
@media (forced-colors: active) {
  /* Alphabet badge. The solid (unique "SR") vs dashed (diff "!=")
     border-STYLE survives HCM untouched — only the color is swapped —
     so the two categories stay distinct on style + glyph alone. Pin the
     styles explicitly (defensive) and paint with a system color so the
     badge outline never drops to a value HCM would render invisibly. */
  .letter::after { border-color: CanvasText; }
  .letter[data-kind="unique"]::after { border-style: solid; }
  .letter[data-kind="diff"]::after   { border-style: dashed; }

  /* Case tones. The per-case accent lives in two decorative 3px marker
     bars — .case-strip-cell::before (nav) and .case-row::before (row).
     These are the pure colour code; opt them out of the forced-colors
     override so the six hues (and NOM's neutral --ink-soft) stay apart.
     Scoped to these tiny decorative bars only — text keeps system colors
     for legibility, and the NOM/GEN/… abbreviations already label each
     case, so meaning is never on color alone. */
  .case-strip-cell::before,
  .case-row::before {
    forced-color-adjust: none;
  }
}

/* -----------------------------------------------------------
   Utilities
   ----------------------------------------------------------- */

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