:root {
    --timeline-rotation: -20deg;
    --timeline-text-width: 12em;

    /* Ground and ink. Not pure black on pure white - the ground is a hair
       cool, and the ink stops short of #000 so long reads are less harsh. */
    --bg: #fbfbfd;
    --ink: #15151b;
    --ink-2: #45454f;
    --ink-muted: #71717f;
    --rule: #e6e6ed;
    --tick: #d2d2dc;
    --tick-dot: #adadba;
    --hover-bg: #f3f3f7;

    /* Visited links only. Three steps darker than --ink-muted, which clears
       4.5:1 on --hover-bg (4.53:1) where the muted ink does not (4.34:1) - a
       visited link is hoverable, so it has to hold contrast on the tint too. */
    --link-visited: #6e6e7c;

    /* One hue, two steps - Japanese dark, English light. Two hues of similar
       lightness collapse for tritanopia (the old blue/emerald pair separated by
       only dE 5.4 there); two steps of one hue differ in lightness alone, which
       is the channel that survives every kind of colour blindness. A single hue
       also cannot read as a flag, which two of them always risk.

       Used at full strength everywhere they appear - the ratio chart, the
       summary swatches and the per-post size bar. The label colour has to follow
       the fill: white holds on the dark step and fails on the light one. */
    --lang-ja-color: #1d4ed8;
    --lang-en-color: #60a5fa;
    --lang-ja-label: #fff;
    --lang-en-label: var(--ink);

    /* Type scale */
    --t-h1: 1.55rem;
    --t-header: 1.25rem;
    --t-title: 1rem;
    --t-meta: 0.78rem;
    --t-micro: 0.72rem;

    /* Spacing ramp */
    --sp-1: 0.25rem;
    --sp-2: 0.5rem;
    --sp-3: 0.75rem;
    --sp-4: 1rem;
    --sp-6: 1.5rem;
}

body {
    font-family: sans-serif;
    margin: 0 1rem;
    color: var(--ink);
    background: var(--bg);
    line-height: 1.62;
}

/* Index rows bleed 12px past the column and the bilingual rails sit on that
   bleed edge, so the column needs at least 12px of margin outside it to have
   anywhere to put them. main is 50rem centred, which leaves the column at
   16px + max(0, (viewport - 832) / 2) - so the rails only clear 16px once the
   viewport passes 856px, and below 832px they are pinned 4px off the screen
   edge. Widening the margin under that threshold buys the room back. */
@media (max-width: 855px) {
    body {
        margin: 0 1.75rem;
    }
}

/* The text stays ink and the rule carries the colour, so a paragraph keeps an
   even weight. The rule uses the same two steps of blue as the language chart
   rather than a colour of its own. #60a5fa is far too weak to be type at
   2.5:1, but it is legible as a 2px rule, which is all it is asked to be. */
a {
    color: var(--ink);
    text-decoration-color: var(--lang-ja-color);
    text-decoration-thickness: 2px;
    text-underline-offset: 3px;
}

/* Hover tints rather than inverting, and the underline stays put - a link
   never stops looking like a link mid-interaction. Same surface the index rows
   use, so the whole site has one hover language. */
a:hover,
a:visited:hover {
    background: var(--hover-bg);
}

/* Visited mutes the text and drops the rule to the light step. Browsers only
   honour colour properties on :visited - text-decoration-style is dropped for
   privacy, so a dotted rule is not available here however well it would read.
   This rule sits after :hover so the visited colour survives being hovered. */
a:visited {
    color: var(--link-visited);
    text-decoration-color: var(--lang-en-color);
}
header {
    display: flex;
    justify-content: space-between;
    font-size: var(--t-header);
    border-bottom: 1px solid var(--ink);
    padding: var(--sp-4) 0;
    margin-bottom: var(--sp-6);
}
header a,
header a:visited {
    color: var(--ink);
    text-decoration: none;
}
header .ja {
    color: var(--ink-muted);
}

h1 {
    justify-content: space-between;
    font-size: var(--t-h1);
    letter-spacing: -0.01em;
}

h1 .ja {
    color: var(--ink-muted);
    font-size: var(--t-title);
    font-weight: normal;
}

article h2 {
    font-size: 1.2rem;
}

pre {
    white-space: pre-wrap;
    overflow-wrap: break-word;
}

main {
    max-width: 50rem;
    margin: 0 auto;
}

/* Article pages are read straight through, so they get a proper measure.
   The index keeps the wider column - its rows need the room. The footer
   follows along so its rule lines up with the content above it. */
body.article main,
body.article footer {
    max-width: 38rem;
}

ul.pages {
    list-style: none;
    padding: 0;
}

ul.pages li {
    padding: 1rem 0;
}

footer {
    max-width: 50rem;
    margin: var(--sp-6) auto;

    font-size: var(--t-meta);
    border-top: 1px solid var(--rule);
    padding: var(--sp-4) 0;
    color: var(--ink-muted);
}

table {
    width: 100%;
}

iframe[src*="youtube"] {
    max-width: 100%;
    height: auto;
    aspect-ratio: 16 / 9;
}

/* Mobile responsiveness */
@media (max-width: 768px) {
    header {
        flex-direction: column;
        align-items: flex-start;
        font-size: 1.2rem;
    }

    header .ja {
        margin-top: 0.4rem;
    }

    h1 {
        font-size: 1.5rem;
    }
}

.pages span.header {
    display: none;
}

table.pages {
    position: relative;
}

table.pages th {
    position: sticky;
    top: 0;
    text-align: left;
    padding-bottom: 1rem;
    background-image: linear-gradient(to bottom, var(--bg), var(--bg) 50%, rgba(251, 251, 253, 0));
}

@media (max-width: 480px) {
    header {
        font-size: 1.2rem;
        padding: 0.8rem 0;
    }

    h1 {
        font-size: 1.2rem;
    }

    ul.pages li {
        padding: 0.8rem 0;
    }

    .pages thead {
        display: none;
    }

    .pages td {
        display: block;
    }

    .pages span.header {
        display: inline;
    }

    .pages td:last-child {
        padding-bottom: 1rem;
    }
}

/* The per-post size bar. Same hue as the ratio chart, at the same strength -
   one colour per language, wherever it appears. */
.bar {
    height: 22px;
    border-radius: 0;
    display: flex;
    align-items: center;
    padding: 0 var(--sp-2);
    font-size: var(--t-meta);
    white-space: nowrap;
    min-width: fit-content;
}

/* Rows are separated by a hairline rather than boxed. Nothing on the index
   is outlined at full strength, so the coloured marks stay the loudest thing. */
#index article {
    margin-bottom: 0;
    padding: 0;
    border-bottom: 1px solid var(--rule);
}

#index h2 {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--sp-1);
    font-size: var(--t-title);
    margin: 0;
    padding: 0;
}

#index h2 a {
    text-decoration: none;
    color: inherit;
}

/* The link bleeds wider than the text column and pads the same amount back,
   so the hover surface gets breathing room on both sides while the text
   itself stays on the column edge, lined up with the header and footer
   rules. The row's own hairline stays on the column, so it doesn't inherit
   the bleed. */
#index .article-link {
    display: block;
    text-decoration: none !important;
    color: inherit;
    position: relative;
    padding: var(--sp-4) var(--sp-3);
    margin: 0 calc(var(--sp-3) * -1);
}

#index .article-link:hover,
#index .article-link:active,
#index .article-link:focus {
    text-decoration: none !important;
    background: var(--hover-bg);
    color: inherit;
}

#index .article-link h2 {
    color: var(--ink);
}

.page-metadata {
    margin: var(--sp-1) 0 var(--sp-3) 0;
    font-size: var(--t-meta);
    color: var(--ink-muted);
    position: relative;
}

/* Rotate each li individually rather than the ul, because CSS transform
   doesn't change the element's bounding box - a rotated ul would still
   occupy its pre-rotation space and cause overlap with surrounding content. */
.page-metadata .changes-items {
    display: flex;
    flex-wrap: wrap;
    gap: 0;
    margin: 0;
    padding: calc(abs(sin(var(--timeline-rotation))) * var(--timeline-text-width)) 0 0 0;
    list-style: none;
    align-items: flex-end;
}

.page-metadata .changes-items li {
    transform: rotate(var(--timeline-rotation));
    transform-origin: bottom left;
    white-space: nowrap;
    /* Tuned so the vertical gap between consecutive labels lands at about
       one line-height - the tightest spacing that stays legible. Loosening
       it widens the row enough to wrap, which breaks the cascade. */
    margin-right: -6rem;
    font-size: var(--t-meta);
}

.page-metadata .changes-items li::before {
    content: '●';
    margin-right: 0.4rem;
    font-size: 0.5rem;
    line-height: 0;
    vertical-align: middle;
    color: var(--tick-dot);
}

.language-ratio {
    margin-bottom: var(--sp-6);
    padding: 0;
    border: none;
}

/* The per-post size bar in .meta. Each carries its own label colour, so the
   two bars differ in fill lightness and in label - identity never rests on
   colour alone. */
.ja-bar {
    background: var(--lang-ja-color);
    color: var(--lang-ja-label);
}

.en-bar {
    background: var(--lang-en-color);
    color: var(--lang-en-label);
}

/* Sits under the chart: the chart is the visual, this is its caption. */
.ratio-summary {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    gap: 0 var(--sp-4);
    margin-top: var(--sp-2);
    font-size: var(--t-meta);
    color: var(--ink);
}

.ratio-trend {
    display: block;
    width: 100%;
    height: 48px;
    border-radius: 0;
}

.ratio-area-ja {
    fill: var(--lang-ja-color);
}

.ratio-area-en {
    fill: var(--lang-en-color);
}

.ratio-trend-labels {
    display: flex;
    flex-direction: row;
    justify-content: space-between;
    font-size: var(--t-micro);
    color: var(--ink-muted);
    margin-top: var(--sp-1);
}

/* Identity comes from the swatch, so the words stay in ink - a hue picked
   for a 48px fill is not a hue that reads well at 12px. */
.lang-tag {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-1);
    border-radius: 0;
    font-size: var(--t-meta);
    white-space: nowrap;
    vertical-align: baseline;
}

.lang-swatch {
    display: block;
    width: 9px;
    height: 9px;
    flex: none;
}

.lang-tag.lang-ja .lang-swatch {
    background: var(--lang-ja-color);
}

.lang-tag.lang-en .lang-swatch {
    background: var(--lang-en-color);
}

.lang-tag .lang-count {
    font-style: normal;
    color: var(--ink-muted);
}

/* An eyebrow above the title rather than a filled badge beside it, so it
   never competes with the title horizontally. */
.directory-tag {
    display: inline-block;
    padding: 0;
    border-radius: 0;
    font-size: var(--t-micro);
    font-weight: 500;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--ink-muted);
    background: none;
    white-space: nowrap;
    margin-right: 0;
}

/* A bilingual pair is one post written twice, so it has to read as a pair.
   Two cues do that: the halves sit closer to each other than to neighbouring
   posts, and a rail runs down the bleed margin on each side of them. The rails
   are inset top and bottom so the pair reads as bracketed rather than boxed. */
.language-section {
    margin-bottom: 0;
    padding-bottom: 0;
    border-bottom: none;
}

#index article:has(.language-section) {
    position: relative;
}

/* z-index because the rails and the row's hover surface sit at the same x.
   Both are positioned with z-index auto, so they would paint in tree order and
   the hover surface - being the later sibling - would cover the rail up,
   breaking the bracket apart at the moment the row is pointed at. */
#index article:has(.language-section)::before,
#index article:has(.language-section)::after {
    content: "";
    position: absolute;
    top: var(--sp-6);
    bottom: var(--sp-6);
    width: 2px;
    background: var(--tick);
    z-index: 1;
}

#index article:has(.language-section)::before {
    left: calc(var(--sp-3) * -1);
}

#index article:has(.language-section)::after {
    right: calc(var(--sp-3) * -1);
}

#index .language-section .article-link {
    padding-top: var(--sp-2);
    padding-bottom: var(--sp-2);
}

#index .language-section:first-child .article-link {
    padding-top: var(--sp-4);
}

#index .language-section:last-child .article-link {
    padding-bottom: var(--sp-4);
}

/* A post's own section headings, shown as a table of contents. Separated by
   hairline ticks rather than slashes, so the list reads as structure rather
   than as a run of punctuation. */
.headlines {
    display: flex;
    flex-wrap: wrap;
    gap: 0 var(--sp-3);
    list-style: none;
    margin: var(--sp-1) 0 0 0;
    padding: 0;
    font-size: var(--t-meta);
    line-height: 1.5;
    color: var(--ink-muted);
}

.headlines li {
    position: relative;
}

.headlines li + li::before {
    content: "";
    position: absolute;
    left: calc(var(--sp-3) / -2);
    top: 0.42em;
    width: 1px;
    height: 0.85em;
    background: var(--tick);
}

@media (max-width: 480px) {
    .ratio-trend {
        height: 36px;
    }
}
