/* Shared styling for the StudyDict-style entry renderer (see dictEntry.js).
   Used by StudyDict.html (its own page) and index.html (inline dictionary
   results for short Translate queries — see runShortLookup() there).

   Deliberately does NOT include .output-section / .output-label /
   .output-text / .output-text.loading / .spinner — every page that loads
   this file already defines those itself (byte-identical across index.html,
   grammar.html, studytranslation.html and StudyDict.html), so redeclaring
   them here would just be a second copy to keep in sync for no benefit.
   This file only holds the classes that are unique to a rendered dictionary
   entry. Requires the same --bg/--surface/--border/--red/--gold/--text/
   --muted/--text-soft custom properties every one of those pages already
   defines in :root. */

.output-label.provenance {
  text-align: center;
  margin: 0 auto 0.9rem;
}

.result-headword {
  font-family: 'Noto Serif SC', serif;
  font-size: 2.4rem;
  color: var(--gold);
  text-align: center;
  margin-bottom: 1rem;
}

/* ── Per-character usage gauges (classical/modern; written/spoken;
   single/multiple) ── All three render as the same fuel-gauge-style
   dial (see dictEntry.js's renderDialGauge): needle pivots at bottom-
   center and swings from the left pole up through the top to the right
   pole. Single-hue treatment throughout (gold needle/score against a
   muted track) — each is one measure's position on its own scale, not
   two identities to distinguish. Only ever present for a single-
   character headword; see dictEntry.js's isSingleHanChar / renderGauge.
   Row appears right below the headword (2026-08, was above it — the
   search word itself should confirm the lookup landed before anything
   supplementary does) — not a footnote further down under the entry
   either. Fixed 2-column grid (2026-08, was flex-wrap) rather than
   wrapping incidentally based on viewport width — renderGauge's push
   order is deliberately the same order this grid lays out row-major, so
   it reads as up to three rows of two. Era/Formality lead (2026-08-19,
   moved up from last — user call: these two are meant to be the headline
   signal, and always render, real score or an N/A placeholder, never
   omitted the way every gauge below them can be), then the two
   frequency-derived Prominence dials, then the two Modern-Usage frequency
   sub-gauges. A partially-scored headword (fewer than 6 dials — anything
   but Era/Formality can be missing) just leaves a trailing grid cell
   empty rather than re-flowing. */
.char-gauge-row {
  display: grid;
  grid-template-columns: repeat(2, minmax(200px, 230px));
  justify-content: center;
  gap: 1.1rem 1.3rem;
  margin: 0 auto 1.6rem;
  max-width: 780px;
}
@media (max-width: 480px) {
  .char-gauge-row { grid-template-columns: minmax(0, 230px); }
}
.gauge-block {
  position: relative;
  outline: none; /* focusable (tabindex, for the tooltip below) but not for a visible focus ring — the dial itself is the visual target */
}
/* Era/Formality's "not yet scored" placeholder state (2026-08-19) — dimmed
   so an N/A dial with its needle parked dead-center is never mistaken for
   a real "Balanced" (0) verdict; the needle/pivot/score-text/caption all
   share this one opacity rather than needing per-element overrides. */
.gauge-block-na {
  opacity: 0.45;
}
.gauge-head {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-bottom: 0;
  font-family: 'IM Fell English', serif;
}
.gauge-title {
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-soft, var(--muted));
}
/* Second, dimmer line under the title — currently just Written/Spoken and
   Single/Multiple's "(Modern Usage)" qualifier (see renderDialGauge). */
.gauge-subtitle {
  font-size: 0.6rem;
  letter-spacing: 0.06em;
  color: var(--text-soft, var(--muted));
  opacity: 0.7;
}
/* Deliberately terse — one or two words ("Leans Modern", "Balanced").
   The raw score, methodology, and (for Single/Multiple) the compound-word
   breakdown all live in .gauge-tooltip instead, on hover/focus, rather
   than permanently taking up on-screen space. */
.gauge-caption {
  margin-top: 0.3rem;
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--gold);
  text-align: center;
}

/* Hidden by default; revealed by hovering (or, since .gauge-block carries
   tabindex="0", tabbing to) the gauge — cursor: help signals there's more
   here without cluttering the screen with it up front. Positioned to drop
   below the block; z-index keeps it above the entry content beneath. */
.gauge-tooltip {
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%) translateY(2px);
  z-index: 20;
  width: max-content;
  max-width: 230px;
  margin-top: 0.5rem;
  padding: 0.6rem 0.8rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 4px;
  font-size: 0.74rem;
  line-height: 1.5;
  text-align: center;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity 0.15s ease;
}
.gauge-block:hover,
.gauge-block:focus,
.gauge-block:focus-within {
  cursor: help;
}
.gauge-block:hover .gauge-tooltip,
.gauge-block:focus .gauge-tooltip,
.gauge-block:focus-within .gauge-tooltip {
  opacity: 1;
  visibility: visible;
}
.tooltip-stat {
  color: var(--gold);
  font-weight: 700;
  margin-bottom: 0.25rem;
}
.tooltip-note {
  /* Was var(--muted) — legible on the page's own background, but the
     tooltip's raised .surface panel plus its smaller 0.74rem type made
     that dim brownish tone hard to read. --text-soft is the lighter
     secondary tone already used for this kind of prose elsewhere in this
     file (dial-pole-label, sense-note, example .en, lex-note) — index.html
     was previously missing the variable itself (fixed alongside this), so
     the same var(--text-soft, var(--muted)) pattern now resolves to the
     brighter tone on every page that loads this stylesheet, not just
     StudyDict.html. */
  color: var(--text-soft, var(--muted));
}
/* Era/Formality's Chinese explanation line (2026-08-19 pilot) — same
   Chinese-alongside-English pairing treatment .sense-gloss-zh/.example .zh
   already use elsewhere in this file, just sized for the tooltip context
   it sits in (.tooltip-note's 0.74rem, not the entry body's larger type). */
.tooltip-note-zh {
  font-family: 'Noto Serif SC', serif;
  color: var(--gold);
  margin-top: 0.25rem;
}
/* The one-line AI-judged/pilot provenance note under Era/Formality's
   tooltip content — deliberately smaller and dimmer than .tooltip-note
   itself (not var(--text-soft), an even quieter tone), with a hairline
   rule above it, so it reads as a footnote about the *source* of the
   content above rather than more of the content itself. */
.tooltip-meta {
  margin-top: 0.4rem;
  padding-top: 0.35rem;
  border-top: 1px solid var(--border);
  font-size: 0.66rem;
  font-style: italic;
  opacity: 0.75;
}

.gauge-dial {
  display: block;
  width: 100%;
  /* Kept small on purpose (2026-08, was 0.2rem) — the viewBox crop above
     (renderDialGauge's "0 26 240 124") already did the heavy lifting of
     pulling the dial up under its title; this is just a hairline
     breathing gap, not the thing doing the visual work. */
  margin: 0.05rem auto 0;
}
.dial-track {
  fill: none;
  stroke: var(--border);
  stroke-width: 10;
  stroke-linecap: round;
}
.dial-tick {
  stroke: var(--border);
  stroke-width: 2;
}
.dial-needle {
  stroke: var(--gold);
  stroke-width: 3;
  stroke-linecap: round;
}
.dial-pivot {
  fill: var(--gold);
}
/* Just the decile (no "/10") — the dial itself, plus each gauge's
   Single/Multiple, Written/Spoken, Classical/Modern pole labels, already
   say what scale it's on. */
.dial-score {
  font-family: 'IM Fell English', serif;
  font-size: 1.5rem;
  font-weight: 700;
  fill: var(--gold);
}
.dial-pole-label {
  font-size: 0.65rem;
  letter-spacing: 0.03em;
  fill: var(--text-soft, var(--muted));
}
.dial-pole-zh {
  font-family: 'Noto Serif SC', serif;
}
.dial-pole-en {
  font-family: 'IM Fell English', serif;
}

/* ── Source selector (dictEntry.js's renderSourceSelector) — sits right
   under the gauges, before the provenance badge. Public since 2026-08-18
   (Phase 9 of plans/moedict-csld-integration/) — used to be dev-mode-only
   (StudyDict.html's ?d=1). Deliberately plain/utility-styled (small text,
   thin border, no gold accent) so it reads as a secondary control tucked
   under the entry, not competing with the entry's own content for
   attention. ── */
.source-select-row {
  display: flex;
  justify-content: center;
  align-items: baseline;
  gap: 0.5rem;
  font-family: 'IM Fell English', serif;
  font-size: 0.8rem;
  color: var(--muted);
  margin: 0 auto 0.9rem;
}
.source-select-row label { letter-spacing: 0.03em; }
.source-select {
  font-family: inherit;
  font-size: 0.85rem;
  color: var(--text-soft);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 0.2rem 0.4rem;
}
.source-select:hover, .source-select:focus { border-color: var(--red); outline: none; }

/* ── CC-CEDICT quick gloss (2026-08-20 — public; see dictEntry.js's
   renderCedictQuickGloss). Full mode (2026-09-15, owner call — "available
   but unobtrusive"): sits at the very BOTTOM of the left definition panel,
   after the sense list — a plain-language anchor line kept around for
   reference once the classical gloss note above (when present) and the
   entry itself have already been read, not competing with either for
   first attention. Condensed mode is different again — see renderEntry's
   condensedTopGloss: it's the top-of-card fallback there, shown only when
   there's no classical gloss to show instead. Deliberately small and
   plain regardless of placement — a dashed border and muted color, similar
   "supplementary aside, not part of the reviewed entry" language the
   Diagnostics box uses (StudyDict.html's #diagnosticsBox) — so it doesn't
   compete with the
   entry's own content for attention. ── */
.cedict-quick-gloss {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.15rem 0.5rem;
  font-family: 'IM Fell English', serif;
  font-size: 0.85rem;
  color: var(--text-soft, var(--muted));
  border: 1px dashed var(--border);
  border-radius: 4px;
  padding: 0.5rem 0.75rem;
  margin-bottom: 1rem;
}
/* One row per CC-CEDICT line (2026-09-12 — see renderCedictQuickGloss's
   own comment: a headword can have more than one). A `.cqg-lines` with a
   single `.cqg-line` child (the overwhelming common case) sits inline
   with the trailing `.cqg-tag` exactly as the old single-row layout did;
   a genuine multi-line headword stacks its extra readings underneath
   instead of losing them. */
.cedict-quick-gloss .cqg-lines {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}
.cedict-quick-gloss .cqg-line {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem;
}
.cedict-quick-gloss .cqg-tag {
  font-size: 0.65rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: 3px;
  padding: 0.05rem 0.35rem;
  align-self: flex-start;
}
/* "Reviewed" tag (2026-09-18) — flags a CC-CEDICT entry the
   cedict_classical_gloss job type has already checked and confirmed fine
   for a classical reader (needs_revision: false), so it doesn't look
   identical to a word nobody's run through that job yet. Gold accent
   (the same color .top-pinyin-line/.classical-gloss-note already use for
   "classical-reader-checked" content) rather than a new success color —
   this site's palette has no green/success token, and reusing gold keeps
   this reading as "part of the same review pass," not an unrelated status. */
.cedict-quick-gloss .cqg-tag.cqg-reviewed {
  color: var(--gold);
  border-color: var(--gold);
}
.cedict-quick-gloss .cqg-pinyin {
  font-style: italic;
  color: var(--muted);
}
.cedict-quick-gloss .cqg-gloss {
  color: var(--text);
}

/* ── Classical-gloss note (2026-09-14, admin/ai_jobs.py's
   cedict_classical_gloss job type) — a second, distinct supplementary line
   right below .cedict-quick-gloss: that box is a plain restatement of the
   entry above it, this one is "here's what a classical reader specifically
   needs that isn't in that entry at all." Solid gold left border (not
   .cedict-quick-gloss's dashed full border) so it reads as an addition/
   correction being flagged, not a passive aside — same --gold accent
   .top-pinyin-line already uses for "the classical reading," tying this
   content to that established meaning rather than introducing a new color
   for the same idea. Only ever rendered when the job type's own
   needs_revision is true (see renderClassicalGloss) — full mode keeps this
   small/quiet, same posture as .cedict-quick-gloss's own full-mode
   treatment. No pinyin header of its own (2026-09-15) — .top-pinyin-line
   above already shows the entry's full reading list once, in both modes;
   see renderClassicalGloss's own comment for why repeating it here read as
   real duplication on a genuinely polyphonic word. ── */
.classical-gloss-note {
  font-family: 'IM Fell English', serif;
  font-size: 0.85rem;
  color: var(--text-soft, var(--muted));
  border-left: 3px solid var(--gold);
  border-radius: 0 4px 4px 0;
  padding: 0.4rem 0.75rem;
  margin-bottom: 1rem;
}
.classical-gloss-note .cgn-gloss {
  color: var(--text);
}
.classical-gloss-note .cgn-note {
  margin-top: 0.25rem;
  font-style: italic;
  color: var(--muted);
  font-size: 0.8rem;
}
/* Inline per-sense reading tags (2026-09-15) — dictEntry.js's
   renderGlossWithPinyinTags wraps a parenthetical like "(bù)" or "(fǒu)"
   in .cgn-gloss/.cgn-note text with this span whenever it's confidently a
   pinyin reading (see that function's own accent-mark heuristic), so it
   reads as a reading tag rather than blending into an ordinary
   parenthetical aside sitting right next to it, e.g. "(standard preverbal
   negator)". Same italic/gold treatment as .cgn-pinyin, tying the two
   together as the same kind of information. */
.classical-gloss-note .cgn-inline-py {
  font-style: italic;
  color: var(--gold);
}

/* Condensed mode (2026-09-14, same "the flashcard reveal side leads with
   the answer" treatment .cedict-quick-gloss's own panel-compact override
   already established) — centered and stacked under the CC-CEDICT line
   rather than the small left-border-callout layout full mode uses. No tag,
   no pinyin header at all here (see renderClassicalGloss), so .cgn-gloss
   is the box's own entire content and gets the exact same prominent
   treatment .panel-compact .cqg-gloss uses (2026-09-14, owner request:
   "same size font as the CC-CEDICT gloss") — this reads as a continuation
   of that answer, not a smaller footnote below it. */
.panel-compact .classical-gloss-note {
  text-align: center;
  border-left: none;
  border-top: 1px solid var(--border);
  border-radius: 0;
  padding: 0.6rem 0 0;
  margin-bottom: 0.9rem;
}
/* Standalone (2026-09-15) — dictEntry.js passes this when the classical
   gloss wins over CC-CEDICT outright (no quick-gloss box above it in this
   render at all — see renderEntry's condensedTopGloss), not merely sitting
   below one. The base rule's border-top/padding-top read as "more of the
   answer above this line," which is wrong with nothing above it. */
.panel-compact .classical-gloss-note.cgn-standalone {
  border-top: none;
  padding-top: 0;
}
.panel-compact .classical-gloss-note .cgn-gloss {
  font-size: 1.9rem;
  font-weight: 700;
  font-style: normal;
  color: var(--text);
}

/* ── Prominent pinyin line (2026-09-11, owner request; unconditional in
   both modes since 2026-09-15 — dictEntry.js's renderTopPinyin, the very
   first thing in the panel, ahead of both the classical gloss note and the
   CC-CEDICT quick gloss) — deliberately much larger/bolder than
   .register-pinyin's own in-header reading (that header doesn't even
   render in condensed mode — see .register-header's own comment), since
   this is meant to be the one thing a quick flip (or a StudyDict lookup)
   checks first, and the ONLY place either mode shows the entry's full
   reading list — the classical-gloss-note deliberately doesn't repeat it
   (see that rule's own comment). Centered, not left-aligned like most of
   this page's own content, on purpose, so it reads as its own headline
   rather than another content line — full mode's headword above it
   (.result-headword) is centered the same way. ── */
.top-pinyin-line {
  text-align: center;
  font-family: 'IM Fell English', serif;
  font-size: 1.9rem;
  font-style: italic;
  font-weight: 700;
  color: var(--gold);
  letter-spacing: 0.04em;
  margin-bottom: 0.75rem;
}
.top-pinyin-line .pinyin-sep { font-size: 1.3rem; }

/* ── Condensed-mode "full entry" link (2026-09, srs-flashcards Phase 3) —
   dictEntry.js's renderEntry() emits this in place of the whole right-panel
   accordion when createDictEntryViewer was constructed with mode:'condensed'
   (the flashcard review page's reveal side). Same muted-at-rest/gold-on-
   hover convention as .accordion-count-link — this is the same kind of
   "here's more, if you want it" aside, just standing in for a whole section
   instead of one count. ── */
.condensed-full-link {
  margin-top: 0.75rem;
  text-align: right;
}
.condensed-full-link a {
  font-family: 'IM Fell English', serif;
  font-size: 0.8rem;
  letter-spacing: 0.03em;
  color: var(--muted);
  text-decoration: none;
  transition: color 0.2s;
}
.condensed-full-link a:hover, .condensed-full-link a:focus-visible {
  color: var(--gold);
  text-decoration: underline;
}
/* Second copy of the same link (2026-09-15, owner request), right after the
   Short Classical Gloss/CC-CEDICT box instead of at the very bottom — swaps
   the bottom-footer spacing above for a small gap under it instead, so it
   reads as a lead-in to the sense list rather than trailing whitespace. */
.condensed-full-link-top {
  margin-top: 0;
  margin-bottom: 0.75rem;
}

/* ── Compact layout (2026-09-11 follow-up, owner request — "we don't want
   as many blank or nearly blank lines... it should feel more like a
   flashcard, even on a small screen") — dictEntry.js's renderEntry adds
   `panel-compact` alongside `panel` on condensed mode's own wrapping div,
   so every rule below only ever touches a flashcard's reveal side (and the
   word-detail page, which shares the same mode) — full mode's own more
   spacious reading layout (StudyDict.html, the admin dashboard) keeps
   every one of these base rules completely untouched. Values here are
   overrides on top of the base rules defined throughout this file (.panel,
   .sense, .register-body + .register-body, .merged-sense + .merged-sense,
   etc.) — deliberately living together in one block instead of scattered
   next to each base rule, so "how condensed mode's spacing differs" reads
   as one coherent story rather than fragments spread across the file. ── */
/* Compound selector (not bare .panel-compact) so this reliably beats
   .panel's own line-height/padding regardless of which rule happens to
   come first in the file — both classes sit on the same element (see
   renderEntry's `panelClass`), so a same-specificity tie would otherwise
   be decided by source order alone, fragile to a future reshuffle. */
.panel.panel-compact { line-height: 1.35; padding: 1rem 1.1rem; }
.panel-compact .top-pinyin-line { margin-bottom: 0.5rem; }
/* CC-CEDICT quick gloss, made prominent (2026-09-12, owner request) —
   full mode keeps .cedict-quick-gloss's original small/muted/dashed
   "supplementary aside" treatment (see that rule's own comment above),
   but on a flashcard's reveal side the CC-CEDICT line effectively *is*
   the answer, not an aside to it, so here it's promoted to sit right
   under .top-pinyin-line at that same size/weight — stacked and
   centered the same way, rather than the small inline row (tag · pinyin ·
   gloss) full mode uses. The tag/pinyin sub-labels stay small, muted
   metadata; only the gloss text itself (`.cqg-gloss`, "the answer") gets
   the pinyin's own 1.9rem/700 treatment. */
.panel-compact .cedict-quick-gloss {
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 0.15rem;
  border: none;
  padding: 0;
  margin-bottom: 0.9rem;
}
/* Multi-line headwords (2026-09-12 — see renderCedictQuickGloss's own
   comment) still stack each reading's own pinyin above its own gloss,
   centered, same as the single-line case always has; `.cqg-lines` adds a
   bit more breathing room between distinct readings than within one. */
.panel-compact .cedict-quick-gloss .cqg-lines {
  align-items: center;
  gap: 0.5rem;
}
.panel-compact .cedict-quick-gloss .cqg-line {
  flex-direction: column;
  align-items: center;
  gap: 0.15rem;
}
.panel-compact .cedict-quick-gloss .cqg-tag { font-size: 0.6rem; }
.panel-compact .cedict-quick-gloss .cqg-pinyin { font-size: 0.85rem; }
.panel-compact .cedict-quick-gloss .cqg-gloss {
  font-size: 1.9rem;
  font-weight: 700;
  font-style: normal;
  color: var(--text);
}
.panel-compact .sense { margin-bottom: 0.55rem; }
.panel-compact .sense-head { margin-bottom: 0; }
.panel-compact .sense-note { margin: 0.05rem 0 0.15rem; }
.panel-compact .condensed-examples { margin-top: 0.15rem; }
.panel-compact .example { margin-top: 0.2rem; padding-left: 0.7rem; }
/* The two big structural dividers — a second register showing at once
   (Classical + Modern both on by default, no toggle to hide one anymore —
   see renderEntry) and a second merged group (every group shows now, not
   just the top-ranked one — see renderMergedGroup) — were the single
   biggest contributors to "blank" feeling: 1.75rem+1.5rem and
   1.3rem+1.3rem respectively in full mode, more vertical gap than most
   individual senses take up. Trimmed to a plain thin rule with real but
   modest breathing room, not removed outright — a new register/group
   starting is still real information worth a visual break, just not a
   quarter-page one. */
.panel-compact .register-body + .register-body { margin-top: 0.8rem; padding-top: 0.7rem; }
.panel-compact .merged-sense + .merged-sense { margin-top: 0.55rem; padding-top: 0.55rem; }

/* ── Register toggle (Classical / Modern) — two independently clickable
   buttons, both on/shown by default, same "start selected, click to hide"
   pattern as the per-reading pinyin toggles below (.register-pinyin.
   pinyin-toggle) — this is one level up (a whole register, not a reading),
   see dictEntry.js's renderRegisterToggleControl/toggleRegister. Both
   options shown at once, separated by "/"; an active (shown) one is bold
   and full-opacity, a toggled-off one dimmed — same active/dimmed language
   .toggle-opt already had when this was a single click-to-flip control.
   The Script toggle (Traditional / Simplified) used to share this exact
   block — it's now a persistent control in the page's own top nav instead
   of one that only exists inside a rendered entry (see dictEntry.js's
   setScript/getScript), styled by page-local CSS there and still a plain
   <span>, not a <button> — .toggle-opt's active/dimmed rule stays shared
   between the two, the button-only reset just below is scoped to
   .register-toggle so it doesn't affect that nav version. ── */
.register-toggle {
  user-select: none;
  display: flex;
  justify-content: center;
  align-items: baseline;
  gap: 0.4rem;
  width: fit-content;
  font-family: 'IM Fell English', serif;
  font-size: 0.8rem;
  letter-spacing: 0.04em;
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 0.5rem 1rem;
  margin: 0 auto 1rem;
  transition: border-color 0.2s;
}
.register-toggle:hover { border-color: var(--red); }
.register-toggle .zh { font-family: 'Noto Serif SC', serif; margin-right: 0.3rem; }
.register-toggle .sep { color: var(--muted); opacity: 0.5; }
/* Reset the two <button> toggles back to plain inline text, same treatment
   .register-pinyin.pinyin-toggle already gives its own toggle buttons. */
.register-toggle .toggle-opt {
  background: transparent;
  border: none;
  padding: 0;
  font: inherit;
  letter-spacing: inherit;
  cursor: pointer;
}
.toggle-opt { color: var(--text-soft, var(--muted)); opacity: 0.6; transition: opacity 0.2s, color 0.2s; }
.toggle-opt.active { color: var(--gold); opacity: 1; font-weight: 700; }

/* When both registers are shown at once (the default — see
   enabledRegisters), the second .register-body gets a divider separating
   it from the first, same red-gradient language as the merged-sense group
   divider below (.merged-sense + .merged-sense) — this is the same kind of
   "a new, independent block starts here" boundary, just one level up. */
.register-body + .register-body {
  margin-top: 1.75rem;
  padding-top: 1.5rem;
  border-top: 2px solid transparent;
  border-image: linear-gradient(to right, var(--red), transparent 65%) 1;
}

/* ── Two-half split: left register panel | right supplementary accordion ── */
.sd-layout {
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: start;
  gap: 1.5rem;
}
@media (max-width: 720px) {
  .sd-layout { grid-template-columns: 1fr; }
}

.panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 1.25rem 1.4rem;
  line-height: 1.8;
  color: var(--text);
}

/* char+pinyin (.register-header-main) on the left, pipeline badges (see
   below) on the right — space-between, wrapping to a second line rather
   than squeezing/overlapping if the panel gets narrow (a single-column
   .sd-layout on a phone can still be fairly tight). */
.register-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: wrap;
  row-gap: 0.3rem;
  column-gap: 0.7rem;
  margin-bottom: 1rem;
  padding-bottom: 0.7rem;
  border-bottom: 1px solid var(--border);
}
.register-header-main {
  display: flex;
  align-items: baseline;
  gap: 0.7rem;
}
.register-char {
  font-family: 'Noto Serif SC', serif;
  font-size: 1.6rem;
  color: var(--gold);
  line-height: 1;
}
.register-pinyin-group {
  display: inline-flex;
  align-items: baseline;
  flex-wrap: wrap;
}
.register-pinyin {
  font-family: 'IM Fell English', serif;
  font-size: 1.15rem;
  font-style: italic;
  color: var(--gold);
  letter-spacing: 0.05em;
}
/* A 多音字/破音字 headword (e.g. 樂 lè/yuè/yào/lào — see dictEntry.js's
   renderPinyinBadges) turns each reading into its own toggle button instead
   of one plain joined line: reset to plain inline text so it still reads as
   the same italic gold pinyin, just clickable/focusable, and the senses
   for a toggled-off reading (see togglePinyinReading) drop out of the list
   below — no reading can ever be the sole survivor and then get switched
   off, so the sense list is never left empty. */
.register-pinyin.pinyin-toggle {
  background: transparent;
  border: none;
  padding: 0;
  font: inherit;
  font-style: italic;
  letter-spacing: 0.05em;
  cursor: pointer;
}
.register-pinyin.pinyin-toggle:hover,
.register-pinyin.pinyin-toggle:focus-visible { text-decoration: underline; }
.register-pinyin.pinyin-off {
  color: var(--muted);
  opacity: 0.75;
}
.register-pinyin.pinyin-off:hover,
.register-pinyin.pinyin-off:focus-visible { color: var(--text-soft, var(--muted)); }
.pinyin-sep {
  font-family: 'IM Fell English', serif;
  color: var(--muted);
  opacity: 0.5;
  margin: 0 0.15em;
}

/* Two small "has this word been through X" indicators — Ranked
   (admin/ai_jobs.py's sense_rank) and Categorized (moedict_register_tag's
   Classical/Modern split). See dictEntry.js's registerRanked/
   entryCategorized. Deliberately pale and quiet either way (this is
   supplementary pipeline status, not a claim about the entry's content) —
   only the dot's fill distinguishes "done" from "not yet", never a loud
   color change. Hidden per-badge (not just dimmed) when the underlying
   question doesn't even apply (e.g. a register with fewer than 2 senses,
   or a tier with no register concept at all — see registerRanked/
   entryCategorized's null returns), so an inapplicable badge never reads
   as "not done yet". */
.register-badges {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  font-family: 'IM Fell English', serif;
  font-size: 0.68rem;
  letter-spacing: 0.03em;
  color: var(--muted);
}
.hw-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  white-space: nowrap;
  opacity: 0.6;
}
.hw-badge.is-on { opacity: 0.85; }
.hw-badge-dot {
  width: 0.4rem;
  height: 0.4rem;
  border-radius: 50%;
  border: 1px solid var(--muted);
  background: transparent;
}
.hw-badge.is-on .hw-badge-dot { background: var(--gold); border-color: var(--gold); }

/* ── Senses ── */
.sense { margin-bottom: 1.1rem; }
.sense:last-child { margin-bottom: 0; }
.sense-head { margin-bottom: 0.2rem; }
.sense-num { color: var(--text); margin-right: 0.4rem; }
/* Only present when this sense reads differently from the register
   headline (破音字), so it is styled to be caught while scanning. */
.sense-pinyin {
  font-family: 'IM Fell English', serif;
  font-style: italic;
  color: var(--gold);
  letter-spacing: 0.04em;
  margin-right: 0.5rem;
}
/* Single-character register glyph (古/今/白/通 — see dictEntry.js's
   senseRegisterGlyph), between the pinyin and the POS tag. Quieter than
   .sense-pos (no border/box) since it's read at a glance, not scanned for
   like the POS abbreviation is. */
.sense-register-tag {
  font-family: 'Noto Serif SC', serif;
  color: var(--text);
  margin-right: 0.4rem;
  cursor: default;
}
.sense-pos {
  font-size: 0.62rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--red);
  border: 1px solid var(--border);
  border-radius: 2px;
  padding: 0.05rem 0.4rem;
  margin-right: 0.5rem;
  white-space: nowrap;
}
.sense-gloss { color: var(--text); font-size: 1.05rem; }
/* Only present on a MOE (moedict_en tier) sense — the original Chinese
   def the English gloss was translated from (see sheet.js's withGlossZh).
   Same treatment as an example's .zh span, so a MOE gloss reads as
   "Chinese, then English" the same way a StudyDict example already does. */
.sense-gloss-zh { font-family: 'Noto Serif SC', serif; color: var(--gold); margin-right: 0.5rem; }
.sense-note { color: var(--text-soft, var(--muted)); font-size: 0.97rem; margin: 0.2rem 0 0.4rem; }
.example {
  padding-left: 0.9rem;
  border-left: 1px solid var(--border);
  margin-top: 0.35rem;
}
.example .zh { font-family: 'Noto Serif SC', serif; color: var(--gold); margin-right: 0.5rem; }
.example .en { color: var(--text-soft, var(--muted)); font-size: 0.95rem; }
.example .src {
  display: block;
  color: var(--muted);
  font-size: 0.82rem;
  margin-top: 0.15rem;
}
/* A citation that's also a real link (2026-09, Classical Usage's per-sample
   verse links — see dictEntry.js's renderExamples) is still an `<a>`, so it
   needs its own reset — otherwise it'd pick up the browser's default blue/
   underlined link look instead of reading like the plain .src text above.
   Same muted-at-rest/gold-on-hover convention as .accordion-count-link. */
a.src { text-decoration: none; transition: color 0.2s; }
a.src:hover, a.src:focus-visible { color: var(--gold); text-decoration: underline; }

/* ── Merged (moedict_csld_merge) group rendering — dev-mode "MoE Merged"
   source only (see dictEntry.js's renderMergedGroup / plans/
   moedict-csld-integration/04-rendering.md). Every raw revised (R) and
   cross-strait (C) sense is shown in full, always — these classes are
   purely about grouping/labeling them, never about collapsing content. ── */

/* Strong rule between groups (adjacent-sibling, so it never appears before
   the first group or between two members of the same group, which share
   one .merged-sense block) — heavier than anything happening inside a
   group, on purpose: this is the one thing that has to read as "new
   meaning starts here." Same red-gradient language as this site's other
   .divider rules, just horizontal instead of vertical. */
.merged-sense + .merged-sense {
  margin-top: 1.3rem;
  padding-top: 1.3rem;
  border-top: 2px solid transparent;
  border-image: linear-gradient(to right, var(--red), transparent 65%) 1;
}

/* Every member (raw R/C sense) inside a group is always shown, always
   lettered (a, b, c...) regardless of group size — a plain list, not the
   old nested accent-bar/closing-line special case (removed 2026-08-18,
   user call: the letters + source tags already say enough on their own,
   no left bar needed to flag that a split happened). */
.merged-member { margin-bottom: 0.6rem; padding-left: 0.9rem; }
.merged-member:last-child { margin-bottom: 0; }
.merged-letter {
  color: var(--muted);
  font-weight: 700;
  margin-right: 0.4rem;
}

/* Small pill distinguishing which dictionary a raw sense came from —
   read straight off the sense's own `source` field (see
   admin/ai_jobs.py's _ccm_write_result), never inferred. Two-color, same
   gold/red pair the rest of the palette already uses for a two-way
   distinction (see .toggle-opt.active vs. .sep, .sense-pos). */
.sense-source-tag {
  display: inline-block;
  font-size: 0.6rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  border: 1px solid var(--border);
  border-radius: 2px;
  padding: 0.03rem 0.35rem;
  margin-right: 0.5rem;
  white-space: nowrap;
}
.sense-source-tag.src-revised { color: var(--gold); border-color: var(--gold); }
.sense-source-tag.src-csld { color: var(--red); border-color: var(--red); }
.sense-source-tag.src-other { color: var(--text); border-color: var(--muted); }
/* Collapsed list of a group's duplicate definitions (merge_add_source). */
.merged-duplicates { margin-top: 0.4rem; opacity: 0.8; }
.merged-duplicates summary { cursor: pointer; color: var(--muted); font-size: 0.8rem; letter-spacing: 0.04em; }
.merged-duplicates summary:hover { color: var(--gold); }

/* The model's one-sentence note on how a group's members relate (e.g.
   which side is coarser/finer, or a Mainland-vs-Taiwan usage note) — shown
   only on request (2026-08-18, was always-visible), collapsed by default
   behind the same sideways-arrow-rotates-down click convention the
   right-panel accordion sections use (.accordion-arrow, reused directly
   rather than a second arrow style). */
.merged-group-note { margin-top: 0.5rem; }
.merge-note-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  background: transparent;
  border: none;
  padding: 0;
  cursor: pointer;
  font-size: 0.82rem;
}
.merge-note-toggle .note-label { color: var(--text); font-style: normal; letter-spacing: 0.06em; transition: color 0.2s; }
.merge-note-toggle:hover .note-label { color: var(--gold); }
.merged-group-note.open .accordion-arrow { transform: rotate(90deg); }
.merge-note-body { display: none; margin-top: 0.35rem; color: var(--text-soft, var(--muted)); font-size: 0.97rem; }
.merged-group-note.open .merge-note-body { display: block; }

/* A sense's examples, collapsed behind the same sideways-arrow-rotates-down
   convention as the merge-note toggle just above — condensed mode only
   (2026-09-11, dictEntry.js's wrapExamplesForCondensed), so a flashcard's
   reveal side leads with the definition itself, not citation sentences. */
.condensed-examples { margin-top: 0.35rem; }
.examples-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  background: transparent;
  border: none;
  padding: 0;
  cursor: pointer;
  color: var(--text);
  font-family: 'IM Fell English', serif;
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  transition: color 0.2s;
}
.examples-toggle:hover { color: var(--gold); }
.condensed-examples.open .accordion-arrow { transform: rotate(90deg); }
.examples-body { display: none; margin-top: 0.35rem; }
.condensed-examples.open .examples-body { display: block; }

/* ── Right-side accordion ── */
.accordion-section { border-bottom: 1px solid var(--border); }
.accordion-section:last-child { border-bottom: none; }
.accordion-head {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  background: transparent;
  border: none;
  color: var(--text);
  font-family: 'IM Fell English', serif;
  font-size: 0.72rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  padding: 0.9rem 0;
  cursor: pointer;
  text-align: left;
}
.accordion-head:hover { color: var(--gold); }
/* Chinese label alongside each (English) section title — the titles
   themselves are self-explanatory once translated, which is also why the
   old one-line .accordion-intro blurb under the head (e.g. "Words most
   often built from this character…") was dropped (2026-08) rather than
   translated too. Same visual pairing dial-pole-zh/dial-pole-en already
   use for a gauge's pole labels: Chinese first, quieter English after. */
.accordion-title-zh {
  font-family: 'Noto Serif SC', serif;
  color: var(--gold);
  margin-right: 0.4rem;
}
.accordion-arrow { color: var(--red); transition: transform 0.2s; display: inline-block; }
.accordion-section.open .accordion-arrow { transform: rotate(90deg); }
/* Count-link row (2026-08-19, chengyu only so far — see renderSection's
   sec.countLink) — the toggle button sits alongside a real <a> to a
   dedicated full-list page instead of inside it, so the link is a normal
   navigation and doesn't get swallowed by the accordion's own toggle-click
   handler. .accordion-head keeps every other rule (font/color/padding) it
   already had; only its width changes here, from 100% to flex:1, so it
   still fills the row minus whatever the link needs. */
.accordion-head-row { display: flex; align-items: center; gap: 0.6rem; }
.accordion-head-row .accordion-head { width: auto; flex: 1; }
.accordion-count-link {
  font-family: 'IM Fell English', serif;
  font-size: 0.68rem;
  letter-spacing: 0.05em;
  color: var(--muted);
  text-decoration: none;
  white-space: nowrap;
  transition: color 0.2s;
}
.accordion-count-link:hover { color: var(--gold); text-decoration: underline; }
.accordion-body { display: none; padding: 0 0 1rem; }
/* Capped height + scroll (2026-08-10) — a long section (many compound
   words, a chengyu-heavy character) used to just push the page taller
   without limit once opened. ~32rem is a rough "50 lines" ceiling at this
   panel's body-text size/line-height; overflow-y scrolls the rest instead
   of growing the page. max-height only (not a fixed height) so a short
   section doesn't carry empty space below it. */
.accordion-section.open .accordion-body { display: block; max-height: 32rem; overflow-y: auto; }

.lex-item { margin-bottom: 1rem; }
.lex-item:last-child { margin-bottom: 0; }
.lex-term { font-family: 'Noto Serif SC', serif; color: var(--gold); font-size: 1.1rem; margin-right: 0.5rem; }
/* A linkable term (currently just Compound Words — see dictEntry.js's
   renderLexItem/buildCompoundWordsSection) is a real <a>, which carries its
   own UA-default underline/color — reset to look identical to a plain
   .lex-term at rest, with underline only on hover/focus as the interactive
   affordance, since visually it should read as the same kind of text until
   the reader's about to act on it. */
.lex-term-link { text-decoration: none; cursor: pointer; }
.lex-term-link:hover, .lex-term-link:focus-visible { text-decoration: underline; }
.lex-pinyin { color: var(--muted); font-style: italic; font-size: 0.9rem; margin-right: 0.5rem; }
.lex-gloss { color: var(--text); }
/* Chinese-then-English pairing for a linkable item's gloss (currently
   Compound Words' moedict-sourced terms only — see dictEntry.js's
   renderLexItem/buildCompoundWordsSection), same gold treatment
   .sense-gloss-zh already uses for the equivalent pairing on a sense. */
.lex-gloss-zh { font-family: 'Noto Serif SC', serif; color: var(--gold); margin-right: 0.5rem; }
.lex-note { color: var(--text-soft, var(--muted)); font-size: 0.95rem; margin-top: 0.15rem; }
.lex-note .note-label { color: var(--red); font-style: normal; letter-spacing: 0.06em; margin-right: 0.4rem; }

/* Collapsible lex-item (2026-09, Classical Usage's per-text items — see
   dictEntry.js's renderLexItem `collapsible` branch): the term stays a
   plain always-visible sibling link, same button-plus-separate-<a> shape
   .accordion-count-link already established, so it isn't nested inside
   (and swallowed by) the toggle button. Arrow rotate/body reveal reuse
   the exact same sideways-arrow-rotates-down convention as the outer
   accordion sections and a merged group's own "Merge note" toggle. */
.lex-item-head-row { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; }
.lex-item-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  background: transparent;
  border: none;
  padding: 0;
  cursor: pointer;
  color: var(--muted);
  font-family: 'IM Fell English', serif;
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  transition: color 0.2s;
}
.lex-item-toggle:hover { color: var(--gold); }
.lex-item-collapsible.open .accordion-arrow { transform: rotate(90deg); }
.lex-item-body { display: none; margin-top: 0.5rem; }
.lex-item-collapsible.open .lex-item-body { display: block; }

/* The queried word itself, highlighted inside a Classical Usage sample
   sentence (2026-09, dictEntry.js's fmtWithHighlight) — the surrounding
   .example .zh text is already gold, so a plain color change wouldn't
   stand out; a solid background wash does, reusing the same --red accent
   already used for arrows/badges throughout this page. */
mark.usage-highlight {
  background: var(--red);
  color: var(--text);
  font-weight: 700;
  padding: 0 0.15em;
  border-radius: 2px;
}
