/* Lichfield chess components — diagrams, puzzles, league tables.
   Loaded unconditionally by default.hbs; the matching JS bails early
   when no .chess-diagram / .chess-puzzle / .league-table is on the page. */

.chess-diagram-wrapper,
.chess-puzzle-wrapper {
    margin: 1.5em auto;
    width: 100%;
    max-width: 480px;
    /* Defensively reset min-width: grid items default to min-content which
       can collapse the wrapper when aspect-ratio is set on a child. */
    min-width: 0;
}

/* --- Board themes -------------------------------------------------------- */
/* The default brown theme comes from chessground.brown.css. Each named
   theme below overrides cg-board with a 2×2 tiled SVG of two squares
   (one transparent, one filled). 25% tile size ⇒ tiled 4× = 8×8 squares.
   Apply via class chess-theme-<name> on the wrapper (set by chess.js
   from the data-theme attribute). */
.chess-theme-blue cg-board {
    background-color: #dee3e6;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 2 2' shape-rendering='crispEdges'%3E%3Cpath fill='%238ca2ad' d='M1 0h1v1H1zM0 1h1v1H0z'/%3E%3C/svg%3E");
    background-size: 25% 25%;
}
.chess-theme-green cg-board {
    background-color: #ffffdd;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 2 2' shape-rendering='crispEdges'%3E%3Cpath fill='%23769656' d='M1 0h1v1H1zM0 1h1v1H0z'/%3E%3C/svg%3E");
    background-size: 25% 25%;
}
.chess-theme-grey cg-board {
    background-color: #ebebeb;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 2 2' shape-rendering='crispEdges'%3E%3Cpath fill='%23808080' d='M1 0h1v1H1zM0 1h1v1H0z'/%3E%3C/svg%3E");
    background-size: 25% 25%;
}
.chess-theme-wood cg-board {
    background-color: #d8b074;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 2 2' shape-rendering='crispEdges'%3E%3Cpath fill='%237a4a1f' d='M1 0h1v1H1zM0 1h1v1H0z'/%3E%3C/svg%3E");
    background-size: 25% 25%;
}
.chess-theme-pink cg-board {
    background-color: #fde6f1;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 2 2' shape-rendering='crispEdges'%3E%3Cpath fill='%23c75d8e' d='M1 0h1v1H1zM0 1h1v1H0z'/%3E%3C/svg%3E");
    background-size: 25% 25%;
}

/* --- Piece sets ---------------------------------------------------------- */
/* Default pieces (Cburnett) come from chessground.cburnett.css. Each named
   set below pulls SVGs from Lichess's CDN. Apply via class
   chess-pieces-<name> on the wrapper (set by chess.js from data-pieces). */
.chess-pieces-alpha .cg-wrap piece.pawn.white   { background-image: url('https://lichess1.org/assets/piece/alpha/wP.svg'); }
.chess-pieces-alpha .cg-wrap piece.pawn.black   { background-image: url('https://lichess1.org/assets/piece/alpha/bP.svg'); }
.chess-pieces-alpha .cg-wrap piece.knight.white { background-image: url('https://lichess1.org/assets/piece/alpha/wN.svg'); }
.chess-pieces-alpha .cg-wrap piece.knight.black { background-image: url('https://lichess1.org/assets/piece/alpha/bN.svg'); }
.chess-pieces-alpha .cg-wrap piece.bishop.white { background-image: url('https://lichess1.org/assets/piece/alpha/wB.svg'); }
.chess-pieces-alpha .cg-wrap piece.bishop.black { background-image: url('https://lichess1.org/assets/piece/alpha/bB.svg'); }
.chess-pieces-alpha .cg-wrap piece.rook.white   { background-image: url('https://lichess1.org/assets/piece/alpha/wR.svg'); }
.chess-pieces-alpha .cg-wrap piece.rook.black   { background-image: url('https://lichess1.org/assets/piece/alpha/bR.svg'); }
.chess-pieces-alpha .cg-wrap piece.queen.white  { background-image: url('https://lichess1.org/assets/piece/alpha/wQ.svg'); }
.chess-pieces-alpha .cg-wrap piece.queen.black  { background-image: url('https://lichess1.org/assets/piece/alpha/bQ.svg'); }
.chess-pieces-alpha .cg-wrap piece.king.white   { background-image: url('https://lichess1.org/assets/piece/alpha/wK.svg'); }
.chess-pieces-alpha .cg-wrap piece.king.black   { background-image: url('https://lichess1.org/assets/piece/alpha/bK.svg'); }

.chess-pieces-staunty .cg-wrap piece.pawn.white   { background-image: url('https://lichess1.org/assets/piece/staunty/wP.svg'); }
.chess-pieces-staunty .cg-wrap piece.pawn.black   { background-image: url('https://lichess1.org/assets/piece/staunty/bP.svg'); }
.chess-pieces-staunty .cg-wrap piece.knight.white { background-image: url('https://lichess1.org/assets/piece/staunty/wN.svg'); }
.chess-pieces-staunty .cg-wrap piece.knight.black { background-image: url('https://lichess1.org/assets/piece/staunty/bN.svg'); }
.chess-pieces-staunty .cg-wrap piece.bishop.white { background-image: url('https://lichess1.org/assets/piece/staunty/wB.svg'); }
.chess-pieces-staunty .cg-wrap piece.bishop.black { background-image: url('https://lichess1.org/assets/piece/staunty/bB.svg'); }
.chess-pieces-staunty .cg-wrap piece.rook.white   { background-image: url('https://lichess1.org/assets/piece/staunty/wR.svg'); }
.chess-pieces-staunty .cg-wrap piece.rook.black   { background-image: url('https://lichess1.org/assets/piece/staunty/bR.svg'); }
.chess-pieces-staunty .cg-wrap piece.queen.white  { background-image: url('https://lichess1.org/assets/piece/staunty/wQ.svg'); }
.chess-pieces-staunty .cg-wrap piece.queen.black  { background-image: url('https://lichess1.org/assets/piece/staunty/bQ.svg'); }
.chess-pieces-staunty .cg-wrap piece.king.white   { background-image: url('https://lichess1.org/assets/piece/staunty/wK.svg'); }
.chess-pieces-staunty .cg-wrap piece.king.black   { background-image: url('https://lichess1.org/assets/piece/staunty/bK.svg'); }

/* --- Floated alignment --------------------------------------------------- */
/* When data-align="left|right" is set, the board floats inside the same
   HTML card so subsequent text in that card wraps around it. Ghost wraps
   each editor block in its own container, so float doesn't escape into
   later paragraph blocks — diagram + wrapping prose must share one card. */
.chess-diagram-wrapper.chess-align-left,
.chess-puzzle-wrapper.chess-align-left {
    float: left;
    margin: 0.4em 1.6em 0.8em 0;
    max-width: 360px;  /* default size when floated */
}

.chess-diagram-wrapper.chess-align-right,
.chess-puzzle-wrapper.chess-align-right {
    float: right;
    margin: 0.4em 0 0.8em 1.6em;
    max-width: 360px;
}

/* --- Explicit sizing ----------------------------------------------------- */
/* Listed after the align rules so size always wins when both are set. */
.chess-diagram-wrapper.chess-size-small,
.chess-puzzle-wrapper.chess-size-small {
    max-width: 240px;
}
.chess-diagram-wrapper.chess-size-medium,
.chess-puzzle-wrapper.chess-size-medium {
    max-width: 360px;
}
.chess-diagram-wrapper.chess-size-large,
.chess-puzzle-wrapper.chess-size-large {
    max-width: 640px;
}

/* On phones, drop the float so boards never get squashed in a narrow column. */
@media (max-width: 600px) {
    .chess-diagram-wrapper.chess-align-left,
    .chess-diagram-wrapper.chess-align-right,
    .chess-puzzle-wrapper.chess-align-left,
    .chess-puzzle-wrapper.chess-align-right {
        float: none;
        margin: 1.5em auto;
        max-width: 100%;
    }
}

/* Grid: 18px rank-label column + board, 18px file-label row below. The grid
   is square overall, so the board cell is (W-18)x(H-18) and stays square. */
.chess-board-grid {
    display: grid;
    grid-template-columns: 18px 1fr;
    grid-template-rows: 1fr 18px;
    aspect-ratio: 1 / 1;
    width: 100%;
}

.chess-board-grid .cg-wrap {
    grid-column: 2;
    grid-row: 1;
    width: 100%;
    height: 100%;
}

.chess-coords-corner {
    grid-column: 1;
    grid-row: 2;
}

.chess-coords {
    display: flex;
    align-items: center;
    justify-content: space-around;
    font-size: 11px;
    font-weight: 600;
    color: #5a5a5a;
    user-select: none;
}

.chess-coords-ranks {
    grid-column: 1;
    grid-row: 1;
    flex-direction: column;
}

.chess-coords-files {
    grid-column: 2;
    grid-row: 2;
    flex-direction: row;
}

.chess-diagram-caption,
.chess-puzzle-caption {
    text-align: center;
    font-size: 0.95em;
    color: #6b6b6b;
    margin-top: 0.5em;
    font-style: italic;
    line-height: 1.35;
}

.chess-puzzle-controls {
    display: flex;
    gap: 0.5em;
    justify-content: center;
    margin-top: 0.75em;
}

.chess-puzzle-controls button {
    font: inherit;
    padding: 0.4em 0.9em;
    border: 1px solid currentColor;
    background: transparent;
    border-radius: 4px;
    cursor: pointer;
}

.chess-puzzle-solution {
    margin-top: 0.75em;
    padding: 0.6em 0.8em;
    border-left: 3px solid #4a8;
    background: rgba(74, 136, 136, 0.06);
    font-family: ui-monospace, "SF Mono", Menlo, monospace;
    font-size: 0.9em;
}

.league-table-wrapper {
    /* Slightly bigger top margin so the table breathes away from the
       paragraph above it. Applies whether or not a title is rendered,
       since the wrapper is always the outer element. */
    margin: 1.2em 0 0.6em;
    overflow-x: auto;
}

/* Reserve space for the un-rendered <div class="league-table"> placeholder.
   Sized to match the height that a collapsed <details> renders at —
   roughly summary line-height (1.25em title × 1.2 ≈ 30px) — so chess.js
   replacing the placeholder is approximately layout-neutral. The page's
   scrollbar gutter is reserved via html { scrollbar-gutter: stable } in
   branding.css, so even minor residual shifts don't change the viewport
   width and trigger vw-based clamps in the hero. */
.league-table[data-league] {
    display: block;
    min-height: 32px;
    margin: 1.2em 0 0.6em;
}
.league-table-placeholder { color: #888; min-height: 24px; }

.league-table-wrapper table {
    /* min-width (not width) so the table can grow wider than its wrapper on
       narrow viewports; the wrapper's overflow-x:auto then provides a
       horizontal scroll. With plain width:100% the table was being forced
       into the viewport and the team column got squeezed to single-character
       width on phones. */
    min-width: 100%;
    border-collapse: collapse;
    font-size: 0.95em;
}

.league-table-wrapper th,
.league-table-wrapper td {
    padding: 0.4em 0.6em;
    text-align: left;
    border-bottom: 1px solid rgba(0, 0, 0, 0.08);
    /* Stop cells wrapping. On narrow viewports the table grows wider than the
       wrapper and the wrapper's overflow-x:auto kicks in, giving a horizontal
       scroll. Without this, "played"/"points"/"drawn" etc. wrap one letter
       per line because the columns get squeezed below their text width. */
    white-space: nowrap;
}
/* The team column is the only one that can legitimately need to wrap (long
   club names). It's the second column in every preset, so override it back
   to normal wrapping. */
.league-table-wrapper th:nth-child(2),
.league-table-wrapper td:nth-child(2) {
    white-space: normal;
}

.league-table-wrapper th {
    font-weight: 600;
    background: rgba(0, 0, 0, 0.03);
}

.league-table-wrapper tr.is-lichfield {
    font-weight: 600;
    background: rgba(255, 200, 0, 0.08);
}

.league-table-meta {
    /* !important needed to beat Source's .gh-content content-spacing rule
       which injects 48px of top margin onto any non-card/non-table that
       follows a table. */
    margin-top: 0.6em !important;
    font-size: 0.8em;
    color: #888;
    text-align: right;
}

/* Inside the league-table block, suppress Source's 48px content-spacing
   gap between the title (summary or h3) and the table itself. We use
   !important rather than chasing specificity because the source rule
   targets the table directly with adjacent-sibling logic that's awkward
   to override otherwise. 0.6em gives a small but visible breathing room
   below the title. */
.gh-content .league-table-wrapper table { margin-top: 0.8em !important; }

.league-table-error {
    padding: 0.8em 1em;
    border-left: 3px solid #c44;
    background: rgba(196, 68, 68, 0.06);
    color: #933;
    font-size: 0.95em;
}
/* Inline retry button used by .league-table-error in the game viewer's
   failure state. */
.league-table-error .chess-game-retry {
    margin-left: 0.6em;
    padding: 0.2em 0.7em;
    font: inherit;
    font-size: 0.9em;
    background: #fff;
    border: 1px solid #c44;
    border-radius: 4px;
    color: #933;
    cursor: pointer;
}
.league-table-error .chess-game-retry:hover {
    background: #fbeaea;
}

.league-table-title {
    margin: 0 0 0.6em;
    font-size: 1.25em;
    font-weight: 600;
    color: var(--ghost-accent-color, #2e7d32);
    line-height: 1.2;
}

/* Collapsible mode — the league title is rendered as <summary> inside a
   <details> element so readers can toggle the table by clicking it.
   The default browser disclosure triangle is hidden in favour of a custom
   chevron drawn from CSS borders, which rotates 90° when the table opens. */
.league-table-collapsible > summary.league-table-title {
    cursor: pointer;
    list-style: none;          /* Firefox / standard */
    user-select: none;
    /* Spacing matches the non-collapsible h3 so layouts stay consistent. */
    display: flex;
    align-items: center;
    gap: 0.5em;
}
.league-table-collapsible > summary.league-table-title::-webkit-details-marker {
    display: none;             /* Safari / Chrome legacy */
}
.league-table-collapsible > summary.league-table-title::before {
    content: "";
    flex: 0 0 auto;
    width: 0.45em;
    height: 0.45em;
    border-right: 0.14em solid currentColor;
    border-bottom: 0.14em solid currentColor;
    transform: rotate(-45deg);
    transition: transform 0.2s ease;
    margin-bottom: 0.15em;     /* optical centring against the title cap-height */
}
.league-table-collapsible[open] > summary.league-table-title::before {
    transform: rotate(45deg);
}
/* Subtle hover treatment so the click affordance isn't only the cursor. */
.league-table-collapsible > summary.league-table-title:hover {
    color: color-mix(in srgb, var(--ghost-accent-color, #2e7d32) 75%, #000);
}

.league-table-narrow {
    max-width: 420px;
    margin-left: auto;
    margin-right: auto;
}
.league-table-narrow .league-table-title {
    font-size: 1.1em;
}
.league-table-narrow table {
    font-size: 0.88em;
}
.league-table-narrow th,
.league-table-narrow td {
    padding: 0.32em 0.5em;
}

/* Ellipsis row separating top-N from a Lichfield-out-of-limit row. */
.league-table-wrapper tr.league-table-gap td {
    text-align: center;
    color: #aaa;
    border-bottom: 1px dashed rgba(0, 0, 0, 0.12);
    padding: 0.15em 0.4em;
    font-size: 0.85em;
}

/* --- Interactive PGN game viewer ---------------------------------------- */
/* Mobile-first stack; on wider viewports the move list sits beside the
   board. Variants on .chess-game-wrapper share the size/align/theme hooks
   from .chess-diagram-wrapper. */

.chess-game-wrapper {
    margin: 1.5em auto;
    width: 100%;
    max-width: 720px;
    min-width: 0;
    font-size: 0.95em;
    color: #2a2a2a;
}

.chess-game-loading {
    color: #888;
    text-align: center;
    padding: 2em 1em;
    font-style: italic;
}

.chess-game-title {
    margin: 0 0 0.4em;
    font-size: 1.25em;
    font-weight: 600;
    color: var(--ghost-accent-color, #2e7d32);
    line-height: 1.2;
}

/* Collapsible mode (mirrors the league-table-collapsible pattern). */
.chess-game-collapsible > summary.chess-game-title {
    cursor: pointer;
    list-style: none;
    user-select: none;
    display: flex;
    align-items: center;
    gap: 0.5em;
}
.chess-game-collapsible > summary.chess-game-title::-webkit-details-marker { display: none; }
.chess-game-collapsible > summary.chess-game-title::before {
    content: "";
    flex: 0 0 auto;
    width: 0.45em;
    height: 0.45em;
    border-right: 0.14em solid currentColor;
    border-bottom: 0.14em solid currentColor;
    transform: rotate(-45deg);
    transition: transform 0.2s ease;
    margin-bottom: 0.15em;
}
.chess-game-collapsible[open] > summary.chess-game-title::before {
    transform: rotate(45deg);
}

.chess-game-meta {
    color: #5a5a5a;
    font-size: 0.92em;
    margin-bottom: 0.6em;
    line-height: 1.5;
}
.chess-game-meta .chess-game-result {
    font-weight: 600;
    color: #2a2a2a;
}

.chess-game-body {
    display: grid;
    grid-template-columns: 1fr;
    gap: 0.7em;
}

.chess-game-board {
    /* Reuse the diagram aspect-ratio grid; full available width. */
    width: 100%;
    margin: 0 auto;
    max-width: 480px;
}

.chess-game-controls {
    display: flex;
    align-items: center;
    gap: 0.4em;
    flex-wrap: wrap;
    justify-content: center;
}
.chess-game-btn {
    font: inherit;
    padding: 0.35em 0.7em;
    min-width: 2.4em;
    /* Flex-centre the glyph. Without this the button uses inline-baseline
       layout, which puts ◀/▶ (centred on the baseline) and ⇤/⇥ (which sit
       lower than baseline) at visibly different vertical positions inside
       their identical-sized buttons. */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid #c8c8c8;
    background: #fff;
    border-radius: 4px;
    cursor: pointer;
    line-height: 1;
    color: #2a2a2a;
    transition: background 0.12s, border-color 0.12s;
}
.chess-game-btn:hover:not(:disabled) {
    background: #f3f3f3;
    border-color: #999;
}
.chess-game-btn:disabled {
    opacity: 0.4;
    cursor: not-allowed;
}
/* Visually scale the start/end glyphs (⇤ / ⇥) without affecting the
   button's own size. transform:scale doesn't take part in layout, so
   the button box stays identical to the prev/next buttons; only the
   glyph is rendered larger. */
.chess-game-glyph-lg {
    display: inline-block;
    transform: scale(1.4);
    transform-origin: center;
    position: relative;
}
/* Mobile (iOS Safari especially) renders ⇤ / ⇥ with the ink-box
   sitting lower in the line-box than the filled triangles ◀ / ▶, so
   flex-centering puts them visually below the triangles. Desktop
   system fonts don't have this offset, so we scope the correction to
   the mobile breakpoint only — applying it everywhere knocks desktop
   out of alignment. */
@media (max-width: 600px) {
    .chess-game-glyph-lg { top: -2px; }
}
.chess-game-btn.chess-game-copy {
    /* Set apart from the playback group; nudged right via auto margin. */
    margin-left: auto;
    font-size: 0.88em;
    padding: 0.35em 0.8em;
    color: var(--ghost-accent-color, #2e7d32);
    border-color: color-mix(in srgb, var(--ghost-accent-color, #2e7d32) 35%, #ccc);
}
.chess-game-position {
    font-variant-numeric: tabular-nums;
    color: #5a5a5a;
    font-size: 0.9em;
    padding: 0 0.4em;
    min-width: 4em;
    text-align: center;
}

.chess-game-moves {
    list-style: none;
    margin: 0;
    padding: 0.4em 0;
    border-top: 1px solid #e5e5e5;
    max-height: 320px;
    overflow-y: auto;
    line-height: 1.6;
}
.chess-game-moves li {
    display: flex;
    align-items: baseline;
    gap: 0.2em;
    padding: 0.05em 0.3em;
}
.chess-game-movenum {
    color: #888;
    font-size: 0.88em;
    min-width: 2.7em;            /* fits "25…" or "100." */
    text-align: right;
    padding-right: 0.3em;
    user-select: none;
    font-variant-numeric: tabular-nums;
}
.chess-game-san {
    font: inherit;
    background: transparent;
    border: 0;
    padding: 0.05em 0.4em;
    border-radius: 3px;
    cursor: pointer;
    color: inherit;
    font-family: ui-monospace, "SF Mono", Menlo, monospace;
    font-size: 0.95em;
}
.chess-game-san:hover {
    background: rgba(0, 0, 0, 0.06);
}
.chess-game-san.is-active {
    background: var(--ghost-accent-color, #2e7d32);
    color: #fff;
    font-weight: 600;
}
.chess-game-san:focus-visible {
    outline: 2px solid var(--ghost-accent-color, #2e7d32);
    outline-offset: 1px;
}

/* Desktop: move list lives to the right of the board. */
@media (min-width: 720px) {
    .chess-game-body {
        grid-template-columns: minmax(0, 480px) minmax(0, 1fr);
        grid-template-areas:
            "meta     meta"
            "board    moves"
            "controls moves";
        column-gap: 1.4em;
        row-gap: 0.6em;
        align-items: start;
    }
    .chess-game-meta     { grid-area: meta; }
    .chess-game-board    { grid-area: board; max-width: none; }
    .chess-game-controls { grid-area: controls; justify-content: flex-start; }
    .chess-game-moves    {
        grid-area: moves;
        border-top: 0;
        border-left: 1px solid #e5e5e5;
        padding: 0 0 0 0.7em;
        max-height: 460px;
    }
    .chess-game-btn.chess-game-copy {
        /* Auto-margin pushes Copy to the right edge of the controls row. */
        margin-left: auto;
    }
}

/* Size variants, same dial as diagrams/puzzles. */
.chess-game-wrapper.chess-size-small  { max-width: 520px; }
.chess-game-wrapper.chess-size-medium { max-width: 720px; }
.chess-game-wrapper.chess-size-large  { max-width: 920px; }

/* Align variants — same float pattern as diagrams. */
.chess-game-wrapper.chess-align-left {
    float: left;
    margin: 0.4em 1.6em 0.8em 0;
    max-width: 520px;
}
.chess-game-wrapper.chess-align-right {
    float: right;
    margin: 0.4em 0 0.8em 1.6em;
    max-width: 520px;
}

@media (max-width: 600px) {
    .chess-diagram-wrapper,
    .chess-puzzle-wrapper {
        max-width: 100%;
    }
    .chess-game-wrapper,
    .chess-game-wrapper.chess-align-left,
    .chess-game-wrapper.chess-align-right {
        float: none;
        margin: 1.5em auto;
        max-width: 100%;
    }
    .chess-game-btn.chess-game-copy {
        /* Wrap Copy onto its own row on narrow screens so it doesn't sit
           awkwardly against the playback buttons. */
        flex-basis: 100%;
        margin-left: 0;
    }

    /* Mobile move list — a single horizontal-scrolling row.
       Why block + inline-flex (and not flex on the row): when the row was
       a flex container, each <li>'s baseline was determined by its own
       internal flex layout and the lis didn't align with each other —
       producing the visible up/down jitter between move pairs. As an
       inline row of inline-flex items, the lis sit on a normal text line
       and align by the standard inline baseline, which is consistent. */
    .chess-game-moves {
        display: block;
        overflow-x: auto;
        overflow-y: hidden;
        max-height: none;
        white-space: nowrap;
        padding: 0.4em 0;
        line-height: 1.9;
        /* iOS / older WebKit smooth-scroll niceties */
        -webkit-overflow-scrolling: touch;
        scroll-snap-type: x proximity;
        /* Soft fade at the right edge to hint there's more content. */
        mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
        -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
        /* Thinner native scrollbar where supported. */
        scrollbar-width: thin;
        scrollbar-color: rgba(0,0,0,0.25) transparent;
    }
    .chess-game-moves > li {
        display: inline-flex;
        align-items: baseline;
        gap: 0.15em;
        padding: 0;
        margin: 0 0.4em 0 0;
        scroll-snap-align: start;
    }
    .chess-game-moves > li > .chess-game-movenum {
        /* Drop the desktop's right-aligned 2.7em column — on a single
           inline row the movenum just sits next to its move. */
        min-width: 0;
        text-align: left;
        padding-right: 0.1em;
    }
    .chess-game-moves::-webkit-scrollbar { height: 4px; }
    .chess-game-moves::-webkit-scrollbar-thumb {
        background: rgba(0,0,0,0.25);
        border-radius: 2px;
    }
}

/* ============================================================
   Fixtures list (<div class="lc-fixtures">)
   Renders a chronological list of all Lichfield team fixtures
   across the leagues, grouped by month. Current month + next
   month show by default; "Show past results" toggle reveals
   earlier months.
   ============================================================ */

.lc-fixtures {
    margin: 2em 0 0;          /* slightly bigger top gap above the
                                  toggle/As-of row; no bottom margin —
                                  last month section carries that. */
}
/* Drop the last month section's bottom margin so the fixtures widget
   sits close to whatever follows it (heading / hr / next paragraph). */
.lc-fixtures .lc-fixtures-month:last-child { margin-bottom: 0.4em; }
.lc-fixtures-header {
    /* Toggle on the left, "As of" on the right, both on one row with
       their text baselines aligned. Wraps onto two rows only if the
       viewport is too narrow to fit both. */
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
    margin-bottom: 1.2rem;
}
.lc-fixtures-meta {
    font-size: 0.85em;
    color: #888;
}
.lc-fixtures-toggle {
    display: inline-flex;
    align-items: center;
    gap: 0.5em;
    cursor: pointer;
    user-select: none;
    font-size: 0.95em;
    color: #555;
}
.lc-fixtures-toggle input { margin: 0; }
.lc-fixtures-month {
    margin: 1.6em 0;
}
/* Same visual shape as .league-table-title above so the section headings
   on a page mixing both look consistent. */
.lc-fixtures-month-title {
    margin: 0 0 0.6em;
    font-size: 1.25em;
    font-weight: 600;
    color: var(--ghost-accent-color, #2e7d32);
    line-height: 1.2;
}
.lc-fixtures-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.95em;
}
/* Source's .gh-content adjacent-sibling rule injects 48px of top margin
   above any <table> following a non-card element. Override so the table
   sits ~0.5em under the month title. !important needed to beat the
   source selector's higher specificity. */
.gh-content .lc-fixtures-table { margin-top: 0.5em !important; }
.lc-fixtures-table th,
.lc-fixtures-table td {
    padding: 0.45em 0.6em;
    text-align: left;
    border-bottom: 1px solid rgba(0, 0, 0, 0.08);
    vertical-align: top;
    white-space: nowrap;
}
.lc-fixtures-table th {
    font-weight: 600;
    background: rgba(0, 0, 0, 0.03);
}
/* Allow the League column to wrap so long-form names
   ("Cannock & District Division 2") use two lines if needed. */
.lc-fixtures-table td.lc-fixtures-comp { white-space: normal; }
/* Score column centred. */
.lc-fixtures-table th:nth-child(4),
.lc-fixtures-table td.lc-fixtures-score {
    text-align: center;
    font-weight: 600;
}
.lc-fixtures-table td.lc-fixtures-score a {
    color: inherit;
    text-decoration: underline dotted;
    text-decoration-thickness: 1px;
    text-underline-offset: 0.18em;
}
.lc-fixtures-table td.lc-fixtures-score a:hover { text-decoration-style: solid; }
.lc-fixtures-v { color: #aaa; font-weight: 400; }
.lc-fixtures-pending { color: #c66; }
.lc-fixtures-time {
    color: #888;
    font-size: 0.85em;
    margin-left: 0.4em;
}
/* Highlight the row's Lichfield team in bold so visitors can scan
   home/away presence at a glance. */
.lc-fixtures-row.lc-fixtures-home-us td.lc-fixtures-home { font-weight: 600; }
.lc-fixtures-row.lc-fixtures-away-us td.lc-fixtures-away { font-weight: 600; }
/* Past fixtures get a slightly muted text color. */
.lc-fixtures-row-past td { color: #555; }

.lc-fixtures-loading,
.lc-fixtures-error,
.lc-fixtures-empty {
    padding: 0.8em;
    color: #888;
    text-align: center;
}
.lc-fixtures-error { color: #c44; }
.lc-fixtures-empty strong { color: #444; font-weight: 600; }

/* Desktop: show full competition name, hide the short variant. */
.lc-fixtures-comp-short { display: none; }

/* Mobile: tighten padding + allow team / competition names to wrap.
   Stack the kick-off time below the date (instead of inline beside it).
   Swap to the short competition label ("Cannock Div 2"). Tighter,
   custom column widths to give Home/Away more breathing room on small
   screens, and a smaller-but-nudged-down score font. */
@media (max-width: 600px) {
    .lc-fixtures-table td,
    .lc-fixtures-table th { padding: 0.4em 0.4em; font-size: 0.92em; }
    .lc-fixtures-table td.lc-fixtures-home,
    .lc-fixtures-table td.lc-fixtures-away,
    .lc-fixtures-table td.lc-fixtures-comp {
        white-space: normal;
    }
    .lc-fixtures-time {
        display: block;
        margin-left: 0;
    }
    .lc-fixtures-comp-full { display: none; }
    .lc-fixtures-comp-short { display: inline; }

    /* Mobile column widths: 10 + 25 + 28 + 10 + 27 = 100. */
    .lc-fixtures-table th:nth-child(1),
    .lc-fixtures-table td.lc-fixtures-date {
        width: 10%;
    }
    .lc-fixtures-table th:nth-child(2),
    .lc-fixtures-table td.lc-fixtures-comp {
        width: 25%;
    }
    .lc-fixtures-table th:nth-child(3),
    .lc-fixtures-table td.lc-fixtures-home {
        width: 28%;
    }
    .lc-fixtures-table th:nth-child(4),
    .lc-fixtures-table td.lc-fixtures-score {
        width: 10%;
        /* Smaller font so "3½ - 2½" doesn't dominate the row, plus a
           padding nudge so the smaller text doesn't hug the top of the
           cell (cells use vertical-align: top by default above). */
        font-size: 0.8em;
        padding-top: 0.7em;
    }
    .lc-fixtures-table th:nth-child(5),
    .lc-fixtures-table td.lc-fixtures-away {
        width: 27%;
    }
}

/* ---------------------------------------------------------------- */
/* Match cards                                                       */
/* ---------------------------------------------------------------- */
/* Placeholder: authors paste <div class="lc-match-card" data-fid="…">
   into a post. chess.js fills it in client-side from fixtures.json. */
.lc-match-card {
    display: block;
    margin: 1.8em 0 0.6em;
}
.lc-match-card-loading,
.lc-match-card-placeholder {
    color: #888;
    font-style: italic;
    font-size: 0.9em;
}
.lc-match-card-error {
    padding: 0.7em 0.9em;
    background: rgba(196, 68, 68, 0.07);
    border-left: 3px solid #c44;
    color: #933;
    font-size: 0.9em;
}

.lc-match-card-inner {
    border: 1px solid rgba(0, 0, 0, 0.1);
    border-radius: 6px;
    background: #fff;
    overflow: hidden;
}

/* Header bar: home  TOTAL  away + meta (league + date) */
.lc-match-card-header {
    padding: 0.8em 1em;
    background: rgba(46, 125, 50, 0.06);   /* hint of accent green */
    border-bottom: 1px solid rgba(0, 0, 0, 0.08);
}
.lc-match-card-score {
    display: flex;
    align-items: center;
    gap: 0.6em;
    font-size: 1.05em;
    line-height: 1.3;
}
.lc-match-card-team {
    flex: 1 1 0;
    min-width: 0;
    font-weight: 500;
}
.lc-match-card-team-home { text-align: right; }
.lc-match-card-team-away { text-align: left; }
.lc-match-card-team.is-us { font-weight: 700; }
.lc-match-card-total {
    flex: 0 0 auto;
    padding: 0 0.7em;
    font-weight: 700;
    font-size: 1.1em;
    color: var(--ghost-accent-color, #2e7d32);
    white-space: nowrap;
}
.lc-match-card-meta {
    margin-top: 0.35em;
    display: flex;
    justify-content: space-between;
    gap: 0.8em;
    flex-wrap: wrap;
    font-size: 0.82em;
    color: #666;
}

/* Boards table. */
.lc-match-card-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.93em;
}
/* Source's .gh-content rule injects 48px above any <table>; override so
   the boards sit flush under the header bar. */
.gh-content .lc-match-card-table { margin-top: 0 !important; }
.lc-match-card-table th,
.lc-match-card-table td {
    padding: 0.45em 0.7em;
    border-bottom: 1px solid rgba(0, 0, 0, 0.06);
    vertical-align: middle;
}
.lc-match-card-table th {
    font-weight: 600;
    background: rgba(0, 0, 0, 0.02);
    text-align: left;
    font-size: 0.95em;
}
/* Lichfield's column header stays the default text colour (the bold
   weight from .is-us elsewhere is enough emphasis on its own). */
.lc-match-card-board-h,
.lc-match-card-board { text-align: center; width: 3em; font-variant-numeric: tabular-nums; }
.lc-match-card-rating-h,
.lc-match-card-rating { text-align: center; width: 4.5em; font-variant-numeric: tabular-nums; color: #555; }
.lc-match-card-result-h,
.lc-match-card-result { text-align: center; white-space: nowrap; font-weight: 600; }
.lc-match-card-player.is-us { font-weight: 600; }

/* Colour markers (white/black to move at start of game on that board). */
.lc-match-card-piece {
    display: inline-block;
    width: 0.85em;
    height: 0.85em;
    border-radius: 50%;
    vertical-align: -0.08em;
    margin-right: 0.15em;
    border: 1px solid rgba(0, 0, 0, 0.55);
}
.lc-piece-white { background: #fff; }
.lc-piece-black { background: #111; border-color: #111; }

/* Totals row sits on top of a tinted bar. */
.lc-match-card-totals td {
    background: rgba(0, 0, 0, 0.025);
    font-weight: 600;
    border-bottom: 0;
    /* "Total" must not wrap to a second line — the board# column is sized
       for a 1-digit number, but on the totals row this cell holds the
       word "Total" instead. */
    white-space: nowrap;
}
.lc-match-card-totals .lc-match-card-result {
    color: var(--ghost-accent-color, #2e7d32);
}

/* Sits BELOW the bordered card, not part of it — plain right-aligned link. */
.lc-match-card-source {
    margin-top: 0.4em;
    text-align: right;
    font-size: 0.82em;
}
.lc-match-card-source a { color: inherit; text-decoration: underline dotted; }
.lc-match-card-source a:hover { text-decoration-style: solid; }

@media (max-width: 600px) {
    .lc-match-card-table { font-size: 0.85em; }
    .lc-match-card-table th,
    .lc-match-card-table td { padding: 0.35em 0.45em; }
    /* Tighter: drop ratings on small screens. Player names get the room. */
    .lc-match-card-rating-h,
    .lc-match-card-rating { display: none; }
    .lc-match-card-score { font-size: 1em; }
    .lc-match-card-total { font-size: 1.05em; padding: 0 0.4em; }
}

/* ---------------------------------------------------------------- */
/* Tournament cross-tables                                            */
/* ---------------------------------------------------------------- */
/* Authors paste <div class="lc-tournament" data-slug="…"></div> into a
   Ghost post. chess.js fills it from /content/files/tournaments.json,
   which is rewritten by the scraper from chessdb.tournament_configs.   */
.lc-tournament {
    display: block;
    margin: 1.8em 0 0.6em;
}
.lc-tournament-loading,
.lc-tournament-placeholder { color: #888; font-style: italic; font-size: 0.9em; }
.lc-tournament-error {
    padding: 0.7em 0.9em;
    background: rgba(196, 68, 68, 0.07);
    border-left: 3px solid #c44;
    color: #933;
    font-size: 0.9em;
}

.lc-tournament-inner {
    border: 1px solid rgba(0, 0, 0, 0.1);
    border-radius: 6px;
    background: #fff;
    overflow: hidden;
}
.lc-tournament-header {
    padding: 0.8em 1em;
    background: rgba(46, 125, 50, 0.06);
    border-bottom: 1px solid rgba(0, 0, 0, 0.08);
}
.lc-tournament-title {
    margin: 0;
    font-size: 1.1em;
    font-weight: 600;
    line-height: 1.3;
    color: inherit;
}
.lc-tournament-meta { margin-top: 0.2em; font-size: 0.82em; color: #666; }

/* Allow horizontal scroll for the cross-table when 7+ rounds push the
   width past the column. The inner table is full-width; the wrap is
   what scrolls. */
.lc-tournament-table-wrap { overflow-x: auto; }
.lc-tournament-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.92em;
}
.gh-content .lc-tournament-table { margin-top: 0 !important; }
.lc-tournament-table th,
.lc-tournament-table td {
    padding: 0.4em 0.55em;
    border-bottom: 1px solid rgba(0, 0, 0, 0.06);
    vertical-align: middle;
    text-align: center;
    white-space: nowrap;
}
.lc-tournament-table th {
    font-weight: 600;
    background: rgba(0, 0, 0, 0.02);
    font-size: 0.95em;
}
.lc-tournament-table td.lc-t-name,
.lc-tournament-table th.lc-t-name {
    text-align: left;
    white-space: normal;
    min-width: 8em;
}
.lc-t-rank, .lc-t-rating, .lc-t-total { font-variant-numeric: tabular-nums; }
.lc-t-rank { color: #555; }
.lc-t-rating { color: #555; }
.lc-t-total { font-weight: 600; font-size: 1.05em; }

/* Per-round cells. */
.lc-t-round { font-variant-numeric: tabular-nums; }
.lc-t-round .lc-t-result { font-weight: 600; font-size: 0.92em; }
.lc-t-win  { background: rgba(46, 125, 50, 0.10); }    /* green tint */
.lc-t-draw { background: rgba(200, 170, 0, 0.10); }    /* amber tint */
.lc-t-loss { background: rgba(180, 60, 60, 0.10); }    /* red tint */
.lc-t-round-bye { color: #aaa; }
.lc-t-piece {
    display: inline-block;
    width: 0.65em; height: 0.65em;
    border-radius: 50%;
    vertical-align: 0.05em;
    margin-right: 0.25em;
    border: 1px solid rgba(0, 0, 0, 0.55);
}

.lc-tournament-source {
    margin-top: 0.4em;
    text-align: right;
    font-size: 0.82em;
}
.lc-tournament-source a { color: inherit; text-decoration: underline dotted; }
.lc-tournament-source a:hover { text-decoration-style: solid; }

/* Mobile: keep every column visible and let the user swipe horizontally
   to see the per-round details. .lc-tournament-table-wrap already has
   overflow-x: auto so the gesture works out of the box; we just tighten
   typography so the table fits more vertically. */
@media (max-width: 600px) {
    .lc-tournament-table { font-size: 0.88em; }
    .lc-tournament-table th,
    .lc-tournament-table td { padding: 0.35em 0.45em; }
    .lc-tournament-table th.lc-t-rating,
    .lc-tournament-table td.lc-t-rating { font-size: 0.85em; }
    /* Smoother gesture on iOS. */
    .lc-tournament-table-wrap { -webkit-overflow-scrolling: touch; }
}

/* ---------------------------------------------------------------- */
/* Homepage row: Daily Puzzle (left) + Latest Results (right)         */
/* ---------------------------------------------------------------- */
/* Two columns matching .lc-feeds-grid above (same max-width, gap and
   minmax breakpoint) so the homepage's stacked rows align in width.
   Zero top padding: .lc-feeds already has 3.5rem of bottom padding;
   that's the gap we want. */
.lc-puzzle-results { padding: 0 0 3.5rem; }
.lc-puzzle-results-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
    gap: 3rem;
    max-width: 920px;
    margin: 0 auto;
    /* 3.5rem of breathing room above the new row to match the feeds
       section's 3.5rem bottom padding, so the divider sits in the
       middle of a balanced 7rem gap. */
    padding: 3.5rem 2rem 0;
    align-items: start;
    /* Divider line — drawn via ::before so we can inset it from the
       grid's 2rem side padding, making it span just the column area
       (not the side padding) and so visually match the column widths. */
    position: relative;
}
.lc-puzzle-results-grid::before {
    content: '';
    position: absolute;
    top: 0;
    left: 2rem;
    right: 2rem;
    border-top: 1px solid var(--lc-border);
}

/* Daily puzzle column. Heading + .lc-daily-puzzle widget. */
.lc-daily-puzzle-loading,
.lc-daily-puzzle-placeholder {
    display: block;
    color: #888;
    font-style: italic;
    padding: 2em 0;
    text-align: center;
}
.lc-daily-puzzle-error {
    padding: 0.7em 0.9em;
    background: rgba(196, 68, 68, 0.07);
    border-left: 3px solid #c44;
    color: #933;
    font-size: 0.9em;
}
.lc-daily-puzzle-caption {
    text-align: center;
    font-size: 0.95em;
    color: #555;
    font-weight: 600;
    margin-bottom: 0.4em;
}
.lc-daily-puzzle .chess-puzzle-wrapper {
    margin: 0.8em auto;
    /* The default chess-puzzle widget caps at 480px. In the homepage
       column it's surrounded by results / news, so a smaller board
       reads better in the visual hierarchy. */
    max-width: 320px;
}
.lc-daily-puzzle-attrib {
    margin: 0.4em auto 0;
    font-size: 0.82em;
    color: #777;
    line-height: 1.45;
    text-align: center;
}
.lc-daily-puzzle-attrib a { color: inherit; text-decoration: underline dotted; }
.lc-daily-puzzle-attrib a:hover { text-decoration-style: solid; }

/* Latest Results column. */
.lc-lr-placeholder { color: #888; font-style: italic; padding: 0.6em 0; }
.lc-lr-error {
    padding: 0.7em 0.9em;
    background: rgba(196, 68, 68, 0.07);
    border-left: 3px solid #c44;
    color: #933;
    font-size: 0.9em;
}
.lc-lr-empty { color: #888; font-style: italic; padding: 0.6em 0; }
.lc-lr-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.95em;
}
/* Source's gh-content injects margin above any <table>; not in scope
   on the homepage but be defensive in case the widget ever lands in a
   post. */
.gh-content .lc-lr-table { margin-top: 0 !important; }
.lc-lr-table th,
.lc-lr-table td {
    padding: 0.4em 0.5em 0.4em 0;
    border-bottom: 1px solid rgba(0, 0, 0, 0.06);
    vertical-align: middle;
    white-space: nowrap;
}
.lc-lr-table th {
    font-weight: 600;
    text-align: left;
    font-size: 0.85em;
    color: #555;
    background: rgba(0, 0, 0, 0.025);
}
.lc-lr-table thead th.lc-lr-result { text-align: right; }
.lc-lr-date { color: #555; font-variant-numeric: tabular-nums; }
.lc-lr-league { color: #555; font-size: 0.9em; }
.lc-lr-opp { white-space: normal; }
.lc-lr-result { text-align: right; font-variant-numeric: tabular-nums; }
.lc-lr-code {
    display: inline-block;
    min-width: 1.4em;
    padding: 0.05em 0.4em;
    border-radius: 3px;
    font-weight: 700;
    font-size: 0.82em;
    text-align: center;
    color: #fff;
    background: #888;
    vertical-align: 1px;
}
.lc-lr-w .lc-lr-code { background: var(--lc-accent, #2e7d32); }
.lc-lr-l .lc-lr-code { background: #c14a4a; }
.lc-lr-d .lc-lr-code { background: #b08a00; }
.lc-lr-score { font-weight: 600; }
.lc-lr-link { color: inherit; text-decoration: none; }
/* Mirror the dotted-underline style used by score links in the main
   fixtures widget (.lc-fixtures-table td.lc-fixtures-score a) — dotted
   by default, solid on hover. Only the score text gets the underline;
   the W/L/D badge has its own background and would look ugly with one. */
.lc-lr-link .lc-lr-score {
    text-decoration: underline dotted;
    text-decoration-thickness: 1px;
    text-underline-offset: 0.18em;
}
.lc-lr-link:hover .lc-lr-score { text-decoration-style: solid; }
.lc-lr-updated {
    margin-top: 0.5em;
    font-size: 0.78em;
    color: #888;
    text-align: left;
}

@media (max-width: 480px) {
    .lc-lr-table { font-size: 0.88em; }
    /* On the narrowest screens drop the date column rather than the
       league — the league + opponent + result combo is more useful than
       the date alone, and recent results are recent by definition. */
    .lc-lr-table th.lc-lr-date,
    .lc-lr-table td.lc-lr-date { display: none; }
}
