/* Ticket to Ride — the whole stylesheet.
 *
 * Dark, because a board full of coloured track reads better against it, and
 * because family game night is usually at night. Laid out so the map takes
 * whatever space is going and the panels stay a fixed, readable column.
 */

:root {
  --bg: #0d1117;
  --panel: #161b22;
  --panel-edge: #262c36;
  --ink: #c9d1d9;
  --ink-dim: #7d8590;
  --accent: #58a6ff;
  --good: #3fb950;
  --bad: #f85149;

  /* The eight train colours, plus locomotives and unclaimed gray track. */
  --red: #c93a40;
  --orange: #f76b15;
  --yellow: #f5d90a;
  --green: #3fbf7f;
  --blue: #3e63dd;
  /* What each player colour is painted as. Red and green are the train-card
   * colours of the same name -- a player's trains and the track they pay
   * with should not be two reds -- and the rest are their own. The class
   * `player-<colour>` sets `--paint` from these, and everything coloured
   * by a player reads that one property. */
  --player-red: var(--red);
  --player-blue: var(--blue);
  --player-green: var(--green);
  --player-yellow: var(--yellow);
  --player-purple: #8e4ec6;
  --pink: #d6409f;
  --white: #e6edf3;
  --black: #4a5058;
  --gray: #6b7280;
  --loco: linear-gradient(135deg, #f5d90a, #d6409f, #3e63dd);

  /* The lit edge of each train colour. A card is a gradient from this down to
   * the colour itself, which is what gives the face its sheen. */
  --red-lit: #e8555a;
  --orange-lit: #ff9142;
  --yellow-lit: #ffe95c;
  --green-lit: #6fdc9f;
  --blue-lit: #6d8bef;
  --pink-lit: #ee6cba;
  --white-lit: #ffffff;
  --black-lit: #6b727c;
  /* White needs a shaded edge of its own; the other seven shade to the colour
   * the board already uses for their track. */
  --white-deep: #d7dee6;

  /* A card face is light, so what is written on it is dark -- except on the
   * two dark colours, which take the light ink instead. The border is the same
   * bright edge on every one. */
  --card-ink: #0b1b2b;
  /* The board's ground, and the dark edge drawn on things that sit on it. */
  --board-ink: #0b1b2b;
  --card-ink-light: #f2f6ff;
  --card-edge: rgb(255 255 255 / 82%);

  /* A card, and the smaller one -- shown by the face-up market always, and by
   * the hand too once the screen is narrow enough that the full size will not
   * fit. The board reserves room for the hand from these, and the fan overlaps
   * cards by a fraction of this width, so they are written down exactly
   * once. */
  --card-width: 78px;
  --card-height: 108px;
  --card-width-small: 44px;
  --card-height-small: 61px;
  --card-radius: 9px;
  --hover-lift: 26px;
  /* How far the count badge hangs off the leading corner. Part of how wide the
   * fan really is, so it is a token the fit test can read. */
  --count-offset: 7px;
  /* The gutter around the whole table. In pixels, not rem, because the fan has
   * to be measured against it and everything it is measured with is pixels. */
  --layout-pad: 12px;
  /* How far a floating panel and the map's zoom buttons sit in from the
   * board's edge, how big a zoom button is, and so how much room the buttons
   * take on the right. */
  --floating-inset: .6rem;
  /* How far the route tip sits from the pointer. */
  --tip-offset: .9rem;
  /* A light wash of the accent, for the thing to look at. */
  --accent-wash: rgb(88 166 255 / 12%);
  /* The glow behind a lit city: the accent, and the green of a finished
   * ticket, at the same strength. These are `--accent` and `--green` with an
   * alpha, and must move with them. */
  --accent-glow: rgb(88 166 255 / 60%);
  --green-glow: rgb(63 191 127 / 60%);
  /* The dashed guide between a ticket's two cities. */
  --guide-dash: 7px;
  --guide-gap: 6px;
  /* A card in flight is the size of a face-up card. How long it is in the
   * air (`--flight-time`) is set on the layer by the code that also tidies
   * it up once landed, so the two cannot disagree. */
  --flight-width: 44px;
  --flight-height: 62px;
  /* Laying a carriage: how long each takes, with an overshoot so it settles
   * rather than arrives. */
  --lay-time: 260ms;
  /* The colour shapes on the slots; a laid one is a touch smaller, to sit
   * inside the car. */
  --shape-size: 9px;
  --lay-ease: cubic-bezier(.2, 1.4, .4, 1);
  --map-controls-size: 2rem;
  --map-controls-width: calc(2 * var(--floating-inset) + var(--map-controls-size));
  /* How far the cards after a hovered one shuffle along to make room. */
  --hover-spread: 10px;
  /* The line of text under the fan, and how far the whole dock sits off the
   * bottom of the board. */
  --hand-total-line: 1.1rem;
  --dock-inset: .4rem;

  /* The shell -- every page that is not the table. Spacing and type first,
   * then the measures its layouts are built from. */
  --raised: #21262d;
  --raised-hover: #2d333b;
  --accent-ink: #04131f;
  /* The focus ring is the one yellow thing on a page, so it is never mistaken
   * for the accent that marks what is selected. */
  --focus: var(--yellow);
  --ring: 3px;
  --ring-gap: 2px;
  --hairline: 1px;
  --edge: 2px;
  --dim: .4;
  --gap: 1rem;
  --gap-small: .5rem;
  --gap-large: 2rem;
  --small: .85rem;
  --tracking: .08em;
  --radius: 10px;
  --radius-small: 8px;
  --radius-tiny: 4px;
  --swatch: .9rem;
  --page: 72rem;
  --prose: 42rem;
  --form: 30rem;
  --field: 8rem;
  --column-wide: 18rem;
  --column-narrow: 9rem;
  --aside: 18rem;
  --stat-size: 1.6rem;
  /* A room code: as it is typed, and as it is read out. */
  --code-typed: 1.3rem;
  --code-size: 2.6rem;
  --code-tracking: .35em;
  /* The replay: how tall the board stands in the page, how tall the list of
   * moves may grow before it scrolls, and a card small enough for a whole
   * deck of them. */
  --stage-height: min(70vh, 40rem);
  --scroller: 22rem;
  --chip-size: 1.5rem;
  --chip-gap: .2rem;
  --chip-pad: .25rem;
  --pip-small: 1.1rem;
  --name-small: .42rem;
  --count-small: .58rem;

  /* How much room the hand takes at the bottom of the board.
   *
   * Added up from the parts rather than written down as one number: the board
   * gives up exactly this much, and if it gives up less the cards sit over
   * live track and you cannot click the routes underneath them. The fan's top
   * padding is the hover lift, because that is the room a lifted card needs. */
  --hand-dock-height: calc(
    var(--hover-lift) + var(--card-height) + var(--hand-total-line) +
    var(--dock-inset)
  );
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
  background: var(--bg);
  color: var(--ink);
  font: 15px/1.5 system-ui, -apple-system, "Segoe UI", sans-serif;
}

main { height: 100%; }

h1 { font-size: 1.6rem; margin: 0 0 .25rem; letter-spacing: -0.01em; }
h2 { font-size: .8rem; margin: 0 0 .5rem; text-transform: uppercase;
     letter-spacing: .08em; color: var(--ink-dim); font-weight: 600; }

.muted { color: var(--ink-dim); }
.hint { min-height: 1.2em; margin: .4rem 0 0; font-size: .85rem; color: var(--ink-dim); }

/* The hand is docked over this same band, so a refusal would otherwise be read
 * through a stack of cards. It sits above them, on its own ground. */
.map-pane > .hint.error {
  position: relative;
  z-index: 6;
  align-self: flex-start;
  max-width: 100%;
  padding: .1rem .5rem;
  border-radius: 6px;
  background: var(--panel);
  border: 1px solid var(--panel-edge);
}

.map-pane > .hint.error:empty { border: none; background: none; }
.error { color: var(--bad); }
.negative { color: var(--bad); }

/* ---------------------------------------------------------------- shell --- */

/* Everything that is not the table: the door, the waiting room, profiles, the
 * lists and the replay theatre. One vocabulary -- a masthead, panels in
 * columns, a row of actions -- shared with the other games on the box, in
 * this game's own colours. A page here is a document that scrolls; the table
 * is a window the board fills, and keeps `main`'s full height. */
main.shell {
  height: auto;
  min-height: 100%;
  max-width: var(--page);
  margin: 0 auto;
  padding: var(--gap);
}

.shell h1 { margin-bottom: var(--gap-small); }
.shell h3 {
  margin: var(--gap) 0 var(--gap-small);
  font-size: var(--small);
  color: var(--ink-dim);
}
.shell h2.section { margin: var(--gap-large) 0 0; }
.shell h2 .swatch { display: inline-block; vertical-align: middle; }

a { color: var(--accent); }

.notice { color: var(--ink-dim); }

.eyebrow {
  margin: 0;
  color: var(--ink-dim);
  font-size: var(--small);
  font-weight: 700;
  letter-spacing: var(--tracking);
  text-transform: uppercase;
}

.lede {
  max-width: var(--prose);
  color: var(--ink-dim);
}

.refusal {
  margin: var(--gap-small) 0;
  padding: var(--gap-small) var(--gap);
  border: var(--hairline) solid var(--bad);
  border-radius: var(--radius-small);
  color: var(--bad);
}

.shell .panel { padding: var(--gap); }

.columns {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(var(--column-wide), 100%), 1fr));
  gap: var(--gap);
  margin: var(--gap) 0;
}
.columns.wide-left {
  grid-template-columns: minmax(0, 2fr) minmax(var(--aside), 1fr);
  align-items: start;
}

.actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--gap);
  margin: var(--gap) 0;
}
.actions .hint { margin: 0; }

.row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--gap-small) var(--gap);
  margin: 0;
  padding: 0;
  list-style: none;
}
.row li {
  display: flex;
  align-items: center;
  gap: var(--gap-small);
}

/* The masthead: the way home, and where else there is to go. */
.masthead,
.masthead nav {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--gap-small) var(--gap);
}
.masthead {
  justify-content: space-between;
  margin-bottom: var(--gap);
  padding-bottom: var(--gap-small);
  border-bottom: var(--hairline) solid var(--panel-edge);
}
.masthead form { margin: 0; }

.brand {
  color: var(--ink);
  font-weight: 800;
  letter-spacing: var(--tracking);
  text-decoration: none;
  text-transform: uppercase;
}
.brand:hover { color: var(--accent); }

/* Fields. A label sits over what it labels. */
.shell label {
  display: block;
  color: var(--ink-dim);
  font-size: var(--small);
}
.shell input,
.shell select {
  padding: var(--gap-small);
  background: var(--bg);
  border: var(--hairline) solid var(--panel-edge);
  border-radius: var(--radius-small);
  color: var(--ink);
  font: inherit;
}
.shell input[type="range"] { padding: 0; accent-color: var(--accent); }

/* The door: two ways in, side by side. */
.door form.panel {
  display: grid;
  gap: var(--gap-small);
  align-content: start;
}
.door form.panel p { margin: 0; }
.door form.panel button { justify-self: start; }
.door select { display: block; width: 100%; margin-top: var(--gap-small); }
/* Only shown when there is a choice to make: one map is not a choice. */
.door .map-choice.hidden { display: none; }

input.code {
  width: 100%;
  font-size: var(--code-typed);
  letter-spacing: var(--code-tracking);
  text-align: center;
  text-transform: uppercase;
}

/* The waiting room. */
.invitation { text-align: center; }
.invitation .code {
  margin: 0;
  color: var(--accent);
  font-size: var(--code-size);
  font-weight: 700;
  letter-spacing: var(--code-tracking);
  /* Tracking trails the last letter; this puts the code back in the middle. */
  text-indent: var(--code-tracking);
}
.invitation .link {
  display: flex;
  gap: var(--gap-small);
  max-width: var(--form);
  margin: 0 auto;
}
.invitation .link input { flex: 1; min-width: 0; }

.members {
  display: grid;
  gap: var(--gap-small);
  margin: 0;
  padding: 0;
  list-style: none;
}
.member {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--gap-small);
}
.member.me .who { font-weight: 700; }
.member.away .who { opacity: var(--dim); }

.tag {
  padding: 0 var(--gap-small);
  border: var(--hairline) solid var(--panel-edge);
  border-radius: var(--radius);
  color: var(--ink-dim);
  font-size: var(--small);
}
.tag.away { border-color: var(--bad); color: var(--bad); }

/* Picking your colour: the five, each named as well as painted (D-0018), yours
 * ringed, the ones somebody else has greyed and named after them. */
.pick-color {
  display: flex;
  flex-wrap: wrap;
  gap: var(--gap-small);
}
.pick {
  display: inline-flex;
  align-items: center;
  gap: var(--gap-small);
  border-width: var(--edge);
  text-transform: capitalize;
}
.pick::before {
  content: "";
  width: var(--swatch);
  height: var(--swatch);
  border-radius: var(--radius-tiny);
  background: var(--paint);
}
.pick:hover:not(:disabled),
.pick.chosen { border-color: var(--paint); }
.pick.chosen { box-shadow: 0 0 0 var(--edge) var(--panel), 0 0 0 calc(2 * var(--edge)) var(--paint); }

/* Profiles, and the lists. */
.profile { display: grid; gap: var(--gap); }
.profile .panel { min-width: 0; }

.inline {
  margin-top: var(--gap);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--gap-small);
}
.inline label { flex-basis: 100%; }
.inline input { flex: 1; min-width: var(--field); max-width: var(--form); }

.stats {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(var(--column-narrow), 1fr));
  gap: var(--gap);
  margin: 0;
}
.stats dt { color: var(--ink-dim); font-size: var(--small); }
.stats dd {
  margin: 0;
  font-size: var(--stat-size);
  font-weight: 700;
  line-height: 1.2;
  font-variant-numeric: tabular-nums;
}

.history,
.directory {
  display: grid;
  gap: var(--gap-small);
  margin: var(--gap-small) 0;
  padding: 0;
  list-style: none;
}
.directory { grid-template-columns: repeat(auto-fill, minmax(var(--column-narrow), 1fr)); }

.entry {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--gap-small) var(--gap);
  padding: var(--gap-small) var(--gap);
  border-left: var(--ring) solid var(--panel-edge);
  background: var(--raised);
  border-radius: var(--radius-tiny);
}
.entry.won { border-left-color: var(--good); }
.entry .result { font-weight: 700; }
.entry .with { color: var(--ink-dim); }
.entry .with a { margin-right: var(--gap-small); }
.entry time {
  margin-left: auto;
  color: var(--ink-dim);
  font-size: var(--small);
}

/* The replay theatre. */
.transport {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--gap-small);
  margin: var(--gap) 0;
}
.transport input[type="range"] { flex: 1; min-width: var(--field); }
.transport .step { font-variant-numeric: tabular-nums; color: var(--ink-dim); }

/* The board fills whatever box it is given (see `.map-view`); at the table
 * that is the window, and here it is this. */
.stage {
  /* The shape of the map being watched (`--map-ratio`, set by the theatre),
   * and no taller than leaves the transport on screen with it. */
  aspect-ratio: var(--map-ratio);
  max-height: var(--stage-height);
  min-width: 0;
}
.beside { display: grid; gap: var(--gap); min-width: 0; }

.moments {
  /* The offset parent of its items, so the theatre can scroll to one. */
  position: relative;
  display: grid;
  gap: var(--hairline);
  max-height: var(--scroller);
  margin: 0;
  padding: 0;
  overflow-y: auto;
  list-style: none;
}
.moment {
  display: flex;
  gap: var(--gap-small);
  width: 100%;
  border-color: transparent;
  background: transparent;
  font-size: var(--small);
  text-align: left;
}
.moment .at {
  flex: none;
  min-width: 3ch;
  color: var(--ink-dim);
  font-variant-numeric: tabular-nums;
  text-align: right;
}
.moment.current { border-color: var(--accent); background: var(--raised); }

/* Hands and piles, laid open. The cards are the hand's own, at the small
 * size: a replay shows every hand at once. */
.replay-cards {
  display: flex;
  flex-wrap: wrap;
  gap: var(--gap-small) var(--gap);
  padding-top: var(--count-offset);
  padding-left: var(--count-offset);
}
/* Sized here rather than by resetting the card tokens: those are the hand's,
 * and the fan is measured against every value they are given. */
.replay-cards .card-face {
  width: var(--card-width-small);
  height: var(--card-height-small);
  padding: var(--chip-pad);
  box-shadow: none;
}
.replay-cards .card-face .pip { font-size: var(--pip-small); }
.replay-cards .card-face .card-name { font-size: var(--name-small); }
.replay-cards .card-face .count { min-width: 0; font-size: var(--count-small); }

.pile {
  display: flex;
  flex-wrap: wrap;
  gap: var(--chip-gap);
  margin: 0;
  padding: 0;
  list-style: none;
}
.card-face.chip {
  width: var(--chip-size);
  height: var(--chip-size);
  padding: 0;
  display: grid;
  place-items: center;
  border-width: var(--hairline);
  border-radius: var(--radius-tiny);
  box-shadow: none;
  font-size: var(--small);
}

.replay-tickets {
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: var(--small);
}
.replay-tickets li {
  display: flex;
  justify-content: space-between;
  gap: var(--gap-small);
  padding: var(--chip-gap) 0;
  border-bottom: var(--hairline) solid var(--panel-edge);
}

/* A media query cannot read a custom property, so this one width is written
 * out. It is the shell's only breakpoint. */
@media (max-width: 800px) {
  .columns.wide-left { grid-template-columns: minmax(0, 1fr); }
  .entry time { margin-left: 0; flex-basis: 100%; }
}

/* -------------------------------------------------------------- buttons --- */

button,
.button {
  display: inline-block;
  font: inherit;
  color: var(--ink);
  background: var(--raised);
  border: var(--hairline) solid var(--panel-edge);
  border-radius: var(--radius-small);
  padding: .5rem .8rem;
  text-decoration: none;
  cursor: pointer;
}

button:hover:not(:disabled),
.button:hover { background: var(--raised-hover); }
button:disabled { opacity: var(--dim); cursor: not-allowed; }

button.primary,
.button.primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
  font-weight: 600;
}

button.primary:hover:not(:disabled),
.button.primary:hover { background: var(--accent); filter: brightness(1.1); }

button.quiet { background: transparent; }
button.quiet:hover:not(:disabled) { background: var(--raised); }

/* One focus ring, everywhere, for whoever is driving with a keyboard. */
button:focus-visible,
.button:focus-visible,
input:focus-visible,
select:focus-visible,
a:focus-visible,
summary:focus-visible {
  outline: var(--ring) solid var(--focus);
  outline-offset: var(--ring-gap);
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .shell * { transition: none; animation: none; }
}

button.wide {
  display: block;
  width: 100%;
  margin-top: .6rem;
}

/* ---------------------------------------------------------------- table --- */

.table {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.status {
  display: flex;
  align-items: baseline;
  gap: 1rem;
  padding: .6rem 1rem;
  border-bottom: 1px solid var(--panel-edge);
  background: var(--panel);
}

.status .brand { font-size: var(--small); }
.status .replay { font-weight: 600; }
.status .replay.not-kept { color: var(--ink-dim); font-weight: 400; }

.status .room {
  font-weight: 700;
  letter-spacing: .25em;
  color: var(--accent);
}

.status .turn { font-weight: 600; }

.status .final-round {
  margin-left: auto;
  color: var(--bad);
  font-weight: 600;
}

.layout {
  display: grid;
  grid-template-columns: 1fr 20rem;
  /* One row, and a definite one. Left to size itself from its contents, the
   * row would take whatever height the board asked for -- and a board asks for
   * the height its map's own proportions imply, which for a tall map is taller
   * than the screen. Pinning the row makes the space definite and lets the
   * board fit itself into what there is. */
  grid-template-rows: minmax(0, 1fr);
  gap: .75rem;
  padding: var(--layout-pad);
  flex: 1;
  min-height: 0;
}

.map-pane {
  position: relative;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.side {
  display: flex;
  flex-direction: column;
  gap: .6rem;
  overflow-y: auto;
  min-height: 0;
}

.panel {
  background: var(--panel);
  border: 1px solid var(--panel-edge);
  border-radius: 10px;
  padding: .7rem .8rem;
}

/* ----------------------------------------------------------------- map ---- */

/* The board and its zoom buttons. The hand lies over the board's foot rather
 * than below it, so the map gets the whole pane (D-0021): the dock takes no
 * clicks itself, only its cards do, and the map can be panned up from under
 * them. */
.map-view {
  position: relative;
  width: 100%;
  /* The route tip near an edge is cut rather than spilling over the side
   * column or the hand. */
  overflow: hidden;
  /* Filled rather than sized from the map's own proportions. A map chooses its
   * own shape, and a tall one asked for a height taller than the screen -- the
   * board ran off the bottom. The SVG letterboxes itself inside whatever box it
   * is given (see `preserveAspectRatio` on the element), so giving it the box
   * and letting it fit works for any shape of map. */
  height: 100%;
}

.board {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 10px;
  border: 1px solid var(--panel-edge);
  /* The board handles its own touches: a finger on it pans the map, and must
   * not scroll the page instead. At the table the page does not scroll anyway
   * -- the table fills the window and the side column scrolls on its own. In
   * the replay theatre it does, and there a finger scrolls the page from
   * anywhere but the board, which is what a map on a page is expected to do.
   * A drag across the city names must not start selecting them. */
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
  cursor: grab;
}
.board.dragging, .board.dragging .route { cursor: grabbing; }

.map-controls {
  position: absolute;
  top: var(--floating-inset);
  right: var(--floating-inset);
  display: flex;
  flex-direction: column;
  gap: .25rem;
}
.map-controls button {
  width: var(--map-controls-size);
  height: var(--map-controls-size);
  padding: 0;
  font-size: 1.1rem;
  line-height: 1;
  background: var(--panel);
  border: 1px solid var(--panel-edge);
  color: var(--ink);
  border-radius: 6px;
  cursor: pointer;
}
.map-controls button:hover { border-color: var(--accent); }

.board-bg { fill: var(--board-ink); }

.city circle {
  fill: #0d1117;
  stroke: var(--ink);
  stroke-width: 2;
}

.city text {
  fill: var(--ink);
  font-size: 11px;
  font-weight: 600;
  paint-order: stroke;
  stroke: var(--board-ink);
  stroke-width: 3px;
  pointer-events: none;
}

/* The two cities of each ticket pinned, pointed at or tabbed to, and the
 * guide between them: a ticket names two places, and this is where they
 * are. Lit softly: several can be lit at once and stay lit through a whole
 * game, so it has to sit under the board rather than shout over it. A
 * ticket already joined by your own track is lit in green instead, so what
 * is done can be told from what is still to build. */
.city.spotlit circle {
  fill: var(--accent);
  fill-opacity: .75;
  stroke: rgb(255 255 255 / 75%);
  stroke-width: 2.5;
  r: 8.5;
  filter: drop-shadow(0 0 5px var(--accent-glow));
}
.city.spotlit text {
  fill: #f2f6ff;
  font-size: 13px;
}
.guide {
  stroke: var(--accent);
  stroke-width: 2;
  stroke-dasharray: var(--guide-dash) var(--guide-gap);
  stroke-linecap: round;
  opacity: .5;
  pointer-events: none;
  animation: march 1.2s linear infinite;
}
/* One dash and one gap per loop, so the march is seamless. */
.city.spotlit.done circle {
  fill: var(--green);
  filter: drop-shadow(0 0 5px var(--green-glow));
}
.guide.done { stroke: var(--green); }
.tickets li.ticket.done { color: var(--green); }
.tickets li.ticket.done b { color: var(--green); }
.tickets li.ticket.done span::after { content: " ✓"; }
@keyframes march {
  to { stroke-dashoffset: calc(-1 * (var(--guide-dash) + var(--guide-gap))); }
}
@media (prefers-reduced-motion: reduce) {
  .guide { animation: none; }
}

/* A held ticket lights up the same way when pointed at or tabbed to. */
.tickets li.ticket:hover,
.tickets li.ticket:focus-visible,
.ticket-breakdown li.ticket:hover,
.ticket-breakdown li.ticket:focus-visible { background: var(--accent-wash); }

/* The tip that follows the pointer over a route: what it is, what it costs,
 * whose it is. Offset from the pointer so the pointer does not cover it, and
 * taking no clicks so the route under it still does. */
.route-tip {
  position: absolute;
  /* Above the hand, below the floating panels: a tip never sits on a panel. */
  z-index: 7;
  transform: translate(var(--tip-offset), var(--tip-offset));
  padding: .3rem .6rem;
  background: var(--panel);
  border: 1px solid var(--panel-edge);
  border-radius: 6px;
  font-size: .8rem;
  white-space: nowrap;
  pointer-events: none;
  box-shadow: 0 6px 18px rgb(0 0 0 / 45%);
}

/* The tick that keeps a ticket lit, beside it in both lists. */
.pin {
  display: inline-flex;
  align-items: center;
  flex: none;
  cursor: pointer;
}
.pin input {
  width: 1rem;
  height: 1rem;
  margin: 0;
  accent-color: var(--accent);
  cursor: pointer;
}
.tickets li.ticket { gap: .5rem; }
.tickets li.ticket span,
.ticket-breakdown li.ticket span { flex: 1; }
/* Everybody's tickets at the end are rows like your own were. */
.ticket-breakdown li.ticket {
  display: flex;
  align-items: center;
  gap: .5rem;
  padding: .15rem .2rem;
  border-radius: 4px;
}
.ticket-options li {
  display: flex;
  align-items: center;
  gap: .5rem;
}
.ticket-options li button.ticket { flex: 1; }

/* A route is a row of slots. Each slot has a bed in the route's own colour,
 * a carriage on it once somebody has laid one, and the colour's shape so it
 * can be read without seeing the colour.
 *
 * The slots are the click target. An earlier version drew a fat transparent
 * line along each route so the gaps between slots were clickable too. It made
 * routes easier to hit and much harder to hit *correctly*: a long diagonal's
 * 16-unit band lies across every route it crosses, so clicking one route
 * could claim its neighbour. Aiming at a slot is unambiguous.
 *
 * Empty and laid have to look like different things, not the same thing in a
 * different colour: an empty slot is drawn hollow -- outlined in the route
 * colour with a faint fill -- and a laid one is a solid carriage in the
 * owner's colour sitting on a rim of the route colour. Yellow's carriage on
 * an orange route reads as both facts.
 *
 * The route's colour is one custom property, set from the class on the route,
 * that the bed and the shape both read. */
.route.red { --tone: var(--red); }
.route.orange { --tone: var(--orange); }
.route.yellow { --tone: var(--yellow); }
.route.green { --tone: var(--green); }
.route.blue { --tone: var(--blue); }
.route.pink { --tone: var(--pink); }
.route.white { --tone: var(--white); }
/* Black's shape would vanish into the board; it takes the page's ink. */
.route.black { --tone: var(--black); --shape-tone: var(--ink); }
.route.gray { --tone: var(--gray); }

.bed {
  fill: var(--tone);
  fill-opacity: .16;
  stroke: var(--tone);
  stroke-width: 1.4;
  stroke-dasharray: 2.5 1.5;
}

/* Once laid, the bed is a solid rim under the carriage. */
.route.claimed .bed {
  fill-opacity: 1;
  stroke: var(--board-ink);
  stroke-width: 1;
  stroke-dasharray: none;
}
/* A laid carriage is a train car: the owner's colour on the body, dark
 * wheels, light windows. */
.carriage .body {
  stroke: var(--board-ink);
  stroke-width: .8;
}
.carriage .wheel {
  fill: var(--board-ink);
  stroke: rgb(255 255 255 / 70%);
  stroke-width: .5;
}
.carriage .window { fill: rgb(255 255 255 / 60%); }

/* The shape: in the route's colour while the slot is empty; once a carriage
 * is on it, dark with a light halo, so it shows on every seat colour. */
.shape {
  font-size: var(--shape-size);
  font-weight: 700;
  fill: var(--shape-tone, var(--tone));
  pointer-events: none;
  user-select: none;
}
.route.claimed .shape {
  fill: var(--board-ink);
  font-size: calc(var(--shape-size) - .5px);
  paint-order: stroke;
  stroke: rgb(255 255 255 / 70%);
  stroke-width: 1.5px;
}

.route.claimable { cursor: pointer; }

/* A route under the pointer, and the one being paid for while the chooser is
 * open, are picked out the same way. */
.route.claimable:hover .bed,
.route.paying .bed {
  fill-opacity: .5;
  stroke: var(--accent);
  stroke-width: 2.2;
  stroke-dasharray: none;
}

/* The move that just happened: its track is laid carriage by carriage along
 * the route, each a beat after the one before (`--lay-delay`, set per
 * carriage), so where somebody is building can be seen happening rather than
 * found afterwards; then it pulses, so a player looking elsewhere can find
 * it. Only the last move is laid this way -- a board joined in progress
 * shows its track already down. */
.carriage {
  transform-box: fill-box;
  transform-origin: center;
}
.route.last .carriage {
  animation: lay var(--lay-time) var(--lay-ease) var(--lay-delay, 0ms) backwards;
}
.route.last .carriage .body {
  stroke: #fff;
  stroke-width: 1.6;
  animation: just-laid 1.4s ease-out calc(var(--lay-delay, 0ms) + var(--lay-time)) 3;
}
@keyframes lay {
  from { opacity: 0; transform: scale(1.8); }
}
@keyframes just-laid {
  0% { stroke-width: 4; stroke-opacity: 1; }
  100% { stroke-width: 1.6; stroke-opacity: .6; }
}

/* ------------------------------------------------------------- flights -- */

/* A card crossing the screen from where it was to where it went: a deck draw
 * to a hand or to another player's row, a face-up card to whoever took it,
 * the deck refilling the display, a card chosen for a payment. The layer
 * covers the window and takes no clicks; each flight is placed at its start
 * and carried to its end by one transition on its transform. */
.flights {
  position: fixed;
  inset: 0;
  /* Above the floating panels and the route tip: a card in flight crosses
   * everything. */
  z-index: 9;
  pointer-events: none;
  overflow: hidden;
}
.flight {
  position: absolute;
  width: var(--flight-width);
  /* Positioned by its centre, so the two ends are the centres of the places. */
  margin-left: calc(var(--flight-width) / -2);
  margin-top: calc(var(--flight-height) / -2);
  transition: transform var(--flight-time) cubic-bezier(.3, .1, .3, 1);
  filter: drop-shadow(0 8px 14px rgb(0 0 0 / 55%));
  will-change: transform;
}
.flight .card-face {
  width: var(--flight-width);
  height: var(--flight-height);
}
.flight .card-face .pip { font-size: 1.1rem; }
.flight .card-face .card-name { display: none; }
/* A destination ticket nobody here is allowed to see: wider than it is
 * tall, as they are. In flight, and in a row beside whoever is choosing. */
.ticket-back {
  --ticket-aspect: .62;
  display: block;
  border: 1px solid var(--card-edge);
  background: repeating-linear-gradient(135deg, #6b4a1f 0 3px, #8a6230 3px 6px);
}
.flight .card-face.ticket-back {
  height: calc(var(--flight-width) * var(--ticket-aspect));
  margin-top: calc((var(--flight-height) - var(--flight-width) * var(--ticket-aspect)) / 2);
  /* A ticket's own edge, not the heavier one a card face has. */
  border: 1px solid var(--card-edge);
  border-radius: 6px;
}
/* A card nobody here is allowed to see. */
.card-face.back {
  display: block;
  background:
    repeating-linear-gradient(45deg, #24304a 0 6px, #1b2538 6px 12px);
  border: 1px solid var(--card-edge);
  border-radius: 8px;
}

@media (prefers-reduced-motion: reduce) {
  .route.last .carriage, .route.last .carriage .body { animation: none; }
  /* Not a card sitting still at its destination for a moment: nothing. */
  .flights { display: none; }
}

/* ----------------------------------------------------------------- cards -- */

/* One card stands for every card of that colour you hold; the count rides in
 * the corner. A hand therefore never grows past nine cards on screen however
 * many are actually in it. */
.card-face {
  position: relative;
  width: var(--card-width);
  height: var(--card-height);
  flex: none;
  border-radius: var(--card-radius);
  border: 2px solid var(--card-edge);
  box-shadow: 0 6px 16px rgb(0 0 0 / 45%);
  display: grid;
  grid-template-rows: 1fr auto;
  place-items: center;
  padding: .4rem;
  color: var(--card-ink);
  user-select: none;
}

.card-face .pip {
  font-size: 2.4rem;
  line-height: 1;
  opacity: .78;
  text-shadow: 0 1px 0 rgb(255 255 255 / 35%);
}

.card-face .card-name {
  font-size: .6rem;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  opacity: .85;
  white-space: nowrap;
  line-height: 1.1;
  /* Cards in the fan overlap rightward, so anything centred on the card gets
   * clipped by its neighbour. The name sits on the leading edge instead,
   * under the count, where it stays readable however tight the fan is. */
  justify-self: start;
}

/* The count. Absent entirely at one, because a single card does not need to be
 * told it is one card.
 *
 * Top *left*, not right: cards in the fan overlap rightwards and each sits
 * above the one before it, so a badge on the right edge is covered by the next
 * card. On the left edge it is always the thing painted on top. */
.card-face .count {
  position: absolute;
  top: calc(var(--count-offset) * -1);
  left: calc(var(--count-offset) * -1);
  min-width: 1.5rem;
  padding: .05rem .3rem;
  border-radius: 999px;
  background: var(--bg);
  color: var(--ink);
  border: 2px solid var(--card-edge);
  font-size: .72rem;
  font-weight: 700;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

.card-face.red { background: linear-gradient(160deg, var(--red-lit), var(--red)); }
.card-face.orange { background: linear-gradient(160deg, var(--orange-lit), var(--orange)); }
.card-face.yellow { background: linear-gradient(160deg, var(--yellow-lit), var(--yellow)); }
.card-face.green { background: linear-gradient(160deg, var(--green-lit), var(--green)); }
.card-face.blue { background: linear-gradient(160deg, var(--blue-lit), var(--blue)); color: var(--card-ink-light); }
.card-face.pink { background: linear-gradient(160deg, var(--pink-lit), var(--pink)); }
.card-face.white { background: linear-gradient(160deg, var(--white-lit), var(--white-deep)); }
.card-face.black { background: linear-gradient(160deg, var(--black-lit), var(--black)); color: var(--card-ink-light); }
.card-face.locomotive {
  background: var(--loco);
  color: var(--card-ink);
}

.card-face.blue .card-name,
.card-face.black .card-name { opacity: .95; }

/* ------------------------------------------------------------------- fan -- */

/* The hand sits in front of you, over the bottom of the board, rather than in
 * a list off to one side. */
.hand-dock {
  position: absolute;
  left: 0;
  right: 0;
  bottom: var(--dock-inset);
  display: flex;
  flex-direction: column;
  align-items: center;
  pointer-events: none;
  z-index: 5;
}

.fan {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  /* Room above for a card to lift into. */
  padding-top: var(--hover-lift);
  pointer-events: auto;
}

.hand-total {
  margin: 0;
  height: var(--hand-total-line);
  font-size: .72rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ink-dim);
  text-shadow: 0 1px 3px #000;
}

/* Each card carries its seat in the fan as custom properties, set inline: the
 * arc and the overlap are computed in Rust, and everything that turns them
 * into a layout is here. Nothing set inline is a real property, so nothing
 * inline can outrank this file -- which is what lets the hover rule below win
 * without an !important.
 *
 * The overshoot in the easing is what makes a card settle rather than arrive. */
.fan .card-face {
  transform: var(--fan);
  transform-origin: 50% 120%;
  /* Cards overlap by a fraction of their own width, which is why that width is
   * a token here rather than a number Rust also has to know. */
  margin-left: calc(var(--card-width) * var(--overlap) * -1);
  z-index: var(--depth);
  transition:
    transform 260ms cubic-bezier(.2, 1.5, .4, 1),
    box-shadow 180ms ease,
    margin 220ms ease;
  animation: deal 320ms cubic-bezier(.2, 1.5, .4, 1) backwards;
}

/* The leading card has nothing to overlap. */
.fan .card-face:first-child { margin-left: 0; }

/* A card lifts out of the fan and straightens when you point at it... */
.fan .card-face:hover {
  transform: translateY(calc(var(--hover-lift) * -1)) rotate(0deg) scale(1.06);
  box-shadow: 0 16px 30px rgb(0 0 0 / 55%);
  z-index: 20;
}

/* ...and the ones after it shuffle along to make room. */
.fan .card-face:hover ~ .card-face {
  transform: var(--fan) translateX(var(--hover-spread));
}

@keyframes deal {
  from {
    opacity: 0;
    transform: translateY(48px) rotate(0deg) scale(.86);
  }
}

@media (prefers-reduced-motion: reduce) {
  .fan .card-face {
    transition: none;
    animation: none;
  }
  .fan .card-face:hover,
  .fan .card-face:hover ~ .card-face { transform: var(--fan); }
}

/* --------------------------------------------------------------- payment -- */

/* Paying for a route. Floats over the board beside the hand rather than
 * covering it: the route being paid for is on the board, and the whole point
 * is to look at it while you choose. */
.payment {
  position: absolute;
  left: 50%;
  bottom: calc(var(--hand-dock-height) + .6rem);
  transform: translateX(-50%);
  width: min(40rem, calc(100% - 2 * var(--layout-pad)));
  padding: .9rem 1.1rem 1rem;
  background: var(--panel);
  border: 1px solid var(--panel-edge);
  border-radius: 14px;
  box-shadow: 0 18px 40px rgb(0 0 0 / 55%);
  z-index: 8;
}

.payment header h2 { margin: 0 0 .15rem; font-size: 1.05rem; }
.payment header p { margin: 0 0 .6rem; font-size: .85rem; }

.payment .label {
  margin: .5rem 0 .3rem;
  font-size: .72rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ink-dim);
}

.payment .row {
  display: flex;
  flex-wrap: wrap;
  gap: .4rem;
  min-height: calc(var(--card-height-small) + .4rem);
  align-items: center;
}

/* The cards in the chooser are the small ones, and are buttons. */
.payment .row button {
  padding: 0;
  border: none;
  background: none;
  border-radius: var(--card-radius);
  cursor: pointer;
  transition: transform 120ms ease;
}
.payment .row button:hover { transform: translateY(-3px); }
.payment .row .card-face {
  width: var(--card-width-small);
  height: var(--card-height-small);
  border-width: 1.5px;
  box-shadow: 0 3px 8px rgb(0 0 0 / 40%);
}
.payment .row .card-face .pip { font-size: 1.1rem; }
.payment .row .card-face .card-name { display: none; }
.payment .row .card-face .count { min-width: 1.2rem; font-size: .62rem; }

/* The payment row is where the chosen cards go: an outlined tray. */
.payment .row.chosen {
  padding: .35rem .5rem;
  border: 1px dashed var(--panel-edge);
  border-radius: 10px;
}
.payment .row .empty { font-size: .85rem; }

.payment footer {
  display: flex;
  justify-content: flex-end;
  gap: .5rem;
  margin-top: .8rem;
}

.payment .hint.error { margin: .5rem 0 0; }

.payment button.ghost {
  background: none;
  border: 1px solid var(--panel-edge);
  color: var(--ink);
  border-radius: 8px;
  padding: .5rem .9rem;
  font: inherit;
  cursor: pointer;
}

/* ---------------------------------------------------------------- market --- */

.market-row {
  display: flex;
  gap: .35rem;
  margin-bottom: .55rem;
}

/* The face-up cards are the same cards, smaller, and clickable. */
.market-slot {
  padding: 0;
  border: none;
  background: none;
  border-radius: var(--card-radius);
  transition: transform 140ms ease;
}

.market-slot .card-face {
  width: var(--card-width-small);
  height: var(--card-height-small);
  border-width: 1.5px;
  box-shadow: 0 3px 8px rgb(0 0 0 / 40%);
}

.market-slot .card-face .pip { font-size: 1.4rem; }
.market-slot .card-face .card-name { display: none; }

.market-slot:hover:not(:disabled) { transform: translateY(-4px); }
.market-slot:disabled { opacity: .5; cursor: not-allowed; }

/* Sized from the same tokens as a real card: a placeholder that does not match
 * makes the row jump as slots empty and refill. */
.market-slot.empty {
  display: inline-block;
  width: var(--card-width-small);
  height: var(--card-height-small);
  border-radius: var(--card-radius);
  border: 1px dashed var(--panel-edge);
}

/* --------------------------------------------------------------- panels --- */

.players ul, .tickets ul, .log ol {
  list-style: none;
  margin: 0;
  padding: 0;
}

.players li {
  display: flex;
  align-items: center;
  gap: .5rem;
  padding: .28rem 0;
}

.players li.turn {
  background: var(--accent-wash);
  border-radius: 6px;
  padding-left: .3rem;
  margin-left: -.3rem;
}

.players .who {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 600;
}
/* Somebody looking at destination tickets: it takes a while, and the table
 * should see what it is waiting for. A line of its own under the row, with a
 * face-down ticket for each being looked at, lifted one after another the way
 * a hand of them is thumbed through. */
.players li.choosing { flex-wrap: wrap; }
.choosing-tickets {
  flex-basis: 100%;
  display: flex;
  align-items: center;
  gap: .45rem;
  color: var(--accent);
  font-size: .78rem;
}
.choosing-tickets .looking { display: inline-flex; gap: .2rem; }
.choosing-tickets .ticket-back {
  width: 1.1rem;
  height: calc(1.1rem * var(--ticket-aspect));
  border-radius: 2px;
}
.choosing-tickets .ticket-back { animation: thumb 1.2s ease-in-out infinite; }
.choosing-tickets .ticket-back:nth-child(2) { animation-delay: .2s; }
.choosing-tickets .ticket-back:nth-child(3) { animation-delay: .4s; }
.choosing-tickets .ticket-back:nth-child(n + 4) { animation-delay: .6s; }
@keyframes thumb {
  0%, 60%, 100% { transform: none; }
  30% { transform: translateY(-.25rem) rotate(-6deg); }
}
@media (prefers-reduced-motion: reduce) {
  .choosing-tickets .ticket-back { animation: none; }
}
.players .stat { font-variant-numeric: tabular-nums; font-weight: 600; }
.players .stat.trains { color: var(--ink-dim); min-width: 2ch; text-align: right; }

.player-red { --paint: var(--player-red); }
.player-blue { --paint: var(--player-blue); }
.player-green { --paint: var(--player-green); }
.player-yellow { --paint: var(--player-yellow); }
.player-purple { --paint: var(--player-purple); }

.swatch {
  width: .9rem;
  height: .9rem;
  border-radius: 3px;
  flex: none;
  background: var(--paint);
  border: 1px solid rgb(255 255 255 / 30%);
}
/* A player's name is written in their colour wherever it appears, so the
 * colour and the name are learned together. */
.who { color: var(--paint); }
.carriage { fill: var(--paint); }
.log li .swatch {
  display: inline-block;
  width: .6rem;
  height: .6rem;
  margin-right: .35rem;
  vertical-align: -1px;
}
.log li .who { font-weight: 600; }

.tickets li {
  display: flex;
  justify-content: space-between;
  gap: .5rem;
  padding: .25rem 0;
  border-bottom: 1px solid var(--panel-edge);
  font-size: .88rem;
}

.log ol { font-size: .82rem; }
.log li { padding: .16rem 0; color: var(--ink-dim); }
.log li.mine { color: var(--ink); }

/* The final scores: wide enough for their table. */
.floating.scores { --floating-width: 30rem; }

/* ------------------------------------------------------------- floating -- */

/* A panel over the board that can be dragged by its header. It is placed by
 * its own class and moved from there by an inline transform, and it is kept
 * inside the board's box, so it can be got out of the way but never lost. */
.floating {
  position: absolute;
  z-index: 8;
  /* The top corner beside the zoom buttons, as wide as its kind of panel
   * asks (`--floating-width`) and never wider than the board leaves. */
  top: var(--floating-inset);
  right: var(--map-controls-width);
  /* Every kind of panel sets `--floating-width`; the fallback is the
   * chooser's, so a kind that forgets is narrow rather than full-width. */
  width: min(var(--floating-width, 22rem), calc(100% - var(--map-controls-width) - var(--floating-inset)));
  display: flex;
  flex-direction: column;
  background: var(--panel);
  border: 1px solid var(--panel-edge);
  border-radius: 14px;
  max-height: calc(100% - var(--hand-dock-height) - 2 * var(--floating-inset));
  box-shadow: 0 12px 32px rgb(0 0 0 / 45%);
}
.floating > .grip {
  padding: .7rem 1.2rem;
  border-bottom: 1px solid var(--panel-edge);
  cursor: grab;
  user-select: none;
  /* A finger on the handle drags the panel, not the page. */
  touch-action: none;
}
.floating.held > .grip { cursor: grabbing; }
.floating > .grip { display: flex; align-items: center; gap: .8rem; }
/* Folds the panel down to its header, and back. */
.floating > .grip .fold {
  flex: none;
  padding: .1rem .55rem;
  font-size: .85rem;
  line-height: 1.4;
}
/* Folded, a panel is its header and no wider than that needs: what it was
 * covering is what is wanted. The body is hidden rather than removed, so it
 * comes back as it was left. */
.floating.folded { width: auto; }
.floating.folded > .grip { border-bottom: none; }
.floating.folded > .body { display: none; }
.floating > .grip h2 { flex: 1; margin: 0; font-size: 1rem; }
.floating > .body {
  padding: .8rem 1.2rem 1.2rem;
  overflow-y: auto;
}

.ticket-options { list-style: none; margin: 1rem 0; padding: 0; }
.ticket-options li { margin-bottom: .4rem; }

button.ticket {
  display: flex;
  justify-content: space-between;
  width: 100%;
  gap: 1rem;
  text-align: left;
}

button.ticket.chosen {
  border-color: var(--accent);
  background: rgb(88 166 255 / 16%);
}

/* The ticket chooser: the top corner beside the zoom buttons, narrow enough
 * to leave most of the map showing. */
.floating.chooser { --floating-width: 22rem; }


.score-sheet table { width: 100%; border-collapse: collapse; margin: .75rem 0; }
.score-sheet th, .score-sheet td { padding: .4rem .3rem; text-align: right; }
.score-sheet th:first-child, .score-sheet td:first-child { text-align: left; }
.score-sheet th { color: var(--ink-dim); font-size: .78rem; text-transform: uppercase; }
.score-sheet tbody tr { border-top: 1px solid var(--panel-edge); }
.score-sheet .winner { font-size: 1.1rem; }
.score-sheet td .swatch { display: inline-block; margin-right: .4rem; vertical-align: middle; }

.ticket-breakdown { list-style: none; padding: 0; font-size: .85rem; }
.ticket-breakdown ul { list-style: none; padding-left: .8rem; margin: .2rem 0 .6rem; }
.ticket-breakdown .done { color: var(--good); }
.ticket-breakdown .missed { color: var(--bad); }

/* ------------------------------------------------------------- narrower --- */

@media (max-width: 900px) {
  .layout {
    grid-template-columns: 1fr;
    grid-template-rows: auto 1fr;
  }
  .side { flex-direction: row; flex-wrap: wrap; overflow-x: auto; }
  .side .panel { flex: 1 1 12rem; }
}

/* On a phone the widest possible hand -- nine colours -- runs off the side of
 * the screen at full size. Shrinking the two card tokens narrows the fan and
 * shortens the dock together, because everything else is derived from them. */
@media (max-width: 700px) {
  :root {
    --card-width: var(--card-width-small);
    --card-height: var(--card-height-small);
    --hover-lift: 18px;
    --count-offset: 6px;
  }
  .card-face { padding: .25rem; }
  .card-face .pip { font-size: 1.1rem; }
  .card-face .card-name { font-size: .42rem; letter-spacing: .02em; }
  .card-face .count { min-width: 1.1rem; font-size: .58rem; padding: .02rem .22rem; }
}
