:root {
    --line-color: #2b2b2b;
    --hl-color: #b8860b;          /* dark goldenrod, ≥3:1 on white */
    --link-color: #35617f;        /* muted steel blue, ~5.7:1 on white */
    --focus-color: #1a73e8;

    /* Trigram colours from the wuxing 正色/間色 (primary + intermediate) system,
       sampled from Sanzo Wada's colour dictionary. Each element's two trigrams
       take its two canonical colours, so they read as distinct hues that still
       share an elemental family: wood = blue + green (震/巽), earth = gold + grey
       (坤/艮), metal = silver + aquamarine (乾/兌), fire = red (離), water =
       purple (坎). 乾's canonical 白 (white) is invisible on white, so it stands
       in with a cool silver. All are ≥3.9:1 against white. */
    --tri-zhen: #005b8d;          /* 震 thunder — wood 正 · 青 (Helvetia Blue) */
    --tri-xun:  #437742;          /* 巽 wind — wood 間 · 綠 (Cossack Green) */
    --tri-li:   #ab544d;          /* 離 fire — 赤 (Ochre Red) */
    --tri-kan:  #80719e;          /* 坎 water — 紫 (Dull Blue Violet) */
    --tri-kun:  #986f2d;          /* 坤 earth — earth 正 · 黃 (Orange Citrine) */
    --tri-gen:  #848061;          /* 艮 mountain — earth 間 (Light Grayish Olive) */
    --tri-qian: #70727c;          /* 乾 heaven — metal 正 · 白→silver (Plumbeous) */
    --tri-dui:  #00908a;          /* 兌 lake — metal 間 · 碧 (Light Porcelain Green) */
}

/* Each element carrying a trigram slug exposes that trigram's colour as
   --tri-color, so buttons, lines and commentary highlights all pick it up. */
[data-tri="li"]   { --tri-color: var(--tri-li); }
[data-tri="kan"]  { --tri-color: var(--tri-kan); }
[data-tri="zhen"] { --tri-color: var(--tri-zhen); }
[data-tri="xun"]  { --tri-color: var(--tri-xun); }
[data-tri="qian"] { --tri-color: var(--tri-qian); }
[data-tri="dui"]  { --tri-color: var(--tri-dui); }
[data-tri="kun"]  { --tri-color: var(--tri-kun); }
[data-tri="gen"]  { --tri-color: var(--tri-gen); }

/* --- Font stacks ---

   Named in one place because the same four stacks were repeated across thirty
   declarations, and the interesting part of each is its tail: what a reader
   sees when the head of the stack is not installed.

   The Han stacks are the ones that matter. `KaiTi` is Windows-only, so on every
   other platform the whole received text falls through it; the tail therefore
   has to reach a real 楷書 by itself. macOS carries several (Kaiti TC/SC,
   BiauKai, STKaiti — see Apple's font list), so those are named. Android names
   nothing usable: its fonts.xml exposes only `sans-serif`/`serif`/`monospace`,
   and its CJK faces are unnamed fallbacks, so a family name like "Noto Serif
   CJK TC" would be inert there. Its one lever is the generic `serif` keyword
   plus a `lang` attribute — Noto Serif CJK is registered `fallbackFor="serif"`
   with a zh-Hant entry, so lang-tagged Han in a serif stack resolves to it.
   That is a 宋 face, not a kai, so LXGW WenKai TC (loaded as a webfont anyway,
   and a kai) comes first: keeping the kai matters more than keeping the body /
   apparatus contrast, which the rail, indent and italic English also carry.

   `Ma Shan Zheng` used to sit second and so was what every non-Windows device
   actually rendered — a heavy brush *display* face, at body size, missing 88 of
   the corpus's characters. It is gone, from the font links too. */
:root {
    --font-serif: "Source Serif 4", serif;

    /* The body 楷書 of the received text. */
    --font-han: 'KaiTi', 'DFKai-SB', 'Kaiti TC', 'Kaiti SC', 'BiauKai', 'STKaiti',
        'LXGW WenKai TC', var(--font-serif);

    /* The quieter kai of the editorial apparatus — glosses, labels, specimens. */
    --font-han-apparatus: 'LXGW WenKai TC', 'KaiTi', 'Kaiti TC', 'Kaiti SC',
        var(--font-serif);

    /* Trigram ☰ and hexagram ䷀ signs, and the ⓘ tip button. Noto Sans Symbols
       covers all three; the rest is for when the webfont does not arrive. */
    --font-symbol: 'Noto Sans Symbols', 'Noto Sans Symbols 2', 'Apple Symbols',
        'Segoe UI Symbol', var(--font-serif);

    /* Reconstructions: IPA extensions and modifier letters. */
    --font-ipa: 'Charis SIL', 'Doulos SIL', 'Gentium Plus', var(--font-serif);
}

body {
    font-family: var(--font-serif);
    color: #333;
    margin: 2rem 1rem;
}

#yijing-nav {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: stretch;
    gap: 0.5rem;
    margin: 0 auto 1.5rem;
}

.nav-links {
    display: flex;
    align-items: stretch;
    gap: 0.5rem;
}

#yijing-select {
    font: inherit;
    color: #333;
    min-height: 44px;
    /* The option labels are long (number · glyph · name · pinyin · English), so
       the control's intrinsic width would otherwise push the row off a narrow
       screen. Let it shrink, and ellipsize what doesn't fit. */
    min-width: 0;
    max-width: 100%;
    text-overflow: ellipsis;
    padding: 0.4rem 2.2rem 0.4rem 0.8rem;
    background-color: #fafafa;
    border: 1px solid #d5d5d5;
    border-radius: 6px;
    cursor: pointer;
    /* Drop the native control chrome and supply a caret matching the plate's
       quiet grey, so the picker reads like the other controls. */
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='12'%20height='8'%20viewBox='0%200%2012%208'%3E%3Cpath%20d='M1%201.5%206%206.5%2011%201.5'%20fill='none'%20stroke='%23666'%20stroke-width='1.6'%20stroke-linecap='round'%20stroke-linejoin='round'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 0.8rem center;
    background-size: 0.7rem;
}

#yijing-select:hover {
    background-color: #f0f0f0;
    border-color: #bbb;
}

#yijing-select:focus-visible {
    outline: 3px solid var(--focus-color);
    outline-offset: 2px;
}

.nav-step {
    font: inherit;
    line-height: 1;
    min-width: 44px;
    min-height: 44px;
    padding: 0 0.6rem;
    cursor: pointer;
    color: #333;
    background: #fafafa;
    border: 1px solid #d5d5d5;
    border-radius: 6px;
}

.nav-step:hover {
    background: #f0f0f0;
    border-color: #bbb;
}

.nav-step:active {
    background: #e4e4e4;
}

.nav-step:focus-visible {
    outline: 3px solid var(--focus-color);
    outline-offset: 2px;
}

/* Quiet text link sitting after the picker in the nav row, leading to the
   About page. Kept visually lighter than the step buttons so it doesn't compete
   with the picker, but with a full-height 44px target and a clear focus ring. */
.nav-about {
    display: inline-flex;
    align-items: center;
    padding: 0 0.6rem;
    min-height: 44px;
    color: #555;
    font-size: 0.95rem;
    text-decoration: none;
    border-bottom: 1px solid transparent;
}

.nav-about:hover {
    color: #333;
    border-bottom-color: currentColor;
}

.nav-about:focus-visible {
    outline: 3px solid var(--focus-color);
    outline-offset: 2px;
    border-radius: 4px;
}

#yijing {
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
    gap: 1.5rem;
}

/* --- Two-column plate: sticky left rail (name · trigrams · figure) beside the
   flowing commentary (Judgement · Image · Lines). --- */

.plate-grid {
    --fig-col: 13rem;
    width: 100%;
    max-width: 52rem;
    display: grid;
    grid-template-columns: var(--fig-col) minmax(0, 1fr);
    grid-template-areas:
        ".      toolbar"
        "figure content";
    column-gap: 2rem;
    align-items: start;
}

.content-col {
    grid-area: content;
    display: flex;
    flex-direction: column;
    gap: 1.75rem;
    min-width: 0;
    text-align: left;
    line-height: 1.6;
}

@media (min-width: 1200px) {
    .plate-grid {
        max-width: 72rem;
    }
}

/* Each right-hand section is set off by a light left rail and a hairline break,
   rather than boxed in a card. */
.plate-section {
    padding-left: 1.2rem;
}

/* Sections after the first are parted by a short left-aligned hairline tick,
   rather than a full-width rule. */
.plate-section + .plate-section {
    padding-top: 1.75rem;
    position: relative;
}

.plate-section + .plate-section::before {
    content: "";
    position: absolute;
    top: 0;
    left: 50%;
    transform: translateX(-50%);
    width: 2.5rem;
    height: 1px;
    background: #e4e4e4;
}

/* The sticky rail keeps the figure in view while the commentary scrolls. */
.figure-col {
    grid-area: figure;
    position: sticky;
    top: 1rem;
    align-self: start;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.6rem;
}

.figure-col #symbol-name {
    margin-bottom: 0.5rem;
}


/* --- The hexagram, drawn as six real lines --- */

.hexagram-lines {
    --line-w: 12rem;      /* width of a full (yang) bar */
    --line-h: 1.5rem;     /* bar thickness */
    --line-gap: 0.5rem;   /* vertical gap between lines */
    --yin-gap: 2.5rem;    /* central gap of a broken (yin) line */
    display: flex;
    flex-direction: column-reverse;  /* line 1 sits at the bottom */
    align-items: center;
    gap: var(--line-gap);
}

.line {
    appearance: none;
    -webkit-appearance: none;
    background: transparent;
    border: 2px solid transparent;
    border-radius: 4px;
    margin: 0;
    padding: 0.55rem 0.5rem;         /* enlarges the hit target */
    min-height: 44px;
    box-sizing: border-box;
    width: calc(var(--line-w) + 1.5rem);
    display: flex;
    flex-direction: row;
    justify-content: center;
    align-items: center;
    gap: var(--yin-gap);
    cursor: pointer;
}

.line .bar {
    height: var(--line-h);
    background: var(--line-color);
    border-radius: 2px;
}

.line.yang .bar {
    width: var(--line-w);
}

.line.yin .bar {
    width: calc((var(--line-w) - var(--yin-gap)) / 2);
}

.line:hover {
    background: rgba(0, 0, 0, 0.05);
}

/* Highlight uses a visible border (a shape cue, not colour alone) as well as
   colour, so it is perceivable without relying on colour vision. The colour is
   the active trigram's own (five-element) hue, falling back to the goldenrod. */
.line.highlighted {
    border-color: var(--tri-color, var(--hl-color));
    background: color-mix(in srgb, var(--tri-color, var(--hl-color)) 12%, transparent);
}

.line.highlighted .bar {
    background: var(--tri-color, var(--hl-color));
}

.line:focus-visible {
    outline: 3px solid var(--focus-color);
    outline-offset: 2px;
}

/* --- Trigram highlight toggles: chips flanking the figure, styled like the
   translation/commentary toggles so they read as controls rather than loud
   coloured labels. At rest they are neutral grey and harmonious with the plate;
   only when active do they take the trigram's own hue — the same hue the lines
   they highlight are drawn in — as a border + tinted fill + weight. --- */

.trigram-toggle {
    font: inherit;
    font-size: 0.9rem;
    padding: 0.25rem 0.7rem;
    color: #666;
    background: #fafafa;
    border: 1px solid #d5d5d5;
    border-radius: 6px;
    cursor: pointer;
    /* Glyph + hanzi + English image word on a single baseline. */
    display: inline-flex;
    flex-direction: row;
    align-items: baseline;
    justify-content: center;
    gap: 0.35em;
}

.trigram-toggle .tri-glyph {
    font-size: 1.15em;
    margin: 0 0.05em;
}

.trigram-toggle .tri-name {
    font-family: var(--font-han);
}

.trigram-toggle .tri-image {
    font-variant: small-caps;
    letter-spacing: 0.02em;
}

.trigram-toggle:hover {
    color: #333;
    background: #f0f0f0;
    border-color: #bbb;
}

/* Active: the trigram's own hue as border + tinted fill + weight — three
   non-colour cues layered on the colour, echoing the highlighted lines. */
.trigram-toggle[aria-pressed="true"] {
    color: var(--tri-color, var(--hl-color));
    border-color: var(--tri-color, var(--hl-color));
    background: color-mix(in srgb, var(--tri-color, var(--hl-color)) 12%, transparent);
    font-weight: 700;
}

.trigram-toggle:focus-visible {
    outline: 3px solid var(--focus-color);
    outline-offset: 2px;
}

/* --- Name block: reference glyph in front of the Chinese name --- */

#symbol-name {
    text-align: center;
    color: #333;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.3em;
}

/* Each Chinese name form (received, then each variant) and its English
   renderings form a group; the tighter inner gap binds a rendering to the
   Chinese head it translates, while #symbol-name's larger gap separates forms. */
#symbol-name .name-group {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.1em;
}

#symbol-name .name-line {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.4em;
}

/* Top line: the reference hexagram symbol, shown large and centred. */
#symbol-name .glyph-line {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.3em;
}

#symbol-name .unicode-glyph {
    font-size: 3.6em;
    line-height: 1;
}

#symbol-name .chinese-name {
    font-family: var(--font-han);
    font-size: 2em;
}

/* The pre-rendered small-seal (小篆) name, shown on the name line beside the
   modern character. The SVG fills with currentColor, so it inherits the name
   colour and any future theme. */
#symbol-name .seal-name {
    display: inline-flex;
    align-items: center;
}

#symbol-name .seal-name svg {
    display: block;
    width: auto;
    height: 2em;
}

/* The oracle-bone (甲骨文) name, shown in red at the head of the name line when
   the font covers the whole name. The SVG fills with currentColor, so this red
   drives it; sized a touch smaller than the seal, as the forms are sparer and
   read better with a little more air. */
#symbol-name .oracle-name {
    display: inline-flex;
    align-items: center;
    color: #8b1a1a;
}

#symbol-name .oracle-name svg {
    display: block;
    width: auto;
    height: 1.7em;
}

/* An ancestral-graph oracle glyph (本字/初文) makes a different claim from a
   name-in-oracle glyph — the depicted graph is the ancestor of the name, not the
   name itself — so it wears a small dagger marker to set it apart. It reuses the
   red .oracle-name colour of the nested glyph. */
#symbol-name .oracle-ancestor {
    display: inline-flex;
    align-items: flex-start;
    color: #8b1a1a;
}

#symbol-name .ancestor-mark {
    font-size: 0.62em;
    line-height: 1;
    margin-left: 0.06em;
    color: #b06a6a;
}

#symbol-name .pinyin {
    font-style: italic;
    color: #666;
}

/* The reading row (reconstructed Old/Middle Chinese ahead of the modern pinyin),
   on its own line under the graphs. */
#symbol-name .reading-line {
    display: flex;
    align-items: baseline;
    justify-content: center;
    gap: 0.4em;
}

/* Reconstructed pronunciations (e.g. Baxter–Sagart): OC then MC, each with a
   small superscript OC/MC tag. Quieter than the pinyin; the notation reads
   left-to-right oldest → newest into the modern reading. */
#symbol-name .reconstruction {
    display: inline-flex;
    align-items: baseline;
    gap: 0.4em;
    color: #777;
    font-family: var(--font-ipa);
}

#symbol-name .reading-label {
    font-size: 0.6em;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: #aaa;
    margin-right: 0.15em;
    vertical-align: 0.35em;
}

/* Middot separators between the script forms (oracle · seal · modern) and
   between the readings (OC · MC · pinyin). Each dot hangs off the element it
   FOLLOWS, so the accessible KaiTi name and pinyin are never prefixed by
   punctuation, and on the graph row the dots ride the aria-hidden glyphs. */
#symbol-name .name-line > .oracle-name::after,
#symbol-name .name-line > .oracle-ancestor::after,
#symbol-name .name-line > .seal-name::after,
#symbol-name .reconstruction::after,
#symbol-name .reconstruction > .reading.oc::after {
    content: '·';
    margin-left: 0.4em;
    color: #bbb;
}

#symbol-name .english {
    color: #555;
}

/* Chinese name variants from excavated traditions (e.g. the Mawangdui silk
   manuscript), one quiet line each under the received name. */
/* An excavated-tradition group spans the whole name block so its divider rule
   can reach full width. */
#symbol-name .variant-group {
    align-self: stretch;
}

/* A labelled break introducing the tradition (帛書): the label centred between
   two hairlines, with extra room above to set the variant apart from the
   received name. */
#symbol-name .variant-divider {
    display: flex;
    align-self: stretch;
    align-items: center;
    gap: 0.6em;
    margin-top: 0.7em;
}

#symbol-name .variant-divider::before,
#symbol-name .variant-divider::after {
    content: '';
    flex: 1;
    border-top: 1px solid #ddd;
}

#symbol-name .variant-line {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.4em;
    font-size: 0.85em;
    color: #666;
}

#symbol-name .variant-label {
    font-size: 0.85em;
    color: #999;
}

#symbol-name .variant-name {
    font-family: var(--font-han);
    font-size: 2em;
    line-height: 1;
}

#symbol-name .variant-pinyin {
    font-style: italic;
}

/* The variant's reading row, quieter and smaller to match its graph row. */
#symbol-name .variant-reading-line {
    font-size: 0.85em;
    color: #666;
}

/* Middot separators on the variant graph row too (oracle · seal · modern),
   matching the received name; the tradition label stays set off by the gap. */
#symbol-name .variant-line > .oracle-name::after,
#symbol-name .variant-line > .oracle-ancestor::after,
#symbol-name .variant-line > .seal-name::after {
    content: '·';
    margin-left: 0.4em;
    color: #bbb;
}

/* --- Commentary sections (Judgement · Image · Lines) --- */

.commentary-title {
    margin: 0 0 0.6rem;
    font-size: 1.1rem;
    font-weight: 600;
    color: #333;
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 0.4em 0.5em;
    position: relative;
}

/* A small seal-script mark (彖 · 象 · 爻) hangs in the left gutter as a quiet
   marginal anchor, outdented so the title text stays flush with the body. */
.commentary-title .seal-mark {
    position: absolute;
    left: -1.75rem;
    top: 0;
    height: 1lh;
    display: flex;
    align-items: center;
    color: #8a8a8a;
}

/* Only a viewBox, so state both dimensions: an SVG with no intrinsic width
   collapses in any layout that does not size it for it. */
.commentary-title .seal-mark svg {
    display: block;
    width: 1.1em;
    height: 1.1em;
}

.commentary-title-zh {
    font-family: var(--font-han);
    font-weight: 400;
    color: #999;
    font-size: 0.95em;
}

/* The "Commentary <term>" group is pushed to the right of the title row, with
   its own info tooltip and a caret-only show/hide toggle. */
/* --- Layers: the base text and the commentary on it -----------------------

   Every layer of the plate has the same shape — a margin rail naming the voice,
   an English caption along the top of the text, and the body itself — whether it
   holds the received text or a commentary on a commentary.

   Indentation means stratigraphy and nothing else: a commentary on the base text
   sits flush with it (it is not *inside* the text), while a commentary on a
   commentary steps in. The vertical spine is drawn per passage rather than once
   down the whole body, so it is continuous while a voice is speaking and simply
   absent where another has cut in: the gap IS the interruption. A filled dot
   marks where a voice cuts in, a hollow ring where the interrupted voice picks
   up again. */

.layer {
    display: grid;
    grid-template-columns: var(--rail-width) minmax(0, 1fr);
    column-gap: var(--rail-gap);
    align-items: start;
    position: relative;
    --rail-width: 3.25rem;
    --rail-gap: 0.75rem;
    --spine: 0.9rem;
    /* Where a voice's spine begins, and so where its dot sits: the two share
       this so the dot always caps the line rather than floating on it. */
    --dot-top: 0.55rem;
    --layer-color: #999;
}

.layer + .layer {
    margin-top: 1.05rem;
}

/* The wings and the later commentators each get their own hue, so a voice is
   recognisable down the page before its name is read. */
.layer[data-commentary="tuan"] { --layer-color: #7a5c9e; }
.layer[data-commentary="daxiang"],
.layer[data-commentary="xiaoxiang"] { --layer-color: #2f7d6f; }
.layer[data-commentary="wenyan"] { --layer-color: #b8860b; }
.layer[data-commentary="wangbi"] { --layer-color: #a2542f; }
.layer[data-commentary="hankangbo"] { --layer-color: #7a6a3f; }
.layer.is-core { --layer-color: #b0b0b0; }

/* The rail carries the Chinese name — short, fixed-width, the thing a reader
   scans down — with the approximate date beneath it. With a caption present the
   text column has two rows (caption, then text), and the rail spans both as a
   subgrid so the name shares the caption's row and the date shares the text's:
   they line up by construction rather than by two stacks happening to add up to
   the same height. */
.layer-rail {
    grid-column: 1;
    grid-row: span 2;
    display: grid;
    grid-template-rows: subgrid;
    text-align: right;
    line-height: 1.3;
}

/* Where subgrid is unavailable the two stacks simply sit at the top of their
   own rows; the date then floats a little high, which is a blemish rather than
   a break. */
@supports not (grid-template-rows: subgrid) {
    .layer-rail {
        grid-row: auto;
        display: block;
        padding-top: 0.2rem;
    }
}

.layer-name {
    font-family: var(--font-han);
    font-size: 1.05rem;
    color: var(--layer-color);
}

/* The pass letter rides with the English caption rather than the margin: the
   rail is too narrow to carry it beside a three-character name (文言傳 A), where
   it wrapped and pulled the date out of alignment with the text. */
.layer-pass {
    color: color-mix(in srgb, var(--layer-color) 70%, #fff);
}

.layer-pass::before {
    content: '·';
    margin: 0 0.4em;
    color: #d2d2d2;
}

.layer-date {
    display: block;
    font-size: 0.68rem;
    color: #c9c9c9;
    font-variant-numeric: tabular-nums;
}

/* A voice already named on this line or judgement is named again more quietly,
   so the reader can follow who is speaking without the label shouting twice. */
.layer-rail.is-short .layer-name {
    font-size: 0.95rem;
    color: color-mix(in srgb, var(--layer-color) 65%, #fff);
}

/* The English name runs along the top of the text it introduces rather than in
   the margin, so a long name ("Commentary on the Judgement") costs length rather
   than forcing the margin wider. It fills its row and sits at the bottom of it,
   next to the words it introduces. */
.layer-caption {
    grid-column: 2;
    display: flex;
    align-items: flex-end;
    position: relative;
    padding-left: var(--spine);
    padding-top: 0.25rem;
    padding-bottom: 0.3rem;
    font-size: 0.62rem;
    line-height: 1.1;
    text-transform: uppercase;
    letter-spacing: 0.09em;
    color: #b4b4b4;
}

.layer-caption.is-short {
    color: #cbcbcb;
}

/* The spine runs alongside the caption too, rather than starting halfway down
   the block. */
.layer-caption::before {
    content: '';
    position: absolute;
    left: 0;
    top: var(--dot-top);
    bottom: 0;
    width: 2px;
    border-radius: 1px 1px 0 0;
    background: color-mix(in srgb, var(--layer-color) 50%, #ececec);
}

/* The info button keeps its 24px touch target, but that is more than twice the
   height of the caps line beside it — left in flow it would inflate the caption's
   row and strand the caption at the bottom of it. Negative block margins take the
   button back out of the row's height without shrinking what can be clicked. */
.layer-caption .tip {
    margin-left: 0.35em;
}

.layer-caption .tip-btn {
    margin-block: -0.4rem;
}

.layer-body {
    grid-column: 2;
    position: relative;
    padding-left: var(--spine);
}

.layer-body > .passage + .passage,
.layer-body > .layer + .passage {
    margin-top: 1rem;
}

/* One spine segment per passage. Segments overhang by half the inter-passage
   gap so consecutive passages join into one unbroken line, while a nested layer
   leaves a real gap. */
.layer-body > .passage {
    position: relative;
}

.layer-body > .passage::before {
    content: '';
    position: absolute;
    left: calc(-1 * var(--spine));
    top: -0.35rem;
    bottom: -0.35rem;
    width: 2px;
    border-radius: 1px;
    background: color-mix(in srgb, var(--layer-color) 50%, #ececec);
}

/* The first passage's spine is already carried down from the caption above it,
   so it need not start early; the last simply stops. */
.layer-body > .passage:last-child::before {
    bottom: 0.3rem;
}

/* A commentary on a commentary steps in one place, inside its host's body. */
.layer .layer {
    margin: 0.85rem 0;
}

/* The dot is the control, and it is the head of this voice's own spine rather
   than a bead laid over it: same colour, no halo punched through the line, so
   the line simply begins there. Folding turns it into a hollow ring, which is
   the one state that should read as an interruption. */
.layer-dot {
    position: absolute;
    left: calc(var(--rail-width) + var(--rail-gap));
    top: var(--dot-top);
    margin-left: 1px;
    transform: translate(-50%, -50%);
    width: 0.95rem;
    height: 0.95rem;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    cursor: pointer;
    display: grid;
    place-items: center;
}

.layer-dot::before {
    content: '';
    width: 0.45rem;
    height: 0.45rem;
    border-radius: 50%;
    background: color-mix(in srgb, var(--layer-color) 50%, #ececec);
    transition: width 0.12s, height 0.12s, background-color 0.12s;
}

.layer-dot:hover::before {
    width: 0.62rem;
    height: 0.62rem;
    background: var(--layer-color);
}

.layer-dot:focus-visible {
    outline: 3px solid var(--focus-color);
    outline-offset: 1px;
}

.layer.is-folded > .layer-dot::before {
    width: 0.62rem;
    height: 0.62rem;
    background: #fff;
    border: 2px solid var(--layer-color);
    box-shadow: 0 0 0 2.5px #fff;
}

/* The base text is the one voice you cannot fold, so it has no dot button and its
   spine would otherwise begin in mid-air. This caps it with the same mark, drawn
   in the spine's own colour and with no hit area — a terminus, not a control.
   A resumed core layer is excluded: it already carries the hollow return ring. */
.layer.is-core:not(.is-resume)::before {
    content: '';
    position: absolute;
    left: calc(var(--rail-width) + var(--rail-gap));
    top: var(--dot-top);
    margin-left: 1px;
    transform: translate(-50%, -50%);
    width: 0.45rem;
    height: 0.45rem;
    border-radius: 50%;
    background: color-mix(in srgb, var(--layer-color) 50%, #ececec);
}

/* The return: a hollow ring where the interrupted voice picks up, drawn on the
   same axis as the break it closes. A voice that never resumes — a commentary
   ending a judgement — simply has no ring. */
.layer.is-resume::after,
.layer-body > .passage.is-resume::after {
    content: '';
    position: absolute;
    width: 0.42rem;
    height: 0.42rem;
    border-radius: 50%;
    transform: translate(-50%, -50%);
    margin-left: 1px;
    background: #fff;
    border: 1.5px solid color-mix(in srgb, var(--layer-color) 70%, #fff);
    box-shadow: 0 0 0 2px #fff;
}

.layer.is-resume::after {
    left: calc(var(--rail-width) + var(--rail-gap));
    top: 0.7rem;
}

/* On a resuming passage the ring CAPS the spine rather than replacing it: the
   ring is its own pseudo-element and the spine simply starts at the ring's
   centre instead of overhanging upwards into the gap it is closing. */
.layer-body > .passage.is-resume::after {
    left: calc(-1 * var(--spine));
    top: 0.7rem;
    /* No white halo here: there is no line above to separate the ring from, and a
       halo would punch a gap into the spine that emerges from beneath it. */
    box-shadow: none;
}

.layer-body > .passage.is-resume::before {
    top: 0.7rem;
}

/* Folded: the voice keeps its rail and the first words of what it says, so the
   reader can see whose voice is waiting rather than only that something is. */
.layer.is-folded > .layer-body,
.layer.is-folded > .layer-caption {
    display: none;
}

.layer.is-folded > .layer-rail {
    grid-row: auto;
    display: block;
    opacity: 0.75;
}

.layer-peek {
    grid-column: 2;
    display: none;
    padding-left: var(--spine);
    padding-top: 0.15rem;
    font-family: var(--font-han-apparatus);
    font-size: 0.9rem;
    color: #aaa;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.layer.is-folded > .layer-peek {
    display: block;
}

/* The gloss speaks in a quieter, distinct voice from the passage above it:
   its Chinese in LXGW WenKai TC (霞鶩文楷) — a regular, faintly 仿宋-leaning kai
   that reads as editorial apparatus beside the brushier body 楷體 — and its
   English in italic. On a platform with no system kai the two stacks converge
   on LXGW WenKai TC and this contrast is lost; the rail, indent and italic
   carry the distinction there. */
.commentary-indent .passage-original {
    font-family: var(--font-han-apparatus);
    font-size: 1.1rem;
}

.commentary-indent .passage-translation {
    font-style: italic;
}

/* Narrow screens have no room for a margin column, so the rail folds back over
   the text and the layout becomes a simple indented stack. The per-passage spine
   and its marks give way to one continuous border; the dot moves onto that border,
   because it is a control, not an ornament — hiding it would leave the folded
   later commentary with no way to open it. */
@media (max-width: 700px) {
    .layer {
        display: block;
        padding-left: var(--spine);
        border-left: 2px solid color-mix(in srgb, var(--layer-color) 50%, #ececec);
    }

    .layer-rail {
        display: block;
        text-align: left;
    }

    .layer-date {
        display: inline;
        margin-left: 0.5em;
    }

    .layer-caption,
    .layer-body,
    .layer-peek {
        padding-left: 0;
    }

    .layer-caption::before,
    .layer-body > .passage::before,
    .layer.is-core:not(.is-resume)::before,
    .layer.is-resume::after,
    .layer-body > .passage.is-resume::after {
        display: none;
    }

    .layer-dot {
        left: 0;
        top: 0.6rem;
    }
}

/* --- The Lines section: each 爻辭 with its (optional) 小象傳 gloss --- */

.lines-list {
    display: flex;
    /* Lines read top-to-bottom in received-text order (初九 first, 上九 last),
       matching the DOM order 1→6. (The drawn figure, in the sticky rail, keeps
       its own bottom-to-top convention.) */
    flex-direction: column;
    gap: 1.25rem;
}

/* --- Info tooltip on section titles --- */

.tip {
    position: relative;
    display: inline-flex;
    align-items: center;
    align-self: center;
}

.tip-btn {
    font: inherit;
    font-family: var(--font-symbol);
    font-size: 1em;
    font-weight: 200;
    line-height: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.5em;
    height: 1.5em;
    min-width: 24px;
    min-height: 24px;
    padding: 0;
    border: none;
    background: transparent;
    color: #888;
    cursor: help;
}

.tip-btn:focus-visible {
    outline: 3px solid var(--focus-color);
    outline-offset: 2px;
}

.tip-box {
    display: none;
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    z-index: 10;
    width: max-content;
    max-width: min(18rem, 80vw);
    padding: 0.5rem 0.65rem;
    background: #2b2b2b;
    color: #fff;
    border-radius: 6px;
    font-family: var(--font-serif);
    font-size: 0.8rem;
    font-weight: 400;
    font-style: normal;
    line-height: 1.45;
    text-align: left;
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
}

.tip:hover .tip-box,
.tip:focus-within .tip-box {
    display: block;
}

/* A passage stacks each original sentence with its translation(s) beneath it,
   so extra translations can be added under the same original line. */
.passage {
    margin: 0;
}

/* A commentary block renders one <dl class="passage"> per segment, so a
   segment's sub-commentary can be interleaved right after it. Spacing between
   these is handled by the shared rule above. */
.passage {
    margin: 0;
}

.passage dt,
.passage dd {
    margin: 0;
}

.passage-original-column,
.passage-translation-column {
    min-width: 0;
}

/* Each segment (a run of original clauses + its translation(s)) is a group.
   Groups are spaced apart; the first sits flush with the section title. */
.passage-group {
    margin-top: 1rem;
}

.passage-group:first-child {
    margin-top: 0;
}

/* The clause boundaries in the data (one <dt> per clause, each ending in ，。；)
   stay in the DOM for alignment/semantics, but render inline so a passage flows
   as running text and wraps only at the column edge — rather than forcing a line
   break after every punctuation mark. Disabled here "for now" in the two-column
   layout; delete these two display rules to restore per-clause line breaks. */
.passage-original {
    display: inline;
    font-family: var(--font-han);
    font-size: 1.3rem;
    color: #222;
}

/* A trigram-image word within an original clause (e.g. 雲 for 坎/water in the
   大象傳). Tinted to match its trigram via the shared [data-tri] rule, with a
   heavier weight so the mark never depends on colour alone. */
.tri-mark {
    color: var(--tri-color, inherit);
    font-weight: 700;
}

.quote-mark {
    color: #8b1a1a;
    text-decoration: underline dotted;
    text-decoration-thickness: 1px;
    text-underline-offset: 0.2em;
}

/* Block, so the translation(s) restart on their own line beneath the running
   original on narrow screens. */
.passage-translation {
    display: block;
    color: #555;
    margin-top: 0.4rem;
}

/* Shown only when a segment carries more than one translation, to name each.
   A quiet upright small-caps tag, set apart from the translation that follows. */
.translation-by {
    font-style: normal;
    font-variant: small-caps;
    letter-spacing: 0.03em;
    color: #999;
    margin-right: 0.4em;
}

/* On wide screens, keep the source and its translation in parallel columns.
   The columns remain separate blocks below the breakpoint for readable
   narrow-screen flow. */
@media (min-width: 900px) {
    .passage-group {
        /* The Chinese is the denser script — it says the same thing in far fewer
           glyphs — so it needs less width than an even split would give it. One
           number to tune the balance. */
        --original-col: 0.8fr;
        display: grid;
        grid-template-columns: minmax(0, var(--original-col)) minmax(0, 2fr);
        column-gap: 1.5rem;
    }

    .passage-translation-column {
        border-left: 1px solid #ddd;
        padding-left: 1.5rem;
    }

    .passage-translation:first-child {
        margin-top: 0;
    }
}

/* --- The Translations toolbar: one show/hide toggle per translator, up top --- */

/* --- The toolbars: translator show/hide, then commentary show/hide, up top --- */

.content-toolbars {
    grid-area: toolbar;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 0.4rem;
    margin-bottom: 0.75rem;
}

.content-toolbar,
.commentary-toolbar {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    justify-content: flex-end;
}

.translation-toggle,
.commentary-filter {
    font: inherit;
    font-size: 0.8rem;
    font-variant: small-caps;
    letter-spacing: 0.03em;
    color: #666;
    background: #fafafa;
    border: 1px solid #d5d5d5;
    border-radius: 6px;
    padding: 0.2rem 0.6rem;
    cursor: pointer;
}

.commentary-filter [lang] {
    font-family: var(--font-han);
}

.translation-toggle:hover,
.commentary-filter:hover {
    color: #333;
    background: #f0f0f0;
    border-color: #bbb;
}

.translation-toggle[aria-pressed="true"],
.commentary-filter[aria-pressed="true"] {
    color: #444;
    background: #eef2f5;
    border-color: #b7c7d1;
}

/* A deselected translator or commentary reads as "off": struck through and dimmed. */
.translation-toggle[aria-pressed="false"],
.commentary-filter[aria-pressed="false"] {
    color: #aaa;
    text-decoration: line-through;
}

.translation-toggle:focus-visible,
.commentary-filter:focus-visible {
    outline: 3px solid var(--focus-color);
    outline-offset: 2px;
}

/* A translation, credit line, or English title the reader switched off. (Commentary
   is no longer hidden this way: the filter chips fold it, keeping its rail.) */
.passage-translation.is-hidden,
.credit-line.is-hidden,
#symbol-name .english.is-hidden {
    display: none;
}

/* --- Narrow screens: stack the plate, unstick the figure rail, and keep the
   nav and its tooltips inside a phone-width viewport --- */

@media (max-width: 680px) {
    .plate-grid {
        grid-template-columns: 1fr;
        grid-template-areas:
            "figure"
            "toolbar"
            "content";
        row-gap: 1.75rem;
    }

    /* Stacked, the rail costs a whole screen before the first word of text. On a
       phone it turns instead: the drawn figure with its two trigram tabs takes a
       narrow left column and the name block the rest, so the Judgement starts
       within the first screenful. DOM order (name · upper · figure · lower) is
       untouched, so the reading order a screen reader gets is unchanged. */
    .figure-col {
        position: static;
        display: grid;
        grid-template-columns: auto minmax(0, 1fr);
        grid-template-rows: auto auto auto;
        align-items: center;
        justify-items: center;
        column-gap: 1rem;
        /* Near the top of the range the pair would otherwise be stretched to the
           full text measure, stranding the figure at the far left. */
        max-width: 34rem;
        margin-inline: auto;
    }

    .figure-col > #symbol-name {
        grid-column: 2;
        grid-row: 1 / span 3;
        margin-bottom: 0;
    }

    .figure-col > .tri-upper      { grid-area: 1 / 1; }
    .figure-col > .hexagram-lines { grid-area: 2 / 1; }
    .figure-col > .tri-lower      { grid-area: 3 / 1; }

    /* A narrower bar keeps the figure legible beside the name. The row height is
       set by the 44px tap target, not by --line-h, so it is left alone. */
    .hexagram-lines {
        --line-w: 7.5rem;
        --yin-gap: 1.5rem;
        --line-gap: 0.35rem;
    }

    /* The About/Rhyme links drop to a row of their own, leaving ‹ picker › intact
       as one stepper across the full width. */
    #yijing-nav {
        row-gap: 0.75rem;
    }

    /* Basis 0 rather than auto: the picker's content width is far wider than a
       phone, and a content-sized basis would wrap it away from its two buttons
       instead of letting it shrink between them. */
    #yijing-select {
        flex: 1 1 0;
    }

    .nav-links {
        flex-basis: 100%;
        justify-content: center;
    }

    /* A tooltip hung under its ⓘ runs off the right edge on a phone, and there is
       no room beside the mark to hang it anywhere else. It becomes a strip pinned
       to the foot of the viewport instead — summoned and dismissed by the same tap
       (focus), but always wholly on screen. */
    .tip-box {
        position: fixed;
        inset: auto 0.75rem 0.75rem;
        width: auto;
        max-width: none;
    }
}

.commentary-credit {
    margin-top: 0.5rem;
    font-size: 0.85rem;
    color: #888;
}

.commentary-credit .credit-line,
.commentary-credit .source-credit {
    margin: 0;
}

.commentary-credit a {
    color: inherit;
}

/* Visually hidden but available to assistive tech (the live region). */
.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;
}

@media (prefers-reduced-motion: no-preference) {
    .line,
    .trigram-toggle {
        transition: background-color 0.15s ease, border-color 0.15s ease;
    }
}

/* --- Colophon: font attribution (required by the Chong Xi Small Seal licence) --- */

#colophon {
    max-width: 52rem;
    margin: 3rem auto 0;
    padding-top: 1rem;
    border-top: 1px solid #e0e0e0;
    text-align: center;
    font-size: 0.85rem;
    color: #777;
}

@media (min-width: 1200px) {
    #colophon {
        max-width: 72rem;
    }
}

#colophon a {
    color: inherit;
}

/* --- About page: a single centred prose column reusing the app's serif and
   colour palette. Standalone (about.html); no plate grid here. --- */

.about-page {
    max-width: 40rem;
    margin: 0 auto;
    line-height: 1.65;
    text-align: left;
    --bronze-ink: #2f6b57;
    --oracle-ink: #8b1a1a;
    --seal-ink: #2b3a5c;
}

/* --- Multi-page routing (about.html) --------------------------------------
   Content is split into <section class="about-view" data-page="…"> pages shown
   one at a time by about-router.js. Visibility is keyed on the data-about-page
   attribute the router sets on <html>; the `html.js` guard means that with NO
   JavaScript the `js` class is never added and every view stays visible (so the
   page degrades gracefully and deep links still show all content). */
html.js .about-view {
    display: none;
}

html.js[data-about-page="about"] .about-view[data-page="about"],
html.js[data-about-page="authorities"] .about-view[data-page="authorities"],
html.js[data-about-page="terms"] .about-view[data-page="terms"],
html.js[data-about-page="trigrams"] .about-view[data-page="trigrams"],
html.js[data-about-page="dating"] .about-view[data-page="dating"],
html.js[data-about-page="references"] .about-view[data-page="references"] {
    display: block;
}

/* On a page switch the router moves focus to the page <h1> (a programmatic,
   non-tabbable target) so keyboard and AT users land on the new page; it isn't a
   user-driven tab stop, so suppress its focus ring. */
.about-view > .about-title:focus {
    outline: none;
}

.about-nav {
    margin: 0 0 1.75rem;
    padding-bottom: 0.75rem;
    border-bottom: 1px solid #e4e4e4;
    font-size: 0.95rem;
}

.about-nav ul {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem 1rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.about-nav a {
    color: #555;
    text-decoration: none;
    border-bottom: 1px solid transparent;
}

.about-nav a:hover {
    color: #333;
    border-bottom-color: currentColor;
}

.about-nav a:focus-visible {
    outline: 3px solid var(--focus-color);
    outline-offset: 2px;
    border-radius: 4px;
}

.about-nav a[aria-current="page"] {
    color: #222;
    font-weight: 600;
    border-bottom-color: currentColor;
}

.about-back {
    margin: 0 0 1.5rem;
    font-size: 0.9rem;
}

.about-back a {
    color: #555;
    text-decoration: none;
    border-bottom: 1px solid transparent;
}

.about-back a:hover {
    color: #333;
    border-bottom-color: currentColor;
}

.about-back a:focus-visible {
    outline: 3px solid var(--focus-color);
    outline-offset: 2px;
    border-radius: 4px;
}

.about-title {
    font-weight: 600;
    line-height: 1.25;
}

.about-title-zh {
    display: block;
    margin-top: 0.25rem;
    font-family: var(--font-han-apparatus);
    font-weight: 400;
    font-size: 0.7em;
    color: #555;
}

.about-lead {
    font-size: 1.05rem;
    color: #444;
}

.about-section {
    margin-top: 2rem;
}

.about-section h2 {
    font-weight: 600;
    border-bottom: 1px solid #e4e4e4;
    padding-bottom: 0.3rem;
}

.about-section-zh {
    margin-left: 0.5rem;
    font-family: var(--font-han-apparatus);
    font-weight: 400;
    font-size: 0.7em;
    color: #555;
}

/* Authors are grouped by dynasty: a light period heading over its entries. */
.author-period {
    margin-top: 1.75rem;
}

.author-period > h3 {
    margin-bottom: 0.75rem;
    padding-bottom: 0.2rem;
    border-bottom: 1px solid #eee;
    font-weight: 600;
    font-size: 1.05rem;
    color: #555;
}

.author-period .period-zh {
    margin-left: 0.35rem;
    font-family: var(--font-han-apparatus);
    font-weight: 400;
    font-size: 0.85em;
    color: #888;
}

.author-period > div > h4 {
    margin: 0.9rem 0 0.2rem;
}

/* The stratigraphy list: each generation spaced out, its members indented, to
   echo the layered indentation used on the hexagram plates. */
.about-strata > li {
    margin-top: 0.9em;
}

.about-strata ul {
    margin-top: 0.4em;
}

.about-strata ul > li {
    margin-top: 0.3em;
}

/* A small pill marking which of the Ten Wings a commentary is. */
.wing-tag {
    display: inline-block;
    margin: 0 0.15em;
    padding: 0.05em 0.45em;
    border: 1px solid #d5d5d5;
    border-radius: 999px;
    background: #f6f6f6;
    font-size: 0.72em;
    font-variant: small-caps;
    letter-spacing: 0.04em;
    color: #666;
    white-space: nowrap;
    vertical-align: 0.08em;
}

/* Structural-terms definition list: each term stands out, its gloss indented. */
.about-page .term-list {
    margin: 0;
}

.about-page .term-list dt {
    font-weight: 600;
    margin-top: 0.9em;
}

.about-page .term-list dd {
    margin-left: 1.5em;
}

/* Bibliography: a hanging-indent list; CJK journal titles stay upright since
   synthetic italics on kai glyphs read poorly. */
.about-page .references {
    list-style: none;
    padding-left: 0;
    font-size: 0.95em;
}

.about-page .references li {
    padding-left: 1.5em;
    text-indent: -1.5em;
    margin-bottom: 0.9em;
}

.about-page .references cite[lang="zh-Hant"] {
    font-style: normal;
}

/* Plain prose links use a muted blue rather than the browser default. Wrapped in
   :where() so it adds no specificity: every special link kind (.cite, .person,
   .ref-backlink, .about-back a) keeps its own colour, and only otherwise-unstyled
   prose links pick this up. */
:where(.about-page a) {
    color: var(--link-color);
    text-underline-offset: 0.12em;
}

:where(.about-page a:hover, .about-page a:focus-visible) {
    color: #24445c;
}

/* --- Citations & references. The plain <a class="cite" href="#ref-…"> link is
   the no-JS base layer; about.js layers on the [n] marker, popover preview and
   back-links. All the enhancement styles degrade to nothing without the JS. --- */
.about-page .cite {
    color: inherit;
    text-decoration: none;
}

.about-page .cite:hover,
.about-page .cite:focus-visible {
    text-decoration: underline;
    text-underline-offset: 0.15em;
}

.about-page .cite-num {
    color: var(--hl-color);
    font-size: 0.72em;
    font-variant-numeric: tabular-nums;
    padding-left: 0.1em;
    text-decoration: none;
}

.about-page .ref-num {
    color: #777;
    font-variant-numeric: tabular-nums;
}

.about-page .references li:target {
    background: color-mix(in srgb, var(--hl-color) 14%, transparent);
    box-shadow: 0 0 0 0.35em color-mix(in srgb, var(--hl-color) 14%, transparent);
    border-radius: 2px;
}

.about-page .ref-backlinks {
    white-space: nowrap;
}

.about-page .ref-backlink {
    margin-left: 0.15em;
    color: var(--hl-color);
    font-size: 0.9em;
    text-decoration: none;
}

.about-page .ref-backlink:hover,
.about-page .ref-backlink:focus-visible {
    text-decoration: underline;
}

/* Popover is appended to <body>, so it is scoped by its own class, not
   .about-page. */
.cite-popover {
    position: absolute;
    z-index: 50;
    max-width: min(24rem, calc(100vw - 1rem));
    padding: 0.6em 0.8em;
    font-family: var(--font-serif);
    font-size: 0.85rem;
    line-height: 1.45;
    color: #4a4437;
    background: #fffdf6;
    border: 1px solid #d8d3c4;
    border-radius: 6px;
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.14);
}

.cite-popover[hidden] {
    display: none;
}

.cite-popover a {
    color: var(--hl-color);
}

@media (prefers-reduced-motion: no-preference) {
    .about-page .references li {
        transition: background 0.3s ease, box-shadow 0.3s ease;
    }
}

/* Inline Han text in the prose defaults to the regular-script (楷書) kai face,
   matching the app's Chinese body font. The seal/oracle legend glyphs opt out:
   they also carry lang="zh-Hant" but must keep their own display faces. */
.about-page [lang="zh-Hant"]:not(.glyph-seal):not(.glyph-oracle) {
    font-family: var(--font-han-apparatus);
}

/* Acronyms in small caps, e.g. <abbr class="sc">MWD</abbr>. all-small-caps (not
   small-caps) is needed because the text is already capitals, which plain
   small-caps leaves at full height. Source Serif 4's webfont ships no real
   small-cap glyphs, so these are the browser's synthesised small caps. */
.about-page abbr.sc {
    font-variant-caps: all-small-caps;
    letter-spacing: 0.03em;
    text-decoration: none;
}

/* Person links point to that person's entry in "Authors & schools". Rendered
   small-caps; their dates and Chinese name live in the entry, so are omitted
   inline (see AGENTS.md). */
.about-page a.person {
    font-variant-caps: small-caps;
    color: inherit;
    text-decoration-line: underline;
    text-decoration-color: color-mix(in srgb, currentColor 35%, transparent);
    text-underline-offset: 0.15em;
}

.about-page a.person:hover,
.about-page a.person:focus-visible {
    text-decoration-color: currentColor;
}

/* --- "Images of the trigrams": one entry per trigram, its figure beside the
   name/image, with a prose slot for the author's comparison. Each entry exposes
   its trigram's palette colour via data-tri, tinting the figure. --- */

.trigram-images {
    margin: 1.5rem 0 0;
    display: flex;
    flex-direction: column;
    gap: 1.5rem;
}

.trigram-image-entry {
    display: grid;
    grid-template-columns: 3.5rem 1fr;
    column-gap: 1rem;
    align-items: baseline;
}

.trigram-image-head {
    display: contents;
    font-weight: normal;
    font-size: 1rem;
}

/* After the heading (display:contents) the prose, category labels and glyph
   lists are direct grid items; keep them all in the content column. */
.trigram-image-entry > :not(.trigram-image-head) {
    grid-column: 2;
    margin: 0.35rem 0 0;
}

.trigram-image-figure {
    grid-column: 1;
    /* Span every row of the entry so the sticky figure can travel the whole
       column. A large span (rather than -1, which only counts explicit grid
       lines) reliably reaches the last implicit row. */
    grid-row: 1 / span 9999;
    align-self: start;
    position: sticky;
    top: 1rem;
    font-family: var(--font-symbol);
    font-size: 2.6rem;
    line-height: 1;
    color: var(--tri-color, var(--line-color));
}

.trigram-image-label {
    grid-column: 2;
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.4rem 0.6rem;
}

.trigram-image-name {
    font-family: var(--font-han);
    font-size: 1.3rem;
    color: var(--tri-color, inherit);
}

.trigram-image-pinyin {
    color: #666;
}

.trigram-image-mwd,
.trigram-image-shifa {
    color: #666;
}

.trigram-image-mwd abbr,
.trigram-image-shifa abbr {
    font-size: 0.82em;
    letter-spacing: 0.04em;
    color: #999;
    text-decoration: none;
    border-bottom: 1px dotted #bbb;
    cursor: help;
}

.trigram-image-shifa [title] {
    border-bottom: 1px dotted #bbb;
    cursor: help;
}

.trigram-image-image {
    font-variant: small-caps;
    letter-spacing: 0.02em;
    color: #444;
}

.trigram-image-note {
    grid-column: 2;
    margin: 0.35rem 0 0;
}

/* Per-category label heading (Attributes, Animal, …) above each glyph list,
   set as a quiet label rather than a bold heading. The child-combinator selector
   matches the general .trigram-image-entry content rule's specificity so this
   margin wins over its default. */
.trigram-image-entry > .attr-head {
    margin: 1.4rem 0 0.2rem;
    font-family: inherit;
    font-size: 0.85rem;
    font-weight: 600;
    letter-spacing: 0;
    color: #777;
}

.attr-head .attr-source {
    margin-left: 0.4em;
    font-family: var(--font-han-apparatus);
    font-size: 0.85em;
    font-weight: normal;
    color: #aaa;
    white-space: nowrap;
}

.shuogua-source {
    margin-top: 1.5rem;
    font-size: 0.85rem;
    color: #777;
}

.shuogua-source a {
    color: inherit;
}

/* --- Reference glyphs: seal (崇羲篆體) and oracle-bone (Oracular) forms, shown as
   committed per-character SVGs (assets/glyphs/) beside the modern character. --- */

/* Each association is a full-width row: the modern/seal/oracle glyphs on the left,
   the gloss pushed to the right, and an optional author commentary block beneath. */
.glyph-list {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    margin: 0.1rem 0 0;
}

.glyph-unit {
    padding: 0.2rem 0.35rem;
    border-radius: 4px;
}

.glyph-unit:hover {
    background: #f7f5ef;
}

.glyph-row {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.1rem 0.35rem;
}

.glyph {
    line-height: 1.15;
    text-align: center;
}

/* Middot separator between adjacent script variants (kai · seal · oracle).
   The gloss is not a .glyph, so no separator precedes it. */
.glyph + .glyph::before {
    content: "·";
    margin: 0 0.2em;
    font-family: var(--font-serif);
    font-size: 1rem;
    color: #b8b0a0;
}

.glyph-kai {
    font-family: var(--font-han-apparatus);
    color: #333;
}

.glyph-seal,
.glyph-bronze,
.glyph-oracle {
    display: inline-flex;
    align-items: baseline;
    gap: 0.1em;
}

/* Per-character seal/oracle SVG. The ink colour is baked into the file (an <img>
   is an isolated document and does not inherit currentColor), so we only size it
   here; width follows the glyph's own aspect ratio. Seal is inky blue, oracle
   brown; verdigris green is reserved for the bronze silhouettes below. */
.glyph-char {
    height: 1.6em;
    width: auto;
    vertical-align: -0.4em;
}

/* Geta 〓: this script has no form for the character. */
.glyph-geta {
    color: #b7ab97;
    font-size: 1.1em;
}

/* A category with no associations for this trigram (e.g. 乾 has no Additional). */
.glyph-empty {
    color: #c4bdb0;
}

/* Gloss sits at the right-hand end of the row, opposite the glyphs. */
.glyph-gloss {
    margin-left: auto;
    padding-left: 1rem;
    max-width: 22em;
    font-family: var(--font-serif);
    font-size: 0.9rem;
    line-height: 1.3;
    text-align: right;
    color: #8a7f6a;
}

/* Where Legge and Baynes disagree, both are shown with small L / B source tags. */
.glyph-gloss.is-divergent {
    max-width: 24em;
}

.glyph-gloss .gloss-src {
    margin-left: 0.1em;
    font-size: 0.72em;
    font-weight: 600;
    letter-spacing: 0.02em;
    color: #b8ac93;
}

/* Author commentary beneath a row: interpretation of how the figure/character
   relate. Optional, hand-written, and preserved by tools/gen-trigram-glyphs.mjs.
   One or more <p class="glyph-note"> may follow a .glyph-row inside a .glyph-unit. */
.glyph-note {
    margin: 0.35rem 0 0.1rem 0.2rem;
    padding: 0.1rem 0 0.1rem 0.75rem;
    border-left: 2px solid #d8d3c4;
    font-family: var(--font-serif);
    font-size: 0.9rem;
    line-height: 1.55;
    color: #4a4437;
}

/* Consecutive commentary paragraphs share one continuous left rule. */
.glyph-note + .glyph-note {
    margin-top: 0;
}

.glyph-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem 1.4rem;
    margin: 0 0 1.1rem;
    padding: 0.6rem 0.8rem;
    background: #f7f5ef;
    border: 1px solid #e6e1d5;
    border-radius: 6px;
    font-size: 0.9rem;
    color: #555;
}

.glyph-legend > span {
    display: inline-flex;
    align-items: baseline;
    gap: 0.45rem;
}

.glyph-legend .glyph-seal,
.glyph-legend .glyph-bronze,
.glyph-legend .glyph-oracle,
.glyph-legend .glyph-kai {
    font-size: 1.4em;
}

/* Inline trigram figures generated from <tri> references (see
   tools/gen-trigram-svgs.mjs). The SVG uses currentColor and a viewBox, so it
   inherits the surrounding text colour. We fix the WIDTH (the glyph column is a
   constant 100 user units) and let the height follow the viewBox aspect ratio, so
   a 1- or 2-glyph figure stays proportionally shorter than a full 3-glyph stack. */
.tri-figure {
    display: inline-block;
    vertical-align: -0.2em;
    color: #4a4437;
}

.tri-figure svg {
    display: block;
    width: 1.5em;
    height: auto;
    overflow: visible;
}

/* Inline character-glyph image from an SVG asset (small-seal 小篆 name glyphs in
   assets/seal/, or Zhou bronze 金文 forms in assets/wiktionary/), referenced as an
   <img>. Loaded this way the SVG's currentColor resolves to its own default (near
   black) rather than the surrounding text colour. Sized to sit as a character in
   running prose; decorative (the readable character precedes it). */
.inline-glyph {
    display: inline-block;
    height: 1.5em;
    width: auto;
    vertical-align: -0.25em;
}

/* Masked silhouette glyphs from single-path SVGs (assets/wiktionary/): the SVG's
   shape is the mask and the box is filled with an ink colour, so we can tint the
   otherwise-black outline. Zhou bronze (金文) uses the verdigris --bronze-ink;
   oracle-bone (甲骨) silhouettes from Wiktionary use the cinnabar --oracle-ink.
   The file path is passed per glyph in the inline --glyph-src; a square box +
   mask-size:contain keeps every glyph a uniform inline size. */
.bronze-glyph,
.about-page .seal-relief,
.about-page .oracle-relief {
    display: inline-block;
    width: 1.5em;
    height: 1.5em;
    vertical-align: -0.35em;
    -webkit-mask: var(--glyph-src) center / contain no-repeat;
    mask: var(--glyph-src) center / contain no-repeat;
}

.bronze-glyph {
    background-color: var(--bronze-ink, #2f6b57);
}

.about-page .oracle-relief {
    background-color: var(--oracle-ink, #8b1a1a);
}

.about-page .seal-relief {
    background-color: var(--seal-ink, #2b3a5c);
}

/* Oracle-bone (甲骨文) character glyph, inlining an SVG from assets/oracle/ that
   fills with currentColor (used where a crisp repo asset exists, e.g. hexagram
   names). Coloured the same cinnabar red; the inline SVG self-sizes by its own
   (tall) aspect ratio. External Wiktionary silhouettes use .oracle-relief above. */
.about-page .oracle-glyph {
    color: var(--oracle-ink, #8b1a1a);
}

.about-page .oracle-glyph svg {
    height: 1.5em;
    width: auto;
    vertical-align: -0.35em;
}
