:root {
    --ink: #e8e6e1;
    --dim: #8b8781;
    --ground: #14161a;
    --panel: #1b1e24;
    --edge: #2a2f38;
    --money: #7fc98a;
    --quiet: #5d6068;
    --accent: #d9a441;
    --held: #e0655a;
    /* How much of a country's own colour is left in an outbound marker. Settled against swatches
       rather than by eye on the map: 82% sat almost exactly on top of the `asleep` fade, which is the
       one thing this must not be mistaken for, and 86% was still close to it. 90% is a step a reader
       can compare two aeroplanes by and no more. */
    --outbound-shade: 90%;
}

* {
    box-sizing: border-box;
}

body {
    margin: 0;
    padding: 24px 16px 64px;
    background: var(--ground);
    color: var(--ink);
    font: 15px/1.5 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    max-width: 880px;
    margin-inline: auto;
}

/* The two pages, and the name of the site at the same time: the page you are on is the heading, the
   other one is the way there. A separate title above them would say the word Ledger twice. */
nav {
    display: flex;
    gap: 20px;
    font-size: 20px;
    letter-spacing: 0.12em;
    text-transform: uppercase;
}

nav a {
    color: var(--quiet);
    text-decoration: none;
}

nav a:hover {
    color: var(--accent);
}

nav a[aria-current='page'] {
    color: var(--ink);
}

h2 {
    font-size: 13px;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--dim);
    margin: 32px 0 10px;
    font-weight: 500;
}

header {
    border-bottom: 1px solid var(--edge);
    padding-bottom: 12px;
}

.line {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-top: 8px;
    color: var(--dim);
    font-size: 13px;
}

/* Who the map draws, at the near end of the line, so the reading and the refresh keep the far end
   between them. Above the media queries with everything else they override. */
.line #shown {
    margin-right: auto;
}

button {
    background: var(--panel);
    color: var(--ink);
    border: 1px solid var(--edge);
    border-radius: 4px;
    padding: 6px 14px;
    font: inherit;
    font-size: 13px;
    cursor: pointer;
}

button:hover {
    border-color: var(--accent);
    color: var(--accent);
}

input {
    background: var(--panel);
    color: var(--ink);
    border: 1px solid var(--edge);
    border-radius: 4px;
    padding: 8px 12px;
    font: inherit;
    flex: 1;
}

#gate {
    margin-top: 48px;
}

#gate .row {
    display: flex;
    gap: 8px;
    max-width: 460px;
}

.note {
    color: var(--dim);
}

table {
    width: 100%;
    border-collapse: collapse;
}

th {
    text-align: left;
    font-weight: 500;
    font-size: 12px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--quiet);
    /* Ruled above as well as below, so the header reads as a box like the prize cards beside it
       rather than as a line of text floating over the first row. The top padding matches their
       inner padding, which puts these labels on the same line as their titles. */
    padding: 10px 10px 8px;
    border-top: 1px solid var(--edge);
    border-bottom: 1px solid var(--edge);
}

td {
    padding: 9px 10px;
    border-bottom: 1px solid var(--edge);
}

.place {
    color: var(--quiet);
    width: 28px;
}

.figure {
    text-align: right;
    width: 80px;
}

.money {
    color: var(--money);
}

a {
    color: inherit;
    text-decoration: none;
    border-bottom: 1px solid var(--edge);
}

a:hover {
    color: var(--accent);
    border-color: var(--accent);
}

/* The links, the status and the strip pin together at the top of the window: they are all read
   while the log scrolls under them, and pinning the strip alone left the nav a scroll away. The
   negative margins are the body's own padding, so the bar covers the width of the window while its
   contents stay on the same measure as everything else, and its height is published as --topbar for
   anything else that sticks below it.

   Ahead of the media queries, like every other rule they touch. */
.topbar {
    position: sticky;
    top: 0;
    z-index: 3;
    background: var(--ground);
    margin: -24px -16px 0;
    padding: 24px 16px 20px;
}

/* What is happening this minute, pinned with the rest of the bar above. The negative inline margin
   is the body's own padding, so the strip runs edge to edge while its contents stay on the same
   measure as everything else. */
#ticker {
    overflow: hidden;
    margin: 0 -16px;
    padding: 7px 0;
    background: var(--panel);
    border-top: 1px solid var(--edge);
    border-bottom: 1px solid var(--edge);
    font-size: 13px;
    white-space: nowrap;
}

/* The items are written out twice and this slides exactly half the track, which is the whole trick:
   the second copy is under the eye by the time the first has left, so there is no seam to hide. */
.ticker-track {
    display: inline-flex;
    animation: ticker-run var(--ticker-seconds) linear infinite;
    /* The strip animates inside the pinned bar, so without a layer of its own every frame of it
       repaints the header over a scrolling log. */
    will-change: transform;
}

@keyframes ticker-run {
    to {
        transform: translateX(-50%);
    }
}

/* A name that catches the eye can be read rather than chased. */
#ticker:hover .ticker-track {
    animation-play-state: paused;
}

/* Somebody who has asked their machine for less movement is not asking for a slower marquee. */
@media (prefers-reduced-motion: reduce) {
    .ticker-track {
        animation: none;
    }
}

/* A screen wide at the least, so a strip with three names on it spreads them out rather than sliding
   them off and leaving the loop to run on nothing. */
.ticker-copy {
    display: inline-flex;
    min-width: 100vw;
    justify-content: space-around;
}

.tick {
    display: inline-flex;
    align-items: baseline;
    gap: 8px;
    padding: 0 18px;
    border-right: 1px solid var(--edge);
}

.tick .country,
.tick .tick-what {
    margin-left: 0;
    color: var(--dim);
}

.tick .worth {
    color: var(--money);
}

/* The people still out there lead the strip and are the reason to look at it at all. */
.tick.underway strong {
    color: var(--accent);
}

/* Five columns of fixed width rather than fractions, because the log is read down a column and not
   across a row: what matters is that every time, every duration and every figure starts where the one
   above it did. The minutes have a column of their own for the same reason - inside the time cell they
   wrapped onto a second line whenever the range was long enough. */
.trip {
    display: grid;
    /* A sixth column for the button that strikes a row off, declared rather than left implicit: an
       implicit column is added past the end of the template, so the X wrapped onto a line of its own
       under every row. The by-hand rows had it right and the trips did not. */
    grid-template-columns: 210px 175px 58px minmax(0, 1fr) 118px auto;
    gap: 12px;
    align-items: start;
    padding: 10px;
    border-bottom: 1px solid var(--edge);
}

.trip .when,
.trip .howlong,
.trip .worth {
    white-space: nowrap;
}

.howlong {
    text-align: right;
    color: var(--quiet);
    font-size: 13px;
}

/* On its own line under the verdict: beside it, a long item name pushed it into a ragged second row
   that lined up with nothing. */
.runner-up {
    display: block;
}

/* A Torn day is a band rather than a repeated date: the log is read to find what a day was worth, and
   a block with an edge and a total under it answers that where a column of dates does not. Every
   other row is shaded so two days running never read as one long one.

   Ahead of the media queries on purpose - the narrow layout collapses these columns, and a plain rule
   after them would win on source order and undo it. */
.day.shaded {
    background: #171a1f;
}

.day-total {
    display: grid;
    grid-template-columns: 210px 175px 58px minmax(0, 1fr) 118px auto;
    gap: 12px;
    padding: 8px 10px;
    border-bottom: 1px solid var(--edge);
    font-size: 13px;
    color: var(--dim);
}

.day-total .worth {
    grid-column: 5;
    color: var(--money);
}

.trip.asleep,
.trip.nothing,
.trip.underway {
    color: var(--quiet);
}

.trip.asleep a,
.trip.nothing a,
.trip.underway a {
    color: var(--quiet);
}

.country {
    color: var(--dim);
    margin-left: 10px;
}

.when {
    color: var(--dim);
    font-size: 13px;
}

.dash {
    color: var(--quiet);
    margin: 0 6px;
}

.runner-up {
    color: var(--quiet);
    font-size: 12px;
}

.worth {
    text-align: right;
    color: var(--money);
}

.trip.asleep .worth,
.trip.nothing .worth,
.trip.underway .worth {
    color: var(--quiet);
}

.empty,
.caveat {
    color: var(--quiet);
    font-size: 13px;
}

.caveat {
    margin-top: 32px;
    border-top: 1px solid var(--edge);
    padding-top: 16px;
}

/* The line people arrive wanting answered, so it is the loudest thing in the quietest paragraph:
   the accent colour and its own line, above a caveat that is otherwise deliberately dim. Uppercase in
   the markup rather than by a rule, because it is written that way and reads that way in the source. */
.no-key {
    display: block;
    color: var(--accent);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    font-weight: 500;
    margin-bottom: 6px;
}

/* Read before the table rather than after it, so the rule is ruled off below itself: under a column
   the line above it separated it from the log, and at the top of the board the same line would sit
   under the header's own. */
#board > .caveat,
#graphs > .caveat,
#atlas > .caveat {
    margin: 0 0 24px;
    border-top: 0;
    border-bottom: 1px solid var(--edge);
    padding: 0 0 16px;
}

/* The map. Everything is drawn in the projection's own units and scaled by the viewBox, so the one
   number that matters here is the aspect ratio the outline was generated at. */
#map {
    margin-top: 24px;
    border: 1px solid var(--edge);
    border-radius: 4px;
    background: var(--panel);
    overflow: hidden;
    /* A drag across the map is a drag of the map. Without this the browser reads the same gesture as
       selecting the labels it passes over and paints half the country names blue. */
    user-select: none;
    -webkit-user-select: none;
    cursor: grab;
}

#map svg {
    display: block;
    width: 100%;
    height: auto;
    /* The wheel is a zoom over the map, so the browser must not also treat it as a page scroll or a
       pinch of its own. */
    touch-action: none;
}

#map.dragging {
    cursor: grabbing;
}

.land {
    fill: #232830;
    stroke: var(--edge);
    stroke-width: 0.4;
}

/* Tinted with its destination's own colour, faintly: a route is background, and eleven bright arcs
   out of one point would be the loudest thing on a map whose subject is people. */
.route {
    fill: none;
    stroke: var(--to);
    stroke-width: 0.8;
    stroke-dasharray: 3 3;
    opacity: 0.22;
}

/* Every marker that belongs to a country carries that country's colour, which is what ties three red
   aeroplanes to the red dot they are heading for without a legend anywhere. */
.place .dot {
    fill: var(--to);
}

/* A country's dot is worth pointing at, and its name is the easier target of the two. */
.place {
    cursor: default;
}

.place.home .dot {
    fill: var(--accent);
}

/* No size and no anchor here: both are written onto the element, because the placing in
   map-render.js has to measure the text and a second copy of either would drift away from it. */
.place-name {
    fill: var(--dim);
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    letter-spacing: 0.08em;
}

.flight-name {
    fill: var(--to);
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

/* From a marker to its name, for every one of them rather than only the ones moved out of a pile:
   drawn sometimes, its absence read as a name belonging to nothing. Its own colour, so a line
   crossing a crowd is still obviously that person's. */
.leader {
    stroke: var(--to);
    stroke-width: 0.5;
    opacity: 0.6;
}

/* Outlined in the sea's own colour, so three aeroplanes on the same heading read as three shapes
   rather than as one blob. */
.plane {
    fill: var(--to);
    stroke: var(--panel);
    stroke-width: 0.7;
}

/* The panel under the pointer. It is drawn into the same layer as the markers, so it survives the
   redraw a second later, and it never takes the pointer: hovering the panel would otherwise count as
   leaving the marker it belongs to and it would close under the cursor. */
.detail-layer {
    pointer-events: none;
}

.detail rect {
    fill: var(--ground);
    stroke: var(--to);
    stroke-width: 0.8;
}

.detail-line {
    fill: var(--dim);
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

/* The name or the country at the top of it, in that country's colour. */
.detail-line.heading {
    fill: var(--to);
}

/* What is on the shelf now against what is only expected: one is a thing you can buy.
   Prefixed, and not called `empty`: the ledger already has an `.empty` and it carries a font size,
   which silently made this column half again too wide for the panel measured around it. */
.detail-line.shelf-stocked {
    fill: var(--money);
}

.detail-line.shelf-empty {
    fill: var(--quiet);
}

/* A marker is worth pointing at, and the whole group answers rather than the four pixels of the
   aeroplane itself: the name beside it is the easier target. */
.flight {
    cursor: default;
}

.flight[data-hovered] .flight-name {
    text-decoration: underline;
}

/* **Going out is drawn a shade darker than coming home**, aeroplane and name together, because the
   nose is four pixels wide in a crowd and the user could not tell who was leaving from who was
   returning. It is deliberately a small step - `--outbound-shade` mixed towards black rather than
   towards the ground - so it cannot be read as the fade `asleep` puts on a marker: that one lightens
   towards the background and takes the whole group with it, this one keeps the country's colour and
   only deepens it. Mixed in oklab, which darkens without dragging the hue somewhere else.

   Applied where the colour is used and never to `--to` itself: a custom property defined from its own
   value is a cycle, and the browser throws the whole declaration away. */
.flight.outbound .plane,
.flight.outbound .pin {
    fill: color-mix(in oklab, var(--to) var(--outbound-shade), #000);
}

.flight.outbound .flight-name {
    fill: color-mix(in oklab, var(--to) var(--outbound-shade), #000);
}

.flight.abroad .pin {
    fill: var(--to);
    stroke: var(--panel);
    stroke-width: 0.7;
}

/* The state of somebody on the ground is drawn on top of their colour rather than instead of it:
   faded for asleep, and a plus in place of the disc for a bed they cannot shop from whatever their
   last action says. The shape carries that second state rather than a colour, because every colour
   here belongs to a country and the ring this replaced was invisible on the red ones.

   The two are independent and compose: somebody hospitalised while logged off is a faded plus, which
   needs no rule of its own and is why the marker carries a class per state rather than one class. */
.flight.asleep {
    opacity: 0.62;
}

.lists {
    display: grid;
    gap: 24px;
    margin-top: 8px;
}

.away-row {
    display: grid;
    grid-template-columns: 140px 1fr 56px;
    gap: 12px;
    padding: 6px 0;
    border-bottom: 1px solid var(--edge);
    font-size: 13px;
}

/* The same colour their aeroplane is, which makes the list the map's legend without one being drawn:
   the red names are the people in the red aeroplanes. */
.away-name {
    color: var(--to);
}

.away-what {
    color: var(--dim);
}

.away-when {
    color: var(--quiet);
    text-align: right;
}

.at-home {
    display: flex;
    flex-wrap: wrap;
    gap: 8px 14px;
    font-size: 13px;
    color: var(--dim);
}

@media (max-width: 640px) {
    .trip,
    .by-hand-row,
    .day-total {
        grid-template-columns: 1fr auto;
        row-gap: 4px;
    }

    .howlong {
        text-align: left;
    }

    .what {
        grid-column: 1 / -1;
    }

    /* The fifth column does not exist here, and asking for it would open an implicit sixth. */
    .day-total .worth {
        grid-column: auto;
    }
}

.add button,
.drop button,
.add-run,
.drop-run {
    padding: 3px 10px;
    font-size: 12px;
}

/* Quiet until it is reached for. It sits at the end of every row in the log and is the one control
   there that cannot be undone, so it reads as a mark in the margin rather than as something to press
   - and it says so in red under the cursor. */
.drop-trip {
    padding: 3px 8px;
    font-size: 12px;
    line-height: 1;
    color: var(--quiet);
    background: none;
    border: 1px solid transparent;
}

.drop-trip:hover,
.drop-trip:focus-visible {
    color: var(--held);
    border-color: var(--edge);
}

.add-anyone {
    display: flex;
    gap: 8px;
    max-width: 520px;
    margin-bottom: 16px;
}

td.add {
    text-align: right;
    width: 1%;
    white-space: nowrap;
}

.by-hand {
    color: var(--accent);
    margin-left: 4px;
    font-size: 12px;
}

.by-hand-row .drop {
    padding-left: 12px;
}


/* Under the verdict with the runner up, for the same reason: a trailing note beside a long item name
   wraps into a line that starts nowhere in particular. */
.judged {
    display: block;
    color: var(--quiet);
    font-size: 12px;
}

.figure {
    white-space: nowrap;
}

.sortable button {
    background: none;
    border: 0;
    padding: 0;
    /* A button centres its own text, so a header long enough to wrap put its second line down the
       middle of a column of right-aligned numbers. */
    text-align: right;
    font: inherit;
    font-size: 12px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--quiet);
    cursor: pointer;
}

.sortable button:hover {
    color: var(--accent);
}

.sortable.sorted button {
    color: var(--ink);
}

/* Before the label, never after it: a marker on the right pushes the label off the edge the figures
   below are aligned to, and the sorted column is exactly the one being read most carefully. */
.sortable.sorted button::before {
    content: "▾ ";
    color: var(--accent);
}

th.sortable {
    text-align: right;
}

th.sortable:first-of-type {
    text-align: right;
}

summary {
    font-size: 13px;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--dim);
    margin: 32px 0 10px;
    cursor: pointer;
    list-style: none;
}

summary::-webkit-details-marker {
    display: none;
}

/* The triangle is drawn rather than left to the browser, whose default marker sits outside the text
   and pulls the heading off the left edge every other block on the page shares. */
summary::before {
    content: '+ ';
    color: var(--quiet);
}

details[open] > summary::before {
    content: '- ';
}

summary:hover {
    color: var(--accent);
}

.pager {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 16px;
    padding: 16px 0;
    color: var(--dim);
    font-size: 13px;
}

.pager button {
    border-radius: 999px;
    padding: 6px 16px;
}

.pager button:disabled {
    color: var(--quiet);
    border-color: var(--edge);
    cursor: default;
}

.pager button:disabled:hover {
    color: var(--quiet);
    border-color: var(--edge);
}

/* Both of these sit ahead of the media queries on purpose: those raise or zero them for the two
   column layout, and a plain rule after them would win on source order and quietly undo it. That has
   now cost two rounds, once on the alignment and once on this gap. */
#months {
    margin-bottom: 12px;
}

/* they raise this for the two column layout, and a plain rule
   sitting after them would win on source order and quietly undo it. */
#categories {
    margin-top: 32px;
}

/* One column until there is genuinely room for two. Below this the prizes sit under the log, which is
   the order they matter in on a narrow screen. */
@media (min-width: 1100px) {
    body {
        max-width: 1440px;
    }

    #board {
        display: grid;
        grid-template-columns: minmax(0, 1fr) 320px;
        /* No row gap on purpose. The picker is its own row, and a gap there stacked on top of its
           own margin and the Standings heading's 32px left eighty-four pixels of nothing between the
           two. The heading's margin is the whole separation, exactly as it is everywhere else. */
        column-gap: 40px;
        row-gap: 0;
        align-items: start;
    }

    #months {
        margin-bottom: 0;
    }

    /* Without this a grid child refuses to shrink below its widest content, and one long item name in
       the trip log would push the prizes off the screen. */
    #board > .column {
        min-width: 0;
    }

    /* Across both columns, because it is about every figure on the board and not only the ones in the
       left one - and a paragraph squeezed into a 320px column would be eight lines tall. */
    #board > .caveat {
        grid-column: 1 / -1;
    }

    #categories {
        position: sticky;
        /* Under the pinned bar rather than under the top of the window, which is where it would be
           hidden by it. */
        top: calc(var(--topbar, 0px) + 24px);
        /* Level with the table's header row, not with the heading above it: the prizes are a second
           reading of the same table, so they start where its columns do. The offset is that heading's
           own line plus the gap under it, written out from the rule that sets them rather than
           measured off a screenshot - change the heading and this follows. */
        margin-top: calc(32px + (13px * 1.5) + 10px);
    }
}

/* Two columns of prizes, so all five are on the screen at once rather than five stacked cards that
   reach the bottom of it. Held back to 1400px because the sidebar has to grow to fit them, and below
   that the trip log's own five columns need the width more than the prizes do. */
@media (min-width: 1400px) {
    /* Across the top of both columns rather than inside the left one. It governs the whole board -
       the standings, the prizes, the log and the hand entries - and putting it in a column would
       both understate that and push the table header out of line with the cards beside it. */
    #months {
        grid-column: 1 / -1;
    }

    #board {
        /* 480 and not 440, measured rather than guessed: the two longest titles need 199px on one
           line and were getting 189, so both wrapped. This leaves each card's text 209px, which is
           slack enough to survive a font that renders a little wider. */
        grid-template-columns: minmax(0, 1fr) 480px;
    }

    #categories {
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: 10px;
        align-content: start;
    }

    .prize {
        margin-bottom: 0;
    }
}

.prize {
    border: 1px solid var(--edge);
    border-radius: 6px;
    padding: 10px 12px;
    margin-bottom: 10px;
}

.prize h3 {
    margin: 0;
    font-size: 13px;
    letter-spacing: 0.06em;
    color: var(--ink);
    font-weight: 500;
}

.prize .reward {
    margin: 1px 0 7px;
    font-size: 12px;
    color: var(--accent);
}

.prize ol {
    list-style: none;
    margin: 0;
    padding: 0;
}

.prize li {
    display: grid;
    grid-template-columns: 14px minmax(0, 1fr) auto;
    gap: 8px;
    align-items: baseline;
    font-size: 13px;
    padding: 1px 0;
}

.prize li.empty {
    display: block;
    color: var(--quiet);
    font-size: 12px;
}

.prize .place {
    color: var(--quiet);
}

.prize .name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.prize .figure {
    color: var(--money);
    text-align: right;
    width: auto;
}

/* The graphs' own picker joins the ledger's two rather than getting a look of its own: they are the
   same control doing the same job a page apart, and a reader crossing between them should not have
   to notice which page they are on. */
#months select,
#players select,
#period-picker select,
#shown,
#detail,
#run {
    background: var(--panel);
    color: var(--ink);
    border: 1px solid var(--edge);
    border-radius: 4px;
    padding: 5px 10px;
    font: inherit;
    font-size: 13px;
    cursor: pointer;
}

#months select:hover,
#players select:hover,
#period-picker select:hover,
#shown:hover,
#detail:hover,
#run:hover {
    border-color: var(--accent);
}

/* The picker sits inside the fold rather than above it, because it narrows the log and nothing else:
   the standings and the prizes are the whole company whichever name is chosen. */
#players {
    margin: 4px 0 12px;
}

/* The same width the ledger opens its second column at: below it the names and what they are doing
   need the whole line. */
@media (min-width: 1100px) {
    .lists {
        grid-template-columns: 1fr 1fr;
    }
}

/* ---------------------------------------------------------------------------------------------
   The graphs page. Nothing below is overridden by any of the media queries above it, and the one
   responsive thing on it - the grid of cards - is an `auto-fill` rather than a breakpoint, so there
   is no rule here that has to be kept above a query to win on source order. That trap has cost two
   rounds already elsewhere in this file.
   --------------------------------------------------------------------------------------------- */

.picker {
    margin: 20px 0 12px;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
}

#typed-range {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
}

.typed {
    color: var(--dim);
    font-size: 12px;
    display: flex;
    align-items: center;
    gap: 6px;
}

.typed input {
    background: var(--panel);
    color: var(--ink);
    border: 1px solid var(--edge);
    border-radius: 4px;
    padding: 4px 8px;
    font: inherit;
    font-size: 13px;
    cursor: pointer;
    /* Chrome draws the picker's own icon in black on a dark field, which is a control you cannot see
       you have. Inverting is the whole of the fix and it touches nothing else. */
    color-scheme: dark;
}

.typed input:hover {
    border-color: var(--accent);
}

/* Every other boundary on this page is Torn's midnight and nothing says so, because nothing else is
   typed in. This one is, and a reader entering a date is entitled to know which clock it lands on. */
.typed-note {
    color: var(--quiet);
    font-size: 11px;
}

/* The chips are the whole of how this page is narrowed, so they read as pressable and say plainly
   which of them are on. The leading one is wider than the rest because it says two different things
   depending on what is picked, and a button that changes width as it changes word moves the row. */
.chips {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-bottom: 8px;
}

.chip {
    background: var(--panel);
    color: var(--dim);
    border: 1px solid var(--edge);
    border-radius: 999px;
    padding: 5px 12px;
    font: inherit;
    font-size: 12px;
    cursor: pointer;
}

.chip:hover {
    color: var(--ink);
}

/* The person's own colour, the same one their line is drawn in, shown as the rim rather than as the
   fill: eight filled pills at once is the loudest thing on the page, and what is asked of the colour
   is only that this chip is that line. The countries carry none, deliberately - on a page comparing
   people, a bright hue on a place has a reader matching a colour to the wrong kind of thing. */
.chip.on {
    color: var(--ink);
    border-color: var(--to, var(--accent));
    box-shadow: inset 0 0 0 1px var(--to, var(--accent));
}

/* Lit or not, a name keeps a dot of its own colour: the chart draws everybody when nothing is
   picked, so the row has to be readable as a key before anything is chosen. */
.chips#people .chip:not(.all)::before {
    content: '';
    display: inline-block;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    margin-right: 7px;
    vertical-align: 1px;
    background: var(--to, var(--quiet));
}

.chip.all {
    min-width: 104px;
}

.panel {
    border: 1px solid var(--edge);
    border-radius: 4px;
    margin: 16px 0 24px;
    background: var(--panel);
}

.tabs {
    display: flex;
    border-bottom: 1px solid var(--edge);
}

.tab {
    flex: 1;
    background: none;
    border: none;
    border-bottom: 2px solid transparent;
    color: var(--quiet);
    font: inherit;
    padding: 12px 8px;
    cursor: pointer;
}

.tab:hover {
    color: var(--ink);
}

.tab.on {
    color: var(--ink);
    border-bottom-color: var(--accent);
}

#chart {
    padding: 12px 8px 0;
}

/* Scaled by width with the aspect ratio kept, which is what stops the axis labels from being
   stretched sideways on a wide screen: the plot is laid out in its own units and the browser
   magnifies the lot, exactly as the map does with its viewBox. */
#chart svg {
    display: block;
    width: 100%;
    height: auto;
}

.chart-grid {
    stroke: var(--edge);
    stroke-width: 1;
}

.chart-axis {
    fill: var(--dim);
    font-size: 11px;
}

/* One rule for a whole series - its line and every dot on it - off the one colour the group carries.
   Eight people means eight groups, and none of them restates a colour anywhere. */
.chart-line {
    fill: none;
    stroke: var(--who, var(--ink));
    stroke-width: 2;
    stroke-linejoin: round;
}

.chart-dot {
    fill: var(--who, var(--ink));
    /* The wide circle behind it takes every pointer, so this one never has to be aimed at and never
       steals the hover from the shape that carries the card's text. */
    pointer-events: none;
}

/* The target, and nothing else: a drawn dot is about five pixels of radius on a chart with eight
   lines crossing through it, which is the hardest thing on the page to hit. Transparent rather than
   hidden, because `visibility: hidden` and `display: none` both take the pointer with them. */
.chart-hit {
    fill: transparent;
    cursor: pointer;
}

/* Ringed in the page's own ground so it reads as lifted off the line rather than as a fatter dot. */
.chart-hit:hover + .chart-dot,
.chart-dot:hover {
    r: 5;
    stroke: var(--ground);
    stroke-width: 2;
}

/* Eight lines crossing is the comparison the page is open for, and it is also eight lines crossing.
   Hovering one lifts it out and pushes the rest back, which is cheaper to read than any amount of
   dashing or thinning - and it needs no script, because the group is already the unit. */
#chart:hover .series {
    opacity: 0.28;
}

/* A series whose point is being hovered is the one being read, and the target circle sits inside the
   same group as the line - so the two rules agree without either knowing about the other. */
#chart .series:has(.chart-hit:hover) {
    opacity: 1;
}

#chart .series:hover {
    opacity: 1;
}

#chart .series:hover .chart-line {
    stroke-width: 3;
}

.chart-empty {
    color: var(--dim);
    text-align: center;
    padding: 60px 0;
    margin: 0;
}

/* The card floats over the chart, so the box around them both is what it is placed against. */
.plot {
    position: relative;
}

.tip {
    position: absolute;
    pointer-events: none;
    background: var(--ground);
    border: 1px solid var(--money);
    border-radius: 5px;
    padding: 7px 11px 8px;
    white-space: nowrap;
    box-shadow: 0 4px 14px rgb(0 0 0 / 45%);
    z-index: 2;
}

.tip-when {
    margin: 0 0 3px;
    color: var(--ink);
    font-size: 12px;
}

.tip-line {
    margin: 0;
    color: var(--dim);
    font-size: 13px;
    display: flex;
    align-items: center;
    gap: 6px;
}

.tip-line i {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--who, var(--ink));
}

.tip-line b {
    color: var(--ink);
    font-weight: 500;
}

.tip-line b.money {
    color: var(--money);
}

/* Which of the two Daily Travel is showing. Under the tabs rather than beside them: it belongs to
   one tab, and a control on the tab row would read as a fourth chart. */
.toggles {
    display: flex;
    gap: 6px;
    padding: 10px 14px 0;
}

.toggle {
    background: none;
    border: 1px solid var(--edge);
    border-radius: 3px;
    color: var(--dim);
    font: inherit;
    font-size: 12px;
    padding: 4px 10px;
    cursor: pointer;
}

.toggle:hover {
    color: var(--ink);
}

.toggle.on {
    color: var(--ink);
    border-color: var(--accent);
}

/* The lines cannot say whose they are, and the chips above only light the picked ones - while the
   state this page opens in is nothing picked, which is everybody. */
.legend {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 16px;
    padding: 6px 14px 0;
    font-size: 12px;
    color: var(--dim);
}

.key {
    display: flex;
    align-items: center;
    gap: 6px;
}

.key i {
    width: 14px;
    height: 2px;
    background: var(--who, var(--ink));
}

.key b {
    color: var(--money);
    font-weight: 400;
}

.scope {
    color: var(--dim);
    font-size: 12px;
    margin: 0;
    padding: 8px 14px 12px;
}

/* As many cards as fit, at whatever width is left over. An `auto-fill` rather than a breakpoint
   because the number of countries changes with the filter, and a fixed three columns leaves one
   card stranded across a whole row whenever the answer is four. */
.cards {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: 12px;
    margin-bottom: 12px;
}

.card {
    border: 1px solid var(--edge);
    border-radius: 4px;
    background: var(--panel);
    padding: 14px 16px 16px;
}

/* The title and the picker share the card's top line. The title keeps its own bottom margin as the
   card's only heading spacing, so a card with no picker on it is laid out exactly as before. */
.card-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
}

/* Smaller than the pickers above the board: this one narrows a card rather than the whole page, and
   at the size of those it was the loudest thing in the column. */
#detail {
    font-size: 12px;
    padding: 3px 6px;
    max-width: 60%;
}

.card h3 {
    margin: 0 0 12px;
    font-size: 15px;
    font-weight: 500;
    letter-spacing: 0.04em;
}

.card h3.country {
    color: var(--to, var(--ink));
}

.figures {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 10px 6px;
    text-align: center;
}

/* Two figures rather than three on the first row of a card, which is the shape torn.report uses and
   the reason it reads: trips and time are what the card is about, and the money below it is the
   answer. Spanning is cheaper than a second grid. */
.figures:first-of-type {
    grid-template-columns: repeat(2, 1fr);
}

.figure b {
    display: block;
    font-weight: 500;
    color: var(--ink);
    font-size: 14px;
}

.figure span {
    display: block;
    color: var(--dim);
    font-size: 11px;
}

.figure.money b {
    color: var(--money);
}

.figure.spend b {
    color: var(--accent);
}

.figures-head {
    text-align: center;
    color: var(--dim);
    font-size: 11px;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    border-top: 1px solid var(--edge);
    margin: 12px 0 10px;
    padding-top: 8px;
}

.imports {
    width: 100%;
    border-collapse: collapse;
    margin-top: 14px;
    font-size: 12px;
}

/* Two pages share one stylesheet, and this file's `th` is not a class but the element itself: the
   ledger's table header is uppercase, letter-spaced and ruled top and bottom, and every one of those
   landed on an item name here. "Xanax" rendered as "XANAX" inside a box. The same collision the shop
   panel's `.empty` caused on the map, one selector wider - so the inherited rule is undone once,
   above the two that build on it. */
.imports th {
    text-transform: none;
    letter-spacing: 0;
    font-size: 12px;
    border: none;
    padding: 6px 0;
}

.imports th[scope='col'] {
    text-align: right;
    color: var(--dim);
    font-weight: 500;
    border-bottom: 1px solid var(--edge);
    padding-bottom: 6px;
}

.imports th[scope='col']:first-child {
    text-align: left;
}

.imports th[scope='row'] {
    text-align: left;
    font-weight: 400;
    color: var(--ink);
}

.imports td {
    text-align: right;
    padding: 6px 0;
    vertical-align: top;
}

.imports td.money {
    color: var(--money);
}

/* How many were carried and what one of them made, both said under the thing they belong to rather
   than in columns of their own: the table is read down a column, and two more of them on a card this
   narrow is where the numbers start wrapping. */
.units,
.unit-rate {
    display: block;
    color: var(--dim);
    font-size: 11px;
}

.ring {
    display: flex;
    align-items: center;
    justify-content: center;
    /* The card it opens is placed against this box, the way the chart's is placed against the plot. */
    position: relative;
}

#ring {
    width: 100%;
    display: flex;
    justify-content: center;
}

.ring svg {
    width: 100%;
    max-width: 260px;
    height: auto;
}

.ring-slice {
    stroke: var(--panel);
    stroke-width: 2;
    cursor: pointer;
}

/* The slice under the pointer is the one being read, and the ramp it is drawn from is eleven steps
   of one hue - so lifting it has to be something other than a colour. */
.ring-slice:hover {
    stroke: var(--ink);
}

.ring-total {
    fill: var(--ink);
    font-size: 26px;
}

.ring-word {
    fill: var(--dim);
    font-size: 11px;
}
