/*
 * FlatUI: flat, minimal game UI over any canvas. Load themes.css first, then this file.
 *
 * The look follows AArcade Core's menus (2026-10): windows edged in the theme's colour under an accent title bar, tabs
 * with a full underline, settings as a book (sections down a rail, rows of title, hint and control), bands of headline
 * numbers and filters over full-width table rows, progress bars that carry their value. Made responsive: everything
 * here also works on a phone, by touch, by keyboard and by gamepad.
 *
 * Everything the kit draws sits inside an element with the class "fui" (the kit's own dialogs, toasts and corner
 * buttons carry it; put it on your own containers of kit markup). Selectors are written ".fui .fui-…" so they win over
 * a game's global rules such as button { … } or input[type=range] { … }.
 *
 * Sizes are in em, from --fui-size (15px) × --fui-scale (the settings menu's interface size). Colours are the theme's
 * --game-* tokens (themes.css). Nothing here touches the canvas or the page outside .fui.
 *
 * Light on the GPU, because it sits over a game that redraws every frame: no backdrop-filter, filter or blur (over a
 * canvas they are recomputed every frame the game draws); modals only darken what is behind them; small shadows;
 * animations on opacity and transform only; no :has() (state comes from attributes the scripts set). Keep it so in
 * a fork; tests/kit.test.js and the browser check fail on a blur or a filter.
 */

/* Exo 2 (SIL OFL) is the display face: the title screen's game name. Everything else uses the system's UI font. */
@font-face {
  font-family: 'Exo 2';
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url('fonts/exo2-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329,
    U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Exo 2';
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url('fonts/exo2-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329,
    U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ---- Kit tokens: shape, type, motion. A fork changes these; colours are in themes.css. ---- */
:root {
  /* the system's UI font, Segoe UI first (as AArcade Core): nothing to download, crisp at small sizes */
  --fui-font: 'Segoe UI', system-ui, -apple-system, 'Helvetica Neue', 'Noto Sans', Roboto, Arial, sans-serif;
  --fui-display-font: 'Exo 2', var(--fui-font);
  --fui-size: 15px;
  --fui-scale: 1;
  --fui-radius: 14px; /* windows and panels */
  --fui-radius-sm: 8px; /* controls */
  --fui-gutter: 1.4em; /* a window's side margin: bands and full-width rows carry it themselves */
  --fui-fast: 120ms;
  --fui-slow: 220ms;
  --fui-ease: cubic-bezier(.2, .7, .2, 1);
  --fui-shadow: 0 2px 6px rgb(0 0 0 / .2); /* small radius: cheap to paint; 'none' is fine too */
  --fui-z: 20; /* the corner buttons over the game; dialogs and toasts use the browser's top layer instead */
  --fui-ring: 0 0 0 2px var(--game-panel), 0 0 0 4px var(--game-accent);
}

/* ---- The scope ---- */
.fui {
  font-family: var(--fui-font);
  font-size: calc(var(--fui-size) * var(--fui-scale));
  line-height: 1.4;
  color: var(--game-text);
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
  -webkit-user-select: none;
  user-select: none;
}
/* Colours the kit mixes from the theme's tokens. Declared on every themed scope, so a wrapper with its own
   data-game-theme mixes its own. */
.fui,
.fui [data-game-theme] {
  --fui-track: color-mix(in srgb, var(--game-text) 9%, var(--game-soft)); /* progress and switch tracks */
  --fui-tint: color-mix(in srgb, var(--game-accent) 15%, var(--game-panel)); /* the selected item's fill */
  /* the accent as text on a tint (the chosen segment, the current section): a quarter of the text colour keeps it
     at 4.5:1 in every theme, the focused section's deeper fill included (the plain accent falls to 3.4:1 there) */
  --fui-accent-ink: color-mix(in srgb, var(--game-accent) 75%, var(--game-text));
  /* the second accent (themes.css), the accent where a theme has none; and its ink on its own tint, as above */
  --fui-accent-2: var(--game-accent-2, var(--game-accent));
  --fui-accent-2-ink: color-mix(in srgb, var(--fui-accent-2) 75%, var(--game-text));
  --fui-edge: color-mix(in srgb, var(--game-titlebar) 70%, #000); /* a window's outer ring */
  --fui-strong-line: color-mix(in srgb, var(--game-muted) 55%, var(--game-line)); /* tags, a hovered control */
  --fui-row-pad: .7em; /* full-width rows' side padding: a screen sets it to --fui-gutter */
}
.fui *,
.fui *::before,
.fui *::after {
  box-sizing: border-box;
}
.fui :focus {
  outline: none;
}
/* no double-tap zoom on controls, so a tap acts at once on phones */
.fui :is(button, input, label, a, select, textarea) {
  touch-action: manipulation;
}
/* The kit's display rules must never beat the hidden attribute (an unsupported fullscreen button, an empty footer). */
.fui[hidden],
.fui [hidden] {
  display: none !important;
}
.fui :is(h1, h2, h3, h4, p) {
  margin: 0;
}

/* Icons: Lucide line icons (icons.js), stroked in the current colour. */
.fui .fui-icon {
  width: 1.25em;
  height: 1.25em;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
  vertical-align: middle;
}

/* ---- Windows and panels ----
   A panel is a flat card. A window (a dialog, or a panel with a title) wears the theme's title bar on top and an edge
   of the same colour all round: over the game, a grey hairline can vanish into whatever is behind it; the theme's own
   colour always separates. */
.fui .fui-panel,
.fui.fui-dialog {
  background: var(--game-panel);
  color: var(--game-text);
  border: 1px solid var(--game-line);
  border-radius: var(--fui-radius);
  box-shadow: var(--fui-shadow);
}
.fui .fui-panel {
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.fui .fui-panel.fui-window,
.fui.fui-dialog:not(.fui-screen):not(.fui-popup) {
  border: 2px solid var(--game-titlebar);
  box-shadow: 0 0 0 1px var(--fui-edge), var(--fui-shadow);
}
/* The title bar: an icon, the title, square buttons (Back or Close) washed white over the bar. */
.fui .fui-panel-head {
  display: flex;
  align-items: center;
  gap: .75em;
  min-height: 3.4em;
  padding: .45em .55em .45em var(--fui-gutter);
  background: var(--game-titlebar);
  color: var(--game-on-titlebar);
}
.fui .fui-panel-head > .fui-head-icon {
  width: 1.35em;
  height: 1.35em;
}
.fui .fui-panel-title {
  flex: 1;
  min-width: 0;
  font-size: 1.13em;
  font-weight: 600;
  letter-spacing: -.005em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.fui .fui-panel-head .fui-button {
  width: 2.5em;
  min-height: 2.5em;
  padding: 0;
  border-color: transparent;
  background: rgb(255 255 255 / .16);
  color: inherit;
}
.fui .fui-panel-head .fui-button:active {
  background: rgb(0 0 0 / .22);
}
/* the big windows (settings, achievements, leaderboards) get the big bar */
.fui.fui-dialog:is(.fui-wide, .fui-large) > .fui-panel-head {
  min-height: 4.1em;
  gap: .9em;
}
.fui.fui-dialog:is(.fui-wide, .fui-large) .fui-panel-title {
  font-size: 1.33em;
}
.fui.fui-dialog:is(.fui-wide, .fui-large) .fui-head-icon {
  width: 1.6em;
  height: 1.6em;
}
.fui.fui-dialog:is(.fui-wide, .fui-large) > .fui-panel-head .fui-button {
  width: 2.8em;
  min-height: 2.8em;
}
.fui .fui-panel-body {
  padding: 1.2em var(--fui-gutter);
  min-height: 0;
}
/* The footer is a band: the window's actions at the right, a secondary one (Reset, Play as a guest) at the left. */
.fui .fui-panel-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: .6em;
  padding: .8em var(--fui-gutter);
  background: var(--game-band);
  border-top: 1px solid var(--game-line);
}
.fui .fui-panel-foot > .fui-start {
  margin-right: auto;
}
.fui .fui-text {
  color: var(--game-muted);
  line-height: 1.55;
}
.fui .fui-text + .fui-text {
  margin-top: .6em;
}
/* The overline: a small label in capitals, over a number, a column or a section. */
.fui .fui-eyebrow {
  font-size: .73em;
  font-weight: 600;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--game-muted);
}

/* ---- Buttons: filled with a hairline; .fui-primary is the one accent call to action ----
   Danger is told apart by form as well as colour: a tinted fill in the danger colour, solid only where it is the
   answer to a question (a dangerous confirm). With Red Baron, primary and danger share a red; their forms differ. */
.fui .fui-button {
  -webkit-appearance: none;
  appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5em;
  min-width: 0;
  min-height: 2.5em;
  margin: 0;
  padding: 0 1.1em;
  border: 1px solid var(--game-line);
  border-radius: var(--fui-radius-sm);
  background: var(--game-soft);
  color: var(--game-text);
  font: inherit;
  font-weight: 600;
  line-height: 1.1;
  text-align: center;
  text-decoration: none;
  text-transform: none;
  white-space: nowrap;
  box-shadow: none;
  cursor: pointer;
  transition: background-color var(--fui-fast), border-color var(--fui-fast), color var(--fui-fast),
    box-shadow var(--fui-fast), transform var(--fui-fast);
}
.fui .fui-button:not(:disabled):active {
  transform: translateY(1px);
}
.fui .fui-button.fui-primary {
  background: var(--game-accent-fill);
  border-color: var(--game-accent-fill);
  color: var(--game-on-accent);
}
.fui .fui-button.fui-danger {
  background: color-mix(in srgb, var(--game-bad) 12%, var(--game-panel));
  border-color: color-mix(in srgb, var(--game-bad) 45%, var(--game-line));
  color: var(--game-bad);
}
.fui .fui-button.fui-danger.fui-primary {
  background: var(--game-bad);
  border-color: var(--game-bad);
  color: var(--game-panel);
}
.fui .fui-button.fui-quiet {
  background: transparent;
  border-color: transparent;
}
.fui .fui-button.fui-block {
  display: flex;
  width: 100%;
}
.fui .fui-button.fui-large {
  min-height: 3em;
  padding: 0 1.5em;
  font-size: 1.05em;
}
.fui .fui-button.fui-small {
  min-height: 2.15em;
  padding: 0 .8em;
  font-size: .87em;
}
.fui .fui-button.fui-icon-only {
  width: 2.5em;
  padding: 0;
}
.fui .fui-button.fui-icon-only.fui-small {
  width: 2.15em;
}
.fui .fui-button:disabled,
.fui .fui-button[aria-disabled='true'] {
  opacity: .45;
  cursor: default;
}
.fui .fui-button-row {
  display: flex;
  flex-wrap: wrap;
  gap: .6em;
}

/* ---- Menus: a stack of big buttons for title, pause and hamburger menus ---- */
.fui .fui-menu {
  display: flex;
  flex-direction: column;
  gap: .4em;
}
.fui .fui-menu-item {
  -webkit-appearance: none;
  appearance: none;
  position: relative;
  display: flex;
  align-items: center;
  gap: .85em;
  width: 100%;
  min-height: 3em;
  margin: 0;
  padding: .4em 1em;
  border: 1px solid var(--game-line);
  border-radius: var(--fui-radius-sm);
  background: var(--game-soft);
  color: var(--game-text);
  font: inherit;
  font-size: 1.03em;
  font-weight: 600;
  text-align: left;
  text-decoration: none;
  text-transform: none;
  box-shadow: none;
  cursor: pointer;
  transition: background-color var(--fui-fast), border-color var(--fui-fast), color var(--fui-fast), box-shadow var(--fui-fast);
}
.fui .fui-menu-item .fui-icon {
  color: var(--game-muted);
  transition: color var(--fui-fast);
}
.fui .fui-menu-item .fui-menu-label {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-width: 0;
}
.fui .fui-menu-item small {
  font-size: .8em;
  font-weight: 400;
  color: var(--game-muted);
}
.fui .fui-menu-item.fui-primary {
  background: var(--game-accent-fill);
  border-color: var(--game-accent-fill);
  color: var(--game-on-accent);
}
.fui .fui-menu-item.fui-primary :is(.fui-icon, small) {
  color: inherit;
}
.fui .fui-menu-item.fui-danger {
  background: color-mix(in srgb, var(--game-bad) 12%, var(--game-panel));
  border-color: color-mix(in srgb, var(--game-bad) 45%, var(--game-line));
}
.fui .fui-menu-item.fui-danger,
.fui .fui-menu-item.fui-danger .fui-icon {
  color: var(--game-bad);
}
.fui .fui-menu-item:disabled {
  opacity: .45;
  cursor: default;
}
.fui .fui-menu-sep {
  height: 1px;
  margin: .35em .2em;
  background: var(--game-line);
}

/* ---- Focus: a ring in the accent, for keys and gamepad (data-fui-input="pad" is set by nav.js) ---- */
.fui :is(.fui-button, .fui-menu-item, .fui-chip, .fui-input, .fui-sort, .fui-key, a):is(:focus-visible, [data-fui-input='pad'] :focus) {
  box-shadow: var(--fui-ring);
}
/* A tab shows the focus as a fill behind its label, not a ring: its underline already says which one is open, and a
   ring cut off by the strip would read as two stray lines beside it. */
.fui .fui-tab:is(:focus-visible, [data-fui-input='pad'] :focus) {
  background: var(--game-soft);
}
.fui .fui-rail .fui-tab[aria-selected='true']:is(:focus-visible, [data-fui-input='pad'] :focus) {
  background: color-mix(in srgb, var(--game-accent) 28%, var(--game-panel));
}
.fui .fui-input:focus {
  border-color: var(--game-accent);
}

/* ---- Settings rows: title and hint on the left, the control hard right ---- */
.fui .fui-rows {
  display: flex;
  flex-direction: column;
}
.fui .fui-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.2em;
  min-height: 3.6em;
  padding: .75em 0;
  border-bottom: 1px solid var(--game-line);
}
.fui .fui-row:last-child {
  border-bottom: 0;
}
.fui .fui-row-label {
  display: flex;
  flex-direction: column;
  gap: .15em;
  flex: 1 1 0;
  min-width: 6em;
  font-weight: 600;
}
.fui .fui-row-label small {
  font-size: .82em;
  font-weight: 400;
  line-height: 1.4;
  color: var(--game-muted);
}
/* A group heading in a section: a title, a note, a hairline under them. */
.fui .fui-group {
  padding: 1.5em 0 .7em;
  border-bottom: 1px solid var(--game-line);
}
.fui .fui-group:first-child {
  padding-top: .3em;
}
.fui .fui-group-title {
  font-size: 1.13em;
  font-weight: 600;
}
.fui .fui-group-note {
  margin-top: .3em;
  font-size: .82em;
  color: var(--game-muted);
}
.fui .fui-section-title {
  margin: 1.2em 0 .2em;
}
.fui .fui-section-title:first-child {
  margin-top: 0;
}

/* ---- Toggle: a real checkbox (role=switch) laid over a drawn track ---- */
.fui .fui-switch {
  position: relative;
  display: inline-flex;
  flex: none;
  width: 2.95em;
  height: 1.6em;
}
.fui .fui-switch input {
  -webkit-appearance: none;
  appearance: none;
  position: absolute;
  inset: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}
.fui .fui-switch-track {
  position: absolute;
  inset: 0;
  border-radius: 999px;
  background: var(--fui-track);
  transition: background-color var(--fui-fast), box-shadow var(--fui-fast);
}
.fui .fui-switch-track::after {
  content: '';
  position: absolute;
  top: 50%;
  left: .2em;
  width: 1.2em;
  height: 1.2em;
  border-radius: 50%;
  background: var(--game-muted);
  transform: translateY(-50%);
  transition: transform var(--fui-slow) var(--fui-ease), background-color var(--fui-fast);
}
.fui .fui-switch input:checked + .fui-switch-track {
  background: var(--game-accent-fill);
}
.fui .fui-switch input:checked + .fui-switch-track::after {
  background: var(--game-on-accent);
  transform: translate(1.35em, -50%);
}
.fui .fui-switch input:disabled {
  cursor: default;
}
.fui .fui-switch input:disabled + .fui-switch-track {
  opacity: .45;
}
.fui .fui-switch input:is(:focus-visible, [data-fui-input='pad'] :focus) + .fui-switch-track {
  box-shadow: var(--fui-ring);
}

/* ---- Slider: a native range input; --fui-fill (set by components.js) paints the filled part ---- */
.fui .fui-slider-wrap {
  display: inline-flex;
  flex: 0 1 auto;
  align-items: center;
  gap: .9em;
  min-width: 0;
}
.fui input.fui-slider {
  -webkit-appearance: none;
  appearance: none;
  flex: 0 1 auto;
  width: 14em;
  min-width: 5em;
  height: 1.75em;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  accent-color: var(--game-accent-fill);
  cursor: pointer;
  --fui-fill: 50%;
}
.fui input.fui-slider::-webkit-slider-runnable-track {
  height: .3em;
  border-radius: 999px;
  background: linear-gradient(to right, var(--game-accent-fill) var(--fui-fill), var(--fui-track) var(--fui-fill));
}
.fui input.fui-slider::-moz-range-track {
  height: .3em;
  border-radius: 999px;
  background: var(--fui-track);
}
.fui input.fui-slider::-moz-range-progress {
  height: .3em;
  border-radius: 999px;
  background: var(--game-accent-fill);
}
/* the knob wears the theme: a small rounded square in the accent's fill */
.fui input.fui-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 1.1em;
  height: 1.1em;
  margin-top: -.4em;
  border-radius: .28em;
  border: 2px solid var(--game-panel);
  background: var(--game-accent-fill);
  transition: box-shadow var(--fui-fast);
}
.fui input.fui-slider::-moz-range-thumb {
  width: 1.1em;
  height: 1.1em;
  border-radius: .28em;
  border: 2px solid var(--game-panel);
  background: var(--game-accent-fill);
  box-sizing: border-box;
}
.fui input.fui-slider:is(:focus-visible, [data-fui-input='pad'] :focus)::-webkit-slider-thumb {
  box-shadow: var(--fui-ring);
}
.fui input.fui-slider:is(:focus-visible, [data-fui-input='pad'] :focus)::-moz-range-thumb {
  box-shadow: var(--fui-ring);
}
.fui input.fui-slider:disabled {
  opacity: .45;
  cursor: default;
}
/* A notched slider: the notches' labels under the thumb's real positions (the thumb is 1.1em wide; the labels' row
   is 0.75em, so its own thumb is 1.1 / 0.75 em); the end labels line up with the track's ends instead. */
.fui .fui-notch-track {
  display: flex;
  flex: 0 1 auto;
  flex-direction: column;
  gap: .2em;
  min-width: 0;
}
.fui input.fui-slider.fui-notched {
  width: 19em; /* room for each notch's label */
}
.fui .fui-notches {
  --fui-thumb: 1.4667em;
  position: relative;
  height: 1.4em;
  color: var(--game-muted);
  font-size: .75em;
  font-weight: 600;
}
.fui .fui-notch {
  position: absolute;
  top: 0;
  left: calc(var(--fui-thumb) / 2 + (100% - var(--fui-thumb)) * var(--fui-notch-at));
  transform: translateX(-50%);
  white-space: nowrap;
  transition: color var(--fui-fast);
}
.fui .fui-notch:first-child {
  transform: translateX(calc(var(--fui-thumb) / -2));
}
.fui .fui-notch:last-child:not(:first-child) {
  transform: translateX(calc(-100% + var(--fui-thumb) / 2));
}
.fui .fui-notch[data-current] {
  color: var(--game-accent);
}
.fui .fui-notch-help {
  min-height: 2.3em; /* room for two lines, so the row keeps its height from notch to notch */
}
.fui .fui-notched-row[data-pending] .fui-notch-track {
  opacity: .6;
}
.fui .fui-notch-help .fui-loader {
  font-size: 1em;
}
.fui .fui-slider-value {
  display: inline-grid;
  justify-items: end;
  flex: none;
  min-width: 2.6em;
  text-align: right;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--game-text);
}
/* the shown value and an invisible copy of the widest one share one cell: the readout never changes width */
.fui .fui-slider-value > * {
  grid-area: 1 / 1;
}
.fui .fui-slider-value > .fui-slider-sizer {
  visibility: hidden;
}

/* ---- Choice: radio buttons drawn as a segmented control (the chosen one tinted with the accent) ---- */
.fui .fui-choice {
  display: inline-flex;
  flex-wrap: wrap;
  gap: .2em;
  padding: .2em;
  border: 1px solid var(--game-line);
  border-radius: var(--fui-radius-sm);
  background: var(--game-soft);
}
.fui .fui-choice label {
  position: relative;
  display: flex;
}
.fui .fui-choice input {
  -webkit-appearance: none;
  appearance: none;
  position: absolute;
  inset: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}
.fui .fui-choice label > span {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5em;
  min-height: 2.15em;
  padding: 0 .9em;
  border-radius: calc(var(--fui-radius-sm) - .2em);
  color: var(--game-muted);
  font-weight: 600;
  white-space: nowrap;
  transition: background-color var(--fui-fast), color var(--fui-fast), box-shadow var(--fui-fast);
}
.fui .fui-choice input:checked + span {
  background: var(--fui-tint);
  color: var(--fui-accent-ink);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--game-accent) 45%, transparent);
}
.fui .fui-choice input:is(:focus-visible, [data-fui-input='pad'] :focus) + span {
  box-shadow: var(--fui-ring);
}
.fui .fui-choice input:disabled + span {
  opacity: .45;
}
/* A choice as a list: one full-width option per line (the theme picker). */
.fui .fui-choice.fui-choice-list {
  display: flex;
  flex-direction: column;
  gap: .4em;
  max-width: 24em;
  padding: 0;
  border: 0;
  background: none;
}
.fui .fui-rows > .fui-choice-list {
  margin: .9em 0 .5em;
}
.fui .fui-choice-list label > span {
  justify-content: flex-start;
  gap: .8em;
  width: 100%;
  min-height: 2.75em;
  padding: 0 .9em;
  border: 1px solid var(--game-line);
  border-radius: var(--fui-radius-sm);
  background: var(--game-soft);
  color: var(--game-text);
}
.fui .fui-choice-list input:checked + span {
  border-color: var(--game-accent);
  background: var(--fui-tint);
  color: var(--game-text);
  box-shadow: none;
}
.fui .fui-choice-list input:checked + span > .fui-icon {
  margin-left: auto;
  color: var(--game-accent);
}
.fui .fui-choice-list input:not(:checked) + span > .fui-icon {
  display: none;
}
/* A theme's swatch: three chips — its title bar, its window, its accent — from its own data-game-theme. */
.fui .fui-swatch {
  display: inline-flex;
  flex: none;
  padding: 1px;
  border-radius: 4px;
  background: var(--fui-strong-line);
}
.fui .fui-swatch > b {
  width: .9em;
  height: .9em;
}
.fui .fui-swatch > b:first-child {
  border-radius: 3px 0 0 3px;
  background: var(--game-titlebar);
}
.fui .fui-swatch > b:nth-child(2) {
  background: var(--game-panel);
  background: rgb(from var(--game-panel) r g b); /* opaque, where the browser can say so */
}
.fui .fui-swatch > b:last-child {
  border-radius: 0 3px 3px 0;
  background: var(--game-accent);
}

/* ---- Tabs: muted labels, the current one in the accent with an underline its full width ---- */
.fui .fui-tabs {
  display: flex;
  align-items: stretch;
  padding: 0 calc(var(--fui-gutter) - 1em);
  border-bottom: 1px solid var(--game-line);
  overflow-x: auto;
  scrollbar-width: none;
}
.fui .fui-tab {
  -webkit-appearance: none;
  appearance: none;
  position: relative;
  display: inline-flex;
  flex: none;
  align-items: center;
  gap: .5em;
  min-height: 3.3em;
  margin: 0;
  padding: 0 1em;
  border: 0;
  border-radius: .3em .3em 0 0;
  background: transparent;
  color: var(--game-muted);
  font: inherit;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  transition: color var(--fui-fast), background-color var(--fui-fast), box-shadow var(--fui-fast);
}
.fui .fui-tab[aria-selected='true'] {
  color: var(--game-accent);
}
.fui .fui-tab[aria-selected='true']::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 3px;
  background: var(--game-accent);
}
.fui .fui-tabs .fui-hint {
  align-self: center;
  margin: 0 .5em;
}
.fui .fui-tabs .fui-hint:last-child {
  margin-left: auto;
}

/* ---- The book: sections down a rail on the left, the current one's rows on the right (the settings menu) ----
   tabs({ layout: 'rail' }). In a narrow window the rail turns into a strip of tabs on top (a container query on the
   book, so a phone and a narrow window both get it). */
.fui .fui-book {
  container-type: inline-size;
  display: flex;
  flex: 1;
  min-height: 0;
}
.fui .fui-book-layout {
  display: flex;
  flex: 1;
  min-width: 0;
  min-height: 0;
}
.fui .fui-tabs.fui-rail {
  flex-direction: column;
  flex: none;
  gap: .15em;
  width: 13em;
  padding: .7em .55em;
  border-bottom: 0;
  border-right: 1px solid var(--game-line);
  background: var(--game-band);
  overflow-x: hidden;
  overflow-y: auto;
}
.fui .fui-rail .fui-tab {
  min-height: 2.45em;
  padding: 0 .85em;
  border-radius: 6px;
  font-weight: 500;
}
.fui .fui-rail .fui-tab[aria-selected='true'] {
  background: var(--fui-tint);
  color: var(--fui-accent-ink);
  font-weight: 600;
}
.fui .fui-rail .fui-tab[aria-selected='true']::after {
  display: none;
}
.fui .fui-rail .fui-tab .fui-icon {
  display: none;
}
.fui .fui-rail-hints {
  display: flex;
  align-items: center;
  gap: .4em;
  margin-top: auto;
  padding: .8em .35em .1em;
  color: var(--game-muted);
  font-size: .8em;
}
.fui .fui-tabs .fui-rail-hints .fui-hint {
  margin: 0;
}
.fui .fui-book-layout > .fui-panel-body {
  flex: 1;
  min-width: 0;
  overflow: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: var(--fui-track) transparent;
}
@container (max-width: 36em) {
  .fui .fui-book-layout {
    flex-direction: column;
  }
  .fui .fui-tabs.fui-rail {
    flex-direction: row;
    gap: 0;
    width: auto;
    padding: 0 calc(var(--fui-gutter) - 1em);
    border-right: 0;
    border-bottom: 1px solid var(--game-line);
    background: transparent;
    overflow-x: auto;
    overflow-y: hidden;
  }
  .fui .fui-rail .fui-tab {
    min-height: 3.1em;
    padding: 0 1em;
    border-radius: .3em .3em 0 0;
    font-weight: 600;
  }
  .fui .fui-rail .fui-tab[aria-selected='true'] {
    background: transparent;
    color: var(--game-accent); /* no tint here: the plain accent, as on every strip of tabs */
  }
  .fui .fui-rail .fui-tab[aria-selected='true']::after {
    display: block;
  }
  .fui .fui-rail-hints {
    display: none;
  }
}

/* ---- Text input, search field, drop-down ---- */
.fui .fui-input {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  min-height: 2.5em;
  margin: 0;
  padding: 0 .9em;
  border: 1px solid var(--game-line);
  border-radius: var(--fui-radius-sm);
  background: var(--game-soft);
  color: var(--game-text);
  font: inherit;
  -webkit-user-select: text;
  user-select: text;
  transition: border-color var(--fui-fast), box-shadow var(--fui-fast);
}
.fui .fui-input::placeholder {
  color: var(--game-muted);
}
/* searchField(): a magnifier inside the field, the clear button at its end */
.fui .fui-search {
  position: relative;
  display: inline-flex;
  align-items: center;
  width: 17em;
  max-width: 100%;
}
.fui .fui-search > .fui-icon {
  position: absolute;
  left: .8em;
  width: 1.05em;
  height: 1.05em;
  color: var(--game-muted);
  pointer-events: none;
}
.fui .fui-search > .fui-input {
  padding: 0 2.4em 0 2.4em;
}
.fui .fui-search > .fui-input::-webkit-search-cancel-button {
  -webkit-appearance: none;
  appearance: none;
}
.fui .fui-search-clear {
  position: absolute;
  right: .35em;
  display: grid;
  place-items: center;
  width: 1.8em;
  height: 1.8em;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--fui-track);
  color: var(--game-muted);
  cursor: pointer;
}
.fui .fui-search-clear .fui-icon {
  width: .9em;
  height: .9em;
}
.fui .fui-search[data-empty] .fui-search-clear {
  display: none;
}
/* dropdown(): a button showing the choice, a list under it */
.fui .fui-button.fui-select {
  justify-content: space-between;
  gap: .8em;
  min-width: 8.5em;
  padding: 0 .7em 0 .95em;
  font-weight: 500;
}
.fui .fui-select > .fui-icon {
  width: 1em;
  height: 1em;
  color: var(--game-muted);
}
.fui .fui-select-value {
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ---- Dialogs: native <dialog> shown modal, so the game behind is inert and focus stays inside ---- */
.fui.fui-dialog {
  --fui-dialog-width: 32em; /* a window's width (its size sets it); in Big Screen Mode, its content's */
  position: fixed;
  inset: 0;
  width: min(var(--fui-dialog-width), calc(100vw - 2em));
  max-width: none;
  max-height: min(46em, calc(100dvh - 2em));
  margin: auto;
  padding: 0;
  overflow: hidden;
}
.fui.fui-dialog[open] {
  display: flex;
  flex-direction: column;
  animation: fui-pop var(--fui-slow) var(--fui-ease);
}
/* Without a blur, a slightly see-through dialog lets what is behind it ghost through its text: dialogs take the
   panel colour fully opaque (derived from --game-panel, so themes need no extra token). */
@supports (color: rgb(from red r g b)) {
  .fui.fui-dialog:not(.fui-screen) {
    background: rgb(from var(--game-panel) r g b / 1); /* "/ 1": an omitted alpha would keep the token's */
  }
}
.fui.fui-dialog.fui-narrow {
  --fui-dialog-width: 26em;
}
.fui.fui-dialog.fui-wide {
  --fui-dialog-width: 52em;
}
.fui.fui-dialog.fui-large {
  --fui-dialog-width: 72em;
}
.fui.fui-dialog > .fui-panel-body {
  flex: 1;
  overflow: auto;
  overscroll-behavior: contain; /* scrolling to the end does not drag the page behind (phones) */
  scrollbar-width: thin;
  scrollbar-color: var(--fui-track) transparent;
}
.fui.fui-dialog::backdrop {
  background: rgb(6 8 12 / .55); /* a plain darkening, no blur */
  animation: fui-fade var(--fui-slow) ease-out;
}
/* The settings book: a steady height, so moving between sections never resizes the window under the pointer. */
.fui.fui-dialog.fui-settings {
  height: min(40em, calc(100dvh - 2em));
}
.fui .fui-dialog-icon {
  display: grid;
  place-items: center;
  width: 3.4em;
  height: 3.4em;
  margin: 0 auto 1em;
  border-radius: 50%;
  background: var(--game-soft);
  color: var(--game-text);
}
.fui .fui-dialog-icon .fui-icon {
  width: 1.7em;
  height: 1.7em;
}
.fui .fui-dialog-icon.fui-danger {
  color: var(--game-bad);
}
.fui .fui-center {
  text-align: center;
}
.fui .fui-message {
  font-size: 1.15em;
  font-weight: 600;
}
.fui .fui-message + .fui-text {
  margin-top: .45em;
}
.fui .fui-error {
  margin-top: 1em;
  padding: .7em .9em;
  border-radius: var(--fui-radius-sm);
  background: color-mix(in srgb, var(--game-bad) 14%, transparent);
  color: var(--game-text);
  font-size: .92em;
}
.fui .fui-error:empty {
  display: none;
}

@keyframes fui-pop {
  from {
    opacity: 0;
    transform: translateY(.6em) scale(.985);
  }
}
@keyframes fui-fade {
  from {
    opacity: 0;
  }
}

/* The hamburger menu: a short window in the middle of the screen, where every menu opens (on a phone it takes the whole
   screen, as windows do). hamburgerMenu({ at: 'corner' }) anchors it under the corner buttons instead. */
.fui.fui-dialog.fui-sheet {
  --fui-dialog-width: 19em;
}
.fui.fui-dialog.fui-sheet.fui-corner {
  inset: auto;
  top: calc(max(.75em, env(safe-area-inset-top)) + 3.4em);
  right: max(.75em, env(safe-area-inset-right));
  width: min(var(--fui-dialog-width), calc(100vw - 1.5em));
  margin: 0;
  transform-origin: top right;
}
.fui.fui-dialog.fui-sheet.fui-corner.fui-left {
  right: auto;
  left: max(.75em, env(safe-area-inset-left));
  transform-origin: top left;
}
.fui.fui-dialog.fui-sheet.fui-corner::backdrop {
  background: rgb(6 8 12 / .25);
}
.fui.fui-dialog.fui-sheet > .fui-panel-body {
  padding: .5em;
}
/* A drop-down's list: a small window under (or over) its button; dropdown() sets where. */
.fui.fui-dialog.fui-popup {
  inset: auto;
  top: var(--fui-popup-top, 1em);
  left: var(--fui-popup-left, 1em);
  width: auto;
  min-width: var(--fui-popup-width, 10em);
  max-width: calc(100vw - 1em);
  max-height: var(--fui-popup-height, min(24em, calc(100dvh - 1em)));
  margin: 0;
  border-radius: var(--fui-radius-sm);
  transform-origin: top left;
}
.fui.fui-dialog.fui-popup::backdrop {
  background: transparent;
}
.fui.fui-dialog.fui-popup > .fui-panel-body {
  padding: .3em;
}
.fui .fui-popup .fui-menu {
  gap: 0;
}
.fui .fui-popup .fui-menu-item {
  min-height: 2.45em;
  padding: .2em .7em;
  border-color: transparent;
  border-radius: 6px;
  background: transparent;
  font-size: 1em;
  font-weight: 500;
}
.fui .fui-popup .fui-menu-item[aria-checked='true'] {
  color: var(--game-accent);
  font-weight: 600;
}
.fui .fui-popup .fui-menu-item .fui-icon {
  color: var(--game-accent);
}
.fui .fui-popup .fui-menu-item[aria-checked='false'] .fui-icon {
  visibility: hidden;
}

/* ---- Full screens (the title screen): a dialog over the whole viewport, the game visible behind ---- */
.fui.fui-dialog.fui-screen {
  inset: 0;
  width: 100vw;
  max-width: none;
  height: 100dvh;
  max-height: none;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  background: linear-gradient(90deg, var(--game-panel) 0, color-mix(in srgb, var(--game-panel) 70%, transparent) 30em,
    transparent 75%);
}
.fui.fui-dialog.fui-screen > .fui-panel-body {
  height: 100%;
  padding: 0;
  overflow: hidden;
}
.fui.fui-dialog.fui-screen::backdrop {
  background: transparent;
}
.fui .fui-title-layout {
  display: flex;
  flex-direction: column;
  justify-content: center;
  height: 100%;
  /* clear of a phone's notch and home indicator */
  padding: max(2em, 7vh, env(safe-area-inset-top)) max(1.5em, 6vw, env(safe-area-inset-right))
    max(2em, 7vh, env(safe-area-inset-bottom)) max(1.5em, 6vw, env(safe-area-inset-left));
  overflow: auto;
}
/* The width lives on the column, not on the padded layout: viewport-based padding can never squeeze it. */
.fui .fui-title-column {
  display: flex;
  flex-direction: column;
  gap: 2.2em;
  width: min(30em, 100%);
}
.fui .fui-title-column > .fui-menu {
  max-width: 22em;
}
.fui .fui-title-name {
  font-family: var(--fui-display-font);
  font-size: clamp(2.4em, 6.5vw, 4.2em);
  font-weight: 800;
  line-height: .95;
  letter-spacing: -.01em;
  text-transform: uppercase;
}
.fui .fui-title-tagline {
  margin-top: .7em;
  color: var(--game-muted);
  font-size: 1.05em;
}
.fui .fui-title-foot {
  display: flex;
  align-items: center;
  gap: 1em;
  color: var(--game-muted);
  font-size: .85em;
}

/* ---- Toasts: a stack at the top centre, in the top layer (a manual popover) so they show over dialogs ---- */
.fui.fui-toasts {
  position: fixed;
  inset: auto;
  top: max(.9em, env(safe-area-inset-top));
  left: 50%;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: .55em;
  width: min(25em, calc(100vw - 2em));
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--game-text);
  overflow: visible;
  transform: translateX(-50%);
  pointer-events: none;
}
.fui.fui-toasts:empty {
  display: none;
}
.fui .fui-toast {
  --fui-toast-color: var(--game-accent);
  position: relative;
  display: flex;
  align-items: center;
  gap: .8em;
  padding: .75em .7em .75em 1.15em;
  border: 1px solid var(--game-line);
  border-radius: var(--fui-radius-sm);
  background: var(--game-panel);
  box-shadow: var(--fui-shadow);
  overflow: hidden;
  pointer-events: auto;
  animation: fui-toast-in var(--fui-slow) var(--fui-ease);
}
.fui .fui-toast::before {
  content: '';
  position: absolute;
  inset: 0 auto 0 0;
  width: 4px;
  background: var(--fui-toast-color);
}
.fui .fui-toast[data-kind='good'] {
  --fui-toast-color: var(--game-good);
}
.fui .fui-toast[data-kind='warn'] {
  --fui-toast-color: var(--game-warn);
}
.fui .fui-toast[data-kind='bad'] {
  --fui-toast-color: var(--game-bad);
}
.fui .fui-toast > .fui-icon {
  width: 1.4em;
  height: 1.4em;
  color: var(--fui-toast-color);
}
.fui .fui-toast > .fui-toast-image {
  flex: none;
  width: 2.6em;
  height: 2.6em;
  border-radius: 6px;
  object-fit: cover;
}
.fui .fui-toast-text {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-width: 0;
}
.fui .fui-toast-text strong {
  font-weight: 700;
}
.fui .fui-toast-text span {
  color: var(--game-muted);
  font-size: .92em;
}
.fui .fui-toast.fui-leaving {
  animation: fui-toast-out var(--fui-slow) ease-in forwards;
}
@keyframes fui-toast-in {
  from {
    opacity: 0;
    transform: translateY(-.8em);
  }
}
@keyframes fui-toast-out {
  to {
    opacity: 0;
    transform: translateY(-.5em);
  }
}

/* ---- The game's corner buttons: profile chip, sound, hamburger menu, fullscreen ---- */
.fui.fui-chrome {
  position: fixed;
  z-index: var(--fui-z);
  top: max(.75em, env(safe-area-inset-top));
  right: max(.75em, env(safe-area-inset-right));
  display: flex;
  align-items: center;
  gap: .5em;
  pointer-events: none;
}
.fui.fui-chrome.fui-left {
  right: auto;
  left: max(.75em, env(safe-area-inset-left));
}
/* A full screen (the title) owns the view: the corner buttons step aside while it is open (screens.js sets the
   attribute, so no :has() is needed). */
[data-fui-screen] .fui.fui-chrome {
  visibility: hidden;
}
.fui.fui-chrome > * {
  pointer-events: auto;
}
.fui.fui-chrome .fui-button,
.fui.fui-chrome .fui-chip {
  min-height: 2.75em;
  background: var(--game-panel);
  border-color: var(--game-line);
}
.fui.fui-chrome .fui-button.fui-icon-only {
  width: 2.75em;
}

/* ---- Identity: avatars and the profile chip ---- */
.fui .fui-avatar {
  position: relative;
  display: inline-grid;
  place-items: center;
  flex: none;
  width: 2.1em;
  height: 2.1em;
  border-radius: 50%;
  overflow: hidden;
  background: var(--game-soft);
  color: var(--game-text);
  font-size: 1em;
  font-weight: 700;
  line-height: 1;
}
.fui .fui-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.fui .fui-avatar .fui-initials {
  font-size: .8em;
  letter-spacing: .02em;
}
.fui .fui-avatar.fui-large {
  width: 6em;
  height: 6em;
  font-size: 1.1em;
  box-shadow: 0 0 0 3px var(--game-panel), 0 0 0 5px var(--game-accent);
}
.fui .fui-avatar.fui-large .fui-initials {
  font-size: 2em;
}
.fui .fui-avatar.fui-large .fui-icon {
  width: 2.6em;
  height: 2.6em;
}
.fui .fui-chip {
  -webkit-appearance: none;
  appearance: none;
  display: inline-flex;
  align-items: center;
  gap: .55em;
  min-height: 2.75em;
  max-width: 15em;
  margin: 0;
  padding: 0 1em 0 .3em;
  border: 1px solid var(--game-line);
  border-radius: 999px;
  background: var(--game-panel);
  color: var(--game-text);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  transition: background-color var(--fui-fast), box-shadow var(--fui-fast);
}
.fui .fui-chip-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.fui .fui-chip[data-state='out'] .fui-avatar {
  background: transparent;
}
.fui .fui-profile {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .9em;
  text-align: center;
}
.fui .fui-profile-name {
  font-size: 1.45em;
  font-weight: 700;
  overflow-wrap: anywhere;
}
.fui .fui-profile-note {
  color: var(--game-muted);
  font-size: .92em;
}
.fui .fui-link {
  color: var(--game-accent);
  font-weight: 600;
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, var(--game-accent) 50%, transparent);
  text-underline-offset: .25em;
  border-radius: .2em;
}

/* ---- Numbers: stats, the band of headline numbers ---- */
.fui .fui-stat {
  display: inline-flex;
  flex-direction: column;
  gap: .25em;
}
.fui .fui-stat-value {
  font-size: 2.4em;
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -.01em;
  font-variant-numeric: tabular-nums;
}
.fui .fui-stat-label {
  font-size: .73em;
  font-weight: 600;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--game-muted);
}
/* statBand(): a full-width band of a screen's headline numbers, split by hairlines. The hairline is a shadow on each
   cell's left edge, clipped by the band where a cell starts a line, so a band that wraps on a phone stays clean. */
.fui .fui-statband {
  display: flex;
  flex-wrap: wrap;
  row-gap: 1em;
  padding: 1.15em 0 1.05em;
  background: var(--game-band);
  border-bottom: 1px solid var(--game-line);
  overflow: hidden;
}
.fui .fui-statband-cell {
  flex: 1 1 10.5em;
  min-width: 0;
  padding: 0 var(--fui-row-pad);
  box-shadow: -1px 0 0 var(--game-line);
}
.fui .fui-statband-value {
  overflow: hidden;
  font-size: 2em;
  font-weight: 700;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.fui .fui-statband-label {
  margin-top: .35em;
  font-size: .73em;
  font-weight: 600;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--game-muted);
}
.fui .fui-statband-sub {
  margin-top: .2em;
  overflow: hidden;
  color: var(--game-muted);
  font-size: .87em;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.fui .fui-statband-cell > .fui-pbar {
  max-width: 18em;
  margin-top: .6em;
}

/* ---- Small parts: badges, tags, progress, key and pad hints ---- */
.fui .fui-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.7em;
  height: 1.7em;
  padding: 0 .45em;
  border-radius: .4em;
  background: var(--game-accent-fill);
  color: var(--game-on-accent);
  font-size: .75em;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.fui .fui-badge:is(.fui-good, .fui-warn, .fui-bad) {
  color: var(--game-panel);
}
.fui .fui-badge.fui-good {
  background: var(--game-good);
}
.fui .fui-badge.fui-warn {
  background: var(--game-warn);
}
.fui .fui-badge.fui-bad {
  background: var(--game-bad);
}
/* A tag: a caveat beside a title (EXTENDED, HIDDEN, a tier), outlined so it never reads as another badge. */
.fui .fui-tag {
  display: inline-flex;
  flex: none;
  align-items: center;
  padding: .12em .5em;
  border: 1px solid var(--fui-strong-line);
  border-radius: 3px;
  color: var(--game-muted);
  font-size: max(.64em, 10px);
  font-weight: 700;
  letter-spacing: .05em;
  line-height: 1.3;
  text-transform: uppercase;
  white-space: nowrap;
}
.fui .fui-progress {
  height: .4em;
  border-radius: 999px;
  background: var(--fui-track);
  overflow: hidden;
}
.fui .fui-progress > i {
  display: block;
  width: var(--fui-value, 0%);
  height: 100%;
  border-radius: inherit;
  background: var(--game-accent-fill);
}
/* progress(value, label, { text }): a bar that carries its value inside. Two copies of the words: one in the text
   colour over the track, one in the fill's text colour clipped to the fill, so they read at every fill level. */
.fui .fui-pbar {
  position: relative;
  display: block;
  height: 1.85em;
  border-radius: 6px;
  background: var(--fui-track);
  font-size: .73em;
  font-weight: 700;
  line-height: 1.85em;
  font-variant-numeric: tabular-nums;
  overflow: hidden;
}
.fui .fui-pbar > i {
  position: absolute;
  inset: 0 auto 0 0;
  width: var(--fui-value, 0%);
  background: var(--game-accent-fill);
}
.fui .fui-pbar > span {
  position: relative;
  display: block;
  padding: 0 .5em;
  overflow: hidden;
  color: var(--game-text);
  text-align: center;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.fui .fui-pbar > span + span {
  position: absolute;
  inset: 0;
  color: var(--game-on-accent);
  clip-path: inset(0 calc(100% - var(--fui-value, 0%)) 0 0);
}

/* ---- The loader: hitch-friendly (components.js loader()) ----
   A 3 x 3 grid of squares whose missing one steps round the ring: 8 hard steps a lap, 10 a second. Each square is
   either there or not (opacity with steps(), never in between), the squares are whole pixels with square corners, and
   nothing turns or fades: no blending anywhere. A game that freezes or drops frames only makes one step last longer,
   instead of a smooth spinner visibly stuttering; and the compositor runs it, so it keeps stepping while the page's
   script is busy. The ring is read clockwise from the top-left; the centre square stays. */
.fui .fui-loader {
  --fui-loader-cell: 6px;
  --fui-loader-gap: 3px;
  display: inline-flex;
  align-items: center;
  gap: .7em;
  color: var(--game-muted);
  font-weight: 600;
}
.fui .fui-loader.fui-small {
  --fui-loader-cell: 4px;
  --fui-loader-gap: 2px;
}
.fui .fui-loader.fui-large {
  --fui-loader-cell: 10px;
  --fui-loader-gap: 4px;
}
/* whole pixels at every interface size, so no square edge is ever smoothed */
@supports (width: round(1em, 1px)) {
  .fui .fui-loader {
    --fui-loader-cell: round(.4em, 1px);
    --fui-loader-gap: round(.2em, 1px);
  }
  .fui .fui-loader.fui-small {
    --fui-loader-cell: round(.27em, 1px);
    --fui-loader-gap: round(.13em, 1px);
  }
  .fui .fui-loader.fui-large {
    --fui-loader-cell: round(.67em, 1px);
    --fui-loader-gap: round(.27em, 1px);
  }
}
.fui .fui-loader-grid {
  display: grid;
  flex: none;
  grid-template-columns: repeat(3, var(--fui-loader-cell));
  grid-auto-rows: var(--fui-loader-cell);
  gap: var(--fui-loader-gap);
  color: var(--game-accent);
}
.fui .fui-loader-grid > i {
  background: currentColor;
  animation: fui-loader-gap 800ms steps(1, end) infinite;
  animation-delay: calc(var(--fui-step) * 100ms - 800ms);
}
.fui .fui-loader-grid > i:nth-child(1) { --fui-step: 0; }
.fui .fui-loader-grid > i:nth-child(2) { --fui-step: 1; }
.fui .fui-loader-grid > i:nth-child(3) { --fui-step: 2; }
.fui .fui-loader-grid > i:nth-child(6) { --fui-step: 3; }
.fui .fui-loader-grid > i:nth-child(9) { --fui-step: 4; }
.fui .fui-loader-grid > i:nth-child(8) { --fui-step: 5; }
.fui .fui-loader-grid > i:nth-child(7) { --fui-step: 6; }
.fui .fui-loader-grid > i:nth-child(4) { --fui-step: 7; }
.fui .fui-loader-grid > i:nth-child(5) {
  animation: none;
}
/* gone for the first eighth of the lap, then back: steps(1, end) jumps, it never fades */
@keyframes fui-loader-gap {
  from {
    opacity: 0;
  }
  12.5% {
    opacity: 1;
  }
}

.fui .fui-kbd,
.fui .fui-hint::before {
  display: inline-grid;
  place-items: center;
  min-width: 1.75em;
  height: 1.75em;
  padding: 0 .4em;
  border: 1px solid color-mix(in srgb, currentColor 45%, transparent);
  border-radius: .4em;
  font-size: .72em;
  font-weight: 700;
  line-height: 1;
  letter-spacing: .02em;
  white-space: nowrap;
}
/* A hint shows the key with a keyboard (data-key) and the button with a gamepad (data-pad); none for touch. */
.fui .fui-hint {
  display: inline-flex;
  margin-left: auto;
  opacity: .8;
}
.fui .fui-hint::before {
  content: attr(data-key);
}
[data-fui-input='pad'] .fui .fui-hint::before {
  content: attr(data-pad);
  padding: 0;
  border-radius: 50%;
}
/* a footer holding nothing but hints goes too (the pause menu's, for the mouse) */
[data-fui-input='pointer'] .fui :is(.fui-hint, .fui-hints, .fui-rail-hints, .fui-panel-foot.fui-foot-hints) {
  display: none;
}
@media (pointer: coarse) {
  :root:not([data-fui-input]) .fui :is(.fui-hint, .fui-hints, .fui-rail-hints, .fui-panel-foot.fui-foot-hints) {
    display: none;
  }
}
.fui .fui-hints {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .4em 1.2em;
  color: var(--game-muted);
  font-size: .85em;
}
.fui .fui-hints > span {
  display: inline-flex;
  align-items: center;
  gap: .5em;
}
.fui .fui-hints .fui-hint {
  margin: 0;
}
.fui .fui-bindings {
  display: grid;
  grid-template-columns: 1fr auto auto;
  align-items: center;
  gap: .55em 1em;
}
.fui .fui-bindings > span:nth-child(3n + 1) {
  font-weight: 600;
}
.fui .fui-bindings .fui-kbd.fui-pad {
  border-radius: 999px;
}

/* ---- The controls editor (controls.js): a table per context; each key a cap the player presses to change it ---- */
.fui .fui-binding-table {
  display: flex;
  flex-direction: column;
}
.fui .fui-binding-row {
  display: grid;
  grid-template-columns: minmax(6em, 1.15fr) minmax(0, 1fr) minmax(0, 1fr) 2.2em;
  align-items: center;
  gap: .4em 1em;
  min-height: 3em;
  padding: .35em var(--fui-row-pad);
  border-bottom: 1px solid var(--game-line);
  transition: background-color var(--fui-fast), box-shadow var(--fui-fast);
}
.fui .fui-binding-head {
  min-height: 2.5em;
  color: var(--game-muted);
  font-size: .73em;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.fui .fui-binding-head > span {
  display: inline-flex;
  align-items: center;
  gap: .5em;
}
.fui .fui-binding-head .fui-icon {
  width: 1.5em;
  height: 1.5em;
}
.fui .fui-binding-action {
  display: flex;
  flex-direction: column;
  gap: .15em;
  min-width: 0;
  font-weight: 600;
}
.fui .fui-binding-action small {
  font-size: .82em;
  font-weight: 400;
  color: var(--game-muted);
}
.fui .fui-binding-cell {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .4em;
  min-width: 0;
}
.fui .fui-binding-none {
  color: var(--game-muted);
}
.fui .fui-binding-reset {
  display: flex;
  justify-content: flex-end;
}
/* A cap: a key, or a pad button (round), as the hints draw them but larger; a button where the player may change it. */
.fui .fui-key {
  -webkit-appearance: none;
  appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .35em;
  min-width: 2.5em;
  height: 2.3em;
  padding: 0 .65em;
  border: 1px solid var(--fui-strong-line);
  border-radius: var(--fui-radius-sm);
  background: var(--game-soft);
  color: var(--game-text);
  font: inherit;
  font-size: .85em;
  font-weight: 700;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color var(--fui-fast), border-color var(--fui-fast), box-shadow var(--fui-fast);
}
.fui .fui-key.fui-pad {
  border-radius: 999px;
}
.fui span.fui-key {
  border-color: var(--game-line);
  background: transparent;
  cursor: default;
}
.fui .fui-key[data-locked] {
  color: var(--game-muted);
}
.fui .fui-key .fui-icon {
  width: 1.1em;
  height: 1.1em;
}
.fui .fui-key.fui-key-add {
  min-width: 2.3em;
  padding: 0;
  border-style: dashed;
  background: transparent;
  color: var(--game-muted);
}
.fui .fui-key-group {
  display: inline-flex;
  align-items: center;
  gap: .3em;
}
/* a two-key axis reads "A / D" */
.fui .fui-key-axis > .fui-key + .fui-key {
  position: relative;
  margin-left: .8em;
}
.fui .fui-key-axis > .fui-key + .fui-key::before {
  content: '/';
  position: absolute;
  left: -.85em;
  color: var(--game-muted);
  font-weight: 400;
  pointer-events: none;
}
.fui .fui-key-mod {
  color: var(--game-muted);
  font-size: .85em;
}
/* In a narrow window an action's name takes its own line, its keys and buttons side by side under it. */
@media (max-width: 40em) {
  .fui .fui-binding-row {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) 2.2em;
  }
  .fui .fui-binding-row > :first-child {
    grid-column: 1 / 3;
  }
  .fui .fui-binding-row > .fui-binding-reset {
    grid-row: 1;
    grid-column: 3;
  }
  .fui .fui-binding-head > :first-child {
    display: none;
  }
}

/* The capture: a small window that listens for the next key or button. The countdown and the hold bar move by
   transform only (controls.js sets scaleX while it listens, and nothing runs once it closes). */
.fui.fui-dialog.fui-capture .fui-panel-body {
  text-align: center;
}
.fui .fui-capture-box {
  display: grid;
  place-items: center;
  min-height: 4.2em;
  margin: 1em 0 .7em;
  padding: .6em;
  border: 2px dashed var(--fui-strong-line);
  border-radius: var(--fui-radius-sm);
  color: var(--game-muted);
  font-size: 1.3em;
  font-weight: 700;
  outline: none;
  transition: border-color var(--fui-fast), color var(--fui-fast);
}
.fui .fui-capture-box[data-candidate] {
  border-style: solid;
  border-color: var(--game-accent);
  color: var(--game-text);
}
.fui .fui-capture-box.fui-capture-mouse {
  cursor: pointer;
}
.fui :is(.fui-capture-time, .fui-capture-holdbar) {
  display: block;
  height: 4px;
  overflow: hidden;
  border-radius: 2px;
  background: var(--game-soft);
}
.fui :is(.fui-capture-time, .fui-capture-holdbar) > i {
  display: block;
  height: 100%;
  background: var(--game-accent);
  transform-origin: left center;
}
.fui .fui-capture-holdbar {
  width: 3em;
}
.fui .fui-capture-holdbar > i {
  transform: scaleX(0);
}
.fui .fui-hints.fui-capture-hold {
  justify-content: center;
  margin-top: .9em;
}
.fui .fui-capture-note {
  min-height: 1.4em;
  margin-top: .7em;
  font-size: .9em;
  font-weight: 600;
}
.fui .fui-capture-note:empty {
  margin-top: 0;
}

/* ---- For screen readers only (a column heading's full word next to its short sign) ---- */
.fui .fui-sr {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
/* A focused scroll region (a long table): up / down scroll it with keys and pads (nav.js); a ring inside its edge. */
.fui .fui-scroll:is(:focus-visible, [data-fui-input='pad'] :focus) {
  outline: 2px solid var(--game-accent);
  outline-offset: -2px;
}

/* ---- What a game keeps online (identity.js: the log-in dialog, the profile, the consent dialog) ---- */
.fui .fui-kept {
  display: flex;
  flex-direction: column;
  gap: .6em;
  width: fit-content;
  max-width: 100%;
  margin: .9em auto .3em;
  padding: 0;
  list-style: none;
  text-align: left;
}
.fui .fui-kept li {
  display: flex;
  align-items: flex-start;
  gap: .65em;
}
.fui .fui-kept li > .fui-icon {
  color: var(--game-accent);
}
.fui .fui-kept li[data-missing] > .fui-icon {
  color: var(--game-muted);
}
.fui .fui-kept li > span {
  display: flex;
  flex-direction: column;
}
.fui .fui-kept small {
  color: var(--game-warn);
  font-size: .82em;
  font-weight: 600;
}
.fui .fui-profile-kept {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .3em;
}
.fui .fui-profile-kept .fui-kept {
  margin: .3em auto .5em;
}

/* ---- Tables: a filter band, column headings, full-width rows ----
   The grammar of AArcade Core's lists: a band that says what the list is (its label and count, its filters, a search)
   over column headings in capitals; rows run the full width of the window, split by hairlines; the row under the
   pointer lights up with an accent mark on its left edge. Rows and headings share their columns (each table sets
   them), and full-width rows carry --fui-row-pad as their side padding. */
.fui .fui-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .55em .9em;
  padding: .6em var(--fui-row-pad);
  background: var(--game-raised);
  border-bottom: 1px solid var(--game-line);
}
.fui .fui-toolbar-label {
  display: inline-flex;
  align-items: baseline;
  gap: .75em;
  margin-right: .3em;
  font-size: .73em;
  font-weight: 600;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--game-muted);
  white-space: nowrap;
}
.fui .fui-toolbar-label > b {
  color: var(--game-text);
  font-size: 1.2em;
  letter-spacing: 0;
  font-variant-numeric: tabular-nums;
}
.fui .fui-toolbar > .fui-search {
  margin-left: auto;
}
.fui .fui-thead {
  min-height: 2.75em;
  padding: 0 var(--fui-row-pad);
  background: var(--game-raised);
  border-bottom: 1px solid var(--game-line);
  color: var(--game-muted);
}
.fui .fui-thead > * {
  font-size: .73em;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.fui .fui-trow {
  border-bottom: 1px solid var(--game-line);
  transition: background-color var(--fui-fast), box-shadow var(--fui-fast);
}
/* A sortable heading: a button; the caret shows only on the sorted column, pointing the way the list runs. */
.fui .fui-sort {
  -webkit-appearance: none;
  appearance: none;
  display: inline-flex;
  align-items: center;
  gap: .5em;
  margin: 0 -.35em;
  padding: .35em;
  border: 0;
  border-radius: 4px;
  background: none;
  color: inherit;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  cursor: pointer;
  transition: color var(--fui-fast), box-shadow var(--fui-fast);
}
.fui [aria-sort] > .fui-sort {
  color: var(--game-text);
}
.fui .fui-sort-caret {
  width: 0;
  height: 0;
  border-right: .32em solid transparent;
  border-left: .32em solid transparent;
}
.fui [aria-sort='ascending'] .fui-sort-caret {
  border-bottom: .4em solid currentColor;
}
.fui [aria-sort='descending'] .fui-sort-caret {
  border-top: .4em solid currentColor;
}
.fui .fui-cell-num {
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
/* a value with a capitals line under it: a date and how long ago, a share of players */
.fui .fui-cell-pair {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .15em;
  text-align: center;
  white-space: nowrap;
}
.fui .fui-cell-pair > strong {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.fui .fui-cell-pair > small {
  font-size: .7em;
  font-weight: 600;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--game-muted);
}
.fui .fui-cell-none {
  color: var(--game-muted);
}

/* ---- Leaderboards (leaderboards.js): a table drawn from data; its columns come from --fui-lb-columns ----
   Rows share the table's columns through subgrid, so a long name never pushes a score out of line; a narrow table
   (a phone, the results screen) moves the detail columns under the name (a container query, no script). */
.fui .fui-leaderboard {
  container-type: inline-size;
  display: flex;
  flex-direction: column;
  min-height: 0;
}
/* The table is its own scroll region: its columns are laid out inside its scroll bar, so a long table never needs to
   scroll sideways; the header row stays on top. */
.fui .fui-lb-table {
  display: grid;
  grid-template-columns: var(--fui-lb-columns, minmax(2.4em, max-content) minmax(0, 1fr) minmax(5em, max-content));
  align-content: start;
  column-gap: 1.2em;
  min-height: 0;
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: var(--fui-track) transparent;
  font-variant-numeric: tabular-nums;
  transition: opacity var(--fui-fast);
}
.fui .fui-lb-table[data-busy] {
  opacity: .55;
}
.fui .fui-lb-rows {
  display: grid;
  grid-column: 1 / -1;
  grid-template-columns: subgrid;
}
.fui .fui-lb-row {
  display: grid;
  grid-column: 1 / -1;
  grid-template-columns: subgrid;
  align-items: center;
  min-height: 2.9em;
  padding: .3em var(--fui-row-pad);
  border-bottom: 1px solid var(--game-line);
  transition: background-color var(--fui-fast), box-shadow var(--fui-fast);
}
@supports not (grid-template-columns: subgrid) {
  .fui .fui-lb-rows,
  .fui .fui-lb-row {
    grid-template-columns: var(--fui-lb-columns);
  }
}
.fui .fui-lb-head {
  position: sticky;
  top: 0;
  z-index: 1;
  min-height: 2.75em;
  background: var(--game-raised);
  color: var(--game-muted);
  font-size: .73em;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.fui .fui-lb-details {
  display: contents;
}
.fui .fui-lb-rank,
.fui .fui-lb-detail,
.fui .fui-lb-score {
  text-align: right;
  white-space: nowrap;
}
.fui .fui-lb-rank {
  color: var(--game-muted);
  font-weight: 700;
}
.fui .fui-lb-name {
  display: flex;
  align-items: center;
  gap: .55em;
  min-width: 0;
  font-weight: 600;
}
.fui .fui-lb-player {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.fui .fui-lb-detail {
  color: var(--game-muted);
}
.fui .fui-lb-score {
  font-weight: 700;
}
.fui .fui-lb-head .fui-lb-detail,
.fui .fui-lb-head .fui-lb-score,
.fui .fui-lb-head .fui-lb-name {
  color: inherit;
  font-weight: inherit;
}
/* the player's own row: a tint and an accent edge */
.fui .fui-lb-row.fui-you {
  background: var(--fui-tint);
  box-shadow: inset 3px 0 var(--game-accent);
}
.fui .fui-lb-row.fui-you .fui-lb-rank {
  color: var(--game-text);
}
.fui .fui-lb-gap {
  min-height: 2em;
}
.fui .fui-lb-gap > span {
  display: flex;
  grid-column: 1 / -1;
  align-items: center;
  justify-content: center;
  gap: .4em;
  color: var(--game-muted);
  font-size: .82em;
  font-weight: 600;
}
.fui .fui-lb-message {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .2em;
  padding: 1.8em 1em;
  text-align: center;
}
.fui .fui-lb-message .fui-dialog-icon {
  margin-bottom: .6em;
}
.fui .fui-lb-message > .fui-loader {
  margin: 1.2em 0;
}
.fui .fui-lb-message .fui-button {
  margin-top: 1em;
}
.fui .fui-lb-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .6em 1em;
  padding: .7em var(--fui-row-pad) 0;
}
.fui .fui-lb-foot:empty,
.fui .fui-lb-note:empty {
  display: none;
}
.fui .fui-lb-you {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .5em .8em;
  color: var(--game-muted);
}
.fui .fui-lb-you strong {
  color: var(--game-text);
}
.fui .fui-lb-pages .fui-loader {
  margin-right: .3em;
}
.fui .fui-lb-pages {
  display: flex;
  align-items: center;
  gap: .4em;
  margin-left: auto;
}
.fui .fui-lb-page {
  min-width: 7.5em;
  color: var(--game-muted);
  font-size: .9em;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  text-align: center;
}
.fui .fui-lb-note {
  display: flex;
  flex-wrap: wrap;
  gap: .3em 1.2em;
  padding: .6em var(--fui-row-pad) 0;
  color: var(--game-muted);
  font-size: .82em;
}
.fui .fui-lb-note > span {
  display: inline-flex;
  align-items: center;
  gap: .4em;
}
.fui .fui-lb-note .fui-icon {
  width: 1.1em;
  height: 1.1em;
}
@container (max-width: 30em) {
  .fui .fui-lb-table {
    grid-template-columns: minmax(2em, max-content) minmax(0, 1fr) minmax(4.5em, max-content);
    column-gap: .8em;
  }
  .fui .fui-lb-details {
    display: flex;
    flex-wrap: wrap;
    grid-row: 2;
    grid-column: 2 / -1;
    gap: 0 .9em;
    font-size: .8em;
  }
  .fui .fui-lb-head .fui-lb-details {
    display: none;
  }
  .fui .fui-lb-detail::before {
    content: attr(data-label) ' ';
  }
  .fui .fui-lb-score {
    grid-row: 1;
    grid-column: 3;
  }
  .fui .fui-lb-pages {
    margin-left: 0;
  }
}

/* The leaderboard screen: a steady height, so switching boards does not make it jump; the rows run the full width. */
.fui.fui-dialog.fui-lb-screen {
  height: min(46em, calc(100dvh - 2em));
}
.fui.fui-lb-screen > .fui-lb-host {
  --fui-row-pad: var(--fui-gutter);
  display: flex;
  flex-direction: column;
  padding: 0 0 1em;
  overflow: hidden;
}
.fui .fui-lb-host > .fui-leaderboard {
  flex: 1;
}
.fui .fui-lb-host .fui-lb-table {
  flex: 0 1 auto;
}
.fui .fui-lb-host .fui-lb-foot {
  margin-top: auto; /* the rank line and the pages stay at the bottom, however few the rows */
}
.fui .fui-lb-picker {
  display: flex;
  align-items: center;
  gap: .5em;
  padding: .55em var(--fui-gutter);
  border-bottom: 1px solid var(--game-line);
}
.fui .fui-lb-picker > .fui-hint {
  margin: 0;
}
.fui .fui-button.fui-lb-pick {
  flex: 1;
  justify-content: space-between;
  min-width: 0;
}
.fui .fui-lb-pick > span {
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ---- The results screen (results.js): the score big, the post's state, the window around the player ---- */
.fui.fui-results > .fui-panel-body {
  display: flex;
  flex-direction: column;
  gap: 1.3em;
  padding: 1.6em var(--fui-gutter);
}
.fui .fui-results-title {
  margin-top: .2em;
  font-size: 1.9em;
  font-weight: 700;
  line-height: 1.05;
}
.fui .fui-results-stats {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 1.2em 2.4em;
}
.fui .fui-hero-line {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .4em .7em;
}
.fui .fui-hero .fui-stat-value {
  font-size: 3.4em;
}
.fui .fui-results-post {
  --fui-post-color: var(--game-accent);
  display: flex;
  align-items: center;
  gap: .8em;
  padding: .8em 1em;
  border-radius: var(--fui-radius-sm);
  background: color-mix(in srgb, var(--fui-post-color) 13%, transparent);
  box-shadow: inset 3px 0 var(--fui-post-color);
}
.fui .fui-results-post[data-kind='good'] {
  --fui-post-color: var(--game-good);
}
.fui .fui-results-post[data-kind='warn'] {
  --fui-post-color: var(--game-warn);
}
.fui .fui-results-post[data-kind='bad'] {
  --fui-post-color: var(--game-bad);
}
.fui .fui-results-post .fui-loader-grid {
  color: var(--fui-post-color);
}
.fui .fui-results-post > .fui-icon {
  width: 1.4em;
  height: 1.4em;
  color: var(--fui-post-color);
}
.fui .fui-results-words {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-width: 0;
}
.fui .fui-results-words span {
  color: var(--game-muted);
  font-size: .92em;
}
/* the window around the player sits in a well of its own */
.fui.fui-results .fui-lb-table {
  border: 1px solid var(--game-line);
  border-radius: var(--fui-radius-sm);
}
.fui.fui-results .fui-lb-rows > .fui-lb-row:last-child {
  border-bottom: 0;
}

/* ---- Saves (saves.js): the save-status pill, and the two sides of a conflict ---- */
.fui.fui-save-status {
  display: inline-flex;
  align-items: center;
  gap: .45em;
  min-height: 2.2em;
  padding: 0 .85em 0 .6em;
  border: 1px solid var(--game-line);
  border-radius: 999px;
  background: var(--game-panel);
  color: var(--game-muted);
  font-size: calc(var(--fui-size) * var(--fui-scale) * .85);
  font-weight: 600;
  white-space: nowrap;
  transition: opacity var(--fui-slow);
}
.fui.fui-save-status .fui-icon {
  width: 1.15em;
  height: 1.15em;
  color: var(--game-accent);
}
.fui.fui-save-status .fui-save-icon {
  display: inline-flex;
}
.fui.fui-save-status[data-state='online'] .fui-icon {
  color: var(--game-good);
}
.fui.fui-save-status[data-state='offline'] .fui-icon {
  color: var(--game-warn);
}
.fui.fui-save-status[data-state='failed'] .fui-icon {
  color: var(--game-bad);
}
.fui.fui-save-status[data-quiet] {
  opacity: 0;
}
.fui.fui-save-status[data-compact] {
  justify-content: center;
  width: 2.2em;
  padding: 0;
}
.fui.fui-save-status[data-compact] .fui-save-text {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
}
.fui .fui-save-sides {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(13em, 100%), 1fr));
  gap: .8em;
  margin-top: 1.1em;
}
.fui .fui-save-side {
  display: flex;
  flex-direction: column;
  gap: .35em;
  padding: 1em 1.1em;
  border: 1px solid var(--game-line);
  border-radius: var(--fui-radius-sm);
  background: var(--game-raised);
}
.fui .fui-save-side[data-newer] {
  border-color: var(--game-accent);
  box-shadow: inset 3px 0 var(--game-accent);
}
.fui .fui-save-side-head {
  display: flex;
  align-items: center;
  gap: .5em;
}
.fui .fui-save-side-head .fui-badge {
  margin-left: auto;
}
.fui .fui-save-when {
  color: var(--game-muted);
  font-size: .92em;
}
.fui .fui-save-summary {
  font-weight: 600;
}

/* ---- Achievements and stats (achievements.js) ----
   The headline band, a filter band (count, filter, search), sortable column headings, then full-width rows: the art
   (the hosted pictures, never greyed by a filter), the title (in the accent once earned) and its description, a bar
   with its value inside, when it was unlocked, the share of players who have it. In a narrow view the three columns
   move under the title. */
.fui .fui-achievements {
  container-type: inline-size;
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.fui .fui-achievements > .fui-lb-you,
.fui .fui-stats > .fui-lb-you {
  padding: .7em var(--fui-row-pad);
  background: var(--fui-tint);
  border-bottom: 1px solid var(--game-line);
  color: var(--game-text);
}
.fui :is(.fui-achievements, .fui-stats) > :not(.fui-ach-table),
.fui .fui-ach-list > * {
  flex: none; /* the bands and each row keep their height; only the list of rows gives way */
}
.fui .fui-ach-table {
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.fui .fui-ach-thead,
.fui .fui-ach {
  display: grid;
  grid-template-columns: 4.4em minmax(0, 1fr) 10.5em 6.5em 5.5em;
  column-gap: 1.3em;
  align-items: center;
}
/* the headings sit outside the scrolling rows: they make room for the rows' scroll bar (achievements.js measures it) */
.fui .fui-ach-thead {
  padding-right: calc(var(--fui-row-pad) + var(--fui-scrollbar, 0px));
}
.fui .fui-ach-thead > :first-child {
  grid-column: 1 / 3;
}
.fui .fui-ach-thead > :nth-child(n + 2) {
  display: flex;
  justify-content: center;
}
.fui .fui-ach-list {
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: var(--fui-track) transparent;
}
.fui .fui-ach {
  min-height: 5.6em;
  padding: .7em var(--fui-row-pad);
}
.fui .fui-ach-art {
  display: grid;
  place-items: center;
  width: 4.4em;
  height: 4.4em;
  border: 1px solid var(--game-line);
  border-radius: var(--fui-radius-sm);
  overflow: hidden;
  background: var(--game-soft);
  color: var(--game-accent);
}
.fui .fui-ach-art[data-locked] {
  color: var(--game-muted);
}
.fui .fui-ach-art img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.fui .fui-ach-art .fui-icon {
  width: 1.8em;
  height: 1.8em;
}
.fui .fui-ach-main {
  display: flex;
  flex-direction: column;
  gap: .2em;
  min-width: 0;
}
.fui .fui-ach-title {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .25em .6em;
  min-width: 0;
}
.fui .fui-ach-title > strong {
  font-size: 1.13em;
  font-weight: 600;
  overflow-wrap: anywhere;
}
.fui .fui-ach.fui-unlocked .fui-ach-title > strong {
  color: var(--game-accent);
}
.fui .fui-ach-desc {
  color: var(--game-muted);
  font-size: .87em;
}
.fui .fui-ach-meta {
  display: contents;
}
.fui .fui-ach-nomatch {
  padding: 1.6em var(--fui-row-pad);
  color: var(--game-muted);
  text-align: center;
}
@container (max-width: 42em) {
  .fui .fui-ach-thead {
    display: none;
  }
  .fui .fui-ach {
    grid-template-columns: 3.2em minmax(0, 1fr);
    align-items: start;
    row-gap: .5em;
    min-height: 0;
  }
  .fui .fui-ach-art {
    width: 3.2em;
    height: 3.2em;
  }
  .fui .fui-ach-meta {
    display: flex;
    flex-wrap: wrap;
    grid-column: 2;
    align-items: center;
    gap: .35em 1em;
  }
  .fui .fui-ach-progress {
    flex: 1 1 8em;
    max-width: 14em;
  }
  .fui .fui-ach-meta .fui-cell-pair {
    flex-direction: row;
    align-items: baseline;
    gap: .4em;
  }
  .fui .fui-toolbar > .fui-search {
    flex: 1 1 12em;
  }
  .fui .fui-statband-value {
    font-size: 1.55em;
  }
}
/* The stats: a Stat / You / Everyone table under its own headline band */
.fui .fui-stats {
  container-type: inline-size;
  display: flex;
  flex-direction: column;
}
.fui .fui-stats-thead,
.fui .fui-stats-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 9em 9em;
  column-gap: 1.3em;
  align-items: center;
}
.fui .fui-stats-list[data-solo] :is(.fui-stats-thead, .fui-stats-row) {
  grid-template-columns: minmax(0, 1fr) 9em;
}
.fui .fui-stats-thead > :nth-child(n + 2) {
  text-align: right;
}
.fui .fui-stats-row {
  min-height: 3.3em;
  padding: .55em var(--fui-row-pad);
}
.fui .fui-stats-name {
  font-size: 1.05em;
  font-weight: 600;
}
.fui .fui-stats-value {
  font-size: 1.05em;
  font-weight: 700;
}
.fui .fui-stats-total {
  color: var(--game-muted);
}
.fui .fui-stats-empty {
  padding: 1.6em var(--fui-row-pad);
}
@container (max-width: 30em) {
  .fui .fui-stats-thead,
  .fui .fui-stats-row {
    grid-template-columns: minmax(0, 1fr) 6.5em 6.5em;
    column-gap: .8em;
  }
  .fui .fui-statband-value {
    font-size: 1.55em;
  }
}
/* The achievements screen: a steady height; the rows scroll under the bands, which run the full width */
.fui.fui-dialog.fui-ach-screen {
  height: min(48em, calc(100dvh - 2em));
}
.fui.fui-ach-screen .fui-ach-host {
  --fui-row-pad: var(--fui-gutter);
  display: flex;
  flex: 1;
  flex-direction: column;
  min-height: 0;
  padding: 0;
  overflow: auto;
}
.fui .fui-ach-host > :is(.fui-achievements, .fui-stats) {
  flex: 1;
}

/* ---- The HUD (hud.js): a click-through layer over the game, nine regions, parts that write only on change ----
   The regions sit on a 3 x 3 grid inside the safe area; the top corner on the corner buttons' side starts under
   them. Only the HUD's own controls (the action bar, a prompt that is a button) take clicks; the rest lets them
   through to the game. Meters move by transform; the cooldown cover is one transform animation on the compositor. */
.fui.fui-hud {
  position: fixed;
  inset: 0;
  z-index: calc(var(--fui-z) - 1);
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  grid-template-rows: auto minmax(0, 1fr) auto;
  grid-template-areas: 'tl t tr' 'l c r' 'bl b br';
  gap: .75em;
  padding: max(.9em, env(safe-area-inset-top)) max(.9em, env(safe-area-inset-right)) max(.9em, env(safe-area-inset-bottom))
    max(.9em, env(safe-area-inset-left));
  pointer-events: none;
}
[data-fui-screen] .fui.fui-hud {
  visibility: hidden;
}
.fui .fui-hud-region {
  display: flex;
  flex-direction: column;
  gap: .6em;
  min-width: 0;
}
.fui .fui-hud-region[data-region='top-left'] { grid-area: tl; align-items: flex-start; }
.fui .fui-hud-region[data-region='top'] { grid-area: t; align-items: center; }
.fui .fui-hud-region[data-region='top-right'] { grid-area: tr; align-items: flex-end; }
.fui .fui-hud-region[data-region='left'] { grid-area: l; align-self: center; align-items: flex-start; }
.fui .fui-hud-region[data-region='centre'] { grid-area: c; align-self: center; align-items: center; }
.fui .fui-hud-region[data-region='right'] { grid-area: r; align-self: center; align-items: flex-end; }
.fui .fui-hud-region[data-region='bottom-left'] { grid-area: bl; align-self: end; align-items: flex-start; }
.fui .fui-hud-region[data-region='bottom'] { grid-area: b; align-self: end; align-items: center; }
.fui .fui-hud-region[data-region='bottom-right'] { grid-area: br; align-self: end; align-items: flex-end; }
/* clear of the corner buttons (top right by default) */
.fui.fui-hud[data-chrome='right'] .fui-hud-region[data-region='top-right'],
.fui.fui-hud[data-chrome='left'] .fui-hud-region[data-region='top-left'] {
  margin-top: 3.6em;
}
.fui .fui-hud-card {
  display: flex;
  flex-direction: column;
  gap: .8em;
  padding: .9em 1.1em;
  border: 1px solid var(--game-line);
  border-radius: var(--fui-radius);
  background: var(--game-panel);
  box-shadow: var(--fui-shadow);
}
/* actionBar(): square slots, the key in a corner, a count, the selected one tinted */
.fui .fui-actionbar {
  display: flex;
  gap: .4em;
  padding: .4em;
  border: 1px solid var(--game-line);
  border-radius: calc(var(--fui-radius-sm) + .4em);
  background: var(--game-panel);
  box-shadow: var(--fui-shadow);
  pointer-events: auto;
}
.fui .fui-slot {
  -webkit-appearance: none;
  appearance: none;
  position: relative;
  display: grid;
  place-items: center;
  width: 3.4em;
  height: 3.4em;
  margin: 0;
  padding: 0;
  border: 1px solid var(--game-line);
  border-radius: var(--fui-radius-sm);
  overflow: hidden;
  background: var(--game-soft);
  color: var(--game-text);
  font: inherit;
  cursor: pointer;
  transition: background-color var(--fui-fast), border-color var(--fui-fast), box-shadow var(--fui-fast);
}
.fui .fui-slot-art {
  display: grid;
  place-items: center;
  width: 100%;
  height: 100%;
}
.fui .fui-slot-art .fui-icon {
  width: 1.5em;
  height: 1.5em;
}
.fui .fui-slot-art img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.fui .fui-slot-key {
  position: absolute;
  top: .25em;
  left: .35em;
  color: var(--game-muted);
  font-size: .66em;
  font-weight: 700;
  line-height: 1;
}
.fui .fui-slot-count {
  position: absolute;
  right: .3em;
  bottom: .2em;
  font-size: .75em;
  font-weight: 700;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.fui .fui-slot-cool {
  position: absolute;
  inset: 0;
  background: rgb(0 0 0 / .5);
  transform: scaleY(0);
  transform-origin: bottom;
  pointer-events: none;
}
.fui .fui-slot[aria-current='true'] {
  border-color: var(--game-accent);
  background: var(--fui-tint);
  box-shadow: inset 0 0 0 1px var(--game-accent);
}
.fui .fui-slot[aria-disabled='true'] {
  cursor: default;
}
.fui .fui-slot[aria-disabled='true']:not([data-cooling]) .fui-slot-art {
  opacity: .4;
}
/* selectable: 'pad': the selection shows only to a gamepad player */
:root:not([data-fui-input='pad']) .fui .fui-actionbar[data-select='pad'] .fui-slot[aria-current='true'] {
  border-color: var(--game-line);
  background: var(--game-soft);
  box-shadow: none;
}
/* the key is for keys and the mouse; a pad player uses the selected slot, a thumb taps */
[data-fui-input='pad'] .fui .fui-slot-key {
  display: none;
}
@media (pointer: coarse) {
  :root:not([data-fui-input='keys']) .fui .fui-slot-key {
    display: none;
  }
}
/* meter(): a labelled bar; its colour turns at the thresholds */
.fui .fui-meter {
  --fui-meter-color: var(--game-accent-fill);
  display: flex;
  flex-direction: column;
  gap: .35em;
  min-width: 11em;
}
.fui .fui-meter[data-kind='good'] { --fui-meter-color: var(--game-good); }
.fui .fui-meter[data-kind='warn'],
.fui .fui-meter[data-state='warn'] { --fui-meter-color: var(--game-warn); }
.fui .fui-meter[data-kind='bad'],
.fui .fui-meter[data-state='bad'] { --fui-meter-color: var(--game-bad); }
.fui .fui-meter-head {
  display: flex;
  align-items: baseline;
  gap: .5em;
  color: var(--game-muted);
  font-size: .73em;
  font-weight: 600;
  letter-spacing: .07em;
  text-transform: uppercase;
}
.fui .fui-meter-head .fui-icon {
  align-self: center;
  width: 1.4em;
  height: 1.4em;
  color: var(--fui-meter-color);
  transition: color var(--fui-fast);
}
.fui .fui-meter-value {
  margin-left: auto;
  color: var(--game-text);
  font-size: 1.4em;
  font-weight: 700;
  letter-spacing: 0;
  font-variant-numeric: tabular-nums;
  text-transform: none;
}
.fui .fui-meter-track {
  position: relative;
  height: .55em;
  border-radius: 999px;
  overflow: hidden;
  background: var(--fui-track);
}
.fui .fui-meter-fill {
  position: absolute;
  inset: 0;
  background: var(--fui-meter-color);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--fui-fast) linear, background-color var(--fui-fast);
}
.fui .fui-meter-track.fui-segmented::after {
  content: '';
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(to right, transparent 0 calc(100% / var(--fui-segments) - 2px),
    var(--game-panel) 0 calc(100% / var(--fui-segments)));
}
/* prompt(): a short invitation with its key, fading in and out */
.fui .fui-prompt {
  display: inline-flex;
  align-items: center;
  gap: .65em;
  margin: 0;
  padding: .55em 1em .55em .7em;
  border: 1px solid var(--game-line);
  border-radius: 999px;
  background: var(--game-panel);
  box-shadow: var(--fui-shadow);
  color: var(--game-text);
  font: inherit;
  font-weight: 600;
  opacity: 0;
  transform: translateY(.5em);
  transition: opacity var(--fui-slow), transform var(--fui-slow) var(--fui-ease);
  pointer-events: none;
}
.fui .fui-prompt[data-shown] {
  opacity: 1;
  transform: none;
}
.fui button.fui-prompt[data-shown] {
  pointer-events: auto;
  cursor: pointer;
}
.fui .fui-prompt .fui-hint {
  margin: 0;
  opacity: 1;
}
@media (max-width: 40em) {
  .fui.fui-hud {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-rows: auto auto auto minmax(0, 1fr) auto auto;
    grid-template-areas: 't t' 'tl tr' 'l r' 'c c' 'bl br' 'b b';
    gap: .5em;
  }
  /* on a narrow screen the corner buttons span the top: the whole top row starts under them */
  .fui.fui-hud {
    padding-top: calc(max(.9em, env(safe-area-inset-top)) + 3.5em);
  }
  .fui.fui-hud[data-chrome] .fui-hud-region[data-region] {
    margin-top: 0;
  }
  .fui .fui-slot {
    width: 3em;
    height: 3em;
  }
  .fui .fui-meter {
    min-width: 8em;
  }
}

/* ---- A plain text field (textField()): its label over it, a hint or an error line under it ---- */
.fui .fui-field {
  display: flex;
  flex-direction: column;
  gap: .4em;
  min-width: 0;
}
.fui .fui-field-label {
  font-weight: 600;
}
.fui .fui-field-note {
  display: flex;
  align-items: flex-start;
  gap: .8em;
  min-height: 1.3em;
  color: var(--game-muted);
  font-size: .85em;
}
.fui .fui-field-hint,
.fui .fui-field-error {
  flex: 1;
  min-width: 0;
}
.fui .fui-field-error {
  display: inline-flex;
  align-items: center;
  gap: .4em;
  color: var(--game-bad);
  font-weight: 600;
}
.fui .fui-field-error .fui-icon {
  flex: none;
  width: 1.1em;
  height: 1.1em;
}
.fui .fui-field-left {
  margin-left: auto;
  font-variant-numeric: tabular-nums;
}
.fui .fui-field[data-invalid] .fui-input {
  border-color: var(--game-bad);
}

/* ---- The title screen's logo (titleScreen({ logo })) and its loading bar ---- */
.fui .fui-title-name.fui-title-logo {
  line-height: 0;
  text-transform: none;
}
.fui .fui-title-logo img {
  display: block;
  width: auto;
  max-width: min(26em, 100%);
  max-height: min(15em, 34vh);
  object-fit: contain;
  object-position: left center;
}
/* the bar's em is its own small type: 26em of it is the menu's width */
.fui .fui-title-loading {
  max-width: 26em;
  font-size: .87em;
}

/* ---- Talking with characters (talk.js) ----
   The chat log and the composer, the cast strip, the activity pill and captions. The player's lines wear the accent's
   tint, a speaker's the second accent's (--fui-accent-2: the accent where a theme has none), so place and names tell
   them apart in every theme and hue adds to it where a theme has two. */

/* a headshot: the avatar's circle, in three sizes */
.fui .fui-portrait.fui-small {
  width: 1.6em;
  height: 1.6em;
}

/* the log: lines from the foot up, scrolling; the newest at the foot, by the field */
.fui .fui-chat {
  position: relative;
  display: flex;
  flex: 1;
  flex-direction: column;
  min-height: 0;
}
.fui .fui-chat-lines {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: .75em;
  min-height: 0;
  padding: 1em var(--fui-row-pad);
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-user-select: text; /* a player may copy what a character said */
  user-select: text;
}
.fui .fui-chat-lines > :first-child {
  margin-top: auto;
}
.fui .fui-chat-line {
  display: flex;
  align-items: flex-start;
  gap: .6em;
  min-width: 0;
  animation: fui-line-in var(--fui-slow) var(--fui-ease);
}
.fui .fui-chat-line p {
  margin: 0;
}
.fui .fui-chat-bubble {
  padding: .5em .8em;
  border-radius: var(--fui-radius-sm);
  line-height: 1.45;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
/* the player's own: at the right, in the accent's tint */
.fui .fui-chat-line[data-kind='player'] {
  justify-content: flex-end;
}
.fui .fui-chat-line[data-kind='player'] > .fui-chat-bubble {
  max-width: min(85%, 34em);
  border-bottom-right-radius: 3px;
  background: var(--fui-tint);
}
/* a speaker's: the headshot, the name in the second accent and a stage direction over the words in its tint */
.fui .fui-chat-line[data-kind='speaker'] > .fui-portrait {
  margin-top: .1em;
}
.fui .fui-chat-body {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: .2em;
  min-width: 0;
  max-width: min(85%, 34em);
}
.fui .fui-chat-who {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0 .5em;
  font-size: .87em;
}
.fui .fui-chat-name {
  color: var(--fui-accent-2);
  font-weight: 700;
}
.fui .fui-chat-direction {
  color: var(--game-muted);
  font-style: italic;
}
.fui .fui-chat-line[data-kind='speaker'] .fui-chat-bubble {
  border-top-left-radius: 3px;
  background: color-mix(in srgb, var(--fui-accent-2) 11%, var(--game-panel));
}
/* a line spoken by a voice. Waiting, as a phone's "Typing…": the marks in the second accent, then what the reply is
   doing in small capitals (a fork restyles .fui-chat-wait). Spoken: every word in place but dim, each lit as the voice
   begins it; --fui-unspoken is how dim (.4). Opacity only, a change of brightness, so reduced motion keeps it. */
.fui .fui-chat-line[data-wait] .fui-chat-bubble {
  color: var(--game-muted);
}
.fui .fui-chat-line[data-wait] .fui-chat-text {
  display: inline-flex;
  align-items: center;
  gap: .65em;
}
.fui .fui-chat-marks {
  display: inline-grid;
  place-items: center;
  color: var(--fui-accent-2);
}
.fui .fui-chat-marks .fui-loader-grid {
  color: inherit;
}
.fui .fui-chat-wait {
  font-size: .78em;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.fui .fui-chat-word {
  opacity: var(--fui-unspoken, .4);
  transition: opacity 90ms linear;
}
.fui .fui-chat-word[data-said] {
  opacity: 1;
}
/* the system's: small, an icon and words across the log; a notice and an error on a tint of their status colour */
.fui .fui-chat-line:is([data-kind='info'], [data-kind='notice'], [data-kind='error']) {
  align-items: center;
  gap: .55em;
  padding: .45em .75em;
  border-radius: var(--fui-radius-sm);
  color: var(--game-muted);
  font-size: .87em;
}
.fui .fui-chat-line:is([data-kind='info'], [data-kind='notice'], [data-kind='error']) > .fui-icon {
  flex: none;
  width: 1.15em;
  height: 1.15em;
}
.fui .fui-chat-line[data-kind='notice'] {
  background: color-mix(in srgb, var(--game-warn) 12%, var(--game-panel));
  color: var(--game-text);
}
.fui .fui-chat-line[data-kind='notice'] > .fui-icon {
  color: var(--game-warn);
}
.fui .fui-chat-line[data-kind='error'] {
  background: color-mix(in srgb, var(--game-bad) 12%, var(--game-panel));
  color: var(--game-text);
}
.fui .fui-chat-line[data-kind='error'] > .fui-icon {
  color: var(--game-bad);
}
.fui .fui-chat-count {
  font-variant-numeric: tabular-nums;
  font-weight: 700;
}
/* "New lines": over the log's foot while the player reads further up */
.fui .fui-chat-more {
  -webkit-appearance: none;
  appearance: none;
  position: absolute;
  bottom: .7em;
  left: 50%;
  display: inline-flex;
  align-items: center;
  gap: .4em;
  min-height: 2.15em;
  margin: 0;
  padding: 0 .95em;
  border: 0;
  border-radius: 999px;
  background: var(--game-accent-fill);
  color: var(--game-on-accent);
  font: inherit;
  font-size: .85em;
  font-weight: 600;
  box-shadow: var(--fui-shadow);
  transform: translateX(-50%);
  cursor: pointer;
  animation: fui-fade var(--fui-fast);
}
.fui .fui-chat-more .fui-icon {
  width: 1em;
  height: 1em;
}
@keyframes fui-line-in {
  from {
    opacity: 0;
    transform: translateY(.5em);
  }
}

/* the composer: a band under the log; why sending waits over the field */
.fui .fui-composer {
  display: flex;
  flex-direction: column;
  gap: .45em;
  margin: 0;
  padding: .7em var(--fui-row-pad);
  border-top: 1px solid var(--game-line);
  background: var(--game-band);
}
.fui .fui-composer-status {
  display: flex;
  align-items: center;
  gap: .55em;
  margin: 0;
  color: var(--game-muted);
  font-size: .87em;
}
.fui .fui-composer-status > .fui-icon {
  width: 1.05em;
  height: 1.05em;
}
.fui .fui-composer-row {
  position: relative;
  display: flex;
  align-items: center;
  gap: .5em;
}
.fui .fui-composer-row > .fui-input {
  flex: 1;
  min-width: 0;
  padding-right: 3em;
}
.fui .fui-composer-left {
  position: absolute;
  right: 4em;
  color: var(--game-muted);
  font-size: .8em;
  font-variant-numeric: tabular-nums;
  pointer-events: none;
}
.fui .fui-composer .fui-input:read-only {
  color: var(--game-muted);
}

/* the cast strip: tiles in a row that scrolls sideways */
.fui .fui-cast {
  display: flex;
  gap: .35em;
  max-width: 100%;
  padding: .35em;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x proximity;
  scrollbar-width: thin;
  pointer-events: auto; /* in the HUD too, which lets clicks through to the game elsewhere */
}
.fui .fui-cast-tile {
  -webkit-appearance: none;
  appearance: none;
  display: flex;
  flex: none;
  flex-direction: column;
  align-items: center;
  gap: .4em;
  width: 6em;
  margin: 0;
  padding: .55em .3em .45em;
  border: 1px solid transparent;
  border-radius: var(--fui-radius-sm);
  background: transparent;
  color: var(--game-text);
  font: inherit;
  scroll-snap-align: start;
  cursor: pointer;
  transition: background-color var(--fui-fast), border-color var(--fui-fast);
}
.fui .fui-cast-tile:is(:focus-visible, [data-fui-input='pad'] :focus) {
  box-shadow: var(--fui-ring);
}
.fui .fui-cast-tile[aria-pressed='true'] {
  border-color: var(--game-accent);
  background: var(--fui-tint);
}
.fui .fui-cast-face {
  position: relative;
  display: grid;
}
.fui .fui-cast-tile .fui-portrait {
  width: 3em;
  height: 3em;
}
.fui .fui-cast-name {
  max-width: 100%;
  overflow: hidden;
  font-size: .8em;
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.fui .fui-cast-tile[aria-pressed='true'] .fui-cast-name {
  color: var(--fui-accent-ink);
}
/* speaking: a ring in the second accent, and a second one that steps outward and fades (transform and opacity) */
.fui .fui-cast-face::before,
.fui .fui-cast-face::after {
  content: '';
  position: absolute;
  inset: -4px;
  border: 2px solid var(--fui-accent-2);
  border-radius: 50%;
  opacity: 0;
  pointer-events: none;
}
.fui .fui-cast-tile[data-speaking] .fui-cast-face::before {
  opacity: 1;
}
.fui .fui-cast-tile[data-speaking] .fui-cast-face::after {
  animation: fui-speaking 1200ms steps(6, end) infinite;
}
@keyframes fui-speaking {
  from {
    opacity: .9;
    transform: scale(1);
  }
  to {
    opacity: 0;
    transform: scale(1.3);
  }
}
/* waiting a turn: the headshot dimmed, its place in line on it */
.fui .fui-cast-tile[data-waiting] .fui-portrait {
  opacity: .55;
}
.fui .fui-cast-turn {
  position: absolute;
  right: -.4em;
  bottom: -.25em;
  display: grid;
  place-items: center;
  min-width: 1.5em;
  height: 1.5em;
  padding: 0 .3em;
  border: 1px solid var(--game-line);
  border-radius: 999px;
  background: var(--game-band);
  color: var(--game-text);
  font-size: .72em;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
/* a new face pops in */
.fui .fui-cast-tile[data-new] {
  animation: fui-pop-in var(--fui-slow) var(--fui-ease);
}
@keyframes fui-pop-in {
  from {
    opacity: 0;
    transform: scale(.6);
  }
}
/* compact: one small row of headshots at the chat log's size; the names for screen readers and on hover (the title),
   the selected one ringed in the accent, the speaking ring and the waiting number as above */
.fui .fui-cast[data-compact] {
  gap: .2em;
  padding: .3em;
}
.fui .fui-cast[data-compact] .fui-cast-tile {
  position: relative;
  width: auto;
  gap: 0;
  padding: .22em;
  border-radius: 50%;
}
.fui .fui-cast[data-compact] .fui-cast-tile .fui-portrait {
  width: 2.1em;
  height: 2.1em;
}
.fui .fui-cast[data-compact] .fui-cast-name {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
.fui .fui-cast[data-compact] .fui-cast-face::before,
.fui .fui-cast[data-compact] .fui-cast-face::after {
  inset: -3px;
}
.fui .fui-cast[data-compact] .fui-cast-turn {
  right: -.55em;
  bottom: -.4em;
  font-size: .62em;
}

/* the activity pill: one status, drawn by its state */
.fui .fui-activity {
  display: inline-flex;
  align-items: center;
  gap: .6em;
  min-height: 2.25em;
  padding: 0 .95em 0 .8em;
  border: 1px solid var(--game-line);
  border-radius: 999px;
  background: var(--game-panel);
  color: var(--game-text);
  font-size: .87em;
  font-weight: 600;
  box-shadow: var(--fui-shadow);
  animation: fui-fade var(--fui-fast);
}
.fui .fui-activity-art {
  display: inline-grid;
  place-items: center;
  min-width: 1.3em;
  color: var(--game-accent);
}
.fui .fui-activity-art:empty {
  display: none;
}
.fui .fui-activity .fui-loader-grid {
  color: inherit;
}
/* thinking: three dots lit in turn; speaking: four bars that step like a level meter. Hard steps, as the loader. */
.fui .fui-dots {
  display: inline-flex;
  gap: .22em;
}
.fui .fui-dots > i {
  width: .4em;
  height: .4em;
  border-radius: 50%;
  background: currentColor;
  animation: fui-dot 900ms steps(1, end) infinite;
}
.fui .fui-dots > i:nth-child(2) {
  animation-delay: -600ms;
}
.fui .fui-dots > i:nth-child(3) {
  animation-delay: -300ms;
}
@keyframes fui-dot {
  0% {
    opacity: 1;
  }
  33.333% {
    opacity: .3;
  }
}
.fui .fui-bars {
  display: inline-flex;
  align-items: flex-end;
  gap: .16em;
  height: 1em;
}
.fui .fui-bars > i {
  width: .22em;
  height: 100%;
  border-radius: 1px;
  background: currentColor;
  transform-origin: 50% 100%;
  animation: fui-bar 800ms steps(1, end) infinite;
}
.fui .fui-bars > i:nth-child(2) {
  animation-duration: 600ms;
  animation-delay: -200ms;
}
.fui .fui-bars > i:nth-child(3) {
  animation-duration: 700ms;
  animation-delay: -500ms;
}
.fui .fui-bars > i:nth-child(4) {
  animation-duration: 900ms;
  animation-delay: -100ms;
}
@keyframes fui-bar {
  0% {
    transform: scaleY(.35);
  }
  25% {
    transform: scaleY(1);
  }
  50% {
    transform: scaleY(.6);
  }
  75% {
    transform: scaleY(.85);
  }
}

/* captions: the name over the words; a word shows when the voice reaches it, the rest hold their place unseen */
.fui .fui-captions {
  max-width: min(40em, 92vw);
  pointer-events: none;
}
.fui .fui-captions.fui-off {
  visibility: hidden;
}
.fui .fui-caption {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .15em;
  padding: .55em 1em .65em;
  border-radius: var(--fui-radius-sm);
  background: color-mix(in srgb, var(--game-band) 90%, transparent);
  text-align: center;
  animation: fui-fade var(--fui-fast);
}
.fui .fui-caption-name {
  color: var(--fui-accent-2);
  font-size: .78em;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
}
.fui .fui-caption-words {
  margin: 0;
  color: var(--game-text);
  font-size: 1.15em;
  font-weight: 600;
  line-height: 1.4;
}
.fui .fui-caption-words > span {
  opacity: 0;
  transition: opacity 90ms linear;
}
.fui .fui-caption-words > span[data-said],
.fui .fui-caption[data-all] .fui-caption-words > span {
  opacity: 1;
}
/* over a character's head: moveTo() puts the layer's corner on the point, the bubble's foot sits over it */
.fui .fui-captions[data-place='over'] {
  position: absolute;
  top: 0;
  left: 0;
  will-change: transform;
}
.fui .fui-captions[data-place='over'] > .fui-caption {
  width: max-content;
  max-width: 22em;
  transform: translate(-50%, calc(-100% - .6em));
}

/* ---- The corner dock (dock.js): a round launcher in a corner that opens into a compact window ---- */
.fui.fui-dock {
  position: fixed;
  inset: auto max(1em, env(safe-area-inset-right)) max(1em, env(safe-area-inset-bottom)) auto;
  z-index: var(--fui-dock-z, 30);
  display: flex;
  flex-direction: column;
  align-items: flex-end;
}
.fui.fui-dock[data-corner='bottom-left'] {
  inset: auto auto max(1em, env(safe-area-inset-bottom)) max(1em, env(safe-area-inset-left));
  align-items: flex-start;
}
.fui.fui-dock[data-corner='top-right'] {
  inset: max(1em, env(safe-area-inset-top)) max(1em, env(safe-area-inset-right)) auto auto;
}
.fui.fui-dock[data-corner='top-left'] {
  inset: max(1em, env(safe-area-inset-top)) auto auto max(1em, env(safe-area-inset-left));
  align-items: flex-start;
}
.fui.fui-dock.fui-inside {
  position: absolute;
}
/* a full screen (the title) has the whole view: the dock steps aside, as the HUD and the corner buttons do */
[data-fui-screen] .fui.fui-dock {
  visibility: hidden;
}
.fui .fui-dock-launcher {
  -webkit-appearance: none;
  appearance: none;
  position: relative;
  display: grid;
  place-items: center;
  width: 3.6em;
  height: 3.6em;
  margin: 0;
  padding: 0;
  border: 2px solid var(--game-titlebar);
  border-radius: 50%;
  background: var(--game-accent-fill);
  color: var(--game-on-accent);
  font: inherit;
  box-shadow: 0 0 0 1px var(--fui-edge), var(--fui-shadow);
  cursor: pointer;
  animation: fui-pop-in var(--fui-slow) var(--fui-ease);
  transition: transform var(--fui-fast);
}
.fui .fui-dock-launcher:active {
  transform: scale(.95);
}
.fui .fui-dock-launcher:is(:focus-visible, [data-fui-input='pad'] :focus) {
  box-shadow: var(--fui-ring);
}
.fui .fui-dock-face {
  display: grid;
  place-items: center;
  width: 100%;
  height: 100%;
  overflow: hidden;
  border-radius: 50%;
  font-weight: 700;
}
.fui .fui-dock-face img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.fui .fui-dock-face > .fui-icon {
  width: 1.6em;
  height: 1.6em;
}
.fui .fui-dock-badge {
  position: absolute;
  top: -.35em;
  right: -.35em;
  background: var(--game-titlebar);
  color: var(--game-on-titlebar);
  box-shadow: 0 0 0 2px var(--game-panel);
}
.fui .fui-dock-window {
  width: min(24em, calc(100vw - 2em));
  height: min(36em, calc(100vh - 2em));
  border-radius: var(--fui-radius);
  background: linear-gradient(var(--game-panel), var(--game-panel)), var(--game-band); /* opaque over any page */
  transform-origin: 100% 100%;
  animation: fui-pop var(--fui-slow) var(--fui-ease);
}
@supports (height: 100dvh) {
  .fui .fui-dock-window {
    height: min(36em, calc(100dvh - 2em));
  }
}
.fui.fui-dock:is([data-corner='bottom-left'], [data-corner='top-left']) .fui-dock-window {
  transform-origin: 0 100%;
}
.fui .fui-dock-window:focus {
  outline: none;
}
.fui .fui-dock-body {
  display: flex;
  flex: 1;
  flex-direction: column;
  min-height: 0;
}
@media (pointer: coarse) {
  .fui .fui-chat-more {
    min-height: max(44px, 2.75em);
  }
}

/* ---- Phones: modals take the whole screen ----
   "A phone" is a narrow screen, or a short touch screen (a phone held sideways). components.js sets
   data-fui-modal on <html> while a menu is open, and --fui-vv-height / --fui-vv-top from the visual viewport, so a
   dialog fits the part of the screen the on-screen keyboard leaves (the browser's address bar is handled by dvh).
   A dialog that should stay a window on phones too carries .fui-windowed (createDialog({ fullscreenOnMobile: false })). */
@media (max-width: 40em), (max-height: 32em) and (pointer: coarse) {
  .fui {
    --fui-gutter: 1em;
  }
  .fui.fui-dialog:not(.fui-screen):not(.fui-windowed) {
    inset: auto 0 auto 0;
    top: var(--fui-vv-top, 0px);
    box-sizing: border-box; /* the safe-area padding inside the screen's width, not added to it */
    width: 100%;
    max-width: none;
    height: var(--fui-vv-height, 100vh);
    max-height: none;
    margin: 0;
    padding: 0 env(safe-area-inset-right) 0 env(safe-area-inset-left);
    border: 0;
    border-radius: 0;
    box-shadow: none;
    transform-origin: center bottom;
  }
  @supports (height: 100dvh) {
    .fui.fui-dialog:not(.fui-screen):not(.fui-windowed) {
      height: var(--fui-vv-height, 100dvh);
    }
  }
  .fui.fui-dialog:not(.fui-screen):not(.fui-windowed)[open] {
    animation: fui-rise var(--fui-slow) var(--fui-ease);
  }
  .fui.fui-dialog:not(.fui-screen):not(.fui-windowed) > .fui-panel-head {
    min-height: 3.4em;
    padding-top: max(.45em, env(safe-area-inset-top));
  }
  .fui.fui-dialog:not(.fui-screen):not(.fui-windowed) .fui-panel-title {
    font-size: 1.13em;
  }
  .fui.fui-dialog:not(.fui-screen):not(.fui-windowed) > .fui-panel-foot {
    padding-bottom: max(.8em, env(safe-area-inset-bottom));
  }
  .fui.fui-dialog:not(.fui-screen):not(.fui-windowed) > .fui-panel-foot > .fui-button {
    flex: 1 1 auto; /* big, easy targets for thumbs */
  }
  /* short dialogs (confirm, log in, profile, pause) sit in the middle of the screen */
  .fui.fui-dialog.fui-narrow:not(.fui-windowed) > .fui-panel-body {
    display: flex;
    flex-direction: column;
    justify-content: center;
  }
  /* the page behind does not scroll or bounce while a menu is open */
  :root[data-fui-modal] {
    overflow: hidden;
  }
}
/* On a phone, the open dock takes the whole screen (above the on-screen keyboard) and the page behind holds still */
@media (max-width: 40em), (max-height: 32em) and (pointer: coarse) {
  .fui.fui-dock[data-open]:not(.fui-inside) {
    inset: auto 0 auto 0;
    top: var(--fui-vv-top, 0px);
    height: var(--fui-vv-height, 100vh);
  }
  @supports (height: 100dvh) {
    .fui.fui-dock[data-open]:not(.fui-inside) {
      height: var(--fui-vv-height, 100dvh);
    }
  }
  .fui.fui-dock[data-open]:not(.fui-inside) .fui-dock-window {
    box-sizing: border-box;
    width: 100%;
    height: 100%;
    padding: 0 env(safe-area-inset-right) 0 env(safe-area-inset-left);
    border: 0;
    border-radius: 0;
    box-shadow: none;
    animation: fui-rise var(--fui-slow) var(--fui-ease);
  }
  .fui.fui-dock[data-open]:not(.fui-inside) .fui-panel-head {
    padding-top: max(.45em, env(safe-area-inset-top));
  }
  .fui.fui-dock[data-open]:not(.fui-inside) .fui-composer {
    padding-bottom: max(.7em, env(safe-area-inset-bottom));
  }
  :root[data-fui-dock-open] {
    overflow: hidden;
  }
}
@keyframes fui-rise {
  from {
    opacity: 0;
    transform: translateY(1.5em);
  }
}

/* ---- Big Screen Mode: every window takes the whole screen on any screen, as on phones ----
   The app's call (a game on a TV or a kiosk, or one that wants its menus full screen, the way Steam's big-screen mode
   does): <html data-fui-big-screen> (setBigScreen(), createGameUI({ bigScreen: true })) for every window,
   createDialog({ bigScreen: true }) for one, bigScreen: false to keep one a window. The window pads itself to a
   column of its usual width (--fui-dialog-width) in the middle, so no line runs the width of a TV and everything
   inside keeps the layout it has in a window; the title bar and the actions band reach back out to the screen's
   edges, their contents lined up on the column. Phones keep their own layout (the block above); drop-down lists
   (.fui-windowed) and the title screen (.fui-screen) are not windows. */
@property --fui-big-inset {
  syntax: '<length>';
  inherits: true;
  initial-value: 0px;
}
@media not ((max-width: 40em) or ((max-height: 32em) and (pointer: coarse))) {
  :is(:root[data-fui-big-screen] .fui.fui-dialog:not(.fui-no-big-screen), .fui.fui-dialog.fui-big-screen):not(.fui-screen):not(.fui-windowed) {
    /* a length, computed here and inherited as one: the bars line up on the column whatever their own type size */
    --fui-big-inset: max(0px, calc((100vw - var(--fui-dialog-width)) / 2));
    inset: 0;
    box-sizing: border-box;
    width: 100%;
    max-width: none;
    height: 100vh;
    height: 100dvh;
    max-height: none;
    margin: 0;
    padding: 0 var(--fui-big-inset);
    border: 0;
    border-radius: 0;
    box-shadow: none;
  }
  :is(:root[data-fui-big-screen] .fui.fui-dialog:not(.fui-no-big-screen), .fui.fui-dialog.fui-big-screen):not(.fui-screen):not(.fui-windowed)[open] {
    animation: fui-fade var(--fui-slow) ease-out;
  }
  /* the title bar and the actions band run across the screen; every window has the big title bar */
  :is(:root[data-fui-big-screen] .fui.fui-dialog:not(.fui-no-big-screen), .fui.fui-dialog.fui-big-screen):not(.fui-screen):not(.fui-windowed) > :is(.fui-panel-head, .fui-panel-foot) {
    margin: 0 calc(-1 * var(--fui-big-inset));
    padding-left: calc(var(--fui-big-inset) + var(--fui-gutter));
    padding-right: calc(var(--fui-big-inset) + var(--fui-gutter));
  }
  :is(:root[data-fui-big-screen] .fui.fui-dialog:not(.fui-no-big-screen), .fui.fui-dialog.fui-big-screen):not(.fui-screen):not(.fui-windowed) > .fui-panel-head {
    min-height: 4.1em;
    gap: .9em;
    padding-right: calc(var(--fui-big-inset) + .55em); /* its button just past the content's right edge, as in a window */
  }
  :is(:root[data-fui-big-screen] .fui.fui-dialog:not(.fui-no-big-screen), .fui.fui-dialog.fui-big-screen):not(.fui-screen):not(.fui-windowed) > .fui-panel-head .fui-panel-title {
    font-size: 1.33em;
  }
  :is(:root[data-fui-big-screen] .fui.fui-dialog:not(.fui-no-big-screen), .fui.fui-dialog.fui-big-screen):not(.fui-screen):not(.fui-windowed) > .fui-panel-head .fui-head-icon {
    width: 1.6em;
    height: 1.6em;
  }
  :is(:root[data-fui-big-screen] .fui.fui-dialog:not(.fui-no-big-screen), .fui.fui-dialog.fui-big-screen):not(.fui-screen):not(.fui-windowed) > .fui-panel-head .fui-button {
    width: 2.8em;
    min-height: 2.8em;
  }
  /* short windows (confirm, pause, log in) sit in the middle of the screen, as on phones */
  :is(:root[data-fui-big-screen] .fui.fui-dialog:not(.fui-no-big-screen), .fui.fui-dialog.fui-big-screen):not(.fui-screen):not(.fui-windowed).fui-narrow > .fui-panel-body {
    display: flex;
    flex-direction: column;
    justify-content: center;
  }
  /* the page behind does not scroll (nor show its scroll bar) while a window covers it */
  :root[data-fui-big-screen][data-fui-modal],
  :root[data-fui-modal-big] {
    overflow: hidden;
  }
}

/* ---- Hover: only where a real pointer hovers, so a tap on a phone leaves no sticky highlight ---- */
@media (hover: hover) {
  .fui .fui-button:not(:disabled):hover {
    background: color-mix(in srgb, var(--game-text) 7%, var(--game-soft));
    border-color: var(--fui-strong-line);
  }
  .fui .fui-button.fui-primary:not(:disabled):hover {
    background: color-mix(in srgb, var(--game-accent-fill) 86%, var(--game-on-accent));
    border-color: color-mix(in srgb, var(--game-accent-fill) 86%, var(--game-on-accent));
  }
  .fui .fui-button.fui-danger:not(:disabled):hover {
    background: color-mix(in srgb, var(--game-bad) 20%, var(--game-panel));
    border-color: var(--game-bad);
  }
  .fui .fui-button.fui-danger.fui-primary:not(:disabled):hover {
    background: color-mix(in srgb, var(--game-bad) 86%, var(--game-panel));
  }
  .fui .fui-button.fui-quiet:not(:disabled):hover {
    background: var(--game-soft);
    border-color: transparent;
  }
  .fui .fui-panel-head .fui-button:not(:disabled):hover {
    background: rgb(255 255 255 / .28);
    border-color: transparent;
  }
  .fui .fui-menu-item:not(:disabled):hover {
    background: color-mix(in srgb, var(--game-text) 7%, var(--game-soft));
    border-color: var(--fui-strong-line);
  }
  .fui .fui-menu-item:not(:disabled):hover .fui-icon {
    color: var(--game-text);
  }
  .fui .fui-menu-item.fui-primary:not(:disabled):hover {
    background: color-mix(in srgb, var(--game-accent-fill) 86%, var(--game-on-accent));
    border-color: color-mix(in srgb, var(--game-accent-fill) 86%, var(--game-on-accent));
  }
  .fui .fui-menu-item.fui-primary:not(:disabled):hover .fui-icon {
    color: inherit;
  }
  .fui .fui-menu-item.fui-danger:not(:disabled):hover {
    background: color-mix(in srgb, var(--game-bad) 20%, var(--game-panel));
    border-color: var(--game-bad);
  }
  .fui .fui-menu-item.fui-danger:not(:disabled):hover .fui-icon {
    color: var(--game-bad);
  }
  .fui .fui-popup .fui-menu-item:not(:disabled):hover {
    background: var(--game-soft);
    border-color: transparent;
  }
  .fui .fui-popup .fui-menu-item:not(:disabled):hover .fui-icon {
    color: var(--game-accent);
  }
  .fui .fui-choice label:hover > span {
    color: var(--game-text);
  }
  .fui .fui-choice-list label:hover > span {
    border-color: var(--fui-strong-line);
  }
  .fui .fui-tab:hover {
    color: var(--game-text);
  }
  .fui .fui-tab[aria-selected='true']:hover {
    color: var(--game-accent);
  }
  .fui .fui-rail .fui-tab:not([aria-selected='true']):hover {
    background: var(--game-soft);
  }
  .fui .fui-rail .fui-tab[aria-selected='true']:hover {
    color: var(--fui-accent-ink);
  }
  .fui .fui-sort:hover {
    color: var(--game-text);
  }
  .fui .fui-search-clear:hover {
    color: var(--game-text);
  }
  .fui :is(.fui-trow, .fui-lb-rows > .fui-lb-row:not(.fui-lb-gap)):hover {
    background: var(--game-raised);
    box-shadow: inset 3px 0 var(--game-accent);
  }
  .fui .fui-lb-row.fui-you:hover {
    background: var(--fui-tint);
  }
  .fui .fui-slot:not([aria-disabled='true']):hover {
    background: color-mix(in srgb, var(--game-text) 7%, var(--game-soft));
    border-color: var(--fui-strong-line);
  }
  .fui.fui-chrome .fui-button:not(:disabled):hover {
    background: color-mix(in srgb, var(--game-soft) 85%, var(--game-panel));
  }
  .fui .fui-chip:hover {
    background: var(--game-soft);
  }
  .fui button.fui-key:hover {
    border-color: var(--game-accent);
  }
  .fui .fui-binding-row:not(.fui-binding-head):hover {
    background: var(--game-raised);
    box-shadow: inset 3px 0 var(--game-accent);
  }
}

/* ---- Touch, small screens, motion ---- */
@media (pointer: coarse) {
  :root {
    --fui-size: 16px;
  }
  .fui .fui-button,
  .fui .fui-chip {
    min-height: 3em;
  }
  .fui .fui-button.fui-icon-only {
    width: 3em;
  }
  /* small buttons (a pager, a toast's Undo, a log-in prompt) stay small to the eye, not to a thumb: 44px */
  .fui .fui-button.fui-small {
    min-height: max(44px, 2.75em);
  }
  .fui .fui-button.fui-icon-only.fui-small {
    width: max(44px, 2.75em);
  }
  /* a dialog's ✕ is the main way out on a phone: a full 44px target */
  .fui .fui-panel-head .fui-button.fui-icon-only {
    width: max(44px, 2.75em);
    min-height: max(44px, 2.75em);
  }
  /* the controls editor's caps: small to the eye, 44px to a thumb */
  .fui button.fui-key {
    min-width: 44px;
    height: 44px;
  }
  /* iOS zooms into a focused field whose text is under 16px: never let it */
  .fui .fui-input {
    font-size: max(16px, 1em);
  }
}
@media (max-width: 36em) {
  .fui.fui-chrome .fui-chip-name {
    display: none;
  }
  .fui.fui-chrome .fui-chip {
    padding-right: .3em;
  }
  .fui .fui-row {
    flex-wrap: wrap;
  }
  /* a label keeps its words together; a control that no longer fits beside it moves under it */
  .fui .fui-row-label {
    flex: 1 0 9em;
  }
  .fui .fui-slider-wrap {
    flex: 1 1 100%;
  }
  .fui input.fui-slider {
    flex: 1;
    width: auto;
  }
  .fui .fui-notch-track {
    flex: 1 1 auto;
  }
  .fui input.fui-slider.fui-notched {
    width: 100%;
  }
  .fui .fui-choice-list {
    max-width: none;
  }
  .fui.fui-dialog.fui-screen {
    background: linear-gradient(0deg, var(--game-panel) 0, color-mix(in srgb, var(--game-panel) 80%, transparent) 60%,
      color-mix(in srgb, var(--game-panel) 40%, transparent));
  }
  .fui .fui-title-layout {
    justify-content: flex-end;
  }
  .fui .fui-title-column > .fui-menu {
    max-width: none;
  }
}
@media (prefers-reduced-motion: reduce) {
  .fui,
  .fui *,
  .fui *::before,
  .fui *::after,
  .fui.fui-dialog::backdrop {
    animation-duration: 1ms !important;
    transition-duration: 1ms !important;
  }
  /* the loader holds one still frame (an endless animation at 1 ms would flicker); so do the activity pill's dots and
     bars, and a speaker's outer ring (the inner one still says who speaks) */
  .fui :is(.fui-loader-grid, .fui-dots, .fui-bars) > i,
  .fui .fui-cast-face::after {
    animation: none !important;
  }
  .fui .fui-bars > i:nth-child(1) { transform: scaleY(.45); }
  .fui .fui-bars > i:nth-child(2) { transform: scaleY(1); }
  .fui .fui-bars > i:nth-child(3) { transform: scaleY(.7); }
  .fui .fui-bars > i:nth-child(4) { transform: scaleY(.55); }
  .fui .fui-loader-grid > i:nth-child(1) {
    opacity: 0;
  }
}
