/* Edubba — shared stylesheet (wave 1: text-pure, no JS).
   Identity: unfired clay + terracotta, serif text, real script glyphs
   via vendored subset fonts (regenerate with `rake fonts`). */

/* Noto Sans Cuneiform, subset to the codepoints the site uses
   (site/assets/fonts/cuneiform-coverage.txt is the gate-checked
   manifest). OFL 1.1 — license alongside the font file. */
@font-face {
  font-family: "Noto Sans Cuneiform";
  src: url("fonts/NotoSansCuneiform-subset.ttf") format("truetype");
  font-display: swap;
  unicode-range: U+12000-1254F;
}

/* Noto Sans Egyptian Hieroglyphs, same subset pipeline
   (hieroglyphs-coverage.txt is the gate-checked manifest). */
@font-face {
  font-family: "Noto Sans Egyptian Hieroglyphs";
  src: url("fonts/NotoSansEgyptianHieroglyphs-subset.ttf") format("truetype");
  font-display: swap;
  unicode-range: U+13000-1342F;
}

/* Noto Serif TC — traditional character forms (sinographs rulebook
   §4), same subset pipeline (sinographs-coverage.txt is the
   gate-checked manifest). */
@font-face {
  font-family: "Noto Serif TC";
  src: url("fonts/NotoSerifTC-subset.otf") format("opentype");
  font-display: swap;
  unicode-range: U+3400-4DBF, U+4E00-9FFF, U+F900-FAFF, U+20000-2EBEF, U+2F800-2FA1F, U+30000-323AF;
}

:root {
  --bg: #faf8f4;        /* unfired clay, light */
  --ink: #26211c;
  --muted: #6b6257;
  --accent: #8a4b2d;    /* terracotta (site default) */
  --rule: #e0d9cd;
  --measure: 44rem;
  /* Per-school accents (school layouts set --accent to one of these) */
  --accent-cuneiform: #8a4b2d;   /* terracotta — clay and reed */
  --accent-hieroglyphs: #1f5f8b; /* lapis — faience and Nile */
  --accent-sinographs: #a83232;       /* cinnabar — seal ink */
  --logogram: #2f6b33;           /* reed green — logogram voice-marking */
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #1d1a17;
    --ink: #e8e2d8;
    --muted: #a49a8c;
    --accent: #d08a5f;
    --rule: #3a342d;
    --accent-cuneiform: #d08a5f;
    --accent-hieroglyphs: #6fa8d0;
    --accent-sinographs: #d76c6c;
    --logogram: #8fbb7a;
  }
}

/* Native-script text: the unicode-range font-face applies wherever
   these glyphs occur; this class adds sizing safe for dense signs. */
.script, .wordmark-glyphs {
  font-family: "Noto Sans Cuneiform", "Noto Sans Egyptian Hieroglyphs", "Noto Serif TC", Georgia, serif;
  font-style: normal;
}

/* Size law (sinographs rulebook §6, ruled 2026-08-10): characters
   display bigger than cuneiform/Egyptian script everywhere — Han
   strokes are hard to make out at the other scripts' sizes. Scoped
   to INLINE script runs (children of prose containers): elements
   that carry .script themselves (sign-hero, sign-strip, sign-cell,
   SVG groups) keep their own explicit, law-satisfying sizes. */
body.school-sinographs :where(p, li, td, th, dd, dt, figcaption) > :where(.script) { font-size: 1.35em; }

/* Explicit sinograph script contexts — each exceeds its cuneiform
   counterpart (registered in StyleGuardTest::SINO_CONTEXTS). */
.school-sinographs .sign-cell { font-size: 2.6rem; }
.school-sinographs .reading--script .script { font-size: 1.9rem; }
.school-sinographs .sign-hero { font-size: 7.5rem; }
.school-sinographs .sign-strip { font-size: 3.2rem; }

/* Vendored audio samples (sinographs rulebook §2): browser-native
   controls, no JS. Kept compact so a "Hear" column fits a table. */
audio { width: 11rem; height: 2.1rem; vertical-align: middle; }

/* D17-a (owner-ruled 2026-08-11): click the reading, hear it.
   a.say plays its mp3 inline via the one sanctioned script
   (assets/say.js); without JS the link opens the audio file. The
   dotted underline is the whole affordance. */
a.say { text-decoration: none; color: inherit; }
a.say .translit { border-bottom: 1px dotted var(--accent); }
a.say:hover .translit { border-bottom-style: solid; }

/* Sinograph readings ALWAYS stack (rulebook §6): at the size-law
   scale even short classical clauses leave the three-column grid
   no honest room for a gloss — the measured 13em budget still
   clipped in practice (owner report 2026-08-10). Script over
   voice over gloss, full measure each. */
.school-sinographs .reading--script .reading-lines { display: block; }
.school-sinographs .reading--script .reading-line { display: block; padding-block: 0.5rem; }
.school-sinographs .reading--script .reading-line > span { display: block; }

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 400 1.05rem/1.65 Georgia, "Times New Roman", serif;
}

.site-header, main, .site-footer {
  max-width: var(--measure);
  margin-inline: auto;
  padding-inline: 1.25rem;
}

.site-header {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.25rem 0.75rem;
  padding-block: 1.25rem 0.75rem;
  border-bottom: 1px solid var(--rule);
}

.wordmark {
  text-decoration: none;
  color: var(--ink);
  display: inline-flex;
  align-items: baseline;
  gap: 0.5rem;
}

.wordmark-glyphs { color: var(--accent); }

.wordmark-name {
  font-size: 1.35rem;
  font-weight: 700;
  letter-spacing: 0.02em;
}

.site-tagline { color: var(--muted); font-style: italic; }

main { padding-block: 1.5rem 3rem; }

h1, h2, h3 { line-height: 1.25; }
h1 { font-size: 1.9rem; }

a { color: var(--accent); }
a:hover { text-decoration-thickness: 2px; }

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

.site-footer {
  border-top: 1px solid var(--rule);
  padding-block: 1rem 2rem;
  color: var(--muted);
  font-size: 0.9rem;
}

/* --- Landing: school grid --- */

.school-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
  gap: 1rem;
  margin-block: 1.5rem;
}

.school-card {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  padding: 1rem 1.1rem;
  border: 1px solid var(--rule);
  border-top: 3px solid var(--card-accent, var(--accent));
  border-radius: 0 0 4px 4px;
  text-decoration: none;
  color: var(--ink);
}

.school-card:hover strong { text-decoration: underline; }
.school-card strong { font-size: 1.1rem; }

.school-glyph {
  font-size: 2rem;
  line-height: 1.1;
  color: var(--card-accent, var(--accent));
}

.school-note {
  color: var(--muted);
  font-size: 0.9rem;
  line-height: 1.45;
}

.accent-cuneiform   { --card-accent: var(--accent-cuneiform); }
.accent-hieroglyphs { --card-accent: var(--accent-hieroglyphs); }
.accent-sinographs       { --card-accent: var(--accent-sinographs); }

/* --- Landing: family tree (nested lists, readable in any browser) --- */

.tree, .tree ul {
  list-style: none;
  padding-left: 1.1rem;
  border-left: 2px solid var(--rule);
}

.tree { border-left: none; padding-left: 0; }

.tree li {
  margin-block: 0.6rem;
  position: relative;
}

.tree ul li::before {
  content: "";
  position: absolute;
  left: -1.1rem;
  top: 0.7em;
  width: 0.7rem;
  border-top: 2px solid var(--rule);
}

/* --- Sign composition / glyph exhibit figures --- */

.composition { margin: 1.5rem 0; text-align: center; }

.composition-row {
  font-size: 3rem;
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 1.2rem;
  color: var(--accent);
  margin: 0.5rem 0;
}

.composition-row .op {
  color: var(--muted);
  font-family: Georgia, serif;
  font-size: 1.6rem;
}

.composition .citation { text-align: left; }

.glyph-exhibit {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 2rem;
  margin: 1.5rem 0;
}

.glyph-exhibit figure { margin: 0; text-align: center; }
.glyph-exhibit .script { font-size: 4.5rem; color: var(--accent); line-height: 1.2; }
.glyph-exhibit figcaption { color: var(--muted); font-size: 0.85rem; }

/* --- Sign-evolution figures --- */

.evolution { margin: 1.5rem 0; }
.evolution svg { width: 100%; height: auto; color: var(--ink); }

/* --- Course TOC --- */

.course-toc { padding-left: 1.5rem; }
.course-toc li { margin-block: 0.5rem; }
.course-toc em { color: var(--muted); }

.sign-strip {
  font-size: 2.6rem;
  color: var(--accent);
  letter-spacing: 0.1em;
  margin-block: 1.2rem;
}

/* --- Course chapters: sidebar shell --- */

.chapter-shell { display: block; }

.chapter-kicker {
  color: var(--accent);
  font-size: 0.8rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  margin: 0 0 -0.5rem;
}

.course-sidebar-school {
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--accent);
  margin: 1.1rem 0 0.45rem;
  border-bottom: 1px solid var(--rule);
  padding-bottom: 0.3rem;
}
.course-sidebar-school-details:first-child .course-sidebar-school { margin-top: 0; }
.course-sidebar-school { cursor: pointer; }
.course-sidebar-school a { color: inherit; text-decoration: none; }
.course-sidebar-school a:hover { text-decoration: underline; }

.course-sidebar-title {
  font-size: 0.8rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  cursor: pointer;
  color: var(--muted);
  margin: 0 0 0.6rem 0.5rem;
}

.course-sidebar-title a { color: inherit; text-decoration: none; }
.course-sidebar-title a:hover { color: var(--accent); }

.course-sidebar-list {
  list-style: none;
  margin: 0;
  padding: 0;
  font-size: 0.88rem;
  line-height: 1.4;
}

.course-sidebar-list li { margin: 0; }

.course-sidebar-list a,
.course-sidebar-list .current {
  display: flex;
  gap: 0.6rem;
  padding: 0.35rem 0.6rem;
  border-radius: 4px;
  text-decoration: none;
  color: var(--ink);
}

.course-sidebar-list a:hover { background: var(--rule); }

.course-sidebar-list .current {
  background: var(--accent);
  color: var(--bg);
  font-weight: 600;
}

.course-sidebar-list .ch-no {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 0.8rem;
  color: var(--accent);
  min-width: 1.6em;
  padding-top: 0.1em;
}

.course-sidebar-list .current .ch-no { color: var(--bg); }

@media (min-width: 1100px) {
  .chapter-shell {
    display: grid;
    grid-template-columns: 15rem minmax(0, 1fr);
    gap: 2.5rem;
    align-items: start;
  }
  .course-sidebar {
    position: sticky;
    top: 1.5rem;
    border-right: 1px solid var(--rule);
    padding-right: 1.25rem;
    /* The course list outgrew the viewport (owner report
       2026-08-11: wheel over the sidebar scrolled the chapter):
       a sticky element with no scroll viewport of its own passes
       wheel events to the page. Cap it and let it scroll itself;
       when it fits, auto does nothing and the wheel falls through
       as before. No sign-links live here (nav text only) — the
       style guard carries it in NO_TIP_CONTAINERS. */
    max-height: calc(100vh - 3rem);
    overflow-y: auto;
    scrollbar-width: thin;
  }
  .course-sidebar-details summary,
  .course-sidebar-school-details summary { list-style: none; }
  .course-sidebar-details summary::-webkit-details-marker,
  .course-sidebar-school-details summary::-webkit-details-marker { display: none; }
}

@media (max-width: 1099.9px) {
  .course-sidebar {
    border: 1px solid var(--rule);
    border-radius: 4px;
    padding: 0.6rem 0.9rem;
    margin-bottom: 1.25rem;
  }
  .course-sidebar-details:not([open]) .course-sidebar-title { margin-bottom: 0; }
}

/* On wide screens the chapter column needs more room than --measure */
@media (min-width: 1100px) {
  body:has(.chapter-shell) .site-header,
  body:has(.chapter-shell) main,
  body:has(.chapter-shell) .site-footer {
    max-width: 62rem;
  }
}

.chapter-nav {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0.25rem 1rem;
  font-size: 0.9rem;
  color: var(--muted);
  border-bottom: 1px solid var(--rule);
  padding-block: 0.5rem;
}

.chapter-nav-bottom {
  border-bottom: none;
  border-top: 1px solid var(--rule);
  margin-top: 2.5rem;
}

/* Footnotes render below the bottom navigation line (owner rule):
   kramdown emits .footnotes inside the content stream, so the
   chapter column is a flex stack and the footnotes are ordered last. */
.chapter-main { display: flex; flex-direction: column; }
.chapter-main > * { order: 0; }
.chapter-main > .chapter-nav-bottom { order: 1; }
.chapter-main > .footnotes {
  order: 2;
  border: none;
  color: var(--muted);
  font-size: 0.85rem;
  margin-top: 0.75rem;
}
.chapter-main > .footnotes hr { display: none; }

.course-sidebar-other {
  margin: 0 0 0.6rem 0.5rem;
  opacity: 0.85;
}

.course-sidebar-current { margin-top: 0.2rem; }

.chapter-nav-steps { display: inline-flex; gap: 1rem; }

.chapter-standfirst {
  color: var(--muted);
  border-left: 3px solid var(--accent);
  padding-left: 0.9rem;
}

.sign-table {
  border-collapse: collapse;
  width: 100%;
  /* The declared grid IS the layout (table-balance law, owner
     ruling 2026-08-11): fixed layout makes every column's width
     computable, so the table-balance lint can enforce that no
     single column drives the table's height. Below min-width the
     wrapper scrolls instead of crushing the columns. */
  table-layout: fixed;
  min-width: 38rem;
  margin: 0 0 1rem;
}
.sign-table td, .sign-table th { overflow-wrap: break-word; }

.sign-table th, .sign-table td {
  text-align: left;
  padding: 0.5rem 0.75rem;
  border-bottom: 1px solid var(--rule);
  vertical-align: baseline;
}

.sign-table th {
  color: var(--muted);
  font-size: 0.85rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.sign-cell { font-size: 2rem; color: var(--accent); }
.sign-cell a { text-decoration: none; color: inherit; }
.sign-cell a:hover { text-decoration: underline dotted; text-underline-offset: 0.2em; }

/* The declared column grid (table-balance law, owner ruling
   2026-08-11: a HARD rule): every fixed-layout sign table carries
   its computed per-table <colgroup> (script/table_wrap.rb from
   script/table_balance.rb) — the colgroup IS the layout. Cell
   width rules on the header row would OVERRIDE the colgroup in
   fixed layout (measured in Chrome, phase-22 surface review: the
   old 50%/18% fallbacks silently beat the computed grid and
   crushed the label columns), so fixed tables carry none. Tables
   whose last column is short (references, shelf indexes) opt out
   with sign-table--tail-fit and keep auto layout (rules below). */
/* Narrow screens: a wide table scrolls inside its render-time
   wrapper (div.table-scroll, added by script/table_wrap.rb),
   never bleeding past the page edge. The wrapper — not the
   table — is the scroll container, so the table keeps its real
   fixed-layout grid. A scroll container CLIPS: overflow-x forces
   the other axis to clip too (CSS spec), so a hover bubble can
   never escape the box. Every scroll container hosting
   sign-links therefore reserves bubble headroom above its first
   line — padding pulled back by an equal negative margin, so the
   clip box grows while the layout stays put — and pins its
   bubbles to the glyph's left edge (see the .sign-tip section).
   Owner report 2026-08-09: half-invisible tooltip; right rim
   2026-08-11. test/style_guard_test.rb enforces the pairing for
   every overflow rule in this sheet. */
.table-scroll {
  overflow-x: auto;
  padding-top: 5.5rem;
  margin-top: calc(1rem - 5.5rem);   /* table's old 1rem top gap, pulled back */
  padding-right: 14rem;
  margin-right: -14rem;
}
/* Non-sign tables that borrow the styling (the pinyin primer's
   phonetics grids — no glyph column, their own proportions) opt
   out of the fixed grid and the balance lint with --even. */
.sign-table--even { table-layout: auto; min-width: 0; }
.sign-table--even th:last-child, .sign-table--even td:last-child { width: auto; }
.sign-table--even th:nth-last-child(2),
.sign-table--even td:nth-last-child(2) { width: auto; }
.sign-table--tail-fit { table-layout: auto; min-width: 0; }
.sign-table--tail-fit th:last-child,
.sign-table--tail-fit td:last-child { width: auto; white-space: nowrap; }
.sign-facts td:last-child { width: auto; }

/* --- Spiral warm-up (Stage C retrieval panels) --- */
.warmup {
  margin: 1.25rem 0 2rem;
  border: 1px solid var(--rule);
  border-left: 3px solid var(--accent);
  border-radius: 4px;
  padding: 0.6rem 0.9rem;
}
.warmup > summary {
  cursor: pointer;
  color: var(--muted);
  font-size: 0.9rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.warmup-list { margin: 0.75rem 0 0.25rem; padding-left: 1.4rem; }
.warmup-list li { margin: 0.5rem 0; }
.warmup-list summary { cursor: pointer; }
.warmup-list .script { font-size: 1.6rem; color: var(--accent); }
.warmup-answer { margin: 0.4rem 0 0.2rem 1rem; color: var(--muted); }
.warmup-answer .script { font-size: 1.8rem; }

/* --- Drill shelves --- */
.drill-list { list-style: none; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr)); gap: 0.6rem; }
.drill-card { border: 1px solid var(--rule); border-radius: 4px; padding: 0.55rem 0.8rem; }
.drill-card summary { cursor: pointer; }
.drill-card .script { font-size: 1.7rem; color: var(--accent); }
.drill-contrasts { list-style: none; padding: 0; }
.drill-contrast-row { display: flex; flex-wrap: wrap; gap: 0.6rem; margin: 0.6rem 0; }
.drill-contrast-cell {
  border: 1px solid var(--rule); border-radius: 4px;
  padding: 0.4rem 0.9rem; text-decoration: none; color: inherit;
}
.drill-contrast-cell:hover { border-color: var(--accent); }
.drill-contrast-cell .script { font-size: 1.9rem; color: var(--accent); }

/* The deal — cuts of the deck; :visited fades tiles already worked
   (the only per-reader state the site keeps, and the browser keeps
   it for us). Today's featured cut wears the thicker border, which
   a :visited rule cannot unset. */
.deal-row { display: flex; flex-wrap: wrap; gap: 0.6rem; margin: 1rem 0 1.5rem; }
a.deal-tile {
  display: flex; flex-direction: column; align-items: center;
  min-width: 3.4rem; padding: 0.5rem 0.6rem 0.35rem;
  border: 1px solid var(--rule); border-radius: 4px;
  text-decoration: none; color: var(--accent);
}
a.deal-tile .script { font-size: 1.9rem; color: currentColor; }
.deal-tile-n { font-size: 0.75rem; color: currentColor; opacity: 0.75; }
a.deal-tile:hover { border-color: var(--accent); }
a.deal-tile:visited { color: #9b9189; border-color: #d8d2cb; }
.deal-tile--today { border-width: 2px; }
.deal-next { margin-top: 1.5rem; }
@media (prefers-color-scheme: dark) {
  a.deal-tile:visited { color: #7d766f; border-color: #4a453f; }
}

@media print {
  .course-sidebar, .site-header, .site-footer, .chapter-nav, .warmup { display: none; }
  .drill-card { break-inside: avoid; border: 1px dashed #999; }
  .drill-list { grid-template-columns: repeat(3, 1fr); }
  .drill-card details > *:not(summary) { display: none; }
  .deal-row, .deal-next { display: none; }
}

/* --- Sign Codex pages (Addenda Signs shelves) --- */
.sign-hero {
  font-size: 6.5rem;
  line-height: 1.15;
  color: var(--accent);
  text-align: center;
  margin: 1.5rem 0 0;
}
.sign-page h1 { text-align: center; margin-top: 0.25rem; }
.sign-facts { max-width: 36rem; margin-inline: auto; }
.sign-facts th { width: 7rem; }

.reading {
  margin: 1.5rem 0;
  border: 1px solid var(--rule);
  border-left: 3px solid var(--accent);
  border-radius: 0 4px 4px 0;
  padding: 1rem 1.25rem;
}

.reading-line {
  display: grid;
  grid-template-columns: minmax(12rem, 1fr) 1fr;
  gap: 0.35rem 1.5rem;
  padding-block: 0.2rem;
}

/* One tablet line is ONE visual line of script (rulebook §5):
   the script column takes its content's width and never wraps;
   a long line scrolls inside the figure, never folding into
   false extra lines beside an unwrapped transliteration.
   The whole figure is ONE grid (lines contribute cells via
   display: contents), so the script column is sized by the
   widest line and translit/gloss align across all rows. */
/* Column math (the reading-width lint enforces it, script/lint.rb):
   measure 44rem − figure padding 2.5rem − border ≈ 41.3rem of
   content; minus 2×1rem gaps and the 8rem + 11rem text floors
   leaves 20.3rem for the script column — 14.5em at the 1.4rem
   script size. A figure whose widest line exceeds that budget
   must declare reading--stacked below — three columns may never
   cut text at the measure. */
.reading--script .reading-lines {
  display: grid;
  grid-template-columns: max-content minmax(8rem, 1.1fr) minmax(11rem, 1.4fr);
  gap: 0.4rem 1rem;
  align-items: baseline;
  overflow-x: auto;
  /* bubble headroom: a scroll container clips both axes (see the
     .sign-table comment) — grow the clip box, not the layout;
     the right rim gets the same reserve as the top */
  padding-top: 5.5rem;
  margin-top: -5.5rem;
  padding-right: 14rem;
  margin-right: -14rem;
}

/* Stacked variant for over-budget lines: the voice sits UNDER its
   script, both full width — text is never cut, and only a truly
   measure-wide script line ever scrolls (§5: inside the figure). */
.reading--stacked .reading-lines { display: block; }
.reading--stacked .reading-line { display: block; padding-block: 0.5rem; }
.reading--stacked .reading-line > span { display: block; }

.reading--script .reading-line { display: contents; }

/* Logogram voice-marking (cuneiform rulebook §9, ruled 2026-08-09):
   green binds a stretch of signs read as a whole word to the
   capitals that speak it — same class on the glyphs and on the
   voice, so the reader sees which signs break out of the
   syllabic sequence. Color inherits through sign-links. */
.logo { color: var(--logogram); }

.reading--script .script {
  font-size: 1.4rem;
  line-height: 1.3;
  white-space: nowrap;
}

@media (max-width: 480px) {
  .reading-line { grid-template-columns: 1fr; }
  .reading-line .gloss { padding-left: 1rem; }
}

/* Below the full measure the three-column budget can't hold:
   script readings stack (same guarantee as reading--stacked). */
@media (max-width: 44rem) {
  .reading--script .reading-lines { grid-template-columns: 1fr; }
}

/* Course pages carry their school's accent (landing cards already do) */
body.school-hieroglyphs { --accent: var(--accent-hieroglyphs); }
body.school-sinographs { --accent: var(--accent-sinographs); }

.translit { font-style: italic; }
/* Bound transcription (rulebook §9): its own register beside the
   hyphenated transliteration — italic too, but visually set off
   by a hair of letterspacing; hyphens vs macrons do the rest. */
.norm { font-style: italic; letter-spacing: 0.02em; }
/* transliteration indexes: rendered as real <sub> at build time */
sub { font-size: 0.72em; line-height: 0; }
.gloss { color: var(--muted); }

.citation {
  margin-top: 0.9rem;
  padding-top: 0.75rem;
  border-top: 1px dashed var(--rule);
  color: var(--muted);
  font-size: 0.85rem;
  line-height: 1.55;
}

.citation code { font-size: 0.85em; }

/* --- Sign links (every returning glyph links to its introduction) --- */

a.sign-link { text-decoration: none; color: inherit; position: relative; }
a.sign-link:hover { text-decoration: underline dotted; text-underline-offset: 0.2em; }

/* Hover bubble: sign name · readings · meaning (pure CSS, no JS).
   Hidden bubbles must take NO geometry: display, not visibility —
   a visibility-hidden bubble still contributes its box to a scroll
   container's scrollable width (phantom sideways scroll, owner
   report 2026-08-09). */
.sign-tip {
  display: none;
  position: absolute;
  left: 50%;
  bottom: calc(100% + 0.45em);
  transform: translateX(-50%);
  width: max-content;
  max-width: 16em;
  padding: 0.35em 0.65em;
  border: 1px solid var(--rule);
  border-radius: 0.35em;
  background: var(--bg);
  color: var(--ink);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.18);
  /* full typographic reset: bubbles must look identical no matter
     what display styling (size, spacing, mono) the host glyph sits in */
  font-family: Georgia, serif;
  font-size: 0.78rem;
  font-style: normal;
  font-weight: normal;
  letter-spacing: normal;
  word-spacing: normal;
  text-transform: none;
  text-indent: 0;
  line-height: 1.4;
  text-align: center;
  white-space: normal;
  opacity: 0;
  transition: opacity 0.12s ease-in 0.08s;
  pointer-events: none;
  z-index: 5;
}
a.sign-link:hover .sign-tip,
a.sign-link:focus-visible .sign-tip,
a.term:hover .sign-tip,
a.term:focus-visible .sign-tip {
  display: block;
  opacity: 1;
}
/* Fade-in across the display flip where supported; elsewhere the
   bubble simply appears (the 0.08s delay still guards sweeps). */
@starting-style {
  a.sign-link:hover .sign-tip,
  a.sign-link:focus-visible .sign-tip,
  a.term:hover .sign-tip,
  a.term:focus-visible .sign-tip { opacity: 0; }
}

/* Inside a scroll container the bubble may not cross the box's
   left rim: pin it to its glyph's left edge (headroom above is
   reserved by the container — see the .sign-table comment). */
.sign-table .sign-tip,
.reading--script .sign-tip {
  left: 0;
  transform: none;
  text-align: left;
}
/* …and the right rim is the mirror (owner report 2026-08-11: a
   last-column bubble cut in half): a glyph in the LAST column
   extends its bubble across the container's right rim — pin those
   to the glyph's right edge instead, growing leftward into the
   wide row. */
.sign-table td:last-child .sign-tip {
  left: auto;
  right: 0;
}

/* Glossary terms: dotted underline, bubble on hover, link to /terms/ */
a.term {
  position: relative;
  color: inherit;
  text-decoration: underline dotted;
  text-decoration-color: var(--muted);
  text-underline-offset: 0.2em;
  cursor: help;
}
a.term:hover { text-decoration-color: var(--accent); }

/* Cited Nabu URNs link to their axis desk; keep the code look */
a.urn-link { text-decoration: none; }
a.urn-link:hover code { color: var(--accent); }

/* Glossary page */
.terms-list dt { font-weight: 700; margin-top: 0.9rem; }
.terms-list dd { margin: 0.15rem 0 0 1.25rem; color: var(--ink); }

/* Long sign strings may wrap (grid columns stay intact); runs that
   must never split — cartouche + contents — are marked .nobr */
.script .nobr { white-space: nowrap; }

/* --- Read it cold --- */
.cold-read { margin-top: 2.5rem; }
.cold-read-check { margin: 0.75rem 0; }
.cold-read-check > summary { cursor: pointer; color: var(--muted); }
