:root {
    color-scheme: light;
    --navy-950: #081e35;
    --navy-900: #0e2a47;
    --navy-700: #1b4a7a;
    --navy-100: #dbe6f1;
    --navy-50: #eef3f9;
    --brass-600: #a8752e;
    --gold-300: #d9b96c;
    --paper: #fdfcf9;
    --ink-900: #1c2733;
    --ink-600: #56687a;
    --line: #e3e0d8;
    /* A match's outcome for the club, on the Allsvenskan page. */
    --won-bg: #e2f0e5;
    --won-ink: #1f6b3b;
    --drawn-bg: #f6ecd6;
    --drawn-ink: #845a1f;
    --lost-bg: #f7e2df;
    --lost-ink: #a3372a;
    --serif: 'Palatino Linotype', Palatino, Georgia, 'Times New Roman', serif;
    --sans: 'Segoe UI', system-ui, -apple-system, sans-serif;
}

html, body {
    font-family: var(--sans);
    color: var(--ink-900);
    background-color: var(--paper);
}

body {
    font-size: 1.0625rem;
    line-height: 1.6;
}

h1, h2, h3, h4 {
    font-family: var(--serif);
    line-height: 1.15;
}

h1 {
    margin-bottom: 1rem;
}

a, .btn-link {
    color: var(--navy-700);
}

.btn-primary {
    color: #fff;
    background-color: var(--navy-700);
    border-color: var(--navy-700);
}

.btn-primary:hover, .btn-primary:focus {
    background-color: var(--navy-900);
    border-color: var(--navy-900);
}

.btn-outline-primary {
    color: var(--navy-700);
    border-color: var(--navy-700);
}

.btn-outline-primary:hover {
    background-color: var(--navy-700);
    border-color: var(--navy-700);
}

.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
  box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem var(--brass-600);
}

.card {
    border-color: var(--line);
    border-radius: 14px;
}

.text-muted {
    color: var(--ink-600) !important;
}

h1:focus {
    outline: none;
}

/* Navbar: deep navy with readable links. */
.navbar-dark {
    --bs-navbar-color: rgba(255, 255, 255, 0.85);
    --bs-navbar-hover-color: #fff;
    --bs-navbar-active-color: #fff;
}

.navbar-dark .navbar-nav .nav-link {
    color: rgba(255, 255, 255, 0.85);
}

.navbar-dark .navbar-nav .nav-link:hover,
.navbar-dark .navbar-nav .nav-link:focus {
    color: #fff;
}

/* Cards that act as links: hover affordance and a link-colored title. */
.clickable-card {
    transition: transform 0.12s ease, box-shadow 0.12s ease;
}

a:hover .clickable-card,
a:focus .clickable-card {
    transform: translateY(-3px);
    box-shadow: 0 10px 24px rgba(14, 42, 71, 0.12);
}

.clickable-card .card-title {
    color: var(--navy-700);
}

/* Full-width bands escaping the centered content container. */
.full-bleed {
    width: 100vw;
    margin-left: calc(50% - 50vw);
}

/* ───── Front-page hero ───── */
.hero {
    margin-top: -28px; /* cancels the content container's top padding */
    background:
        linear-gradient(170deg, rgba(8, 30, 53, 0.82) 0%, rgba(14, 42, 71, 0.62) 55%, rgba(8, 30, 53, 0.85) 100%),
        url("/images/chess-background.jpg") center / cover no-repeat;
    color: #fff;
    padding: 76px 0 84px;
}

.hero-inner {
    max-width: 640px;
}

.hero .eyebrow {
    font-size: 0.8rem;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--gold-300);
    margin-bottom: 14px;
}

.hero h1 {
    font-size: clamp(2.1rem, 5vw, 3.1rem);
    font-weight: 600;
    margin-bottom: 18px;
}

.hero .lede {
    font-size: 1.15rem;
    color: rgba(255, 255, 255, 0.88);
    margin: 0 0 26px;
    max-width: 56ch;
}

.facts {
    display: flex;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 30px;
}

.fact {
    background: rgba(255, 255, 255, 0.1);
    border: 1px solid rgba(255, 255, 255, 0.22);
    border-radius: 999px;
    padding: 7px 18px;
    font-size: 0.92rem;
}

.fact b {
    color: var(--gold-300);
    font-weight: 600;
}

.cta-row {
    display: flex;
    gap: 14px;
    flex-wrap: wrap;
}

.hero-btn-solid {
    background: #fff;
    color: var(--navy-900);
    font-weight: 600;
    padding: 11px 26px;
    border-radius: 10px;
}

.hero-btn-solid:hover {
    background: var(--navy-50);
    color: var(--navy-900);
}

.hero-btn-ghost {
    border: 1.5px solid rgba(255, 255, 255, 0.55);
    color: #fff;
    font-weight: 600;
    padding: 11px 26px;
    border-radius: 10px;
}

.hero-btn-ghost:hover {
    border-color: #fff;
    color: #fff;
    background: rgba(255, 255, 255, 0.08);
}

/* ───── Inner-page title band ───── */
.page-band {
    margin-top: -28px;
    background: linear-gradient(135deg, var(--navy-900) 0%, var(--navy-700) 100%);
    color: #fff;
    padding: 30px 0 26px;
    margin-bottom: 30px;
}

.page-band h1 {
    margin: 0;
    font-size: 2rem;
    color: #fff;
}

/* ───── KM: one season per page, stepped through from the band ───── */
.season-band .container {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 14px 24px;
}

.season-eyebrow {
    display: block;
    font-size: 0.78rem;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--gold-300);
    margin-bottom: 6px;
}

.season-pager {
    display: flex;
    gap: 8px;
}

.season-step {
    border: 1.5px solid rgba(255, 255, 255, 0.55);
    color: #fff;
    border-radius: 10px;
    padding: 5px 14px;
    font-weight: 600;
    font-size: 0.92rem;
    text-decoration: none;
    white-space: nowrap;
}

.season-step:hover {
    border-color: #fff;
    color: #fff;
    background: rgba(255, 255, 255, 0.08);
}

.season-step.is-disabled {
    opacity: 0.35;
}

/* Tucked up under the band, where the date belongs to the heading above it. */
.season-meta {
    color: var(--ink-600);
    font-size: 0.92rem;
    margin: -12px 0 18px;
}

.season-archive {
    background: var(--navy-50);
    border: 1px solid var(--navy-100);
    border-radius: 10px;
    padding: 10px 16px;
    margin-bottom: 22px;
}

.season-aside {
    border: 1px solid var(--line);
    border-radius: 14px;
    background: #fff;
    padding: 18px 22px;
}

.season-aside h2,
.season-rounds h2 {
    font-size: 1.15rem;
    font-weight: 600;
    margin-bottom: 0.6rem;
}

.season-rounds {
    margin-top: 0;
}

.season-list {
    list-style: none;
    padding: 0;
    margin: 0;
}

.season-list li {
    padding: 5px 0;
    border-bottom: 1px solid var(--line);
}

.season-list li:last-child {
    border-bottom: none;
}

/* ───── Front-page sections ───── */
.home-section {
    margin-top: 52px;
}

.section-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 20px;
}

.section-head .label {
    font-size: 0.78rem;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--brass-600);
    display: block;
    margin-bottom: 4px;
}

.section-head h2 {
    font-size: 1.7rem;
    margin: 0;
}

.section-head .more {
    font-size: 0.92rem;
    text-decoration: none;
    white-space: nowrap;
}

.section-head .more:hover {
    text-decoration: underline;
}

/* The hero button's destination is only meaningful once it has a label, so it is
   revealed by the label field being non-empty. :placeholder-shown is what makes this
   possible without script, which is why that field carries a placeholder. */
.cta-row-fields .cta-slug-field {
    display: none;
}

.cta-row-fields:has(#cta-text:not(:placeholder-shown)) .cta-slug-field {
    display: block;
}

/* ───── The hub: a scanning layout, denser than a club's own front page ───── */

/* A slim band, not a hero: the newest article should be visible without scrolling. */
.hub-band {
    margin-top: -28px;
    background: linear-gradient(135deg, var(--navy-900) 0%, var(--navy-700) 100%);
    color: #fff;
    padding: 26px 0 24px;
    margin-bottom: 8px;
}

.hub-band h1 {
    font-size: clamp(1.5rem, 3vw, 2rem);
    font-weight: 600;
    margin: 0 0 6px;
}

.hub-band p {
    margin: 0;
    color: rgba(255, 255, 255, 0.82);
    font-size: 0.98rem;
    max-width: 62ch;
}

.hub-grid {
    display: grid;
    grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
    gap: 40px;
}

/* The sidebar follows you down the feed rather than scrolling away and leaving an
   empty column. align-self keeps it its own height instead of stretching. */
.hub-aside {
    position: sticky;
    top: 84px;
    align-self: start;
}

@media (max-width: 800px) {
    .hub-grid {
        grid-template-columns: 1fr;
        gap: 0;
    }

    /* The tournament list is short; a dozen articles are not. Keep it reachable
       instead of stranding it below the whole feed. */
    .hub-aside {
        order: -1;
        position: static;
    }
}

/* Cards rather than hairline-separated rows: on the hub the news is the attraction,
   so each item is allowed its own surface and room to breathe. */
.hub-cards {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.hub-card {
    background: #fff;
    border: 1px solid var(--line);
    border-radius: 14px;
    padding: 22px 24px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    text-decoration: none;
    color: inherit;
    transition: transform 0.12s ease, box-shadow 0.12s ease;
}

.hub-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 10px 24px rgba(14, 42, 71, 0.12);
    color: inherit;
}

.hub-card .hub-item-title {
    font-size: 1.3rem;
}

/* The newest article leads: larger, with a longer excerpt, so the column has a
   starting point instead of a uniform wall. */
.hub-card-lead {
    padding: 28px 30px;
    border-color: var(--navy-100);
    background: linear-gradient(180deg, var(--navy-50) 0%, #fff 60%);
}

.hub-card-lead .hub-item-title {
    font-size: clamp(1.5rem, 2.6vw, 1.9rem);
    line-height: 1.25;
}

.hub-card-lead .hub-item-excerpt {
    font-size: 1.02rem;
}

.hub-list {
    display: flex;
    flex-direction: column;
}

.hub-item {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 14px 0;
    border-bottom: 1px solid var(--line);
    text-decoration: none;
    color: inherit;
}

.hub-item:hover {
    color: var(--navy-700);
}

.hub-item:hover .hub-item-title {
    text-decoration: underline;
}

.hub-item-club {
    font-size: 0.78rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--brass-600);
}

.hub-item-title {
    font-family: var(--serif);
    font-size: 1.08rem;
    color: var(--navy-700);
}

.hub-item-excerpt {
    font-size: 0.94rem;
    color: var(--ink-900);
}

.hub-item-meta {
    font-size: 0.85rem;
    color: var(--ink-600);
}

/* The sidebar as its own module, so it holds its ground beside the news cards
   instead of reading as leftover text. */
.hub-panel {
    background: var(--navy-50);
    border: 1px solid var(--navy-100);
    border-radius: 14px;
    /* Matches the news cards, so the two columns feel like one page. */
    padding: 22px 24px;
}

.hub-panel p {
    font-size: 0.94rem;
    margin: 0 0 12px;
}

.hub-panel p:last-of-type {
    margin-bottom: 16px;
}

.hub-cta {
    display: inline-block;
    background: var(--navy-700);
    color: #fff;
    font-weight: 600;
    padding: 9px 18px;
    border-radius: 10px;
    text-decoration: none;
}

.hub-cta:hover {
    background: var(--navy-900);
    color: #fff;
}

.hub-panel .section-head {
    margin-bottom: 10px;
}

.hub-panel .hub-item {
    padding: 14px 0;
    border-bottom-color: var(--navy-100);
}

.hub-panel .hub-item:first-of-type {
    padding-top: 0;
}

.hub-panel .hub-item:last-child {
    border-bottom: none;
    padding-bottom: 0;
}

.hub-empty {
    color: var(--ink-600);
    font-size: 0.94rem;
    margin: 0;
}

/* ───── The club strip along the bottom ───── */
.hub-clubs {
    border-top: 1px solid var(--line);
    padding-top: 8px;
}

.hub-club-row {
    display: flex;
    flex-wrap: wrap;
    gap: 28px;
}

.hub-club {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    width: 150px;
    text-align: center;
    text-decoration: none;
    color: inherit;
}

.hub-club-mark {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 64px;
    width: 64px;
    margin-bottom: 4px;
}

.hub-club-mark img {
    max-height: 64px;
    max-width: 100%;
    width: auto;
}

/* A club without a logo shows its initials, so the row stays even rather than gappy. */
.hub-club-initials {
    border: 1px solid var(--line);
    border-radius: 50%;
    background: var(--navy-50);
    color: var(--navy-700);
    font-family: var(--serif);
    font-size: 1.25rem;
    letter-spacing: 0.02em;
}

.hub-club-name {
    font-weight: 600;
    color: var(--navy-700);
}

.hub-club:hover .hub-club-name {
    text-decoration: underline;
}

.article-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: 20px;
}

.article-card {
    background: #fff;
    border: 1px solid var(--line);
    border-radius: 14px;
    padding: 24px;
    display: flex;
    flex-direction: column;
    gap: 10px;
    text-decoration: none;
    color: inherit;
    transition: transform 0.12s ease, box-shadow 0.12s ease;
}

.article-card:hover {
    transform: translateY(-3px);
    box-shadow: 0 10px 24px rgba(14, 42, 71, 0.12);
    color: inherit;
}

.article-card h3 {
    font-size: 1.22rem;
    color: var(--navy-700);
    margin: 0;
}

.article-card p {
    margin: 0;
    color: var(--ink-600);
    font-size: 0.95rem;
}

.article-card .byline {
    margin-top: auto;
    font-size: 0.82rem;
    color: var(--ink-600);
}

/* ───── Event rows with date chips ───── */
.event-list {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.event-row {
    display: flex;
    align-items: center;
    gap: 20px;
    background: #fff;
    border: 1px solid var(--line);
    border-radius: 14px;
    padding: 14px 22px;
    text-decoration: none;
    color: inherit;
    transition: transform 0.12s ease, box-shadow 0.12s ease;
}

.event-row:hover {
    transform: translateY(-2px);
    box-shadow: 0 8px 20px rgba(14, 42, 71, 0.1);
    color: inherit;
}

/* A row that leads somewhere but also contains its own links (a map pin) cannot
   be an anchor — nested anchors are invalid. Instead an invisible link covers
   the card, and the links inside are lifted above it. */
.event-row.has-row-link {
    position: relative;
}

.event-row .row-link {
    position: absolute;
    inset: 0;
    border-radius: inherit;
}

.event-row .info a {
    position: relative;
    z-index: 1;
}

.date-chip {
    flex: 0 0 76px;
    text-align: center;
    background: var(--navy-50);
    border-radius: 10px;
    padding: 9px 6px;
    font-variant-numeric: tabular-nums;
}

.date-chip .d {
    display: block;
    font-family: var(--serif);
    font-size: 1.3rem;
    color: var(--navy-900);
    line-height: 1.1;
}

.date-chip .m {
    display: block;
    font-size: 0.72rem;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--ink-600);
}

.event-row .event-name {
    display: block;
    font-weight: 600;
    font-size: 1.08rem;
}

.event-row .event-meta {
    display: block;
    margin-top: 2px;
    font-size: 0.88rem;
    color: var(--ink-600);
}

/* The club's own players on a tournament card (Våra spelare). */
.event-row .event-players {
    display: block;
    margin-top: 4px;
    font-size: 0.92rem;
}

/* ───── Allsvenskan matches ───── */

/* The outcome's colours, set once per row and read by the score and its labels. */
.match-row {
    --outcome-bg: transparent;
    --outcome-ink: var(--ink-600);
}

.match-row.won {
    --outcome-bg: var(--won-bg);
    --outcome-ink: var(--won-ink);
}

.match-row.drawn {
    --outcome-bg: var(--drawn-bg);
    --outcome-ink: var(--drawn-ink);
}

.match-row.lost {
    --outcome-bg: var(--lost-bg);
    --outcome-ink: var(--lost-ink);
}

/* In the event lists: the result after the title. */
.match-row .match-result {
    margin-left: 0.45em;
    color: var(--outcome-ink);
}

/* On the Allsvenskan page: a results board, the teams either side of the score. Every
   rule below reaches only the board, so that in the event lists a match is laid out
   exactly like the events around it. */
.match-row .info:has(.match-board) {
    flex: 1 1 auto;
    min-width: 0;
}

.match-board {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
    align-items: center;
    column-gap: 16px;
}

.match-team {
    font-size: 1.08rem;
    line-height: 1.3;
}

.match-team.home {
    text-align: right;
}

.match-team.ours {
    font-weight: 600;
}

.match-score {
    display: grid;
    grid-template-columns: auto auto auto;
    justify-content: center;
    align-items: baseline;
    column-gap: 0.35em;
    /* Wide enough for "5½ – 2½", so the boxes, and the names either side, line up
       from row to row. */
    min-width: 6.5rem;
    padding: 4px 14px 5px;
    border-radius: 10px;
    background: var(--outcome-bg);
    color: var(--outcome-ink);
    font-family: var(--serif);
    font-size: 1.45rem;
    line-height: 1.1;
    font-variant-numeric: tabular-nums;
}

.match-score .match-outcome {
    grid-column: 1 / -1;
    justify-self: center;
    font-family: var(--sans);
    font-size: 0.68rem;
    letter-spacing: 0.12em;
    text-transform: uppercase;
}

.match-board + .event-meta {
    text-align: center;
}

/* The outcome is in the score box here; the line beneath needs it only on a phone. */
.match-row .event-meta .match-outcome {
    display: none;
    color: var(--outcome-ink);
}

.match-row .event-meta .match-outcome::after {
    content: " · ";
    color: var(--ink-600);
}

/* Board by board, folded away under a played match. It lines up with the scoreboard
   rather than the card: indented past the date chip (76px and the row's 20px gap), and
   with room on the right to match the board numbers on the left, so the results sit
   under the score. */
.match-row:has(.match-boards) {
    position: relative;
    flex-wrap: wrap;
    row-gap: 4px;
    cursor: pointer;
}

.match-boards {
    flex: 1 0 100%;
    padding-left: 96px;
}

/* An arrow under the scoreboard. Its summary is stretched over the whole card, as the
   event rows' links are, so that the card itself opens and closes the boards. */
.match-boards > summary {
    display: block;
    width: fit-content;
    margin: 0 auto;
    padding: 2px 12px 6px;
    list-style: none;
}

.match-boards > summary::-webkit-details-marker {
    display: none;
}

.match-boards > summary::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 14px;
}

.board-toggle {
    display: block;
    width: 0.7rem;
    height: 0.7rem;
    border-right: 2px solid var(--navy-700);
    border-bottom: 2px solid var(--navy-700);
    transform: rotate(45deg);
    transition: transform 0.15s ease;
}

.match-boards[open] .board-toggle {
    transform: translateY(5px) rotate(225deg);
}

.board-list {
    margin: 8px 0 2px;
    padding: 0;
    list-style: none;
    font-size: 0.92rem;
    font-variant-numeric: tabular-nums;
}

/* Number, home player, result, away player, and an empty column as wide as the
   number's on the right, so that the results sit under the score. */
.board-row {
    display: grid;
    grid-template-columns: 2rem minmax(0, 1fr) 4.5rem minmax(0, 1fr) 2rem;
    align-items: center;
    column-gap: 8px;
    padding: 5px 0;
    border-top: 1px solid var(--line);
}

.board-row.won {
    --board-ink: var(--won-ink);
}

.board-row.drawn {
    --board-ink: var(--drawn-ink);
}

.board-row.lost {
    --board-ink: var(--lost-ink);
}

.board-number {
    font-size: 0.8rem;
    color: var(--ink-600);
}

.board-player {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
}

.board-player.home {
    justify-content: flex-end;
    text-align: right;
}

.board-player.ours {
    font-weight: 600;
}

.board-result {
    display: flex;
    justify-content: center;
    white-space: nowrap;
    font-family: var(--serif);
    font-size: 1.05rem;
    color: var(--board-ink);
}

.board-rating {
    margin-left: 0.4em;
    font-size: 0.85em;
    font-weight: 400;
    color: var(--ink-600);
}

/* The colour each side played, as a square beside the result. */
.piece {
    flex: 0 0 auto;
    width: 0.75rem;
    height: 0.75rem;
    border: 1.5px solid var(--ink-900);
    border-radius: 2px;
}

.piece.white {
    background: #fff;
}

.piece.black {
    background: var(--ink-900);
}

/* Too narrow for two names and a score side by side, so the board stands on end: a
   team per line with its score at the edge, ours in the outcome's colour. */
@media (max-width: 575.98px) {
    /* A slimmer date chip leaves the names room enough for two lines at most. Only on
       the board: in the event lists a match keeps the chip of the events around it. */
    .match-row:has(.match-board) {
        gap: 14px;
        padding-left: 16px;
        padding-right: 16px;
    }

    .match-row:has(.match-board) .date-chip {
        flex-basis: 62px;
    }

    .match-board {
        grid-template-columns: minmax(0, 1fr) auto;
        grid-template-areas:
            "home home-score"
            "away away-score";
        column-gap: 10px;
        row-gap: 2px;
    }

    .match-team.home {
        grid-area: home;
        text-align: left;
    }

    .match-team.away {
        grid-area: away;
    }

    .match-score {
        display: contents;
        font-size: 1.2rem;
    }

    .match-score .score {
        text-align: right;
        color: var(--ink-600);
    }

    .match-score .score.home {
        grid-area: home-score;
    }

    .match-score .score.away {
        grid-area: away-score;
    }

    .match-score .score.ours {
        color: var(--outcome-ink);
    }

    .match-score .score-dash,
    .match-score .match-outcome {
        display: none;
    }

    .match-board + .event-meta {
        text-align: left;
    }

    .match-row .event-meta .match-outcome {
        display: inline;
    }

    /* The boards take the whole card, and stand on end like the board above: a
       player per line, their share at the edge, ours in the board's colour. */
    .match-boards {
        padding-left: 0;
    }

    .board-list {
        font-size: 0.88rem;
    }

    .board-row {
        grid-template-columns: 1.4rem minmax(0, 1fr) auto;
        grid-template-areas:
            "number home home-mark"
            ". away away-mark";
        column-gap: 6px;
        row-gap: 1px;
    }

    .board-number {
        grid-area: number;
    }

    .board-player.home {
        grid-area: home;
        justify-content: flex-start;
        text-align: left;
    }

    .board-player.away {
        grid-area: away;
    }

    .board-player.home .piece {
        order: -1;
    }

    .board-result {
        display: contents;
    }

    .board-result .board-mark {
        text-align: right;
        color: var(--ink-600);
    }

    .board-result .board-mark.ours {
        color: var(--board-ink);
    }

    .board-result .board-mark.home {
        grid-area: home-mark;
    }

    .board-result .board-mark.away {
        grid-area: away-mark;
    }

    .board-mark-separator {
        display: none;
    }
}

/* Past events sit below the upcoming ones, visually quieter. */
.past-year {
    font-size: 1.2rem;
    color: var(--ink-600);
    margin: 1.25rem 0 0.75rem;
}

.past-events .event-row {
    opacity: 0.72;
}

.past-events .event-row:hover,
.past-events .event-row:focus {
    opacity: 1;
}

/* ───── Editor grid templates: result lists and Berger cross tables ───── */
.result-table, .berger-table {
    width: 100%;
    border-collapse: collapse;
    margin-bottom: 1rem;
}

.result-table th, .result-table td,
.berger-table th, .berger-table td {
    border: 1px solid var(--ink-600);
    padding: 4px 8px;
}

.result-table th, .berger-table th {
    background: var(--navy-50);
    text-align: center;
}

.result-table th:first-child, .result-table td:first-child {
    width: 3.5rem;
    text-align: center;
}

.result-table th:last-child, .result-table td:last-child {
    width: 4.5rem;
    text-align: center;
}

.berger-table {
    text-align: center;
    font-variant-numeric: tabular-nums;
}

.berger-table th:nth-child(2), .berger-table td:nth-child(2) {
    text-align: left;
    width: 30%;
    min-width: 8rem;
}

.berger-table td {
    height: 2.6rem;
}

/* The pre-printed opponent number sits in the cell corner: top-right for
   white, top-left (plus shading) for black — like the paper protocol sheets. */
.berger-table td[data-opponent] {
    position: relative;
    padding-top: 14px;
    min-width: 2.5rem;
}

.berger-table td[data-opponent]::before {
    content: attr(data-opponent);
    position: absolute;
    top: 2px;
    right: 4px;
    font-size: 0.7rem;
    line-height: 1;
    color: var(--ink-600);
}

/* A neutral grey: a tint of the site's blue did not read as black. */
.berger-table td[data-black] {
    background: #d5d7da;
}

/* The round a player is free, in an odd field. Striped and dashed, and without a
   number in the corner, so it does not read as a result nobody has filled in — nor
   as a black game, which is shaded. */
.berger-table td.berger-bye {
    background: repeating-linear-gradient(135deg, #ece9e2 0 5px, #fff 5px 10px);
    color: var(--ink-600);
    font-weight: 700;
}

/* The darker ink keeps the small number readable on the grey. */
.berger-table td[data-black]::before {
    right: auto;
    left: 4px;
    color: var(--ink-900);
}

/* "2½ / 4": the games behind the points, shown while players have played different
   numbers of them — see BergerTableRenderer. */
.berger-table .berger-played {
    color: var(--ink-600);
    font-size: 0.85em;
    white-space: nowrap;
}

@media (max-width: 640px) {
    .berger-table {
        display: block;
        overflow-x: auto;
    }
}

/* ───── Tournament standings on events (from member.schack.se) ───── */

/* The standings as their own surface, framed like the hub's modules: this is live
   data fetched from outside, and the frame is what keeps it from reading as part
   of the club's own prose. */
.standings-panel {
    margin-top: 2.5rem;
    border: 1px solid var(--line);
    border-radius: 14px;
    background: #fff;
    padding: 20px 24px 14px;
}

.standings-panel h2,
.standings-dialog h2 {
    font-size: 1.35rem;
    margin: 0;
}

/* The dialog's heading row: title left, close button right. */
.standings-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 16px;
}

.standings-panel .standings-info {
    margin: 2px 0 0;
}

/* One gap below the heading block, whether or not the info line rendered. */
.standings-panel .standings-table {
    margin-top: 14px;
}

/* Every other row tinted, as result lists conventionally are — the eye follows a
   row across the columns without sliding. Halfway between the paper and the
   header's navy-50, so the header keeps its weight. The page assigns .alt by
   rendered position rather than nth-child, so the gap rows of a capped table
   cannot double the stripes up around themselves. */
.standings-table tr.alt td {
    background: #f6f9fc;
}

/* The seam of a capped table: rows were skipped here. */
.standings-gap td {
    text-align: center;
    color: var(--ink-600);
}

/* The club under the player's name, where the Klubb column has stepped aside. */
.standings-table .row-club {
    display: block;
    font-size: 0.82rem;
    color: var(--ink-600);
}

/* The rating list has no place column: names sit first and need the room the
   result-table's narrow first column would deny them. */
.players-table th:first-child,
.players-table td:first-child {
    width: auto;
    text-align: left;
}

/* A player's current and recent tournaments, under the name. On a phone the name
   column is too narrow for a sentence, so the notes step aside there — the
   spotlight card above the table still carries what is happening now. */
.players-table .player-note {
    display: block;
    font-size: 0.82rem;
    color: var(--ink-600);
}

@media (max-width: 575.98px) {
    .players-table .player-note {
        display: none;
    }
}

/* ───── The club form's SSF-id search ───── */

/* Spinner arrows on an id number are decoration at best. */
.no-spinner::-webkit-outer-spin-button,
.no-spinner::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

.no-spinner {
    -moz-appearance: textfield;
    appearance: textfield;
}

.ssf-search-results {
    margin-top: 6px;
    font-size: 0.92rem;
    color: var(--ink-600);
}

.ssf-search-hit {
    display: block;
    background: none;
    border: 0;
    padding: 2px 0;
    color: var(--navy-700);
    cursor: pointer;
    text-align: left;
}

.ssf-search-hit:hover {
    text-decoration: underline;
}

/* The club's own players, picked out the way every visitor scans for them: a warm
   gold against the cool stripes. Placed after the stripe rule — the specificity is
   equal (nth-child counts as a class), so order is what lets this win. */
.standings-table tr.own-club td {
    background: #f9f2df;
}

/* Poäng and Särskiljning: centred numbers in narrow columns, wherever they sit —
   the tiebreak column only exists when the tournament has one, so the generic
   first/last-child rules of .result-table cannot address them. */
.standings-table .num {
    width: 5rem;
    text-align: center;
}

/* Long names and clubs still need more than a phone's width even with the Elo
   column hidden — scroll the table inside itself, as the Berger tables do,
   rather than the whole page. */
@media (max-width: 640px) {
    .standings-table {
        display: block;
        overflow-x: auto;
    }
}

/* The fullscreen view: a native <dialog>, trimmed so the screen it claims goes
   to table rows — it hugs a shorter table and stops at the viewport for a long
   one. Readable width rather than wall-to-wall on large monitors; the table
   scrolls in its own region so the heading and close button stay put. */
.standings-dialog {
    width: min(100vw - 24px, 64rem);
    height: auto;
    max-height: calc(100vh - 24px);
    /* The browser's own dialog default is max-width: calc(100% - 6px - 2em), which
       silently clamps the width set above — hence the explicit none. */
    max-width: none;
    border: 1px solid var(--line);
    border-radius: 14px;
    padding: 14px 18px;
}

/* display is the dialog's own show/hide mechanism, so flex only applies open. */
.standings-dialog[open] {
    display: flex;
    flex-direction: column;
}

.standings-dialog::backdrop {
    background: rgba(8, 30, 53, 0.55);
}

/* Hold the page still while the dialog is open — a modal dialog does not stop the
   document behind it from scrolling. scrollbar-gutter keeps the vanished
   scrollbar's width reserved, so the page does not jump sideways as it locks. */
html:has(.standings-dialog[open]) {
    overflow: hidden;
    scrollbar-gutter: stable;
}

/* min-height lets the region shrink below its content and actually scroll —
   without it, flex refuses and the dialog overflows past max-height instead. */
.standings-scroll {
    flex: 1;
    min-height: 0;
    overflow: auto;
    margin: 10px 0 0;
}

.standings-scroll .standings-table {
    margin: 0;
}

/* On a phone the frame is ornament — give the rows the whole screen. inset with
   margin: 0 fills the viewport; dvh rather than vh so the browser's own toolbars
   do not push the bottom rows out of reach. */
@media (max-width: 640px) {
    .standings-dialog {
        inset: 0;
        margin: 0;
        width: auto;
        height: 100dvh;
        max-height: none;
        padding: 10px 12px;
        border: 0;
        border-radius: 0;
    }
}

/* The header row holds its ground while the rows scroll beneath it. The collapsed
   borders scroll away with the rows — a blemish not worth trading the sticky for. */
.standings-scroll th {
    position: sticky;
    top: 0;
    z-index: 1;
}

.standings-close {
    background: none;
    border: 0;
    padding: 0 2px;
    font-size: 1.6rem;
    line-height: 1;
    color: var(--ink-600);
    cursor: pointer;
}

.standings-close:hover {
    color: var(--ink-900);
}

/* ───── Statistics bars (admin) ───── */
.stat-bar {
    display: inline-block;
    height: 0.7rem;
    border-radius: 2px;
    vertical-align: middle;
    min-width: 0;
}

.stat-bar-human {
    background: var(--navy-700);
}

.stat-bar-bot {
    background: var(--navy-100);
    margin-left: 2px;
}

/* ───── Small icon links (map, calendar) ───── */
.icon-link svg {
    width: 0.85em;
    height: 0.85em;
    margin-left: 0.25em;
    vertical-align: -0.08em;
}

/* In the footer the address stays as muted as its surroundings; the icon and
   hover underline carry the affordance. */
.site-footer .footer-muted .icon-link {
    color: inherit;
}
.sponsor-row {
    display: flex;
    gap: 16px;
    flex-wrap: wrap;
    align-items: center;
}

.sponsor-pill {
    display: inline-flex;
    align-items: center;
    border: 1px solid var(--line);
    background: #fff;
    border-radius: 999px;
    padding: 10px 26px;
    text-decoration: none;
    color: var(--ink-600);
}

.sponsor-pill:hover {
    border-color: var(--brass-600);
    color: var(--brass-600);
}

.sponsor-pill img {
    /* A definite height keeps SVG logos from collapsing to zero size in the flex pill. */
    height: 44px;
    width: auto;
    max-width: 160px;
    object-fit: contain;
}

/* Destructive actions sit apart from the primary ones. */
.danger-zone {
    display: flex;
    justify-content: flex-end;
}

/* Event editor: hide the end/time fields when their checkbox is unchecked.
   Pure CSS so it works with static server rendering; the server decides what
   to save based on the checkbox values, so old browsers degrade gracefully. */
/* The pin's end date only matters once the article is pinned. The field keeps
   posting while hidden, which is exactly what leaves a date waiting for next time. */
.article-form:not(:has(#is-pinned:checked)) .pin-only {
    display: none;
}

.pin-only .form-control {
    max-width: 16rem;
}

/* Why an older article sits at the top of a list ordered by date. */
.pinned-mark {
    white-space: nowrap;
}

.pin-icon {
    width: 0.85em;
    height: 0.85em;
    vertical-align: -0.1em;
}

.event-form:has(#has-end:not(:checked)) .end-only,
.event-form:has(#has-times:not(:checked)) .time-only {
    display: none;
}

@media (prefers-reduced-motion: reduce) {
    .clickable-card, .article-card, .event-row {
        transition: none;
    }
}

.valid.modified:not([type=checkbox]) {
    outline: 1px solid #26b050;
}

.invalid {
    outline: 1px solid #e50000;
}

.validation-message {
    color: #e50000;
}

.blazor-error-boundary {
    background: #b32121;
    padding: 1rem;
    color: white;
    border-radius: 8px;
}

    .blazor-error-boundary::after {
        content: "Ett fel har inträffat."
    }

.darker-border-checkbox.form-check-input {
    border-color: #929292;
}

.form-floating > .form-control-plaintext::placeholder, .form-floating > .form-control::placeholder {
    color: var(--bs-secondary-color);
    text-align: end;
}

.form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder {
    text-align: start;
}

/* ===== Rich article content — also themes the WYSIWYG editing surface ===== */

.article-body img,
.jodit-wysiwyg img {
    max-width: 100%;
    height: auto;
}

.article-body table,
.jodit-wysiwyg table {
    border-collapse: collapse;
    margin: 1rem 0;
    max-width: 100%;
}

.article-body th,
.article-body td,
.jodit-wysiwyg th,
.jodit-wysiwyg td {
    border: 1px solid var(--line);
    padding: 0.35rem 0.7rem;
}

.article-body th,
.jodit-wysiwyg th {
    background: var(--navy-50);
}

.article-body blockquote,
.jodit-wysiwyg blockquote {
    border-left: 3px solid var(--gold-300);
    margin: 1rem 0;
    padding: 0.25rem 0 0.25rem 1rem;
    color: var(--ink-600);
}

/* Placeholder look: in the editor always; on pages only until the viewer
   script has turned the block into a live board (it adds the lpv class to
   the block element itself). */
.article-body .chess-game:not(.lpv):not(:has(.lpv)),
.jodit-wysiwyg .chess-game {
    border: 2px dashed var(--navy-700);
    border-radius: 8px;
    padding: 1rem;
    margin: 1rem 0;
    background: var(--navy-50);
    text-align: center;
    user-select: none;
}

/* ───── Embedded chess games (lichess pgn-viewer) ───── */
.article-body .chess-game.lpv,
.article-body .chess-game:has(.lpv) {
    max-width: 40rem;
    margin: 1.5rem auto;
}

/* Retheme the viewer chrome from lichess dark to the site's palette. The board
   and pieces keep the lichess look; only the surrounding surfaces change. */
.lpv {
    --c-lpv-bg: #fff;
    --c-lpv-bg-movelist: #fff;
    --c-lpv-bg-controls: #fff;
    --c-lpv-bg-pane: var(--navy-50);
    --c-lpv-bg-player: var(--navy-50);
    --c-lpv-bg-variation: var(--navy-50);
    --c-lpv-border: var(--line);
    --c-lpv-side-border: var(--line);
    --c-lpv-font: var(--ink-900);
    --c-lpv-font-shy: var(--ink-600);
    --c-lpv-font-bg: var(--ink-600);
    --c-lpv-past-moves: var(--ink-900);
    --c-lpv-pgn-text: var(--ink-600);
    --c-lpv-move-hover: var(--navy-100);
    --c-lpv-fbt-hover: var(--navy-100);
    --c-lpv-current-move: var(--navy-700);
    --c-lpv-accent: var(--navy-700);
    --c-lpv-accent-over: #fff;
    /* Annotation glyph colors, darkened for a light background. */
    --c-lpv-inaccuracy: hsl(202, 78%, 40%);
    --c-lpv-mistake: hsl(41, 100%, 35%);
    --c-lpv-blunder: hsl(0, 69%, 45%);
    --c-lpv-good-move: hsl(130, 67%, 30%);
    --c-lpv-brilliant: hsl(129, 71%, 32%);
    --c-lpv-interesting: hsl(307, 60%, 45%);
    --c-lpv-bg-inaccuracy-hover: var(--navy-100);
    --c-lpv-bg-mistake-hover: var(--navy-100);
    --c-lpv-bg-blunder-hover: var(--navy-100);
    --c-lpv-bg-good-hover: var(--navy-100);
    --c-lpv-bg-brilliant-hover: var(--navy-100);
    --c-lpv-bg-interesting-hover: var(--navy-100);
}

/* Frame the viewer like the site's cards. Doubled class beats the viewer's own
   .lpv rules, whose stylesheet loads after this one. */
.chess-game.lpv {
    border: 1px solid var(--line);
    border-radius: 14px;
    overflow: hidden;
}

/* Board squares: the site's navy instead of the lichess brown. The conic
   gradient draws the checkerboard, so the two square colors are just these. */
.lpv cg-board {
    background-color: var(--navy-50);
    background-image: conic-gradient(#6d8caf 0 90deg, var(--navy-50) 0 180deg, #6d8caf 0 270deg, var(--navy-50) 0);
    background-size: 25% 25%;
}

/* ===== Weekly club nights (recurring events) ===== */

.break-notice {
    font-style: italic;
    opacity: 0.9;
}

.recurring-row .date-chip .d {
    font-size: 0.95rem;
    letter-spacing: 0.02em;
}

.recurring-description {
    display: block;
    margin-top: 0.25rem;
    color: var(--ink-600);
}

/* A club night's coming evenings, on its own page: a quiet table in which only what
   differs from an ordinary evening stands out. */
.coming-evenings {
    margin-top: 1.25rem;
}

.coming-evenings h3 {
    font-size: 1.1rem;
    font-weight: 600;
    margin-bottom: 0.5rem;
}

.coming-evenings h4 {
    font-size: 1rem;
    margin: 1.25rem 0 0.5rem;
    color: var(--ink-600);
}

/* Not an article table: rows ruled, no grid. The first two columns have fixed widths
   so that the table of later evenings lines up under the coming ones. */
.evening-table {
    border-collapse: collapse;
    width: 100%;
    max-width: 40rem;
    margin: 0;
}

.evening-table td {
    border: none;
    border-bottom: 1px solid var(--line);
    padding: 0.4rem 1rem 0.4rem 0;
    vertical-align: top;
}

.evening-table .evening-date {
    width: 7rem;
}

.evening-table .evening-time {
    width: 7.5rem;
}

.evening-table .evening-date,
.evening-table .evening-time {
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

.evening-table .is-changed {
    font-weight: 600;
}

.evening-table tr.is-cancelled td {
    color: var(--ink-600);
    font-style: italic;
}

/* On a phone the text gets a line of its own under the date and time, rather than a
   column too narrow to read. */
@media (max-width: 575.98px) {
    .evening-table tbody,
    .evening-table td {
        display: block;
    }

    .evening-table tr {
        display: grid;
        grid-template-columns: 7rem 1fr;
        column-gap: 1rem;
        padding: 0.4rem 0;
        border-bottom: 1px solid var(--line);
    }

    .evening-table td {
        border: none;
        padding: 0;
        width: auto;
    }

    .evening-table td:nth-child(3) {
        grid-column: 1 / -1;
    }
}

/* Club night editor. Time and place only matter for an evening that takes place, and
   "tills vidare" only for a break, which then needs no end date. Hidden, the fields
   still post; the save ignores them. */
.override-form:has(#is-break:checked) .program-only,
.override-form:not(:has(#is-break:checked)) .break-only,
.override-form:has(#is-break:checked):has(#until-further-notice:checked) .end-date-field {
    display: none;
}

/* Not Bootstrap's text-nowrap: its !important would stop a phone letting a range wrap. */
.override-dates {
    white-space: nowrap;
}

/* On a phone, upright or sideways, the text gets a line of its own under the date and
   the buttons. As three columns the table needs about 490px once it holds a date range,
   more than the card has below md: it sticks out of the card, and on an upright phone
   past the screen's edge, where the page clips it, buttons included. */
@media (max-width: 767.98px) {
    .override-table,
    .override-table tbody {
        display: block;
    }

    .override-table thead {
        display: none;
    }

    .override-table tr {
        display: grid;
        grid-template-columns: 1fr auto;
        border-bottom-width: var(--bs-border-width);
    }

    /* The line goes under the whole row rather than each cell. The cells still fill the
       row, so that a marked row is shaded throughout, with their content centered. */
    .override-table td {
        border-bottom-width: 0;
        align-content: center;
    }

    .override-table td:nth-child(2) {
        grid-row: 2;
        grid-column: 1 / -1;
        padding-top: 0;
    }

    .override-dates {
        white-space: normal;
    }
}

/* The form that writes a row, shaded apart from the table of rows above it. */
.override-panel {
    padding: 1.25rem 1rem 1rem;
}

/* This evening's time and place, boxed so they are not mistaken for the club night's
   own fields in the card above. */
.override-place {
    border: 1px solid var(--line);
    border-radius: 10px;
    background: #fff;
    padding: 0.5rem 1rem 0;
}

.override-place legend {
    float: none;
    width: auto;
    margin-bottom: 0.25rem;
    padding: 0 0.35rem;
    font-size: 1rem;
    font-weight: 600;
}

a.fact {
    color: inherit;
    text-decoration: none;
}

a.fact:hover {
    text-decoration: underline;
}

/* ===== Admin-editable pages ===== */

/* The first paragraph doubles as the page intro (replaces the old .lead class,
   which the sanitizer strips from stored content). */
.page-body > p:first-of-type {
    font-size: 1.25rem;
    font-weight: 300;
}

/* The menu-title field only matters when the page is shown in the navbar. */
.page-form:not(:has(#show-in-nav:checked)) .nav-title-only {
    display: none;
}

.form-details summary {
    cursor: pointer;
    color: var(--ink-600);
}

/* ===== The menu as an outline (Sidor) ===== */

/* A group's rows share a tint, so that the group reads as one entry with its pages. */
.menu-outline > tbody.menu-group > tr {
    --bs-table-bg: var(--navy-50);
}

/* Indented by where the row is rather than by a class, so a row dragged into or out of
   a group shows its new place at once. */
.menu-outline > tbody.menu-group > tr:not(.menu-group-heading) > td:first-child {
    padding-left: 2rem;
}

/* The note on an empty group goes as soon as a page is dragged into it. */
.menu-outline .menu-group:has([data-menu-page]) .menu-group-empty {
    display: none;
}

/* The drag handles and their hint are menu-outline.js's to offer: without the script,
   the buttons do all the moving. */
.menu-grip,
.menu-outline-hint {
    display: none;
}

.menu-outline.is-sortable .menu-grip {
    display: inline-block;
    padding-right: 0.35rem;
    color: var(--ink-600);
    cursor: grab;
    touch-action: none;
    user-select: none;
}

form:has(.menu-outline.is-sortable) .menu-outline-hint {
    display: block;
}

.menu-outline .is-dragged > td,
.menu-outline tbody.is-dragged > tr > td {
    --bs-table-bg: #f6ecd6;
}

.menu-outline.is-saving {
    opacity: 0.6;
}

body.is-dragging-menu {
    cursor: grabbing;
    user-select: none;
}

/* "Flytta": a <details> opening into a small menu of where the page can go. */
.menu-move {
    position: relative;
    display: inline-block;
}

.menu-move > summary {
    list-style: none;
}

.menu-move > summary::-webkit-details-marker {
    display: none;
}

.menu-move > .dropdown-menu {
    display: block;
    top: calc(100% + 2px);
    right: 0;
}

/* Shortcode placeholder — a live component replaces it on the public page. */
.jodit-wysiwyg .shortcode {
    border: 2px dashed var(--navy-700);
    border-radius: 8px;
    padding: 0.6rem 1rem;
    margin: 1rem 0;
    background: var(--navy-50);
    text-align: center;
    color: var(--navy-700);
    user-select: none;
}
